From: Mike Risher Date: Tue, 31 Dec 2019 19:51:37 +0000 (+0000) Subject: lp1857911 Statistical Categories UI port X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=9866d057c354cc554731999fa28225118798a61c;p=working%2FEvergreen.git lp1857911 Statistical Categories UI port This UI allows editing copy statistical categories (stat cats), patron statistical categories, and their entries. They are filtered by location. This port opens a new page when editing deleting or adding entries. 2/21/2020 update - New entries now have a default stat cat and org setting that cannot be edited. Signed-off-by: Mike Risher Changes to be committed: modified: Open-ILS/examples/fm_IDL.xml modified: Open-ILS/src/eg2/src/app/staff/admin/local/admin-local-splash.component.html modified: Open-ILS/src/eg2/src/app/staff/admin/local/routing.module.ts new file: Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat.component.html new file: Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat.component.ts new file: Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat.module.ts new file: Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat_entries.component.html new file: Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat_entries.component.ts new file: Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat_routing.module.ts --- diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index 5be2f5a028..a898376bfd 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -6905,7 +6905,10 @@ SELECT usr, + + + @@ -7228,7 +7231,7 @@ SELECT usr, - + @@ -7241,8 +7244,22 @@ SELECT usr, + + + + + + + + + + + + + + - + @@ -7254,6 +7271,20 @@ SELECT usr, + + + + + + + + + + + + + + @@ -8250,7 +8281,16 @@ SELECT usr, + + + + + + + + + diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/admin-local-splash.component.html b/Open-ILS/src/eg2/src/app/staff/admin/local/admin-local-splash.component.html index e051d37c42..a8135d9366 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/local/admin-local-splash.component.html +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/admin-local-splash.component.html @@ -59,7 +59,7 @@ + routerLink="/staff/admin/local/asset/stat_cat_editor"> +
+
+ + + + +
+
Focus location
+ + +
+ + + + + + + Edit Entries + + + + + +
+
+ + + +
+
Focus location
+ + +
+ + + + + + + Edit Entries + + + + +
+
+
+
+
+ + + + + + + + + diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat.component.ts new file mode 100644 index 0000000000..3c6adad258 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat.component.ts @@ -0,0 +1,172 @@ +import {Pager} from '@eg/share/util/pager'; +import {GridComponent} from '@eg/share/grid/grid.component'; +import {GridDataSource} from '@eg/share/grid/grid'; +import {IdlObject} from '@eg/core/idl.service'; +import {PcrudService} from '@eg/core/pcrud.service'; +import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component'; +import {StringComponent} from '@eg/share/string/string.component'; +import {ToastService} from '@eg/share/toast/toast.service'; +import {Component, OnInit, ViewChild} from '@angular/core'; +import {NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap'; +import {OrgService} from '@eg/core/org.service'; + +@Component({ + templateUrl: './stat_cat.component.html' +}) + +export class StatCatComponent implements OnInit { + currentTab: string; + ascDataSource: GridDataSource = new GridDataSource(); + actscDataSource: GridDataSource = new GridDataSource(); + + // currently selected org. Starting value is CONS (id 1) + selectedOrgId = 1; + + // list of orgs to retrieve stat cats for + orgFamly: any; + + @ViewChild('copyGrid', {static: false}) copyGrid: GridComponent; + @ViewChild('patronGrid', {static: false}) patronGrid: GridComponent; + @ViewChild('copyDialog', {static: false}) copyDialog: FmRecordEditorComponent; + @ViewChild('patronDialog', {static: false}) patronDialog: FmRecordEditorComponent; + @ViewChild('updateSuccessString', {static: false}) updateSuccessString: StringComponent; + @ViewChild('updateFailedString', {static: false}) updateFailedString: StringComponent; + @ViewChild('deleteFailedString', {static: false}) deleteFailedString: StringComponent; + @ViewChild('deleteSuccessString', {static: false}) deleteSuccessString: StringComponent; + @ViewChild('createSuccessString', {static: false}) createSuccessString: StringComponent; + @ViewChild('createErrString', {static: false}) createErrString: StringComponent; + + constructor( + private pcrud: PcrudService, + private org: OrgService, + private toast: ToastService + ) { + } + + ngOnInit() { + this.getOrgFamly(); + this.getAscData(); + this.getActscData(); + } + + getOrgFamly() { + this.orgFamly = this.org.fullPath(this.selectedOrgId); + this.orgFamly = this.orgFamly.map(record => { + return record.id(); + }); + return this.orgFamly; + } + + getAscData() { + this.ascDataSource.getRows = (pager: Pager, sort: any[]) => { + const orderBy = {asc: 'id'}; + return this.pcrud.search('asc', {owner: this.orgFamly}, orderBy); + }; + } + + getActscData() { + this.actscDataSource.getRows = (pager: Pager, sort: any[]) => { + const orderBy = {actsc: 'id'}; + return this.pcrud.search('actsc', {owner: this.orgFamly}, orderBy); + }; + } + + editStatCat = (idlThing) => { + const idlString = idlThing[0].classname; + const lookupResponse = this.lookUpType(idlString); + const currentGrid = lookupResponse.currentGrid; + const currentDialog = lookupResponse.currentDialog; + currentDialog.mode = 'update'; + currentDialog.recordId = idlThing[0].id(); + currentDialog.open({size: 'lg'}).subscribe( + id => { + console.debug('Record editor performed action'); + currentGrid.reload(); + }, + err => { + console.debug(err); + }, + () => console.debug('Dialog closed') + ); + } + + onTabChange(event: NgbTabChangeEvent) { + this.currentTab = event.nextId; + } + + orgOnChange = (org: IdlObject): void => { + this.selectedOrgId = org.id(); + this.getOrgFamly(); + if (this.copyGrid) { + this.getAscData(); + this.copyGrid.reload(); + } + if (this.patronGrid) { + this.getActscData(); + this.patronGrid.reload(); + } + } + + deleteStatCat = (idlThings: IdlObject[]) => { + const idlString = idlThings[0].classname; + const currentGrid = this.lookUpType(idlString).currentGrid; + idlThings.forEach(idlThing => idlThing.isdeleted(true)); + this.pcrud.autoApply(idlThings).subscribe( + val => { + console.debug('deleted: ' + val); + this.deleteSuccessString.current() + .then(str => this.toast.success(str)); + currentGrid.reload(); + }, + err => { + this.deleteFailedString.current() + .then(str => this.toast.danger(str)); + } + ); + } + + lookUpType = (idlString) => { + let currentDialog; + let currentGrid; + if (idlString === 'asc') { + currentGrid = this.copyGrid; + currentDialog = this.copyDialog; + } else { + currentGrid = this.patronGrid; + currentDialog = this.patronDialog; + } + return { + currentDialog: currentDialog, + currentGrid: currentGrid + }; + } + + newStatCat = (type: any) => { + let currentDialog; + let currentGrid; + if (this.currentTab === 'patron') { + currentGrid = this.patronGrid; + currentDialog = this.patronDialog; + } else { + currentGrid = this.copyGrid; + currentDialog = this.copyDialog; + } + currentDialog.mode = 'create'; + currentDialog.recordId = null; + currentDialog.record = null; + currentDialog.open({size: 'lg'}).subscribe( + ok => { + this.createSuccessString.current() + .then(str => this.toast.success(str)); + currentGrid.reload(); + }, + rejection => { + if (!rejection.dismissed) { + this.createErrString.current() + .then(str => this.toast.danger(str)); + } + } + ); + } + +} diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat.module.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat.module.ts new file mode 100644 index 0000000000..6be786b5a1 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat.module.ts @@ -0,0 +1,20 @@ +import {NgModule} from '@angular/core'; +import {AdminCommonModule} from '@eg/staff/admin/common.module'; +import {StatCatComponent} from './stat_cat.component'; +import {StatCatEntriesComponent} from './stat_cat_entries.component'; +import {StatCatRoutingModule} from './stat_cat_routing.module'; + +@NgModule({ + declarations: [ + StatCatComponent, + StatCatEntriesComponent, + ], + imports: [ + AdminCommonModule, + StatCatRoutingModule, + ], + exports: [], + providers: [] +}) + +export class StatCatModule {} diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat_entries.component.html b/Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat_entries.component.html new file mode 100644 index 0000000000..7a7030be3b --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat_entries.component.html @@ -0,0 +1,41 @@ + + + + + + +
+ + + + + +
+
+ + + + + +
+ + + + + + + + + diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat_entries.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat_entries.component.ts new file mode 100644 index 0000000000..12bd15e8ee --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat_entries.component.ts @@ -0,0 +1,155 @@ +import {Pager} from '@eg/share/util/pager'; +import {GridComponent} from '@eg/share/grid/grid.component'; +import {GridDataSource} from '@eg/share/grid/grid'; +import {IdlService, IdlObject} from '@eg/core/idl.service'; +import {PcrudService} from '@eg/core/pcrud.service'; +import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component'; +import {StringComponent} from '@eg/share/string/string.component'; +import {ToastService} from '@eg/share/toast/toast.service'; +import {Component, OnInit, ViewChild} from '@angular/core'; +import {ActivatedRoute} from '@angular/router'; +import {Router} from '@angular/router'; + +@Component({ + templateUrl: './stat_cat_entries.component.html' +}) + +export class StatCatEntriesComponent implements OnInit { + statCatId: number; + statCatOrg: number; + statCatType: string; + defaultNewRecord: IdlObject; + copyDataSource: GridDataSource = new GridDataSource(); + patronDataSource: GridDataSource = new GridDataSource(); + + @ViewChild('copyGrid', {static: false}) copyGrid: GridComponent; + @ViewChild('patronGrid', {static: false}) patronGrid: GridComponent; + @ViewChild('copyDialog', {static: false}) copyDialog: FmRecordEditorComponent; + @ViewChild('patronDialog', {static: false}) patronDialog: FmRecordEditorComponent; + @ViewChild('updateSuccessString', {static: false}) updateSuccessString: StringComponent; + @ViewChild('updateFailedString', {static: false}) updateFailedString: StringComponent; + @ViewChild('deleteFailedString', {static: false}) deleteFailedString: StringComponent; + @ViewChild('deleteSuccessString', {static: false}) deleteSuccessString: StringComponent; + @ViewChild('createSuccessString', {static: false}) createSuccessString: StringComponent; + @ViewChild('createErrString', {static: false}) createErrString: StringComponent; + + constructor( + private router: Router, + private idl: IdlService, + private pcrud: PcrudService, + private route: ActivatedRoute, + private toast: ToastService + ) { + } + + ngOnInit() { + this.statCatId = parseInt(this.route.snapshot.paramMap.get('id'), 10); + if (this.router.url.includes('copy_entries')) { + this.statCatType = 'Copy'; + this.copyDataSource.getRows = (pager: Pager, sort: any[]) => { + const orderBy: any = {order_by: {asce: 'id'}}; + return this.pcrud.search('asce', {stat_cat: this.statCatId}, orderBy); + }; + this.getParentRecordOrg('asc'); + } else if (this.router.url.includes('patron_entries')) { + this.statCatType = 'Patron'; + this.patronDataSource.getRows = (pager: Pager, sort: any[]) => { + const orderBy: any = {order_by: {actsce: 'id'}}; + return this.pcrud.search('actsce', {stat_cat: this.statCatId}, orderBy); + }; + this.getParentRecordOrg('actsc'); + } else { + console.debug('Error - unable to determine type of stat cat'); + } + } + + getParentRecordOrg = (searchIdl) => { + return this.pcrud.search(searchIdl, {id: this.statCatId}, {} + ).subscribe(rec => { + this.statCatOrg = rec.owner(); + return rec; + }); + } + + deleteEntry = (idlThings: IdlObject[]) => { + const currentGrid = this.lookupType().currentGrid; + idlThings.forEach(idlThing => idlThing.isdeleted(true)); + this.pcrud.autoApply(idlThings).subscribe( + val => { + console.debug('deleted: ' + val); + this.deleteSuccessString.current() + .then(str => this.toast.success(str)); + currentGrid.reload(); + }, + err => { + this.deleteFailedString.current() + .then(str => this.toast.danger(str)); + } + ); + } + + lookupType() { + let currentDialog; + let currentGrid; + let newIdl; + if (this.statCatType === 'Copy') { + currentGrid = this.copyGrid; + currentDialog = this.copyDialog; + newIdl = 'asce'; + } else { + currentGrid = this.patronGrid; + currentDialog = this.patronDialog; + newIdl = 'actsce'; + } + return { + currentGrid: currentGrid, + currentDialog: currentDialog, + newIdl: newIdl + }; + } + + createNewEntry = () => { + const lookupResponse = this.lookupType(); + const currentDialog = lookupResponse.currentDialog; + const currentGrid = lookupResponse.currentGrid; + this.defaultNewRecord = this.idl.create(lookupResponse.newIdl); + + // pre-populate new record with the current stat_cat and org + this.defaultNewRecord.owner(this.statCatOrg); + this.defaultNewRecord.stat_cat(this.statCatId); + currentDialog.mode = 'create'; + currentDialog.recordId = null; + currentDialog.record = this.defaultNewRecord; + currentDialog.open({size: 'lg'}).subscribe( + ok => { + this.createSuccessString.current() + .then(str => this.toast.success(str)); + currentGrid.reload(); + }, + rejection => { + if (!rejection.dismissed) { + this.createErrString.current() + .then(str => this.toast.danger(str)); + } + } + ); + } + + editEntry = (idlThing) => { + const lookupResponse = this.lookupType(); + const currentDialog = lookupResponse.currentDialog; + const currentGrid = lookupResponse.currentGrid; + currentDialog.mode = 'update'; + currentDialog.recordId = idlThing[0].id(); + currentDialog.open({size: 'lg'}).subscribe( + id => { + console.debug('Record editor performed action'); + currentGrid.reload(); + }, + err => { + console.debug(err); + }, + () => console.debug('Dialog closed') + ); + } +} diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat_routing.module.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat_routing.module.ts new file mode 100644 index 0000000000..f2d205da56 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/stat_cat/stat_cat_routing.module.ts @@ -0,0 +1,22 @@ +import {NgModule} from '@angular/core'; +import {RouterModule, Routes} from '@angular/router'; +import {StatCatComponent} from './stat_cat.component'; +import {StatCatEntriesComponent} from './stat_cat_entries.component'; + +const routes: Routes = [{ + path: '', + component: StatCatComponent +}, { + path: 'copy_entries/:id', + component: StatCatEntriesComponent +}, { + path: 'patron_entries/:id', + component: StatCatEntriesComponent +}]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) + +export class StatCatRoutingModule {}