LPXXX Missing pieces angular port WIP user/berick/lpxxx-item-missing-pieces-angular
authorBill Erickson <berickxx@gmail.com>
Mon, 2 Mar 2020 22:57:19 +0000 (17:57 -0500)
committerBill Erickson <berickxx@gmail.com>
Mon, 2 Mar 2020 22:57:19 +0000 (17:57 -0500)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/eg2/src/app/staff/cat/item/item.module.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/cat/item/missing-pieces.component.html [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/cat/item/missing-pieces.component.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/cat/item/routing.module.ts [new file with mode: 0644]

diff --git a/Open-ILS/src/eg2/src/app/staff/cat/item/item.module.ts b/Open-ILS/src/eg2/src/app/staff/cat/item/item.module.ts
new file mode 100644 (file)
index 0000000..9c501fb
--- /dev/null
@@ -0,0 +1,24 @@
+import {NgModule} from '@angular/core';
+import {StaffCommonModule} from '@eg/staff/common.module';
+import {CommonWidgetsModule} from '@eg/share/common-widgets.module';
+import {ItemRoutingModule} from './routing.module';
+import {HoldingsModule} from '@eg/staff/share/holdings/holdings.module';
+import {PatronModule} from '@eg/staff/share/patron/patron.module';
+import {MarkItemMissingPiecesComponent} from './missing-pieces.component';
+
+@NgModule({
+  declarations: [
+    MarkItemMissingPiecesComponent
+  ],
+  imports: [
+    StaffCommonModule,
+    CommonWidgetsModule,
+    ItemRoutingModule,
+    HoldingsModule,
+    PatronModule
+  ],
+  providers: [
+  ]
+})
+
+export class ItemModule {}
diff --git a/Open-ILS/src/eg2/src/app/staff/cat/item/missing-pieces.component.html b/Open-ILS/src/eg2/src/app/staff/cat/item/missing-pieces.component.html
new file mode 100644 (file)
index 0000000..28e64ca
--- /dev/null
@@ -0,0 +1,76 @@
+<eg-staff-banner i18n-bannerText bannerText="Mark Item Missing Pieces">
+</eg-staff-banner>
+
+<eg-patron-penalty-dialog #penaltyDialog></eg-patron-penalty-dialog>
+
+<div class="row">
+  <div class="col-lg-12 form-inline">
+    <div class="input-group">
+      <div class="input-group-prepend">
+        <span class="input-group-text" id='barcode-label' i18n>Barcode</span>
+      </div>
+      <input type="text" class="form-control" id="item-barcode-input" 
+        (keyup.enter)="getItemByBarcode()" [(ngModel)]="itemBarcode" 
+        aria-describedby="barcode-label"/>
+    </div>
+    <button class="btn btn-outline-dark" 
+      (click)="getItemByBarcode()" i18n>Submit</button>
+  </div>
+</div>
+
+<div class="mt-3 mb-3 p-2" *ngIf="item">
+  <div class="row">
+    <div class="col-lg-2" i18n>Title: </div>
+    <div class="col-lg-10">{{display('title')}}</div>
+  </div>
+  <div class="row">
+    <div class="col-lg-2" i18n>Author: </div>
+    <div class="col-lg-10">{{display('author')}}</div>
+  </div>
+  <div class="row">
+    <div class="col-lg-2" i18n>Call Number: </div>
+    <div class="col-lg-10">{{item.call_number().label()}}</div>
+  </div>
+  <div class="row mt-2">
+    <div class="col-lg-12">
+      <button class="btn btn-success" (click)="processItem()" i18n>
+        Mark Item as Missing Pieces?
+      </button>
+      <button class="btn btn-warning ml-2" (click)="reset()" i18n>
+        Cancel
+      </button>
+    </div>
+  </div>
+</div>
+
+<div class="row m-1" *ngIf="circNotFound">
+  <div class="col-lg-6 offset-lg-3">
+    <div class="alert alert-warning" i18n>
+     No circulation found for item with barcode {{itemBarcode}}.
+     Item not modified.
+    </div>
+  </div>
+</div>
+
+<div class="row m-1" *ngIf="processing">
+  <div class="col-lg-6 offset-lg-3">
+    <eg-progress-inline></eg-progress-inline>
+  </div>
+</div>
+
+<div *ngIf="letter">
+  <div class="row">
+    <div class="col-lg-3">
+      <button class="btn btn-outline-dark" (click)="printLetter()" i18n>
+        Print Letter
+      </button>
+    </div>
+  </div>
+  <div class="row m-1">
+    <div class="col-lg-8">
+      <textarea [(ngModel)]="letter" 
+        rows="{{letterRowCount()}}" class="form-control">
+      </textarea>
+    </div>
+  </div>
+</div>
diff --git a/Open-ILS/src/eg2/src/app/staff/cat/item/missing-pieces.component.ts b/Open-ILS/src/eg2/src/app/staff/cat/item/missing-pieces.component.ts
new file mode 100644 (file)
index 0000000..e14f55b
--- /dev/null
@@ -0,0 +1,156 @@
+import {Component, Input, AfterViewInit, ViewChild, Renderer2} from '@angular/core';
+import {Router, ActivatedRoute, ParamMap} from '@angular/router';
+import {IdlObject} from '@eg/core/idl.service';
+import {PcrudService} from '@eg/core/pcrud.service';
+import {AuthService} from '@eg/core/auth.service';
+import {NetService} from '@eg/core/net.service';
+import {PrintService} from '@eg/share/print/print.service';
+import {HoldingsService} from '@eg/staff/share/holdings/holdings.service';
+import {EventService} from '@eg/core/event.service';
+import {PatronPenaltyDialogComponent} from '@eg/staff/share/patron/penalty-dialog.component';
+
+@Component({
+  templateUrl: 'missing-pieces.component.html'
+})
+export class MarkItemMissingPiecesComponent implements AfterViewInit {
+
+    itemId: number;
+    itemBarcode: string;
+    item: IdlObject;
+    letter: string;
+    circNotFound = false;
+    processing = false;
+
+    @ViewChild('penaltyDialog', {static: false})
+    penaltyDialog: PatronPenaltyDialogComponent;
+
+    constructor(
+        private route: ActivatedRoute,
+        private renderer: Renderer2,
+        private net: NetService,
+        private printer: PrintService,
+        private pcrud: PcrudService,
+        private auth: AuthService,
+        private evt: EventService,
+        private holdings: HoldingsService
+    ) {
+        this.itemId = +this.route.snapshot.paramMap.get('id');
+    }
+
+    ngAfterViewInit() {
+        if (this.itemId) { this.getItemById(); }
+        this.renderer.selectRootElement('#item-barcode-input').focus();
+    }
+
+    getItemByBarcode(): Promise<any> {
+        this.itemId = null;
+
+        if (!this.itemBarcode) { return Promise.resolve(); }
+
+        return this.holdings.getItemIdFromBarcode(this.itemBarcode)
+        .then(id => {
+            this.itemId = id;
+            return this.getItemById();
+        });
+    }
+
+    getItemById(): Promise<any> {
+        this.circNotFound = false;
+
+        if (!this.itemId) { return Promise.resolve(); }
+
+        const flesh = {
+            flesh: 3,
+            flesh_fields: {
+                acp: ['call_number'],
+                acn: ['record'],
+                bre: ['flat_display_entries']
+            }
+        };
+
+        return this.pcrud.retrieve('acp', this.itemId, flesh)
+        .toPromise().then(item => {
+            this.item = item;
+            this.itemId = item.id();
+            this.itemBarcode = item.barcode();
+
+        }).then(_ =>
+            setTimeout(() =>
+                this.renderer.selectRootElement('#item-barcode-input').select())
+        );
+    }
+
+    display(field: string): string {
+        if (!this.item) { return ''; }
+
+        const entry = this.item.call_number().record()
+            .flat_display_entries()
+            .filter(fde => fde.name() === field)[0];
+
+        return entry ? entry.value() : '';
+    }
+
+    reset() {
+        this.item = null;
+        this.itemId = null;
+        this.itemBarcode = null;
+        this.circNotFound = false;
+    }
+
+    processItem() {
+        this.circNotFound = false;
+
+        if (!this.item) { return; }
+
+        this.processing = true;
+
+        this.net.request(
+            'open-ils.circ',
+            'open-ils.circ.mark_item_missing_pieces',
+            this.auth.token(), this.itemId
+        ).subscribe(resp => {
+            const evt = this.evt.parse(resp); // always returns event
+            this.processing = false;
+
+            if (evt.textcode === 'ACTION_CIRCULATION_NOT_FOUND') {
+                this.circNotFound = true;
+                return;
+            }
+
+            const payload = evt.payload;
+
+            if (payload.letter) {
+                this.letter = payload.letter.template_output().data();
+            }
+
+            if (payload.slip) {
+                this.printer.print({
+                    printContext: 'default',
+                    contentType: 'text/html',
+                    text: payload.slip.template_output().data()
+                });
+            }
+
+            if (payload.circ) {
+                this.penaltyDialog.patronId = payload.circ.usr();
+                this.penaltyDialog.open().subscribe(
+                    penId => console.debug('Applied penalty ', penId));
+            }
+        });
+    }
+
+    printLetter() {
+        this.printer.print({
+            printContext: 'default',
+            contentType: 'text/plain',
+            text: this.letter
+        });
+    }
+
+    letterRowCount(): number {
+        return this.letter ? this.letter.split(/\n/).length + 2 : 20;
+    }
+}
+
+
+
diff --git a/Open-ILS/src/eg2/src/app/staff/cat/item/routing.module.ts b/Open-ILS/src/eg2/src/app/staff/cat/item/routing.module.ts
new file mode 100644 (file)
index 0000000..b3e7759
--- /dev/null
@@ -0,0 +1,20 @@
+import {NgModule} from '@angular/core';
+import {RouterModule, Routes} from '@angular/router';
+import {MarkItemMissingPiecesComponent} from './missing-pieces.component';
+
+const routes: Routes = [{
+    path: 'missing_pieces',
+    component: MarkItemMissingPiecesComponent
+  }, {
+    path: 'missing_pieces/:id',
+    component: MarkItemMissingPiecesComponent
+}];
+
+@NgModule({
+  imports: [RouterModule.forChild(routes)],
+  exports: [RouterModule],
+  providers: []
+})
+
+export class ItemRoutingModule {}
+