Skip to content

Commit

Permalink
Merge pull request #456 from nyaruka/generic-start
Browse files Browse the repository at this point in the history
Switch to generic StartProgress widget
  • Loading branch information
ericnewcomer authored Sep 25, 2024
2 parents 1dc3078 + a848a5d commit 78b078d
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 99 deletions.
1 change: 1 addition & 0 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@
<temba-tabs collapses index="0">
<temba-tab name="Overview" icon="default">
<temba-progress style="margin-bottom:8px" total="100" current="25" eta="2030-09-17T07:00:00.000Z"></temba-progress>

<div style="display:flex;flex-wrap: wrap;">
<temba-checkbox label="Check this out" checked></temba-checkbox>
<temba-select placeholder="Select a color" clearable>
Expand Down
6 changes: 5 additions & 1 deletion src/dialog/Modax.ts
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,11 @@ export class Modax extends RapidElement {
}

private isDestructive(): boolean {
return this.endpoint && this.endpoint.indexOf('delete') > -1;
return (
this.endpoint &&
(this.endpoint.indexOf('delete') > -1 ||
this.endpoint.indexOf('interrupt') > -1)
);
}

private handleGotoStep(evt: MouseEvent) {
Expand Down
76 changes: 0 additions & 76 deletions src/progress/FlowStartProgress.ts

This file was deleted.

66 changes: 46 additions & 20 deletions src/progress/ProgressBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,20 @@ export class ProgressBar extends RapidElement {
background: #f1f1f1;
border-radius: var(--curvature);
box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.05);
overflow: hidden;
min-height: 1.5rem;
}
.message {
padding: 0 0.25rem;
color: rgba(0, 0, 0, 0.4);
}
.meter {
flex-grow: 1;
display: flex;
box-sizing: content-box;
position: relative;
border-radius: var(--curvature);
border-top-right-radius: 0;
border-bottom-right-radius: 0;
padding: 4px;
Expand All @@ -26,7 +32,7 @@ export class ProgressBar extends RapidElement {
.meter > span {
display: block;
height: 100%;
border-radius: var(--curvature);
border-radius: calc(var(--curvature) * 0.8);
background-color: var(--color-primary-dark);
background-image: linear-gradient(
center bottom,
Expand All @@ -36,7 +42,6 @@ export class ProgressBar extends RapidElement {
position: relative;
overflow: hidden;
min-width: 3px;
}
.meter > span:after,
Expand All @@ -59,7 +64,7 @@ export class ProgressBar extends RapidElement {
);
z-index: 1;
background-size: 50px 50px;
animation: move 16s linear infinite;
animation: move 8s linear infinite;
border-top-right-radius: var(--curvature);
border-bottom-right-radius: var(--curvature);
border-top-left-radius: var(--curvature);
Expand All @@ -80,24 +85,35 @@ export class ProgressBar extends RapidElement {
}
}
.complete {
transition: width 2s;
.meter .complete {
transition: flex-basis 2s;
}
.incomplete {
.meter .incomplete {
flex-grow: 1;
}
.etc {
font-size: 0.7em;
display: flex;
flex-direction: row;
background: rgba(0, 0, 0, 0.07);
font-weight: bold;
white-space: nowrap;
border-top-right-radius: var(--curvature);
border-bottom-right-radius: var(--curvature);
color: rgba(0, 0, 0, 0.5);
align-self: center;
padding: 2px 6px;
padding: 0px 6px;
align-self: stretch;
align-items: center;
}
.etc > div {
font-size: 0.7em;
}
.wrapper *::last-child {
border-top-right-radius: var(--curvature);
border-bottom-right-radius: var(--curvature);
overflow: hidden;
}
.meter.done > span:after,
Expand Down Expand Up @@ -134,6 +150,9 @@ export class ProgressBar extends RapidElement {
@property({ type: Boolean })
showPercentage = false;

@property({ type: String })
message: string;

public updated(
changes: PropertyValueMap<any> | Map<PropertyKey, unknown>
): void {
Expand All @@ -156,24 +175,31 @@ export class ProgressBar extends RapidElement {
}

public render(): TemplateResult {
return html`<div class="wrapper">
return html`<div class="wrapper ${this.done ? 'complete' : ''}">
<div class="meter ${this.done ? 'done' : ''}">
${this.message
? html`<div class="message">${this.message}</div>`
: null}
<span class="complete" style="flex-basis: ${this.pct}%"></span>
<div class="incomplete"></div>
</div>
${this.showPercentage || this.showEstimatedCompletion
? html`<div class="etc">
${this.estimatedCompletionDate &&
this.showEstimatedCompletion &&
!this.done
? html`<temba-date
value="${this.estimatedCompletionDate.toISOString()}"
display="countdown"
></temba-date>`
: html`${this.pct}%`}
<div>
${this.estimatedCompletionDate &&
this.showEstimatedCompletion &&
!this.done
? html`<temba-date
value="${this.estimatedCompletionDate.toISOString()}"
display="countdown"
></temba-date>`
: html`${this.pct}%`}
</div>
</div>`
: null}
<slot></slot>
</div>`;
}
}
154 changes: 154 additions & 0 deletions src/progress/StartProgress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { css, html, PropertyValueMap, TemplateResult } from 'lit';
import { RapidElement } from '../RapidElement';
import { property } from 'lit/decorators.js';
import { fetchResults, showModax } from '../utils';

export class StartProgress extends RapidElement {
static styles = css`
temba-icon[name='close'] {
cursor: pointer;
margin: 0 4px;
}
temba-icon[name='close']:hover {
color: var(--color-primary-dark);
}
`;
@property({ type: String })
id: string;

@property({ type: Number })
current: number;

@property({ type: Number })
total: number;

@property({ type: Number })
refreshes: number = 0;

@property({ type: String })
eta: string;

@property({ type: Boolean })
complete = false;

@property({ type: String })
message: string;

@property({ type: String })
statusEndpoint: string;

@property({ type: String })
interruptTitle: string;

@property({ type: String })
interruptEndpoint: string;

public updated(
changes: PropertyValueMap<any> | Map<PropertyKey, unknown>
): void {
super.updated(changes);
if (changes.has('id')) {
this.refresh();
}

// Useful for simulating progress
/*
if (changes.has('current')) {
this.requestUpdate();
setTimeout(() => {
this.current = this.current + 100000;
this.complete = this.current >= this.total;
this.message = null;
if (this.complete) {
this.scheduleRemoval();
}
}, 5000);
}*/
}

public interruptStart(): void {
showModax(this.interruptTitle, this.interruptEndpoint);
}

public refresh(): void {
fetchResults(this.statusEndpoint).then((data: any) => {
if (data.length > 0) {
this.refreshes++;
const start = data[0];

this.current = start.progress.current;
this.total = start.progress.total;

this.complete =
start.status == 'Completed' ||
start.status == 'Failed' ||
start.status == 'Interrupted' ||
start.progress.current >= start.progress.total;

if (start.status === 'Queued') {
this.message = 'Waiting..';
} else {
this.message = null;
}

if (start.status === 'Started') {
const elapsed =
new Date().getTime() - new Date(start.modified_on).getTime();
const rate = this.current / elapsed;

// only calculate eta if the rate is actually reasonable
if (rate > 0.1) {
const eta = new Date(
new Date().getTime() + (this.total - this.current) / rate
);
// Don't bother with estimates months out
const nextMonth = new Date();
nextMonth.setMonth(nextMonth.getMonth() + 2);
if (eta > nextMonth) {
this.eta = null;
} else {
this.eta = eta.toISOString();
}
}
}

if (!this.complete && this.current < this.total) {
// refresh with a backoff up to 1 minute
setTimeout(() => {
this.refresh();
}, Math.min(1000 * this.refreshes, 60000));
} else {
this.complete = true;
}

if (this.complete) {
this.scheduleRemoval();
}
}
});
}

public scheduleRemoval(): void {
setTimeout(() => {
this.remove();
}, 5000);
}

public render(): TemplateResult {
return html`<temba-progress
total=${this.total}
current=${this.current}
eta=${this.eta}
message=${this.message}
>
${!this.complete
? html`<temba-icon
name="close"
@click=${this.interruptStart}
></temba-icon>`
: null}
</temba-progress>`;
}
}
Loading

0 comments on commit 78b078d

Please sign in to comment.