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