LPXXX Angular Volcopy
authorBill Erickson <berickxx@gmail.com>
Thu, 2 Jul 2020 14:42:15 +0000 (10:42 -0400)
committerBill Erickson <berickxx@gmail.com>
Thu, 2 Jul 2020 14:42:15 +0000 (10:42 -0400)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/eg2/src/app/staff/cat/volcopy/copy-attrs.component.ts
Open-ILS/src/eg2/src/app/staff/cat/volcopy/volcopy.component.ts
Open-ILS/src/eg2/src/app/staff/cat/volcopy/volcopy.service.ts
Open-ILS/src/eg2/src/app/staff/share/holdings/copy-tags-dialog.component.html
Open-ILS/src/eg2/src/app/staff/share/holdings/copy-tags-dialog.component.ts

index 241a25f..2097f00 100644 (file)
@@ -372,23 +372,28 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit {
     }
 
     openCopyTags() {
-        this.copyTagsDialog.mode = 'create';
         this.copyTagsDialog.inPlaceMode = true;
+        this.copyTagsDialog.copyIds = this.context.copyList().map(c => c.id());
+        console.log('IDS', this.copyTagsDialog.copyIds);
 
         this.copyTagsDialog.open({size: 'lg'}).subscribe(newTags => {
             if (!newTags || newTags.length === 0) { return; }
 
             newTags.forEach(tag => {
                 this.context.copyList().forEach(copy => {
-                    console.log('ADDING TAG ', tag);
-                    /*
-                    const a = this.idl.clone(newTag);
-                    a.isnew(true);
-                    a.copy(copy.id());
-                    if (!copy.copy_alerts()) { copy.copy_alerts([]); }
-                    copy.copy_alerts().push(a);
+
+                    if (copy.tags().filter(
+                        map => map.tag().id() === tag.id()).length > 0) {
+                        return; // map already exists
+                    }
+
+                    const map = this.idl.create('acptcm');
+                    map.isnew(true);
+                    map.copy(copy.id());
+                    map.tag(tag);
+
+                    copy.tags().push(map);
                     copy.ischanged(true);
-                    */
                 });
             });
         });
index 46d356e..d16abb3 100644 (file)
@@ -17,8 +17,12 @@ import {NgbTabset, NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap';
 const COPY_FLESH = {
     flesh: 1,
     flesh_fields: {
-        acp: ['call_number', 'location', 'parts',
-                'creator', 'editor', 'stat_cat_entries']
+        acp: [
+            'call_number', 'location', 'parts', 'tags',
+            'creator', 'editor', 'stat_cat_entries'
+        ],
+        acptcm: ['tag'],
+        acpt: ['tag_type']
     }
 };
 
index e0c76b1..ba20dc9 100644 (file)
@@ -214,6 +214,7 @@ export class VolCopyService {
         copy.ref('f');
         copy.mint_condition('t');
         copy.parts([]);
+        copy.tags([]);
         copy.stat_cat_entries([]);
 
         return copy;
index b2c1ffa..f1b53d8 100644 (file)
@@ -5,10 +5,10 @@
   <div class="modal-header">
     <h4 class="modal-title">
       <ng-container *ngIf="mode == 'create'">
-        <span i18n>Adding tags for {{copies.length}} item(s).</span>
+        <span i18n>Adding tags for {{copyIds.length}} item(s).</span>
       </ng-container>
       <ng-container *ngIf="mode == 'manage'">
-        <span i18n>Managing tags for item {{copies[0].barcode()}}</span>
+        <span i18n>Managing tags for item {{copy.barcode()}}</span>
       </ng-container>
       <span i18n></span>
     </h4>
     </button>
   </div>
   <div class="modal-body p-4 form-validated">
-    <div class="row mt-2 p-2" *ngFor="let tag of newTags">
-      <div class="col-lg-4">
-        {{tag.tag_type()}}
-      </div>
-      <div class="col-lg-5">
-        {{tag.label()}}
-      </div>
-      <div class="col-lg-3">
-        <button class="btn btn-outline-danger" (click)="removeTag(tag)" i18n>
-          Remove
-        </button>
+
+    <ng-container *ngIf="mode == 'manage' && copy.tags().length">
+      <h4 i18n>Existing Tags</h4>
+      <div class="row mt-2 p-2" *ngFor="let map of copy.tags()">
+        <div class="col-lg-4">{{map.tag().tag_type().label()}}</div>
+        <div class="col-lg-5">{{map.tag().label()}}</div>
+        <div class="col-lg-3">
+          <button class="btn btn-outline-danger" (click)="removeTag(map.tag())" i18n>
+            Remove
+          </button>
+        </div>
       </div>
+      <hr/>
+    </ng-container>
+
+    <h4 i18n>New Tags</h4>
+    <div class="row mt-2 p-2" *ngFor="let tag of newTags">
+      <ng-container *ngIf="!tag.isdeleted()">
+        <div class="col-lg-4">{{tagTypeMap[tag.tag_type()].label()}}</div>
+        <div class="col-lg-5">{{tag.label()}}</div>
+        <div class="col-lg-3">
+          <button class="btn btn-outline-danger" (click)="removeTag(tag)" i18n>
+            Remove
+          </button>
+        </div>
+      </ng-container>
     </div>
 
     <div class="row mt-2 p-2 rounded border border-success">
         </div>  
       </div>
     </div>
-    <ng-container *ngIf="mode == 'manage'">
-      <!-- in manage mode list all of the tags linked to the copy -->
-      <!--
-      <div class="row mt-2" 
-        *ngFor="let tag of copy.copy_tags()">
-        <div class="col-lg-12 pb-2"><hr/></div>
-        <div class="col-lg-4">
-          <eg-combobox [entries]="tagTypes" [startId]="tag.tag_type()"
-            i18n-placeholder placeholder="Tag Type..."
-            [required]="true"
-            (onChange)="tag.tag_type($event ? $event.id : null); tag.ischanged(true)">
-          </eg-combobox>
-          <div class="pl-2 pt-2" i18n>
-            Added: {{tag.create_time() | date:'shortDate'}}
-          </div>
-        </div>
-        <div class="col-lg-5">
-          <textarea class="form-control" rows="2" 
-            i18n-placeholder placeholder="Tag Note..."
-            (ngModelChange)="tag.note($event); tag.ischanged(true)"
-            [ngModel]="tag.note()">
-          </textarea>
-        </div>
-        <div class="col-lg-3">
-          <div class="d-flex flex-column">
-            <div class="form-check">
-              <input class="form-check-input" type="checkbox" 
-                [ngModel]="tag.temp() == 't'" 
-                (ngModelChange)="tag.temp($event ? 't' : 'f'); tag.ischanged(true)"
-                id="tag-temporary-{{tag.id()}}">
-              <label class="form-check-label" for="tag-temporary-{{tag.id()}}" i18n>
-                Temporary?
-              </label>
-            </div>
-            <div class="form-check pt-2">
-              <input class="form-check-input" type="checkbox" 
-                [ngModel]="tag.ack_time() != null" 
-                (ngModelChange)="tag.ack_time($event ? 'now' : null); tag.ischanged(true)"
-                id="tag-temporary-{{tag.id()}}">
-              <label class="form-check-label" for="tag-temporary-{{tag.id()}}" i18n>
-                Clear?
-              </label>
-            </div>
-          </div>
-        </div>
-      </div>
-      -->
-    </ng-container>
   </div>
   <div class="modal-footer">
     <button type="button" class="btn btn-secondary" (click)="close()" i18n>Cancel</button>
index e008b81..65f6775 100644 (file)
@@ -25,12 +25,10 @@ import {ComboboxEntry} from '@eg/share/combobox/combobox.component';
 export class CopyTagsDialogComponent
     extends DialogComponent implements OnInit {
 
-    static autoId = -1;
-
-    @Input() copyIds: number[] = [];
-
     // If there are multiple copyIds, only new tags may be applied.
     // If there is only one copyId, then tags may be applied or removed.
+    @Input() copyIds: number[] = [];
+
     mode: string; // create | manage
 
     // If true, no attempt is made to save the new tags to the
@@ -49,7 +47,9 @@ export class CopyTagsDialogComponent
     curTag: ComboboxEntry = null;
     curTagType: ComboboxEntry = null;
     newTags: IdlObject[] = [];
+    deletedMaps: IdlObject[] = [];
     tagMap: {[id: number]: IdlObject} = {};
+    tagTypeMap: {[id: number]: IdlObject} = {};
 
     tagDataSource: (term: string) => Observable<ComboboxEntry>;
 
@@ -94,6 +94,7 @@ export class CopyTagsDialogComponent
         this.copy = null;
         this.copies = [];
         this.newTags = [];
+        this.deletedMaps = [];
 
         if (this.copyIds.length === 0 && !this.inPlaceMode) {
             return throwError('copy ID required');
@@ -102,17 +103,14 @@ export class CopyTagsDialogComponent
         // In manage mode, we can only manage a single copy.
         // But in create mode, we can add tags to multiple copies.
 
-        if (this.copyIds.length === 1) {
+        if (this.copyIds.length === 1 && !this.inPlaceMode) {
             this.mode = 'manage';
         } else {
             this.mode = 'create';
         }
 
         // Observify data loading
-        const obs = from(
-            this.getTagTypes()
-            .then(_ => this.getCopies())
-        );
+        const obs = from(this.getTagTypes().then(_ => this.getCopies()));
 
         // Return open() observable to caller
         return obs.pipe(switchMap(_ => super.open(args)));
@@ -125,16 +123,20 @@ export class CopyTagsDialogComponent
         return this.pcrud.search('cctt',
             {owner: this.org.ancestors(this.auth.user().ws_ou(), true)},
             {order_by: {cctt: 'label'}}
-        ).pipe(tap(tag =>
-            this.tagTypes.push({id: tag.code(), label: tag.label()})
-        )).toPromise();
+        ).pipe(tap(tag => {
+            this.tagTypeMap[tag.code()] = tag;
+            this.tagTypes.push({id: tag.code(), label: tag.label()});
+        })).toPromise();
     }
 
     getCopies(): Promise<any> {
         if (this.inPlaceMode) { return Promise.resolve(); }
 
         return this.pcrud.search('acp', {id: this.copyIds},
-            {flesh: 1, flesh_fields: {acp: ['tags']}}, {atomic: true})
+            {flesh: 3, flesh_fields: {
+                acp: ['tags'], acptcm: ['tag'], acpt: ['tag_type']}},
+            {atomic: true}
+        )
         .toPromise().then(copies => {
             this.copies = copies;
             if (copies.length === 1) {
@@ -146,7 +148,15 @@ export class CopyTagsDialogComponent
     removeTag(tag: IdlObject) {
         this.newTags = this.newTags.filter(t => t.id() !== tag.id());
 
-        // TODO: delete existing maps where needed.
+        if (tag.isnew() || this.mode === 'create') { return; }
+
+        const existing = this.copy.tags().filter(m => m.tag().id() === tag.id())[0];
+        if (!existing) { return; }
+
+        existing.isdeleted(true);
+        this.deletedMaps.push(existing);
+        this.copy.tags(this.copy.tags().filter(m => m.tag().id() !== tag.id()));
+        this.copy.ischanged(true);
     }
 
     addNew() {
@@ -157,7 +167,6 @@ export class CopyTagsDialogComponent
         if (this.curTag.freetext) {
             // Create a new tag w/ the provided tag text.
             tag = this.idl.create('acpt');
-            tag.id(CopyTagsDialogComponent.autoId--);
             tag.isnew(true);
             tag.tag_type(this.curTagType.id);
             tag.label(this.curTag.label);
@@ -187,6 +196,11 @@ export class CopyTagsDialogComponent
         return promise;
     }
 
+    deleteMaps(): Promise<any> {
+        if (this.deletedMaps.length === 0) { return Promise.resolve(); }
+        return this.pcrud.remove(this.deletedMaps).toPromise();
+    }
+
     applyChanges() {
 
         if (this.inPlaceMode) {
@@ -194,15 +208,13 @@ export class CopyTagsDialogComponent
             return;
         }
 
-        // Create the tags then map them to our copies
-
-        let promise = this.createNewTags();
+        let promise = this.deleteMaps().then(_ => this.createNewTags());
 
         this.newTags.forEach(tag => {
             this.copies.forEach(copy => {
 
                 if (copy.tags() && copy.tags().filter(
-                    t => t.tag_type() === tag.id()).length > 0) {
+                    map => map.tag().id() === tag.id()).length > 0) {
                     return; // map already exists
                 }
 
@@ -221,16 +233,5 @@ export class CopyTagsDialogComponent
             this.close(this.newTags.length > 0);
         });
     }
-
-    /*
-    applyChanges() {
-        const tags = this.copy.copy_tags().filter(a => a.ischanged());
-        if (tags.length === 0) { return; }
-        this.pcrud.update(tags).toPromise().then(
-            ok => this.successMsg.current().then(msg => this.toast.success(msg)),
-            err => this.errorMsg.current().then(msg => this.toast.danger(msg))
-        );
-    }
-    */
 }