From 6a58e9b9c47731f093adc462403805826275e7fa Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Thu, 18 Jun 2020 12:24:53 -0400 Subject: [PATCH] LPXXX Angular Volcopy Signed-off-by: Bill Erickson --- .../src/app/share/combobox/combobox.component.ts | 2 +- .../item-location-select.component.ts | 2 +- .../app/share/org-select/org-select.component.ts | 2 +- .../staff/cat/volcopy/copy-attrs.component.html | 18 ++++ .../app/staff/cat/volcopy/copy-attrs.component.ts | 109 +++++++++++++++++++-- .../app/staff/cat/volcopy/vol-edit.component.ts | 4 +- .../src/app/staff/cat/volcopy/volcopy.component.ts | 14 ++- .../src/eg2/src/app/staff/cat/volcopy/volcopy.ts | 15 ++- 8 files changed, 153 insertions(+), 13 deletions(-) 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 bfbeb4da3e..d4dd6f1c97 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 @@ -35,6 +35,7 @@ export interface ComboboxEntry { }] }) export class ComboboxComponent implements ControlValueAccessor, OnInit { + static domIdAuto = 0; selected: ComboboxEntry; click$: Subject; @@ -42,7 +43,6 @@ export class ComboboxComponent implements ControlValueAccessor, OnInit { @ViewChild('instance', { static: true }) instance: NgbTypeahead; - static domIdAuto = 0; @Input() domId = 'eg-combobox-' + ComboboxComponent.domIdAuto++; // Applies a name attribute to the input. diff --git a/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.ts b/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.ts index 2ea5ef860d..d5a3baf4e0 100644 --- a/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.ts +++ b/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.ts @@ -30,6 +30,7 @@ import {StringComponent} from '@eg/share/string/string.component'; }) export class ItemLocationSelectComponent implements OnInit, AfterViewInit, ControlValueAccessor { + static domIdAuto = 0; // Limit copy locations to those owned at or above org units where // the user has work permissions for the provided permission code. @@ -45,7 +46,6 @@ export class ItemLocationSelectComponent @Input() required: boolean; - static domIdAuto = 0; @Input() domId = 'eg-item-location-select-' + ItemLocationSelectComponent.domIdAuto++; diff --git a/Open-ILS/src/eg2/src/app/share/org-select/org-select.component.ts b/Open-ILS/src/eg2/src/app/share/org-select/org-select.component.ts index 4336e56404..431ac60e67 100644 --- a/Open-ILS/src/eg2/src/app/share/org-select/org-select.component.ts +++ b/Open-ILS/src/eg2/src/app/share/org-select/org-select.component.ts @@ -24,6 +24,7 @@ interface OrgDisplay { templateUrl: './org-select.component.html' }) export class OrgSelectComponent implements OnInit { + static domIdAuto = 0; selected: OrgDisplay; hidden: number[] = []; @@ -40,7 +41,6 @@ export class OrgSelectComponent implements OnInit { @Input() stickySetting: string; // ID to display in the DOM for this selector - static domIdAuto = 0; @Input() domId = 'eg-org-select-' + OrgSelectComponent.domIdAuto++; // Org unit field displayed in the selector diff --git a/Open-ILS/src/eg2/src/app/staff/cat/volcopy/copy-attrs.component.html b/Open-ILS/src/eg2/src/app/staff/cat/volcopy/copy-attrs.component.html index eae85ece13..9dcccf581e 100644 --- a/Open-ILS/src/eg2/src/app/staff/cat/volcopy/copy-attrs.component.html +++ b/Open-ILS/src/eg2/src/app/staff/cat/volcopy/copy-attrs.component.html @@ -432,6 +432,24 @@

Statistics

+ +
+ + + + + +
+
diff --git a/Open-ILS/src/eg2/src/app/staff/cat/volcopy/copy-attrs.component.ts b/Open-ILS/src/eg2/src/app/staff/cat/volcopy/copy-attrs.component.ts index ccfe284ff1..b955cee82c 100644 --- a/Open-ILS/src/eg2/src/app/staff/cat/volcopy/copy-attrs.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/cat/volcopy/copy-attrs.component.ts @@ -25,10 +25,15 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit { // Some values are scalar, some IdlObjects depending on copy fleshyness. values: {[field: string]: any} = {}; + // Map of stat ID to entry ID. + statCatValues: {[statId: number]: number} = {}; + ageProtectRules: IdlObject[] = []; floatingGroups: IdlObject[] = []; itemTypeMaps: IdlObject[] = []; circModifiers: IdlObject[] = []; + statCats: IdlObject[] = []; + statCatEntryMap: {[id: number]: IdlObject} = {}; // entry id => entry loanDurationLabelMap: {[level: number]: string} = {}; fineLevelLabelMap: {[level: number]: string} = {}; @@ -94,7 +99,7 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit { }).then(_ => { return this.pcrud.retrieveAll('cfg') - .pipe(tap(rule => this.floatingGroups.push(rule))).toPromise() + .pipe(tap(rule => this.floatingGroups.push(rule))).toPromise(); }).then(_ => { @@ -104,7 +109,7 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit { }).then(_ => { return this.pcrud.retrieveAll('ccm') - .pipe(tap(rule => this.circModifiers.push(rule))).toPromise() + .pipe(tap(rule => this.circModifiers.push(rule))).toPromise(); }).then(_ => { @@ -114,13 +119,72 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit { }).then(_ => { return this.pcrud.retrieveAll('citm') - .pipe(tap(itemType => this.itemTypeMaps.push(itemType))).toPromise() + .pipe(tap(itemType => this.itemTypeMaps.push(itemType))).toPromise(); }).then(_ => { this.itemTypeMaps = this.itemTypeMaps.sort( (a, b) => a.value() < b.value() ? -1 : 1); + + }).then(_ => { + + return this.net.request('open-ils.circ', + 'open-ils.circ.stat_cat.asset.retrieve.all', + this.auth.token(), this.auth.user().ws_ou() + ).toPromise().then(stats => this.statCats = stats); + + }).then(_ => { + + // Sort most local to the front of the list. + this.statCats = this.statCats.sort((s1, s2) => { + const d1 = this.org.get(s1.owner()).ou_type().depth(); + const d2 = this.org.get(s2.owner()).ou_type().depth(); + + if (d1 > d2) { + return -1; + } else if (d1 < d2) { + return 1; + } else { + return s1.name() < s2.name() ? -1 : 1; + } + }); + + this.statCats.forEach(cat => { + cat.entries().forEach( + entry => this.statCatEntryMap[entry.id()] = entry); + }); + }); + } + + orgSn(orgId: number): string { + return orgId ? this.org.get(orgId).shortname() : ''; + } + + statCatCounts(catId: number): {[value: string]: number} { + catId = Number(catId); + const counts = {}; + + this.context.copyList().forEach(copy => { + const entry = copy.stat_cat_entries() + .filter(e => e.stat_cat() === catId)[0]; + + let value = ''; + if (entry) { + if (this.statCatEntryMap[entry.id()]) { + value = this.statCatEntryMap[entry.id()].value(); + } else { + // Map to a remote stat cat. Ignore. + return; + } + } + + if (counts[value] === undefined) { + counts[value] = 0; + } + counts[value]++; }); + + return counts; } itemAttrCounts(field: string): {[value: string]: number} { @@ -131,7 +195,7 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit { if (counts[value] === undefined) { counts[value] = 0; - }; + } counts[value]++; }); @@ -147,11 +211,11 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit { ' : ' + copy.call_number().label(); } - let value = copy[field](); + const value = copy[field](); if (!value && value !== 0) { return ''; } - switch(field) { + switch (field) { case 'status': return this.volcopy.copyStatuses[value].name(); @@ -228,8 +292,41 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit { owningLibChanged() { // TODO + // copies.ischanged(true); console.log('OWNING LIB ', this.values['owning_lib']); } + + + // Create or modify a stat cat entry for each copy that does not + // already match the new value. + statCatChanged(catId: number) { + catId = Number(catId); + + const entryId = this.statCatValues[catId]; + this.context.copyList().forEach(copy => { + + let entry = copy.stat_cat_entries() + .filter(e => e.stat_cat() === catId)[0]; + + if (entry) { + if (entry.id() === entryId) { + // Requested mapping already exists. + return; + } + } else { + + // Copy has no entry for this stat cat yet. + entry = this.idl.create('asce'); + entry.stat_cat(catId); + copy.stat_cat_entries().push(entry); + } + + entry.id(entryId); + entry.value(this.statCatEntryMap[entryId].value()); + + copy.ischanged(true); + }); + } } diff --git a/Open-ILS/src/eg2/src/app/staff/cat/volcopy/vol-edit.component.ts b/Open-ILS/src/eg2/src/app/staff/cat/volcopy/vol-edit.component.ts index c5da3cce7d..44f6db440d 100644 --- a/Open-ILS/src/eg2/src/app/staff/cat/volcopy/vol-edit.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/cat/volcopy/vol-edit.component.ts @@ -379,7 +379,7 @@ export class VolEditComponent implements OnInit { } barcodeChanged(copy: IdlObject, barcode: string) { - copy.barcode(barcode); + // note: copy.barcode(barcode) applied via ngModel copy.ischanged(true); copy._dupe_barcode = false; @@ -412,7 +412,6 @@ export class VolEditComponent implements OnInit { } deleteOneCopy(copyNode: HoldingsTreeNode) { - const targetCopy = copyNode.target; const orgNodes = this.context.orgNodes(); @@ -462,6 +461,7 @@ export class VolEditComponent implements OnInit { } deleteOneVol(volNode: HoldingsTreeNode) { + let deleteVolIdx = null; const targetVol = volNode.target; diff --git a/Open-ILS/src/eg2/src/app/staff/cat/volcopy/volcopy.component.ts b/Open-ILS/src/eg2/src/app/staff/cat/volcopy/volcopy.component.ts index 5932ffb81a..7d493f12ca 100644 --- a/Open-ILS/src/eg2/src/app/staff/cat/volcopy/volcopy.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/cat/volcopy/volcopy.component.ts @@ -16,7 +16,8 @@ import {VolCopyService} from './volcopy.service'; const COPY_FLESH = { flesh: 1, flesh_fields: { - acp: ['call_number', 'location', 'parts', 'creator', 'editor'] + acp: ['call_number', 'location', 'parts', + 'creator', 'editor', 'stat_cat_entries'] } }; @@ -317,6 +318,17 @@ export class VolCopyComponent implements OnInit { volumes.push(vol); }); + // De-flesh before posting + volumes.forEach(vol => { + vol.copies().forEach(copy => { + ['editor', 'creator', 'location'].forEach(field => { + if (typeof copy[field]() === 'object') { + copy[field](copy[field]().id()); + } + }); + }); + }); + if (volumes.length > 0) { this.saveApi(volumes); } else { diff --git a/Open-ILS/src/eg2/src/app/staff/cat/volcopy/volcopy.ts b/Open-ILS/src/eg2/src/app/staff/cat/volcopy/volcopy.ts index 5d745fb2a0..d751c7eda5 100644 --- a/Open-ILS/src/eg2/src/app/staff/cat/volcopy/volcopy.ts +++ b/Open-ILS/src/eg2/src/app/staff/cat/volcopy/volcopy.ts @@ -170,11 +170,24 @@ export class VolCopyContext { o1.target.shortname() < o2.target.shortname() ? -1 : 1); } + // Changes pending and no unresolved issues. isSaveable(): boolean { const dupeBc = this.copyList().filter(c => c._dupe_barcode).length; if (dupeBc) { return false; } - return true; + const modified = (o: IdlObject): boolean => { + return o.isnew() || o.ischanged() || o.isdeleted(); + }; + + if (this.volNodes().filter(n => modified(n.target)).length > 0) { + return true; + } + + if (this.copyList().filter(c => modified(c)).length > 0) { + return true; + } + + return false; } } -- 2.11.0