]>
Commit | Line | Data |
---|---|---|
1 | import { Component, OnInit, ViewChild } from '@angular/core'; | |
2 | import { FormControl, Validators } from '@angular/forms'; | |
3 | import { NgbActiveModal, NgbTypeahead } from '@ng-bootstrap/ng-bootstrap'; | |
4 | import { RgwRealmService } from '~/app/shared/api/rgw-realm.service'; | |
5 | import { ActionLabelsI18n } from '~/app/shared/constants/app.constants'; | |
6 | import { NotificationType } from '~/app/shared/enum/notification-type.enum'; | |
7 | import { CdFormGroup } from '~/app/shared/forms/cd-form-group'; | |
8 | import { CdValidators } from '~/app/shared/forms/cd-validators'; | |
9 | import { NotificationService } from '~/app/shared/services/notification.service'; | |
10 | import { RgwZone } from '../models/rgw-multisite'; | |
11 | import _ from 'lodash'; | |
12 | import { SelectMessages } from '~/app/shared/components/select/select-messages.model'; | |
13 | import { HostService } from '~/app/shared/api/host.service'; | |
14 | import { CdTableFetchDataContext } from '~/app/shared/models/cd-table-fetch-data-context'; | |
15 | import { SelectOption } from '~/app/shared/components/select/select-option.model'; | |
16 | import { Observable, Subject, merge } from 'rxjs'; | |
17 | import { debounceTime, distinctUntilChanged, filter, map } from 'rxjs/operators'; | |
18 | ||
19 | @Component({ | |
20 | selector: 'cd-rgw-multisite-import', | |
21 | templateUrl: './rgw-multisite-import.component.html', | |
22 | styleUrls: ['./rgw-multisite-import.component.scss'] | |
23 | }) | |
24 | export class RgwMultisiteImportComponent implements OnInit { | |
25 | readonly endpoints = /^((https?:\/\/)|(www.))(?:([a-zA-Z]+)|(\d+\.\d+.\d+.\d+)):\d{2,4}$/; | |
26 | readonly ipv4Rgx = /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/i; | |
27 | readonly ipv6Rgx = /^(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}$/i; | |
28 | @ViewChild(NgbTypeahead, { static: false }) | |
29 | typeahead: NgbTypeahead; | |
30 | ||
31 | importTokenForm: CdFormGroup; | |
32 | multisiteInfo: object[] = []; | |
33 | zoneList: RgwZone[] = []; | |
34 | zoneNames: string[]; | |
35 | hosts: any; | |
36 | labels: string[]; | |
37 | labelClick = new Subject<string>(); | |
38 | labelFocus = new Subject<string>(); | |
39 | ||
40 | constructor( | |
41 | public activeModal: NgbActiveModal, | |
42 | public hostService: HostService, | |
43 | ||
44 | public rgwRealmService: RgwRealmService, | |
45 | public actionLabels: ActionLabelsI18n, | |
46 | public notificationService: NotificationService | |
47 | ) { | |
48 | this.hosts = { | |
49 | options: [], | |
50 | messages: new SelectMessages({ | |
51 | empty: $localize`There are no hosts.`, | |
52 | filter: $localize`Filter hosts` | |
53 | }) | |
54 | }; | |
55 | this.createForm(); | |
56 | } | |
57 | ngOnInit(): void { | |
58 | this.zoneList = | |
59 | this.multisiteInfo[2] !== undefined && this.multisiteInfo[2].hasOwnProperty('zones') | |
60 | ? this.multisiteInfo[2]['zones'] | |
61 | : []; | |
62 | this.zoneNames = this.zoneList.map((zone) => { | |
63 | return zone['name']; | |
64 | }); | |
65 | const hostContext = new CdTableFetchDataContext(() => undefined); | |
66 | this.hostService.list(hostContext.toParams(), 'false').subscribe((resp: object[]) => { | |
67 | const options: SelectOption[] = []; | |
68 | _.forEach(resp, (host: object) => { | |
69 | if (_.get(host, 'sources.orchestrator', false)) { | |
70 | const option = new SelectOption(false, _.get(host, 'hostname'), ''); | |
71 | options.push(option); | |
72 | } | |
73 | }); | |
74 | this.hosts.options = [...options]; | |
75 | }); | |
76 | this.hostService.getLabels().subscribe((resp: string[]) => { | |
77 | this.labels = resp; | |
78 | }); | |
79 | } | |
80 | ||
81 | createForm() { | |
82 | this.importTokenForm = new CdFormGroup({ | |
83 | realmToken: new FormControl('', { | |
84 | validators: [Validators.required] | |
85 | }), | |
86 | zoneName: new FormControl(null, { | |
87 | validators: [ | |
88 | Validators.required, | |
89 | CdValidators.custom('uniqueName', (zoneName: string) => { | |
90 | return this.zoneNames && this.zoneNames.indexOf(zoneName) !== -1; | |
91 | }) | |
92 | ] | |
93 | }), | |
94 | rgw_frontend_port: new FormControl(null, { | |
95 | validators: [Validators.required, Validators.pattern('^[0-9]*$')] | |
96 | }), | |
97 | placement: new FormControl('hosts'), | |
98 | label: new FormControl(null, [ | |
99 | CdValidators.requiredIf({ | |
100 | placement: 'label', | |
101 | unmanaged: false | |
102 | }) | |
103 | ]), | |
104 | hosts: new FormControl([]), | |
105 | count: new FormControl(null, [CdValidators.number(false)]), | |
106 | unmanaged: new FormControl(false) | |
107 | }); | |
108 | } | |
109 | ||
110 | onSubmit() { | |
111 | const values = this.importTokenForm.value; | |
112 | const placementSpec: object = { | |
113 | placement: {} | |
114 | }; | |
115 | if (!values['unmanaged']) { | |
116 | switch (values['placement']) { | |
117 | case 'hosts': | |
118 | if (values['hosts'].length > 0) { | |
119 | placementSpec['placement']['hosts'] = values['hosts']; | |
120 | } | |
121 | break; | |
122 | case 'label': | |
123 | placementSpec['placement']['label'] = values['label']; | |
124 | break; | |
125 | } | |
126 | if (_.isNumber(values['count']) && values['count'] > 0) { | |
127 | placementSpec['placement']['count'] = values['count']; | |
128 | } | |
129 | } | |
130 | this.rgwRealmService | |
131 | .importRealmToken( | |
132 | values['realmToken'], | |
133 | values['zoneName'], | |
134 | values['rgw_frontend_port'], | |
135 | placementSpec | |
136 | ) | |
137 | .subscribe( | |
138 | () => { | |
139 | this.notificationService.show( | |
140 | NotificationType.success, | |
141 | $localize`Realm token import successfull` | |
142 | ); | |
143 | this.activeModal.close(); | |
144 | }, | |
145 | () => { | |
146 | this.importTokenForm.setErrors({ cdSubmitButton: true }); | |
147 | } | |
148 | ); | |
149 | } | |
150 | ||
151 | searchLabels = (text$: Observable<string>) => { | |
152 | return merge( | |
153 | text$.pipe(debounceTime(200), distinctUntilChanged()), | |
154 | this.labelFocus, | |
155 | this.labelClick.pipe(filter(() => !this.typeahead.isPopupOpen())) | |
156 | ).pipe( | |
157 | map((value) => | |
158 | this.labels | |
159 | .filter((label: string) => label.toLowerCase().indexOf(value.toLowerCase()) > -1) | |
160 | .slice(0, 10) | |
161 | ) | |
162 | ); | |
163 | }; | |
164 | } |