]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core'; |
2 | ||
f67539c2 TL |
3 | import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; |
4 | import _ from 'lodash'; | |
5 | import moment from 'moment'; | |
6 | ||
7 | import { RbdService } from '~/app/shared/api/rbd.service'; | |
8 | import { TableStatusViewCache } from '~/app/shared/classes/table-status-view-cache'; | |
9 | import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component'; | |
10 | import { ActionLabelsI18n } from '~/app/shared/constants/app.constants'; | |
11 | import { TableComponent } from '~/app/shared/datatable/table/table.component'; | |
12 | import { CellTemplate } from '~/app/shared/enum/cell-template.enum'; | |
13 | import { Icons } from '~/app/shared/enum/icons.enum'; | |
14 | import { ViewCacheStatus } from '~/app/shared/enum/view-cache-status.enum'; | |
15 | import { CdTableAction } from '~/app/shared/models/cd-table-action'; | |
16 | import { CdTableColumn } from '~/app/shared/models/cd-table-column'; | |
17 | import { CdTableSelection } from '~/app/shared/models/cd-table-selection'; | |
18 | import { ExecutingTask } from '~/app/shared/models/executing-task'; | |
19 | import { FinishedTask } from '~/app/shared/models/finished-task'; | |
20 | import { ImageSpec } from '~/app/shared/models/image-spec'; | |
21 | import { Permission } from '~/app/shared/models/permissions'; | |
22 | import { Task } from '~/app/shared/models/task'; | |
23 | import { CdDatePipe } from '~/app/shared/pipes/cd-date.pipe'; | |
24 | import { AuthStorageService } from '~/app/shared/services/auth-storage.service'; | |
25 | import { ModalService } from '~/app/shared/services/modal.service'; | |
26 | import { TaskListService } from '~/app/shared/services/task-list.service'; | |
27 | import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service'; | |
11fdf7f2 TL |
28 | import { RbdTrashPurgeModalComponent } from '../rbd-trash-purge-modal/rbd-trash-purge-modal.component'; |
29 | import { RbdTrashRestoreModalComponent } from '../rbd-trash-restore-modal/rbd-trash-restore-modal.component'; | |
30 | ||
31 | @Component({ | |
32 | selector: 'cd-rbd-trash-list', | |
33 | templateUrl: './rbd-trash-list.component.html', | |
34 | styleUrls: ['./rbd-trash-list.component.scss'], | |
35 | providers: [TaskListService] | |
36 | }) | |
37 | export class RbdTrashListComponent implements OnInit { | |
9f95a23c | 38 | @ViewChild(TableComponent, { static: true }) |
11fdf7f2 | 39 | table: TableComponent; |
9f95a23c | 40 | @ViewChild('expiresTpl', { static: true }) |
11fdf7f2 | 41 | expiresTpl: TemplateRef<any>; |
9f95a23c | 42 | @ViewChild('deleteTpl', { static: true }) |
11fdf7f2 TL |
43 | deleteTpl: TemplateRef<any>; |
44 | ||
9f95a23c TL |
45 | icons = Icons; |
46 | ||
11fdf7f2 TL |
47 | columns: CdTableColumn[]; |
48 | executingTasks: ExecutingTask[] = []; | |
49 | images: any; | |
f67539c2 | 50 | modalRef: NgbModalRef; |
11fdf7f2 TL |
51 | permission: Permission; |
52 | retries: number; | |
53 | selection = new CdTableSelection(); | |
54 | tableActions: CdTableAction[]; | |
f67539c2 | 55 | tableStatus = new TableStatusViewCache(); |
9f95a23c | 56 | disablePurgeBtn = true; |
11fdf7f2 TL |
57 | |
58 | constructor( | |
59 | private authStorageService: AuthStorageService, | |
60 | private rbdService: RbdService, | |
f67539c2 | 61 | private modalService: ModalService, |
11fdf7f2 | 62 | private cdDatePipe: CdDatePipe, |
f67539c2 | 63 | public taskListService: TaskListService, |
11fdf7f2 | 64 | private taskWrapper: TaskWrapperService, |
eafe8130 | 65 | public actionLabels: ActionLabelsI18n |
11fdf7f2 TL |
66 | ) { |
67 | this.permission = this.authStorageService.getPermissions().rbdImage; | |
11fdf7f2 TL |
68 | const restoreAction: CdTableAction = { |
69 | permission: 'update', | |
9f95a23c | 70 | icon: Icons.undo, |
11fdf7f2 | 71 | click: () => this.restoreModal(), |
eafe8130 | 72 | name: this.actionLabels.RESTORE |
11fdf7f2 TL |
73 | }; |
74 | const deleteAction: CdTableAction = { | |
75 | permission: 'delete', | |
9f95a23c | 76 | icon: Icons.destroy, |
11fdf7f2 | 77 | click: () => this.deleteModal(), |
eafe8130 | 78 | name: this.actionLabels.DELETE |
11fdf7f2 TL |
79 | }; |
80 | this.tableActions = [restoreAction, deleteAction]; | |
81 | } | |
82 | ||
83 | ngOnInit() { | |
84 | this.columns = [ | |
85 | { | |
f67539c2 | 86 | name: $localize`ID`, |
11fdf7f2 TL |
87 | prop: 'id', |
88 | flexGrow: 1, | |
89 | cellTransformation: CellTemplate.executing | |
90 | }, | |
91 | { | |
f67539c2 | 92 | name: $localize`Name`, |
11fdf7f2 TL |
93 | prop: 'name', |
94 | flexGrow: 1 | |
95 | }, | |
96 | { | |
f67539c2 | 97 | name: $localize`Pool`, |
11fdf7f2 TL |
98 | prop: 'pool_name', |
99 | flexGrow: 1 | |
100 | }, | |
9f95a23c | 101 | { |
f67539c2 | 102 | name: $localize`Namespace`, |
9f95a23c TL |
103 | prop: 'namespace', |
104 | flexGrow: 1 | |
105 | }, | |
11fdf7f2 | 106 | { |
f67539c2 | 107 | name: $localize`Status`, |
11fdf7f2 TL |
108 | prop: 'deferment_end_time', |
109 | flexGrow: 1, | |
110 | cellTemplate: this.expiresTpl | |
111 | }, | |
112 | { | |
f67539c2 | 113 | name: $localize`Deleted At`, |
11fdf7f2 TL |
114 | prop: 'deletion_time', |
115 | flexGrow: 1, | |
116 | pipe: this.cdDatePipe | |
117 | } | |
118 | ]; | |
119 | ||
9f95a23c TL |
120 | const itemFilter = (entry: any, task: Task) => { |
121 | const imageSpec = new ImageSpec(entry.pool_name, entry.namespace, entry.id); | |
122 | return imageSpec.toString() === task.metadata['image_id_spec']; | |
123 | }; | |
124 | ||
125 | const taskFilter = (task: Task) => { | |
126 | return ['rbd/trash/remove', 'rbd/trash/restore'].includes(task.name); | |
127 | }; | |
128 | ||
11fdf7f2 TL |
129 | this.taskListService.init( |
130 | () => this.rbdService.listTrash(), | |
131 | (resp) => this.prepareResponse(resp), | |
132 | (images) => (this.images = images), | |
133 | () => this.onFetchError(), | |
9f95a23c TL |
134 | taskFilter, |
135 | itemFilter, | |
11fdf7f2 TL |
136 | undefined |
137 | ); | |
138 | } | |
139 | ||
140 | prepareResponse(resp: any[]): any[] { | |
9f95a23c | 141 | let images: any[] = []; |
11fdf7f2 | 142 | const viewCacheStatusMap = {}; |
f67539c2 | 143 | |
9f95a23c | 144 | resp.forEach((pool: Record<string, any>) => { |
11fdf7f2 TL |
145 | if (_.isUndefined(viewCacheStatusMap[pool.status])) { |
146 | viewCacheStatusMap[pool.status] = []; | |
147 | } | |
148 | viewCacheStatusMap[pool.status].push(pool.pool_name); | |
149 | images = images.concat(pool.value); | |
9f95a23c | 150 | this.disablePurgeBtn = !images.length; |
11fdf7f2 TL |
151 | }); |
152 | ||
f67539c2 TL |
153 | let status: number; |
154 | if (viewCacheStatusMap[3]) { | |
155 | status = 3; | |
156 | } else if (viewCacheStatusMap[1]) { | |
157 | status = 1; | |
158 | } else if (viewCacheStatusMap[2]) { | |
159 | status = 2; | |
160 | } | |
161 | ||
162 | if (status) { | |
163 | const statusFor = | |
164 | (viewCacheStatusMap[status].length > 1 ? 'pools ' : 'pool ') + | |
165 | viewCacheStatusMap[status].join(); | |
166 | ||
167 | this.tableStatus = new TableStatusViewCache(status, statusFor); | |
168 | } else { | |
169 | this.tableStatus = new TableStatusViewCache(); | |
170 | } | |
171 | ||
11fdf7f2 TL |
172 | images.forEach((image) => { |
173 | image.cdIsExpired = moment().isAfter(image.deferment_end_time); | |
174 | }); | |
f67539c2 | 175 | |
11fdf7f2 TL |
176 | return images; |
177 | } | |
178 | ||
179 | onFetchError() { | |
180 | this.table.reset(); // Disable loading indicator. | |
f67539c2 | 181 | this.tableStatus = new TableStatusViewCache(ViewCacheStatus.ValueException); |
11fdf7f2 TL |
182 | } |
183 | ||
11fdf7f2 TL |
184 | updateSelection(selection: CdTableSelection) { |
185 | this.selection = selection; | |
186 | } | |
187 | ||
188 | restoreModal() { | |
189 | const initialState = { | |
11fdf7f2 | 190 | poolName: this.selection.first().pool_name, |
9f95a23c | 191 | namespace: this.selection.first().namespace, |
11fdf7f2 TL |
192 | imageName: this.selection.first().name, |
193 | imageId: this.selection.first().id | |
194 | }; | |
195 | ||
f67539c2 | 196 | this.modalRef = this.modalService.show(RbdTrashRestoreModalComponent, initialState); |
11fdf7f2 TL |
197 | } |
198 | ||
199 | deleteModal() { | |
200 | const poolName = this.selection.first().pool_name; | |
9f95a23c | 201 | const namespace = this.selection.first().namespace; |
11fdf7f2 TL |
202 | const imageId = this.selection.first().id; |
203 | const expiresAt = this.selection.first().deferment_end_time; | |
f67539c2 | 204 | const isExpired = moment().isAfter(expiresAt); |
9f95a23c | 205 | const imageIdSpec = new ImageSpec(poolName, namespace, imageId); |
11fdf7f2 TL |
206 | |
207 | this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, { | |
f67539c2 TL |
208 | itemDescription: 'RBD', |
209 | itemNames: [imageIdSpec], | |
210 | bodyTemplate: this.deleteTpl, | |
211 | bodyContext: { expiresAt, isExpired }, | |
212 | submitActionObservable: () => | |
213 | this.taskWrapper.wrapTaskAroundCall({ | |
214 | task: new FinishedTask('rbd/trash/remove', { | |
215 | image_id_spec: imageIdSpec.toString() | |
216 | }), | |
217 | call: this.rbdService.removeTrash(imageIdSpec, true) | |
218 | }) | |
11fdf7f2 TL |
219 | }); |
220 | } | |
221 | ||
11fdf7f2 TL |
222 | purgeModal() { |
223 | this.modalService.show(RbdTrashPurgeModalComponent); | |
224 | } | |
225 | } |