From 95c5ed22dc5d9feec0f4eb630a35711c2ef4b3f2 Mon Sep 17 00:00:00 2001 From: Mike Risher Date: Tue, 17 Sep 2019 21:33:04 +0000 Subject: [PATCH] lp1844169-search-filter-groups Port search filter groups admin from DOJO UI to Angular. Each search filter group has its own edit page, from which you can edit search filter group entries. Signed-off-by: Mike Risher Changes to be committed: modified: eg2/src/app/staff/admin/local/admin-local-splash.component.html modified: eg2/src/app/staff/admin/local/routing.module.ts new file: eg2/src/app/staff/admin/local/search-filter/search-filter-group-entries.component.html new file: eg2/src/app/staff/admin/local/search-filter/search-filter-group-entries.component.ts new file: eg2/src/app/staff/admin/local/search-filter/search-filter-group-routing.module.ts new file: eg2/src/app/staff/admin/local/search-filter/search-filter-group.component.html new file: eg2/src/app/staff/admin/local/search-filter/search-filter-group.component.ts new file: eg2/src/app/staff/admin/local/search-filter/search-filter-group.module.ts modified: Open-ILS/examples/fm_IDL.xml --- Open-ILS/examples/fm_IDL.xml | 20 ++-- .../admin/local/admin-local-splash.component.html | 2 +- .../src/app/staff/admin/local/routing.module.ts | 3 + .../search-filter/query-dialog.component.html | 45 ++++++++ .../local/search-filter/query-dialog.component.ts | 90 +++++++++++++++ .../search-filter-group-entries.component.html | 37 +++++++ .../search-filter-group-entries.component.ts | 122 +++++++++++++++++++++ .../search-filter-group-routing.module.ts | 19 ++++ .../search-filter-group.component.html | 23 ++++ .../search-filter/search-filter-group.component.ts | 88 +++++++++++++++ .../search-filter/search-filter-group.module.ts | 24 ++++ 11 files changed, 462 insertions(+), 11 deletions(-) create mode 100644 Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/query-dialog.component.html create mode 100644 Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/query-dialog.component.ts create mode 100644 Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group-entries.component.html create mode 100644 Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group-entries.component.ts create mode 100644 Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group-routing.module.ts create mode 100644 Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group.component.html create mode 100644 Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group.component.ts create mode 100644 Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group.module.ts diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index 7622efd0db..5db9766225 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -6253,12 +6253,12 @@ SELECT usr, - - - - - - + + + + + + @@ -6275,10 +6275,10 @@ 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 223d1817cc..c01a044483 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 @@ -49,7 +49,7 @@ + routerLink="/staff/admin/local/actor/search_filter_group"> + + + + diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/query-dialog.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/query-dialog.component.ts new file mode 100644 index 0000000000..36432d9a92 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/query-dialog.component.ts @@ -0,0 +1,90 @@ +import {Component, OnInit, Input} from '@angular/core'; +import {NetService} from '@eg/core/net.service'; +import {ActivatedRoute} from '@angular/router'; +import {IdlService, IdlObject} from '@eg/core/idl.service'; +import {AuthService} from '@eg/core/auth.service'; +import {DialogComponent} from '@eg/share/dialog/dialog.component'; +import {NgbModal} from '@ng-bootstrap/ng-bootstrap'; + +@Component({ + selector: 'eg-query-dialog', + templateUrl: 'query-dialog.component.html' +}) + +export class QueryDialogComponent extends DialogComponent implements OnInit { + + currentId: number; + newAsq: IdlObject; + newAsfge: IdlObject; + + @Input() mode: 'create' | 'update'; + @Input() record: IdlObject; + @Input() recordId: number; + @Input() newQueryLabel: string; + @Input() newQueryText: string; + @Input() newQueryPosition: string; + + constructor( + private modal: NgbModal, // required for passing to parent + private route: ActivatedRoute, + private idl: IdlService, + private net: NetService, + private auth: AuthService + ) { + super(modal); // required for subclassing + } + + ngOnInit() { + this.currentId = parseInt(this.route.snapshot.paramMap.get('id'), 10); + this.newAsfge = this.idl.create('asfge'); + this.newAsq = this.idl.create('asq'); + } + + // wipe out all data so next time we start with a clean slate + closeAndReset(data) { + this.mode = undefined; + this.record = undefined; + this.recordId = undefined; + this.newQueryLabel = undefined; + this.newQueryPosition = undefined; + this.newQueryText = undefined; + this.close(data); + } + + save() { + if (!this.newQueryLabel || !this.newQueryPosition || !this.newQueryText) { + this.closeAndReset({notFilledOut: true}); + } + const recToSave = this.prepareRecord(); + return this.net.request( + 'open-ils.actor', + 'open-ils.actor.filter_group_entry.crud', + this.auth.token(), + recToSave + ).toPromise().then(res => { + this.closeAndReset(res); + }); + } + + prepareRecord(): IdlObject { + let recToSave; + let queryToSave; + if (this.mode === 'create') { + recToSave = this.idl.clone(this.newAsfge); + queryToSave = this.idl.clone(this.newAsq); + recToSave.isnew(true); + recToSave.query(queryToSave); + } else if (this.mode === 'update') { + recToSave = this.record; + queryToSave = this.record.query(); + recToSave.ischanged(true); + } else { + console.debug('Error! No mode defined!'); + } + queryToSave.label(this.newQueryLabel); + queryToSave.query_text(this.newQueryText); + recToSave.pos(this.newQueryPosition); + recToSave.grp(this.currentId); + return recToSave; + } +} diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group-entries.component.html b/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group-entries.component.html new file mode 100644 index 0000000000..43dc7629e8 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group-entries.component.html @@ -0,0 +1,37 @@ + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group-entries.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group-entries.component.ts new file mode 100644 index 0000000000..3bfdc5b2d4 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group-entries.component.ts @@ -0,0 +1,122 @@ +import {Component, OnInit, Input, ViewChild} from '@angular/core'; +import {ActivatedRoute} from '@angular/router'; +import {GridDataSource} from '@eg/share/grid/grid'; +import {GridComponent} from '@eg/share/grid/grid.component'; +import {Pager} from '@eg/share/util/pager'; +import {PcrudService} from '@eg/core/pcrud.service'; +import {IdlObject} from '@eg/core/idl.service'; +import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component'; +import {ToastService} from '@eg/share/toast/toast.service'; +import {StringComponent} from '@eg/share/string/string.component'; +import {QueryDialogComponent} from './query-dialog.component'; + +@Component({ + templateUrl: './search-filter-group-entries.component.html' +}) + +export class SearchFilterGroupEntriesComponent implements OnInit { + + @ViewChild('editDialog', { static: false }) editDialog: FmRecordEditorComponent; + @ViewChild('queryDialog', { static: false }) queryDialog: QueryDialogComponent; + @ViewChild('grid', { static: true }) grid: GridComponent; + + @ViewChild('updateSuccessString', { static: false }) updateSuccessString: StringComponent; + @ViewChild('updateFailedString', { static: false }) updateFailedString: StringComponent; + @ViewChild('createString', { static: false }) createString: StringComponent; + @ViewChild('createQueryString', { static: false }) createQueryString: StringComponent; + @ViewChild('queryRequiredString', { static: false }) queryRequiredString: StringComponent; + @ViewChild('createErrString', { static: false }) createErrString: StringComponent; + @ViewChild('deleteFailedString', { static: false }) deleteFailedString: StringComponent; + @ViewChild('deleteSuccessString', { static: false }) deleteSuccessString: StringComponent; + + @Input() dataSource: GridDataSource; + + currentId: number; + + constructor( + private route: ActivatedRoute, + private pcrud: PcrudService, + private toast: ToastService + ) { + this.dataSource = new GridDataSource(); + } + + ngOnInit() { + this.currentId = parseInt(this.route.snapshot.paramMap.get('id'), 10); + this.dataSource.getRows = (pager: Pager, sort: any[]) => { + const searchOps = { + offset: pager.offset, + limit: pager.limit, + order_by: {asfge: 'pos'}, + flesh: 1, + flesh_fields: {asfge: ['query']} + }; + return this.pcrud.search('asfge', {grp: this.currentId}, searchOps); + }; + this.grid.onRowActivate.subscribe( + (idlThing: IdlObject) => this.editQuery([idlThing]) + ); + } + + createQuery = () => { + this.queryDialog.mode = 'create'; + this.queryDialog.open({size: 'lg'}).subscribe( + result => { + if (result.notFilledOut) { + this.queryRequiredString.current() + .then(str => this.toast.danger(str)); + } else { + this.createQueryString.current() + .then(str => this.toast.success(str)); + this.grid.reload(); + } + }, + error => { + this.createErrString.current() + .then(str => this.toast.danger(str)); + } + ); + } + + editQuery = (event) => { + const firstRecord = event[0]; + this.queryDialog.record = firstRecord; + this.queryDialog.mode = 'update'; + this.queryDialog.newQueryLabel = firstRecord.query().label(); + this.queryDialog.newQueryText = firstRecord.query().query_text(); + this.queryDialog.newQueryPosition = firstRecord.pos(); + this.queryDialog.recordId = firstRecord.id(); + this.queryDialog.open({size: 'lg'}).subscribe( + result => { + if (result.notFilledOut) { + this.queryRequiredString.current() + .then(str => this.toast.danger(str)); + } else { + this.updateSuccessString.current() + .then(str => this.toast.success(str)); + this.grid.reload(); + } + }, + error => { + this.updateFailedString.current() + .then(str => this.toast.danger(str)); + } + ); + } + + deleteSelected = (idlThings: IdlObject[]) => { + 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)); + }, + err => { + this.deleteFailedString.current() + .then(str => this.toast.danger(str)); + }, + () => this.grid.reload() + ); + } +} diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group-routing.module.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group-routing.module.ts new file mode 100644 index 0000000000..9763794dc8 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group-routing.module.ts @@ -0,0 +1,19 @@ +import {NgModule} from '@angular/core'; +import {RouterModule, Routes} from '@angular/router'; +import {SearchFilterGroupComponent} from './search-filter-group.component'; +import {SearchFilterGroupEntriesComponent} from './search-filter-group-entries.component'; + +const routes: Routes = [{ + path: ':id', + component: SearchFilterGroupEntriesComponent + }, { + path: '', + component: SearchFilterGroupComponent +}]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) + +export class SearchFilterGroupRoutingModule {} diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group.component.html b/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group.component.html new file mode 100644 index 0000000000..1defc26874 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group.component.html @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group.component.ts new file mode 100644 index 0000000000..a7106d2cc9 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group.component.ts @@ -0,0 +1,88 @@ +import {Pager} from '@eg/share/util/pager'; +import {Component, Input, ViewChild, OnInit} from '@angular/core'; +import {Router, ActivatedRoute} from '@angular/router'; +import {IdlService, IdlObject} from '@eg/core/idl.service'; +import {GridDataSource} from '@eg/share/grid/grid'; +import {GridComponent} from '@eg/share/grid/grid.component'; +import {ToastService} from '@eg/share/toast/toast.service'; +import {PcrudService} from '@eg/core/pcrud.service'; +import {OrgService} from '@eg/core/org.service'; +import {PermService} from '@eg/core/perm.service'; +import {AuthService} from '@eg/core/auth.service'; +import {StringComponent} from '@eg/share/string/string.component'; +import {AdminPageComponent} from '../../../share/admin-page/admin-page.component'; + +@Component({ + templateUrl: './search-filter-group.component.html' +}) + +export class SearchFilterGroupComponent extends AdminPageComponent implements OnInit { + + @Input() gridDataSource: GridDataSource; + @ViewChild('grid', {static: true}) grid: GridComponent; + @ViewChild('createString', {static: false}) createString: StringComponent; + @ViewChild('createErrString', {static: false}) createErrString: StringComponent; + @ViewChild('deleteFailedString', {static: false}) deleteFailedString: StringComponent; + @ViewChild('deleteSuccessString', {static: false}) deleteSuccessString: StringComponent; + + constructor( + route: ActivatedRoute, + idl: IdlService, + org: OrgService, + auth: AuthService, + pcrud: PcrudService, + perm: PermService, + toast: ToastService, + private router: Router + ) { + super(route, idl, org, auth, pcrud, perm, toast); + } + + ngOnInit() { + this.gridDataSource = new GridDataSource(); + this.gridDataSource.getRows = (pager: Pager, sort: any[]) => { + const searchOps = { + offset: pager.offset, + limit: pager.limit, + order_by: {} + }; + return this.pcrud.retrieveAll('asfg', searchOps); + }; + this.grid.onRowActivate.subscribe( + (idlThing: IdlObject) => { + const idToEdit = idlThing.id(); + this.navigateToEditPage(idToEdit); + } + ); + } + + createNew = () => { + this.editDialog.mode = 'create'; + this.editDialog.recordId = null; + this.editDialog.record = null; + this.editDialog.hiddenFieldsList = ['id', 'create_date']; + this.editDialog.open({size: 'lg'}).subscribe( + ok => { + this.createString.current() + .then(str => this.toast.success(str)); + this.grid.reload(); + }, + rejection => { + if (!rejection.dismissed) { + this.createErrString.current() + .then(str => this.toast.danger(str)); + } + } + ); + } + + editSelected = (sfGroups: IdlObject[]) => { + const idToEdit = sfGroups[0].id(); + this.navigateToEditPage(idToEdit); + } + + navigateToEditPage(id: any) { + this.router.navigate(['/staff/admin/local/actor/search_filter_group/' + id]); + } + + } diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group.module.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group.module.ts new file mode 100644 index 0000000000..9afcf38fb2 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group.module.ts @@ -0,0 +1,24 @@ +import {NgModule} from '@angular/core'; +import {AdminCommonModule} from '@eg/staff/admin/common.module'; +import {SearchFilterGroupComponent} from './search-filter-group.component'; +import {SearchFilterGroupEntriesComponent} from './search-filter-group-entries.component'; +import {SearchFilterGroupRoutingModule} from './search-filter-group-routing.module'; +import {QueryDialogComponent} from './query-dialog.component'; + +@NgModule({ + declarations: [ + SearchFilterGroupComponent, + SearchFilterGroupEntriesComponent, + QueryDialogComponent + ], + imports: [ + AdminCommonModule, + SearchFilterGroupRoutingModule, + ], + exports: [ + ], + providers: [ + ] +}) + +export class SearchFilterGroupModule {} -- 2.11.0