]>
Commit | Line | Data |
---|---|---|
9f95a23c TL |
1 | import { |
2 | Component, | |
3 | EventEmitter, | |
4 | Input, | |
5 | OnDestroy, | |
6 | OnInit, | |
7 | Output, | |
8 | ViewChild | |
9 | } from '@angular/core'; | |
9f95a23c | 10 | |
f67539c2 | 11 | import _ from 'lodash'; |
9f95a23c TL |
12 | import { Subscription } from 'rxjs'; |
13 | ||
f67539c2 TL |
14 | import { HostService } from '~/app/shared/api/host.service'; |
15 | import { OrchestratorService } from '~/app/shared/api/orchestrator.service'; | |
16 | import { FormModalComponent } from '~/app/shared/components/form-modal/form-modal.component'; | |
17 | import { TableComponent } from '~/app/shared/datatable/table/table.component'; | |
18 | import { CellTemplate } from '~/app/shared/enum/cell-template.enum'; | |
19 | import { Icons } from '~/app/shared/enum/icons.enum'; | |
20 | import { NotificationType } from '~/app/shared/enum/notification-type.enum'; | |
21 | import { CdTableAction } from '~/app/shared/models/cd-table-action'; | |
22 | import { CdTableColumn } from '~/app/shared/models/cd-table-column'; | |
23 | import { CdTableColumnFiltersChange } from '~/app/shared/models/cd-table-column-filters-change'; | |
24 | import { CdTableSelection } from '~/app/shared/models/cd-table-selection'; | |
25 | import { OrchestratorFeature } from '~/app/shared/models/orchestrator.enum'; | |
26 | import { OrchestratorStatus } from '~/app/shared/models/orchestrator.interface'; | |
27 | import { Permission } from '~/app/shared/models/permissions'; | |
28 | import { DimlessBinaryPipe } from '~/app/shared/pipes/dimless-binary.pipe'; | |
29 | import { AuthStorageService } from '~/app/shared/services/auth-storage.service'; | |
30 | import { ModalService } from '~/app/shared/services/modal.service'; | |
31 | import { NotificationService } from '~/app/shared/services/notification.service'; | |
9f95a23c TL |
32 | import { InventoryDevice } from './inventory-device.model'; |
33 | ||
34 | @Component({ | |
35 | selector: 'cd-inventory-devices', | |
36 | templateUrl: './inventory-devices.component.html', | |
37 | styleUrls: ['./inventory-devices.component.scss'] | |
38 | }) | |
39 | export class InventoryDevicesComponent implements OnInit, OnDestroy { | |
40 | @ViewChild(TableComponent, { static: true }) | |
41 | table: TableComponent; | |
42 | ||
43 | // Devices | |
44 | @Input() devices: InventoryDevice[] = []; | |
45 | ||
a4b75251 | 46 | @Input() showAvailDeviceOnly = false; |
9f95a23c TL |
47 | // Do not display these columns |
48 | @Input() hiddenColumns: string[] = []; | |
49 | ||
39ae355f TL |
50 | @Input() hostname = ''; |
51 | ||
52 | @Input() diskType = ''; | |
53 | ||
9f95a23c TL |
54 | // Show filters for these columns, specify empty array to disable |
55 | @Input() filterColumns = [ | |
56 | 'hostname', | |
57 | 'human_readable_type', | |
58 | 'available', | |
59 | 'sys_api.vendor', | |
60 | 'sys_api.model', | |
61 | 'sys_api.size' | |
62 | ]; | |
63 | ||
64 | // Device table row selection type | |
65 | @Input() selectionType: string = undefined; | |
66 | ||
67 | @Output() filterChange = new EventEmitter<CdTableColumnFiltersChange>(); | |
68 | ||
69 | @Output() fetchInventory = new EventEmitter(); | |
70 | ||
71 | icons = Icons; | |
72 | columns: Array<CdTableColumn> = []; | |
73 | selection: CdTableSelection = new CdTableSelection(); | |
74 | permission: Permission; | |
75 | tableActions: CdTableAction[]; | |
76 | fetchInventorySub: Subscription; | |
77 | ||
f67539c2 TL |
78 | @Input() orchStatus: OrchestratorStatus = undefined; |
79 | ||
80 | actionOrchFeatures = { | |
81 | identify: [OrchestratorFeature.DEVICE_BLINK_LIGHT] | |
82 | }; | |
83 | ||
9f95a23c TL |
84 | constructor( |
85 | private authStorageService: AuthStorageService, | |
86 | private dimlessBinary: DimlessBinaryPipe, | |
f67539c2 | 87 | private modalService: ModalService, |
9f95a23c | 88 | private notificationService: NotificationService, |
f67539c2 TL |
89 | private orchService: OrchestratorService, |
90 | private hostService: HostService | |
9f95a23c TL |
91 | ) {} |
92 | ||
93 | ngOnInit() { | |
94 | this.permission = this.authStorageService.getPermissions().osd; | |
95 | this.tableActions = [ | |
96 | { | |
97 | permission: 'update', | |
98 | icon: Icons.show, | |
99 | click: () => this.identifyDevice(), | |
f67539c2 TL |
100 | name: $localize`Identify`, |
101 | disable: (selection: CdTableSelection) => this.getDisable('identify', selection), | |
9f95a23c TL |
102 | canBePrimary: (selection: CdTableSelection) => !selection.hasSingleSelection, |
103 | visible: () => _.isString(this.selectionType) | |
104 | } | |
105 | ]; | |
106 | const columns = [ | |
107 | { | |
f67539c2 | 108 | name: $localize`Hostname`, |
9f95a23c TL |
109 | prop: 'hostname', |
110 | flexGrow: 1 | |
111 | }, | |
112 | { | |
f67539c2 | 113 | name: $localize`Device path`, |
9f95a23c TL |
114 | prop: 'path', |
115 | flexGrow: 1 | |
116 | }, | |
117 | { | |
f67539c2 | 118 | name: $localize`Type`, |
9f95a23c TL |
119 | prop: 'human_readable_type', |
120 | flexGrow: 1, | |
121 | cellTransformation: CellTemplate.badge, | |
122 | customTemplateConfig: { | |
123 | map: { | |
124 | hdd: { value: 'HDD', class: 'badge-hdd' }, | |
125 | ssd: { value: 'SSD', class: 'badge-ssd' } | |
126 | } | |
127 | } | |
128 | }, | |
129 | { | |
f67539c2 | 130 | name: $localize`Available`, |
9f95a23c | 131 | prop: 'available', |
f6b5b4d7 TL |
132 | flexGrow: 1, |
133 | cellClass: 'text-center', | |
134 | cellTransformation: CellTemplate.checkIcon | |
9f95a23c TL |
135 | }, |
136 | { | |
f67539c2 | 137 | name: $localize`Vendor`, |
9f95a23c TL |
138 | prop: 'sys_api.vendor', |
139 | flexGrow: 1 | |
140 | }, | |
141 | { | |
f67539c2 | 142 | name: $localize`Model`, |
9f95a23c TL |
143 | prop: 'sys_api.model', |
144 | flexGrow: 1 | |
145 | }, | |
146 | { | |
f67539c2 | 147 | name: $localize`Size`, |
9f95a23c TL |
148 | prop: 'sys_api.size', |
149 | flexGrow: 1, | |
150 | pipe: this.dimlessBinary | |
151 | }, | |
152 | { | |
f67539c2 | 153 | name: $localize`OSDs`, |
9f95a23c TL |
154 | prop: 'osd_ids', |
155 | flexGrow: 1, | |
156 | cellTransformation: CellTemplate.badge, | |
157 | customTemplateConfig: { | |
158 | class: 'badge-dark', | |
159 | prefix: 'osd.' | |
160 | } | |
161 | } | |
162 | ]; | |
163 | ||
164 | this.columns = columns.filter((col: any) => { | |
165 | return !this.hiddenColumns.includes(col.prop); | |
166 | }); | |
167 | ||
168 | // init column filters | |
169 | _.forEach(this.filterColumns, (prop) => { | |
170 | const col = _.find(this.columns, { prop: prop }); | |
171 | if (col) { | |
172 | col.filterable = true; | |
173 | } | |
39ae355f TL |
174 | |
175 | if (col?.prop === 'human_readable_type' && this.diskType === 'ssd') { | |
176 | col.filterInitValue = this.diskType; | |
177 | } | |
178 | ||
179 | if (col?.prop === 'hostname' && this.hostname) { | |
180 | col.filterInitValue = this.hostname; | |
181 | } | |
9f95a23c TL |
182 | }); |
183 | ||
184 | if (this.fetchInventory.observers.length > 0) { | |
185 | this.fetchInventorySub = this.table.fetchData.subscribe(() => { | |
186 | this.fetchInventory.emit(); | |
187 | }); | |
188 | } | |
189 | } | |
190 | ||
a4b75251 TL |
191 | getDevices() { |
192 | if (this.showAvailDeviceOnly) { | |
193 | this.hostService.inventoryDeviceList().subscribe( | |
194 | (devices: InventoryDevice[]) => { | |
195 | this.devices = _.filter(devices, 'available'); | |
196 | this.devices = [...this.devices]; | |
197 | }, | |
198 | () => { | |
199 | this.devices = []; | |
200 | } | |
201 | ); | |
202 | } else { | |
203 | this.devices = [...this.devices]; | |
204 | } | |
205 | } | |
206 | ||
9f95a23c TL |
207 | ngOnDestroy() { |
208 | if (this.fetchInventorySub) { | |
209 | this.fetchInventorySub.unsubscribe(); | |
210 | } | |
211 | } | |
212 | ||
213 | onColumnFiltersChanged(event: CdTableColumnFiltersChange) { | |
214 | this.filterChange.emit(event); | |
215 | } | |
216 | ||
f67539c2 TL |
217 | getDisable(action: 'identify', selection: CdTableSelection): boolean | string { |
218 | if (!selection.hasSingleSelection) { | |
219 | return true; | |
220 | } | |
221 | return this.orchService.getTableActionDisableDesc( | |
222 | this.orchStatus, | |
223 | this.actionOrchFeatures[action] | |
224 | ); | |
225 | } | |
226 | ||
9f95a23c TL |
227 | updateSelection(selection: CdTableSelection) { |
228 | this.selection = selection; | |
229 | } | |
230 | ||
231 | identifyDevice() { | |
232 | const selected = this.selection.first(); | |
233 | const hostname = selected.hostname; | |
234 | const device = selected.path || selected.device_id; | |
235 | this.modalService.show(FormModalComponent, { | |
f67539c2 TL |
236 | titleText: $localize`Identify device ${device}`, |
237 | message: $localize`Please enter the duration how long to blink the LED.`, | |
238 | fields: [ | |
239 | { | |
240 | type: 'select', | |
241 | name: 'duration', | |
242 | value: 300, | |
243 | required: true, | |
244 | typeConfig: { | |
245 | options: [ | |
246 | { text: $localize`1 minute`, value: 60 }, | |
247 | { text: $localize`2 minutes`, value: 120 }, | |
248 | { text: $localize`5 minutes`, value: 300 }, | |
249 | { text: $localize`10 minutes`, value: 600 }, | |
250 | { text: $localize`15 minutes`, value: 900 } | |
251 | ] | |
9f95a23c | 252 | } |
9f95a23c | 253 | } |
f67539c2 TL |
254 | ], |
255 | submitButtonText: $localize`Execute`, | |
256 | onSubmit: (values: any) => { | |
257 | this.hostService.identifyDevice(hostname, device, values.duration).subscribe(() => { | |
258 | this.notificationService.show( | |
259 | NotificationType.success, | |
260 | $localize`Identifying '${device}' started on host '${hostname}'` | |
261 | ); | |
262 | }); | |
9f95a23c TL |
263 | } |
264 | }); | |
265 | } | |
266 | } |