From e6ce65d3b8b0188b4c30bc31abce9e2cbba40336 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Mon, 29 Oct 2018 12:31:26 -0400 Subject: [PATCH] LP#1800481 Vandelay import form templates Support saving MARC Import form values as named templates. Values are stored as (by defualt) workstation settings. A template may be selected as the default and templates may be deleted. Includes release notes update angular vandelay. Signed-off-by: Bill Erickson Signed-off-by: Dan Wells --- .../app/share/combobox/combobox.component.ts | 6 + .../staff/cat/vandelay/import.component.html | 48 +++++-- .../staff/cat/vandelay/import.component.ts | 134 +++++++++++++++++- Open-ILS/src/sql/Pg/950.data.seed-values.sql | 10 ++ .../YYYY.data.vandelay-template-settings.sql | 15 ++ .../Cataloging/vandelay-angular-port.adoc | 7 + 6 files changed, 210 insertions(+), 10 deletions(-) create mode 100644 Open-ILS/src/sql/Pg/upgrade/YYYY.data.vandelay-template-settings.sql diff --git a/Open-ILS/src/eg2/src/app/share/combobox/combobox.component.ts b/Open-ILS/src/eg2/src/app/share/combobox/combobox.component.ts index e8adff329a..323623c3a0 100644 --- a/Open-ILS/src/eg2/src/app/share/combobox/combobox.component.ts +++ b/Open-ILS/src/eg2/src/app/share/combobox/combobox.component.ts @@ -132,6 +132,12 @@ export class ComboboxComponent implements OnInit { this.applySelection(); } + // Manually set the selected value by ID. + // This does NOT fire the onChange handler. + applyEntryId(entryId: any) { + this.selected = this.entrylist.filter(e => e.id === entryId)[0]; + } + onBlur() { // When the selected value is a string it means we have either // no value (user cleared the input) or a free-text value. diff --git a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/import.component.html b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/import.component.html index c85233254c..58b3bb015d 100644 --- a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/import.component.html +++ b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/import.component.html @@ -10,14 +10,41 @@

MARC File Upload

+
+
+ +
+
+ + +
+
+ + + +
+
+
- @@ -31,7 +58,8 @@
- @@ -68,7 +96,8 @@
- Holdings Import Profile
- Merge Profile
- @@ -118,7 +149,8 @@
- diff --git a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/import.component.ts b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/import.component.ts index 3b36f6a341..74341b929a 100644 --- a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/import.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/import.component.ts @@ -6,13 +6,33 @@ import {EventService} from '@eg/core/event.service'; import {OrgService} from '@eg/core/org.service'; import {AuthService} from '@eg/core/auth.service'; import {ToastService} from '@eg/share/toast/toast.service'; -import {ComboboxEntry} from '@eg/share/combobox/combobox.component'; +import {ComboboxComponent, + ComboboxEntry} from '@eg/share/combobox/combobox.component'; import {VandelayService, VandelayImportSelection, VANDELAY_UPLOAD_PATH} from './vandelay.service'; import {HttpClient, HttpRequest, HttpEventType} from '@angular/common/http'; import {HttpResponse, HttpErrorResponse} from '@angular/common/http'; import {ProgressInlineComponent} from '@eg/share/dialog/progress-inline.component'; import {Subject} from 'rxjs/Subject'; +import {ServerStoreService} from '@eg/core/server-store.service'; + +const TEMPLATE_SETTING_NAME = 'eg.cat.vandelay.import.templates'; + +const TEMPLATE_ATTRS = [ + 'recordType', + 'selectedBibSource', + 'selectedMatchSet', + 'mergeOnExact', + 'importNonMatch', + 'mergeOnBestMatch', + 'mergeOnSingleMatch', + 'autoOverlayAcqCopies', + 'selectedHoldingsProfile', + 'selectedMergeProfile', + 'selectedFallThruMergeProfile', + 'selectedTrashGroups', + 'minQualityRatio' +]; interface ImportOptions { session_key: string; @@ -25,6 +45,7 @@ interface ImportOptions { merge_profile?: any; fall_through_merge_profile?: any; strip_field_groups?: number[]; + match_quality_ratio: number, exit_early: boolean; } @@ -77,6 +98,10 @@ export class ImportComponent implements OnInit, AfterViewInit, OnDestroy { // Optional enqueue/import tracker session name. sessionName: string; + selectedTemplate: string; + formTemplates: {[name: string]: any}; + newTemplateName: string; + @ViewChild('fileSelector') private fileSelector; @ViewChild('uploadProgress') private uploadProgress: ProgressInlineComponent; @@ -85,6 +110,22 @@ export class ImportComponent implements OnInit, AfterViewInit, OnDestroy { @ViewChild('importProgress') private importProgress: ProgressInlineComponent; + // Need these refs so values can be applied via external stimuli + @ViewChild('formTemplateSelector') + private formTemplateSelector: ComboboxComponent; + @ViewChild('recordTypeSelector') + private recordTypeSelector: ComboboxComponent; + @ViewChild('bibSourceSelector') + private bibSourceSelector: ComboboxComponent; + @ViewChild('matchSetSelector') + private matchSetSelector: ComboboxComponent; + @ViewChild('holdingsProfileSelector') + private holdingsProfileSelector: ComboboxComponent; + @ViewChild('mergeProfileSelector') + private mergeProfileSelector: ComboboxComponent; + @ViewChild('fallThruMergeProfileSelector') + private fallThruMergeProfileSelector: ComboboxComponent; + constructor( private http: HttpClient, private toast: ToastService, @@ -92,6 +133,7 @@ export class ImportComponent implements OnInit, AfterViewInit, OnDestroy { private net: NetService, private auth: AuthService, private org: OrgService, + private store: ServerStoreService, private vandelay: VandelayService ) { this.applyDefaults(); @@ -102,6 +144,7 @@ export class ImportComponent implements OnInit, AfterViewInit, OnDestroy { this.selectedBibSource = 1; // default to system local this.recordType = 'bib'; this.bibTrashGroups = []; + this.formTemplates = {}; if (this.vandelay.importSelection) { @@ -161,12 +204,36 @@ export class ImportComponent implements OnInit, AfterViewInit, OnDestroy { this.vandelay.getBibTrashGroups().then( groups => this.bibTrashGroups = groups), this.org.settings(['vandelay.default_match_set']).then( - s => this.defaultMatchSet = s['vandelay.default_match_set']) + s => this.defaultMatchSet = s['vandelay.default_match_set']), + this.loadTemplates() ]; return Promise.all(promises); } + loadTemplates() { + this.store.getItem(TEMPLATE_SETTING_NAME).then( + templates => { + this.formTemplates = templates || {}; + + Object.keys(this.formTemplates).forEach(name => { + if (this.formTemplates[name].default) { + this.selectedTemplate = name; + } + }); + } + ); + } + + formatTemplateEntries(): ComboboxEntry[] { + const entries = []; + + Object.keys(this.formTemplates || {}).forEach( + name => entries.push({id: name, label: name})); + + return entries; + } + // Format typeahead data sets formatEntries(etype: string): ComboboxEntry[] { const rtype = this.recordType; @@ -469,6 +536,7 @@ export class ImportComponent implements OnInit, AfterViewInit, OnDestroy { merge_profile: this.selectedMergeProfile, fall_through_merge_profile: this.selectedFallThruMergeProfile, strip_field_groups: this.selectedTrashGroups, + match_quality_ratio: this.minQualityRatio, exit_early: true }; @@ -487,5 +555,67 @@ export class ImportComponent implements OnInit, AfterViewInit, OnDestroy { openQueue() { console.log('opening queue ' + this.activeQueueId); } + + saveTemplate() { + + const template = {}; + TEMPLATE_ATTRS.forEach(key => template[key] = this[key]); + + console.debug("Saving import profile", template); + + this.formTemplates[this.selectedTemplate] = template; + return this.store.setItem(TEMPLATE_SETTING_NAME, this.formTemplates); + } + + markTemplateDefault() { + + Object.keys(this.formTemplates).forEach( + name => delete this.formTemplates.default + ); + + this.formTemplates[this.selectedTemplate].default = true; + + return this.store.setItem(TEMPLATE_SETTING_NAME, this.formTemplates); + } + + templateSelectorChange(entry: ComboboxEntry) { + + if (!entry) { + this.selectedTemplate = ''; + return; + } + + this.selectedTemplate = entry.label; // label == name + + if (entry.freetext) { + // User is entering a new template name. + // Nothing to apply. + return; + } + + // User selected an existing template, apply it to the form. + + const template = this.formTemplates[entry.id]; + + // Copy the template values into "this" + TEMPLATE_ATTRS.forEach(key => this[key] = template[key]); + + // Some values must be manually passed to the combobox'es + + this.recordTypeSelector.applyEntryId(this.recordType); + this.bibSourceSelector.applyEntryId(this.selectedBibSource); + this.matchSetSelector.applyEntryId(this.selectedMatchSet); + this.holdingsProfileSelector + .applyEntryId(this.selectedHoldingsProfile); + this.mergeProfileSelector.applyEntryId(this.selectedMergeProfile); + this.fallThruMergeProfileSelector + .applyEntryId(this.selectedFallThruMergeProfile); + } + + deleteTemplate() { + delete this.formTemplates[this.selectedTemplate]; + this.formTemplateSelector.selected = null; + return this.store.setItem(TEMPLATE_SETTING_NAME, this.formTemplates); + } } diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql index e8ef9ed3f6..c10e34fe62 100644 --- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql +++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql @@ -19520,6 +19520,16 @@ VALUES ( 'bool' ); +INSERT INTO config.workstation_setting_type (name, grp, datatype, label) +VALUES ( + 'eg.cat.vandelay.import.templates', 'cat', 'object', + oils_i18n_gettext( + 'eg.cat.vandelay.import.templates', + 'Vandelay Import Form Templates', + 'cwst', 'label' + ) +); + INSERT into config.workstation_setting_type (name, grp, datatype, label) VALUES ( diff --git a/Open-ILS/src/sql/Pg/upgrade/YYYY.data.vandelay-template-settings.sql b/Open-ILS/src/sql/Pg/upgrade/YYYY.data.vandelay-template-settings.sql new file mode 100644 index 0000000000..bd104ef32d --- /dev/null +++ b/Open-ILS/src/sql/Pg/upgrade/YYYY.data.vandelay-template-settings.sql @@ -0,0 +1,15 @@ +BEGIN; + +SELECT evergreen.upgrade_deps_block_check('YYYY', :eg_version); + +INSERT INTO config.workstation_setting_type (name, grp, datatype, label) +VALUES ( + 'eg.cat.vandelay.import.templates', 'cat', 'object', + oils_i18n_gettext( + 'eg.cat.vandelay.import.templates', + 'Vandelay Import Form Templates', + 'cwst', 'label' + ) +); + +COMMIT; diff --git a/docs/RELEASE_NOTES_NEXT/Cataloging/vandelay-angular-port.adoc b/docs/RELEASE_NOTES_NEXT/Cataloging/vandelay-angular-port.adoc index 6b5173b044..2baa53b3c5 100644 --- a/docs/RELEASE_NOTES_NEXT/Cataloging/vandelay-angular-port.adoc +++ b/docs/RELEASE_NOTES_NEXT/Cataloging/vandelay-angular-port.adoc @@ -6,6 +6,13 @@ Angular(6) instead of Dojo. The functionality is consistent with the previous version of the interface, with minor UI adjustments to match the Angular style, plus one new interface called 'Recent Imports' +Import Templates +++++++++++++++++ + +Users may now saves sets of import attributes from the MARC import form as +named templates. Users may select a default template, applied on page load +by default, and users may delete existing templates. + Recent Imports Tab ++++++++++++++++++ -- 2.43.2