From: Mike Risher Date: Tue, 17 Sep 2019 21:33:04 +0000 (+0000) Subject: LP#1844169: port Search Filter Groups admin interface to Angular X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=3db4db0b6e94d1895dc4c0e3c7425b39851fab2e;p=evergreen%2Fpines.git LP#1844169: port Search Filter Groups admin interface to Angular 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 Signed-off-by: Terran McCanna Signed-off-by: Galen Charlton --- diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index 242c357b43..5c462e4ce2 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -6535,12 +6535,12 @@ SELECT usr, - - - - - - + + + + + + @@ -6557,10 +6557,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 d9e34eaf7f..e460ca47e2 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 @@ -57,7 +57,7 @@ + routerLink="/staff/admin/local/actor/search_filter_group"> + import('./search-filter/search-filter-group.module').then(m => m.SearchFilterGroupModule) }, { path: 'config/circ_limit_set', loadChildren: () => diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/query-dialog.component.html b/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/query-dialog.component.html new file mode 100644 index 0000000000..9f2521164c --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/query-dialog.component.html @@ -0,0 +1,45 @@ + + + + + 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..f1d1776cc3 --- /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.newQueryPosition != 0)) || !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..f533942491 --- /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..43cc24ed54 --- /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') editDialog: FmRecordEditorComponent; + @ViewChild('queryDialog') queryDialog: QueryDialogComponent; + @ViewChild('grid', { static: true }) grid: GridComponent; + + @ViewChild('updateSuccessString') updateSuccessString: StringComponent; + @ViewChild('updateFailedString') updateFailedString: StringComponent; + @ViewChild('createString') createString: StringComponent; + @ViewChild('createQueryString') createQueryString: StringComponent; + @ViewChild('queryRequiredString') queryRequiredString: StringComponent; + @ViewChild('createErrString') createErrString: StringComponent; + @ViewChild('deleteFailedString') deleteFailedString: StringComponent; + @ViewChild('deleteSuccessString') 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..519f54f464 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/search-filter/search-filter-group.component.ts @@ -0,0 +1,92 @@ +import {Pager} from '@eg/share/util/pager'; +import {Location} from '@angular/common'; +import {FormatService} from '@eg/core/format.service'; +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') createString: StringComponent; + @ViewChild('createErrString') createErrString: StringComponent; + @ViewChild('deleteFailedString') deleteFailedString: StringComponent; + @ViewChild('deleteSuccessString') deleteSuccessString: StringComponent; + + constructor( + route: ActivatedRoute, + ngLocation: Location, + format: FormatService, + idl: IdlService, + org: OrgService, + auth: AuthService, + pcrud: PcrudService, + perm: PermService, + toast: ToastService, + private router: Router + ) { + super(route, ngLocation, format, 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 {}