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);
100 fetchSettingTypes(pager: Pager): Observable<any> {
101 return new Observable<any>(observer => {
102 this.pcrud.retrieveAll('coust', {flesh: 3, flesh_fields: {
103 'coust': ['grp', 'view_perm']
105 { authoritative: true }).subscribe(
106 settingTypes => this.allocateSettingTypes(settingTypes),
109 this.refreshSettings = false;
110 this.mergeSettingValues().then(
112 this.flattenSettings(observer);
120 mergeSettingValues(): Promise<any> {
121 const settingNames = this.settingTypeArr.map(setting => setting.name);
122 return new Promise((resolve, reject) => {
125 'open-ils.actor.ou_setting.ancestor_default.batch',
126 this.contextOrg.id(), settingNames, this.auth.token()
129 let settingVals = Object.keys(blob).map(key => {
130 return {'name': key, 'setting': blob[key]}
132 settingVals.forEach(key => {
134 let settingsObj = this.settingTypeArr.filter(
135 setting => setting.name == key.name
137 settingsObj.value = key.setting.value;
138 settingsObj.value_str = settingsObj.value;
139 if (settingsObj.dataType == 'link' && (key.setting.value || key.setting.value == 0)) {
140 this.fetchLinkedField(settingsObj.fmClass, key.setting.value, settingsObj.value_str).then(res => {
141 settingsObj.value_str = res;
144 settingsObj._org_unit = this.org.get(key.setting.org);
145 settingsObj.context = settingsObj._org_unit.shortname();
148 resolve(this.settingTypeArr);
155 fetchLinkedField(fmClass, id, val) {
156 return new Promise((resolve, reject) => {
157 return this.pcrud.retrieve(fmClass, id).subscribe(linkedField => {
158 val = linkedField.name();
164 fetchHistory(setting): Promise<any> {
165 let name = setting.name;
166 return new Promise((resolve, reject) => {
169 'open-ils.actor.org_unit.settings.history.retrieve',
170 this.auth.token(), name, this.contextOrg.id()
172 this.currentHistory = [];
173 if (!Array.isArray(res)) {
177 log.org = this.org.get(log.org);
178 log.new_value_str = log.new_value;
179 log.original_value_str = log.original_value;
180 if (setting.dataType == "link") {
182 this.fetchLinkedField(setting.fmClass, parseInt(log.new_value), log.new_value_str).then(val => {
183 log.new_value_str = val;
186 if (log.original_value) {
187 this.fetchLinkedField(setting.fmClass, parseInt(log.original_value), log.original_value_str).then(val => {
188 log.original_value_str = val;
192 if (log.new_value_str) log.new_value_str = log.new_value_str.replace(/^"(.*)"$/, '$1');
193 if (log.original_value_str) log.original_value_str = log.original_value_str.replace(/^"(.*)"$/, '$1');
195 this.currentHistory = res;
196 this.currentHistory.sort((a, b) => {
197 return a.date_applied < b.date_applied ? 1 : -1;
200 resolve(this.currentHistory);
201 }, err=>{reject(err);});
205 allocateSettingTypes(coust: IdlObject) {
206 let entry = new OrgUnitSetting();
207 entry.name = coust.name();
208 entry.label = coust.label();
209 entry.dataType = coust.datatype();
210 if (coust.fm_class()) entry.fmClass = coust.fm_class();
211 if (coust.description()) entry.description = coust.description();
212 // For some reason some setting types don't have a grp, should look into this...
213 if (coust.grp()) entry.grp = coust.grp().label();
214 if (coust.view_perm())
215 entry.view_perm = coust.view_perm().code();
217 this.settingTypeArr.push(entry);
220 flattenSettings(observer: Observer<any>) {
221 this.gridDataSource.data = this.settingTypeArr;
225 contextOrgChanged(org: IdlObject) {
226 this.updateGrid(org);
229 applyFilter(clear?: boolean) {
230 if (clear) this.filterString = '';
231 this.updateGrid(this.contextOrg);
234 updateSetting(obj, entry) {
237 'open-ils.actor.org_unit.settings.update',
238 this.auth.token(), obj.context.id(), obj.setting
239 ).toPromise().then(res=> {
240 this.toast.success(entry.label + " Updated.");
241 if (!obj.setting[entry.name]) {
242 let settingsObj = this.settingTypeArr.filter(
243 setting => setting.name == entry.name
245 settingsObj.value = null;
246 settingsObj.value_str = null;
247 settingsObj._org_unit = null;
248 settingsObj.context = null;
250 this.mergeSettingValues();
253 this.toast.danger(entry.label + " failed to update: " + err.desc);
257 showEditSettingValueDialog(entry: OrgUnitSetting) {
258 this.editOuSettingDialog.entry = entry;
259 this.editOuSettingDialog.entryValue = entry.value;
260 this.editOuSettingDialog.entryContext = entry._org_unit || this.contextOrg;
261 this.editOuSettingDialog.open({size: 'lg'}).subscribe(
263 this.updateSetting(res, entry);
268 showHistoryDialog(entry: OrgUnitSetting) {
270 this.fetchHistory(entry).then(
272 this.orgUnitSettingHistoryDialog.history = this.currentHistory;
273 this.orgUnitSettingHistoryDialog.gridDataSource.data = this.currentHistory;
274 this.orgUnitSettingHistoryDialog.entry = entry;
275 this.orgUnitSettingHistoryDialog.open({size: 'lg'}).subscribe(res => {
277 this.updateSetting(res, entry);
285 showJsonDialog(isExport: boolean) {
286 this.ouSettingJsonDialog.isExport = isExport;
287 this.ouSettingJsonDialog.jsonData = "";
289 this.ouSettingJsonDialog.jsonData = "{";
290 this.gridDataSource.data.forEach(entry => {
291 this.ouSettingJsonDialog.jsonData +=
292 "\"" + entry.name + "\": {\"org\": \"" +
293 this.contextOrg.id() + "\", \"value\": ";
295 this.ouSettingJsonDialog.jsonData += "\"" + entry.value + "\"";
297 this.ouSettingJsonDialog.jsonData += "null";
299 this.ouSettingJsonDialog.jsonData += "}";
300 if (this.gridDataSource.data.indexOf(entry) != (this.gridDataSource.data.length - 1))
301 this.ouSettingJsonDialog.jsonData += ",";
303 this.ouSettingJsonDialog.jsonData += "}";
306 this.ouSettingJsonDialog.open({size: 'lg'}).subscribe(res => {
307 if (res.apply && res.jsonData) {
308 let jsonSettings = JSON.parse(res.jsonData);
309 Object.entries(jsonSettings).forEach((fields) => {
310 let entry = this.settingTypeArr.find(x => x.name == fields[0]);
311 let obj = {setting: {}, context: {}};
312 let val = this.parseValType(fields[1]['value'], entry.dataType);
313 obj.setting[fields[0]] = val;
314 obj.context = this.org.get(fields[1]['org']);
315 this.updateSetting(obj, entry);
321 parseValType(value, dataType) {
322 if (dataType == "integer" || "currency" || "link") {
323 return Number(value);
324 } else if (dataType == "bool") {
325 return (value === 'true');
332 if (this.filterString != this.prevFilter) {
333 this.prevFilter = this.filterString;
334 if (this.filterString) {
335 this.gridDataSource.data = [];
336 let tempGrid = this.settingTypeArr;
337 tempGrid.forEach(row => {
339 row.name.includes(this.filterString) ||
340 row.label.includes(this.filterString) ||
341 (row.grp && row.grp.includes(this.filterString)) ||
342 (row.description && row.description.includes(this.filterString));
343 if (containsString) {
344 this.gridDataSource.data.push(row);
348 this.gridDataSource.data = this.settingTypeArr;
354 if (this.contextOrg != org) {
355 this.contextOrg = org;
356 this.refreshSettings = true;
359 if (this.filterString != this.prevFilter) {
360 this.refreshSettings = true;
363 if (this.refreshSettings) {
364 this.mergeSettingValues().then(
365 res => this.filterCoust()