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({
DialogComponent,
ConfirmDialogComponent,
PromptDialogComponent,
+ ProgressInlineComponent,
ProgressDialogComponent
],
imports: [
DialogComponent,
ConfirmDialogComponent,
PromptDialogComponent,
+ ProgressInlineComponent,
ProgressDialogComponent
]
})
@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;
// 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;
}
}
// 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[]> => {
--- /dev/null
+
+.eg-progress-inline progress {
+ width: 100%;
+ height: 25px;
+}
--- /dev/null
+<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>
--- /dev/null
+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;
+ }
+}
+
+
})
/**
+ * 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...
<!-- 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>
<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>