@nyaruka/temba-components 0.107.0 → 0.107.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,9 +22,18 @@ export class FlowStartProgress extends RapidElement {
22
22
  this.started = start.progress.started;
23
23
  this.total = start.progress.total;
24
24
  const elapsed = new Date().getTime() - new Date(start.created_on).getTime();
25
- const rate = this.started / (elapsed / 1000);
25
+ const rate = this.started / elapsed;
26
26
  // calculate the estimated time of arrival
27
- this.eta = new Date(new Date().getTime() + ((this.total - this.started) / rate) * 1000).toISOString();
27
+ const eta = new Date(new Date().getTime() + (this.total - this.started) / rate);
28
+ // Don't bother with estimates months out
29
+ const nextMonth = new Date();
30
+ nextMonth.setMonth(nextMonth.getMonth() + 2);
31
+ if (eta > nextMonth) {
32
+ this.eta = null;
33
+ }
34
+ else {
35
+ this.eta = eta.toISOString();
36
+ }
28
37
  if (this.started < this.total) {
29
38
  // refresh with a backoff up to 1 minute
30
39
  setTimeout(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"FlowStartProgress.js","sourceRoot":"","sources":["../../../src/progress/FlowStartProgress.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAoC,MAAM,KAAK,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,MAAM,OAAO,iBAAkB,SAAQ,YAAY;IAAnD;;QAWE,cAAS,GAAW,CAAC,CAAC;IAkDxB,CAAC;IA7CQ,OAAO,CACZ,OAA0D;QAE1D,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACvB,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC;IACH,CAAC;IAEM,OAAO;QACZ,YAAY,CAAC,iCAAiC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAC7D,CAAC,IAAS,EAAE,EAAE;YACZ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpB,IAAI,CAAC,SAAS,EAAE,CAAC;gBACjB,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;gBACtB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC;gBACtC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAElC,MAAM,OAAO,GACX,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC;gBAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;gBAE7C,0CAA0C;gBAC1C,IAAI,CAAC,GAAG,GAAG,IAAI,IAAI,CACjB,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CACnE,CAAC,WAAW,EAAE,CAAC;gBAEhB,IAAI,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;oBAC9B,wCAAwC;oBACxC,UAAU,CAAC,GAAG,EAAE;wBACd,IAAI,CAAC,OAAO,EAAE,CAAC;oBACjB,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;gBAC7C,CAAC;YACH,CAAC;QACH,CAAC,CACF,CAAC;IACJ,CAAC;IAEM,MAAM;QACX,OAAO,IAAI,CAAA;cACD,IAAI,CAAC,KAAK;gBACR,IAAI,CAAC,OAAO;YAChB,IAAI,CAAC,GAAG;uBACG,CAAC;IACtB,CAAC;CACF;AA3DC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;+CACd;AAGb;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;kDACX;AAGhB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;gDACb;AAGd;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;oDACL;AAGtB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;8CACf","sourcesContent":["import { html, PropertyValueMap, TemplateResult } from 'lit';\nimport { RapidElement } from '../RapidElement';\nimport { property } from 'lit/decorators.js';\nimport { fetchResults } from '../utils';\n\nexport class FlowStartProgress extends RapidElement {\n @property({ type: String })\n uuid: string;\n\n @property({ type: Number })\n started: number;\n\n @property({ type: Number })\n total: number;\n\n @property({ type: Number })\n refreshes: number = 0;\n\n @property({ type: String })\n eta: string;\n\n public updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n if (changes.has('uuid')) {\n this.refresh();\n }\n }\n\n public refresh(): void {\n fetchResults(`/api/v2/flow_starts.json?uuid=${this.uuid}`).then(\n (data: any) => {\n if (data.length > 0) {\n this.refreshes++;\n const start = data[0];\n this.started = start.progress.started;\n this.total = start.progress.total;\n\n const elapsed =\n new Date().getTime() - new Date(start.created_on).getTime();\n const rate = this.started / (elapsed / 1000);\n\n // calculate the estimated time of arrival\n this.eta = new Date(\n new Date().getTime() + ((this.total - this.started) / rate) * 1000\n ).toISOString();\n\n if (this.started < this.total) {\n // refresh with a backoff up to 1 minute\n setTimeout(() => {\n this.refresh();\n }, Math.min(1000 * this.refreshes, 60000));\n }\n }\n }\n );\n }\n\n public render(): TemplateResult {\n return html`<temba-progress\n total=${this.total}\n current=${this.started}\n eta=${this.eta}\n ></temba-progress>`;\n }\n}\n"]}
1
+ {"version":3,"file":"FlowStartProgress.js","sourceRoot":"","sources":["../../../src/progress/FlowStartProgress.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, PropertyValueMap, TemplateResult } from 'lit';\nimport { RapidElement } from '../RapidElement';\nimport { property } from 'lit/decorators.js';\nimport { fetchResults } from '../utils';\n\nexport class FlowStartProgress extends RapidElement {\n @property({ type: String })\n uuid: string;\n\n @property({ type: Number })\n started: number;\n\n @property({ type: Number })\n total: number;\n\n @property({ type: Number })\n refreshes: number = 0;\n\n @property({ type: String })\n eta: string;\n\n public updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n if (changes.has('uuid')) {\n this.refresh();\n }\n }\n\n public refresh(): void {\n fetchResults(`/api/v2/flow_starts.json?uuid=${this.uuid}`).then(\n (data: any) => {\n if (data.length > 0) {\n this.refreshes++;\n const start = data[0];\n this.started = start.progress.started;\n this.total = start.progress.total;\n\n const elapsed =\n new Date().getTime() - new Date(start.created_on).getTime();\n const rate = this.started / elapsed;\n\n // calculate the estimated time of arrival\n const eta = new Date(\n new Date().getTime() + (this.total - this.started) / rate\n );\n\n // Don't bother with estimates months out\n const nextMonth = new Date();\n nextMonth.setMonth(nextMonth.getMonth() + 2);\n if (eta > nextMonth) {\n this.eta = null;\n } else {\n this.eta = eta.toISOString();\n }\n\n if (this.started < this.total) {\n // refresh with a backoff up to 1 minute\n setTimeout(() => {\n this.refresh();\n }, Math.min(1000 * this.refreshes, 60000));\n }\n }\n }\n );\n }\n\n public render(): TemplateResult {\n return html`<temba-progress\n total=${this.total}\n current=${this.started}\n eta=${this.eta}\n ></temba-progress>`;\n }\n}\n"]}
@@ -10,6 +10,7 @@ export class ProgressBar extends RapidElement {
10
10
  this.pct = 0;
11
11
  this.done = false;
12
12
  this.showEstimatedCompletion = false;
13
+ this.showPercentage = false;
13
14
  }
14
15
  updated(changes) {
15
16
  if (changes.has('eta') && this.eta) {
@@ -17,17 +18,29 @@ export class ProgressBar extends RapidElement {
17
18
  this.showEstimatedCompletion = this.estimatedCompletionDate > new Date();
18
19
  }
19
20
  if (changes.has('current')) {
20
- this.pct = Math.floor(Math.min((this.current / this.total) * 100, 100));
21
+ const pct = Math.floor(Math.min((this.current / this.total) * 100, 100));
22
+ if (Number.isNaN(pct)) {
23
+ this.showPercentage = false;
24
+ }
25
+ else {
26
+ this.pct = pct;
27
+ this.showPercentage = true;
28
+ }
21
29
  this.done = this.pct >= 100;
22
30
  }
23
31
  }
24
32
  render() {
25
- return html `<div class="meter ${this.done ? 'done' : ''}">
26
- <span class="complete" style="width: ${this.pct}%"></span>
27
- <div class="incomplete"></div>
28
- ${this.pct >= 0 || this.estimatedCompletionDate
29
- ? html ` <div class="etc">
30
- ${this.estimatedCompletionDate
33
+ return html `<div class="wrapper">
34
+ <div class="meter ${this.done ? 'done' : ''}">
35
+ <span class="complete" style="flex-basis: ${this.pct}%"></span>
36
+ <div class="incomplete"></div>
37
+ </div>
38
+
39
+ ${this.showPercentage || this.showEstimatedCompletion
40
+ ? html `<div class="etc">
41
+ ${this.estimatedCompletionDate &&
42
+ this.showEstimatedCompletion &&
43
+ !this.done
31
44
  ? html `<temba-date
32
45
  value="${this.estimatedCompletionDate.toISOString()}"
33
46
  display="countdown"
@@ -39,23 +52,29 @@ export class ProgressBar extends RapidElement {
39
52
  }
40
53
  }
41
54
  ProgressBar.styles = css `
55
+ .wrapper {
56
+ display: flex;
57
+ box-sizing: content-box;
58
+ background: #f1f1f1;
59
+ border-radius: var(--curvature);
60
+ box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.05);
61
+ }
62
+
42
63
  .meter {
64
+ flex-grow: 1;
43
65
  display: flex;
44
66
  box-sizing: content-box;
45
- height: 8px;
46
67
  position: relative;
47
- background: #f1f1f1;
48
68
  border-radius: var(--curvature);
69
+ border-top-right-radius: 0;
70
+ border-bottom-right-radius: 0;
49
71
  padding: 4px;
50
- box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.05);
72
+ min-height: 6px;
51
73
  }
52
74
  .meter > span {
53
75
  display: block;
54
76
  height: 100%;
55
- border-top-right-radius: var(--curvature);
56
- border-bottom-right-radius: var(--curvature);
57
- border-top-left-radius: var(--curvature);
58
- border-bottom-left-radius: var(--curvature);
77
+ border-radius: var(--curvature);
59
78
  background-color: var(--color-primary-dark);
60
79
  background-image: linear-gradient(
61
80
  center bottom,
@@ -65,7 +84,9 @@ ProgressBar.styles = css `
65
84
 
66
85
  position: relative;
67
86
  overflow: hidden;
87
+ min-width: 3px;
68
88
  }
89
+
69
90
  .meter > span:after,
70
91
  .animate > span > span {
71
92
  content: '';
@@ -117,17 +138,14 @@ ProgressBar.styles = css `
117
138
 
118
139
  .etc {
119
140
  font-size: 0.7em;
120
- padding: 4px;
121
- padding-top: 1px;
122
- padding-left: 8px;
123
- padding-right: 8px;
124
- margin-top: -4px;
125
- margin-bottom: -4px;
126
- margin-right: -4px;
127
- margin-left: 0.5em;
128
141
  background: rgba(0, 0, 0, 0.07);
129
142
  font-weight: bold;
130
143
  white-space: nowrap;
144
+ border-top-right-radius: var(--curvature);
145
+ border-bottom-right-radius: var(--curvature);
146
+ color: rgba(0, 0, 0, 0.5);
147
+ align-self: center;
148
+ padding: 2px 6px;
131
149
  }
132
150
 
133
151
  .meter.done > span:after,
@@ -160,4 +178,7 @@ __decorate([
160
178
  __decorate([
161
179
  property({ type: Boolean })
162
180
  ], ProgressBar.prototype, "showEstimatedCompletion", void 0);
181
+ __decorate([
182
+ property({ type: Boolean })
183
+ ], ProgressBar.prototype, "showPercentage", void 0);
163
184
  //# sourceMappingURL=ProgressBar.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProgressBar.js","sourceRoot":"","sources":["../../../src/progress/ProgressBar.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAoC,MAAM,KAAK,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C,MAAM,OAAO,WAAY,SAAQ,YAAY;IAA7C;;QAwGE,UAAK,GAAG,GAAG,CAAC;QAGZ,YAAO,GAAG,CAAC,CAAC;QAGZ,QAAG,GAAG,CAAC,CAAC;QAGR,SAAI,GAAG,KAAK,CAAC;QASb,4BAAuB,GAAG,KAAK,CAAC;IAgClC,CAAC;IA9BQ,OAAO,CACZ,OAA0D;QAE1D,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACnC,IAAI,CAAC,uBAAuB,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAClD,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC,uBAAuB,GAAG,IAAI,IAAI,EAAE,CAAC;QAC3E,CAAC;QAED,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YACxE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC;QAC9B,CAAC;IACH,CAAC;IAEM,MAAM;QACX,OAAO,IAAI,CAAA,qBAAqB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;6CACd,IAAI,CAAC,GAAG;;QAE7C,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,uBAAuB;YAC7C,CAAC,CAAC,IAAI,CAAA;cACA,IAAI,CAAC,uBAAuB;gBAC5B,CAAC,CAAC,IAAI,CAAA;2BACO,IAAI,CAAC,uBAAuB,CAAC,WAAW,EAAE;;+BAEtC;gBACjB,CAAC,CAAC,IAAI,CAAA,GAAG,IAAI,CAAC,GAAG,GAAG;iBACjB;YACT,CAAC,CAAC,IAAI;WACH,CAAC;IACV,CAAC;;AAxJM,kBAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoGlB,AApGY,CAoGX;AAGF;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;0CACf;AAGZ;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;4CACf;AAGZ;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;wCACnB;AAGR;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;yCACf;AAGb;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;wCACf;AAGZ;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;4DACf;AAG9B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;4DACI","sourcesContent":["import { css, html, PropertyValueMap, TemplateResult } from 'lit';\nimport { RapidElement } from '../RapidElement';\nimport { property } from 'lit/decorators.js';\n\nexport class ProgressBar extends RapidElement {\n static styles = css`\n .meter {\n display: flex;\n box-sizing: content-box;\n height: 8px;\n position: relative;\n background: #f1f1f1;\n border-radius: var(--curvature);\n padding: 4px;\n box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.05);\n }\n .meter > span {\n display: block;\n height: 100%;\n border-top-right-radius: var(--curvature);\n border-bottom-right-radius: var(--curvature);\n border-top-left-radius: var(--curvature);\n border-bottom-left-radius: var(--curvature);\n background-color: var(--color-primary-dark);\n background-image: linear-gradient(\n center bottom,\n rgb(43, 194, 83) 37%,\n rgb(84, 240, 83) 69%\n );\n\n position: relative;\n overflow: hidden;\n }\n .meter > span:after,\n .animate > span > span {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n right: 0;\n background-image: linear-gradient(\n -45deg,\n rgba(255, 255, 255, 0.2) 25%,\n transparent 25%,\n transparent 50%,\n rgba(255, 255, 255, 0.2) 50%,\n rgba(255, 255, 255, 0.2) 75%,\n transparent 75%,\n transparent\n );\n z-index: 1;\n background-size: 50px 50px;\n animation: move 16s linear infinite;\n border-top-right-radius: var(--curvature);\n border-bottom-right-radius: var(--curvature);\n border-top-left-radius: var(--curvature);\n border-bottom-left-radius: var(--curvature);\n overflow: hidden;\n }\n\n .animate > span:after {\n display: none;\n }\n\n @keyframes move {\n 0% {\n background-position: 0 0;\n }\n 100% {\n background-position: 50px 50px;\n }\n }\n\n .complete {\n transition: width 2s;\n }\n\n .incomplete {\n flex-grow: 1;\n }\n\n .etc {\n font-size: 0.7em;\n padding: 4px;\n padding-top: 1px;\n padding-left: 8px;\n padding-right: 8px;\n margin-top: -4px;\n margin-bottom: -4px;\n margin-right: -4px;\n margin-left: 0.5em;\n background: rgba(0, 0, 0, 0.07);\n font-weight: bold;\n white-space: nowrap;\n }\n\n .meter.done > span:after,\n .done .animate > span > span {\n display: none;\n }\n\n .meter.done > span {\n background: rgb(var(--success-rgb));\n }\n `;\n\n @property({ type: Number })\n total = 100;\n\n @property({ type: Number })\n current = 0;\n\n @property({ type: Number })\n pct = 0;\n\n @property({ type: Boolean })\n done = false;\n\n @property({ type: String })\n eta: string;\n\n @property({ type: String, attribute: false })\n estimatedCompletionDate: Date;\n\n @property({ type: Boolean })\n showEstimatedCompletion = false;\n\n public updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n if (changes.has('eta') && this.eta) {\n this.estimatedCompletionDate = new Date(this.eta);\n this.showEstimatedCompletion = this.estimatedCompletionDate > new Date();\n }\n\n if (changes.has('current')) {\n this.pct = Math.floor(Math.min((this.current / this.total) * 100, 100));\n this.done = this.pct >= 100;\n }\n }\n\n public render(): TemplateResult {\n return html`<div class=\"meter ${this.done ? 'done' : ''}\">\n <span class=\"complete\" style=\"width: ${this.pct}%\"></span>\n <div class=\"incomplete\"></div>\n ${this.pct >= 0 || this.estimatedCompletionDate\n ? html` <div class=\"etc\">\n ${this.estimatedCompletionDate\n ? html`<temba-date\n value=\"${this.estimatedCompletionDate.toISOString()}\"\n display=\"countdown\"\n ></temba-date>`\n : html`${this.pct}%`}\n </div>`\n : null}\n </div>`;\n }\n}\n"]}
1
+ {"version":3,"file":"ProgressBar.js","sourceRoot":"","sources":["../../../src/progress/ProgressBar.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, PropertyValueMap, TemplateResult } from 'lit';\nimport { RapidElement } from '../RapidElement';\nimport { property } from 'lit/decorators.js';\n\nexport class ProgressBar extends RapidElement {\n static styles = css`\n .wrapper {\n display: flex;\n box-sizing: content-box;\n background: #f1f1f1;\n border-radius: var(--curvature);\n box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.05);\n }\n\n .meter {\n flex-grow: 1;\n display: flex;\n box-sizing: content-box;\n position: relative;\n border-radius: var(--curvature);\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n padding: 4px;\n min-height: 6px;\n }\n .meter > span {\n display: block;\n height: 100%;\n border-radius: var(--curvature);\n background-color: var(--color-primary-dark);\n background-image: linear-gradient(\n center bottom,\n rgb(43, 194, 83) 37%,\n rgb(84, 240, 83) 69%\n );\n\n position: relative;\n overflow: hidden;\n min-width: 3px;\n }\n\n .meter > span:after,\n .animate > span > span {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n right: 0;\n background-image: linear-gradient(\n -45deg,\n rgba(255, 255, 255, 0.2) 25%,\n transparent 25%,\n transparent 50%,\n rgba(255, 255, 255, 0.2) 50%,\n rgba(255, 255, 255, 0.2) 75%,\n transparent 75%,\n transparent\n );\n z-index: 1;\n background-size: 50px 50px;\n animation: move 16s linear infinite;\n border-top-right-radius: var(--curvature);\n border-bottom-right-radius: var(--curvature);\n border-top-left-radius: var(--curvature);\n border-bottom-left-radius: var(--curvature);\n overflow: hidden;\n }\n\n .animate > span:after {\n display: none;\n }\n\n @keyframes move {\n 0% {\n background-position: 0 0;\n }\n 100% {\n background-position: 50px 50px;\n }\n }\n\n .complete {\n transition: width 2s;\n }\n\n .incomplete {\n flex-grow: 1;\n }\n\n .etc {\n font-size: 0.7em;\n background: rgba(0, 0, 0, 0.07);\n font-weight: bold;\n white-space: nowrap;\n border-top-right-radius: var(--curvature);\n border-bottom-right-radius: var(--curvature);\n color: rgba(0, 0, 0, 0.5);\n align-self: center;\n padding: 2px 6px;\n }\n\n .meter.done > span:after,\n .done .animate > span > span {\n display: none;\n }\n\n .meter.done > span {\n background: rgb(var(--success-rgb));\n }\n `;\n\n @property({ type: Number })\n total = 100;\n\n @property({ type: Number })\n current = 0;\n\n @property({ type: Number })\n pct = 0;\n\n @property({ type: Boolean })\n done = false;\n\n @property({ type: String })\n eta: string;\n\n @property({ type: String, attribute: false })\n estimatedCompletionDate: Date;\n\n @property({ type: Boolean })\n showEstimatedCompletion = false;\n\n @property({ type: Boolean })\n showPercentage = false;\n\n public updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n if (changes.has('eta') && this.eta) {\n this.estimatedCompletionDate = new Date(this.eta);\n this.showEstimatedCompletion = this.estimatedCompletionDate > new Date();\n }\n\n if (changes.has('current')) {\n const pct = Math.floor(Math.min((this.current / this.total) * 100, 100));\n if (Number.isNaN(pct)) {\n this.showPercentage = false;\n } else {\n this.pct = pct;\n this.showPercentage = true;\n }\n\n this.done = this.pct >= 100;\n }\n }\n\n public render(): TemplateResult {\n return html`<div class=\"wrapper\">\n <div class=\"meter ${this.done ? 'done' : ''}\">\n <span class=\"complete\" style=\"flex-basis: ${this.pct}%\"></span>\n <div class=\"incomplete\"></div>\n </div>\n\n ${this.showPercentage || this.showEstimatedCompletion\n ? html`<div class=\"etc\">\n ${this.estimatedCompletionDate &&\n this.showEstimatedCompletion &&\n !this.done\n ? html`<temba-date\n value=\"${this.estimatedCompletionDate.toISOString()}\"\n display=\"countdown\"\n ></temba-date>`\n : html`${this.pct}%`}\n </div>`\n : null}\n </div>`;\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nyaruka/temba-components",
3
- "version": "0.107.0",
3
+ "version": "0.107.1",
4
4
  "description": "Web components to support rapidpro and related projects",
5
5
  "author": "Nyaruka <code@nyaruka.coim>",
6
6
  "main": "dist/index.js",
@@ -39,12 +39,21 @@ export class FlowStartProgress extends RapidElement {
39
39
 
40
40
  const elapsed =
41
41
  new Date().getTime() - new Date(start.created_on).getTime();
42
- const rate = this.started / (elapsed / 1000);
42
+ const rate = this.started / elapsed;
43
43
 
44
44
  // calculate the estimated time of arrival
45
- this.eta = new Date(
46
- new Date().getTime() + ((this.total - this.started) / rate) * 1000
47
- ).toISOString();
45
+ const eta = new Date(
46
+ new Date().getTime() + (this.total - this.started) / rate
47
+ );
48
+
49
+ // Don't bother with estimates months out
50
+ const nextMonth = new Date();
51
+ nextMonth.setMonth(nextMonth.getMonth() + 2);
52
+ if (eta > nextMonth) {
53
+ this.eta = null;
54
+ } else {
55
+ this.eta = eta.toISOString();
56
+ }
48
57
 
49
58
  if (this.started < this.total) {
50
59
  // refresh with a backoff up to 1 minute
@@ -4,23 +4,29 @@ import { property } from 'lit/decorators.js';
4
4
 
5
5
  export class ProgressBar extends RapidElement {
6
6
  static styles = css`
7
+ .wrapper {
8
+ display: flex;
9
+ box-sizing: content-box;
10
+ background: #f1f1f1;
11
+ border-radius: var(--curvature);
12
+ box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.05);
13
+ }
14
+
7
15
  .meter {
16
+ flex-grow: 1;
8
17
  display: flex;
9
18
  box-sizing: content-box;
10
- height: 8px;
11
19
  position: relative;
12
- background: #f1f1f1;
13
20
  border-radius: var(--curvature);
21
+ border-top-right-radius: 0;
22
+ border-bottom-right-radius: 0;
14
23
  padding: 4px;
15
- box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.05);
24
+ min-height: 6px;
16
25
  }
17
26
  .meter > span {
18
27
  display: block;
19
28
  height: 100%;
20
- border-top-right-radius: var(--curvature);
21
- border-bottom-right-radius: var(--curvature);
22
- border-top-left-radius: var(--curvature);
23
- border-bottom-left-radius: var(--curvature);
29
+ border-radius: var(--curvature);
24
30
  background-color: var(--color-primary-dark);
25
31
  background-image: linear-gradient(
26
32
  center bottom,
@@ -30,7 +36,9 @@ export class ProgressBar extends RapidElement {
30
36
 
31
37
  position: relative;
32
38
  overflow: hidden;
39
+ min-width: 3px;
33
40
  }
41
+
34
42
  .meter > span:after,
35
43
  .animate > span > span {
36
44
  content: '';
@@ -82,17 +90,14 @@ export class ProgressBar extends RapidElement {
82
90
 
83
91
  .etc {
84
92
  font-size: 0.7em;
85
- padding: 4px;
86
- padding-top: 1px;
87
- padding-left: 8px;
88
- padding-right: 8px;
89
- margin-top: -4px;
90
- margin-bottom: -4px;
91
- margin-right: -4px;
92
- margin-left: 0.5em;
93
93
  background: rgba(0, 0, 0, 0.07);
94
94
  font-weight: bold;
95
95
  white-space: nowrap;
96
+ border-top-right-radius: var(--curvature);
97
+ border-bottom-right-radius: var(--curvature);
98
+ color: rgba(0, 0, 0, 0.5);
99
+ align-self: center;
100
+ padding: 2px 6px;
96
101
  }
97
102
 
98
103
  .meter.done > span:after,
@@ -126,6 +131,9 @@ export class ProgressBar extends RapidElement {
126
131
  @property({ type: Boolean })
127
132
  showEstimatedCompletion = false;
128
133
 
134
+ @property({ type: Boolean })
135
+ showPercentage = false;
136
+
129
137
  public updated(
130
138
  changes: PropertyValueMap<any> | Map<PropertyKey, unknown>
131
139
  ): void {
@@ -135,18 +143,30 @@ export class ProgressBar extends RapidElement {
135
143
  }
136
144
 
137
145
  if (changes.has('current')) {
138
- this.pct = Math.floor(Math.min((this.current / this.total) * 100, 100));
146
+ const pct = Math.floor(Math.min((this.current / this.total) * 100, 100));
147
+ if (Number.isNaN(pct)) {
148
+ this.showPercentage = false;
149
+ } else {
150
+ this.pct = pct;
151
+ this.showPercentage = true;
152
+ }
153
+
139
154
  this.done = this.pct >= 100;
140
155
  }
141
156
  }
142
157
 
143
158
  public render(): TemplateResult {
144
- return html`<div class="meter ${this.done ? 'done' : ''}">
145
- <span class="complete" style="width: ${this.pct}%"></span>
146
- <div class="incomplete"></div>
147
- ${this.pct >= 0 || this.estimatedCompletionDate
148
- ? html` <div class="etc">
149
- ${this.estimatedCompletionDate
159
+ return html`<div class="wrapper">
160
+ <div class="meter ${this.done ? 'done' : ''}">
161
+ <span class="complete" style="flex-basis: ${this.pct}%"></span>
162
+ <div class="incomplete"></div>
163
+ </div>
164
+
165
+ ${this.showPercentage || this.showEstimatedCompletion
166
+ ? html`<div class="etc">
167
+ ${this.estimatedCompletionDate &&
168
+ this.showEstimatedCompletion &&
169
+ !this.done
150
170
  ? html`<temba-date
151
171
  value="${this.estimatedCompletionDate.toISOString()}"
152
172
  display="countdown"