@nyaruka/temba-components 0.130.1 → 0.130.3
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 +34 -4
- package/DEV_DATA.md +89 -0
- package/demo/data/flows/food-order.json +4 -4
- package/demo/data/flows/sample-flow.json +132 -147
- package/dist/temba-components.js +787 -659
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/display/Chat.js +5 -3
- package/out-tsc/src/display/Chat.js.map +1 -1
- package/out-tsc/src/events.js.map +1 -1
- package/out-tsc/src/flow/CanvasNode.js +83 -78
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +1 -0
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeEditor.js +47 -3
- package/out-tsc/src/flow/NodeEditor.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_urn.js +1 -1
- package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_channel.js +1 -1
- package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_field.js +2 -1
- package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_language.js +3 -1
- package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_name.js +1 -1
- package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_status.js +17 -14
- package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
- package/out-tsc/src/flow/actions/set_run_result.js +1 -1
- package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_llm.js +12 -12
- package/out-tsc/src/flow/nodes/split_by_llm.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_response.js +609 -6
- package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
- package/out-tsc/src/flow/operators.js +194 -0
- package/out-tsc/src/flow/operators.js.map +1 -0
- package/out-tsc/src/flow/types.js.map +1 -1
- package/out-tsc/src/form/ArrayEditor.js +84 -19
- package/out-tsc/src/form/ArrayEditor.js.map +1 -1
- package/out-tsc/src/form/Checkbox.js +12 -0
- package/out-tsc/src/form/Checkbox.js.map +1 -1
- package/out-tsc/src/form/FieldRenderer.js +13 -3
- package/out-tsc/src/form/FieldRenderer.js.map +1 -1
- package/out-tsc/src/form/TextInput.js +20 -1
- package/out-tsc/src/form/TextInput.js.map +1 -1
- package/out-tsc/src/form/select/Select.js +7 -0
- package/out-tsc/src/form/select/Select.js.map +1 -1
- package/out-tsc/src/interfaces.js.map +1 -1
- package/out-tsc/src/layout/Dialog.js +3 -4
- package/out-tsc/src/layout/Dialog.js.map +1 -1
- package/out-tsc/src/list/RunList.js +2 -2
- package/out-tsc/src/list/RunList.js.map +1 -1
- package/out-tsc/src/live/ContactChat.js +101 -44
- package/out-tsc/src/live/ContactChat.js.map +1 -1
- package/out-tsc/src/live/ContactDetails.js +7 -0
- package/out-tsc/src/live/ContactDetails.js.map +1 -1
- package/out-tsc/src/live/ContactNameFetch.js +1 -1
- package/out-tsc/src/live/ContactNameFetch.js.map +1 -1
- package/out-tsc/src/webchat/index.js +0 -11
- package/out-tsc/src/webchat/index.js.map +1 -1
- package/out-tsc/test/NodeHelper.js +25 -27
- package/out-tsc/test/NodeHelper.js.map +1 -1
- package/out-tsc/test/nodes/split_by_llm.test.js +12 -4
- package/out-tsc/test/nodes/split_by_llm.test.js.map +1 -1
- package/out-tsc/test/nodes/split_by_llm_categorize.test.js +101 -91
- package/out-tsc/test/nodes/split_by_llm_categorize.test.js.map +1 -1
- package/out-tsc/test/nodes/split_by_random.test.js +120 -112
- package/out-tsc/test/nodes/split_by_random.test.js.map +1 -1
- package/out-tsc/test/nodes/wait_for_digits.test.js +131 -111
- package/out-tsc/test/nodes/wait_for_digits.test.js.map +1 -1
- package/out-tsc/test/nodes/wait_for_response.test.js +549 -85
- package/out-tsc/test/nodes/wait_for_response.test.js.map +1 -1
- package/out-tsc/test/temba-checkbox.test.js +32 -32
- package/out-tsc/test/temba-checkbox.test.js.map +1 -1
- package/out-tsc/test/temba-contact-chat.test.js +2 -1
- package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
- package/out-tsc/test/temba-dropdown.test.js +0 -4
- package/out-tsc/test/temba-dropdown.test.js.map +1 -1
- package/out-tsc/test/temba-flow-editor-node.test.js +9 -4
- package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
- package/out-tsc/test/temba-integration-markdown.test.js +13 -15
- package/out-tsc/test/temba-integration-markdown.test.js.map +1 -1
- package/out-tsc/test/temba-node-editor.test.js +5 -38
- package/out-tsc/test/temba-node-editor.test.js.map +1 -1
- package/out-tsc/test/temba-run-list.test.js +2 -2
- package/out-tsc/test/temba-run-list.test.js.map +1 -1
- package/out-tsc/test/utils.test.js +2 -1
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +6 -2
- package/screenshots/truth/actions/add_contact_groups/editor/descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/long-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/many-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/multiple-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/single-group.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/long-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/many-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/multiple-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/single-group.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/cleanup-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/long-descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/many-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/multiple-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/remove-from-all-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/single-group.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/cleanup-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/long-descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/many-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/multiple-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/remove-from-all-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/single-group.png +0 -0
- package/screenshots/truth/actions/send_email/editor/complex-business-email.png +0 -0
- package/screenshots/truth/actions/send_email/editor/empty-body.png +0 -0
- package/screenshots/truth/actions/send_email/editor/empty-subject.png +0 -0
- package/screenshots/truth/actions/send_email/editor/long-subject.png +0 -0
- package/screenshots/truth/actions/send_email/editor/multiline-body.png +0 -0
- package/screenshots/truth/actions/send_email/editor/multiple-recipients.png +0 -0
- package/screenshots/truth/actions/send_email/editor/simple-email.png +0 -0
- package/screenshots/truth/actions/send_email/editor/with-expressions.png +0 -0
- package/screenshots/truth/actions/send_email/render/complex-business-email.png +0 -0
- package/screenshots/truth/actions/send_email/render/empty-body.png +0 -0
- package/screenshots/truth/actions/send_email/render/empty-subject.png +0 -0
- package/screenshots/truth/actions/send_email/render/long-subject.png +0 -0
- package/screenshots/truth/actions/send_email/render/multiline-body.png +0 -0
- package/screenshots/truth/actions/send_email/render/multiple-recipients.png +0 -0
- package/screenshots/truth/actions/send_email/render/simple-email.png +0 -0
- package/screenshots/truth/actions/send_email/render/with-expressions.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/long-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/multiline-text-with-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/simple-text.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-linebreaks.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-many-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-without-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/long-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/multiline-text-with-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/simple-text.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-with-linebreaks.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-with-many-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-with-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-without-quick-replies.png +0 -0
- package/screenshots/truth/checkbox/checkbox-label-background-hover.png +0 -0
- package/screenshots/truth/checkbox/checkbox-whitespace-label-no-background-hover.png +0 -0
- package/screenshots/truth/checkbox/checkbox-with-help-text.png +0 -0
- package/screenshots/truth/checkbox/checked.png +0 -0
- package/screenshots/truth/checkbox/default.png +0 -0
- package/screenshots/truth/editor/wait.png +0 -0
- package/screenshots/truth/integration/textinput-markdown-errors.png +0 -0
- package/screenshots/truth/lightbox/img-zoomed.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/information-extraction.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/sentiment-analysis.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/summarization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/translation-task.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/information-extraction.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/sentiment-analysis.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/summarization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/translation-task.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/basic-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/custom-input-and-result-name.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/many-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/minimal-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/basic-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/custom-input-and-result-name.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/feedback-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/many-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/minimal-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/ab-test-multiple-variants.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/sampling-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/three-way-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/two-bucket-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/ab-test-multiple-variants.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/sampling-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/three-way-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/two-bucket-split.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/basic-digits-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/phone-number-collection.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/single-digit-with-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/verification-code.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/basic-digits-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/phone-number-collection.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/single-digit-with-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/verification-code.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/basic-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/custom-result-name.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/no-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/short-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/basic-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/custom-result-name.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/no-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/short-timeout.png +0 -0
- package/screenshots/truth/run-list/basic.png +0 -0
- package/screenshots/truth/templates/default.png +0 -0
- package/screenshots/truth/wait-for-response/rules-editor.png +0 -0
- package/screenshots/truth/wait-for-response/timeout-editor-unchecked.png +0 -0
- package/screenshots/truth/wait-for-response/timeout-editor.png +0 -0
- package/scripts/dev-data-sync.mjs +182 -0
- package/src/display/Chat.ts +6 -4
- package/src/events.ts +6 -6
- package/src/flow/CanvasNode.ts +89 -79
- package/src/flow/Editor.ts +1 -0
- package/src/flow/NodeEditor.ts +55 -3
- package/src/flow/actions/add_contact_urn.ts +1 -1
- package/src/flow/actions/set_contact_channel.ts +1 -1
- package/src/flow/actions/set_contact_field.ts +2 -1
- package/src/flow/actions/set_contact_language.ts +3 -1
- package/src/flow/actions/set_contact_name.ts +1 -1
- package/src/flow/actions/set_contact_status.ts +18 -18
- package/src/flow/actions/set_run_result.ts +1 -1
- package/src/flow/nodes/split_by_llm.ts +14 -13
- package/src/flow/nodes/wait_for_response.ts +717 -5
- package/src/flow/operators.ts +215 -0
- package/src/flow/types.ts +10 -2
- package/src/form/ArrayEditor.ts +117 -37
- package/src/form/Checkbox.ts +12 -0
- package/src/form/FieldRenderer.ts +24 -3
- package/src/form/TextInput.ts +19 -1
- package/src/form/select/Select.ts +7 -0
- package/src/interfaces.ts +1 -1
- package/src/layout/Dialog.ts +4 -4
- package/src/list/RunList.ts +2 -2
- package/src/live/ContactChat.ts +128 -67
- package/src/live/ContactDetails.ts +7 -0
- package/src/live/ContactNameFetch.ts +1 -1
- package/src/webchat/index.ts +0 -16
- package/static/api/labels.json +6 -1
- package/test/NodeHelper.ts +38 -40
- package/test/nodes/split_by_llm.test.ts +43 -32
- package/test/nodes/split_by_llm_categorize.test.ts +130 -120
- package/test/nodes/split_by_random.test.ts +136 -128
- package/test/nodes/wait_for_digits.test.ts +147 -127
- package/test/nodes/wait_for_response.test.ts +657 -104
- package/test/temba-checkbox.test.ts +36 -32
- package/test/temba-contact-chat.test.ts +2 -1
- package/test/temba-dropdown.test.ts +0 -12
- package/test/temba-flow-editor-node.test.ts +11 -4
- package/test/temba-integration-markdown.test.ts +16 -17
- package/test/temba-node-editor.test.ts +5 -43
- package/test/temba-run-list.test.ts +2 -2
- package/test/utils.test.ts +2 -1
- package/test-assets/contacts/history.json +4 -7
- package/test-assets/list/runs.json +8 -8
- package/web-dev-mock.mjs +86 -30
- package/web-dev-server.config.mjs +272 -31
- package/screenshots/truth/dropdown/bottom-edge-collision.png +0 -0
- package/screenshots/truth/dropdown/right-edge-collision.png +0 -0
- package/screenshots/truth/editor/send_msg.png +0 -0
- package/screenshots/truth/editor/set_contact_language.png +0 -0
- package/screenshots/truth/editor/set_contact_name.png +0 -0
- package/screenshots/truth/editor/set_run_result.png +0 -0
- package/screenshots/truth/integration/checkbox-markdown-errors.png +0 -0
|
@@ -5,7 +5,6 @@ import { RapidElement } from '../RapidElement';
|
|
|
5
5
|
import { CustomEventType } from '../interfaces';
|
|
6
6
|
import { DEFAULT_AVATAR } from '../webchat/assets';
|
|
7
7
|
import { hashCode } from '../utils';
|
|
8
|
-
import { renderMarkdown } from '../markdown';
|
|
9
8
|
const BATCH_TIME_WINDOW = 60 * 60 * 1000;
|
|
10
9
|
const SCROLL_FETCH_BUFFER = 0.05;
|
|
11
10
|
const MIN_FETCH_TIME = 250;
|
|
@@ -494,7 +493,10 @@ export class Chat extends RapidElement {
|
|
|
494
493
|
// make sure our messages have ids
|
|
495
494
|
messages.forEach((m) => {
|
|
496
495
|
if (!m.id) {
|
|
497
|
-
m.id =
|
|
496
|
+
m.id =
|
|
497
|
+
hashCode((m.text.strings || []).join('')) +
|
|
498
|
+
'_' +
|
|
499
|
+
m.date.toISOString();
|
|
498
500
|
}
|
|
499
501
|
});
|
|
500
502
|
if (!startTime) {
|
|
@@ -687,7 +689,7 @@ export class Chat extends RapidElement {
|
|
|
687
689
|
if (event.type === MessageType.Error ||
|
|
688
690
|
event.type === MessageType.Collapse ||
|
|
689
691
|
event.type === MessageType.Inline) {
|
|
690
|
-
return html `<div class="event">${
|
|
692
|
+
return html `<div class="event">${event.text}</div>`;
|
|
691
693
|
}
|
|
692
694
|
const message = event;
|
|
693
695
|
return html `
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Chat.js","sourceRoot":"","sources":["../../../src/display/Chat.ts"],"names":[],"mappings":"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","sourcesContent":["import { TemplateResult, html, PropertyValueMap, css } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { RapidElement } from '../RapidElement';\nimport { CustomEventType } from '../interfaces';\nimport { DEFAULT_AVATAR } from '../webchat/assets';\nimport { hashCode } from '../utils';\nimport { renderMarkdown } from '../markdown';\n\nconst BATCH_TIME_WINDOW = 60 * 60 * 1000;\nconst SCROLL_FETCH_BUFFER = 0.05;\nconst MIN_FETCH_TIME = 250;\n\nexport enum MessageType {\n Inline = 'inline',\n Error = 'error',\n Collapse = 'collapse',\n Note = 'note',\n MsgIn = 'msg_in',\n MsgOut = 'msg_out'\n}\n\ninterface User {\n avatar?: string;\n email: string;\n name: string;\n}\n\nexport interface ChatEvent {\n id?: string;\n type: MessageType;\n text: string;\n date: Date;\n user?: User;\n popup?: TemplateResult;\n}\n\nexport interface Message extends ChatEvent {\n sendError?: boolean;\n attachments?: string[];\n}\n\nconst TIME_FORMAT = { hour: 'numeric', minute: '2-digit' } as any;\nconst VERBOSE_FORMAT = {\n weekday: undefined,\n year: undefined,\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit'\n} as any;\n\nexport class Chat extends RapidElement {\n static get styles() {\n return css`\n :host {\n display: flex;\n flex-direction: column;\n flex-grow: 1;\n position: relative;\n z-index: 1;\n }\n\n slot[name='header'] {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n display: block;\n }\n\n slot[name='footer'] {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n display: block;\n }\n\n .block {\n margin-bottom: 1em;\n display: flex;\n flex-direction: row;\n }\n\n .block.outgoing {\n flex-direction: row-reverse;\n }\n\n .block.collapse {\n margin: 0;\n align-items: center;\n display: flex;\n flex-direction: column;\n margin-bottom: 0.5em;\n }\n\n .block.collapse .messsage {\n transform: scaleY(0);\n margin: 0;\n padding: 0;\n line-height: 0;\n }\n\n .time {\n text-align: center;\n font-size: 0.8em;\n color: #999;\n margin-top: 2em;\n border-top: 1px solid #e9e9e9;\n padding: 1em;\n margin-left: 10%;\n margin-right: 10%;\n }\n\n .time.first {\n border-top: none;\n margin-top: 0;\n border-bottom: 1px solid #e9e9e9;\n margin-bottom: 2em;\n }\n\n .first .time {\n margin-top: 0;\n border-top: none;\n padding-top: 0;\n }\n\n .row {\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n margin-bottom: 0.25em;\n }\n\n .input-panel {\n padding: 1em;\n background: #fff;\n }\n\n temba-user {\n margin-right: 0.6em;\n margin-left: 0.6em;\n width: 2em;\n align-self: flex-end;\n }\n\n .toggle {\n flex-shrink: 0;\n width: 4em;\n height: 4em;\n overflow: hidden;\n border-radius: 100%;\n box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 1em 0.7em,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px,\n inset 0 0 0 0.25em rgba(0, 0, 0, 0.1);\n cursor: pointer;\n transition: box-shadow var(--toggle-speed, 200ms) ease-out;\n position: absolute;\n bottom: 1em;\n right: 1em;\n }\n\n .toggle:hover {\n box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 1em 0.7em,\n rgba(0, 0, 0, 0.4) 0px 1px 2px 0px,\n inset 0 0 0 0.25em rgba(0, 0, 0, 0.2);\n }\n\n .incoming .row {\n flex-direction: row-reverse;\n margin-left: 1em;\n }\n\n .bubble {\n padding: 0.75em;\n padding-bottom: 0.25em;\n background: var(--color-chat-in, #f1f1f1);\n border-radius: var(--curvature);\n border: var(--chat-border-in, none);\n }\n\n .bubble .name {\n font-size: 0.95em;\n font-weight: 400;\n color: rgba(0, 0, 0, 0.4);\n margin-bottom: 0.25em;\n }\n\n .outgoing .latest .bubble {\n border-bottom-left-radius: 0;\n }\n\n .incoming .bubble-wrap {\n align-items: flex-end;\n }\n\n .incoming .bubble {\n background: var(--color-chat-out, #3c92dd);\n border: var(--chat-border-out, none);\n color: white;\n }\n\n .incoming .latest .bubble {\n border-bottom-right-radius: 0;\n }\n\n .incoming .bubble .name {\n color: rgba(255, 255, 255, 0.7);\n }\n\n .note .bubble {\n background: #fffac3;\n color: rgba(0, 0, 0, 0.7);\n }\n\n .note .bubble .name {\n color: rgba(0, 0, 0, 0.5);\n }\n\n .message {\n margin-bottom: 0.5em;\n line-height: 1.2em;\n word-break: break-word;\n }\n\n .message-text {\n white-space: pre-line;\n }\n\n .chat {\n width: 28rem;\n border-radius: var(--curvature);\n overflow: hidden;\n box-shadow: rgba(0, 0, 0, 0.1) 0px 3px 7px 0px,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px, rgba(0, 0, 0, 0.1) 5em 5em 5em 5em;\n position: absolute;\n bottom: 3em;\n right: 1em;\n transition: all var(--toggle-speed, 200ms) ease-out;\n transform: scale(0.9);\n pointer-events: none;\n opacity: 0;\n }\n\n .chat.open {\n bottom: 6em;\n opacity: 1;\n transform: scale(1);\n pointer-events: initial;\n }\n\n .messages {\n position: relative;\n flex-grow: 1;\n overflow: hidden;\n }\n\n .scroll {\n position: absolute;\n top: 0;\n bottom: 0;\n right: 0;\n left: 0;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n overflow-scrolling: touch;\n padding: 1em 1em 1em 1em;\n padding-bottom: 2.5em;\n display: flex;\n flex-direction: column-reverse;\n }\n\n .messages:before {\n content: '';\n background: radial-gradient(\n farthest-side at 50% 0,\n rgba(0, 0, 0, 0.2),\n rgba(0, 0, 0, 0)\n )\n center top;\n height: 10px;\n display: block;\n position: absolute;\n width: 100%;\n transition: opacity var(--toggle-speed, 200ms) ease-out;\n z-index: 1;\n }\n\n .messages:after {\n content: '';\n background: radial-gradient(\n farthest-side at 50% 100%,\n rgba(0, 0, 0, 0.2),\n rgba(0, 0, 0, 0)\n )\n center bottom;\n height: 10px;\n display: block;\n position: absolute;\n bottom: 0;\n margin-top: -10px;\n width: 100%;\n margin-right: 5em;\n transition: opacity var(--toggle-speed, 200ms) ease-out;\n z-index: 1;\n }\n\n .bubble-wrap {\n position: relative;\n max-width: 70%;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n margin-top: -1em;\n padding-top: 1em;\n }\n\n .scroll-at-top.messages:before {\n opacity: 0;\n }\n\n .scroll-at-bottom.messages:after {\n opacity: 0;\n }\n\n .input {\n border: none;\n flex-grow: 1;\n color: #333;\n font-size: 1em;\n }\n\n .input:focus {\n outline: none;\n }\n\n input::placeholder {\n opacity: 0.3;\n }\n\n .input.inactive {\n // pointer-events: none;\n // opacity: 0.3;\n }\n\n .active {\n }\n\n .send-icon {\n color: #eee;\n pointer-events: none;\n transform: rotate(-45deg);\n transition: transform 0.2s ease-out;\n }\n\n .pending .send-icon {\n color: var(--color-primary-dark);\n pointer-events: initial;\n transform: rotate(0deg);\n }\n\n .notice {\n padding: 1em;\n background: #f8f8f8;\n color: #666;\n text-align: center;\n cursor: pointer;\n }\n\n .connecting .notice {\n display: flex;\n justify-content: center;\n }\n\n .connecting .notice temba-icon {\n margin-left: 0.5em;\n }\n\n .reconnect {\n color: var(--color-primary-dark);\n text-decoration: underline;\n font-size: 0.9em;\n }\n\n .input:disabled {\n background: transparent !important;\n }\n\n temba-loading {\n justify-content: center;\n margin: 0.5em auto;\n margin-bottom: 2em;\n }\n\n temba-loading.hidden {\n display: none;\n }\n\n .inline {\n }\n\n .event {\n flex-grow: 1;\n align-self: center;\n display: flex;\n flex-direction: column;\n align-items: center;\n }\n\n .event p {\n margin: 0;\n padding: 0;\n }\n\n .collapse {\n }\n\n a {\n color: var(--color-primary-dark);\n }\n\n .attachments {\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n align-items: center;\n align-self: flex-start;\n }\n\n .incoming .attachments {\n align-self: flex-end;\n }\n\n temba-thumbnail {\n margin: 0.4em;\n border-radius: var(--curvature);\n }\n\n .error .bubble {\n border: 1px solid var(--color-error);\n background: white;\n color: #333;\n }\n\n .error .bubble .name {\n color: #999;\n }\n\n .error temba-thumbnail {\n --thumb-background: var(--color-error);\n --thumb-icon: white;\n }\n\n .outgoing .popup {\n justify-content: left;\n }\n\n .incoming .popup {\n justify-content: right;\n }\n\n .popup {\n display: flex;\n position: absolute;\n background: #fff;\n margin: 0;\n padding: 0.5em 1em;\n border-radius: var(--curvature);\n box-shadow: rgba(0, 0, 0, 0.05) 0px 3px 7px 0px,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px;\n border: 1px solid #f3f3f3;\n opacity: 0;\n transform: scale(0.7);\n transition: opacity 0.2s ease-out, transform 0.2s ease-out;\n z-index: 2;\n }\n\n .popup .arrow {\n z-index: 1;\n text-shadow: 0px 3px 3px rgba(0, 0, 0, 0.1);\n position: absolute;\n justify-content: center;\n text-align: center;\n font-size: 1.3em;\n transform: translateY(0.7em) scale(1);\n color: #fff;\n bottom: 0;\n }\n\n .bubble-wrap:hover .popup {\n transform: translateY(-120%);\n opacity: 1;\n transition-delay: 1s;\n }\n `;\n }\n\n @property({ type: Array })\n messageGroups: string[][] = [];\n\n @property({ type: Boolean })\n fetching = false;\n\n @property({ type: Boolean, attribute: false })\n hideTopScroll = true;\n\n @property({ type: Boolean, attribute: false })\n hideBottomScroll = true;\n\n @property({ type: String, attribute: 'avatar' })\n defaultAvatar = DEFAULT_AVATAR;\n\n @property({ type: Boolean })\n agent = false;\n\n private msgMap = new Map<string, ChatEvent>();\n\n public firstUpdated(\n changed: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changed);\n const scroll = this.shadowRoot.querySelector('.scroll');\n const hasScroll = scroll.scrollHeight > scroll.clientHeight;\n this.hideBottomScroll = true;\n this.hideTopScroll = !hasScroll;\n }\n\n public addMessages(\n messages: ChatEvent[],\n startTime: Date = null,\n append = false\n ) {\n // make sure our messages have ids\n messages.forEach((m) => {\n if (!m.id) {\n m.id = hashCode(m.text) + '_' + m.date.toISOString();\n }\n });\n\n if (!startTime) {\n startTime = new Date();\n }\n\n const elapsed = new Date().getTime() - startTime.getTime();\n window.setTimeout(\n () => {\n this.fetching = false;\n // first add messages to the map\n const newMessages = [];\n for (const m of messages) {\n if (this.addMessage(m)) {\n newMessages.push(m.id);\n }\n }\n\n if (newMessages.length === 0) {\n return;\n }\n\n const ele = this.shadowRoot.querySelector('.scroll');\n const prevTop = ele.scrollTop;\n\n const grouped = this.groupMessages(newMessages);\n this.insertGroups(grouped, append);\n\n window.setTimeout(() => {\n ele.scrollTop = prevTop;\n\n this.fireCustomEvent(CustomEventType.FetchComplete);\n }, 100);\n },\n // if it's the first load don't wait, otherwise wait a minimum amount of time\n this.messageGroups.length === 0\n ? 0\n : Math.max(0, MIN_FETCH_TIME - elapsed)\n );\n }\n\n private addMessage(msg: ChatEvent): boolean {\n const isNew = !this.messageExists(msg);\n this.msgMap.set(msg.id, msg);\n return isNew;\n }\n\n public messageExists(msg: ChatEvent): boolean {\n return this.msgMap.has(msg.id);\n }\n\n private isSameGroup(msg1: ChatEvent, msg2: ChatEvent): boolean {\n if (msg1 && msg2) {\n return (\n msg1.type === msg2.type &&\n msg1.user?.name === msg2.user?.name &&\n Math.abs(msg1.date.getTime() - msg2.date.getTime()) < BATCH_TIME_WINDOW\n );\n }\n\n return false;\n }\n\n private insertGroups(newGroups: string[][], append = false) {\n if (!append) {\n newGroups.reverse();\n }\n\n for (const newGroup of newGroups) {\n // see if our new group belongs to the most recent group\n const group =\n this.messageGroups[append ? 0 : this.messageGroups.length - 1];\n\n if (group) {\n const lastMsgId = group[group.length - 1];\n const lastMsg = this.msgMap.get(lastMsgId);\n const newMsg = this.msgMap.get(newGroup[0]);\n // if our message belongs to the previous group, in we go\n if (this.isSameGroup(lastMsg, newMsg)) {\n group.push(...newGroup);\n } else {\n // otherwise, just add our entire group as a new one\n if (append) {\n this.messageGroups.splice(0, 0, newGroup);\n } else {\n this.messageGroups.push(newGroup);\n }\n }\n } else {\n if (append) {\n this.messageGroups.splice(0, 0, newGroup);\n } else {\n this.messageGroups.push(newGroup);\n }\n }\n }\n\n this.requestUpdate('messageGroups');\n }\n\n private groupMessages(msgIds: string[]): string[][] {\n // group our messages by origin and user\n const groups = [];\n let lastGroup = [];\n let lastMsg = null;\n for (const msgId of msgIds) {\n const msg = this.msgMap.get(msgId);\n if (!this.isSameGroup(msg, lastMsg)) {\n lastGroup = [];\n groups.push(lastGroup);\n }\n lastGroup.push(msgId);\n lastMsg = msg;\n }\n return groups;\n }\n\n private handleScroll(event: any) {\n const ele = event.target;\n const top = ele.scrollHeight - ele.clientHeight;\n const scroll = Math.round(top + ele.scrollTop);\n const scrollPct = scroll / top;\n\n this.hideTopScroll = scrollPct <= 0.01;\n this.hideBottomScroll = scrollPct >= 0.99;\n\n if (scrollPct < SCROLL_FETCH_BUFFER) {\n this.fireCustomEvent(CustomEventType.ScrollThreshold);\n }\n }\n\n private scrollToBottom() {\n const scroll = this.shadowRoot.querySelector('.scroll');\n if (scroll) {\n scroll.scrollTop = scroll.scrollHeight;\n this.hideBottomScroll = true;\n }\n }\n\n private renderMessageGroup(\n msgIds: string[],\n idx: number,\n groups: string[][]\n ): TemplateResult {\n const today = new Date();\n const firstGroup = idx === groups.length - 1;\n\n let prevMsg: ChatEvent;\n if (idx > 0) {\n const lastGroup = groups[idx - 1];\n if (lastGroup && lastGroup.length > 0) {\n prevMsg = this.msgMap.get(lastGroup[0]);\n }\n }\n\n const mostRecentId = msgIds[msgIds.length - 1];\n const currentMsg = this.msgMap.get(mostRecentId);\n let timeDisplay = null;\n if (\n prevMsg &&\n !this.isSameGroup(prevMsg, currentMsg) &&\n (Math.abs(currentMsg.date.getTime() - prevMsg.date.getTime()) >\n BATCH_TIME_WINDOW ||\n idx === groups.length - 1)\n ) {\n if (\n today.getDate() !== prevMsg.date.getDate() ||\n prevMsg.date.getDate() !== currentMsg.date.getDate()\n ) {\n timeDisplay = html`<div class=\"time ${firstGroup ? 'first' : ''}\">\n ${prevMsg.date.toLocaleTimeString(undefined, VERBOSE_FORMAT)}\n </div>`;\n } else {\n timeDisplay = html`<div class=\"time ${firstGroup ? 'first' : ''}\">\n ${prevMsg.date.toLocaleTimeString(undefined, TIME_FORMAT)}\n </div>`;\n }\n }\n\n const incoming = this.agent\n ? currentMsg.type !== 'msg_in'\n : currentMsg.type === 'msg_in';\n\n const name = currentMsg.user?.name;\n const email = currentMsg.user?.email;\n\n const showAvatar =\n ((currentMsg.type === 'note' ||\n currentMsg.type === 'msg_in' ||\n currentMsg.type === 'msg_out') &&\n this.agent) ||\n !incoming;\n\n return html`\n ${!firstGroup ? timeDisplay : null}\n <div\n class=\"block ${incoming ? 'incoming' : 'outgoing'} ${currentMsg.type}\"\n >\n <div class=\"group-messages\" style=\"flex-grow:1\">\n ${msgIds.map((msgId, index) => {\n const msg = this.msgMap.get(msgId);\n return html`<div class=\"row message\">\n ${this.renderMessage(msg, index == 0 ? name : null)}\n </div>`;\n })}\n </div>\n ${showAvatar\n ? html`<div class=\"avatar\" style=\"align-self:flex-end\">\n <temba-user\n email=${email}\n name=${name}\n avatar=${currentMsg.user?.avatar}\n ?system=${!email && !name}\n >\n </temba-user>\n </div>`\n : null}\n </div>\n ${firstGroup ? timeDisplay : null}\n `;\n }\n\n private renderMessage(event: ChatEvent, name = null): TemplateResult {\n if (\n event.type === MessageType.Error ||\n event.type === MessageType.Collapse ||\n event.type === MessageType.Inline\n ) {\n return html`<div class=\"event\">${renderMarkdown(event.text)}</div>`;\n }\n\n const message = event as Message;\n return html`\n <div class=\"bubble-wrap ${message.sendError ? 'error' : ''}\">\n ${\n message.popup\n ? html`<div class=\"popup\">\n ${message.popup}\n <div class=\"arrow\">▼</div>\n </div>`\n : null\n }\n \n ${\n message.text\n ? html`\n <div class=\"bubble\">\n ${name ? html`<div class=\"name\">${name}</div>` : null}\n <div class=\"message message-text\">${message.text}</div>\n\n <!--div>${message.date.toLocaleDateString(\n undefined,\n VERBOSE_FORMAT\n )}</div-->\n </div>\n `\n : null\n }\n\n <div class=\"attachments\">\n ${(message.attachments || []).map(\n (attachment) =>\n html`<temba-thumbnail\n attachment=\"${attachment}\"\n ></temba-thumbnail>`\n )}\n </div>\n </div>\n </div>\n `;\n }\n\n public reset() {\n this.msgMap.clear();\n this.messageGroups = [];\n this.hideBottomScroll = true;\n this.hideTopScroll = true;\n }\n\n public render(): TemplateResult {\n return html` <div\n class=\"\n messages \n ${this.hideBottomScroll ? 'scroll-at-bottom' : ''}\n ${this.hideTopScroll ? 'scroll-at-top' : ''}\"\n >\n <div class=\"scroll\" @scroll=${this.handleScroll}>\n ${this.messageGroups\n ? this.messageGroups.map(\n (msgGroup, idx, groups) =>\n html`${this.renderMessageGroup(msgGroup, idx, groups)}`\n )\n : null}\n\n <temba-loading\n class=\"${!this.fetching ? 'hidden' : ''}\"\n ></temba-loading>\n </div>\n <slot class=\"header\" name=\"header\"></slot>\n <slot class=\"footer\" name=\"footer\"></slot>\n </div>`;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Chat.js","sourceRoot":"","sources":["../../../src/display/Chat.ts"],"names":[],"mappings":"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","sourcesContent":["import { TemplateResult, html, PropertyValueMap, css } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { RapidElement } from '../RapidElement';\nimport { CustomEventType } from '../interfaces';\nimport { DEFAULT_AVATAR } from '../webchat/assets';\nimport { hashCode } from '../utils';\n\nconst BATCH_TIME_WINDOW = 60 * 60 * 1000;\nconst SCROLL_FETCH_BUFFER = 0.05;\nconst MIN_FETCH_TIME = 250;\n\nexport enum MessageType {\n Inline = 'inline',\n Error = 'error',\n Collapse = 'collapse',\n Note = 'note',\n MsgIn = 'msg_in',\n MsgOut = 'msg_out'\n}\n\ninterface User {\n avatar?: string;\n email: string;\n name: string;\n}\n\nexport interface ChatEvent {\n id?: string;\n type: MessageType;\n text: TemplateResult;\n date: Date;\n user?: User;\n popup?: TemplateResult;\n}\n\nexport interface Message extends ChatEvent {\n sendError?: boolean;\n attachments?: string[];\n}\n\nconst TIME_FORMAT = { hour: 'numeric', minute: '2-digit' } as any;\nconst VERBOSE_FORMAT = {\n weekday: undefined,\n year: undefined,\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit'\n} as any;\n\nexport class Chat extends RapidElement {\n static get styles() {\n return css`\n :host {\n display: flex;\n flex-direction: column;\n flex-grow: 1;\n position: relative;\n z-index: 1;\n }\n\n slot[name='header'] {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n display: block;\n }\n\n slot[name='footer'] {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n display: block;\n }\n\n .block {\n margin-bottom: 1em;\n display: flex;\n flex-direction: row;\n }\n\n .block.outgoing {\n flex-direction: row-reverse;\n }\n\n .block.collapse {\n margin: 0;\n align-items: center;\n display: flex;\n flex-direction: column;\n margin-bottom: 0.5em;\n }\n\n .block.collapse .messsage {\n transform: scaleY(0);\n margin: 0;\n padding: 0;\n line-height: 0;\n }\n\n .time {\n text-align: center;\n font-size: 0.8em;\n color: #999;\n margin-top: 2em;\n border-top: 1px solid #e9e9e9;\n padding: 1em;\n margin-left: 10%;\n margin-right: 10%;\n }\n\n .time.first {\n border-top: none;\n margin-top: 0;\n border-bottom: 1px solid #e9e9e9;\n margin-bottom: 2em;\n }\n\n .first .time {\n margin-top: 0;\n border-top: none;\n padding-top: 0;\n }\n\n .row {\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n margin-bottom: 0.25em;\n }\n\n .input-panel {\n padding: 1em;\n background: #fff;\n }\n\n temba-user {\n margin-right: 0.6em;\n margin-left: 0.6em;\n width: 2em;\n align-self: flex-end;\n }\n\n .toggle {\n flex-shrink: 0;\n width: 4em;\n height: 4em;\n overflow: hidden;\n border-radius: 100%;\n box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 1em 0.7em,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px,\n inset 0 0 0 0.25em rgba(0, 0, 0, 0.1);\n cursor: pointer;\n transition: box-shadow var(--toggle-speed, 200ms) ease-out;\n position: absolute;\n bottom: 1em;\n right: 1em;\n }\n\n .toggle:hover {\n box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 1em 0.7em,\n rgba(0, 0, 0, 0.4) 0px 1px 2px 0px,\n inset 0 0 0 0.25em rgba(0, 0, 0, 0.2);\n }\n\n .incoming .row {\n flex-direction: row-reverse;\n margin-left: 1em;\n }\n\n .bubble {\n padding: 0.75em;\n padding-bottom: 0.25em;\n background: var(--color-chat-in, #f1f1f1);\n border-radius: var(--curvature);\n border: var(--chat-border-in, none);\n }\n\n .bubble .name {\n font-size: 0.95em;\n font-weight: 400;\n color: rgba(0, 0, 0, 0.4);\n margin-bottom: 0.25em;\n }\n\n .outgoing .latest .bubble {\n border-bottom-left-radius: 0;\n }\n\n .incoming .bubble-wrap {\n align-items: flex-end;\n }\n\n .incoming .bubble {\n background: var(--color-chat-out, #3c92dd);\n border: var(--chat-border-out, none);\n color: white;\n }\n\n .incoming .latest .bubble {\n border-bottom-right-radius: 0;\n }\n\n .incoming .bubble .name {\n color: rgba(255, 255, 255, 0.7);\n }\n\n .note .bubble {\n background: #fffac3;\n color: rgba(0, 0, 0, 0.7);\n }\n\n .note .bubble .name {\n color: rgba(0, 0, 0, 0.5);\n }\n\n .message {\n margin-bottom: 0.5em;\n line-height: 1.2em;\n word-break: break-word;\n }\n\n .message-text {\n white-space: pre-line;\n }\n\n .chat {\n width: 28rem;\n border-radius: var(--curvature);\n overflow: hidden;\n box-shadow: rgba(0, 0, 0, 0.1) 0px 3px 7px 0px,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px, rgba(0, 0, 0, 0.1) 5em 5em 5em 5em;\n position: absolute;\n bottom: 3em;\n right: 1em;\n transition: all var(--toggle-speed, 200ms) ease-out;\n transform: scale(0.9);\n pointer-events: none;\n opacity: 0;\n }\n\n .chat.open {\n bottom: 6em;\n opacity: 1;\n transform: scale(1);\n pointer-events: initial;\n }\n\n .messages {\n position: relative;\n flex-grow: 1;\n overflow: hidden;\n }\n\n .scroll {\n position: absolute;\n top: 0;\n bottom: 0;\n right: 0;\n left: 0;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n overflow-scrolling: touch;\n padding: 1em 1em 1em 1em;\n padding-bottom: 2.5em;\n display: flex;\n flex-direction: column-reverse;\n }\n\n .messages:before {\n content: '';\n background: radial-gradient(\n farthest-side at 50% 0,\n rgba(0, 0, 0, 0.2),\n rgba(0, 0, 0, 0)\n )\n center top;\n height: 10px;\n display: block;\n position: absolute;\n width: 100%;\n transition: opacity var(--toggle-speed, 200ms) ease-out;\n z-index: 1;\n }\n\n .messages:after {\n content: '';\n background: radial-gradient(\n farthest-side at 50% 100%,\n rgba(0, 0, 0, 0.2),\n rgba(0, 0, 0, 0)\n )\n center bottom;\n height: 10px;\n display: block;\n position: absolute;\n bottom: 0;\n margin-top: -10px;\n width: 100%;\n margin-right: 5em;\n transition: opacity var(--toggle-speed, 200ms) ease-out;\n z-index: 1;\n }\n\n .bubble-wrap {\n position: relative;\n max-width: 70%;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n margin-top: -1em;\n padding-top: 1em;\n }\n\n .scroll-at-top.messages:before {\n opacity: 0;\n }\n\n .scroll-at-bottom.messages:after {\n opacity: 0;\n }\n\n .input {\n border: none;\n flex-grow: 1;\n color: #333;\n font-size: 1em;\n }\n\n .input:focus {\n outline: none;\n }\n\n input::placeholder {\n opacity: 0.3;\n }\n\n .input.inactive {\n // pointer-events: none;\n // opacity: 0.3;\n }\n\n .active {\n }\n\n .send-icon {\n color: #eee;\n pointer-events: none;\n transform: rotate(-45deg);\n transition: transform 0.2s ease-out;\n }\n\n .pending .send-icon {\n color: var(--color-primary-dark);\n pointer-events: initial;\n transform: rotate(0deg);\n }\n\n .notice {\n padding: 1em;\n background: #f8f8f8;\n color: #666;\n text-align: center;\n cursor: pointer;\n }\n\n .connecting .notice {\n display: flex;\n justify-content: center;\n }\n\n .connecting .notice temba-icon {\n margin-left: 0.5em;\n }\n\n .reconnect {\n color: var(--color-primary-dark);\n text-decoration: underline;\n font-size: 0.9em;\n }\n\n .input:disabled {\n background: transparent !important;\n }\n\n temba-loading {\n justify-content: center;\n margin: 0.5em auto;\n margin-bottom: 2em;\n }\n\n temba-loading.hidden {\n display: none;\n }\n\n .inline {\n }\n\n .event {\n flex-grow: 1;\n align-self: center;\n display: flex;\n flex-direction: column;\n align-items: center;\n }\n\n .event p {\n margin: 0;\n padding: 0;\n }\n\n .collapse {\n }\n\n a {\n color: var(--color-primary-dark);\n }\n\n .attachments {\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n align-items: center;\n align-self: flex-start;\n }\n\n .incoming .attachments {\n align-self: flex-end;\n }\n\n temba-thumbnail {\n margin: 0.4em;\n border-radius: var(--curvature);\n }\n\n .error .bubble {\n border: 1px solid var(--color-error);\n background: white;\n color: #333;\n }\n\n .error .bubble .name {\n color: #999;\n }\n\n .error temba-thumbnail {\n --thumb-background: var(--color-error);\n --thumb-icon: white;\n }\n\n .outgoing .popup {\n justify-content: left;\n }\n\n .incoming .popup {\n justify-content: right;\n }\n\n .popup {\n display: flex;\n position: absolute;\n background: #fff;\n margin: 0;\n padding: 0.5em 1em;\n border-radius: var(--curvature);\n box-shadow: rgba(0, 0, 0, 0.05) 0px 3px 7px 0px,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px;\n border: 1px solid #f3f3f3;\n opacity: 0;\n transform: scale(0.7);\n transition: opacity 0.2s ease-out, transform 0.2s ease-out;\n z-index: 2;\n }\n\n .popup .arrow {\n z-index: 1;\n text-shadow: 0px 3px 3px rgba(0, 0, 0, 0.1);\n position: absolute;\n justify-content: center;\n text-align: center;\n font-size: 1.3em;\n transform: translateY(0.7em) scale(1);\n color: #fff;\n bottom: 0;\n }\n\n .bubble-wrap:hover .popup {\n transform: translateY(-120%);\n opacity: 1;\n transition-delay: 1s;\n }\n `;\n }\n\n @property({ type: Array })\n messageGroups: string[][] = [];\n\n @property({ type: Boolean })\n fetching = false;\n\n @property({ type: Boolean, attribute: false })\n hideTopScroll = true;\n\n @property({ type: Boolean, attribute: false })\n hideBottomScroll = true;\n\n @property({ type: String, attribute: 'avatar' })\n defaultAvatar = DEFAULT_AVATAR;\n\n @property({ type: Boolean })\n agent = false;\n\n private msgMap = new Map<string, ChatEvent>();\n\n public firstUpdated(\n changed: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changed);\n const scroll = this.shadowRoot.querySelector('.scroll');\n const hasScroll = scroll.scrollHeight > scroll.clientHeight;\n this.hideBottomScroll = true;\n this.hideTopScroll = !hasScroll;\n }\n\n public addMessages(\n messages: ChatEvent[],\n startTime: Date = null,\n append = false\n ) {\n // make sure our messages have ids\n messages.forEach((m) => {\n if (!m.id) {\n m.id =\n hashCode((m.text.strings || []).join('')) +\n '_' +\n m.date.toISOString();\n }\n });\n\n if (!startTime) {\n startTime = new Date();\n }\n\n const elapsed = new Date().getTime() - startTime.getTime();\n window.setTimeout(\n () => {\n this.fetching = false;\n // first add messages to the map\n const newMessages = [];\n for (const m of messages) {\n if (this.addMessage(m)) {\n newMessages.push(m.id);\n }\n }\n\n if (newMessages.length === 0) {\n return;\n }\n\n const ele = this.shadowRoot.querySelector('.scroll');\n const prevTop = ele.scrollTop;\n\n const grouped = this.groupMessages(newMessages);\n this.insertGroups(grouped, append);\n\n window.setTimeout(() => {\n ele.scrollTop = prevTop;\n\n this.fireCustomEvent(CustomEventType.FetchComplete);\n }, 100);\n },\n // if it's the first load don't wait, otherwise wait a minimum amount of time\n this.messageGroups.length === 0\n ? 0\n : Math.max(0, MIN_FETCH_TIME - elapsed)\n );\n }\n\n private addMessage(msg: ChatEvent): boolean {\n const isNew = !this.messageExists(msg);\n this.msgMap.set(msg.id, msg);\n return isNew;\n }\n\n public messageExists(msg: ChatEvent): boolean {\n return this.msgMap.has(msg.id);\n }\n\n private isSameGroup(msg1: ChatEvent, msg2: ChatEvent): boolean {\n if (msg1 && msg2) {\n return (\n msg1.type === msg2.type &&\n msg1.user?.name === msg2.user?.name &&\n Math.abs(msg1.date.getTime() - msg2.date.getTime()) < BATCH_TIME_WINDOW\n );\n }\n\n return false;\n }\n\n private insertGroups(newGroups: string[][], append = false) {\n if (!append) {\n newGroups.reverse();\n }\n\n for (const newGroup of newGroups) {\n // see if our new group belongs to the most recent group\n const group =\n this.messageGroups[append ? 0 : this.messageGroups.length - 1];\n\n if (group) {\n const lastMsgId = group[group.length - 1];\n const lastMsg = this.msgMap.get(lastMsgId);\n const newMsg = this.msgMap.get(newGroup[0]);\n // if our message belongs to the previous group, in we go\n if (this.isSameGroup(lastMsg, newMsg)) {\n group.push(...newGroup);\n } else {\n // otherwise, just add our entire group as a new one\n if (append) {\n this.messageGroups.splice(0, 0, newGroup);\n } else {\n this.messageGroups.push(newGroup);\n }\n }\n } else {\n if (append) {\n this.messageGroups.splice(0, 0, newGroup);\n } else {\n this.messageGroups.push(newGroup);\n }\n }\n }\n\n this.requestUpdate('messageGroups');\n }\n\n private groupMessages(msgIds: string[]): string[][] {\n // group our messages by origin and user\n const groups = [];\n let lastGroup = [];\n let lastMsg = null;\n for (const msgId of msgIds) {\n const msg = this.msgMap.get(msgId);\n if (!this.isSameGroup(msg, lastMsg)) {\n lastGroup = [];\n groups.push(lastGroup);\n }\n lastGroup.push(msgId);\n lastMsg = msg;\n }\n return groups;\n }\n\n private handleScroll(event: any) {\n const ele = event.target;\n const top = ele.scrollHeight - ele.clientHeight;\n const scroll = Math.round(top + ele.scrollTop);\n const scrollPct = scroll / top;\n\n this.hideTopScroll = scrollPct <= 0.01;\n this.hideBottomScroll = scrollPct >= 0.99;\n\n if (scrollPct < SCROLL_FETCH_BUFFER) {\n this.fireCustomEvent(CustomEventType.ScrollThreshold);\n }\n }\n\n private scrollToBottom() {\n const scroll = this.shadowRoot.querySelector('.scroll');\n if (scroll) {\n scroll.scrollTop = scroll.scrollHeight;\n this.hideBottomScroll = true;\n }\n }\n\n private renderMessageGroup(\n msgIds: string[],\n idx: number,\n groups: string[][]\n ): TemplateResult {\n const today = new Date();\n const firstGroup = idx === groups.length - 1;\n\n let prevMsg: ChatEvent;\n if (idx > 0) {\n const lastGroup = groups[idx - 1];\n if (lastGroup && lastGroup.length > 0) {\n prevMsg = this.msgMap.get(lastGroup[0]);\n }\n }\n\n const mostRecentId = msgIds[msgIds.length - 1];\n const currentMsg = this.msgMap.get(mostRecentId);\n let timeDisplay = null;\n if (\n prevMsg &&\n !this.isSameGroup(prevMsg, currentMsg) &&\n (Math.abs(currentMsg.date.getTime() - prevMsg.date.getTime()) >\n BATCH_TIME_WINDOW ||\n idx === groups.length - 1)\n ) {\n if (\n today.getDate() !== prevMsg.date.getDate() ||\n prevMsg.date.getDate() !== currentMsg.date.getDate()\n ) {\n timeDisplay = html`<div class=\"time ${firstGroup ? 'first' : ''}\">\n ${prevMsg.date.toLocaleTimeString(undefined, VERBOSE_FORMAT)}\n </div>`;\n } else {\n timeDisplay = html`<div class=\"time ${firstGroup ? 'first' : ''}\">\n ${prevMsg.date.toLocaleTimeString(undefined, TIME_FORMAT)}\n </div>`;\n }\n }\n\n const incoming = this.agent\n ? currentMsg.type !== 'msg_in'\n : currentMsg.type === 'msg_in';\n\n const name = currentMsg.user?.name;\n const email = currentMsg.user?.email;\n\n const showAvatar =\n ((currentMsg.type === 'note' ||\n currentMsg.type === 'msg_in' ||\n currentMsg.type === 'msg_out') &&\n this.agent) ||\n !incoming;\n\n return html`\n ${!firstGroup ? timeDisplay : null}\n <div\n class=\"block ${incoming ? 'incoming' : 'outgoing'} ${currentMsg.type}\"\n >\n <div class=\"group-messages\" style=\"flex-grow:1\">\n ${msgIds.map((msgId, index) => {\n const msg = this.msgMap.get(msgId);\n return html`<div class=\"row message\">\n ${this.renderMessage(msg, index == 0 ? name : null)}\n </div>`;\n })}\n </div>\n ${showAvatar\n ? html`<div class=\"avatar\" style=\"align-self:flex-end\">\n <temba-user\n email=${email}\n name=${name}\n avatar=${currentMsg.user?.avatar}\n ?system=${!email && !name}\n >\n </temba-user>\n </div>`\n : null}\n </div>\n ${firstGroup ? timeDisplay : null}\n `;\n }\n\n private renderMessage(event: ChatEvent, name = null): TemplateResult {\n if (\n event.type === MessageType.Error ||\n event.type === MessageType.Collapse ||\n event.type === MessageType.Inline\n ) {\n return html`<div class=\"event\">${event.text}</div>`;\n }\n\n const message = event as Message;\n return html`\n <div class=\"bubble-wrap ${message.sendError ? 'error' : ''}\">\n ${\n message.popup\n ? html`<div class=\"popup\">\n ${message.popup}\n <div class=\"arrow\">▼</div>\n </div>`\n : null\n }\n \n ${\n message.text\n ? html`\n <div class=\"bubble\">\n ${name ? html`<div class=\"name\">${name}</div>` : null}\n <div class=\"message message-text\">${message.text}</div>\n\n <!--div>${message.date.toLocaleDateString(\n undefined,\n VERBOSE_FORMAT\n )}</div-->\n </div>\n `\n : null\n }\n\n <div class=\"attachments\">\n ${(message.attachments || []).map(\n (attachment) =>\n html`<temba-thumbnail\n attachment=\"${attachment}\"\n ></temba-thumbnail>`\n )}\n </div>\n </div>\n </div>\n `;\n }\n\n public reset() {\n this.msgMap.clear();\n this.messageGroups = [];\n this.hideBottomScroll = true;\n this.hideTopScroll = true;\n }\n\n public render(): TemplateResult {\n return html` <div\n class=\"\n messages \n ${this.hideBottomScroll ? 'scroll-at-bottom' : ''}\n ${this.hideTopScroll ? 'scroll-at-top' : ''}\"\n >\n <div class=\"scroll\" @scroll=${this.handleScroll}>\n ${this.messageGroups\n ? this.messageGroups.map(\n (msgGroup, idx, groups) =>\n html`${this.renderMessageGroup(msgGroup, idx, groups)}`\n )\n : null}\n\n <temba-loading\n class=\"${!this.fetching ? 'hidden' : ''}\"\n ></temba-loading>\n </div>\n <slot class=\"header\" name=\"header\"></slot>\n <slot class=\"footer\" name=\"footer\"></slot>\n </div>`;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/events.ts"],"names":[],"mappings":"","sourcesContent":["import { Msg, ObjectReference, User } from './interfaces';\n\nexport interface EventGroup {\n type: string;\n events: ContactEvent[];\n open: boolean;\n}\n\nexport interface ContactEvent {\n uuid?: string;\n type: string;\n created_on: string;\n created_by?: User;\n}\n\nexport interface ChannelEvent extends ContactEvent {\n channel_event_type: string;\n duration: number;\n\n event: {\n type: string;\n channel: { uuid: string; name: string };\n duration?: number;\n optin?: {\n uuid: string;\n name: string;\n };\n };\n}\n\nexport interface ContactLanguageChangedEvent extends ContactEvent {\n language: string;\n}\n\nexport interface ContactStatusChangedEvent extends ContactEvent {\n status: string;\n}\n\nexport interface OptInEvent extends ContactEvent {\n optin: {\n uuid: string;\n name: string;\n };\n}\n\nexport interface CallEvent extends ContactEvent {\n call?: {\n uuid: string;\n urn: string;\n };\n}\n\nexport interface ChatStartedEvent extends ContactEvent {\n params?: object;\n}\n\nexport interface MsgEvent extends ContactEvent {\n msg: Msg;\n status: string;\n failed_reason?: string;\n failed_reason_display?: string;\n logs_url: string;\n recipient_count?: number;\n created_by?: User;\n optin?: ObjectReference;\n}\n\nexport interface RunEvent extends ContactEvent {\n flow: ObjectReference;\n status: string;\n}\n\nexport interface URNsChangedEvent extends ContactEvent {\n urns: string[];\n}\n\nexport interface TicketEvent extends ContactEvent {\n
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/events.ts"],"names":[],"mappings":"","sourcesContent":["import { Msg, ObjectReference, User } from './interfaces';\n\nexport interface EventGroup {\n type: string;\n events: ContactEvent[];\n open: boolean;\n}\n\nexport interface ContactEvent {\n uuid?: string;\n type: string;\n created_on: string;\n created_by?: User; // deprecated\n _user?: ObjectReference;\n}\n\nexport interface ChannelEvent extends ContactEvent {\n channel_event_type: string;\n duration: number;\n\n event: {\n type: string;\n channel: { uuid: string; name: string };\n duration?: number;\n optin?: {\n uuid: string;\n name: string;\n };\n };\n}\n\nexport interface ContactLanguageChangedEvent extends ContactEvent {\n language: string;\n}\n\nexport interface ContactStatusChangedEvent extends ContactEvent {\n status: string;\n}\n\nexport interface OptInEvent extends ContactEvent {\n optin: {\n uuid: string;\n name: string;\n };\n}\n\nexport interface CallEvent extends ContactEvent {\n call?: {\n uuid: string;\n urn: string;\n };\n}\n\nexport interface ChatStartedEvent extends ContactEvent {\n params?: object;\n}\n\nexport interface MsgEvent extends ContactEvent {\n msg: Msg;\n status: string;\n failed_reason?: string;\n failed_reason_display?: string;\n logs_url: string;\n recipient_count?: number;\n created_by?: User;\n optin?: ObjectReference;\n}\n\nexport interface RunEvent extends ContactEvent {\n flow: ObjectReference;\n status: string;\n}\n\nexport interface URNsChangedEvent extends ContactEvent {\n urns: string[];\n}\n\nexport interface TicketEvent extends ContactEvent {\n ticket: {\n // ticket_opened\n uuid: string;\n topic?: ObjectReference;\n };\n ticket_uuid?: string; // all other event types\n assignee?: User;\n note?: string;\n topic?: ObjectReference;\n}\n\nexport interface NameChangedEvent extends ContactEvent {\n name: string;\n}\n\nexport interface UpdateFieldEvent extends ContactEvent {\n field: { key: string; name: string };\n value: { text: string };\n}\n\nexport interface ContactGroupsEvent extends ContactEvent {\n groups_added: ObjectReference[];\n groups_removed: ObjectReference[];\n}\n\nexport interface AirtimeTransferredEvent extends ContactEvent {\n sender: string;\n recipient: string;\n currency: string;\n amount: string;\n}\n\nexport type CallStartedEvent = ContactEvent;\n\nexport interface ContactHistoryPage {\n has_older: boolean;\n recent_only: boolean;\n next_before: number;\n next_after: number;\n start_date: Date;\n events: ContactEvent[];\n}\n"]}
|
|
@@ -44,60 +44,43 @@ export class CanvasNode extends RapidElement {
|
|
|
44
44
|
|
|
45
45
|
.action {
|
|
46
46
|
position: relative;
|
|
47
|
-
font-size: 13px;
|
|
48
47
|
}
|
|
49
48
|
|
|
50
|
-
.action .remove-button {
|
|
51
|
-
position: absolute;
|
|
52
|
-
top: 5px;
|
|
53
|
-
right: 5px;
|
|
54
|
-
width: 16px;
|
|
55
|
-
height: 16px;
|
|
56
|
-
border-radius: 50%;
|
|
57
|
-
background: var(--color-error, #dc3545);
|
|
58
|
-
color: white;
|
|
59
|
-
border: none;
|
|
60
|
-
cursor: pointer;
|
|
61
|
-
display: none;
|
|
62
|
-
align-items: center;
|
|
63
|
-
justify-content: center;
|
|
64
|
-
font-size: 10px;
|
|
65
|
-
line-height: 1;
|
|
66
|
-
z-index: 10;
|
|
67
|
-
}
|
|
68
49
|
|
|
69
|
-
.action:hover .remove-button,
|
|
50
|
+
.action .cn-title:hover .remove-button,
|
|
70
51
|
.router:hover .remove-button {
|
|
71
|
-
|
|
52
|
+
opacity: 0.7;
|
|
72
53
|
}
|
|
73
54
|
|
|
74
|
-
.action.removing .title,
|
|
75
|
-
.router .title.removing {
|
|
55
|
+
.action.removing .cn-title,
|
|
56
|
+
.router .cn-title.removing {
|
|
76
57
|
background-color: var(--color-error, #dc3545) !important;
|
|
77
58
|
}
|
|
78
59
|
|
|
79
|
-
.action.removing .title .name,
|
|
80
|
-
.router .title.removing .name {
|
|
60
|
+
.action.removing .cn-title .name,
|
|
61
|
+
.router .cn-title.removing .name {
|
|
81
62
|
color: white;
|
|
82
63
|
}
|
|
83
64
|
|
|
84
|
-
.
|
|
85
|
-
|
|
86
|
-
top: 5px;
|
|
87
|
-
right: 5px;
|
|
88
|
-
width: 16px;
|
|
89
|
-
height: 16px;
|
|
90
|
-
border-radius: 50%;
|
|
91
|
-
background: var(--color-error, #dc3545);
|
|
65
|
+
.remove-button {
|
|
66
|
+
background: transparent;
|
|
92
67
|
color: white;
|
|
93
|
-
|
|
68
|
+
opacity: 0;
|
|
94
69
|
cursor: pointer;
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
justify-content: center;
|
|
98
|
-
font-size: 10px;
|
|
70
|
+
font-size: 1em;
|
|
71
|
+
font-weight: 600;
|
|
99
72
|
line-height: 1;
|
|
100
73
|
z-index: 10;
|
|
74
|
+
transition: all 100ms ease-in-out;
|
|
75
|
+
align-self: center;
|
|
76
|
+
padding:0.25em;
|
|
77
|
+
border: 0px solid red;
|
|
78
|
+
width: 1em;
|
|
79
|
+
pointer-events: auto; /* Ensure remove button can receive events */
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.remove-button:hover {
|
|
83
|
+
opacity: 1;
|
|
101
84
|
}
|
|
102
85
|
|
|
103
86
|
.action.sortable {
|
|
@@ -131,14 +114,24 @@ export class CanvasNode extends RapidElement {
|
|
|
131
114
|
transition: all 200ms ease-in-out;
|
|
132
115
|
cursor: move;
|
|
133
116
|
background: rgba(0, 0, 0, 0.02);
|
|
134
|
-
|
|
135
|
-
|
|
117
|
+
width: 1em;
|
|
118
|
+
padding: 0.25em;
|
|
119
|
+
border: 0px solid red;
|
|
120
|
+
pointer-events: auto; /* Ensure drag handle can receive events */
|
|
121
|
+
}
|
|
122
|
+
.title-spacer {
|
|
123
|
+
width: 2em;
|
|
124
|
+
|
|
136
125
|
}
|
|
137
126
|
|
|
138
127
|
.action:hover .drag-handle {
|
|
139
|
-
opacity: 0.
|
|
140
|
-
|
|
141
|
-
|
|
128
|
+
opacity: 0.7;
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
strong {
|
|
134
|
+
font-weight: 500;
|
|
142
135
|
}
|
|
143
136
|
|
|
144
137
|
.action .drag-handle:hover {
|
|
@@ -146,20 +139,27 @@ export class CanvasNode extends RapidElement {
|
|
|
146
139
|
|
|
147
140
|
}
|
|
148
141
|
|
|
149
|
-
.action .title,
|
|
150
|
-
.router .title {
|
|
142
|
+
.action .cn-title,
|
|
143
|
+
.router .cn-title {
|
|
151
144
|
display: flex;
|
|
152
145
|
color: #fff;
|
|
153
|
-
padding: 5px 1px;
|
|
154
146
|
text-align: center;
|
|
155
147
|
font-size: 1em;
|
|
156
|
-
font-weight:
|
|
148
|
+
font-weight: 500;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.cn-title .name {
|
|
152
|
+
padding: 0.3em 0;
|
|
153
|
+
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.router .cn-title {
|
|
157
157
|
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
.title .name {
|
|
160
|
+
.cn-title .name {
|
|
161
161
|
flex-grow: 1;
|
|
162
|
-
|
|
162
|
+
}
|
|
163
163
|
|
|
164
164
|
.quick-replies {
|
|
165
165
|
margin-top: 0.5em;
|
|
@@ -196,7 +196,7 @@ export class CanvasNode extends RapidElement {
|
|
|
196
196
|
margin-top: -0.8em;
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
-
.category .title {
|
|
199
|
+
.category .cn-title {
|
|
200
200
|
font-weight: normal;
|
|
201
201
|
font-size: 1em;
|
|
202
202
|
max-width: 150px;
|
|
@@ -210,7 +210,7 @@ export class CanvasNode extends RapidElement {
|
|
|
210
210
|
}
|
|
211
211
|
|
|
212
212
|
.result-name {
|
|
213
|
-
font-weight:
|
|
213
|
+
font-weight: 500;
|
|
214
214
|
display: inline-block;
|
|
215
215
|
}
|
|
216
216
|
|
|
@@ -286,7 +286,7 @@ export class CanvasNode extends RapidElement {
|
|
|
286
286
|
border-bottom-right-radius: var(--curvature);
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
-
.router .title {
|
|
289
|
+
.router .cn-title {
|
|
290
290
|
border-top-left-radius: var(--curvature);
|
|
291
291
|
border-top-right-radius: var(--curvature);
|
|
292
292
|
}
|
|
@@ -295,7 +295,7 @@ export class CanvasNode extends RapidElement {
|
|
|
295
295
|
overflow: hidden;
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
-
.action:first-child .title {
|
|
298
|
+
.action:first-child .cn-title {
|
|
299
299
|
border-top-left-radius: var(--curvature);
|
|
300
300
|
border-top-right-radius: var(--curvature);
|
|
301
301
|
}
|
|
@@ -521,9 +521,10 @@ export class CanvasNode extends RapidElement {
|
|
|
521
521
|
(_a = getStore()) === null || _a === void 0 ? void 0 : _a.getState().updateNode(this.node.uuid, { ...this.node, actions: newActions });
|
|
522
522
|
}
|
|
523
523
|
handleActionMouseDown(event, action) {
|
|
524
|
-
// Don't handle clicks on the remove button or when action is in removing state
|
|
524
|
+
// Don't handle clicks on the remove button, drag handle, or when action is in removing state
|
|
525
525
|
const target = event.target;
|
|
526
526
|
if (target.closest('.remove-button') ||
|
|
527
|
+
target.closest('.drag-handle') ||
|
|
527
528
|
this.actionRemovingState.has(action.uuid)) {
|
|
528
529
|
return;
|
|
529
530
|
}
|
|
@@ -540,9 +541,10 @@ export class CanvasNode extends RapidElement {
|
|
|
540
541
|
this.pendingActionClick = null;
|
|
541
542
|
return;
|
|
542
543
|
}
|
|
543
|
-
// Don't handle clicks on the remove button or when action is in removing state
|
|
544
|
+
// Don't handle clicks on the remove button, drag handle, or when action is in removing state
|
|
544
545
|
const target = event.target;
|
|
545
546
|
if (target.closest('.remove-button') ||
|
|
547
|
+
target.closest('.drag-handle') ||
|
|
546
548
|
this.actionRemovingState.has(action.uuid)) {
|
|
547
549
|
this.actionClickStartPos = null;
|
|
548
550
|
this.pendingActionClick = null;
|
|
@@ -615,11 +617,12 @@ export class CanvasNode extends RapidElement {
|
|
|
615
617
|
}
|
|
616
618
|
}
|
|
617
619
|
handleNodeMouseDown(event) {
|
|
618
|
-
// Don't handle clicks on the remove button, exits, or when node is in removing state
|
|
620
|
+
// Don't handle clicks on the remove button, exits, drag handle, or when node is in removing state
|
|
619
621
|
const target = event.target;
|
|
620
622
|
if (target.closest('.remove-button') ||
|
|
621
623
|
target.closest('.exit') ||
|
|
622
624
|
target.closest('.exit-wrapper') ||
|
|
625
|
+
target.closest('.drag-handle') ||
|
|
623
626
|
this.actionRemovingState.has(this.node.uuid)) {
|
|
624
627
|
return;
|
|
625
628
|
}
|
|
@@ -635,11 +638,12 @@ export class CanvasNode extends RapidElement {
|
|
|
635
638
|
this.pendingNodeClick = null;
|
|
636
639
|
return;
|
|
637
640
|
}
|
|
638
|
-
// Don't handle clicks on the remove button, exits, or when node is in removing state
|
|
641
|
+
// Don't handle clicks on the remove button, exits, drag handle, or when node is in removing state
|
|
639
642
|
const target = event.target;
|
|
640
643
|
if (target.closest('.remove-button') ||
|
|
641
644
|
target.closest('.exit') ||
|
|
642
645
|
target.closest('.exit-wrapper') ||
|
|
646
|
+
target.closest('.drag-handle') ||
|
|
643
647
|
this.actionRemovingState.has(this.node.uuid)) {
|
|
644
648
|
this.nodeClickStartPos = null;
|
|
645
649
|
this.pendingNodeClick = null;
|
|
@@ -680,22 +684,37 @@ export class CanvasNode extends RapidElement {
|
|
|
680
684
|
this.nodeClickStartPos = null;
|
|
681
685
|
this.pendingNodeClick = null;
|
|
682
686
|
}
|
|
683
|
-
renderTitle(config, isRemoving = false) {
|
|
687
|
+
renderTitle(config, action, index, isRemoving = false) {
|
|
684
688
|
var _a, _b;
|
|
685
|
-
return html `<div class="title" style="background:${config.color}">
|
|
689
|
+
return html `<div class="cn-title" style="background:${config.color}">
|
|
686
690
|
${((_b = (_a = this.node) === null || _a === void 0 ? void 0 : _a.actions) === null || _b === void 0 ? void 0 : _b.length) > 1
|
|
687
691
|
? html `<temba-icon class="drag-handle" name="sort"></temba-icon>`
|
|
688
692
|
: null}
|
|
689
693
|
|
|
690
694
|
<div class="name">${isRemoving ? 'Remove?' : config.name}</div>
|
|
695
|
+
<div
|
|
696
|
+
class="remove-button"
|
|
697
|
+
@click=${(e) => this.handleActionRemoveClick(e, action, index)}
|
|
698
|
+
title="Remove action"
|
|
699
|
+
>
|
|
700
|
+
✕
|
|
701
|
+
</div>
|
|
691
702
|
</div>`;
|
|
692
703
|
}
|
|
693
704
|
renderNodeTitle(config, isRemoving = false) {
|
|
694
705
|
return html `<div
|
|
695
|
-
class="title ${isRemoving ? 'removing' : ''}"
|
|
706
|
+
class="cn-title ${isRemoving ? 'removing' : ''}"
|
|
696
707
|
style="background:${config.color}"
|
|
697
708
|
>
|
|
709
|
+
<div class="title-spacer"></div>
|
|
698
710
|
<div class="name">${isRemoving ? 'Remove?' : config.name}</div>
|
|
711
|
+
<div
|
|
712
|
+
class="remove-button"
|
|
713
|
+
@click=${(e) => this.handleNodeRemoveClick(e)}
|
|
714
|
+
title="Remove node"
|
|
715
|
+
>
|
|
716
|
+
✕
|
|
717
|
+
</div>
|
|
699
718
|
</div>`;
|
|
700
719
|
}
|
|
701
720
|
renderAction(node, action, index) {
|
|
@@ -706,20 +725,13 @@ export class CanvasNode extends RapidElement {
|
|
|
706
725
|
class="action sortable ${action.type} ${isRemoving ? 'removing' : ''}"
|
|
707
726
|
id="action-${index}"
|
|
708
727
|
>
|
|
709
|
-
<button
|
|
710
|
-
class="remove-button"
|
|
711
|
-
@click=${(e) => this.handleActionRemoveClick(e, action, index)}
|
|
712
|
-
title="Remove action"
|
|
713
|
-
>
|
|
714
|
-
✕
|
|
715
|
-
</button>
|
|
716
728
|
<div
|
|
717
729
|
class="action-content"
|
|
718
730
|
@mousedown=${(e) => this.handleActionMouseDown(e, action)}
|
|
719
731
|
@mouseup=${(e) => this.handleActionMouseUp(e, action)}
|
|
720
732
|
style="cursor: pointer;"
|
|
721
733
|
>
|
|
722
|
-
${this.renderTitle(config, isRemoving)}
|
|
734
|
+
${this.renderTitle(config, action, index, isRemoving)}
|
|
723
735
|
<div class="body">
|
|
724
736
|
${config.render
|
|
725
737
|
? config.render(node, action)
|
|
@@ -732,13 +744,13 @@ export class CanvasNode extends RapidElement {
|
|
|
732
744
|
class="action sortable ${isRemoving ? 'removing' : ''}"
|
|
733
745
|
id="action-${index}"
|
|
734
746
|
>
|
|
735
|
-
<
|
|
747
|
+
<div
|
|
736
748
|
class="remove-button"
|
|
737
749
|
@click=${(e) => this.handleActionRemoveClick(e, action, index)}
|
|
738
750
|
title="Remove action"
|
|
739
751
|
>
|
|
740
752
|
✕
|
|
741
|
-
</
|
|
753
|
+
</div>
|
|
742
754
|
${action.type}
|
|
743
755
|
</div>`;
|
|
744
756
|
}
|
|
@@ -773,7 +785,7 @@ export class CanvasNode extends RapidElement {
|
|
|
773
785
|
@mouseup=${(e) => this.handleNodeMouseUp(e)}
|
|
774
786
|
style="cursor: pointer;"
|
|
775
787
|
>
|
|
776
|
-
<div class="title">${category.name}</div>
|
|
788
|
+
<div class="cn-title">${category.name}</div>
|
|
777
789
|
${this.renderExit(exit)}
|
|
778
790
|
</div>`;
|
|
779
791
|
})}
|
|
@@ -807,13 +819,6 @@ export class CanvasNode extends RapidElement {
|
|
|
807
819
|
>
|
|
808
820
|
${nodeConfig && nodeConfig.type !== 'execute_actions'
|
|
809
821
|
? html `<div class="router" style="position: relative;">
|
|
810
|
-
<button
|
|
811
|
-
class="remove-button"
|
|
812
|
-
@click=${(e) => this.handleNodeRemoveClick(e)}
|
|
813
|
-
title="Remove node"
|
|
814
|
-
>
|
|
815
|
-
✕
|
|
816
|
-
</button>
|
|
817
822
|
<div
|
|
818
823
|
@mousedown=${(e) => this.handleNodeMouseDown(e)}
|
|
819
824
|
@mouseup=${(e) => this.handleNodeMouseUp(e)}
|