]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select.component.ts
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / shared / components / select / select.component.ts
1 import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core';
2 import { FormControl, ValidatorFn } from '@angular/forms';
3
4 import { I18n } from '@ngx-translate/i18n-polyfill';
5 import * as _ from 'lodash';
6
7 import { CdFormGroup } from '../../forms/cd-form-group';
8 import { SelectMessages } from './select-messages.model';
9 import { SelectOption } from './select-option.model';
10
11 @Component({
12 selector: 'cd-select',
13 templateUrl: './select.component.html',
14 styleUrls: ['./select.component.scss']
15 })
16 export class SelectComponent implements OnInit, OnChanges {
17 @Input()
18 elemClass: string;
19 @Input()
20 data: Array<string> = [];
21 @Input()
22 options: Array<SelectOption> = [];
23 @Input()
24 messages = new SelectMessages({}, this.i18n);
25 @Input()
26 selectionLimit: number;
27 @Input()
28 customBadges = false;
29 @Input()
30 customBadgeValidators: ValidatorFn[] = [];
31
32 @Output()
33 selection = new EventEmitter();
34
35 form: CdFormGroup;
36 filter: FormControl;
37 Object = Object;
38 filteredOptions: Array<SelectOption> = [];
39
40 constructor(private i18n: I18n) {}
41
42 ngOnInit() {
43 this.initFilter();
44 if (this.data.length > 0) {
45 this.initMissingOptions();
46 }
47 this.options = _.sortBy(this.options, ['name']);
48 this.updateOptions();
49 }
50
51 private initFilter() {
52 this.filter = new FormControl('', { validators: this.customBadgeValidators });
53 this.form = new CdFormGroup({ filter: this.filter });
54 this.filteredOptions = [...(this.options || [])];
55 }
56
57 private initMissingOptions() {
58 const options = this.options.map((option) => option.name);
59 const needToCreate = this.data.filter((option) => options.indexOf(option) === -1);
60 needToCreate.forEach((option) => this.addOption(option));
61 this.forceOptionsToReflectData();
62 }
63
64 private addOption(name: string) {
65 this.options.push(new SelectOption(false, name, ''));
66 this.options = _.sortBy(this.options, ['name']);
67 this.triggerSelection(this.options.find((option) => option.name === name));
68 }
69
70 triggerSelection(option: SelectOption) {
71 if (
72 !option ||
73 (this.selectionLimit && !option.selected && this.data.length >= this.selectionLimit)
74 ) {
75 return;
76 }
77 option.selected = !option.selected;
78 this.updateOptions();
79 this.selection.emit({ option: option });
80 }
81
82 private updateOptions() {
83 this.data.splice(0, this.data.length);
84 this.options.forEach((option: SelectOption) => {
85 if (option.selected) {
86 this.data.push(option.name);
87 }
88 });
89 this.updateFilter();
90 }
91
92 updateFilter() {
93 this.filteredOptions = this.options.filter((option) => option.name.includes(this.filter.value));
94 }
95
96 private forceOptionsToReflectData() {
97 this.options.forEach((option) => {
98 if (this.data.indexOf(option.name) !== -1) {
99 option.selected = true;
100 }
101 });
102 }
103
104 ngOnChanges() {
105 if (this.filter) {
106 this.updateFilter();
107 }
108 if (!this.options || !this.data || this.data.length === 0) {
109 return;
110 }
111 this.forceOptionsToReflectData();
112 }
113
114 selectOption() {
115 if (this.filteredOptions.length === 0) {
116 this.addCustomOption();
117 } else {
118 this.triggerSelection(this.filteredOptions[0]);
119 this.resetFilter();
120 }
121 }
122
123 addCustomOption() {
124 if (!this.isCreatable()) {
125 return;
126 }
127 this.addOption(this.filter.value);
128 this.resetFilter();
129 }
130
131 isCreatable() {
132 return (
133 this.customBadges &&
134 this.filter.valid &&
135 this.filter.value.length > 0 &&
136 this.filteredOptions.every((option) => option.name !== this.filter.value)
137 );
138 }
139
140 private resetFilter() {
141 this.filter.setValue('');
142 this.updateFilter();
143 }
144
145 removeItem(item: string) {
146 this.triggerSelection(
147 this.options.find((option: SelectOption) => option.name === item && option.selected)
148 );
149 }
150 }