]>
Commit | Line | Data |
---|---|---|
11fdf7f2 | 1 | import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core'; |
f6b5b4d7 | 2 | import { FormControl } from '@angular/forms'; |
9f95a23c | 3 | import { Router } from '@angular/router'; |
11fdf7f2 TL |
4 | |
5 | import { I18n } from '@ngx-translate/i18n-polyfill'; | |
9f95a23c | 6 | import * as _ from 'lodash'; |
11fdf7f2 | 7 | import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal'; |
9f95a23c | 8 | import { forkJoin as observableForkJoin, Observable } from 'rxjs'; |
11fdf7f2 TL |
9 | |
10 | import { OsdService } from '../../../../shared/api/osd.service'; | |
e306af50 | 11 | import { ListWithDetails } from '../../../../shared/classes/list-with-details.class'; |
11fdf7f2 TL |
12 | import { ConfirmationModalComponent } from '../../../../shared/components/confirmation-modal/confirmation-modal.component'; |
13 | import { CriticalConfirmationModalComponent } from '../../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component'; | |
9f95a23c TL |
14 | import { FormModalComponent } from '../../../../shared/components/form-modal/form-modal.component'; |
15 | import { ActionLabelsI18n, URLVerbs } from '../../../../shared/constants/app.constants'; | |
11fdf7f2 TL |
16 | import { TableComponent } from '../../../../shared/datatable/table/table.component'; |
17 | import { CellTemplate } from '../../../../shared/enum/cell-template.enum'; | |
9f95a23c TL |
18 | import { Icons } from '../../../../shared/enum/icons.enum'; |
19 | import { NotificationType } from '../../../../shared/enum/notification-type.enum'; | |
f6b5b4d7 | 20 | import { CdFormGroup } from '../../../../shared/forms/cd-form-group'; |
11fdf7f2 TL |
21 | import { CdTableAction } from '../../../../shared/models/cd-table-action'; |
22 | import { CdTableColumn } from '../../../../shared/models/cd-table-column'; | |
23 | import { CdTableSelection } from '../../../../shared/models/cd-table-selection'; | |
9f95a23c | 24 | import { FinishedTask } from '../../../../shared/models/finished-task'; |
11fdf7f2 TL |
25 | import { Permissions } from '../../../../shared/models/permissions'; |
26 | import { DimlessBinaryPipe } from '../../../../shared/pipes/dimless-binary.pipe'; | |
27 | import { AuthStorageService } from '../../../../shared/services/auth-storage.service'; | |
9f95a23c TL |
28 | import { DepCheckerService } from '../../../../shared/services/dep-checker.service'; |
29 | import { NotificationService } from '../../../../shared/services/notification.service'; | |
30 | import { TaskWrapperService } from '../../../../shared/services/task-wrapper.service'; | |
31 | import { URLBuilderService } from '../../../../shared/services/url-builder.service'; | |
11fdf7f2 | 32 | import { OsdFlagsModalComponent } from '../osd-flags-modal/osd-flags-modal.component'; |
81eedcae | 33 | import { OsdPgScrubModalComponent } from '../osd-pg-scrub-modal/osd-pg-scrub-modal.component'; |
11fdf7f2 TL |
34 | import { OsdRecvSpeedModalComponent } from '../osd-recv-speed-modal/osd-recv-speed-modal.component'; |
35 | import { OsdReweightModalComponent } from '../osd-reweight-modal/osd-reweight-modal.component'; | |
36 | import { OsdScrubModalComponent } from '../osd-scrub-modal/osd-scrub-modal.component'; | |
37 | ||
9f95a23c TL |
38 | const BASE_URL = 'osd'; |
39 | ||
11fdf7f2 TL |
40 | @Component({ |
41 | selector: 'cd-osd-list', | |
42 | templateUrl: './osd-list.component.html', | |
9f95a23c TL |
43 | styleUrls: ['./osd-list.component.scss'], |
44 | providers: [{ provide: URLBuilderService, useValue: new URLBuilderService(BASE_URL) }] | |
11fdf7f2 | 45 | }) |
e306af50 | 46 | export class OsdListComponent extends ListWithDetails implements OnInit { |
9f95a23c | 47 | @ViewChild('osdUsageTpl', { static: true }) |
11fdf7f2 | 48 | osdUsageTpl: TemplateRef<any>; |
9f95a23c | 49 | @ViewChild('markOsdConfirmationTpl', { static: true }) |
11fdf7f2 | 50 | markOsdConfirmationTpl: TemplateRef<any>; |
9f95a23c | 51 | @ViewChild('criticalConfirmationTpl', { static: true }) |
11fdf7f2 | 52 | criticalConfirmationTpl: TemplateRef<any>; |
9f95a23c | 53 | @ViewChild(TableComponent, { static: true }) |
11fdf7f2 | 54 | tableComponent: TableComponent; |
9f95a23c | 55 | @ViewChild('reweightBodyTpl', { static: false }) |
11fdf7f2 | 56 | reweightBodyTpl: TemplateRef<any>; |
9f95a23c | 57 | @ViewChild('safeToDestroyBodyTpl', { static: false }) |
11fdf7f2 | 58 | safeToDestroyBodyTpl: TemplateRef<any>; |
f6b5b4d7 TL |
59 | @ViewChild('deleteOsdExtraTpl', { static: false }) |
60 | deleteOsdExtraTpl: TemplateRef<any>; | |
11fdf7f2 TL |
61 | |
62 | permissions: Permissions; | |
63 | tableActions: CdTableAction[]; | |
64 | bsModalRef: BsModalRef; | |
65 | columns: CdTableColumn[]; | |
9f95a23c TL |
66 | clusterWideActions: CdTableAction[]; |
67 | icons = Icons; | |
11fdf7f2 | 68 | |
11fdf7f2 | 69 | selection = new CdTableSelection(); |
9f95a23c | 70 | osds: any[] = []; |
11fdf7f2 | 71 | |
9f95a23c TL |
72 | protected static collectStates(osd: any) { |
73 | const states = [osd['in'] ? 'in' : 'out']; | |
74 | if (osd['up']) { | |
75 | states.push('up'); | |
76 | } else if (osd.state.includes('destroyed')) { | |
77 | states.push('destroyed'); | |
78 | } else { | |
79 | states.push('down'); | |
80 | } | |
81 | return states; | |
11fdf7f2 TL |
82 | } |
83 | ||
84 | constructor( | |
85 | private authStorageService: AuthStorageService, | |
86 | private osdService: OsdService, | |
87 | private dimlessBinaryPipe: DimlessBinaryPipe, | |
88 | private modalService: BsModalService, | |
eafe8130 | 89 | private i18n: I18n, |
9f95a23c TL |
90 | private urlBuilder: URLBuilderService, |
91 | private router: Router, | |
92 | private depCheckerService: DepCheckerService, | |
93 | private taskWrapper: TaskWrapperService, | |
94 | public actionLabels: ActionLabelsI18n, | |
95 | public notificationService: NotificationService | |
11fdf7f2 | 96 | ) { |
e306af50 | 97 | super(); |
11fdf7f2 TL |
98 | this.permissions = this.authStorageService.getPermissions(); |
99 | this.tableActions = [ | |
9f95a23c TL |
100 | { |
101 | name: this.actionLabels.CREATE, | |
102 | permission: 'create', | |
103 | icon: Icons.add, | |
104 | click: () => { | |
105 | this.depCheckerService.checkOrchestratorOrModal( | |
106 | this.actionLabels.CREATE, | |
107 | this.i18n('OSD'), | |
108 | () => { | |
109 | this.router.navigate([this.urlBuilder.getCreate()]); | |
110 | } | |
111 | ); | |
112 | }, | |
113 | canBePrimary: (selection: CdTableSelection) => !selection.hasSelection | |
114 | }, | |
115 | { | |
116 | name: this.actionLabels.EDIT, | |
117 | permission: 'update', | |
118 | icon: Icons.edit, | |
119 | click: () => this.editAction() | |
120 | }, | |
11fdf7f2 | 121 | { |
eafe8130 | 122 | name: this.actionLabels.SCRUB, |
11fdf7f2 | 123 | permission: 'update', |
9f95a23c | 124 | icon: Icons.analyse, |
11fdf7f2 | 125 | click: () => this.scrubAction(false), |
9f95a23c TL |
126 | disable: () => !this.hasOsdSelected, |
127 | canBePrimary: (selection: CdTableSelection) => selection.hasSelection | |
11fdf7f2 TL |
128 | }, |
129 | { | |
eafe8130 | 130 | name: this.actionLabels.DEEP_SCRUB, |
11fdf7f2 | 131 | permission: 'update', |
9f95a23c | 132 | icon: Icons.deepCheck, |
11fdf7f2 TL |
133 | click: () => this.scrubAction(true), |
134 | disable: () => !this.hasOsdSelected | |
135 | }, | |
136 | { | |
eafe8130 | 137 | name: this.actionLabels.REWEIGHT, |
11fdf7f2 TL |
138 | permission: 'update', |
139 | click: () => this.reweight(), | |
9f95a23c TL |
140 | disable: () => !this.hasOsdSelected || !this.selection.hasSingleSelection, |
141 | icon: Icons.reweight | |
11fdf7f2 TL |
142 | }, |
143 | { | |
eafe8130 | 144 | name: this.actionLabels.MARK_OUT, |
11fdf7f2 TL |
145 | permission: 'update', |
146 | click: () => this.showConfirmationModal(this.i18n('out'), this.osdService.markOut), | |
147 | disable: () => this.isNotSelectedOrInState('out'), | |
9f95a23c | 148 | icon: Icons.left |
11fdf7f2 TL |
149 | }, |
150 | { | |
eafe8130 | 151 | name: this.actionLabels.MARK_IN, |
11fdf7f2 TL |
152 | permission: 'update', |
153 | click: () => this.showConfirmationModal(this.i18n('in'), this.osdService.markIn), | |
154 | disable: () => this.isNotSelectedOrInState('in'), | |
9f95a23c | 155 | icon: Icons.right |
11fdf7f2 TL |
156 | }, |
157 | { | |
eafe8130 | 158 | name: this.actionLabels.MARK_DOWN, |
11fdf7f2 TL |
159 | permission: 'update', |
160 | click: () => this.showConfirmationModal(this.i18n('down'), this.osdService.markDown), | |
161 | disable: () => this.isNotSelectedOrInState('down'), | |
9f95a23c | 162 | icon: Icons.down |
11fdf7f2 TL |
163 | }, |
164 | { | |
eafe8130 | 165 | name: this.actionLabels.MARK_LOST, |
11fdf7f2 TL |
166 | permission: 'delete', |
167 | click: () => | |
168 | this.showCriticalConfirmationModal( | |
169 | this.i18n('Mark'), | |
170 | this.i18n('OSD lost'), | |
171 | this.i18n('marked lost'), | |
9f95a23c TL |
172 | (ids: number[]) => { |
173 | return this.osdService.safeToDestroy(JSON.stringify(ids)); | |
174 | }, | |
175 | 'is_safe_to_destroy', | |
11fdf7f2 TL |
176 | this.osdService.markLost |
177 | ), | |
178 | disable: () => this.isNotSelectedOrInState('up'), | |
9f95a23c | 179 | icon: Icons.flatten |
11fdf7f2 TL |
180 | }, |
181 | { | |
eafe8130 | 182 | name: this.actionLabels.PURGE, |
11fdf7f2 TL |
183 | permission: 'delete', |
184 | click: () => | |
185 | this.showCriticalConfirmationModal( | |
186 | this.i18n('Purge'), | |
187 | this.i18n('OSD'), | |
188 | this.i18n('purged'), | |
9f95a23c TL |
189 | (ids: number[]) => { |
190 | return this.osdService.safeToDestroy(JSON.stringify(ids)); | |
191 | }, | |
192 | 'is_safe_to_destroy', | |
193 | (id: number) => { | |
194 | this.selection = new CdTableSelection(); | |
195 | return this.osdService.purge(id); | |
196 | } | |
11fdf7f2 TL |
197 | ), |
198 | disable: () => this.isNotSelectedOrInState('up'), | |
9f95a23c | 199 | icon: Icons.erase |
11fdf7f2 TL |
200 | }, |
201 | { | |
eafe8130 | 202 | name: this.actionLabels.DESTROY, |
11fdf7f2 TL |
203 | permission: 'delete', |
204 | click: () => | |
205 | this.showCriticalConfirmationModal( | |
206 | this.i18n('destroy'), | |
207 | this.i18n('OSD'), | |
208 | this.i18n('destroyed'), | |
9f95a23c TL |
209 | (ids: number[]) => { |
210 | return this.osdService.safeToDestroy(JSON.stringify(ids)); | |
211 | }, | |
212 | 'is_safe_to_destroy', | |
213 | (id: number) => { | |
214 | this.selection = new CdTableSelection(); | |
215 | return this.osdService.destroy(id); | |
216 | } | |
11fdf7f2 TL |
217 | ), |
218 | disable: () => this.isNotSelectedOrInState('up'), | |
9f95a23c TL |
219 | icon: Icons.destroyCircle |
220 | }, | |
221 | { | |
222 | name: this.actionLabels.DELETE, | |
223 | permission: 'delete', | |
f6b5b4d7 | 224 | click: () => this.delete(), |
9f95a23c TL |
225 | disable: () => !this.hasOsdSelected, |
226 | icon: Icons.destroy | |
11fdf7f2 TL |
227 | } |
228 | ]; | |
9f95a23c TL |
229 | } |
230 | ||
231 | ngOnInit() { | |
232 | this.clusterWideActions = [ | |
81eedcae | 233 | { |
9f95a23c TL |
234 | name: this.i18n('Flags'), |
235 | icon: Icons.flag, | |
81eedcae | 236 | click: () => this.configureFlagsAction(), |
9f95a23c TL |
237 | permission: 'read', |
238 | visible: () => this.permissions.osd.read | |
81eedcae TL |
239 | }, |
240 | { | |
9f95a23c TL |
241 | name: this.i18n('Recovery Priority'), |
242 | icon: Icons.deepCheck, | |
81eedcae | 243 | click: () => this.configureQosParamsAction(), |
9f95a23c TL |
244 | permission: 'read', |
245 | visible: () => this.permissions.configOpt.read | |
81eedcae TL |
246 | }, |
247 | { | |
248 | name: this.i18n('PG scrub'), | |
9f95a23c | 249 | icon: Icons.analyse, |
81eedcae | 250 | click: () => this.configurePgScrubAction(), |
9f95a23c TL |
251 | permission: 'read', |
252 | visible: () => this.permissions.configOpt.read | |
81eedcae TL |
253 | } |
254 | ]; | |
11fdf7f2 TL |
255 | this.columns = [ |
256 | { prop: 'host.name', name: this.i18n('Host') }, | |
9f95a23c TL |
257 | { prop: 'id', name: this.i18n('ID'), flexGrow: 1, cellTransformation: CellTemplate.bold }, |
258 | { | |
259 | prop: 'collectedStates', | |
260 | name: this.i18n('Status'), | |
261 | flexGrow: 1, | |
262 | cellTransformation: CellTemplate.badge, | |
263 | customTemplateConfig: { | |
264 | map: { | |
265 | in: { class: 'badge-success' }, | |
266 | up: { class: 'badge-success' }, | |
267 | down: { class: 'badge-danger' }, | |
268 | out: { class: 'badge-danger' }, | |
269 | destroyed: { class: 'badge-danger' } | |
270 | } | |
271 | } | |
272 | }, | |
273 | { | |
274 | prop: 'tree.device_class', | |
275 | name: this.i18n('Device class'), | |
276 | flexGrow: 1, | |
277 | cellTransformation: CellTemplate.badge, | |
278 | customTemplateConfig: { | |
279 | map: { | |
280 | hdd: { class: 'badge-hdd' }, | |
281 | ssd: { class: 'badge-ssd' } | |
282 | } | |
283 | } | |
284 | }, | |
285 | { | |
286 | prop: 'stats.numpg', | |
287 | name: this.i18n('PGs'), | |
288 | flexGrow: 1 | |
289 | }, | |
290 | { | |
291 | prop: 'stats.stat_bytes', | |
292 | name: this.i18n('Size'), | |
293 | flexGrow: 1, | |
294 | pipe: this.dimlessBinaryPipe | |
295 | }, | |
81eedcae | 296 | { prop: 'stats.usage', name: this.i18n('Usage'), cellTemplate: this.osdUsageTpl }, |
11fdf7f2 TL |
297 | { |
298 | prop: 'stats_history.out_bytes', | |
299 | name: this.i18n('Read bytes'), | |
300 | cellTransformation: CellTemplate.sparkline | |
301 | }, | |
302 | { | |
303 | prop: 'stats_history.in_bytes', | |
9f95a23c | 304 | name: this.i18n('Write bytes'), |
11fdf7f2 TL |
305 | cellTransformation: CellTemplate.sparkline |
306 | }, | |
307 | { | |
308 | prop: 'stats.op_r', | |
309 | name: this.i18n('Read ops'), | |
310 | cellTransformation: CellTemplate.perSecond | |
311 | }, | |
312 | { | |
313 | prop: 'stats.op_w', | |
314 | name: this.i18n('Write ops'), | |
315 | cellTransformation: CellTemplate.perSecond | |
316 | } | |
317 | ]; | |
9f95a23c | 318 | } |
81eedcae | 319 | |
9f95a23c TL |
320 | /** |
321 | * Only returns valid IDs, e.g. if an OSD is falsely still selected after being deleted, it won't | |
322 | * get returned. | |
323 | */ | |
324 | getSelectedOsdIds(): number[] { | |
325 | const osdIds = this.osds.map((osd) => osd.id); | |
326 | return this.selection.selected.map((row) => row.id).filter((id) => osdIds.includes(id)); | |
11fdf7f2 TL |
327 | } |
328 | ||
9f95a23c TL |
329 | getSelectedOsds(): any[] { |
330 | return this.osds.filter( | |
331 | (osd) => !_.isUndefined(osd) && this.getSelectedOsdIds().includes(osd.id) | |
332 | ); | |
333 | } | |
334 | ||
335 | get hasOsdSelected(): boolean { | |
336 | return this.getSelectedOsdIds().length > 0; | |
11fdf7f2 TL |
337 | } |
338 | ||
339 | updateSelection(selection: CdTableSelection) { | |
340 | this.selection = selection; | |
341 | } | |
342 | ||
343 | /** | |
9f95a23c | 344 | * Returns true if no rows are selected or if *any* of the selected rows are in the given |
11fdf7f2 TL |
345 | * state. Useful for deactivating the corresponding menu entry. |
346 | */ | |
347 | isNotSelectedOrInState(state: 'in' | 'up' | 'down' | 'out'): boolean { | |
9f95a23c TL |
348 | const selectedOsds = this.getSelectedOsds(); |
349 | if (selectedOsds.length === 0) { | |
11fdf7f2 TL |
350 | return true; |
351 | } | |
11fdf7f2 TL |
352 | switch (state) { |
353 | case 'in': | |
9f95a23c | 354 | return selectedOsds.some((osd) => osd.in === 1); |
11fdf7f2 | 355 | case 'out': |
9f95a23c | 356 | return selectedOsds.some((osd) => osd.in !== 1); |
11fdf7f2 | 357 | case 'down': |
9f95a23c | 358 | return selectedOsds.some((osd) => osd.up !== 1); |
11fdf7f2 | 359 | case 'up': |
9f95a23c | 360 | return selectedOsds.some((osd) => osd.up === 1); |
11fdf7f2 TL |
361 | } |
362 | } | |
363 | ||
364 | getOsdList() { | |
365 | this.osdService.getList().subscribe((data: any[]) => { | |
81eedcae | 366 | this.osds = data.map((osd) => { |
11fdf7f2 | 367 | osd.collectedStates = OsdListComponent.collectStates(osd); |
9f95a23c TL |
368 | osd.stats_history.out_bytes = osd.stats_history.op_out_bytes.map((i: string) => i[1]); |
369 | osd.stats_history.in_bytes = osd.stats_history.op_in_bytes.map((i: string) => i[1]); | |
81eedcae | 370 | osd.stats.usage = osd.stats.stat_bytes_used / osd.stats.stat_bytes; |
11fdf7f2 TL |
371 | osd.cdIsBinary = true; |
372 | return osd; | |
373 | }); | |
374 | }); | |
375 | } | |
376 | ||
9f95a23c TL |
377 | editAction() { |
378 | const selectedOsd = _.filter(this.osds, ['id', this.selection.first().id]).pop(); | |
379 | ||
380 | this.modalService.show(FormModalComponent, { | |
381 | initialState: { | |
382 | titleText: this.i18n('Edit OSD: {{id}}', { | |
383 | id: selectedOsd.id | |
384 | }), | |
385 | fields: [ | |
386 | { | |
387 | type: 'text', | |
388 | name: 'deviceClass', | |
389 | value: selectedOsd.tree.device_class, | |
390 | label: this.i18n('Device class'), | |
391 | required: true | |
392 | } | |
393 | ], | |
394 | submitButtonText: this.i18n('Edit OSD'), | |
395 | onSubmit: (values: any) => { | |
396 | this.osdService.update(selectedOsd.id, values.deviceClass).subscribe(() => { | |
397 | this.notificationService.show( | |
398 | NotificationType.success, | |
399 | this.i18n('Updated OSD "{{id}}"', { | |
400 | id: selectedOsd.id | |
401 | }) | |
402 | ); | |
403 | this.getOsdList(); | |
404 | }); | |
405 | } | |
406 | } | |
407 | }); | |
408 | } | |
409 | ||
410 | scrubAction(deep: boolean) { | |
11fdf7f2 TL |
411 | if (!this.hasOsdSelected) { |
412 | return; | |
413 | } | |
414 | ||
415 | const initialState = { | |
9f95a23c | 416 | selected: this.getSelectedOsdIds(), |
11fdf7f2 TL |
417 | deep: deep |
418 | }; | |
419 | ||
420 | this.bsModalRef = this.modalService.show(OsdScrubModalComponent, { initialState }); | |
421 | } | |
422 | ||
81eedcae | 423 | configureFlagsAction() { |
11fdf7f2 TL |
424 | this.bsModalRef = this.modalService.show(OsdFlagsModalComponent, {}); |
425 | } | |
426 | ||
427 | showConfirmationModal(markAction: string, onSubmit: (id: number) => Observable<any>) { | |
428 | this.bsModalRef = this.modalService.show(ConfirmationModalComponent, { | |
429 | initialState: { | |
430 | titleText: this.i18n('Mark OSD {{markAction}}', { markAction: markAction }), | |
431 | buttonText: this.i18n('Mark {{markAction}}', { markAction: markAction }), | |
432 | bodyTpl: this.markOsdConfirmationTpl, | |
433 | bodyContext: { | |
434 | markActionDescription: markAction | |
435 | }, | |
436 | onSubmit: () => { | |
9f95a23c TL |
437 | observableForkJoin( |
438 | this.getSelectedOsdIds().map((osd: any) => onSubmit.call(this.osdService, osd)) | |
439 | ).subscribe(() => this.bsModalRef.hide()); | |
11fdf7f2 TL |
440 | } |
441 | } | |
442 | }); | |
443 | } | |
444 | ||
445 | reweight() { | |
446 | const selectedOsd = this.osds.filter((o) => o.id === this.selection.first().id).pop(); | |
447 | this.modalService.show(OsdReweightModalComponent, { | |
448 | initialState: { | |
449 | currentWeight: selectedOsd.weight, | |
450 | osdId: selectedOsd.id | |
451 | } | |
452 | }); | |
453 | } | |
454 | ||
f6b5b4d7 TL |
455 | delete() { |
456 | const deleteFormGroup = new CdFormGroup({ | |
457 | preserve: new FormControl(false) | |
458 | }); | |
459 | ||
460 | this.depCheckerService.checkOrchestratorOrModal( | |
461 | this.actionLabels.DELETE, | |
462 | this.i18n('OSD'), | |
463 | () => { | |
464 | this.showCriticalConfirmationModal( | |
465 | this.i18n('delete'), | |
466 | this.i18n('OSD'), | |
467 | this.i18n('deleted'), | |
468 | (ids: number[]) => { | |
469 | return this.osdService.safeToDelete(JSON.stringify(ids)); | |
470 | }, | |
471 | 'is_safe_to_delete', | |
472 | (id: number) => { | |
473 | this.selection = new CdTableSelection(); | |
474 | return this.taskWrapper.wrapTaskAroundCall({ | |
475 | task: new FinishedTask('osd/' + URLVerbs.DELETE, { | |
476 | svc_id: id | |
477 | }), | |
478 | call: this.osdService.delete(id, deleteFormGroup.value.preserve, true) | |
479 | }); | |
480 | }, | |
481 | true, | |
482 | deleteFormGroup, | |
483 | this.deleteOsdExtraTpl | |
484 | ); | |
485 | } | |
486 | ); | |
487 | } | |
488 | ||
9f95a23c TL |
489 | /** |
490 | * Perform check first and display a critical confirmation modal. | |
491 | * @param {string} actionDescription name of the action. | |
492 | * @param {string} itemDescription the item's name that the action operates on. | |
493 | * @param {string} templateItemDescription the action name to be displayed in modal template. | |
494 | * @param {Function} check the function is called to check if the action is safe. | |
495 | * @param {string} checkKey the safe indicator's key in the check response. | |
496 | * @param {Function} action the action function. | |
f6b5b4d7 TL |
497 | * @param {boolean} taskWrapped if true, hide confirmation modal after action |
498 | * @param {CdFormGroup} childFormGroup additional child form group to be passed to confirmation modal | |
499 | * @param {TemplateRef<any>} childFormGroupTemplate template for additional child form group | |
9f95a23c | 500 | */ |
11fdf7f2 TL |
501 | showCriticalConfirmationModal( |
502 | actionDescription: string, | |
503 | itemDescription: string, | |
504 | templateItemDescription: string, | |
9f95a23c TL |
505 | check: (ids: number[]) => Observable<any>, |
506 | checkKey: string, | |
507 | action: (id: number | number[]) => Observable<any>, | |
f6b5b4d7 TL |
508 | taskWrapped: boolean = false, |
509 | childFormGroup?: CdFormGroup, | |
510 | childFormGroupTemplate?: TemplateRef<any> | |
11fdf7f2 | 511 | ): void { |
9f95a23c | 512 | check(this.getSelectedOsdIds()).subscribe((result) => { |
11fdf7f2 TL |
513 | const modalRef = this.modalService.show(CriticalConfirmationModalComponent, { |
514 | initialState: { | |
515 | actionDescription: actionDescription, | |
516 | itemDescription: itemDescription, | |
517 | bodyTemplate: this.criticalConfirmationTpl, | |
518 | bodyContext: { | |
9f95a23c TL |
519 | safeToPerform: result[checkKey], |
520 | message: result.message, | |
f6b5b4d7 TL |
521 | actionDescription: templateItemDescription, |
522 | osdIds: this.getSelectedOsdIds() | |
11fdf7f2 | 523 | }, |
f6b5b4d7 TL |
524 | childFormGroup: childFormGroup, |
525 | childFormGroupTemplate: childFormGroupTemplate, | |
11fdf7f2 | 526 | submitAction: () => { |
9f95a23c TL |
527 | const observable = observableForkJoin( |
528 | this.getSelectedOsdIds().map((osd: any) => action.call(this.osdService, osd)) | |
529 | ); | |
530 | if (taskWrapped) { | |
531 | observable.subscribe( | |
532 | undefined, | |
533 | () => { | |
534 | this.getOsdList(); | |
535 | modalRef.hide(); | |
536 | }, | |
537 | () => modalRef.hide() | |
538 | ); | |
539 | } else { | |
540 | observable.subscribe( | |
541 | () => { | |
542 | this.getOsdList(); | |
543 | modalRef.hide(); | |
544 | }, | |
545 | () => modalRef.hide() | |
546 | ); | |
547 | } | |
11fdf7f2 TL |
548 | } |
549 | } | |
550 | }); | |
551 | }); | |
552 | } | |
553 | ||
554 | configureQosParamsAction() { | |
555 | this.bsModalRef = this.modalService.show(OsdRecvSpeedModalComponent, {}); | |
556 | } | |
81eedcae TL |
557 | |
558 | configurePgScrubAction() { | |
559 | this.bsModalRef = this.modalService.show(OsdPgScrubModalComponent, { class: 'modal-lg' }); | |
560 | } | |
11fdf7f2 | 561 | } |