@nyaruka/temba-components 0.35.0 → 0.35.2
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.
- package/CHANGELOG.md +15 -0
- package/dist/{30636513.js → 41042aab.js} +89 -64
- package/dist/index.js +89 -64
- package/dist/sw.js +1 -1
- package/dist/sw.js.map +1 -1
- package/dist/templates/components-body.html +1 -1
- package/dist/templates/components-head.html +1 -1
- package/out-tsc/src/contacts/ContactPending.js +30 -35
- package/out-tsc/src/contacts/ContactPending.js.map +1 -1
- package/out-tsc/src/contacts/events.js +24 -10
- package/out-tsc/src/contacts/events.js.map +1 -1
- package/out-tsc/src/date/TembaDate.js +37 -11
- package/out-tsc/src/date/TembaDate.js.map +1 -1
- package/out-tsc/src/dropdown/Dropdown.js +30 -5
- package/out-tsc/src/dropdown/Dropdown.js.map +1 -1
- package/out-tsc/src/list/RunList.js +17 -16
- package/out-tsc/src/list/RunList.js.map +1 -1
- package/out-tsc/src/store/Store.js +12 -26
- package/out-tsc/src/store/Store.js.map +1 -1
- package/out-tsc/src/vectoricon/index.js +3 -0
- package/out-tsc/src/vectoricon/index.js.map +1 -1
- package/out-tsc/test/temba-contact-history.test.js +5 -8
- package/out-tsc/test/temba-contact-history.test.js.map +1 -1
- package/out-tsc/test/temba-date.test.js +3 -9
- package/out-tsc/test/temba-date.test.js.map +1 -1
- package/out-tsc/test/utils.test.js +9 -0
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +1 -1
- package/screenshots/truth/contacts/contact-active-default.png +0 -0
- package/screenshots/truth/contacts/contact-active-show-chat-history.png +0 -0
- package/screenshots/truth/contacts/contact-active-show-chat-msg.png +0 -0
- package/screenshots/truth/contacts/contact-archived-hide-chat-msg.png +0 -0
- package/screenshots/truth/contacts/contact-archived-show-chat-history.png +0 -0
- package/screenshots/truth/contacts/contact-blocked-hide-chat-msg.png +0 -0
- package/screenshots/truth/contacts/contact-blocked-show-chat-history.png +0 -0
- package/screenshots/truth/contacts/contact-stopped-hide-chat-msg.png +0 -0
- package/screenshots/truth/contacts/contact-stopped-show-chat-history.png +0 -0
- package/screenshots/truth/contacts/fields-updated.png +0 -0
- package/screenshots/truth/contacts/history-expanded.png +0 -0
- package/screenshots/truth/contacts/history.png +0 -0
- package/screenshots/truth/date/duration.png +0 -0
- package/src/contacts/ContactPending.ts +38 -34
- package/src/contacts/events.ts +24 -10
- package/src/date/TembaDate.ts +40 -11
- package/src/dropdown/Dropdown.ts +29 -5
- package/src/list/RunList.ts +17 -28
- package/src/store/Store.ts +13 -37
- package/src/vectoricon/index.ts +3 -0
- package/test/temba-contact-history.test.ts +7 -7
- package/test/temba-date.test.ts +3 -8
- package/test/utils.test.ts +10 -1
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import '../temba-modules';
|
|
2
|
+
import { DateTime } from 'luxon';
|
|
3
|
+
import * as sinon from 'sinon';
|
|
2
4
|
import { stub } from 'sinon';
|
|
3
5
|
import { expect, fixture, html, assert } from '@open-wc/testing';
|
|
4
6
|
import MouseHelper from './MouseHelper';
|
|
@@ -160,4 +162,11 @@ export const loadStore = async () => {
|
|
|
160
162
|
await store.httpComplete;
|
|
161
163
|
return store;
|
|
162
164
|
};
|
|
165
|
+
export const mockNow = (isodate) => {
|
|
166
|
+
const now = DateTime.fromISO(isodate);
|
|
167
|
+
// mock the current time
|
|
168
|
+
sinon.replace(DateTime, 'now', () => {
|
|
169
|
+
return now;
|
|
170
|
+
});
|
|
171
|
+
};
|
|
163
172
|
//# sourceMappingURL=utils.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../test/utils.test.ts"],"names":[],"mappings":"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","sourcesContent":["import '../temba-modules';\n\ninterface Clip {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nimport { stub } from 'sinon';\nimport { expect, fixture, html, assert } from '@open-wc/testing';\nimport MouseHelper from './MouseHelper';\nimport { Store } from '../src/store/Store';\n\nexport interface CodeMock {\n endpoint: RegExp;\n body: string;\n headers: any;\n}\n\nconst gets: CodeMock[] = [];\nconst posts: CodeMock[] = [];\nlet normalFetch;\n\nexport const showMouse = async () => {\n const mouse = await fixture(html`<mouse-helper />`);\n assert.instanceOf(mouse, MouseHelper);\n};\n\nexport const getAttributes = (attrs: any = {}) => {\n return `${Object.keys(attrs)\n .map((name: string) => {\n if (typeof attrs[name] === 'boolean' && attrs[name]) {\n return name;\n }\n return `${name}='${attrs[name]}'`;\n })\n .join(' ')}`;\n};\n\nexport const getComponent = async (\n tag,\n attrs: any = {},\n slot = '',\n width = 250,\n height = 0,\n style = ''\n) => {\n const spec = `<${tag} ${getAttributes(attrs)}>${slot}</${tag}>`;\n const parentNode = document.createElement('div');\n const styleAttribute = `\n ${width > 0 ? `width:${width}px;` : ``} \n ${height > 0 ? `height:${height}px;` : ``}\n ${style ? style : ``}\n `;\n\n parentNode.setAttribute('style', styleAttribute);\n return await fixture(spec, { parentNode });\n};\n\nconst createResponse = mocked => {\n const mockResponse = new window.Response(mocked.body, {\n status: 200,\n headers: {\n 'Content-type': 'text/html',\n ...mocked.headers,\n },\n });\n\n return Promise.resolve(mockResponse);\n};\n\nconst createJSONResponse = mocked => {\n const mockResponse = new window.Response(JSON.stringify(mocked.body), {\n status: 200,\n headers: {\n 'Content-type': 'application/json',\n ...mocked.headers,\n },\n });\n\n return Promise.resolve(mockResponse);\n};\n\nconst getResponse = (endpoint: string, options) => {\n // check if our path has been mocked in code\n const mocks = options.method === 'GET' ? gets : posts;\n const codeMock = mocks.find(mock => mock.endpoint.test(endpoint));\n\n if (codeMock) {\n if (typeof codeMock.body === 'string') {\n // see if we are being mocked to a file\n if (codeMock.body.startsWith('/')) {\n endpoint = codeMock.body;\n } else {\n return createResponse(codeMock);\n }\n } else {\n return createJSONResponse(codeMock);\n }\n }\n\n // otherwise fetch over http\n return normalFetch(endpoint, options);\n};\n\nbefore(async () => {\n normalFetch = window.fetch;\n stub(window, 'fetch').callsFake(getResponse);\n await setViewport({ width: 1024, height: 768, deviceScaleFactor: 2 });\n});\n\nafter(() => {\n (window.fetch as any).restore();\n});\n\nexport const mockGET = (endpoint: RegExp, body: any, headers: any = {}) => {\n gets.push({ endpoint, body, headers });\n};\n\nexport const mockPOST = (endpoint: RegExp, body: any, headers: any = {}) => {\n posts.push({ endpoint, body, headers });\n};\n\nexport const checkTimers = (clock: any) => {\n expect(\n Object.keys(clock.timers).length,\n `Timers still to be run ${JSON.stringify(clock.timers)}`\n ).to.equal(0);\n};\n\nexport const delay = (millis: number) => {\n return new Promise(function (resolve) {\n setTimeout(resolve, millis);\n });\n};\n\nexport const assertScreenshot = async (\n filename: string,\n clip: Clip,\n threshold = 0.1,\n exclude: Clip[] = []\n) => {\n // const screenShotsEnabled = !!__karma__.config.args.find(\n // (option: string) => option === '--screenshots'\n // );\n\n await (window as any).waitFor(200);\n\n // console.log((window as any).watched);\n if ((window as any).watched) {\n // return;\n }\n\n const mochaUI = document.querySelector('#mocha');\n mochaUI.classList.add('screenshots');\n\n try {\n await (window as any).matchPageSnapshot(\n `${filename}.png`,\n clip,\n exclude,\n threshold\n );\n } catch (error) {\n if (error.message) {\n throw new Error(\n `${error.message} ${\n error.expected\n ? `Expected ${error.expected} but got ${error.actual}`\n : ''\n } ${error.files ? `\\n${error.files.join('\\n')}` : ''}`\n );\n }\n throw new Error(error);\n } finally {\n mochaUI.classList.remove('screenshots');\n }\n};\n\nexport const getClip = (ele: HTMLElement) => {\n let clip: any = ele.getBoundingClientRect();\n if (!clip.width || !clip.height) {\n clip = ele.shadowRoot.firstElementChild.getBoundingClientRect();\n }\n\n const padding = 10;\n const width = clip.width + padding * 2;\n const height = clip.height + padding * 2;\n const y = clip.y - padding;\n const x = clip.x - padding;\n\n const newClip = {\n x,\n y,\n width,\n height,\n bottom: y + height,\n right: x + width,\n top: y,\n left: x,\n };\n\n return newClip;\n};\n\nexport const getHTMLAttrs = (attrs: any = {}) => {\n return Object.keys(attrs)\n .map((name: string) => `${name}='${attrs[name]}'`)\n .join(' ');\n};\n\nexport const getHTML = (tag: string, attrs: any = {}) => {\n return `<${tag} ${getHTMLAttrs(attrs)}></${tag}>`;\n};\n\nexport const loadStore = async () => {\n const store: Store = await fixture(\n `<temba-store \n completion='/test-assets/store/editor.json'\n groups='/test-assets/store/groups.json'\n languages='/test-assets/store/languages.json'\n fields='/test-assets/store/fields.json'\n />`\n );\n await store.httpComplete;\n await store.httpComplete;\n\n return store;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../test/utils.test.ts"],"names":[],"mappings":"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","sourcesContent":["import '../temba-modules';\nimport { DateTime } from 'luxon';\nimport * as sinon from 'sinon';\ninterface Clip {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nimport { stub } from 'sinon';\nimport { expect, fixture, html, assert } from '@open-wc/testing';\nimport MouseHelper from './MouseHelper';\nimport { Store } from '../src/store/Store';\n\nexport interface CodeMock {\n endpoint: RegExp;\n body: string;\n headers: any;\n}\n\nconst gets: CodeMock[] = [];\nconst posts: CodeMock[] = [];\nlet normalFetch;\n\nexport const showMouse = async () => {\n const mouse = await fixture(html`<mouse-helper />`);\n assert.instanceOf(mouse, MouseHelper);\n};\n\nexport const getAttributes = (attrs: any = {}) => {\n return `${Object.keys(attrs)\n .map((name: string) => {\n if (typeof attrs[name] === 'boolean' && attrs[name]) {\n return name;\n }\n return `${name}='${attrs[name]}'`;\n })\n .join(' ')}`;\n};\n\nexport const getComponent = async (\n tag,\n attrs: any = {},\n slot = '',\n width = 250,\n height = 0,\n style = ''\n) => {\n const spec = `<${tag} ${getAttributes(attrs)}>${slot}</${tag}>`;\n const parentNode = document.createElement('div');\n const styleAttribute = `\n ${width > 0 ? `width:${width}px;` : ``} \n ${height > 0 ? `height:${height}px;` : ``}\n ${style ? style : ``}\n `;\n\n parentNode.setAttribute('style', styleAttribute);\n return await fixture(spec, { parentNode });\n};\n\nconst createResponse = mocked => {\n const mockResponse = new window.Response(mocked.body, {\n status: 200,\n headers: {\n 'Content-type': 'text/html',\n ...mocked.headers,\n },\n });\n\n return Promise.resolve(mockResponse);\n};\n\nconst createJSONResponse = mocked => {\n const mockResponse = new window.Response(JSON.stringify(mocked.body), {\n status: 200,\n headers: {\n 'Content-type': 'application/json',\n ...mocked.headers,\n },\n });\n\n return Promise.resolve(mockResponse);\n};\n\nconst getResponse = (endpoint: string, options) => {\n // check if our path has been mocked in code\n const mocks = options.method === 'GET' ? gets : posts;\n const codeMock = mocks.find(mock => mock.endpoint.test(endpoint));\n\n if (codeMock) {\n if (typeof codeMock.body === 'string') {\n // see if we are being mocked to a file\n if (codeMock.body.startsWith('/')) {\n endpoint = codeMock.body;\n } else {\n return createResponse(codeMock);\n }\n } else {\n return createJSONResponse(codeMock);\n }\n }\n\n // otherwise fetch over http\n return normalFetch(endpoint, options);\n};\n\nbefore(async () => {\n normalFetch = window.fetch;\n stub(window, 'fetch').callsFake(getResponse);\n await setViewport({ width: 1024, height: 768, deviceScaleFactor: 2 });\n});\n\nafter(() => {\n (window.fetch as any).restore();\n});\n\nexport const mockGET = (endpoint: RegExp, body: any, headers: any = {}) => {\n gets.push({ endpoint, body, headers });\n};\n\nexport const mockPOST = (endpoint: RegExp, body: any, headers: any = {}) => {\n posts.push({ endpoint, body, headers });\n};\n\nexport const checkTimers = (clock: any) => {\n expect(\n Object.keys(clock.timers).length,\n `Timers still to be run ${JSON.stringify(clock.timers)}`\n ).to.equal(0);\n};\n\nexport const delay = (millis: number) => {\n return new Promise(function (resolve) {\n setTimeout(resolve, millis);\n });\n};\n\nexport const assertScreenshot = async (\n filename: string,\n clip: Clip,\n threshold = 0.1,\n exclude: Clip[] = []\n) => {\n // const screenShotsEnabled = !!__karma__.config.args.find(\n // (option: string) => option === '--screenshots'\n // );\n\n await (window as any).waitFor(200);\n\n // console.log((window as any).watched);\n if ((window as any).watched) {\n // return;\n }\n\n const mochaUI = document.querySelector('#mocha');\n mochaUI.classList.add('screenshots');\n\n try {\n await (window as any).matchPageSnapshot(\n `${filename}.png`,\n clip,\n exclude,\n threshold\n );\n } catch (error) {\n if (error.message) {\n throw new Error(\n `${error.message} ${\n error.expected\n ? `Expected ${error.expected} but got ${error.actual}`\n : ''\n } ${error.files ? `\\n${error.files.join('\\n')}` : ''}`\n );\n }\n throw new Error(error);\n } finally {\n mochaUI.classList.remove('screenshots');\n }\n};\n\nexport const getClip = (ele: HTMLElement) => {\n let clip: any = ele.getBoundingClientRect();\n if (!clip.width || !clip.height) {\n clip = ele.shadowRoot.firstElementChild.getBoundingClientRect();\n }\n\n const padding = 10;\n const width = clip.width + padding * 2;\n const height = clip.height + padding * 2;\n const y = clip.y - padding;\n const x = clip.x - padding;\n\n const newClip = {\n x,\n y,\n width,\n height,\n bottom: y + height,\n right: x + width,\n top: y,\n left: x,\n };\n\n return newClip;\n};\n\nexport const getHTMLAttrs = (attrs: any = {}) => {\n return Object.keys(attrs)\n .map((name: string) => `${name}='${attrs[name]}'`)\n .join(' ');\n};\n\nexport const getHTML = (tag: string, attrs: any = {}) => {\n return `<${tag} ${getHTMLAttrs(attrs)}></${tag}>`;\n};\n\nexport const loadStore = async () => {\n const store: Store = await fixture(\n `<temba-store \n completion='/test-assets/store/editor.json'\n groups='/test-assets/store/groups.json'\n languages='/test-assets/store/languages.json'\n fields='/test-assets/store/fields.json'\n />`\n );\n await store.httpComplete;\n await store.httpComplete;\n\n return store;\n};\n\nexport const mockNow = (isodate: string) => {\n const now = DateTime.fromISO(isodate);\n // mock the current time\n sinon.replace(DateTime, 'now', () => {\n return now;\n });\n};\n"]}
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { css, html, PropertyValueMap, TemplateResult } from 'lit';
|
|
2
2
|
import { property } from 'lit/decorators';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
CustomEventType,
|
|
5
|
+
ScheduledEvent,
|
|
6
|
+
ScheduledEventType,
|
|
7
|
+
} from '../interfaces';
|
|
4
8
|
import { StoreElement } from '../store/StoreElement';
|
|
5
9
|
import { Icon } from '../vectoricon';
|
|
6
10
|
|
|
@@ -92,6 +96,12 @@ export class ContactPending extends StoreElement {
|
|
|
92
96
|
0 0 0px 1px rgba(0, 0, 0, 0.02);
|
|
93
97
|
}
|
|
94
98
|
|
|
99
|
+
.event:hover {
|
|
100
|
+
cursor: pointer;
|
|
101
|
+
box-shadow: 0 0 8px 1px rgba(0, 0, 0, 0.055),
|
|
102
|
+
0 0 0px 2px var(--color-link-primary);
|
|
103
|
+
}
|
|
104
|
+
|
|
95
105
|
.time {
|
|
96
106
|
white-space: nowrap;
|
|
97
107
|
background: rgba(0, 0, 0, 0.02);
|
|
@@ -128,18 +138,17 @@ export class ContactPending extends StoreElement {
|
|
|
128
138
|
margin-right: 0.25em;
|
|
129
139
|
}
|
|
130
140
|
|
|
131
|
-
.campaign_event .scheduled-by:hover {
|
|
132
|
-
color: var(--color-link-primary);
|
|
133
|
-
--icon-color: var(--color-link-primary);
|
|
134
|
-
cursor: pointer;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
141
|
.scheduled-by .name {
|
|
138
142
|
flex-grow: 1;
|
|
139
143
|
}
|
|
140
144
|
`;
|
|
141
145
|
}
|
|
142
146
|
|
|
147
|
+
constructor() {
|
|
148
|
+
super();
|
|
149
|
+
this.handleEventClicked = this.handleEventClicked.bind(this);
|
|
150
|
+
}
|
|
151
|
+
|
|
143
152
|
protected updated(
|
|
144
153
|
changes: PropertyValueMap<any> | Map<PropertyKey, unknown>
|
|
145
154
|
): void {
|
|
@@ -153,52 +162,47 @@ export class ContactPending extends StoreElement {
|
|
|
153
162
|
}
|
|
154
163
|
}
|
|
155
164
|
|
|
156
|
-
public
|
|
165
|
+
public handleEventClicked(event: ScheduledEvent) {
|
|
166
|
+
this.fireCustomEvent(CustomEventType.Selection, event);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
public renderEvent(scheduledEvent: ScheduledEvent) {
|
|
157
170
|
return html`
|
|
158
|
-
<div
|
|
171
|
+
<div
|
|
172
|
+
class="event ${scheduledEvent.type}"
|
|
173
|
+
@click="${() => this.handleEventClicked(scheduledEvent)}"
|
|
174
|
+
>
|
|
159
175
|
<div class="type">
|
|
160
176
|
<temba-icon
|
|
161
177
|
size="2"
|
|
162
|
-
name="${
|
|
178
|
+
name="${scheduledEvent.message ? Icon.message : Icon.flow}"
|
|
163
179
|
></temba-icon>
|
|
164
180
|
</div>
|
|
165
181
|
|
|
166
182
|
<div class="details">
|
|
167
183
|
<div>
|
|
168
|
-
${
|
|
169
|
-
? html`
|
|
170
|
-
<div
|
|
171
|
-
class="flow linked"
|
|
172
|
-
href="/flow/editor/${event.flow.uuid}/"
|
|
173
|
-
onclick="goto(event)"
|
|
174
|
-
>
|
|
175
|
-
${event.flow.name}
|
|
176
|
-
</div>
|
|
177
|
-
`
|
|
184
|
+
${scheduledEvent.flow
|
|
185
|
+
? html` Start ${scheduledEvent.flow.name}`
|
|
178
186
|
: null}
|
|
179
|
-
${
|
|
180
|
-
? html` <div class="message">${
|
|
187
|
+
${scheduledEvent.message
|
|
188
|
+
? html` <div class="message">${scheduledEvent.message}</div> `
|
|
181
189
|
: null}
|
|
182
190
|
</div>
|
|
183
191
|
|
|
184
192
|
<div class="scheduled-by">
|
|
185
|
-
${
|
|
186
|
-
? html`<div
|
|
187
|
-
style="display:flex"
|
|
188
|
-
href="/campaign/read/${event.campaign.uuid}/"
|
|
189
|
-
onclick="goto(event, this)"
|
|
190
|
-
>
|
|
193
|
+
${scheduledEvent.campaign
|
|
194
|
+
? html`<div style="display:flex">
|
|
191
195
|
<temba-icon name="${Icon.campaign}"></temba-icon>
|
|
192
|
-
<div class="name">${
|
|
196
|
+
<div class="name">${scheduledEvent.campaign.name}</div>
|
|
193
197
|
</div>`
|
|
194
198
|
: html`
|
|
195
|
-
${
|
|
199
|
+
${scheduledEvent.type === ScheduledEventType.ScheduledTrigger
|
|
196
200
|
? html`<temba-icon
|
|
197
|
-
name="${ICONS[
|
|
201
|
+
name="${ICONS[scheduledEvent.type]}"
|
|
198
202
|
></temba-icon>`
|
|
199
203
|
: null}
|
|
200
204
|
<div class="name">
|
|
201
|
-
${this.REPEAT_PERIOD[
|
|
205
|
+
${this.REPEAT_PERIOD[scheduledEvent.repeat_period]}
|
|
202
206
|
</div>
|
|
203
207
|
`}
|
|
204
208
|
</div>
|
|
@@ -207,10 +211,10 @@ export class ContactPending extends StoreElement {
|
|
|
207
211
|
<div class="time">
|
|
208
212
|
<div class="duration">
|
|
209
213
|
<temba-tip
|
|
210
|
-
text=${this.store.formatDate(
|
|
214
|
+
text=${this.store.formatDate(scheduledEvent.scheduled)}
|
|
211
215
|
position="left"
|
|
212
216
|
>
|
|
213
|
-
${this.store.getShortDurationFromIso(
|
|
217
|
+
${this.store.getShortDurationFromIso(scheduledEvent.scheduled)}
|
|
214
218
|
</temba-tip>
|
|
215
219
|
</div>
|
|
216
220
|
</div>
|
package/src/contacts/events.ts
CHANGED
|
@@ -239,8 +239,8 @@ export const getEventStyles = () => {
|
|
|
239
239
|
.tickets .note-summary {
|
|
240
240
|
display: flex;
|
|
241
241
|
flex-direction: row;
|
|
242
|
-
|
|
243
|
-
|
|
242
|
+
font-size: 85%;
|
|
243
|
+
margin-top: -0.5em;
|
|
244
244
|
color: rgba(0, 0, 0, 0.6);
|
|
245
245
|
padding: 8px 3px;
|
|
246
246
|
}
|
|
@@ -310,12 +310,11 @@ export const getEventStyles = () => {
|
|
|
310
310
|
|
|
311
311
|
.msg-summary {
|
|
312
312
|
display: flex;
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
font-size: 80%;
|
|
313
|
+
font-size: 85%;
|
|
316
314
|
color: rgba(0, 0, 0, 0.6);
|
|
317
315
|
padding: 6px 3px;
|
|
318
316
|
margin-bottom: 0.5em;
|
|
317
|
+
margin-top: -0.5em;
|
|
319
318
|
}
|
|
320
319
|
|
|
321
320
|
.msg-summary temba-icon.log {
|
|
@@ -776,7 +775,11 @@ export const renderMsgEvent = (
|
|
|
776
775
|
<div class="separator">•</div>`);
|
|
777
776
|
}
|
|
778
777
|
summary.push(
|
|
779
|
-
html`<
|
|
778
|
+
html`<temba-date
|
|
779
|
+
class="time"
|
|
780
|
+
value="${event.created_on}"
|
|
781
|
+
display="duration"
|
|
782
|
+
></temba-date>`
|
|
780
783
|
);
|
|
781
784
|
|
|
782
785
|
return html`<div style="display:flex;align-items:flex-start">
|
|
@@ -938,7 +941,11 @@ export const renderNoteCreated = (
|
|
|
938
941
|
<div class="description">${event.note}</div>
|
|
939
942
|
<div class="note-summary">
|
|
940
943
|
<div style="flex-grow:1"></div>
|
|
941
|
-
<
|
|
944
|
+
<temba-date
|
|
945
|
+
class="time"
|
|
946
|
+
value="${event.created_on}"
|
|
947
|
+
display="duration"
|
|
948
|
+
></temba-date>
|
|
942
949
|
</div>
|
|
943
950
|
</div>
|
|
944
951
|
<div style="margin-left:0.8em;margin-top:0.3em;font-size:0.8em">
|
|
@@ -986,14 +993,17 @@ export const renderTicketAction = (
|
|
|
986
993
|
${getDisplayName(event.created_by)} ${action} this ticket
|
|
987
994
|
</div>
|
|
988
995
|
<div class="subtext" style="justify-content:center">
|
|
989
|
-
|
|
996
|
+
<temba-date
|
|
997
|
+
class="time"
|
|
998
|
+
value="${reopened}"
|
|
999
|
+
display="duration"
|
|
1000
|
+
></temba-date>
|
|
990
1001
|
</div>
|
|
991
1002
|
</div>
|
|
992
1003
|
`;
|
|
993
1004
|
};
|
|
994
1005
|
|
|
995
1006
|
export const renderTicketAssigned = (event: TicketEvent): TemplateResult => {
|
|
996
|
-
const created = new Date(event.created_on);
|
|
997
1007
|
return html`
|
|
998
1008
|
<div class="assigned active">
|
|
999
1009
|
<div style="text-align:center">
|
|
@@ -1005,7 +1015,11 @@ export const renderTicketAssigned = (event: TicketEvent): TemplateResult => {
|
|
|
1005
1015
|
: html`${getDisplayName(event.created_by)} unassigned this ticket`}
|
|
1006
1016
|
</div>
|
|
1007
1017
|
<div class="subtext" style="justify-content:center">
|
|
1008
|
-
|
|
1018
|
+
<temba-date
|
|
1019
|
+
class="time"
|
|
1020
|
+
value="${event.created_on}"
|
|
1021
|
+
display="duration"
|
|
1022
|
+
></temba-date>
|
|
1009
1023
|
</div>
|
|
1010
1024
|
</div>
|
|
1011
1025
|
`;
|
package/src/date/TembaDate.ts
CHANGED
|
@@ -7,7 +7,11 @@ import { DateTime } from 'luxon';
|
|
|
7
7
|
export const Display = {
|
|
8
8
|
date: DateTime.DATE_SHORT,
|
|
9
9
|
datetime: DateTime.DATETIME_SHORT,
|
|
10
|
+
time: DateTime.TIME_SIMPLE,
|
|
11
|
+
timedate: 'timedate',
|
|
10
12
|
duration: 'duration',
|
|
13
|
+
relative: 'relative',
|
|
14
|
+
day: 'LLL d',
|
|
11
15
|
};
|
|
12
16
|
|
|
13
17
|
export class TembaDate extends RapidElement {
|
|
@@ -48,19 +52,44 @@ export class TembaDate extends RapidElement {
|
|
|
48
52
|
}
|
|
49
53
|
|
|
50
54
|
public render(): TemplateResult {
|
|
51
|
-
if (this.datetime) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
if (this.datetime && this.store) {
|
|
56
|
+
this.datetime.setLocale(this.store.getLocale());
|
|
57
|
+
|
|
58
|
+
let formatted = '';
|
|
59
|
+
if (this.display === Display.timedate) {
|
|
60
|
+
const hours = Math.abs(
|
|
61
|
+
this.datetime.diffNow().milliseconds / 1000 / 60 / 60
|
|
62
|
+
);
|
|
63
|
+
if (hours < 24) {
|
|
64
|
+
formatted = this.datetime.toLocaleString(Display.time);
|
|
65
|
+
} else if (hours < 24 * 365) {
|
|
66
|
+
formatted = this.datetime.toFormat(Display.day);
|
|
67
|
+
} else {
|
|
68
|
+
formatted = this.datetime.toLocaleString(Display.date);
|
|
69
|
+
}
|
|
70
|
+
} else if (this.display === Display.relative) {
|
|
71
|
+
const minutes = Math.abs(
|
|
72
|
+
this.datetime.diffNow().milliseconds / 1000 / 60
|
|
73
|
+
);
|
|
74
|
+
if (minutes < 1) {
|
|
75
|
+
return html`<div class="date">just now</div>`;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
formatted = this.store.getShortDuration(this.datetime);
|
|
79
|
+
} else if (this.display === Display.duration) {
|
|
80
|
+
const minutes = Math.abs(
|
|
81
|
+
this.datetime.diffNow().milliseconds / 1000 / 60
|
|
82
|
+
);
|
|
83
|
+
if (minutes < 1) {
|
|
84
|
+
return html`<div class="date">just now</div>`;
|
|
85
|
+
}
|
|
86
|
+
formatted = this.store.getShortDuration(this.datetime);
|
|
87
|
+
} else if (this.display === Display.day) {
|
|
88
|
+
formatted = this.datetime.toLocaleString(Display.day);
|
|
56
89
|
} else {
|
|
57
|
-
|
|
58
|
-
<div class="date">
|
|
59
|
-
${this.datetime.toLocaleString(Display[this.display])}
|
|
60
|
-
</div>
|
|
61
|
-
`;
|
|
90
|
+
formatted = this.datetime.toLocaleString(Display[this.display]);
|
|
62
91
|
}
|
|
92
|
+
return html`<div class="date">${formatted}</div>`;
|
|
63
93
|
}
|
|
64
|
-
return null;
|
|
65
94
|
}
|
|
66
95
|
}
|
package/src/dropdown/Dropdown.ts
CHANGED
|
@@ -5,10 +5,19 @@ import { RapidElement } from '../RapidElement';
|
|
|
5
5
|
export class Dropdown extends RapidElement {
|
|
6
6
|
static get styles() {
|
|
7
7
|
return css`
|
|
8
|
+
.wrapper {
|
|
9
|
+
position: relative;
|
|
10
|
+
}
|
|
11
|
+
|
|
8
12
|
.toggle {
|
|
9
13
|
cursor: pointer;
|
|
10
14
|
}
|
|
11
15
|
|
|
16
|
+
.dropdown-wrapper {
|
|
17
|
+
position: relative;
|
|
18
|
+
overflow: auto;
|
|
19
|
+
}
|
|
20
|
+
|
|
12
21
|
.dropdown {
|
|
13
22
|
position: absolute;
|
|
14
23
|
opacity: 0;
|
|
@@ -52,6 +61,9 @@ export class Dropdown extends RapidElement {
|
|
|
52
61
|
@property({ type: Boolean })
|
|
53
62
|
open = false;
|
|
54
63
|
|
|
64
|
+
@property({ type: String, attribute: 'drop_align' })
|
|
65
|
+
dropAlign = 'left';
|
|
66
|
+
|
|
55
67
|
@property({ type: Number })
|
|
56
68
|
arrowSize = 6;
|
|
57
69
|
|
|
@@ -96,6 +108,8 @@ export class Dropdown extends RapidElement {
|
|
|
96
108
|
// a better way to deal with this
|
|
97
109
|
window.setTimeout(() => {
|
|
98
110
|
this.open = false;
|
|
111
|
+
// blur our host element too
|
|
112
|
+
(this.shadowRoot.host as HTMLDivElement).blur();
|
|
99
113
|
}, 200);
|
|
100
114
|
});
|
|
101
115
|
}
|
|
@@ -111,7 +125,7 @@ export class Dropdown extends RapidElement {
|
|
|
111
125
|
}
|
|
112
126
|
}
|
|
113
127
|
|
|
114
|
-
public
|
|
128
|
+
public handleToggleClicked(): void {
|
|
115
129
|
if (!this.open) {
|
|
116
130
|
this.open = true;
|
|
117
131
|
|
|
@@ -124,11 +138,21 @@ export class Dropdown extends RapidElement {
|
|
|
124
138
|
|
|
125
139
|
public render(): TemplateResult {
|
|
126
140
|
return html`
|
|
127
|
-
<div class
|
|
128
|
-
<slot
|
|
129
|
-
|
|
141
|
+
<div class="wrapper ${this.open ? 'open' : ''}">
|
|
142
|
+
<slot
|
|
143
|
+
name="toggle"
|
|
144
|
+
class="toggle"
|
|
145
|
+
@click="${this.handleToggleClicked}"
|
|
146
|
+
></slot>
|
|
147
|
+
<div
|
|
148
|
+
class="dropdown"
|
|
149
|
+
tabindex="0"
|
|
150
|
+
style="${this.dropAlign == 'right' ? 'right:0' : ''}"
|
|
151
|
+
>
|
|
130
152
|
<div class="arrow"></div>
|
|
131
|
-
<
|
|
153
|
+
<div class="dropdown-wrapper">
|
|
154
|
+
<slot name="dropdown" tabindex="1"></slot>
|
|
155
|
+
</div>
|
|
132
156
|
</div>
|
|
133
157
|
</div>
|
|
134
158
|
`;
|
package/src/list/RunList.ts
CHANGED
|
@@ -141,7 +141,7 @@ export class RunList extends TembaList {
|
|
|
141
141
|
</div>
|
|
142
142
|
|
|
143
143
|
<div style="flex-shrink:1">
|
|
144
|
-
${
|
|
144
|
+
<temba-date value="${run.modified_on}" display="duration" />
|
|
145
145
|
</div>
|
|
146
146
|
${this.getIcon(run)}
|
|
147
147
|
</div>
|
|
@@ -227,7 +227,6 @@ export class RunList extends TembaList {
|
|
|
227
227
|
return null;
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
-
const exitType = this.selectedRun.exit_type;
|
|
231
230
|
const resultKeys = Object.keys(this.selectedRun.values);
|
|
232
231
|
|
|
233
232
|
return html` <div
|
|
@@ -251,35 +250,25 @@ export class RunList extends TembaList {
|
|
|
251
250
|
>
|
|
252
251
|
${this.selectedRun.exit_type
|
|
253
252
|
? html`
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
: null}
|
|
265
|
-
${exitType == 'interrupted' || exitType == 'expired'
|
|
266
|
-
? html` after
|
|
267
|
-
${this.store.getShortDurationFromIso(
|
|
268
|
-
this.selectedRun.created_on,
|
|
269
|
-
this.selectedRun.exited_on,
|
|
270
|
-
true
|
|
271
|
-
)}`
|
|
272
|
-
: null}
|
|
253
|
+
<div style="margin-left:2em;flex-grow:1;display:flex">
|
|
254
|
+
${this.getIcon(this.selectedRun)}
|
|
255
|
+
<div style="margin-left:0.5em">
|
|
256
|
+
${capitalize(this.selectedRun.exit_type)}
|
|
257
|
+
</div>
|
|
258
|
+
<temba-date
|
|
259
|
+
value="${this.selectedRun.exited_on}"
|
|
260
|
+
compare="${this.selectedRun.created_on}"
|
|
261
|
+
display="duration"
|
|
262
|
+
/>
|
|
273
263
|
</div>
|
|
274
264
|
`
|
|
275
265
|
: html`${this.getIcon(this.selectedRun)}
|
|
276
|
-
<div style="margin-left:
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
this.selectedRun.created_on
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
)}
|
|
266
|
+
<div style="margin-left:1.5em;flex-grow:1;display:flex">
|
|
267
|
+
<div>Started </div>
|
|
268
|
+
<temba-date
|
|
269
|
+
value="${this.selectedRun.created_on}"
|
|
270
|
+
display="duration"
|
|
271
|
+
/>
|
|
283
272
|
</div>`}
|
|
284
273
|
</div>
|
|
285
274
|
</div>
|
package/src/store/Store.ts
CHANGED
|
@@ -74,6 +74,10 @@ export class Store extends RapidElement {
|
|
|
74
74
|
|
|
75
75
|
private cache: any;
|
|
76
76
|
|
|
77
|
+
public getLocale() {
|
|
78
|
+
return this.locale[0];
|
|
79
|
+
}
|
|
80
|
+
|
|
77
81
|
public reset() {
|
|
78
82
|
this.cache = Lru(this.max, this.ttl);
|
|
79
83
|
|
|
@@ -192,41 +196,17 @@ export class Store extends RapidElement {
|
|
|
192
196
|
});
|
|
193
197
|
}
|
|
194
198
|
|
|
195
|
-
public getShortDuration(
|
|
196
|
-
scheduled: DateTime,
|
|
197
|
-
compareDate: DateTime = null,
|
|
198
|
-
showSeconds = false
|
|
199
|
-
) {
|
|
199
|
+
public getShortDuration(scheduled: DateTime, compareDate: DateTime = null) {
|
|
200
200
|
const now = compareDate || DateTime.now();
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
return this.humanizer.humanize(duration, {
|
|
205
|
-
language: this.getLanguageCode(),
|
|
206
|
-
largest: 1,
|
|
207
|
-
round: true,
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
if (Math.abs(duration) < 60000) {
|
|
212
|
-
return 'just now';
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
return this.humanizer.humanize(duration, {
|
|
216
|
-
language: this.getLanguageCode(),
|
|
217
|
-
largest: 1,
|
|
218
|
-
round: false,
|
|
219
|
-
});
|
|
201
|
+
return scheduled
|
|
202
|
+
.setLocale(this.locale[0])
|
|
203
|
+
.toRelative({ base: now, style: 'long' });
|
|
220
204
|
}
|
|
221
205
|
|
|
222
|
-
public getShortDurationFromIso(
|
|
223
|
-
isoDateA: string,
|
|
224
|
-
isoDateB: string = null,
|
|
225
|
-
showSeconds = false
|
|
226
|
-
) {
|
|
206
|
+
public getShortDurationFromIso(isoDateA: string, isoDateB: string = null) {
|
|
227
207
|
const scheduled = DateTime.fromISO(isoDateA);
|
|
228
208
|
const now = isoDateB ? DateTime.fromISO(isoDateB) : DateTime.now();
|
|
229
|
-
return this.getShortDuration(scheduled, now
|
|
209
|
+
return this.getShortDuration(scheduled, now);
|
|
230
210
|
}
|
|
231
211
|
|
|
232
212
|
public setKeyedAssets(name: string, values: string[]): void {
|
|
@@ -278,13 +258,9 @@ export class Store extends RapidElement {
|
|
|
278
258
|
}
|
|
279
259
|
|
|
280
260
|
public formatDate(dateString: string) {
|
|
281
|
-
return
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
day: 'numeric',
|
|
285
|
-
hour: 'numeric',
|
|
286
|
-
minute: 'numeric',
|
|
287
|
-
});
|
|
261
|
+
return DateTime.fromISO(dateString)
|
|
262
|
+
.setLocale(this.getLocale())
|
|
263
|
+
.toLocaleString(DateTime.DATETIME_SHORT);
|
|
288
264
|
}
|
|
289
265
|
|
|
290
266
|
public postUrl(
|
package/src/vectoricon/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export enum Icon {
|
|
2
|
+
analytics = 'bar-chart-01',
|
|
2
3
|
account = 'user-01',
|
|
3
4
|
active = 'play',
|
|
4
5
|
add_note = 'file-02',
|
|
@@ -55,9 +56,11 @@ export enum Icon {
|
|
|
55
56
|
org_new = 'stars-02',
|
|
56
57
|
org_suspended = 'slash-circle-01',
|
|
57
58
|
org_verified = 'check-verified-02',
|
|
59
|
+
overview = 'pie-chart-01',
|
|
58
60
|
featured = 'star-01',
|
|
59
61
|
resthooks = 'share-07',
|
|
60
62
|
restore = 'play',
|
|
63
|
+
runs = 'rows-03',
|
|
61
64
|
search = 'search-refraction',
|
|
62
65
|
select_open = 'chevron-down',
|
|
63
66
|
select_clear = 'x',
|