diff options
Diffstat (limited to 'client/src/app/shared/shared-forms/select/select-checkbox-all.component.ts')
-rw-r--r-- | client/src/app/shared/shared-forms/select/select-checkbox-all.component.ts | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/client/src/app/shared/shared-forms/select/select-checkbox-all.component.ts b/client/src/app/shared/shared-forms/select/select-checkbox-all.component.ts new file mode 100644 index 000000000..ebf7b77a6 --- /dev/null +++ b/client/src/app/shared/shared-forms/select/select-checkbox-all.component.ts | |||
@@ -0,0 +1,115 @@ | |||
1 | import { Component, forwardRef, Input } from '@angular/core' | ||
2 | import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' | ||
3 | import { Notifier } from '@app/core' | ||
4 | import { SelectOptionsItem } from '../../../../types/select-options-item.model' | ||
5 | import { ItemSelectCheckboxValue } from './select-checkbox.component' | ||
6 | |||
7 | @Component({ | ||
8 | selector: 'my-select-checkbox-all', | ||
9 | styleUrls: [ './select-shared.component.scss' ], | ||
10 | |||
11 | template: ` | ||
12 | <my-select-checkbox | ||
13 | [(ngModel)]="selectedItems" | ||
14 | (ngModelChange)="onModelChange()" | ||
15 | [availableItems]="availableItems" | ||
16 | [selectableGroup]="true" [selectableGroupAsModel]="true" | ||
17 | [placeholder]="placeholder" | ||
18 | (focusout)="onBlur()" | ||
19 | > | ||
20 | </my-select-checkbox>`, | ||
21 | |||
22 | providers: [ | ||
23 | { | ||
24 | provide: NG_VALUE_ACCESSOR, | ||
25 | useExisting: forwardRef(() => SelectCheckboxAllComponent), | ||
26 | multi: true | ||
27 | } | ||
28 | ] | ||
29 | }) | ||
30 | export class SelectCheckboxAllComponent implements ControlValueAccessor { | ||
31 | @Input() availableItems: SelectOptionsItem[] = [] | ||
32 | @Input() allGroupLabel: string | ||
33 | |||
34 | @Input() placeholder: string | ||
35 | @Input() maxItems: number | ||
36 | |||
37 | selectedItems: ItemSelectCheckboxValue[] | ||
38 | |||
39 | constructor ( | ||
40 | private notifier: Notifier | ||
41 | ) { | ||
42 | |||
43 | } | ||
44 | |||
45 | propagateChange = (_: any) => { /* empty */ } | ||
46 | |||
47 | writeValue (items: string[]) { | ||
48 | this.selectedItems = items | ||
49 | ? items.map(l => ({ id: l })) | ||
50 | : [ { group: this.allGroupLabel } ] | ||
51 | } | ||
52 | |||
53 | registerOnChange (fn: (_: any) => void) { | ||
54 | this.propagateChange = fn | ||
55 | } | ||
56 | |||
57 | registerOnTouched () { | ||
58 | // Unused | ||
59 | } | ||
60 | |||
61 | onModelChange () { | ||
62 | if (!this.isMaxConstraintValid()) return | ||
63 | |||
64 | this.propagateChange(this.buildOutputItems()) | ||
65 | } | ||
66 | |||
67 | onBlur () { | ||
68 | // Automatically use "All languages" if the user did not select any language | ||
69 | if (Array.isArray(this.selectedItems) && this.selectedItems.length === 0) { | ||
70 | this.selectedItems = [ { group: this.allGroupLabel } ] | ||
71 | } | ||
72 | } | ||
73 | |||
74 | private isMaxConstraintValid () { | ||
75 | if (!this.maxItems) return true | ||
76 | |||
77 | const outputItems = this.buildOutputItems() | ||
78 | if (!outputItems) return true | ||
79 | |||
80 | if (outputItems.length >= this.maxItems) { | ||
81 | this.notifier.error($localize`You can't select more than ${this.maxItems} items`) | ||
82 | |||
83 | return false | ||
84 | } | ||
85 | |||
86 | return true | ||
87 | } | ||
88 | |||
89 | private buildOutputItems () { | ||
90 | if (!Array.isArray(this.selectedItems)) return undefined | ||
91 | |||
92 | // null means "All" | ||
93 | if (this.selectedItems.length === 0 || this.selectedItems.length === this.availableItems.length) { | ||
94 | return null | ||
95 | } | ||
96 | |||
97 | if (this.selectedItems.length === 1) { | ||
98 | const item = this.selectedItems[0] | ||
99 | |||
100 | const itemGroup = typeof item === 'string' || typeof item === 'number' | ||
101 | ? item | ||
102 | : item.group | ||
103 | |||
104 | if (itemGroup === this.allGroupLabel) return null | ||
105 | } | ||
106 | |||
107 | return this.selectedItems.map(l => { | ||
108 | if (typeof l === 'string' || typeof l === 'number') return l | ||
109 | |||
110 | if (l.group) return l.group | ||
111 | |||
112 | return l.id + '' | ||
113 | }) | ||
114 | } | ||
115 | } | ||