1 import {Component, OnInit, Input, ViewChild} from '@angular/core';
2 import {Observable, Observer} from 'rxjs';
3 import {Pager} from '@eg/share/util/pager';
4 import {IdlObject, IdlService} from '@eg/core/idl.service';
5 import {OrgService} from '@eg/core/org.service';
6 import {PcrudService} from '@eg/core/pcrud.service';
7 import {AuthService} from '@eg/core/auth.service';
8 import {NetService} from '@eg/core/net.service';
9 import {GridDataSource} from '@eg/share/grid/grid';
10 import {GridComponent} from '@eg/share/grid/grid.component';
11 import {ToastService} from '@eg/share/toast/toast.service';
13 import {EditOuSettingDialogComponent
14 } from '@eg/staff/admin/local/org-unit-settings/edit-org-unit-setting-dialog.component';
15 import {OuSettingHistoryDialogComponent
16 } from '@eg/staff/admin/local/org-unit-settings/org-unit-setting-history-dialog.component';
17 import {OuSettingJsonDialogComponent
18 } from '@eg/staff/admin/local/org-unit-settings/org-unit-setting-json-dialog.component';
20 export class OrgUnitSetting {
29 _idlOptions: IdlObject[];
37 templateUrl: './org-unit-settings.component.html'
40 export class OrgUnitSettingsComponent implements OnInit {
42 contextOrg: IdlObject;
45 gridDataSource: GridDataSource;
46 gridTemplateContext: any;
48 currentHistory: any[];
49 currentOptions: any[];
51 @ViewChild('orgUnitSettingsGrid', { static: true }) orgUnitSettingsGrid: GridComponent;
53 @ViewChild('editOuSettingDialog', { static: true })
54 private editOuSettingDialog: EditOuSettingDialogComponent;
55 @ViewChild('orgUnitSettingHistoryDialog', { static: true })
56 private orgUnitSettingHistoryDialog: OuSettingHistoryDialogComponent;
57 @ViewChild('ouSettingJsonDialog', { static: true })
58 private ouSettingJsonDialog: OuSettingJsonDialogComponent;
60 refreshSettings: boolean;
61 renderFromPrefs: boolean;
63 settingTypeArr: any[];
65 @Input() filterString: string;
68 private org: OrgService,
69 private pcrud: PcrudService,
70 private auth: AuthService,
71 private toast: ToastService,
72 private net: NetService,
74 this.gridDataSource = new GridDataSource();
75 this.refreshSettings = true;
76 this.renderFromPrefs = true;
78 this.contextOrg = this.org.get(this.auth.user().ws_ou());
83 this.settingTypeArr = [];
84 this.gridDataSource.getRows = (pager: Pager, sort: any[]) => {
85 return this.fetchSettingTypes(pager);
87 this.orgUnitSettingsGrid.onRowActivate.subscribe((setting: OrgUnitSetting) => {
88 this.showEditSettingValueDialog(setting);
92 fetchSettingTypes(pager: Pager): Observable<any> {
93 return new Observable<any>(observer => {
94 this.pcrud.retrieveAll('coust', {flesh: 3, flesh_fields: {
95 'coust': ['grp', 'view_perm']
97 { authoritative: true }).subscribe(
98 settingTypes => this.allocateSettingTypes(settingTypes),
101 this.refreshSettings = false;
102 this.mergeSettingValues().then(
104 this.flattenSettings(observer);
112 mergeSettingValues(): Promise<any> {
113 const settingNames = this.settingTypeArr.map(setting => setting.name);
114 return new Promise((resolve, reject) => {
117 'open-ils.actor.ou_setting.ancestor_default.batch',
118 this.contextOrg.id(), settingNames, this.auth.token()
121 const settingVals = Object.keys(blob).map(key => {
122 return {'name': key, 'setting': blob[key]};
124 settingVals.forEach(key => {
126 const settingsObj = this.settingTypeArr.filter(
127 setting => setting.name === key.name
129 settingsObj.value = key.setting.value;
130 settingsObj.value_str = settingsObj.value;
131 if (settingsObj.dataType === 'link' && (key.setting.value || key.setting.value === 0)) {
132 this.fetchLinkedField(settingsObj.fmClass, key.setting.value, settingsObj.value_str).then(res => {
133 settingsObj.value_str = res;
136 settingsObj._org_unit = this.org.get(key.setting.org);
137 settingsObj.context = settingsObj._org_unit.shortname();
140 resolve(this.settingTypeArr);
147 fetchLinkedField(fmClass, id, val) {
148 return new Promise((resolve, reject) => {
149 return this.pcrud.retrieve(fmClass, id).subscribe(linkedField => {
150 val = linkedField.name();
156 fetchHistory(setting): Promise<any> {
157 const name = setting.name;
158 return new Promise((resolve, reject) => {
161 'open-ils.actor.org_unit.settings.history.retrieve',
162 this.auth.token(), name, this.contextOrg.id()
164 this.currentHistory = [];
165 if (!Array.isArray(res)) {
169 log.org = this.org.get(log.org);
170 log.new_value_str = log.new_value;
171 log.original_value_str = log.original_value;
172 if (setting.dataType === 'link') {
174 this.fetchLinkedField(setting.fmClass, Number(log.new_value), log.new_value_str).then(val => {
175 log.new_value_str = val;
178 if (log.original_value) {
179 this.fetchLinkedField(setting.fmClass, Number(log.original_value), log.original_value_str).then(val => {
180 log.original_value_str = val;
184 if (log.new_value_str) { log.new_value_str = log.new_value_str.replace(/^"(.*)"$/, '$1'); }
185 if (log.original_value_str) { log.original_value_str = log.original_value_str.replace(/^"(.*)"$/, '$1'); }
187 this.currentHistory = res;
188 this.currentHistory.sort((a, b) => {
189 return a.date_applied < b.date_applied ? 1 : -1;
192 resolve(this.currentHistory);
193 }, err => {reject(err); });
197 allocateSettingTypes(coust: IdlObject) {
198 const entry = new OrgUnitSetting();
199 entry.name = coust.name();
200 entry.label = coust.label();
201 entry.dataType = coust.datatype();
202 if (coust.fm_class()) { entry.fmClass = coust.fm_class(); }
203 if (coust.description()) { entry.description = coust.description(); }
204 // For some reason some setting types don't have a grp, should look into this...
205 if (coust.grp()) { entry.grp = coust.grp().label(); }
206 if (coust.view_perm()) {
207 entry.view_perm = coust.view_perm().code();
210 this.settingTypeArr.push(entry);
213 flattenSettings(observer: Observer<any>) {
214 this.gridDataSource.data = this.settingTypeArr;
218 contextOrgChanged(org: IdlObject) {
219 this.updateGrid(org);
222 applyFilter(clear?: boolean) {
223 if (clear) { this.filterString = ''; }
224 this.updateGrid(this.contextOrg);
227 updateSetting(obj, entry) {
230 'open-ils.actor.org_unit.settings.update',
231 this.auth.token(), obj.context.id(), obj.setting
232 ).toPromise().then(res => {
233 this.toast.success(entry.label + ' Updated.');
234 if (!obj.setting[entry.name]) {
235 const settingsObj = this.settingTypeArr.filter(
236 setting => setting.name === entry.name
238 settingsObj.value = null;
239 settingsObj.value_str = null;
240 settingsObj._org_unit = null;
241 settingsObj.context = null;
243 this.mergeSettingValues();
246 this.toast.danger(entry.label + ' failed to update: ' + err.desc);
250 showEditSettingValueDialog(entry: OrgUnitSetting) {
251 this.editOuSettingDialog.entry = entry;
252 this.editOuSettingDialog.entryValue = entry.value;
253 this.editOuSettingDialog.entryContext = entry._org_unit || this.contextOrg;
254 this.editOuSettingDialog.open({size: 'lg'}).subscribe(
256 this.updateSetting(res, entry);
261 showHistoryDialog(entry: OrgUnitSetting) {
263 this.fetchHistory(entry).then(
265 this.orgUnitSettingHistoryDialog.history = this.currentHistory;
266 this.orgUnitSettingHistoryDialog.gridDataSource.data = this.currentHistory;
267 this.orgUnitSettingHistoryDialog.entry = entry;
268 this.orgUnitSettingHistoryDialog.open({size: 'lg'}).subscribe(res => {
270 this.updateSetting(res, entry);
278 showJsonDialog(isExport: boolean) {
279 this.ouSettingJsonDialog.isExport = isExport;
280 this.ouSettingJsonDialog.jsonData = '';
282 this.ouSettingJsonDialog.jsonData = '{';
283 this.gridDataSource.data.forEach(entry => {
284 this.ouSettingJsonDialog.jsonData +=
285 '"' + entry.name + '": {"org": "' +
286 this.contextOrg.id() + '", "value": ';
288 this.ouSettingJsonDialog.jsonData += '"' + entry.value + '"';
290 this.ouSettingJsonDialog.jsonData += 'null';
292 this.ouSettingJsonDialog.jsonData += '}';
293 if (this.gridDataSource.data.indexOf(entry) !== (this.gridDataSource.data.length - 1)) {
294 this.ouSettingJsonDialog.jsonData += ',';
297 this.ouSettingJsonDialog.jsonData += '}';
300 this.ouSettingJsonDialog.open({size: 'lg'}).subscribe(res => {
301 if (res.apply && res.jsonData) {
302 const jsonSettings = JSON.parse(res.jsonData);
303 Object.entries(jsonSettings).forEach((fields) => {
304 const entry = this.settingTypeArr.find(x => x.name === fields[0]);
305 const obj = {setting: {}, context: {}};
306 const val = this.parseValType(fields[1]['value'], entry.dataType);
307 obj.setting[fields[0]] = val;
308 obj.context = this.org.get(fields[1]['org']);
309 this.updateSetting(obj, entry);
315 parseValType(value, dataType) {
316 if (dataType === 'integer' || 'currency' || 'link') {
317 return Number(value);
318 } else if (dataType === 'bool') {
319 return (value === 'true');
326 if (this.filterString !== this.prevFilter) {
327 this.prevFilter = this.filterString;
328 if (this.filterString) {
329 this.gridDataSource.data = [];
330 const tempGrid = this.settingTypeArr;
331 tempGrid.forEach(row => {
332 const containsString =
333 row.name.includes(this.filterString) ||
334 row.label.includes(this.filterString) ||
335 (row.grp && row.grp.includes(this.filterString)) ||
336 (row.description && row.description.includes(this.filterString));
337 if (containsString) {
338 this.gridDataSource.data.push(row);
342 this.gridDataSource.data = this.settingTypeArr;
348 if (this.contextOrg !== org) {
349 this.contextOrg = org;
350 this.refreshSettings = true;
353 if (this.filterString !== this.prevFilter) {
354 this.refreshSettings = true;
357 if (this.refreshSettings) {
358 this.mergeSettingValues().then(
359 res => this.filterCoust()