1 import {Component, EventEmitter, OnInit, Input, Output, ViewChild, forwardRef} from '@angular/core';
2 import {ControlValueAccessor, FormGroup, FormControl, NG_VALUE_ACCESSOR} from '@angular/forms';
3 import {AuthService} from '@eg/core/auth.service';
4 import {IdlObject} from '@eg/core/idl.service';
5 import {OrgService} from '@eg/core/org.service';
7 export interface OrgFamily {
9 includeAncestors?: boolean;
10 includeDescendants?: boolean;
15 selector: 'eg-org-family-select',
16 templateUrl: 'org-family-select.component.html',
19 provide: NG_VALUE_ACCESSOR,
20 useExisting: forwardRef(() => OrgFamilySelectComponent),
25 export class OrgFamilySelectComponent implements ControlValueAccessor, OnInit {
27 // The label for this input
28 @Input() labelText = 'Library';
30 // Should the Ancestors checkbox be hidden?
31 @Input() hideAncestorSelector = false;
33 // Should the Descendants checkbox be hidden?
34 @Input() hideDescendantSelector = false;
36 // Should the Ancestors checkbox be checked by default?
38 // Ignored if [hideAncestorSelector]="true"
39 @Input() ancestorSelectorChecked = false;
41 // Should the Descendants checkbox be checked by default?
43 // Ignored if [hideDescendantSelector]="true"
44 @Input() descendantSelectorChecked = false;
47 @Input() selectedOrgId: number;
49 // Only show the OUs that the user has certain permissions at
50 @Input() limitPerms: string[];
52 @Input() domId: string;
54 // this is the most up-to-date value used for ngModel and reactive form
58 orgOnChange: ($event: IdlObject) => void;
59 emitArray: () => void;
61 familySelectors: FormGroup;
63 propagateChange = (_: OrgFamily) => {};
66 private auth: AuthService,
67 private org: OrgService
72 if (this.selectedOrgId) {
73 this.options = {primaryOrgId: this.selectedOrgId};
74 } else if (this.auth.user()) {
75 this.options = {primaryOrgId: this.auth.user().ws_ou()};
78 this.familySelectors = new FormGroup({
79 'includeAncestors': new FormControl({
80 value: this.ancestorSelectorChecked,
81 disabled: this.disableAncestorSelector()}),
82 'includeDescendants': new FormControl({
83 value: this.descendantSelectorChecked,
84 disabled: this.disableDescendantSelector()}),
88 this.domId = 'org-family-select-' + Math.floor(Math.random() * 100000);
91 this.familySelectors.valueChanges.subscribe(val => {
95 this.orgOnChange = ($event: IdlObject) => {
96 this.options.primaryOrgId = $event.id();
97 this.disableAncestorSelector() ? this.includeAncestors.disable() : this.includeAncestors.enable();
98 this.disableDescendantSelector() ? this.includeDescendants.disable() : this.includeDescendants.enable();
102 this.emitArray = () => {
103 // Prepare and emit an array containing the primary org id and
104 // optionally ancestor and descendant org units.
106 this.options.orgIds = [this.options.primaryOrgId];
108 if (this.includeAncestors.value) {
109 this.options.orgIds = this.org.ancestors(this.options.primaryOrgId, true);
112 if (this.includeDescendants.value) {
113 this.options.orgIds = this.options.orgIds.concat(
114 this.org.descendants(this.options.primaryOrgId, true));
117 // Using ancestors() and descendants() can result in
118 // duplicate org ID's. Be nice and uniqify.
119 const hash: any = {};
120 this.options.orgIds.forEach(id => hash[id] = true);
121 this.options.orgIds = Object.keys(hash).map(id => Number(id));
123 this.propagateChange(this.options);
127 writeValue(value: OrgFamily) {
129 this.selectedOrgId = value['primaryOrgId'];
130 this.familySelectors.patchValue({
131 'includeAncestors': value['includeAncestors'] ? value['includeAncestors'] : false,
132 'includeDescendants': value['includeDescendants'] ? value['includeDescendants'] : false,
137 registerOnChange(fn) {
138 this.propagateChange = fn;
141 registerOnTouched() {}
143 disableAncestorSelector(): boolean {
144 return this.options.primaryOrgId === this.org.root().id();
147 disableDescendantSelector(): boolean {
148 const contextOrg = this.org.get(this.options.primaryOrgId);
149 return contextOrg.children().length === 0;
152 get includeAncestors() {
153 return this.familySelectors.get('includeAncestors');
155 get includeDescendants() {
156 return this.familySelectors.get('includeDescendants');