1 import {Component, OnInit, Input, ViewChild, ViewEncapsulation
2 } from '@angular/core';
3 import {Router} from '@angular/router';
4 import {Observable, Observer, of} from 'rxjs';
5 import {map} from 'rxjs/operators';
6 import {Pager} from '@eg/share/util/pager';
7 import {IdlObject, IdlService} from '@eg/core/idl.service';
8 import {OrgService} from '@eg/core/org.service';
9 import {PcrudService} from '@eg/core/pcrud.service';
10 import {AuthService} from '@eg/core/auth.service';
11 import {NetService} from '@eg/core/net.service';
12 import {GridDataSource} from '@eg/share/grid/grid';
13 import {GridComponent} from '@eg/share/grid/grid.component';
14 import {GridToolbarCheckboxComponent
15 } from '@eg/share/grid/grid-toolbar-checkbox.component';
16 import {StoreService} from '@eg/core/store.service';
17 import {ServerStoreService} from '@eg/core/server-store.service';
18 import {ToastService} from '@eg/share/toast/toast.service';
20 import {EditOuSettingDialogComponent
21 } from '@eg/staff/admin/local/org-unit-settings/edit-org-unit-setting-dialog.component';
22 import {OuSettingHistoryDialogComponent
23 } from '@eg/staff/admin/local/org-unit-settings/org-unit-setting-history-dialog.component';
24 import {OuSettingJsonDialogComponent
25 } from '@eg/staff/admin/local/org-unit-settings/org-unit-setting-json-dialog.component';
27 export class OrgUnitSetting {
36 _idlOptions: IdlObject[];
44 templateUrl: './org-unit-settings.component.html'
47 export class OrgUnitSettingsComponent {
49 contextOrg: IdlObject;
52 gridDataSource: GridDataSource;
53 gridTemplateContext: any;
55 currentHistory: any[];
56 currentOptions: any[];
58 @ViewChild('orgUnitSettingsGrid', { static:true }) orgUnitSettingsGrid: GridComponent;
60 @ViewChild('editOuSettingDialog', { static:true })
61 private editOuSettingDialog: EditOuSettingDialogComponent;
62 @ViewChild('orgUnitSettingHistoryDialog', { static:true })
63 private orgUnitSettingHistoryDialog: OuSettingHistoryDialogComponent;
64 @ViewChild('ouSettingJsonDialog', { static:true })
65 private ouSettingJsonDialog: OuSettingJsonDialogComponent;
67 refreshSettings: boolean;
68 renderFromPrefs: boolean;
70 settingTypeArr: any[];
72 @Input() filterString: string;
75 private router: Router,
76 private org: OrgService,
77 private idl: IdlService,
78 private pcrud: PcrudService,
79 private auth: AuthService,
80 private store: ServerStoreService,
81 private localStore: StoreService,
82 private toast: ToastService,
83 private net: NetService,
85 this.gridDataSource = new GridDataSource();
86 this.refreshSettings = true;
87 this.renderFromPrefs = true;
89 this.contextOrg = this.org.get(this.auth.user().ws_ou());
94 this.settingTypeArr = [];
95 this.gridDataSource.getRows = (pager: Pager, sort: any[]) => {
96 return this.fetchSettingTypes(pager);
98 this.orgUnitSettingsGrid.onRowActivate.subscribe((setting:OrgUnitSetting) => {
99 this.showEditSettingValueDialog(setting);
103 fetchSettingTypes(pager: Pager): Observable<any> {
104 return new Observable<any>(observer => {
105 this.pcrud.retrieveAll('coust', {flesh: 3, flesh_fields: {
106 'coust': ['grp', 'view_perm']
108 { authoritative: true }).subscribe(
109 settingTypes => this.allocateSettingTypes(settingTypes),
112 this.refreshSettings = false;
113 this.mergeSettingValues().then(
115 this.flattenSettings(observer);
123 mergeSettingValues(): Promise<any> {
124 const settingNames = this.settingTypeArr.map(setting => setting.name);
125 return new Promise((resolve, reject) => {
128 'open-ils.actor.ou_setting.ancestor_default.batch',
129 this.contextOrg.id(), settingNames, this.auth.token()
132 let settingVals = Object.keys(blob).map(key => {
133 return {'name': key, 'setting': blob[key]}
135 settingVals.forEach(key => {
137 let settingsObj = this.settingTypeArr.filter(
138 setting => setting.name == key.name
140 settingsObj.value = key.setting.value;
141 settingsObj.value_str = settingsObj.value;
142 if (settingsObj.dataType == 'link' && (key.setting.value || key.setting.value == 0)) {
143 this.fetchLinkedField(settingsObj.fmClass, key.setting.value, settingsObj.value_str).then(res => {
144 settingsObj.value_str = res;
147 settingsObj._org_unit = this.org.get(key.setting.org);
148 settingsObj.context = settingsObj._org_unit.shortname();
151 resolve(this.settingTypeArr);
158 fetchLinkedField(fmClass, id, val) {
159 return new Promise((resolve, reject) => {
160 return this.pcrud.retrieve(fmClass, id).subscribe(linkedField => {
161 val = linkedField.name();
167 fetchHistory(setting): Promise<any> {
168 let name = setting.name;
169 return new Promise((resolve, reject) => {
172 'open-ils.actor.org_unit.settings.history.retrieve',
173 this.auth.token(), name, this.contextOrg.id()
175 this.currentHistory = [];
176 if (!Array.isArray(res)) {
180 log.org = this.org.get(log.org);
181 log.new_value_str = log.new_value;
182 log.original_value_str = log.original_value;
183 if (setting.dataType == "link") {
185 this.fetchLinkedField(setting.fmClass, parseInt(log.new_value), log.new_value_str).then(val => {
186 log.new_value_str = val;
189 if (log.original_value) {
190 this.fetchLinkedField(setting.fmClass, parseInt(log.original_value), log.original_value_str).then(val => {
191 log.original_value_str = val;
195 if (log.new_value_str) log.new_value_str = log.new_value_str.replace(/^"(.*)"$/, '$1');
196 if (log.original_value_str) log.original_value_str = log.original_value_str.replace(/^"(.*)"$/, '$1');
198 this.currentHistory = res;
199 this.currentHistory.sort((a, b) => {
200 return a.date_applied < b.date_applied ? 1 : -1;
203 resolve(this.currentHistory);
204 }, err=>{reject(err);});
208 allocateSettingTypes(coust: IdlObject) {
209 let entry = new OrgUnitSetting();
210 entry.name = coust.name();
211 entry.label = coust.label();
212 entry.dataType = coust.datatype();
213 if (coust.fm_class()) entry.fmClass = coust.fm_class();
214 if (coust.description()) entry.description = coust.description();
215 // For some reason some setting types don't have a grp, should look into this...
216 if (coust.grp()) entry.grp = coust.grp().label();
217 if (coust.view_perm())
218 entry.view_perm = coust.view_perm().code();
220 this.settingTypeArr.push(entry);
223 flattenSettings(observer: Observer<any>) {
224 this.gridDataSource.data = this.settingTypeArr;
228 contextOrgChanged(org: IdlObject) {
229 this.updateGrid(org);
232 applyFilter(clear?: boolean) {
233 if (clear) this.filterString = '';
234 this.updateGrid(this.contextOrg);
237 updateSetting(obj, entry) {
240 'open-ils.actor.org_unit.settings.update',
241 this.auth.token(), obj.context.id(), obj.setting
242 ).toPromise().then(res=> {
243 this.toast.success(entry.label + " Updated.");
244 if (!obj.setting[entry.name]) {
245 let settingsObj = this.settingTypeArr.filter(
246 setting => setting.name == entry.name
248 settingsObj.value = null;
249 settingsObj.value_str = null;
250 settingsObj._org_unit = null;
251 settingsObj.context = null;
253 this.mergeSettingValues();
256 this.toast.danger(entry.label + " failed to update: " + err.desc);
260 showEditSettingValueDialog(entry: OrgUnitSetting) {
261 this.editOuSettingDialog.entry = entry;
262 this.editOuSettingDialog.entryValue = entry.value;
263 this.editOuSettingDialog.entryContext = entry._org_unit || this.contextOrg;
264 this.editOuSettingDialog.open({size: 'lg'}).subscribe(
266 this.updateSetting(res, entry);
271 showHistoryDialog(entry: OrgUnitSetting) {
273 this.fetchHistory(entry).then(
275 this.orgUnitSettingHistoryDialog.history = this.currentHistory;
276 this.orgUnitSettingHistoryDialog.gridDataSource.data = this.currentHistory;
277 this.orgUnitSettingHistoryDialog.entry = entry;
278 this.orgUnitSettingHistoryDialog.open({size: 'lg'}).subscribe(res => {
280 this.updateSetting(res, entry);
288 showJsonDialog(isExport: boolean) {
289 this.ouSettingJsonDialog.isExport = isExport;
290 this.ouSettingJsonDialog.jsonData = "";
292 this.ouSettingJsonDialog.jsonData = "{";
293 this.gridDataSource.data.forEach(entry => {
294 this.ouSettingJsonDialog.jsonData +=
295 "\"" + entry.name + "\": {\"org\": \"" +
296 this.contextOrg.id() + "\", \"value\": ";
298 this.ouSettingJsonDialog.jsonData += "\"" + entry.value + "\"";
300 this.ouSettingJsonDialog.jsonData += "null";
302 this.ouSettingJsonDialog.jsonData += "}";
303 if (this.gridDataSource.data.indexOf(entry) != (this.gridDataSource.data.length - 1))
304 this.ouSettingJsonDialog.jsonData += ",";
306 this.ouSettingJsonDialog.jsonData += "}";
309 this.ouSettingJsonDialog.open({size: 'lg'}).subscribe(res => {
310 if (res.apply && res.jsonData) {
311 let jsonSettings = JSON.parse(res.jsonData);
312 Object.entries(jsonSettings).forEach((fields) => {
313 let entry = this.settingTypeArr.find(x => x.name == fields[0]);
314 let obj = {setting: {}, context: {}};
315 let val = this.parseValType(fields[1]['value'], entry.dataType);
316 obj.setting[fields[0]] = val;
317 obj.context = this.org.get(fields[1]['org']);
318 this.updateSetting(obj, entry);
324 parseValType(value, dataType) {
325 if (dataType == "integer" || "currency" || "link") {
326 return Number(value);
327 } else if (dataType == "bool") {
328 return (value === 'true');
335 if (this.filterString != this.prevFilter) {
336 this.prevFilter = this.filterString;
337 if (this.filterString) {
338 this.gridDataSource.data = [];
339 let tempGrid = this.settingTypeArr;
340 tempGrid.forEach(row => {
342 row.name.includes(this.filterString) ||
343 row.label.includes(this.filterString) ||
344 (row.grp && row.grp.includes(this.filterString)) ||
345 (row.description && row.description.includes(this.filterString));
346 if (containsString) {
347 this.gridDataSource.data.push(row);
351 this.gridDataSource.data = this.settingTypeArr;
357 if (this.contextOrg != org) {
358 this.contextOrg = org;
359 this.refreshSettings = true;
362 if (this.filterString != this.prevFilter) {
363 this.refreshSettings = true;
366 if (this.refreshSettings) {
367 this.mergeSettingValues().then(
368 res => this.filterCoust()