]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/eg2/src/app/share/org-family-select/org-family-select.component.ts
LP1850473: manual and automated eslint fixes
[Evergreen.git] / Open-ILS / src / eg2 / src / app / share / org-family-select / org-family-select.component.ts
1 /* eslint-disable no-unused-expressions */
2 import {Component, EventEmitter, OnInit, Input, Output, ViewChildren, QueryList, forwardRef} from '@angular/core';
3 import {ControlValueAccessor, FormGroup, FormControl, NG_VALUE_ACCESSOR} from '@angular/forms';
4 import {AuthService} from '@eg/core/auth.service';
5 import {IdlObject} from '@eg/core/idl.service';
6 import {OrgService} from '@eg/core/org.service';
7 import {OrgSelectComponent} from '@eg/share/org-select/org-select.component';
8 import {ServerStoreService} from '@eg/core/server-store.service';
9
10 export interface OrgFamily {
11   primaryOrgId: number;
12   includeAncestors?: boolean;
13   includeDescendants?: boolean;
14   orgIds?: number[];
15 }
16
17 @Component({
18     selector: 'eg-org-family-select',
19     templateUrl: 'org-family-select.component.html',
20     providers: [
21         {
22             provide: NG_VALUE_ACCESSOR,
23             useExisting: forwardRef(() => OrgFamilySelectComponent),
24             multi: true
25         }
26     ]
27 })
28 export class OrgFamilySelectComponent implements ControlValueAccessor, OnInit {
29
30     // ARIA label for selector. Required if there is no <label> in the markup.
31     @Input() ariaLabel?: string;
32
33     // Should the Ancestors checkbox be hidden?
34     @Input() hideAncestorSelector = false;
35
36     // Should the Descendants checkbox be hidden?
37     @Input() hideDescendantSelector = false;
38
39     // Should the Ancestors checkbox be checked by default?
40     //
41     // Ignored if [hideAncestorSelector]="true"
42     @Input() ancestorSelectorChecked = false;
43
44     // Should the Descendants checkbox be checked by default?
45     //
46     // Ignored if [hideDescendantSelector]="true"
47     @Input() descendantSelectorChecked = false;
48
49     // Default org unit
50     @Input() selectedOrgId: number;
51
52     // Only show the OUs that the user has certain permissions at
53     @Input() limitPerms: string[];
54
55     @Input() domId: string;
56
57     @Input() persistKey: string;
58
59     @Output() onChange = new EventEmitter<any>();
60
61     @ViewChildren(OrgSelectComponent)  orgSelects: QueryList<OrgSelectComponent>;
62
63     // this is the most up-to-date value used for ngModel and reactive form
64     // subscriptions
65     options: OrgFamily;
66
67     orgOnChange: ($event: IdlObject) => void;
68     emitArray: () => void;
69
70     familySelectors: FormGroup;
71
72     propagateChange = (_: OrgFamily) => {};
73     propagateTouch = () => {};
74
75     constructor(
76         private auth: AuthService,
77         private org: OrgService,
78         private serverStore: ServerStoreService
79     ) {
80     }
81
82     ngOnInit() {
83         if (this.selectedOrgId) {
84             this.options = {primaryOrgId: this.selectedOrgId};
85         } else if (this.auth.user()) {
86             this.options = {primaryOrgId: this.auth.user().ws_ou()};
87         }
88
89         this.familySelectors = new FormGroup({
90             'includeAncestors': new FormControl({
91                 value: this.ancestorSelectorChecked,
92                 disabled: this.disableAncestorSelector()}),
93             'includeDescendants': new FormControl({
94                 value: this.descendantSelectorChecked,
95                 disabled: this.disableDescendantSelector()}),
96         });
97
98         if (!this.domId) {
99             // eslint-disable-next-line no-magic-numbers
100             this.domId = 'org-family-select-' + Math.floor(Math.random() * 100000);
101         }
102
103         this.familySelectors.valueChanges.subscribe(val => {
104             this.emitArray();
105         });
106
107         this.orgOnChange = ($event: IdlObject) => {
108             this.options.primaryOrgId = $event.id();
109             this.disableAncestorSelector() ? this.includeAncestors.disable() : this.includeAncestors.enable();
110             this.disableDescendantSelector() ? this.includeDescendants.disable() : this.includeDescendants.enable();
111             this.emitArray();
112         };
113
114         this.emitArray = () => {
115             // Prepare and emit an array containing the primary org id and
116             // optionally ancestor and descendant org units, and flags that select those.
117
118             this.options.orgIds = [this.options.primaryOrgId];
119             this.options.includeAncestors = this.includeAncestors.value;
120             this.options.includeDescendants = this.includeDescendants.value;
121
122             if (this.includeAncestors.value) {
123                 this.options.orgIds = this.org.ancestors(this.options.primaryOrgId, true);
124             }
125
126             if (this.includeDescendants.value) {
127                 this.options.orgIds = this.options.orgIds.concat(
128                     this.org.descendants(this.options.primaryOrgId, true));
129             }
130
131             // Using ancestors() and descendants() can result in
132             // duplicate org ID's.  Be nice and uniqify.
133             const hash: any = {};
134             this.options.orgIds.forEach(id => hash[id] = true);
135             this.options.orgIds = Object.keys(hash).map(id => Number(id));
136
137             this.propagateChange(this.options);
138             this.onChange.emit(this.options);
139
140             if (this.persistKey) {
141                 const key = `eg.orgfamilyselect.${this.persistKey}`;
142                 this.serverStore.setItem(key, this.options);
143             }
144         };
145
146         this.loadPersistedValues();
147     }
148
149     private loadPersistedValues() {
150         if (!this.persistKey) {return;}
151
152         const key = `eg.orgfamilyselect.${this.persistKey}`;
153
154         this.serverStore.getItem(key).then(persistedOptions => {
155             if (persistedOptions) {
156                 this.writeValue(persistedOptions);
157             }
158         });
159     }
160
161     writeValue(value: OrgFamily) {
162         if (value) {
163             this.selectedOrgId = value['primaryOrgId'];
164             if (this.orgSelects) {
165                 this.orgSelects.toArray()[0].applyOrgId = this.selectedOrgId;
166                 this.options = {primaryOrgId: this.selectedOrgId};
167             }
168             this.familySelectors.patchValue({
169                 'includeAncestors': value['includeAncestors'] ? value['includeAncestors'] : false,
170                 'includeDescendants': value['includeDescendants'] ? value['includeDescendants'] : false,
171             });
172         }
173     }
174
175     registerOnChange(fn) {
176         this.propagateChange = fn;
177     }
178
179     registerOnTouched(fn) {
180         this.propagateTouch = fn;
181     }
182
183     disableAncestorSelector(): boolean {
184         return this.options.primaryOrgId === this.org.root().id();
185     }
186
187     disableDescendantSelector(): boolean {
188         const contextOrg = this.org.get(this.options.primaryOrgId);
189         return contextOrg.children().length === 0;
190     }
191
192     get includeAncestors() {
193         return this.familySelectors.get('includeAncestors');
194     }
195     get includeDescendants() {
196         return this.familySelectors.get('includeDescendants');
197     }
198
199 }
200