]>
Commit | Line | Data |
---|---|---|
9f95a23c TL |
1 | import { Component, OnInit, ViewChild } from '@angular/core'; |
2 | import { FormControl, Validators } from '@angular/forms'; | |
3 | import { Router } from '@angular/router'; | |
4 | ||
5 | import { I18n } from '@ngx-translate/i18n-polyfill'; | |
6 | import * as _ from 'lodash'; | |
7 | import { BsModalService } from 'ngx-bootstrap/modal'; | |
8 | ||
9 | import { OrchestratorService } from '../../../../shared/api/orchestrator.service'; | |
10 | import { SubmitButtonComponent } from '../../../../shared/components/submit-button/submit-button.component'; | |
11 | import { ActionLabelsI18n } from '../../../../shared/constants/app.constants'; | |
12 | import { Icons } from '../../../../shared/enum/icons.enum'; | |
13 | import { CdFormGroup } from '../../../../shared/forms/cd-form-group'; | |
14 | import { CdTableColumn } from '../../../../shared/models/cd-table-column'; | |
15 | import { AuthStorageService } from '../../../../shared/services/auth-storage.service'; | |
16 | import { InventoryDevice } from '../../inventory/inventory-devices/inventory-device.model'; | |
17 | import { OsdCreationPreviewModalComponent } from '../osd-creation-preview-modal/osd-creation-preview-modal.component'; | |
18 | import { DevicesSelectionChangeEvent } from '../osd-devices-selection-groups/devices-selection-change-event.interface'; | |
19 | import { DevicesSelectionClearEvent } from '../osd-devices-selection-groups/devices-selection-clear-event.interface'; | |
20 | import { OsdDevicesSelectionGroupsComponent } from '../osd-devices-selection-groups/osd-devices-selection-groups.component'; | |
21 | import { DriveGroup } from './drive-group.model'; | |
22 | import { OsdFeature } from './osd-feature.interface'; | |
23 | ||
24 | @Component({ | |
25 | selector: 'cd-osd-form', | |
26 | templateUrl: './osd-form.component.html', | |
27 | styleUrls: ['./osd-form.component.scss'] | |
28 | }) | |
29 | export class OsdFormComponent implements OnInit { | |
30 | @ViewChild('dataDeviceSelectionGroups', { static: false }) | |
31 | dataDeviceSelectionGroups: OsdDevicesSelectionGroupsComponent; | |
32 | ||
33 | @ViewChild('walDeviceSelectionGroups', { static: false }) | |
34 | walDeviceSelectionGroups: OsdDevicesSelectionGroupsComponent; | |
35 | ||
36 | @ViewChild('dbDeviceSelectionGroups', { static: false }) | |
37 | dbDeviceSelectionGroups: OsdDevicesSelectionGroupsComponent; | |
38 | ||
39 | @ViewChild('previewButton', { static: false }) | |
40 | previewButton: SubmitButtonComponent; | |
41 | ||
42 | icons = Icons; | |
43 | ||
44 | form: CdFormGroup; | |
45 | columns: Array<CdTableColumn> = []; | |
46 | ||
47 | loading = false; | |
48 | allDevices: InventoryDevice[] = []; | |
49 | ||
50 | availDevices: InventoryDevice[] = []; | |
51 | dataDeviceFilters: any[] = []; | |
52 | dbDeviceFilters: any[] = []; | |
53 | walDeviceFilters: any[] = []; | |
54 | hostname = ''; | |
55 | driveGroup = new DriveGroup(); | |
56 | ||
57 | action: string; | |
58 | resource: string; | |
59 | ||
60 | features: { [key: string]: OsdFeature }; | |
61 | featureList: OsdFeature[] = []; | |
62 | ||
63 | hasOrchestrator = false; | |
9f95a23c TL |
64 | |
65 | constructor( | |
66 | public actionLabels: ActionLabelsI18n, | |
67 | private authStorageService: AuthStorageService, | |
68 | private i18n: I18n, | |
69 | private orchService: OrchestratorService, | |
70 | private router: Router, | |
71 | private bsModalService: BsModalService | |
72 | ) { | |
73 | this.resource = this.i18n('OSDs'); | |
74 | this.action = this.actionLabels.CREATE; | |
75 | this.features = { | |
76 | encrypted: { | |
77 | key: 'encrypted', | |
78 | desc: this.i18n('Encryption') | |
79 | } | |
80 | }; | |
81 | this.featureList = _.map(this.features, (o, key) => Object.assign(o, { key: key })); | |
82 | this.createForm(); | |
83 | } | |
84 | ||
85 | ngOnInit() { | |
86 | this.orchService.status().subscribe((status) => { | |
87 | this.hasOrchestrator = status.available; | |
88 | if (this.hasOrchestrator) { | |
89 | this.getDataDevices(); | |
90 | } | |
91 | }); | |
92 | ||
93 | this.form.get('walSlots').valueChanges.subscribe((value) => this.setSlots('wal', value)); | |
94 | this.form.get('dbSlots').valueChanges.subscribe((value) => this.setSlots('db', value)); | |
95 | _.each(this.features, (feature) => { | |
96 | this.form | |
97 | .get('features') | |
98 | .get(feature.key) | |
99 | .valueChanges.subscribe((value) => this.featureFormUpdate(feature.key, value)); | |
100 | }); | |
101 | } | |
102 | ||
103 | createForm() { | |
104 | this.form = new CdFormGroup({ | |
105 | walSlots: new FormControl(0, { | |
9f95a23c TL |
106 | validators: [Validators.min(0)] |
107 | }), | |
108 | dbSlots: new FormControl(0, { | |
9f95a23c TL |
109 | validators: [Validators.min(0)] |
110 | }), | |
111 | features: new CdFormGroup( | |
112 | this.featureList.reduce((acc: object, e) => { | |
113 | // disable initially because no data devices are selected | |
114 | acc[e.key] = new FormControl({ value: false, disabled: true }); | |
115 | return acc; | |
116 | }, {}) | |
117 | ) | |
118 | }); | |
119 | } | |
120 | ||
121 | getDataDevices() { | |
122 | if (this.loading) { | |
123 | return; | |
124 | } | |
125 | this.loading = true; | |
126 | this.orchService.inventoryDeviceList().subscribe( | |
127 | (devices: InventoryDevice[]) => { | |
128 | this.allDevices = _.filter(devices, 'available'); | |
129 | this.availDevices = [...this.allDevices]; | |
130 | this.loading = false; | |
131 | }, | |
132 | () => { | |
133 | this.allDevices = []; | |
134 | this.availDevices = []; | |
135 | this.loading = false; | |
136 | } | |
137 | ); | |
138 | } | |
139 | ||
140 | setSlots(type: string, slots: number) { | |
141 | if (typeof slots !== 'number') { | |
142 | return; | |
143 | } | |
144 | if (slots >= 0) { | |
145 | this.driveGroup.setSlots(type, slots); | |
146 | } | |
147 | } | |
148 | ||
149 | featureFormUpdate(key: string, checked: boolean) { | |
150 | this.driveGroup.setFeature(key, checked); | |
151 | } | |
152 | ||
153 | enableFeatures() { | |
154 | this.featureList.forEach((feature) => { | |
155 | this.form.get(feature.key).enable({ emitEvent: false }); | |
156 | }); | |
157 | } | |
158 | ||
159 | disableFeatures() { | |
160 | this.featureList.forEach((feature) => { | |
161 | const control = this.form.get(feature.key); | |
162 | control.disable({ emitEvent: false }); | |
163 | control.setValue(false, { emitEvent: false }); | |
164 | }); | |
165 | } | |
166 | ||
167 | onDevicesSelected(event: DevicesSelectionChangeEvent) { | |
168 | this.availDevices = event.dataOut; | |
169 | ||
170 | if (event.type === 'data') { | |
171 | // If user selects data devices for a single host, make only remaining devices on | |
172 | // that host as available. | |
173 | const hostnameFilter = _.find(event.filters, { prop: 'hostname' }); | |
174 | if (hostnameFilter) { | |
175 | this.hostname = hostnameFilter.value.raw; | |
176 | this.availDevices = event.dataOut.filter((device: InventoryDevice) => { | |
177 | return device.hostname === this.hostname; | |
178 | }); | |
179 | this.driveGroup.setHostPattern(this.hostname); | |
180 | } else { | |
181 | this.driveGroup.setHostPattern('*'); | |
182 | } | |
183 | this.enableFeatures(); | |
184 | } | |
185 | this.driveGroup.setDeviceSelection(event.type, event.filters); | |
186 | } | |
187 | ||
188 | onDevicesCleared(event: DevicesSelectionClearEvent) { | |
189 | if (event.type === 'data') { | |
190 | this.availDevices = [...this.allDevices]; | |
191 | this.walDeviceSelectionGroups.devices = []; | |
192 | this.dbDeviceSelectionGroups.devices = []; | |
193 | this.disableFeatures(); | |
194 | this.driveGroup.reset(); | |
195 | this.form.get('walSlots').setValue(0, { emitEvent: false }); | |
196 | this.form.get('dbSlots').setValue(0, { emitEvent: false }); | |
197 | } else { | |
198 | this.availDevices = [...this.availDevices, ...event.clearedDevices]; | |
199 | this.driveGroup.clearDeviceSelection(event.type); | |
200 | const slotControlName = `${event.type}Slots`; | |
201 | this.form.get(slotControlName).setValue(0, { emitEvent: false }); | |
202 | } | |
203 | } | |
204 | ||
205 | submit() { | |
206 | // use user name and timestamp for drive group name | |
207 | const user = this.authStorageService.getUsername(); | |
208 | this.driveGroup.setName(`dashboard-${user}-${_.now()}`); | |
209 | const modalRef = this.bsModalService.show(OsdCreationPreviewModalComponent, { | |
210 | initialState: { driveGroups: [this.driveGroup.spec] } | |
211 | }); | |
212 | modalRef.content.submitAction.subscribe(() => { | |
213 | this.router.navigate(['/osd']); | |
214 | }); | |
215 | this.previewButton.loading = false; | |
216 | } | |
217 | } |