From e5944fc1db8197de45dff4de10d4efa3877b3047 Mon Sep 17 00:00:00 2001 From: Galen Charlton Date: Tue, 3 Aug 2021 18:59:51 -0400 Subject: [PATCH] LP#1938835: admin interface for customizing the staff portal Sponsored-by: Pioneer Library System Signed-off-by: Galen Charlton Signed-off-by: Mike Rylander --- .../admin/local/admin-local-splash.component.html | 2 + .../app/staff/admin/local/admin-local.module.ts | 6 +- .../src/app/staff/admin/local/routing.module.ts | 4 + .../clone-portal-entries-dialog.component.html | 50 +++++++++ .../clone-portal-entries-dialog.component.ts | 34 ++++++ .../staff-portal-page.component.html | 111 ++++++++++++++++++++ .../staff-portal-page.component.ts | 114 +++++++++++++++++++++ 7 files changed, 320 insertions(+), 1 deletion(-) create mode 100644 Open-ILS/src/eg2/src/app/staff/admin/local/staff_portal_page/clone-portal-entries-dialog.component.html create mode 100644 Open-ILS/src/eg2/src/app/staff/admin/local/staff_portal_page/clone-portal-entries-dialog.component.ts create mode 100644 Open-ILS/src/eg2/src/app/staff/admin/local/staff_portal_page/staff-portal-page.component.html create mode 100644 Open-ILS/src/eg2/src/app/staff/admin/local/staff_portal_page/staff-portal-page.component.ts 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 5ab24963ad..41f19dcf71 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 @@ -64,6 +64,8 @@ routerLink="/staff/admin/local/asset/copy_location_order"> + import('./survey/survey.module').then(m => m.SurveyModule) diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/staff_portal_page/clone-portal-entries-dialog.component.html b/Open-ILS/src/eg2/src/app/staff/admin/local/staff_portal_page/clone-portal-entries-dialog.component.html new file mode 100644 index 0000000000..322c036146 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/staff_portal_page/clone-portal-entries-dialog.component.html @@ -0,0 +1,50 @@ + + + + + diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/staff_portal_page/clone-portal-entries-dialog.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/staff_portal_page/clone-portal-entries-dialog.component.ts new file mode 100644 index 0000000000..77730398e5 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/staff_portal_page/clone-portal-entries-dialog.component.ts @@ -0,0 +1,34 @@ +import {Component, Input, ViewChild, TemplateRef, OnInit} from '@angular/core'; +import {DialogComponent} from '@eg/share/dialog/dialog.component'; +import {NgForm, NG_VALIDATORS} from '@angular/forms'; +import {NgbModal} from '@ng-bootstrap/ng-bootstrap'; + +@Component({ + selector: 'eg-clone-portal-entries-dialog', + templateUrl: './clone-portal-entries-dialog.component.html' +}) + +export class ClonePortalEntriesDialogComponent + extends DialogComponent implements OnInit { + + result = { }; + + constructor( + private modal: NgbModal + ) { + super(modal); + } + + ngOnInit() { + this.onOpen$.subscribe(() => this._initRecord()); + } + + private _initRecord() { + this.result = { + source_library: null, + target_library: null, + overwrite_target: false + }; + } + +} diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/staff_portal_page/staff-portal-page.component.html b/Open-ILS/src/eg2/src/app/staff/admin/local/staff_portal_page/staff-portal-page.component.html new file mode 100644 index 0000000000..8649e83f2f --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/staff_portal_page/staff-portal-page.component.html @@ -0,0 +1,111 @@ +{{idlClassDef.label}} Update Succeeded + + +Update of {{idlClassDef.label}} failed + + +Delete of {{idlClassDef.label}} failed or was not allowed + + +{{idlClassDef.label}} Successfully Deleted + + +{{idlClassDef.label}} Successfully Created + + +Failed to create new {{idlClassDef.label}} + + + + + + + + + + + +
+
+ + + + +
+
+
+ + Filters Applied: {{gridFilters | json}} + Clear Filters + +
+
+
+
+ + + + + + + + + + {{configLinkLabel(row, col)}} + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/staff_portal_page/staff-portal-page.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/staff_portal_page/staff-portal-page.component.ts new file mode 100644 index 0000000000..13d285f5d8 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/staff_portal_page/staff-portal-page.component.ts @@ -0,0 +1,114 @@ +import {Component, Input, ViewChild, OnInit} from '@angular/core'; +import {Location} from '@angular/common'; +import {FormatService} from '@eg/core/format.service'; +import {AdminPageComponent} from '@eg/staff/share/admin-page/admin-page.component'; +import {ActivatedRoute} from '@angular/router'; +import {IdlService, IdlObject} from '@eg/core/idl.service'; +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 {NetService} from '@eg/core/net.service'; +import {GridCellTextGenerator} from '@eg/share/grid/grid'; +import {StringComponent} from '@eg/share/string/string.component'; +import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component'; +import {ClonePortalEntriesDialogComponent} from './clone-portal-entries-dialog.component'; +import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component'; +import {merge, Observable, empty} from 'rxjs'; + +@Component({ + templateUrl: './staff-portal-page.component.html' +}) + +export class AdminStaffPortalPageComponent extends AdminPageComponent implements OnInit { + + idlClass = 'cusppe'; + fieldOrder = 'label,entry_type,target_url,entry_text,image_url,page_col,col_pos,owner,id'; + classLabel: string; + + refreshSelected: (idlThings: IdlObject[]) => void; + createNew: () => void; + cellTextGenerator: GridCellTextGenerator; + + @ViewChild('refreshString', { static: true }) refreshString: StringComponent; + @ViewChild('refreshErrString', { static: true }) refreshErrString: StringComponent; + @ViewChild('cloneSuccessString', { static: true }) cloneSuccessString: StringComponent; + @ViewChild('cloneFailedString', { static: true }) cloneFailedString: StringComponent; + @ViewChild('cloneDialog', { static: true}) cloneDialog: ClonePortalEntriesDialogComponent; + @ViewChild('delConfirm', { static: true }) delConfirm: ConfirmDialogComponent; + + constructor( + route: ActivatedRoute, + ngLocation: Location, + format: FormatService, + idl: IdlService, + org: OrgService, + auth: AuthService, + pcrud: PcrudService, + perm: PermService, + toast: ToastService, + private net: NetService + ) { + super(route, ngLocation, format, idl, org, auth, pcrud, perm, toast); + } + + ngOnInit() { + super.ngOnInit(); + + this.defaultNewRecord = this.idl.create(this.idlClass); + this.defaultNewRecord.owner(this.auth.user().ws_ou()); + } + + cloneEntries() { + this.cloneDialog.open().subscribe( + result => { + this._handleClone(result.source_library, result.target_library, result.overwrite_target); + } + ); + } + + deleteSelected(idlThings: IdlObject[]) { + this.delConfirm.open().subscribe(confirmed => { + if (!confirmed) { return; } + super.deleteSelected(idlThings); + }); + } + + _handleClone(src: number, tgt: number, overwrite: Boolean) { + const updates: IdlObject[] = []; + + const delObs = (overwrite) ? + this.pcrud.search('cusppe', { owner: tgt }, {}, {}) : + empty(); + const newObs = this.pcrud.search('cusppe', { owner: src }, {}, {}); + merge(delObs, newObs).subscribe( + entry => { + if (entry.owner() === tgt) { + entry.isdeleted(true); + } else { + entry.owner(tgt); + entry.id(null); + entry.isnew(true); + } + updates.push(entry); + }, + err => {}, + ).add(() => { + this.pcrud.autoApply(updates).subscribe( + val => {}, + err => { + this.cloneFailedString.current() + .then(str => this.toast.danger(str)); + }, + () => { + this.cloneSuccessString.current() + .then(str => this.toast.success(str)); + this.searchOrgs = {primaryOrgId: tgt}; // change the org filter to the + // the one we just cloned into + this.grid.reload(); + } + ); + }); + } +} -- 2.11.0