LP#1775466 Inline progress; more combobox
authorBill Erickson <berickxx@gmail.com>
Mon, 2 Jul 2018 18:50:19 +0000 (14:50 -0400)
committerBill Erickson <berickxx@gmail.com>
Wed, 5 Sep 2018 14:05:23 +0000 (10:05 -0400)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/eg2/src/app/common.module.ts
Open-ILS/src/eg2/src/app/share/combobox/combobox.component.ts
Open-ILS/src/eg2/src/app/share/dialog/progress-inline.component.css [new file with mode: 0644]
Open-ILS/src/eg2/src/app/share/dialog/progress-inline.component.html [new file with mode: 0644]
Open-ILS/src/eg2/src/app/share/dialog/progress-inline.component.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/share/dialog/progress.component.ts
Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html

index e04e003..48e19d9 100644 (file)
@@ -24,6 +24,7 @@ import {PrintComponent} from '@eg/share/print/print.component';
 import {DialogComponent} from '@eg/share/dialog/dialog.component';
 import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component';
 import {PromptDialogComponent} from '@eg/share/dialog/prompt.component';
+import {ProgressInlineComponent} from '@eg/share/dialog/progress-inline.component';
 import {ProgressDialogComponent} from '@eg/share/dialog/progress.component';
 
 @NgModule({
@@ -32,6 +33,7 @@ import {ProgressDialogComponent} from '@eg/share/dialog/progress.component';
     DialogComponent,
     ConfirmDialogComponent,
     PromptDialogComponent,
+    ProgressInlineComponent,
     ProgressDialogComponent
   ],
   imports: [
@@ -49,6 +51,7 @@ import {ProgressDialogComponent} from '@eg/share/dialog/progress.component';
     DialogComponent,
     ConfirmDialogComponent,
     PromptDialogComponent,
+    ProgressInlineComponent,
     ProgressDialogComponent
   ]
 })
index 2ab9b13..470ef0d 100644 (file)
@@ -49,9 +49,6 @@ export class ComboboxComponent implements OnInit {
 
     @Input() allowFreeText = false;
 
-    // If true select the first item in the list
-    @Input() selectFirst: boolean;
-
     // Entry ID of the default entry to select (optional)
     // onChange() is NOT fired when applying the default value
     @Input() startId: any;
@@ -99,24 +96,15 @@ export class ComboboxComponent implements OnInit {
     // Apply a default selection where needed
     applySelection() {
 
-        if (this.defaultSelectionApplied 
-            || !this.entrylist || this.entrylist.length === 0) {
-            // Avoid unnecessary processing.  Also as the page renders,
-            // the entrylist may be empty at times, avoid any attempts
-            // to apply selection during that time
-            return;
-        }
+        if (this.startId && 
+            this.entrylist && !this.defaultSelectionApplied) {
 
-        if (this.startId) {
             const entry = 
                 this.entrylist.filter(e => e.id === this.startId)[0];
             if (entry) {
                 this.selected = entry;
                 this.defaultSelectionApplied = true;
             }
-        } else if (this.selectFirst) {
-            this.selected = this.entrylist[0];
-            this.defaultSelectionApplied = true;
         }
     }
 
@@ -153,7 +141,7 @@ export class ComboboxComponent implements OnInit {
     // This only fires when an item in the list is selected, not when
     // the value is cleared or free-text is used.
     selectorChanged(selEvent: NgbTypeaheadSelectItemEvent) {
-        this.onChange.emit(selEvent.item.id);
+        this.onChange.emit(selEvent.item);
     }
 
     filter = (text$: Observable<string>): Observable<ComboboxEntry[]> => {
diff --git a/Open-ILS/src/eg2/src/app/share/dialog/progress-inline.component.css b/Open-ILS/src/eg2/src/app/share/dialog/progress-inline.component.css
new file mode 100644 (file)
index 0000000..fa08a1f
--- /dev/null
@@ -0,0 +1,5 @@
+
+.eg-progress-inline progress {
+  width: 100%;
+  height: 25px;
+}
diff --git a/Open-ILS/src/eg2/src/app/share/dialog/progress-inline.component.html b/Open-ILS/src/eg2/src/app/share/dialog/progress-inline.component.html
new file mode 100644 (file)
index 0000000..078d701
--- /dev/null
@@ -0,0 +1,22 @@
+<div class="eg-progress-inline">
+
+  <div *ngIf="hasValue() && hasMax()">
+    <!-- determinate progress bar.  shows max/value progress -->
+    <div class="col-lg-10">
+      <progress max="{{max}}" value="{{value}}"></progress>
+    </div>
+    <div class="col-lg-2">{{percent()}}%</div>
+  </div>
+
+  <div *ngIf="hasValue() && !hasMax()">
+    <!-- semi-determinate progress bar.  shows value -->
+    <div class="col-lg-10"><progress max="1"></progress></div>
+    <div class="col-lg-2">{{value}}...</div>
+  </div>
+
+  <div *ngIf="!hasValue()">
+    <!-- indeterminate -->
+    <div class="col-lg-12"><progress max="1"></progress></div>
+  </div>
+
+</div>
diff --git a/Open-ILS/src/eg2/src/app/share/dialog/progress-inline.component.ts b/Open-ILS/src/eg2/src/app/share/dialog/progress-inline.component.ts
new file mode 100644 (file)
index 0000000..9b131d1
--- /dev/null
@@ -0,0 +1,92 @@
+import {Component, Input, ViewChild, TemplateRef} from '@angular/core';
+
+/**
+ * Inline Progress Bar
+ *
+ * // assuming a template reference...
+ * @ViewChild('progress')
+ * private progress: progressInlineComponent;
+ *
+ * progress.update({value : 0, max : 123});
+ * progress.increment();
+ * progress.increment();
+ *
+ * Each progress has 2 numbers, 'max' and 'value'.
+ * The content of these values determines how the progress displays.
+ *
+ * There are 3 flavors:
+ *
+ * -- value is set, max is set
+ * determinate: shows a progression with a percent complete.
+ *
+ * -- value is set, max is unset
+ * semi-determinate, with a value report.  Shows a value-less
+ * <progress/>, but shows the value as a number in the progress.
+ *
+ * This is useful in cases where the total number of items to retrieve
+ * from the server is unknown, but we know how many items we've
+ * retrieved thus far.  It helps to reinforce that something specific
+ * is happening, but we don't know when it will end.
+ *
+ * -- value is unset
+ * indeterminate: shows a generic value-less <progress/> with no
+ * clear indication of progress.
+ */
+@Component({
+  selector: 'eg-progress-inline',
+  templateUrl: './progress-inline.component.html',
+  styleUrls: ['progress-inline.component.css']
+})
+export class ProgressInlineComponent {
+
+    @Input() max: number;
+    @Input() value: number;
+
+    reset() {
+        delete this.max;
+        delete this.value;
+    }
+
+    hasValue(): boolean {
+        return Number.isInteger(this.value);
+    }
+
+    hasMax(): boolean {
+        return Number.isInteger(this.max);
+    }
+
+    percent(): number {
+        if (this.hasValue()  &&
+            this.hasMax()    &&
+            this.max > 0     &&
+            this.value <= this.max) {
+            return Math.floor((this.value / this.max) * 100);
+        }
+        return 100;
+    }
+
+    // Set the current state of the progress bar.
+    update(args: {[key: string]: number}) {
+        if (args.max !== undefined) {
+            this.max = args.max;
+        }
+        if (args.value !== undefined) {
+            this.value = args.value;
+        }
+    }
+
+    // Increment the current value.  If no amount is specified,
+    // it increments by 1.  Calling increment() on an indetermite
+    // progress bar will force it to be a (semi-)determinate bar.
+    increment(amt?: number) {
+        if (!Number.isInteger(amt)) { amt = 1; }
+
+        if (!this.hasValue()) {
+            this.value = 0;
+        }
+
+        this.value += amt;
+    }
+}
+
+
index 9a32bf5..6bf4edb 100644 (file)
@@ -8,6 +8,18 @@ import {DialogComponent} from '@eg/share/dialog/dialog.component';
 })
 
 /**
+ * TODO: This duplicates the code from ProgressInlineComponent.
+ * This component should insert to <eg-progress-inline/> into
+ * its template instead of duplicating the code.  However, until
+ * Angular bug https://github.com/angular/angular/issues/14842
+ * is fixed, it's not possible to get a reference to the embedded
+ * inline progress, which is needed for access the update/increment
+ * API.
+ * Also consider moving the progress traking logic to a service
+ * to reduce code duplication.
+ */
+
+/**
  * Progress Dialog.
  *
  * // assuming a template reference...
index 739184d..0c0a665 100644 (file)
 
 <!-- Progress Dialog Experiments ----------------------------- -->
 <div class="row mb-3">
+  <div class="col-lg-3">
+    <button class="btn btn-outline-danger" (click)="progress.increment()">Increment Inline</button>
+  </div>
+  <div class="col-lg-3">
+    <eg-progress-inline [max]="100" [value]="1" #progress></eg-progress-inline>
+  </div>
+</div>
+<div class="row mb-3">
   <div class="col-lg-4">
     <eg-progress-dialog #progressDialog>
     </eg-progress-dialog>
@@ -39,7 +47,7 @@
    <button class="btn btn-info" (click)="testToast()">Test Toast Message</button>
   </div>
   <div class="col-lg-4">
-    <eg-combobox [selectFirst]="true" [allowFreeText]="true" 
+    <eg-combobox [allowFreeText]="true" 
       [entries]="taEntries" placeholder="Combobox..."></eg-combobox>
   </div>
 </div>