]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/blob
b93c4ae788ec446964db799fb24229273a8cbd9a
[ceph-ci.git] /
1 import { Component, Input, OnChanges, SimpleChanges, TemplateRef, ViewChild } from '@angular/core';
2 import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
3 import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
4 import { Icons } from '~/app/shared/enum/icons.enum';
5 import { CdTableAction } from '~/app/shared/models/cd-table-action';
6 import { CdTableColumn } from '~/app/shared/models/cd-table-column';
7 import { CdTableSelection } from '~/app/shared/models/cd-table-selection';
8 import { Permission } from '~/app/shared/models/permissions';
9 import { ModalService } from '~/app/shared/services/modal.service';
10 import { RgwMultisiteService } from '~/app/shared/api/rgw-multisite.service';
11 import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
12 import { FinishedTask } from '~/app/shared/models/finished-task';
13 import { Observable, Subscriber, forkJoin as observableForkJoin } from 'rxjs';
14 import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service';
15 import { TableComponent } from '~/app/shared/datatable/table/table.component';
16 import { RgwMultisiteSyncFlowModalComponent } from '../rgw-multisite-sync-flow-modal/rgw-multisite-sync-flow-modal.component';
17 import { FlowType } from '../models/rgw-multisite';
18 import { RgwMultisiteSyncPipeModalComponent } from '../rgw-multisite-sync-pipe-modal/rgw-multisite-sync-pipe-modal.component';
19
20 @Component({
21   selector: 'cd-rgw-multisite-sync-policy-details',
22   templateUrl: './rgw-multisite-sync-policy-details.component.html',
23   styleUrls: ['./rgw-multisite-sync-policy-details.component.scss']
24 })
25 export class RgwMultisiteSyncPolicyDetailsComponent implements OnChanges {
26   @Input()
27   expandedRow: any;
28   @Input()
29   permission: Permission;
30
31   @ViewChild(TableComponent)
32   table: TableComponent;
33   @ViewChild('deleteTpl', { static: true })
34   deleteTpl: TemplateRef<any>;
35
36   flowType = FlowType;
37   modalRef: NgbModalRef;
38   symmetricalFlowData: any = [];
39   directionalFlowData: any = [];
40   pipeData: any = [];
41   symmetricalFlowCols: CdTableColumn[];
42   directionalFlowCols: CdTableColumn[];
43   pipeCols: CdTableColumn[];
44   symFlowTableActions: CdTableAction[];
45   dirFlowTableActions: CdTableAction[];
46   pipeTableActions: CdTableAction[];
47   symFlowSelection = new CdTableSelection();
48   dirFlowSelection = new CdTableSelection();
49   pipeSelection = new CdTableSelection();
50
51   constructor(
52     private actionLabels: ActionLabelsI18n,
53     private modalService: ModalService,
54     private rgwMultisiteService: RgwMultisiteService,
55     private taskWrapper: TaskWrapperService
56   ) {
57     this.symmetricalFlowCols = [
58       {
59         name: 'Name',
60         prop: 'id',
61         flexGrow: 1
62       },
63       {
64         name: 'Zones',
65         prop: 'zones',
66         flexGrow: 1
67       }
68     ];
69     this.directionalFlowCols = [
70       {
71         name: 'Source Zone',
72         prop: 'source_zone',
73         flexGrow: 1
74       },
75       {
76         name: 'Destination Zone',
77         prop: 'dest_zone',
78         flexGrow: 1
79       }
80     ];
81     this.pipeCols = [
82       {
83         name: 'Name',
84         prop: 'id',
85         flexGrow: 1
86       },
87       {
88         name: 'Source Zone',
89         prop: 'source.zones',
90         flexGrow: 1
91       },
92       {
93         name: 'Destination Zone',
94         prop: 'dest.zones',
95         flexGrow: 1
96       },
97       {
98         name: 'Source Bucket',
99         prop: 'source.bucket',
100         flexGrow: 1
101       },
102       {
103         name: 'Destination Bucket',
104         prop: 'dest.bucket',
105         flexGrow: 1
106       }
107     ];
108     const symAddAction: CdTableAction = {
109       permission: 'create',
110       icon: Icons.add,
111       name: this.actionLabels.CREATE,
112       click: () => this.openModal(FlowType.symmetrical),
113       canBePrimary: (selection: CdTableSelection) => !selection.hasSelection
114     };
115     const symEditAction: CdTableAction = {
116       permission: 'update',
117       icon: Icons.edit,
118       name: this.actionLabels.EDIT,
119       click: () => this.openModal(FlowType.symmetrical, true)
120     };
121     const symDeleteAction: CdTableAction = {
122       permission: 'delete',
123       icon: Icons.destroy,
124       disable: () => !this.symFlowSelection.hasSelection,
125       name: this.actionLabels.DELETE,
126       click: () => this.deleteFlow(FlowType.symmetrical),
127       canBePrimary: (selection: CdTableSelection) => selection.hasMultiSelection
128     };
129     this.symFlowTableActions = [symAddAction, symEditAction, symDeleteAction];
130     const dirAddAction: CdTableAction = {
131       permission: 'create',
132       icon: Icons.add,
133       name: this.actionLabels.CREATE,
134       click: () => this.openModal(FlowType.directional),
135       canBePrimary: (selection: CdTableSelection) => !selection.hasSelection
136     };
137     const dirEditAction: CdTableAction = {
138       permission: 'update',
139       icon: Icons.edit,
140       name: this.actionLabels.EDIT,
141       click: () => this.openModal(FlowType.directional, true),
142       disable: () => true // TODO: disabling 'edit' as we are not getting flow ID from backend which is needed for edit
143     };
144     const dirDeleteAction: CdTableAction = {
145       permission: 'delete',
146       icon: Icons.destroy,
147       disable: () => true, // TODO: disabling 'delete' as we are not getting flow ID from backend which is needed for deletion
148       name: this.actionLabels.DELETE,
149       click: () => this.deleteFlow(FlowType.directional),
150       canBePrimary: (selection: CdTableSelection) => selection.hasMultiSelection
151     };
152     this.dirFlowTableActions = [dirAddAction, dirEditAction, dirDeleteAction];
153     const pipeAddAction: CdTableAction = {
154       permission: 'create',
155       icon: Icons.add,
156       name: this.actionLabels.CREATE,
157       click: () => this.openPipeModal(),
158       canBePrimary: (selection: CdTableSelection) => !selection.hasSelection
159     };
160     const pipeEditAction: CdTableAction = {
161       permission: 'update',
162       icon: Icons.edit,
163       name: this.actionLabels.EDIT,
164       click: () => this.openPipeModal(true)
165     };
166     const pipeDeleteAction: CdTableAction = {
167       permission: 'delete',
168       icon: Icons.destroy,
169       disable: () => !this.pipeSelection.hasSelection,
170       name: this.actionLabels.DELETE,
171       click: () => this.deletePipe(),
172       canBePrimary: (selection: CdTableSelection) => selection.hasMultiSelection
173     };
174     this.pipeTableActions = [pipeAddAction, pipeEditAction, pipeDeleteAction];
175   }
176
177   ngOnChanges(changes: SimpleChanges): void {
178     if (changes.expandedRow.currentValue && changes.expandedRow.currentValue.groupName) {
179       this.symmetricalFlowData = [];
180       this.directionalFlowData = [];
181       this.loadData();
182     }
183   }
184
185   loadData(context?: any) {
186     if (this.expandedRow) {
187       this.rgwMultisiteService
188         .getSyncPolicyGroup(this.expandedRow.groupName, this.expandedRow.bucket)
189         .subscribe(
190           (policy: any) => {
191             this.symmetricalFlowData = policy.data_flow[FlowType.symmetrical] || [];
192             this.directionalFlowData = policy.data_flow[FlowType.directional] || [];
193             this.pipeData = policy.pipes || [];
194           },
195           () => {
196             if (context) {
197               context.error();
198             }
199           }
200         );
201     }
202   }
203
204   updateSelection(selection: any, type: FlowType) {
205     if (type === FlowType.directional) {
206       this.dirFlowSelection = selection;
207     } else {
208       this.symFlowSelection = selection;
209     }
210   }
211
212   async openModal(flowType: FlowType, edit = false) {
213     const action = edit ? 'edit' : 'create';
214     const initialState = {
215       groupType: flowType,
216       groupExpandedRow: this.expandedRow,
217       flowSelectedRow:
218         flowType === FlowType.symmetrical
219           ? this.symFlowSelection.first()
220           : this.dirFlowSelection.first(),
221       action: action
222     };
223
224     this.modalRef = this.modalService.show(RgwMultisiteSyncFlowModalComponent, initialState, {
225       size: 'lg'
226     });
227
228     try {
229       const res = await this.modalRef.result;
230       if (res === 'success') {
231         this.loadData();
232       }
233     } catch (err) {}
234   }
235
236   deleteFlow(flowType: FlowType) {
237     let selection = this.symFlowSelection;
238     if (flowType === FlowType.directional) {
239       selection = this.dirFlowSelection;
240     }
241     const flowIds = selection.selected.map((flow: any) => flow.id);
242     this.modalService.show(CriticalConfirmationModalComponent, {
243       itemDescription: selection.hasSingleSelection ? $localize`Flow` : $localize`Flows`,
244       itemNames: flowIds,
245       bodyTemplate: this.deleteTpl,
246       submitActionObservable: () => {
247         return new Observable((observer: Subscriber<any>) => {
248           this.taskWrapper
249             .wrapTaskAroundCall({
250               task: new FinishedTask('rgw/multisite/sync-flow/delete', {
251                 flow_ids: flowIds
252               }),
253               call: observableForkJoin(
254                 selection.selected.map((flow: any) => {
255                   return this.rgwMultisiteService.removeSyncFlow(
256                     flow.id,
257                     flowType,
258                     this.expandedRow.groupName,
259                     this.expandedRow.bucket
260                   );
261                 })
262               )
263             })
264             .subscribe({
265               error: (error: any) => {
266                 // Forward the error to the observer.
267                 observer.error(error);
268                 // Reload the data table content because some deletions might
269                 // have been executed successfully in the meanwhile.
270                 this.table.refreshBtn();
271               },
272               complete: () => {
273                 // Notify the observer that we are done.
274                 observer.complete();
275                 // Reload the data table content.
276                 this.table.refreshBtn();
277               }
278             });
279         });
280       }
281     });
282   }
283
284   async openPipeModal(edit = false) {
285     const action = edit ? 'edit' : 'create';
286     const initialState = {
287       groupExpandedRow: this.expandedRow,
288       pipeSelectedRow: this.pipeSelection.first(),
289       action: action
290     };
291
292     this.modalRef = this.modalService.show(RgwMultisiteSyncPipeModalComponent, initialState, {
293       size: 'lg'
294     });
295
296     try {
297       const res = await this.modalRef.result;
298       if (res === 'success') {
299         this.loadData();
300       }
301     } catch (err) {}
302   }
303
304   deletePipe() {
305     const pipeIds = this.pipeSelection.selected.map((pipe: any) => pipe.id);
306     this.modalService.show(CriticalConfirmationModalComponent, {
307       itemDescription: this.pipeSelection.hasSingleSelection ? $localize`Pipe` : $localize`Pipes`,
308       itemNames: pipeIds,
309       bodyTemplate: this.deleteTpl,
310       submitActionObservable: () => {
311         return new Observable((observer: Subscriber<any>) => {
312           this.taskWrapper
313             .wrapTaskAroundCall({
314               task: new FinishedTask('rgw/multisite/sync-pipe/delete', {
315                 pipe_ids: pipeIds
316               }),
317               call: observableForkJoin(
318                 this.pipeSelection.selected.map((pipe: any) => {
319                   return this.rgwMultisiteService.removeSyncPipe(
320                     pipe.id,
321                     this.expandedRow.groupName,
322                     this.expandedRow.bucket
323                   );
324                 })
325               )
326             })
327             .subscribe({
328               error: (error: any) => {
329                 // Forward the error to the observer.
330                 observer.error(error);
331                 // Reload the data table content because some deletions might
332                 // have been executed successfully in the meanwhile.
333                 this.table.refreshBtn();
334               },
335               complete: () => {
336                 // Notify the observer that we are done.
337                 observer.complete();
338                 // Reload the data table content.
339                 this.table.refreshBtn();
340               }
341             });
342         });
343       }
344     });
345   }
346 }