LPXXX Angular Volcopy
authorBill Erickson <berickxx@gmail.com>
Tue, 23 Jun 2020 16:27:47 +0000 (12:27 -0400)
committerBill Erickson <berickxx@gmail.com>
Tue, 23 Jun 2020 16:27:47 +0000 (12:27 -0400)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/eg2/src/app/staff/cat/volcopy/copy-attrs.component.html
Open-ILS/src/eg2/src/app/staff/cat/volcopy/copy-attrs.component.ts
Open-ILS/src/eg2/src/app/staff/share/holdings/batch-item-attr.component.html
Open-ILS/src/eg2/src/app/staff/share/holdings/batch-item-attr.component.ts

index 7d1c579..4ea94ab 100644 (file)
   </eg-combobox>
 </ng-template>
 
+<!-- this one is also repeated a lot -->
+<ng-template #batchAttr let-field="field" 
+  let-label="label" let-template="template" let-displayAs="displayAs">
+  <eg-batch-item-attr 
+    [name]="field" 
+    [label]="label || copyFieldLabel(field)"
+    [displayAs]="displayAs"
+    [editInputDomId]="field + '-input'"
+    [emptyIsUnset]="true"
+    [editTemplate]="template"
+    [labelCounts]="itemAttrCounts(field)"
+    (valueCleared)="applyCopyValue(field, null)"
+    (changesSaved)="applyCopyValue(field)">
+  </eg-batch-item-attr>
+</ng-template>
 
 <!-- Copy Templates -->
 <div class="row border rounded border-dark pt-2 pb-2 bg-faint">
           domId='location-input' [required]="true" permFilter="UPDATE_COPY">
         </eg-item-location-select>
       </ng-template>
-      <eg-batch-item-attr label="Location / Collection" i18n-label
-        editInputDomId="location-input"
-        [editTemplate]="locationTemplate"
-        [labelCounts]="itemAttrCounts('location')"
-        (changesSaved)="applyCopyValue('location')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'location',template:locationTemplate}">
+      </ng-container>
     </div>
 
     <div *ngIf="displayAttr('circ_lib')">
       <ng-template #circLibTemplate>
         <eg-org-select 
-          domId="circ-lib-input"
+          domId="circ_lib-input"
           (onChange)="values['circ_lib'] = $event ? $event.id() : null"
           [limitPerms]="['UPDATE_COPY']">
         </eg-org-select>
       </ng-template>
-      <eg-batch-item-attr label="Circulating Library" i18n-label
-        editInputDomId="circ-lib-input"
-        [editTemplate]="circLibTemplate"
-        [labelCounts]="itemAttrCounts('circ_lib')"
-        (changesSaved)="circLibChanged()">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'circ_lib',template:circLibTemplate}">
+      </ng-container>
     </div>
 
     <div *ngIf="displayAttr('owning_lib')">
           [limitPerms]="['UPDATE_COPY']">
         </eg-org-select>
       </ng-template>
-      <eg-batch-item-attr label="Owning Library" i18n-label
-        editInputDomId="owning-lib-input"
-        [editTemplate]="owningLibTemplate"
-        [labelCounts]="itemAttrCounts('owning_lib')"
-        (changesSaved)="owningLibChanged()">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'owning_lib',template:owningLibTemplate}">
+      </ng-container>
     </div>
 
     <div *ngIf="displayAttr('copy_number')">
         <input type="number" class="form-control"
           id="copy-number-input" [(ngModel)]="values['copy_number']"/>
       </ng-template>
-      <eg-batch-item-attr label="Copy Number" i18n-label
-        editInputDomId="copy-number-input"
-        [emptyIsUnset]="true"
-        [editTemplate]="copyNumberTemplate"
-        [labelCounts]="itemAttrCounts('copy_number')"
-        (changesSaved)="applyCopyValue('copy_number')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'copy_number',template:copyNumberTemplate}">
+      </ng-container>
     </div>
-
   </div>
 
   <!-- COLUMN 3 -->
         <ng-container *ngTemplateOutlet="yesNoSelect;context:{field:'circulate'}">
         </ng-container>
       </ng-template>
-      <eg-batch-item-attr label="Circulate" i18n-label
-        displayAs="bool"
-        editInputDomId="circulate-input"
-        [editTemplate]="circulateTemplate"
-        [labelCounts]="itemAttrCounts('circulate')"
-        (changesSaved)="applyCopyValue('circulate')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'circulate',template:circulateTemplate,displayAs:'bool'}">
+      </ng-container>
     </div>
 
     <div *ngIf="displayAttr('holdable')">
         <ng-container *ngTemplateOutlet="yesNoSelect;context:{field:'holdable'}">
         </ng-container>
       </ng-template>
-      <eg-batch-item-attr label="Holdable" i18n-label
-        displayAs="bool"
-        editInputDomId="holdable-input"
-        [editTemplate]="holdableTemplate"
-        [labelCounts]="itemAttrCounts('holdable')"
-        (changesSaved)="applyCopyValue('holdable')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'holdable',template:holdableTemplate,displayAs:'bool'}">
+      </ng-container>
     </div>
 
     <div *ngIf="displayAttr('age_protect')">
       <ng-template #ageProtectTemplate>
-        <select class="form-control" 
-          id="age-protect-input" [(ngModel)]="values['age_protect']">
-          <option [value]="null" i18n>&lt;Unset&gt;</option>
-          <option *ngFor="let rule of ageProtectRules" 
-            value="{{rule.id()}}">{{rule.name()}}</option>
-        </select>
+        <eg-combobox domId="age_protect-input"
+          (ngModelChange)="values['age_protect'] = $event ? $event.id : null"
+          [ngModel]="values['age_protect']">
+          <eg-combobox-entry *ngFor="let rule of volcopy.ageProtectRules"
+            [entryId]="rule.id()" [entryLabel]="rule.name()">
+          </eg-combobox-entry>
+        </eg-combobox>
       </ng-template>
-      <eg-batch-item-attr label="Aged-Based Hold Protection" i18n-label
-        editInputDomId="age-protect-input"
-        [emptyIsUnset]="true"
-        [editTemplate]="ageProtectTemplate"
-        [labelCounts]="itemAttrCounts('age_protect')"
-        (changesSaved)="applyCopyValue('age_protect')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'age_protect',template:ageProtectTemplate}">
+      </ng-container>
     </div>
 
     <div *ngIf="displayAttr('floating')">
       <ng-template #floatingTemplate>
-        <select class="form-control" 
-          id="floating-input" [(ngModel)]="values['floating']">
-          <option [value]="null" i18n>&lt;Unset&gt;</option>
-          <option *ngFor="let grp of floatingGroups" 
-            value="{{grp.id()}}">{{grp.name()}}</option>
-        </select>
+        <eg-combobox domId="floating-input"
+          (ngModelChange)="values['floating'] = $event ? $event.id : null"
+          [ngModel]="values['floating']">
+          <eg-combobox-entry *ngFor="let grp of volcopy.floatingGroups"
+            [entryId]="grp.id()" [entryLabel]="grp.name()">
+          </eg-combobox-entry>
+        </eg-combobox>
       </ng-template>
-      <eg-batch-item-attr label="Floating" i18n-label
-        editInputDomId="floating-input"
-        [emptyIsUnset]="true"
-        [editTemplate]="floatingTemplate"
-        [labelCounts]="itemAttrCounts('floating')"
-        (changesSaved)="applyCopyValue('floating')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'floating',template:floatingTemplate}">
+      </ng-container>
     </div>
 
     <div *ngIf="displayAttr('loan_duration')">
           <option value="3" i18n>{{loanDurationLong.text}}</option>
         </select>
       </ng-template>
-      <eg-batch-item-attr label="Loan Duration" i18n-label
-        editInputDomId="loan-duration-input"
-        [emptyIsUnset]="true"
-        [editTemplate]="loanDurationTemplate"
-        [labelCounts]="itemAttrCounts('loan_duration')"
-        (changesSaved)="applyCopyValue('loan_duration')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'loan_duration',template:loanDurationTemplate}">
+      </ng-container>
     </div>
 
     <div *ngIf="displayAttr('fine_level')">
           <option value="3" i18n>{{fineLevelHigh.text}}</option>
         </select>
       </ng-template>
-      <eg-batch-item-attr label="Fine Level" i18n-label
-        editInputDomId="fine-level-input"
-        [emptyIsUnset]="true"
-        [editTemplate]="fineLevelTemplate"
-        [labelCounts]="itemAttrCounts('fine_level')"
-        (changesSaved)="applyCopyValue('fine_level')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'fine_level',template:fineLevelTemplate}">
+      </ng-container>
     </div>
 
     <div *ngIf="displayAttr('circ_as_type')">
       <ng-template #circAsTypeTemplate>
-        <select class="form-control" [(ngModel)]="values['circ_as_type']">
-          <option [value]="null" i18n>&lt;Unset&gt;</option>
-          <option *ngFor="let map of itemTypeMaps"
-            value="{{map.code()}}">{{map.value()}}</option>
-        </select>
+        <eg-combobox domId="circ-as-type-input"
+          (ngModelChange)="values['circ_as_type'] = $event ? $event.id : null"
+          [ngModel]="values['circ_as_type']">
+          <eg-combobox-entry *ngFor="let map of volcopy.itemTypeMaps"
+            [entryId]="map.code()" [entryLabel]="map.value()">
+          </eg-combobox-entry>
+        </eg-combobox>
       </ng-template>
-      <eg-batch-item-attr label="Circulate as Type" i18n-label
-        [emptyIsUnset]="true"
-        [editTemplate]="circAsTypeTemplate"
-        [labelCounts]="itemAttrCounts('circ_as_type')"
-        (changesSaved)="applyCopyValue('circ_as_type')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'circ_as_type',template:circAsTypeTemplate}">
+      </ng-container>
     </div>
 
     <div *ngIf="displayAttr('circ_modifier')">
             value="{{mod.code()}}">{{mod.name()}}</option>
         </select>
       </ng-template>
-      <eg-batch-item-attr label="Circulion Modifier" i18n-label
-        [emptyIsUnset]="true"
-        [editTemplate]="circModifierTemplate"
-        [labelCounts]="itemAttrCounts('circ_modifier')"
-        (changesSaved)="applyCopyValue('circ_modifier')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'circ_modifier',template:circModifierTemplate}">
+      </ng-container>
     </div>
 
   </div>
         <ng-container *ngTemplateOutlet="yesNoSelect;context:{field:'deposit'}">
         </ng-container>
       </ng-template>
-      <eg-batch-item-attr label="Deposit" i18n-label
-        displayAs="bool"
-        editInputDomId="deposit-input"
-        [editTemplate]="depositTemplate"
-        [labelCounts]="itemAttrCounts('deposit')"
-        (changesSaved)="applyCopyValue('deposit')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'deposit',template:depositTemplate,displayAs:'bool'}">
+      </ng-container>
     </div>
 
     <div *ngIf="displayAttr('deposit_amount')">
         <input type="number" class="form-control" 
           id="deposit-amount-input" [(ngModel)]="values['deposit_amount']"/>
       </ng-template>
-      <eg-batch-item-attr label="Deposit Amount" i18n-label
-        displayAs="currency"
-        editInputDomId="deposit-amount-input"
-        [editTemplate]="depositAmountTemplate"
-        [labelCounts]="itemAttrCounts('deposit_amount')"
-        (changesSaved)="applyCopyValue('deposit_amount')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'deposit_amount',template:depositAmountTemplate,displayAs:'currency'}">
+      </ng-container>
     </div>
 
     <div *ngIf="displayAttr('price')">
         <input type="number" class="form-control" 
           id="price-input" [(ngModel)]="values['price']"/>
       </ng-template>
-      <eg-batch-item-attr label="Price" i18n-label
-        displayAs="currency"
-        editInputDomId="price-input"
-        [editTemplate]="priceTemplate"
-        [labelCounts]="itemAttrCounts('price')"
-        (changesSaved)="applyCopyValue('price')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'price',template:priceTemplate,displayAs:'currency'}">
+      </ng-container>
     </div>
 
     <div *ngIf="displayAttr('opac_visible')">
         <ng-container *ngTemplateOutlet="yesNoSelect;context:{field:'opac_visible'}">
         </ng-container>
       </ng-template>
-      <eg-batch-item-attr label="OPAC Visible" i18n-label
-        displayAs="bool"
-        editInputDomId="opac_visible-input"
-        [editTemplate]="opacVisibleTemplate"
-        [labelCounts]="itemAttrCounts('opac_visible')"
-        (changesSaved)="applyCopyValue('opac_visible')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'opac_visible',template:opacVisibleTemplate,displayAs:'bool'}">
+      </ng-container>
     </div>
 
     <div *ngIf="displayAttr('ref')">
         <ng-container *ngTemplateOutlet="yesNoSelect;context:{field:'ref'}">
         </ng-container>
       </ng-template>
-      <eg-batch-item-attr label="Reference" i18n-label
-        displayAs="bool"
-        editInputDomId="ref-input"
-        [editTemplate]="refTemplate"
-        [labelCounts]="itemAttrCounts('ref')"
-        (changesSaved)="applyCopyValue('ref')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'ref',template:refTemplate,displayAs:'bool'}">
+      </ng-container>
     </div>
 
     <div *ngIf="displayAttr('cost')">
         <input type="number" class="form-control" 
           id="cost-input" [(ngModel)]="values['cost']"/>
       </ng-template>
-      <eg-batch-item-attr label="Acquisition Cost" i18n-label
-        displayAs="currency"
-        editInputDomId="cost-input"
-        [emptyIsUnset]="true"
-        [editTemplate]="costTemplate"
-        [labelCounts]="itemAttrCounts('cost')"
-        (changesSaved)="applyCopyValue('cost')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'cost',template:costTemplate,displayAs:'currency'}">
+      </ng-container>
     </div>
 
     <div *ngIf="displayAttr('mint_condition')">
           <option value="f" i18n>{{mintConditionNo.text}}</option>
         </select>
       </ng-template>
-      <eg-batch-item-attr label="Quality" i18n-label
-        editInputDomId="mint-condition-input"
-        [emptyIsUnset]="true"
-        [editTemplate]="mintConditionTemplate"
-        [labelCounts]="itemAttrCounts('mint_condition')"
-        (changesSaved)="applyCopyValue('mint_condition')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'mint_condition',template:mintConditionTemplate}">
+      </ng-container>
     </div>
 
   </div>
     </div>
 
     <ng-container *ngIf="displayAttr('statcats')">
-      <div *ngFor="let cat of statCats(); let idx = index">
+      <div *ngFor="let cat of statCats()">
         <ng-template #statCatTemplate>
-          <eg-combobox domId="stat-cat-input-{{idx}}"
+          <eg-combobox domId="stat-cat-input-{{cat.id()}}"
             (ngModelChange)="statCatValues[cat.id()] = $event ? $event.id : null"
             [ngModel]="statCatValues[cat.id()]">
             <eg-combobox-entry *ngFor="let entry of cat.entries()"
           </eg-combobox>
         </ng-template>
         <eg-batch-item-attr label="{{cat.name()}} ({{orgSn(cat.owner())}})" i18n-label
-          editInputDomId="stat-cat-input-{{idx}}"
+          name="stat_cat_{{cat.id()}}" editInputDomId="stat-cat-input-{{cat.id()}}"
           [emptyIsUnset]="true"
           [editTemplate]="statCatTemplate"
           [labelCounts]="statCatCounts(cat.id())"
index a8ec40b..44d2858 100644 (file)
@@ -1,4 +1,5 @@
-import {Component, Input, OnInit, AfterViewInit, ViewChild, Renderer2} from '@angular/core';
+import {Component, Input, OnInit, AfterViewInit, ViewChild,
+    QueryList, ViewChildren} from '@angular/core';
 import {Router, ActivatedRoute, ParamMap} from '@angular/router';
 import {tap} from 'rxjs/operators';
 import {IdlObject, IdlService} from '@eg/core/idl.service';
@@ -16,6 +17,7 @@ import {StringComponent} from '@eg/share/string/string.component';
 import {CopyAlertsDialogComponent
     } from '@eg/staff/share/holdings/copy-alerts-dialog.component';
 import {ComboboxComponent, ComboboxEntry} from '@eg/share/combobox/combobox.component';
+import {BatchItemAttrComponent} from '@eg/staff/share/holdings/batch-item-attr.component';
 
 @Component({
   selector: 'eg-copy-attrs',
@@ -66,10 +68,12 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit {
     @ViewChild('copyTemplateCbox', {static: false})
         copyTemplateCbox: ComboboxComponent;
 
+    @ViewChildren(BatchItemAttrComponent)
+        batchAttrs: QueryList<BatchItemAttrComponent>;
+
     constructor(
         private router: Router,
         private route: ActivatedRoute,
-        private renderer: Renderer2,
         private evt: EventService,
         private idl: IdlService,
         private org: OrgService,
@@ -77,9 +81,9 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit {
         private auth: AuthService,
         private pcrud: PcrudService,
         private holdings: HoldingsService,
-        private volcopy: VolCopyService,
         private format: FormatService,
-        private store: StoreService
+        private store: StoreService,
+        public  volcopy: VolCopyService
     ) { }
 
     ngOnInit() {
@@ -221,7 +225,13 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit {
     }
 
     applyCopyValue(field: string, value?: any) {
-        if (value === undefined) { value = this.values[field]; }
+        if (value === undefined) {
+            value = this.values[field];
+        } else {
+            this.values[field] = value;
+        }
+
+        // TODO: handle circ_lib, owning_lib changes specially
 
         console.debug('APPLYING', field, value);
 
@@ -233,18 +243,6 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit {
         });
     }
 
-    circLibChanged() {
-        // TODO other stuff happens here?
-        this.applyCopyValue('circ_lib');
-    }
-
-    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) {
@@ -312,9 +310,20 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit {
         });
     }
 
+    saveTemplate() {
+        this.batchAttrs.forEach(comp => {
+            console.log(comp.editInputDomId);
+        });
+    }
+
     displayAttr(field: string): boolean {
         return this.volcopy.defaults.hidden[field] !== true;
     }
+
+    copyFieldLabel(field: string): string {
+        const def = this.idl.classes.acp.field_map[field];
+        return def ? def.label : '';
+    }
 }
 
 
index e8f00a2..f364cd5 100644 (file)
@@ -36,6 +36,7 @@
     <div class="mt-1">
       <button class="btn btn-outline-dark" (click)="save()" i18n>Apply</button>
       <button class="btn btn-outline-dark ml-1" (click)="cancel()" i18n>Cancel</button>
+      <button class="btn btn-outline-dark ml-1" (click)="clear()" i18n>Clear</button>
     </div>
   </ng-container>
 </div>
index 408ebf9..a725454 100644 (file)
@@ -21,6 +21,10 @@ export class BatchItemAttrComponent {
     // Main display label, e.g. "Circulation Modifier"
     @Input() label: string;
 
+    // Optional.  Useful for exracting information (i.e. hasChanges)
+    // on a specific field from a set of batch attr components.
+    @Input() name: string;
+
     // Maps display labels to the number of items that have the label.
     // e.g. {"Stacks": 4, "Display": 12}
     @Input() labelCounts: {[label: string]: number} = {};
@@ -44,6 +48,7 @@ export class BatchItemAttrComponent {
 
     @Output() changesSaved: EventEmitter<void> = new EventEmitter<void>();
     @Output() changesCanceled: EventEmitter<void> = new EventEmitter<void>();
+    @Output() valueCleared: EventEmitter<void> = new EventEmitter<void>();
 
     // Is the editTtemplate visible?
     editing = false;
@@ -63,6 +68,13 @@ export class BatchItemAttrComponent {
         this.changesCanceled.emit();
     }
 
+    clear() {
+        this.hasChanged = true;
+        this.editing = false;
+        this.valueCleared.emit();
+    }
+
+
     toggleEditMode() {
         if (this.readOnly) { return; }