]>
Commit | Line | Data |
---|---|---|
a4b75251 | 1 | import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; |
20effc67 | 2 | import { FormControl } from '@angular/forms'; |
9f95a23c TL |
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({ | |
20effc67 TL |
118 | walSlots: new FormControl(0), |
119 | dbSlots: new FormControl(0), | |
9f95a23c TL |
120 | features: new CdFormGroup( |
121 | this.featureList.reduce((acc: object, e) => { | |
122 | // disable initially because no data devices are selected | |
123 | acc[e.key] = new FormControl({ value: false, disabled: true }); | |
124 | return acc; | |
125 | }, {}) | |
126 | ) | |
127 | }); | |
128 | } | |
129 | ||
130 | getDataDevices() { | |
f67539c2 | 131 | this.hostService.inventoryDeviceList().subscribe( |
9f95a23c TL |
132 | (devices: InventoryDevice[]) => { |
133 | this.allDevices = _.filter(devices, 'available'); | |
134 | this.availDevices = [...this.allDevices]; | |
f67539c2 | 135 | this.loadingReady(); |
9f95a23c TL |
136 | }, |
137 | () => { | |
138 | this.allDevices = []; | |
139 | this.availDevices = []; | |
f67539c2 | 140 | this.loadingError(); |
9f95a23c TL |
141 | } |
142 | ); | |
143 | } | |
144 | ||
145 | setSlots(type: string, slots: number) { | |
146 | if (typeof slots !== 'number') { | |
147 | return; | |
148 | } | |
149 | if (slots >= 0) { | |
150 | this.driveGroup.setSlots(type, slots); | |
151 | } | |
152 | } | |
153 | ||
154 | featureFormUpdate(key: string, checked: boolean) { | |
155 | this.driveGroup.setFeature(key, checked); | |
156 | } | |
157 | ||
158 | enableFeatures() { | |
159 | this.featureList.forEach((feature) => { | |
160 | this.form.get(feature.key).enable({ emitEvent: false }); | |
161 | }); | |
162 | } | |
163 | ||
164 | disableFeatures() { | |
165 | this.featureList.forEach((feature) => { | |
166 | const control = this.form.get(feature.key); | |
167 | control.disable({ emitEvent: false }); | |
168 | control.setValue(false, { emitEvent: false }); | |
169 | }); | |
170 | } | |
171 | ||
172 | onDevicesSelected(event: DevicesSelectionChangeEvent) { | |
173 | this.availDevices = event.dataOut; | |
174 | ||
175 | if (event.type === 'data') { | |
176 | // If user selects data devices for a single host, make only remaining devices on | |
177 | // that host as available. | |
178 | const hostnameFilter = _.find(event.filters, { prop: 'hostname' }); | |
179 | if (hostnameFilter) { | |
180 | this.hostname = hostnameFilter.value.raw; | |
181 | this.availDevices = event.dataOut.filter((device: InventoryDevice) => { | |
182 | return device.hostname === this.hostname; | |
183 | }); | |
184 | this.driveGroup.setHostPattern(this.hostname); | |
185 | } else { | |
186 | this.driveGroup.setHostPattern('*'); | |
187 | } | |
188 | this.enableFeatures(); | |
189 | } | |
190 | this.driveGroup.setDeviceSelection(event.type, event.filters); | |
a4b75251 TL |
191 | |
192 | this.emitDriveGroup.emit(this.driveGroup); | |
9f95a23c TL |
193 | } |
194 | ||
195 | onDevicesCleared(event: DevicesSelectionClearEvent) { | |
196 | if (event.type === 'data') { | |
197 | this.availDevices = [...this.allDevices]; | |
198 | this.walDeviceSelectionGroups.devices = []; | |
199 | this.dbDeviceSelectionGroups.devices = []; | |
200 | this.disableFeatures(); | |
201 | this.driveGroup.reset(); | |
202 | this.form.get('walSlots').setValue(0, { emitEvent: false }); | |
203 | this.form.get('dbSlots').setValue(0, { emitEvent: false }); | |
204 | } else { | |
205 | this.availDevices = [...this.availDevices, ...event.clearedDevices]; | |
206 | this.driveGroup.clearDeviceSelection(event.type); | |
207 | const slotControlName = `${event.type}Slots`; | |
208 | this.form.get(slotControlName).setValue(0, { emitEvent: false }); | |
209 | } | |
210 | } | |
211 | ||
212 | submit() { | |
213 | // use user name and timestamp for drive group name | |
214 | const user = this.authStorageService.getUsername(); | |
215 | this.driveGroup.setName(`dashboard-${user}-${_.now()}`); | |
f67539c2 TL |
216 | const modalRef = this.modalService.show(OsdCreationPreviewModalComponent, { |
217 | driveGroups: [this.driveGroup.spec] | |
9f95a23c | 218 | }); |
f67539c2 | 219 | modalRef.componentInstance.submitAction.subscribe(() => { |
9f95a23c TL |
220 | this.router.navigate(['/osd']); |
221 | }); | |
f67539c2 | 222 | this.previewButtonPanel.submitButton.loading = false; |
9f95a23c TL |
223 | } |
224 | } |