@nyaruka/temba-components 0.142.1 → 0.142.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 +19 -0
- package/dist/temba-components.js +953 -708
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/Icons.js +1 -0
- package/out-tsc/src/Icons.js.map +1 -1
- package/out-tsc/src/flow/CanvasMenu.js +38 -38
- package/out-tsc/src/flow/CanvasMenu.js.map +1 -1
- package/out-tsc/src/flow/CanvasNode.js +171 -17
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +491 -22
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeEditor.js +346 -10
- package/out-tsc/src/flow/NodeEditor.js.map +1 -1
- package/out-tsc/src/flow/NodeTypeSelector.js +2 -0
- package/out-tsc/src/flow/NodeTypeSelector.js.map +1 -1
- package/out-tsc/src/flow/Plumber.js +92 -28
- package/out-tsc/src/flow/Plumber.js.map +1 -1
- package/out-tsc/src/flow/StickyNote.js +63 -3
- package/out-tsc/src/flow/StickyNote.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_urn.js +2 -6
- package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -1
- package/out-tsc/src/flow/actions/enter_flow.js +2 -2
- package/out-tsc/src/flow/actions/enter_flow.js.map +1 -1
- package/out-tsc/src/flow/actions/say_msg.js +2 -1
- package/out-tsc/src/flow/actions/say_msg.js.map +1 -1
- package/out-tsc/src/flow/actions/send_broadcast.js +2 -6
- package/out-tsc/src/flow/actions/send_broadcast.js.map +1 -1
- package/out-tsc/src/flow/actions/send_email.js +2 -6
- package/out-tsc/src/flow/actions/send_email.js.map +1 -1
- package/out-tsc/src/flow/actions/send_msg.js +55 -35
- package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_channel.js +2 -1
- package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_field.js +4 -5
- package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_language.js +3 -3
- package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_name.js +2 -1
- package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_status.js +2 -1
- package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
- package/out-tsc/src/flow/actions/set_run_result.js +3 -3
- package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
- package/out-tsc/src/flow/actions/start_session.js +2 -2
- package/out-tsc/src/flow/actions/start_session.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_llm.js +4 -5
- package/out-tsc/src/flow/nodes/split_by_llm.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_resthook.js +3 -8
- package/out-tsc/src/flow/nodes/split_by_resthook.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_subflow.js +4 -2
- package/out-tsc/src/flow/nodes/split_by_subflow.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_webhook.js +25 -33
- package/out-tsc/src/flow/nodes/split_by_webhook.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_response.js +1 -0
- package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
- package/out-tsc/src/flow/types.js.map +1 -1
- package/out-tsc/src/flow/utils.js +66 -0
- package/out-tsc/src/flow/utils.js.map +1 -1
- package/out-tsc/src/form/FieldRenderer.js +17 -2
- package/out-tsc/src/form/FieldRenderer.js.map +1 -1
- package/out-tsc/src/interfaces.js +1 -0
- package/out-tsc/src/interfaces.js.map +1 -1
- package/out-tsc/src/list/SortableList.js +104 -43
- package/out-tsc/src/list/SortableList.js.map +1 -1
- package/out-tsc/src/simulator/Simulator.js +6 -2
- package/out-tsc/src/simulator/Simulator.js.map +1 -1
- package/out-tsc/test/temba-canvas-menu.test.js +13 -9
- package/out-tsc/test/temba-canvas-menu.test.js.map +1 -1
- package/out-tsc/test/temba-flow-reflow.test.js.map +1 -1
- package/out-tsc/test/temba-node-editor.test.js +9 -10
- package/out-tsc/test/temba-node-editor.test.js.map +1 -1
- package/out-tsc/test/temba-node-type-selector.test.js +3 -3
- package/out-tsc/test/temba-node-type-selector.test.js.map +1 -1
- package/out-tsc/test/temba-simulator.test.js +2 -2
- package/out-tsc/test/temba-simulator.test.js.map +1 -1
- package/package.json +1 -1
- package/screenshots/truth/actions/enter_flow/render/basic-flow.png +0 -0
- package/screenshots/truth/actions/enter_flow/render/long-flow-name.png +0 -0
- package/screenshots/truth/actions/send_email/render/long-subject.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/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/start_session/render/contact-query.png +0 -0
- package/screenshots/truth/actions/start_session/render/contacts-only.png +0 -0
- package/screenshots/truth/actions/start_session/render/create-contact.png +0 -0
- package/screenshots/truth/actions/start_session/render/groups-and-contacts.png +0 -0
- package/screenshots/truth/actions/start_session/render/groups-only.png +0 -0
- package/screenshots/truth/actions/start_session/render/many-recipients.png +0 -0
- package/screenshots/truth/canvas-menu/open.png +0 -0
- package/screenshots/truth/node-type-selector/action-mode.png +0 -0
- package/screenshots/truth/node-type-selector/split-mode.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_categorize/editor/feedback-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/feedback-categorization.png +0 -0
- package/src/Icons.ts +1 -0
- package/src/flow/CanvasMenu.ts +50 -43
- package/src/flow/CanvasNode.ts +201 -17
- package/src/flow/Editor.ts +585 -25
- package/src/flow/NodeEditor.ts +373 -10
- package/src/flow/NodeTypeSelector.ts +2 -0
- package/src/flow/Plumber.ts +104 -37
- package/src/flow/StickyNote.ts +76 -4
- package/src/flow/actions/add_contact_urn.ts +5 -6
- package/src/flow/actions/enter_flow.ts +2 -2
- package/src/flow/actions/say_msg.ts +2 -1
- package/src/flow/actions/send_broadcast.ts +2 -6
- package/src/flow/actions/send_email.ts +2 -6
- package/src/flow/actions/send_msg.ts +59 -38
- package/src/flow/actions/set_contact_channel.ts +5 -1
- package/src/flow/actions/set_contact_field.ts +10 -5
- package/src/flow/actions/set_contact_language.ts +6 -3
- package/src/flow/actions/set_contact_name.ts +5 -1
- package/src/flow/actions/set_contact_status.ts +5 -1
- package/src/flow/actions/set_run_result.ts +6 -3
- package/src/flow/actions/start_session.ts +2 -2
- package/src/flow/nodes/split_by_llm.ts +5 -5
- package/src/flow/nodes/split_by_resthook.ts +3 -8
- package/src/flow/nodes/split_by_subflow.ts +4 -2
- package/src/flow/nodes/split_by_webhook.ts +26 -34
- package/src/flow/nodes/wait_for_response.ts +1 -0
- package/src/flow/types.ts +25 -2
- package/src/flow/utils.ts +79 -1
- package/src/form/FieldRenderer.ts +32 -3
- package/src/interfaces.ts +1 -0
- package/src/list/SortableList.ts +117 -47
- package/src/simulator/Simulator.ts +6 -2
- package/test/temba-canvas-menu.test.ts +13 -9
- package/test/temba-flow-reflow.test.ts +4 -2
- package/test/temba-node-editor.test.ts +9 -10
- package/test/temba-node-type-selector.test.ts +3 -3
- package/test/temba-simulator.test.ts +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StickyNote.js","sourceRoot":"","sources":["../../../src/flow/StickyNote.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, PropertyValueMap, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { RapidElement } from '../RapidElement';\nimport { StickyNote as StickyNoteData } from '../store/flow-definition';\nimport { getStore } from '../store/Store';\nimport { AppState, fromStore, zustand } from '../store/AppState';\n\nexport class StickyNote extends RapidElement {\n @property({ type: String })\n public uuid: string;\n\n @property({ type: Object })\n public data: StickyNoteData;\n\n @property({ type: Boolean })\n private dragging = false;\n\n @property({ type: Boolean })\n public selected = false;\n\n @property({ type: Boolean })\n private colorPickerExpanded = false;\n\n @fromStore(zustand, (state: AppState) => state.isTranslating)\n private isTranslating!: boolean;\n\n static get styles() {\n return css`\n :host {\n --sticky-color: #fef08a;\n --sticky-border-color: #facc15;\n --sticky-text-color: #451a03;\n --curvature: 8px;\n }\n\n .sticky-note {\n width: 182px;\n background-color: var(--sticky-color);\n border: 1px solid var(--sticky-border-color);\n border-radius: var(--curvature);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,\n sans-serif;\n font-size: 12px;\n overflow: hidden;\n transition: transform 0.1s ease, box-shadow 0.2s ease;\n color: var(--sticky-text-color);\n opacity: 0.85;\n }\n\n .sticky-note.dragging {\n opacity: 0.7;\n z-index: 1000;\n transform: rotate(0deg);\n box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);\n }\n\n .sticky-note:hover {\n transform: translateY(0px);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);\n }\n\n /* Color themes */\n .sticky-note.yellow {\n --sticky-color: #fef08a;\n --sticky-border-color: #facc15;\n --sticky-text-color: #451a03;\n }\n .sticky-note.blue {\n --sticky-color: #bfdbfe;\n --sticky-border-color: #3b82f6;\n --sticky-text-color: #1e3a8a;\n }\n .sticky-note.pink {\n --sticky-color: #fce7f3;\n --sticky-border-color: #ec4899;\n --sticky-text-color: #831843;\n }\n .sticky-note.green {\n --sticky-color: #d1fae5;\n --sticky-border-color: #10b981;\n --sticky-text-color: #064e3b;\n }\n .sticky-note.gray {\n --sticky-color: #f3f4f6;\n --sticky-border-color: #6b7280;\n --sticky-text-color: #374151;\n }\n\n /* Title and body containers */\n .sticky-title-container {\n position: relative;\n border-bottom: 1px solid var(--sticky-border-color);\n background-color: rgba(255, 255, 255, 0.5);\n display: flex;\n align-items: center;\n }\n .sticky-body-container {\n position: relative;\n }\n\n /* Editable fields */\n [contenteditable='true'] {\n margin: 2px;\n padding: 4px 8px;\n outline: none;\n border-radius: var(--curvature);\n transition: background 0.2s;\n }\n [contenteditable='true']:focus {\n background-color: rgba(255, 255, 255, 0.8);\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n outline-color: var(--sticky-border-color);\n }\n\n /* Title */\n .sticky-title {\n font-weight: 600;\n font-size: 13px;\n color: var(--sticky-text-color);\n min-height: 20px;\n line-height: 20px;\n border-top-left-radius: var(--curvature);\n border-top-right-radius: var(--curvature);\n flex-grow: 1;\n padding: 4px 8px !important;\n margin: 2px;\n padding-left: 8px;\n }\n .sticky-title:empty::before {\n content: 'Click to add title';\n opacity: 0.5;\n font-style: italic;\n }\n .sticky-title:focus {\n border-bottom-left-radius: 0px;\n border-bottom-right-radius: 0px;\n }\n\n /* Body */\n .sticky-body {\n padding: 8px 10px;\n color: var(--sticky-text-color);\n line-height: 1.4;\n min-height: 48px;\n word-wrap: break-word;\n white-space: pre-wrap;\n margin: 2px;\n }\n .sticky-body:empty::before {\n content: 'Click to add note';\n opacity: 0.5;\n font-style: italic;\n }\n .sticky-body:focus {\n border-top-left-radius: 0px;\n border-top-right-radius: 0px;\n }\n\n /* Drag icon */\n .sticky-title-container > .drag-handle {\n --icon-color: var(--sticky-border-color);\n cursor: move;\n max-width: 20px;\n padding-left: 8px;\n overflow: hidden;\n transition: all 0.2s ease;\n }\n\n .sticky-note:hover .drag-handle {\n }\n\n .sticky-note:focus-within .sticky-title-container > .drag-handle {\n }\n\n /* Focus/active states */\n .sticky-note:focus-within {\n box-shadow: 0 0 0 1px var(--sticky-border-color),\n 0 10px 20px rgba(0, 0, 0, 0.3);\n }\n\n .sticky-note:focus-within .drag-handle {\n max-width: 0px;\n padding-left: 0px;\n }\n\n /* Color picker */\n .color-picker {\n position: absolute;\n bottom: 4px;\n right: 4px;\n width: 8px;\n height: 8px;\n border: 1px solid rgba(0, 0, 0, 0.2);\n\n border-radius: 3px;\n background-color: var(--sticky-color);\n cursor: pointer;\n transition: transform 0.2s ease;\n }\n\n .color-picker:hover {\n transform: scale(1.1);\n }\n\n .color-options {\n position: absolute;\n bottom: 0;\n right: 0;\n display: flex;\n gap: 4px;\n background-color: rgba(255, 255, 255, 0.9);\n border: 1px solid #ccc;\n border-radius: 6px;\n padding: 3px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n transform-origin: bottom right;\n transform: scale(0);\n opacity: 0;\n transition: transform 0.2s ease, opacity 0.2s ease;\n z-index: 1000;\n }\n\n .color-options.expanded {\n transform: scale(1);\n opacity: 1;\n }\n\n .color-option {\n width: 12px;\n height: 12px;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 3px;\n cursor: pointer;\n transition: transform 0.15s ease, border-color 0.15s ease;\n }\n\n .color-option:hover {\n transform: scale(1.1);\n border-color: rgba(0, 0, 0, 0.4);\n }\n\n .color-option.yellow {\n background-color: #fef08a;\n }\n\n .color-option.blue {\n background-color: #bfdbfe;\n }\n\n .color-option.pink {\n background-color: #fce7f3;\n }\n\n .color-option.green {\n background-color: #d1fae5;\n }\n\n .color-option.gray {\n background-color: #f3f4f6;\n }\n `;\n }\n\n protected updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n if (changes.has('data') || changes.has('uuid')) {\n this.updateCanvasSize();\n }\n }\n\n private updateCanvasSize(): void {\n if (!this.data) {\n return;\n }\n\n const element = this.querySelector('.sticky-note');\n if (element) {\n const rect = element.getBoundingClientRect();\n getStore()\n .getState()\n .expandCanvas(\n this.data.position.left + rect.width,\n this.data.position.top + rect.height\n );\n }\n }\n\n private handleTitleBlur(event: FocusEvent): void {\n const target = event.target as HTMLElement;\n const newTitle = target.textContent || '';\n\n if (this.data && newTitle !== this.data.title) {\n getStore()\n .getState()\n .updateStickyNote(this.uuid, {\n ...this.data,\n title: newTitle\n });\n }\n this.requestUpdate();\n }\n\n private handleBodyBlur(event: FocusEvent): void {\n const target = event.target as HTMLElement;\n const newBody = target.innerText || '';\n\n if (this.data && newBody !== this.data.body) {\n getStore()\n .getState()\n .updateStickyNote(this.uuid, {\n ...this.data,\n body: newBody\n });\n }\n this.requestUpdate();\n }\n\n private handleContentMouseDown(event: MouseEvent): void {\n // If this sticky note is selected, don't stop propagation\n // so that group dragging can work\n if (this.selected) {\n return;\n }\n // Otherwise, stop propagation to enable editing\n event.stopPropagation();\n }\n\n private handleTitleKeyDown(event: KeyboardEvent): void {\n if (event.key === 'Enter') {\n event.preventDefault();\n (event.target as HTMLElement).blur();\n }\n if (event.key === 'Escape') {\n (event.target as HTMLElement).blur();\n }\n }\n\n private handleBodyKeyDown(event: KeyboardEvent): void {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n (event.target as HTMLElement).blur();\n }\n if (event.key === 'Escape') {\n (event.target as HTMLElement).blur();\n }\n }\n\n private handleColorPickerMouseEnter(): void {\n this.colorPickerExpanded = true;\n }\n\n private handleColorPickerMouseLeave(): void {\n this.colorPickerExpanded = false;\n }\n\n private handleColorOptionClick(\n event: MouseEvent,\n color: 'yellow' | 'blue' | 'pink' | 'green' | 'gray'\n ): void {\n event.stopPropagation();\n\n if (this.data && color !== this.data.color) {\n getStore()\n .getState()\n .updateStickyNote(this.uuid, {\n ...this.data,\n color: color\n });\n }\n\n this.colorPickerExpanded = false;\n this.requestUpdate();\n }\n\n public render(): TemplateResult {\n if (!this.data) {\n return html`<div class=\"sticky-note\" style=\"display: none;\"></div>`;\n }\n\n const style = `left: ${this.data.position.left}px; top: ${this.data.position.top}px;`;\n\n return html`\n <div\n class=\"sticky-note ${this.data.color} ${this.dragging\n ? 'dragging'\n : ''}\"\n style=\"${style}\"\n data-uuid=\"${this.uuid}\"\n >\n <div class=\"sticky-title-container\">\n <temba-icon name=\"drag\" class=\"drag-handle\"></temba-icon>\n <div\n class=\"sticky-title\"\n contenteditable=\"${!this.isTranslating}\"\n @blur=\"${this.handleTitleBlur}\"\n @keydown=\"${this.handleTitleKeyDown}\"\n @mousedown=\"${this.handleContentMouseDown}\"\n .textContent=\"${this.data.title}\"\n ></div>\n </div>\n <div class=\"sticky-body-container\">\n <div\n class=\"sticky-body\"\n contenteditable=\"${!this.isTranslating}\"\n @blur=\"${this.handleBodyBlur}\"\n @keydown=\"${this.handleBodyKeyDown}\"\n @mousedown=\"${this.handleContentMouseDown}\"\n .textContent=\"${this.data.body}\"\n ></div>\n ${!this.isTranslating\n ? html`<div class=\"edit-icon\" title=\"Edit note\"></div>`\n : ''}\n\n <!-- Color picker -->\n <div\n class=\"color-picker\"\n @mouseenter=\"${this.handleColorPickerMouseEnter}\"\n @mouseleave=\"${this.handleColorPickerMouseLeave}\"\n >\n <div\n class=\"color-options ${this.colorPickerExpanded\n ? 'expanded'\n : ''}\"\n >\n <div\n class=\"color-option yellow\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'yellow')}\"\n ></div>\n <div\n class=\"color-option blue\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'blue')}\"\n ></div>\n <div\n class=\"color-option pink\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'pink')}\"\n ></div>\n <div\n class=\"color-option green\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'green')}\"\n ></div>\n <div\n class=\"color-option gray\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'gray')}\"\n ></div>\n </div>\n </div>\n </div>\n </div>\n `;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"StickyNote.js","sourceRoot":"","sources":["../../../src/flow/StickyNote.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, PropertyValueMap, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { RapidElement } from '../RapidElement';\nimport { StickyNote as StickyNoteData } from '../store/flow-definition';\nimport { getStore } from '../store/Store';\nimport { AppState, fromStore, zustand } from '../store/AppState';\n\nexport class StickyNote extends RapidElement {\n @property({ type: String })\n public uuid: string;\n\n @property({ type: Object })\n public data: StickyNoteData;\n\n @property({ type: Boolean })\n private dragging = false;\n\n @property({ type: Boolean })\n public selected = false;\n\n @property({ type: Boolean })\n private colorPickerExpanded = false;\n\n // On touch devices, contenteditable starts false to prevent Apple Pencil\n // Scribble from hijacking touches. It is set to true on explicit tap.\n private isTouchDevice = navigator.maxTouchPoints > 0;\n private editingField: HTMLElement | null = null;\n\n @fromStore(zustand, (state: AppState) => state.isTranslating)\n private isTranslating!: boolean;\n\n static get styles() {\n return css`\n :host {\n --sticky-color: #fef08a;\n --sticky-border-color: #facc15;\n --sticky-text-color: #451a03;\n --curvature: 8px;\n }\n\n .sticky-note {\n width: 182px;\n background-color: var(--sticky-color);\n border: 1px solid var(--sticky-border-color);\n border-radius: var(--curvature);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,\n sans-serif;\n font-size: 12px;\n overflow: hidden;\n transition: transform 0.1s ease, box-shadow 0.2s ease;\n color: var(--sticky-text-color);\n opacity: 0.85;\n }\n\n .sticky-note.dragging {\n opacity: 0.7;\n z-index: 1000;\n transform: rotate(0deg);\n box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);\n }\n\n .sticky-note:hover {\n transform: translateY(0px);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);\n }\n\n /* Color themes */\n .sticky-note.yellow {\n --sticky-color: #fef08a;\n --sticky-border-color: #facc15;\n --sticky-text-color: #451a03;\n }\n .sticky-note.blue {\n --sticky-color: #bfdbfe;\n --sticky-border-color: #3b82f6;\n --sticky-text-color: #1e3a8a;\n }\n .sticky-note.pink {\n --sticky-color: #fce7f3;\n --sticky-border-color: #ec4899;\n --sticky-text-color: #831843;\n }\n .sticky-note.green {\n --sticky-color: #d1fae5;\n --sticky-border-color: #10b981;\n --sticky-text-color: #064e3b;\n }\n .sticky-note.gray {\n --sticky-color: #f3f4f6;\n --sticky-border-color: #6b7280;\n --sticky-text-color: #374151;\n }\n\n /* Title and body containers */\n .sticky-title-container {\n position: relative;\n border-bottom: 1px solid var(--sticky-border-color);\n background-color: rgba(255, 255, 255, 0.5);\n display: flex;\n align-items: center;\n }\n .sticky-body-container {\n position: relative;\n }\n\n /* Editable fields */\n [contenteditable='true'] {\n margin: 2px;\n padding: 4px 8px;\n outline: none;\n border-radius: var(--curvature);\n transition: background 0.2s;\n }\n [contenteditable='true']:focus {\n background-color: rgba(255, 255, 255, 0.8);\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n outline-color: var(--sticky-border-color);\n }\n\n /* Title */\n .sticky-title {\n font-weight: 600;\n font-size: 13px;\n color: var(--sticky-text-color);\n min-height: 20px;\n line-height: 20px;\n border-top-left-radius: var(--curvature);\n border-top-right-radius: var(--curvature);\n flex-grow: 1;\n padding: 4px 8px !important;\n margin: 2px;\n padding-left: 8px;\n }\n .sticky-title:empty::before {\n content: 'Click to add title';\n opacity: 0.5;\n font-style: italic;\n }\n .sticky-title:focus {\n border-bottom-left-radius: 0px;\n border-bottom-right-radius: 0px;\n }\n\n /* Body */\n .sticky-body {\n padding: 8px 10px;\n color: var(--sticky-text-color);\n line-height: 1.4;\n min-height: 48px;\n word-wrap: break-word;\n white-space: pre-wrap;\n margin: 2px;\n }\n .sticky-body:empty::before {\n content: 'Click to add note';\n opacity: 0.5;\n font-style: italic;\n }\n .sticky-body:focus {\n border-top-left-radius: 0px;\n border-top-right-radius: 0px;\n }\n\n /* Drag icon */\n .sticky-title-container > .drag-handle {\n --icon-color: var(--sticky-border-color);\n cursor: move;\n max-width: 20px;\n padding-left: 8px;\n overflow: hidden;\n transition: all 0.2s ease;\n }\n\n .sticky-note:hover .drag-handle {\n }\n\n .sticky-note:focus-within .sticky-title-container > .drag-handle {\n }\n\n /* Focus/active states */\n .sticky-note:focus-within {\n box-shadow: 0 0 0 1px var(--sticky-border-color),\n 0 10px 20px rgba(0, 0, 0, 0.3);\n }\n\n .sticky-note:focus-within .drag-handle {\n max-width: 0px;\n padding-left: 0px;\n }\n\n /* Color picker */\n .color-picker {\n position: absolute;\n bottom: 4px;\n right: 4px;\n width: 8px;\n height: 8px;\n border: 1px solid rgba(0, 0, 0, 0.2);\n\n border-radius: 3px;\n background-color: var(--sticky-color);\n cursor: pointer;\n transition: transform 0.2s ease;\n }\n\n .color-picker:hover {\n transform: scale(1.1);\n }\n\n .color-options {\n position: absolute;\n bottom: 0;\n right: 0;\n display: flex;\n gap: 4px;\n background-color: rgba(255, 255, 255, 0.9);\n border: 1px solid #ccc;\n border-radius: 6px;\n padding: 3px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n transform-origin: bottom right;\n transform: scale(0);\n opacity: 0;\n transition: transform 0.2s ease, opacity 0.2s ease;\n z-index: 1000;\n }\n\n .color-options.expanded {\n transform: scale(1);\n opacity: 1;\n }\n\n .color-option {\n width: 12px;\n height: 12px;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 3px;\n cursor: pointer;\n transition: transform 0.15s ease, border-color 0.15s ease;\n }\n\n .color-option:hover {\n transform: scale(1.1);\n border-color: rgba(0, 0, 0, 0.4);\n }\n\n .color-option.yellow {\n background-color: #fef08a;\n }\n\n .color-option.blue {\n background-color: #bfdbfe;\n }\n\n .color-option.pink {\n background-color: #fce7f3;\n }\n\n .color-option.green {\n background-color: #d1fae5;\n }\n\n .color-option.gray {\n background-color: #f3f4f6;\n }\n `;\n }\n\n protected updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n if (changes.has('data') || changes.has('uuid')) {\n this.updateCanvasSize();\n }\n }\n\n private updateCanvasSize(): void {\n if (!this.data) {\n return;\n }\n\n const element = this.querySelector('.sticky-note');\n if (element) {\n const rect = element.getBoundingClientRect();\n getStore()\n .getState()\n .expandCanvas(\n this.data.position.left + rect.width,\n this.data.position.top + rect.height\n );\n }\n }\n\n private handleTitleBlur(event: FocusEvent): void {\n this.handleContentBlurForTouch(event);\n const target = event.target as HTMLElement;\n const newTitle = target.textContent || '';\n\n if (this.data && newTitle !== this.data.title) {\n getStore()\n .getState()\n .updateStickyNote(this.uuid, {\n ...this.data,\n title: newTitle\n });\n }\n this.requestUpdate();\n }\n\n private handleBodyBlur(event: FocusEvent): void {\n this.handleContentBlurForTouch(event);\n const target = event.target as HTMLElement;\n const newBody = target.innerText || '';\n\n if (this.data && newBody !== this.data.body) {\n getStore()\n .getState()\n .updateStickyNote(this.uuid, {\n ...this.data,\n body: newBody\n });\n }\n this.requestUpdate();\n }\n\n /* c8 ignore start -- touch-only handlers untestable in headless Chromium */\n private handleDragHandleTouchStart(event: TouchEvent): void {\n // Prevent Apple Pencil Scribble from activating on the adjacent\n // contenteditable fields when touching/dragging the handle.\n event.preventDefault();\n }\n\n /**\n * On touch devices, contenteditable is off by default. A tap on the\n * title or body enables it and focuses the element for editing.\n */\n private handleContentTap(event: TouchEvent): void {\n if (!this.isTouchDevice) return;\n const target = event.target as HTMLElement;\n if (\n !target.classList.contains('sticky-title') &&\n !target.classList.contains('sticky-body')\n )\n return;\n\n // Enable editing and focus\n target.setAttribute('contenteditable', 'true');\n this.editingField = target;\n target.focus();\n event.stopPropagation();\n }\n\n /**\n * When a contenteditable field loses focus on a touch device,\n * disable contenteditable again to prevent Scribble.\n */\n private handleContentBlurForTouch(event: FocusEvent): void {\n const target = event.target as HTMLElement;\n if (this.isTouchDevice && this.editingField === target) {\n target.setAttribute('contenteditable', 'false');\n this.editingField = null;\n }\n }\n /* c8 ignore stop */\n\n private handleContentMouseDown(event: MouseEvent): void {\n // If this sticky note is selected, don't stop propagation\n // so that group dragging can work\n if (this.selected) {\n return;\n }\n // Otherwise, stop propagation to enable editing\n event.stopPropagation();\n }\n\n private handleTitleKeyDown(event: KeyboardEvent): void {\n if (event.key === 'Enter') {\n event.preventDefault();\n (event.target as HTMLElement).blur();\n }\n if (event.key === 'Escape') {\n (event.target as HTMLElement).blur();\n }\n }\n\n private handleBodyKeyDown(event: KeyboardEvent): void {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n (event.target as HTMLElement).blur();\n }\n if (event.key === 'Escape') {\n (event.target as HTMLElement).blur();\n }\n }\n\n private handleColorPickerMouseEnter(): void {\n this.colorPickerExpanded = true;\n }\n\n private handleColorPickerMouseLeave(): void {\n this.colorPickerExpanded = false;\n }\n\n /* c8 ignore next 5 -- touch-only */\n private handleColorPickerTap(event: TouchEvent): void {\n event.stopPropagation();\n event.preventDefault();\n this.colorPickerExpanded = !this.colorPickerExpanded;\n }\n\n private handleColorOptionClick(\n event: MouseEvent | TouchEvent,\n color: 'yellow' | 'blue' | 'pink' | 'green' | 'gray'\n ): void {\n event.stopPropagation();\n event.preventDefault();\n\n if (this.data && color !== this.data.color) {\n getStore()\n .getState()\n .updateStickyNote(this.uuid, {\n ...this.data,\n color: color\n });\n }\n\n this.colorPickerExpanded = false;\n this.requestUpdate();\n }\n\n public render(): TemplateResult {\n if (!this.data) {\n return html`<div class=\"sticky-note\" style=\"display: none;\"></div>`;\n }\n\n const style = `left: ${this.data.position.left}px; top: ${this.data.position.top}px;`;\n\n return html`\n <div\n class=\"sticky-note ${this.data.color} ${this.dragging\n ? 'dragging'\n : ''}\"\n style=\"${style}\"\n data-uuid=\"${this.uuid}\"\n >\n <div class=\"sticky-title-container\">\n <temba-icon\n name=\"drag\"\n class=\"drag-handle\"\n @touchstart=${this.handleDragHandleTouchStart}\n ></temba-icon>\n <div\n class=\"sticky-title\"\n contenteditable=\"${!this.isTranslating && !this.isTouchDevice}\"\n @blur=\"${this.handleTitleBlur}\"\n @keydown=\"${this.handleTitleKeyDown}\"\n @mousedown=\"${this.handleContentMouseDown}\"\n @touchend=\"${this.handleContentTap}\"\n .textContent=\"${this.data.title}\"\n ></div>\n </div>\n <div class=\"sticky-body-container\">\n <div\n class=\"sticky-body\"\n contenteditable=\"${!this.isTranslating && !this.isTouchDevice}\"\n @blur=\"${this.handleBodyBlur}\"\n @keydown=\"${this.handleBodyKeyDown}\"\n @mousedown=\"${this.handleContentMouseDown}\"\n @touchend=\"${this.handleContentTap}\"\n .textContent=\"${this.data.body}\"\n ></div>\n ${!this.isTranslating\n ? html`<div class=\"edit-icon\" title=\"Edit note\"></div>`\n : ''}\n\n <!-- Color picker -->\n <div\n class=\"color-picker\"\n @mouseenter=\"${this.handleColorPickerMouseEnter}\"\n @mouseleave=\"${this.handleColorPickerMouseLeave}\"\n @touchend=\"${this.handleColorPickerTap}\"\n >\n <div\n class=\"color-options ${this.colorPickerExpanded\n ? 'expanded'\n : ''}\"\n >\n <div\n class=\"color-option yellow\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'yellow')}\"\n @touchend=\"${(e: TouchEvent) =>\n this.handleColorOptionClick(e, 'yellow')}\"\n ></div>\n <div\n class=\"color-option blue\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'blue')}\"\n @touchend=\"${(e: TouchEvent) =>\n this.handleColorOptionClick(e, 'blue')}\"\n ></div>\n <div\n class=\"color-option pink\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'pink')}\"\n @touchend=\"${(e: TouchEvent) =>\n this.handleColorOptionClick(e, 'pink')}\"\n ></div>\n <div\n class=\"color-option green\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'green')}\"\n @touchend=\"${(e: TouchEvent) =>\n this.handleColorOptionClick(e, 'green')}\"\n ></div>\n <div\n class=\"color-option gray\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'gray')}\"\n @touchend=\"${(e: TouchEvent) =>\n this.handleColorOptionClick(e, 'gray')}\"\n ></div>\n </div>\n </div>\n </div>\n </div>\n `;\n }\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { html } from 'lit-html';
|
|
2
2
|
import { ACTION_GROUPS, FlowTypes } from '../types';
|
|
3
|
-
import { SCHEMES } from '../utils';
|
|
3
|
+
import { SCHEMES, renderClamped } from '../utils';
|
|
4
4
|
export const add_contact_urn = {
|
|
5
5
|
name: 'Add URN',
|
|
6
6
|
group: ACTION_GROUPS.contacts,
|
|
@@ -8,11 +8,7 @@ export const add_contact_urn = {
|
|
|
8
8
|
render: (_node, action) => {
|
|
9
9
|
const schemeObj = SCHEMES.find((s) => s.scheme === action.scheme);
|
|
10
10
|
const friendlyScheme = (schemeObj === null || schemeObj === void 0 ? void 0 : schemeObj.path) || action.scheme;
|
|
11
|
-
return html
|
|
12
|
-
style="word-wrap: break-word; overflow-wrap: break-word; hyphens: auto;"
|
|
13
|
-
>
|
|
14
|
-
Add ${friendlyScheme} <strong>${action.path}</strong>
|
|
15
|
-
</div>`;
|
|
11
|
+
return renderClamped(html `Add ${friendlyScheme} <strong>${action.path}</strong>`, `Add ${friendlyScheme} ${action.path}`);
|
|
16
12
|
},
|
|
17
13
|
toFormData: (action) => {
|
|
18
14
|
const schemeObj = SCHEMES.find((s) => s.scheme === action.scheme);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add_contact_urn.js","sourceRoot":"","sources":["../../../../src/flow/actions/add_contact_urn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAEL,aAAa,EAGb,SAAS,EACV,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"add_contact_urn.js","sourceRoot":"","sources":["../../../../src/flow/actions/add_contact_urn.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport {\n ActionConfig,\n ACTION_GROUPS,\n FormData,\n ValidationResult,\n FlowTypes\n} from '../types';\nimport { Node, AddContactUrn } from '../../store/flow-definition';\nimport { SCHEMES, renderClamped } from '../utils';\n\nexport const add_contact_urn: ActionConfig = {\n name: 'Add URN',\n group: ACTION_GROUPS.contacts,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: AddContactUrn) => {\n const schemeObj = SCHEMES.find((s) => s.scheme === action.scheme);\n const friendlyScheme = schemeObj?.path || action.scheme;\n return renderClamped(\n html`Add ${friendlyScheme} <strong>${action.path}</strong>`,\n `Add ${friendlyScheme} ${action.path}`\n );\n },\n\n toFormData: (action: AddContactUrn) => {\n const schemeObj = SCHEMES.find((s) => s.scheme === action.scheme);\n return {\n uuid: action.uuid,\n scheme: schemeObj\n ? [{ name: schemeObj.path, value: action.scheme }]\n : null,\n path: action.path || ''\n };\n },\n\n fromFormData: (formData: FormData): AddContactUrn => {\n // Extract scheme value from select format\n const schemeValue =\n Array.isArray(formData.scheme) && formData.scheme.length > 0\n ? formData.scheme[0].value\n : 'tel';\n\n return {\n uuid: formData.uuid,\n type: 'add_contact_urn',\n scheme: schemeValue,\n path: formData.path || ''\n };\n },\n\n form: {\n scheme: {\n type: 'select',\n label: 'URN Type',\n helpText: 'Select the type of URN to add to the contact',\n required: true,\n searchable: false,\n multi: false,\n options: SCHEMES.map((scheme) => ({\n name: scheme.path,\n value: scheme.scheme\n }))\n },\n path: {\n type: 'text',\n label: 'URN Value',\n helpText: 'Enter the URN value (e.g., phone number, Facebook ID, etc.)',\n required: true,\n placeholder: 'Enter the URN value...',\n evaluated: true\n }\n },\n\n validate: (formData: FormData): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n if (!formData.scheme || formData.scheme.length === 0) {\n errors.scheme = 'URN type is required';\n }\n\n if (!formData.path || formData.path.trim() === '') {\n errors.path = 'URN value is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n }\n};\n"]}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { html } from 'lit-html';
|
|
2
2
|
import { ACTION_GROUPS, FlowTypes } from '../types';
|
|
3
|
-
import {
|
|
3
|
+
import { renderFlowLinks } from '../utils';
|
|
4
4
|
export const enter_flow = {
|
|
5
5
|
name: 'Enter a Flow',
|
|
6
6
|
group: ACTION_GROUPS.trigger,
|
|
7
7
|
hideFromActions: true,
|
|
8
8
|
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
|
|
9
9
|
render: (_node, action) => {
|
|
10
|
-
return html `${
|
|
10
|
+
return html `${renderFlowLinks([action.flow], 'flow')}`;
|
|
11
11
|
},
|
|
12
12
|
toFormData: (action) => {
|
|
13
13
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enter_flow.js","sourceRoot":"","sources":["../../../../src/flow/actions/enter_flow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,aAAa,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAElE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"enter_flow.js","sourceRoot":"","sources":["../../../../src/flow/actions/enter_flow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,aAAa,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAElE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,CAAC,MAAM,UAAU,GAAiB;IACtC,IAAI,EAAE,cAAc;IACpB,KAAK,EAAE,aAAa,CAAC,OAAO;IAC5B,eAAe,EAAE,IAAI;IACrB,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC;IACrE,MAAM,EAAE,CAAC,KAAW,EAAE,MAAiB,EAAE,EAAE;QACzC,OAAO,IAAI,CAAA,GAAG,eAAe,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC;IACzD,CAAC;IACD,UAAU,EAAE,CAAC,MAAiB,EAAE,EAAE;QAChC,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE;SACvC,CAAC;IACJ,CAAC;IACD,IAAI,EAAE;QACJ,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,kBAAkB;YAC/B,QAAQ,EAAE,iDAAiD;YAC3D,QAAQ,EAAE,oBAAoB;YAC9B,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,MAAM;SAChB;KACF;IACD,MAAM,EAAE,CAAC,MAAM,CAAC;IAChB,YAAY,EAAE,CAAC,QAAa,EAAa,EAAE;QACzC,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClC,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,IAAI,EAAE,YAAY;YAClB,QAAQ,EAAE,IAAI;YACd,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,KAAK;gBACrC,IAAI,EAAE,QAAQ,CAAC,IAAI;aACpB;SACF,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS, FlowTypes } from '../types';\nimport { Node, EnterFlow } from '../../store/flow-definition';\nimport { renderFlowLinks } from '../utils';\n\nexport const enter_flow: ActionConfig = {\n name: 'Enter a Flow',\n group: ACTION_GROUPS.trigger,\n hideFromActions: true,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: EnterFlow) => {\n return html`${renderFlowLinks([action.flow], 'flow')}`;\n },\n toFormData: (action: EnterFlow) => {\n return {\n uuid: action.uuid,\n flow: action.flow ? [action.flow] : []\n };\n },\n form: {\n flow: {\n type: 'select',\n required: true,\n placeholder: 'Select a flow...',\n helpText: 'The contact will enter this flow and not return',\n endpoint: '/api/v2/flows.json',\n valueKey: 'uuid',\n nameKey: 'name'\n }\n },\n layout: ['flow'],\n fromFormData: (formData: any): EnterFlow => {\n const selected = formData.flow[0];\n return {\n uuid: formData.uuid,\n type: 'enter_flow',\n terminal: true,\n flow: {\n uuid: selected.uuid || selected.value,\n name: selected.name\n }\n };\n }\n};\n"]}
|
|
@@ -2,6 +2,7 @@ import { html } from 'lit-html';
|
|
|
2
2
|
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
|
|
3
3
|
import { ACTION_GROUPS, FlowTypes } from '../types';
|
|
4
4
|
import { renderAudioPlayer } from './audio-player';
|
|
5
|
+
import { renderClamped } from '../utils';
|
|
5
6
|
export const say_msg = {
|
|
6
7
|
name: 'Say Message',
|
|
7
8
|
group: ACTION_GROUPS.send,
|
|
@@ -9,7 +10,7 @@ export const say_msg = {
|
|
|
9
10
|
render: (_node, action) => {
|
|
10
11
|
const text = (action.text || '').replace(/\n/g, '<br>');
|
|
11
12
|
return html `
|
|
12
|
-
${unsafeHTML(text)}
|
|
13
|
+
${renderClamped(html `${unsafeHTML(text)}`, action.text || '')}
|
|
13
14
|
${action.audio_url
|
|
14
15
|
? html `<div style="margin-top: 0.5em;">
|
|
15
16
|
${renderAudioPlayer(action.audio_url)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"say_msg.js","sourceRoot":"","sources":["../../../../src/flow/actions/say_msg.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAChE,OAAO,EAAgB,aAAa,EAAY,SAAS,EAAE,MAAM,UAAU,CAAC;AAE5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"say_msg.js","sourceRoot":"","sources":["../../../../src/flow/actions/say_msg.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport { unsafeHTML } from 'lit-html/directives/unsafe-html.js';\nimport { ActionConfig, ACTION_GROUPS, FormData, FlowTypes } from '../types';\nimport { Node, SayMsg } from '../../store/flow-definition';\nimport { renderAudioPlayer } from './audio-player';\nimport { renderClamped } from '../utils';\n\nexport const say_msg: ActionConfig = {\n name: 'Say Message',\n group: ACTION_GROUPS.send,\n flowTypes: [FlowTypes.VOICE],\n render: (_node: Node, action: SayMsg) => {\n const text = (action.text || '').replace(/\\n/g, '<br>');\n return html`\n ${renderClamped(html`${unsafeHTML(text)}`, action.text || '')}\n ${action.audio_url\n ? html`<div style=\"margin-top: 0.5em;\">\n ${renderAudioPlayer(action.audio_url)}\n </div>`\n : null}\n `;\n },\n form: {\n text: {\n type: 'textarea',\n label: 'Message',\n required: true,\n evaluated: true,\n placeholder: 'Enter message to speak...',\n minHeight: 80\n },\n audio_url: {\n type: 'media',\n label: 'Recording',\n required: false,\n accept: 'audio/*',\n optionalLink: 'Add a recording'\n }\n },\n layout: ['text', 'audio_url'],\n toFormData: (action: SayMsg) => {\n return {\n uuid: action.uuid,\n text: action.text || '',\n audio_url: action.audio_url || ''\n };\n },\n fromFormData: (data: FormData) => {\n const result: any = {\n uuid: data.uuid,\n type: 'say_msg',\n text: data.text || ''\n };\n if (data.audio_url && data.audio_url.trim() !== '') {\n result.audio_url = data.audio_url.trim();\n }\n return result as SayMsg;\n },\n sanitize: (formData: FormData): void => {\n if (formData.text && typeof formData.text === 'string') {\n formData.text = formData.text.trim();\n }\n },\n localizable: ['text', 'audio_url'],\n toLocalizationFormData: (\n action: SayMsg,\n localization: Record<string, any>\n ) => {\n const formData: FormData = {\n uuid: action.uuid\n };\n\n if (localization.text && Array.isArray(localization.text)) {\n formData.text = localization.text[0] || '';\n } else {\n formData.text = '';\n }\n\n if (localization.audio_url && Array.isArray(localization.audio_url)) {\n formData.audio_url = localization.audio_url[0] || '';\n } else {\n formData.audio_url = '';\n }\n\n return formData;\n },\n fromLocalizationFormData: (formData: FormData, action: SayMsg) => {\n const localization: Record<string, any> = {};\n\n if (formData.text && formData.text.trim() !== '') {\n if (formData.text !== action.text) {\n localization.text = [formData.text];\n }\n }\n\n if (formData.audio_url && formData.audio_url.trim() !== '') {\n if (formData.audio_url !== action.audio_url) {\n localization.audio_url = [formData.audio_url];\n }\n }\n\n return localization;\n }\n};\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { html } from 'lit-html';
|
|
2
2
|
import { ACTION_GROUPS, FlowTypes } from '../types';
|
|
3
|
-
import { renderStringList } from '../utils';
|
|
3
|
+
import { renderStringList, renderClamped } from '../utils';
|
|
4
4
|
import { Icon } from '../../Icons';
|
|
5
5
|
export const send_broadcast = {
|
|
6
6
|
name: 'Send Broadcast',
|
|
@@ -14,11 +14,7 @@ export const send_broadcast = {
|
|
|
14
14
|
return html `<div>
|
|
15
15
|
<div>${renderStringList(recipients, Icon.contacts)}</div>
|
|
16
16
|
<div style="margin-top: 0.5em">
|
|
17
|
-
|
|
18
|
-
style="word-wrap: break-word; overflow-wrap: break-word; hyphens: auto;"
|
|
19
|
-
>
|
|
20
|
-
${action.text}
|
|
21
|
-
</div>
|
|
17
|
+
${renderClamped(action.text, action.text)}
|
|
22
18
|
</div>
|
|
23
19
|
</div>`;
|
|
24
20
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"send_broadcast.js","sourceRoot":"","sources":["../../../../src/flow/actions/send_broadcast.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,aAAa,EAAY,SAAS,EAAE,MAAM,UAAU,CAAC;AAE5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"send_broadcast.js","sourceRoot":"","sources":["../../../../src/flow/actions/send_broadcast.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS, FormData, FlowTypes } from '../types';\nimport { Node, SendBroadcast } from '../../store/flow-definition';\nimport { renderStringList, renderClamped } from '../utils';\nimport { Icon } from '../../Icons';\n\nexport const send_broadcast: ActionConfig = {\n name: 'Send Broadcast',\n group: ACTION_GROUPS.broadcast,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: SendBroadcast) => {\n const recipients = [\n ...(action.contacts || []).map((c) => c.name),\n ...(action.groups || []).map((g) => g.name)\n ];\n\n return html`<div>\n <div>${renderStringList(recipients, Icon.contacts)}</div>\n <div style=\"margin-top: 0.5em\">\n ${renderClamped(action.text, action.text)}\n </div>\n </div>`;\n },\n\n form: {\n recipients: {\n type: 'select',\n label: 'Recipients',\n helpText: 'Select the contacts or groups to receive the broadcast',\n options: [],\n multi: true,\n searchable: true,\n endpoint: '/api/v2/contacts.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Search for contacts or groups...',\n required: true\n },\n text: {\n type: 'message-editor',\n label: 'Message',\n helpText:\n 'Enter the message to send with optional attachments. You can use expressions like @contact.name',\n required: true,\n evaluated: true,\n placeholder: 'Type your message here...',\n maxAttachments: 10,\n accept: '',\n endpoint: '/api/v2/media.json',\n counter: 'temba-charcount',\n gsm: true,\n autogrow: true\n }\n },\n\n layout: ['recipients', 'text'],\n\n toFormData: (action: SendBroadcast) => {\n return {\n uuid: action.uuid,\n recipients: [...(action.contacts || []), ...(action.groups || [])],\n text: action.text || '',\n attachments: action.attachments || []\n };\n },\n\n fromFormData: (formData: FormData): SendBroadcast => {\n const recipients = formData.recipients || [];\n const contacts = recipients\n .filter((r: any) => !r.group)\n .map((c: any) => ({ uuid: c.uuid, name: c.name }));\n const groups = recipients\n .filter((r: any) => r.group)\n .map((g: any) => ({ uuid: g.uuid, name: g.name }));\n\n const result: SendBroadcast = {\n uuid: formData.uuid,\n type: 'send_broadcast',\n text: formData.text || '',\n contacts,\n groups,\n attachments: formData.attachments || []\n };\n\n // Remove empty attachments array to match original format\n if (result.attachments.length === 0) {\n delete result.attachments;\n }\n\n return result;\n },\n\n sanitize: (formData: FormData): void => {\n if (formData.text && typeof formData.text === 'string') {\n formData.text = formData.text.trim();\n }\n }\n};\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { html } from 'lit-html';
|
|
2
2
|
import { ACTION_GROUPS, FlowTypes } from '../types';
|
|
3
|
-
import { renderStringList } from '../utils';
|
|
3
|
+
import { renderStringList, renderClamped } from '../utils';
|
|
4
4
|
import { Icon } from '../../Icons';
|
|
5
5
|
export const send_email = {
|
|
6
6
|
name: 'Send Email',
|
|
@@ -10,11 +10,7 @@ export const send_email = {
|
|
|
10
10
|
return html `<div>
|
|
11
11
|
<div>${renderStringList(action.addresses, Icon.email)}</div>
|
|
12
12
|
<div style="margin-top: 0.5em">
|
|
13
|
-
|
|
14
|
-
style="word-wrap: break-word; overflow-wrap: break-word; hyphens: auto;"
|
|
15
|
-
>
|
|
16
|
-
${action.subject}
|
|
17
|
-
</div>
|
|
13
|
+
${renderClamped(action.subject, action.subject)}
|
|
18
14
|
</div>
|
|
19
15
|
</div>`;
|
|
20
16
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"send_email.js","sourceRoot":"","sources":["../../../../src/flow/actions/send_email.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAEL,aAAa,EAGb,SAAS,EACV,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"send_email.js","sourceRoot":"","sources":["../../../../src/flow/actions/send_email.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAEL,aAAa,EAGb,SAAS,EACV,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEnC,MAAM,CAAC,MAAM,UAAU,GAAiB;IACtC,IAAI,EAAE,YAAY;IAClB,KAAK,EAAE,aAAa,CAAC,SAAS;IAC9B,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC;IACrE,MAAM,EAAE,CAAC,KAAW,EAAE,MAAiB,EAAE,EAAE;QACzC,OAAO,IAAI,CAAA;aACF,gBAAgB,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC;;UAEjD,aAAa,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC;;WAE5C,CAAC;IACV,CAAC;IACD,IAAI,EAAE;QACJ,SAAS,EAAE;YACT,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,YAAY;YACnB,KAAK,EAAE,IAAI;YACX,UAAU,EAAE,IAAI;YAChB,WAAW,EAAE,wBAAwB;YACrC,MAAM,EAAE,IAAI;SACb;QACD,OAAO,EAAE;YACP,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,SAAS;YAChB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,qBAAqB;YAClC,SAAS,EAAE,GAAG;SACf;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,UAAU;YAChB,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,IAAI;YACf,SAAS,EAAE,GAAG;SACf;KACF;IACD,YAAY,EAAE,CAAC,QAAkB,EAAa,EAAE;QAC9C,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,IAAI,EAAE,YAAY;YAClB,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,GAAG,CAC/B,CAAC,IAAqC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CACtD;YACD,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,IAAI,EAAE,QAAQ,CAAC,IAAI;SACpB,CAAC;IACJ,CAAC;IACD,QAAQ,EAAE,CAAC,QAAkB,EAAoB,EAAE;QACjD,MAAM,MAAM,GAA8B,EAAE,CAAC;QAE7C,IAAI,CAAC,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3D,MAAM,CAAC,SAAS,GAAG,kDAAkD,CAAC;QACxE,CAAC;QAED,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;YACvC,MAAM;SACP,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport {\n ActionConfig,\n ACTION_GROUPS,\n FormData,\n ValidationResult,\n FlowTypes\n} from '../types';\nimport { Node, SendEmail } from '../../store/flow-definition';\nimport { renderStringList, renderClamped } from '../utils';\nimport { Icon } from '../../Icons';\n\nexport const send_email: ActionConfig = {\n name: 'Send Email',\n group: ACTION_GROUPS.broadcast,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: SendEmail) => {\n return html`<div>\n <div>${renderStringList(action.addresses, Icon.email)}</div>\n <div style=\"margin-top: 0.5em\">\n ${renderClamped(action.subject, action.subject)}\n </div>\n </div>`;\n },\n form: {\n addresses: {\n type: 'select',\n label: 'Recipients',\n multi: true,\n searchable: true,\n placeholder: 'Search for contacts...',\n emails: true\n },\n subject: {\n type: 'text',\n label: 'Subject',\n required: true,\n placeholder: 'Enter email subject',\n maxLength: 255\n },\n body: {\n type: 'textarea',\n required: true,\n evaluated: true,\n minHeight: 175\n }\n },\n fromFormData: (formData: FormData): SendEmail => {\n return {\n uuid: formData.uuid,\n type: 'send_email',\n addresses: formData.addresses.map(\n (addr: { name: string; value: string }) => addr.value\n ),\n subject: formData.subject,\n body: formData.body\n };\n },\n validate: (formData: FormData): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n if (!formData.addresses || formData.addresses.length === 0) {\n errors.addresses = 'At least one recipient email address is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n }\n};\n"]}
|
|
@@ -2,28 +2,33 @@ import { html } from 'lit-html';
|
|
|
2
2
|
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
|
|
3
3
|
import { ACTION_GROUPS, FlowTypes } from '../types';
|
|
4
4
|
import { titleCase } from '../../utils';
|
|
5
|
+
import { renderClamped } from '../utils';
|
|
5
6
|
export const send_msg = {
|
|
6
7
|
name: 'Send Message',
|
|
7
8
|
group: ACTION_GROUPS.send,
|
|
8
9
|
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
|
|
10
|
+
hideFromActions: true,
|
|
9
11
|
render: (_node, action) => {
|
|
10
12
|
var _a;
|
|
11
13
|
const text = action.text.replace(/\n/g, '<br>');
|
|
12
14
|
return html `
|
|
13
|
-
${
|
|
15
|
+
${action.template
|
|
16
|
+
? html `<div
|
|
17
|
+
style="border: 1px solid #7dc8bc;padding: 0.5em;margin-bottom: 0.5em;border-radius: 4px; display:flex;align-items: flex-start;background: #f0faf7;color: #128C7E;font-size: 0.85em;"
|
|
18
|
+
>
|
|
19
|
+
<temba-icon
|
|
20
|
+
name="channel_wac"
|
|
21
|
+
style="--icon-size: 14px;"
|
|
22
|
+
></temba-icon>
|
|
23
|
+
<div style="margin-left:0.4em">${action.template.name}</div>
|
|
24
|
+
</div>`
|
|
25
|
+
: null}
|
|
26
|
+
${renderClamped(html `${unsafeHTML(text)}`, action.text)}
|
|
14
27
|
${((_a = (action.quick_replies || [])) === null || _a === void 0 ? void 0 : _a.length) > 0
|
|
15
28
|
? html `<div class="quick-replies">
|
|
16
29
|
${(action.quick_replies || []).map((reply) => {
|
|
17
30
|
return html `<div class="quick-reply">${reply}</div>`;
|
|
18
31
|
})}
|
|
19
|
-
${action.template
|
|
20
|
-
? html `<div
|
|
21
|
-
style="border: 1px solid var(--color-widget-border);padding: 0.5em;margin-top: 1em;border-radius: var(--curvature); display:flex;background: rgba(0,0,0,.03);"
|
|
22
|
-
>
|
|
23
|
-
<temba-icon name="channel_wac"></temba-icon>
|
|
24
|
-
<div style="margin-left:0.5em">${action.template.name}</div>
|
|
25
|
-
</div>`
|
|
26
|
-
: null}
|
|
27
32
|
</div>`
|
|
28
33
|
: null}
|
|
29
34
|
`;
|
|
@@ -53,6 +58,10 @@ export const send_msg = {
|
|
|
53
58
|
maxItems: 10,
|
|
54
59
|
evaluated: true
|
|
55
60
|
},
|
|
61
|
+
template: {
|
|
62
|
+
type: 'template-editor',
|
|
63
|
+
endpoint: '/api/internal/templates.json'
|
|
64
|
+
},
|
|
56
65
|
runtime_attachments: {
|
|
57
66
|
type: 'array',
|
|
58
67
|
itemLabel: 'Attachment',
|
|
@@ -86,31 +95,35 @@ export const send_msg = {
|
|
|
86
95
|
layout: [
|
|
87
96
|
'text',
|
|
88
97
|
{
|
|
89
|
-
type: '
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
98
|
+
type: 'accordion',
|
|
99
|
+
sections: [
|
|
100
|
+
{
|
|
101
|
+
label: 'Quick Replies',
|
|
102
|
+
collapsed: true,
|
|
103
|
+
getValueCount: (formData) => {
|
|
104
|
+
var _a;
|
|
105
|
+
return ((_a = formData.quick_replies) === null || _a === void 0 ? void 0 : _a.length) || 0;
|
|
106
|
+
},
|
|
107
|
+
items: ['quick_replies']
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
label: 'WhatsApp Template',
|
|
111
|
+
collapsed: true,
|
|
112
|
+
getValueCount: (formData) => {
|
|
113
|
+
return !!formData.template;
|
|
114
|
+
},
|
|
115
|
+
items: ['template']
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
label: 'Runtime Attachments',
|
|
119
|
+
collapsed: true,
|
|
120
|
+
getValueCount: (formData) => {
|
|
121
|
+
var _a;
|
|
122
|
+
return (((_a = formData.runtime_attachments) === null || _a === void 0 ? void 0 : _a.filter((item) => item && item.expression && item.expression.trim() !== '').length) || 0);
|
|
123
|
+
},
|
|
124
|
+
items: ['runtime_attachments']
|
|
125
|
+
}
|
|
126
|
+
]
|
|
114
127
|
}
|
|
115
128
|
],
|
|
116
129
|
toFormData: (action) => {
|
|
@@ -143,7 +156,9 @@ export const send_msg = {
|
|
|
143
156
|
quick_replies: (action.quick_replies || []).map((reply) => ({
|
|
144
157
|
name: reply,
|
|
145
158
|
value: reply
|
|
146
|
-
}))
|
|
159
|
+
})),
|
|
160
|
+
template: action.template || null,
|
|
161
|
+
template_variables: action.template_variables || []
|
|
147
162
|
};
|
|
148
163
|
},
|
|
149
164
|
fromFormData: (data) => {
|
|
@@ -164,6 +179,11 @@ export const send_msg = {
|
|
|
164
179
|
if (result.quick_replies.length === 0) {
|
|
165
180
|
delete result.quick_replies;
|
|
166
181
|
}
|
|
182
|
+
// Add template and template_variables if a template is selected
|
|
183
|
+
if (data.template) {
|
|
184
|
+
result.template = data.template;
|
|
185
|
+
result.template_variables = data.template_variables || [];
|
|
186
|
+
}
|
|
167
187
|
return result;
|
|
168
188
|
},
|
|
169
189
|
sanitize: (formData) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"send_msg.js","sourceRoot":"","sources":["../../../../src/flow/actions/send_msg.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport { unsafeHTML } from 'lit-html/directives/unsafe-html.js';\nimport {\n ActionConfig,\n ACTION_GROUPS,\n FormData,\n ValidationResult,\n FlowTypes\n} from '../types';\nimport { Node, SendMsg } from '../../store/flow-definition';\nimport { titleCase } from '../../utils';\n\nexport const send_msg: ActionConfig = {\n name: 'Send Message',\n group: ACTION_GROUPS.send,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: SendMsg) => {\n const text = action.text.replace(/\\n/g, '<br>');\n return html`\n ${unsafeHTML(text)}\n ${(action.quick_replies || [])?.length > 0\n ? html`<div class=\"quick-replies\">\n ${(action.quick_replies || []).map((reply) => {\n return html`<div class=\"quick-reply\">${reply}</div>`;\n })}\n ${action.template\n ? html`<div\n style=\"border: 1px solid var(--color-widget-border);padding: 0.5em;margin-top: 1em;border-radius: var(--curvature); display:flex;background: rgba(0,0,0,.03);\"\n >\n <temba-icon name=\"channel_wac\"></temba-icon>\n <div style=\"margin-left:0.5em\">${action.template.name}</div>\n </div>`\n : null}\n </div>`\n : null}\n `;\n },\n form: {\n text: {\n type: 'message-editor',\n label: 'Message',\n helpText:\n 'Enter the message to send with optional attachments. You can use expressions like @contact.name',\n required: true,\n evaluated: true,\n placeholder: 'Type your message here...',\n maxAttachments: 10,\n accept: '',\n endpoint: '/api/v2/media.json',\n counter: 'temba-charcount',\n gsm: true,\n autogrow: true\n },\n quick_replies: {\n type: 'select',\n options: [],\n multi: true,\n tags: true,\n searchable: true,\n placeholder: 'Add quick replies...',\n maxItems: 10,\n evaluated: true\n },\n runtime_attachments: {\n type: 'array',\n itemLabel: 'Attachment',\n sortable: true,\n maxItems: 10,\n isEmptyItem: (item: any) => {\n return !item.expression || item.expression.trim() === '';\n },\n itemConfig: {\n type: {\n type: 'select',\n width: '140px',\n options: [\n { value: 'image', name: 'Image' },\n { value: 'audio', name: 'Audio' },\n { value: 'video', name: 'Video' },\n { value: 'document', name: 'Document' }\n ],\n required: true,\n searchable: false\n },\n expression: {\n type: 'text',\n placeholder: 'Expression (e.g. @contact.photo)',\n required: true,\n evaluated: true\n }\n }\n }\n },\n layout: [\n 'text',\n {\n type: 'group',\n label: 'Quick Replies',\n items: ['quick_replies'],\n collapsible: true,\n collapsed: (formData: FormData) => {\n // Collapse only if there are no quick replies\n return !formData.quick_replies || formData.quick_replies.length === 0;\n },\n getGroupValueCount: (formData: FormData) => {\n return formData.quick_replies?.length || 0;\n }\n },\n {\n type: 'group',\n label: 'Runtime Attachments',\n items: ['runtime_attachments'],\n collapsible: true,\n collapsed: true,\n helpText: 'Add dynamic attachments that are evaluated at runtime',\n contentPadding: '12px',\n getGroupValueCount: (formData: FormData) => {\n return (\n formData.runtime_attachments?.filter(\n (item: any) =>\n item && item.expression && item.expression.trim() !== ''\n ).length || 0\n );\n }\n }\n ],\n toFormData: (action: SendMsg) => {\n // Extract runtime attachments from the text field attachments\n const runtimeAttachments: {\n type: { name: string; value: string };\n expression: string;\n }[] = [];\n const staticAttachments: string[] = [];\n\n if (action.attachments && Array.isArray(action.attachments)) {\n action.attachments.forEach((attachment) => {\n if (typeof attachment === 'string' && attachment.includes(':')) {\n const colonIndex = attachment.indexOf(':');\n const contentType = attachment.substring(0, colonIndex);\n const value = attachment.substring(colonIndex + 1);\n\n if (!contentType.includes('/')) {\n runtimeAttachments.push({\n type: { name: titleCase(contentType), value: contentType },\n expression: value\n });\n } else {\n staticAttachments.push(attachment);\n }\n }\n });\n }\n\n return {\n uuid: action.uuid,\n text: action.text || '',\n attachments: staticAttachments,\n runtime_attachments: runtimeAttachments,\n quick_replies: (action.quick_replies || []).map((reply) => ({\n name: reply,\n value: reply\n }))\n };\n },\n fromFormData: (data: FormData) => {\n const result = {\n uuid: data.uuid,\n type: 'send_msg',\n text: data.text || '',\n attachments: [],\n quick_replies: (data.quick_replies || []).map((reply: any) =>\n typeof reply === 'string' ? reply : reply.value || reply.name || reply\n )\n };\n\n // Combine static attachments from text field with runtime attachments\n const staticAttachments = data.attachments || [];\n const runtimeAttachments = (data.runtime_attachments || [])\n .filter(\n (item: {\n type: [{ name: string; value: string }];\n expression: string;\n }) => item && item.type && item.expression\n ) // Filter out invalid items\n .map(\n (item: {\n type: [{ name: string; value: string }];\n expression: string;\n }) => `${item.type[0].value}:${item.expression}`\n );\n\n result.attachments = [...staticAttachments, ...runtimeAttachments];\n\n // Remove quick_replies if empty to match original format\n if (result.quick_replies.length === 0) {\n delete (result as any).quick_replies;\n }\n\n return result as SendMsg;\n },\n sanitize: (formData: FormData): void => {\n if (formData.text && typeof formData.text === 'string') {\n formData.text = formData.text.trim();\n }\n },\n validate: (formData: FormData): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n // Check total attachment count (static + runtime should not exceed 10)\n const staticAttachments = formData.attachments || [];\n const runtimeAttachments = (formData.runtime_attachments || []).filter(\n (item: any) => item && item.expression && item.expression.trim() !== ''\n );\n\n const totalAttachments =\n staticAttachments.length + runtimeAttachments.length;\n if (totalAttachments > 10) {\n if (runtimeAttachments.length > 0) {\n errors.runtime_attachments =\n 'Each message can only have up to 10 attachments';\n }\n if (staticAttachments.length > 0) {\n errors.text = 'Each message can only have up to 10 total attachments';\n }\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n localizable: ['text', 'quick_replies', 'attachments'],\n toLocalizationFormData: (\n action: SendMsg,\n localization: Record<string, any>\n ) => {\n // Convert localized values to form data format\n // Localized values are stored as arrays even for single values\n const formData: FormData = {\n uuid: action.uuid\n };\n\n // Handle text (single value, but stored as array in localization)\n if (localization.text && Array.isArray(localization.text)) {\n formData.text = localization.text[0] || '';\n } else {\n // Fall back to empty string if no localization\n formData.text = '';\n }\n\n // Handle attachments (already an array)\n if (localization.attachments && Array.isArray(localization.attachments)) {\n formData.attachments = localization.attachments;\n }\n\n // Handle quick_replies (already an array)\n if (\n localization.quick_replies &&\n Array.isArray(localization.quick_replies)\n ) {\n formData.quick_replies = localization.quick_replies.map((reply) => ({\n name: reply,\n value: reply\n }));\n }\n\n // Extract runtime attachments from localized attachments\n const runtimeAttachments: {\n type: { name: string; value: string };\n expression: string;\n }[] = [];\n const staticAttachments: string[] = [];\n\n if (formData.attachments && Array.isArray(formData.attachments)) {\n formData.attachments.forEach((attachment) => {\n if (typeof attachment === 'string' && attachment.includes(':')) {\n const colonIndex = attachment.indexOf(':');\n const contentType = attachment.substring(0, colonIndex);\n const value = attachment.substring(colonIndex + 1);\n\n if (!contentType.includes('/')) {\n runtimeAttachments.push({\n type: { name: titleCase(contentType), value: contentType },\n expression: value\n });\n } else {\n staticAttachments.push(attachment);\n }\n }\n });\n }\n\n formData.attachments = staticAttachments;\n formData.runtime_attachments = runtimeAttachments;\n\n return formData;\n },\n fromLocalizationFormData: (formData: FormData, action: SendMsg) => {\n // Convert form data to localization format\n // All values must be stored as arrays\n const localization: Record<string, any> = {};\n\n // Handle text (store as single-element array)\n // Only save if not empty and different from base action\n if (formData.text && formData.text.trim() !== '') {\n if (formData.text !== action.text) {\n localization.text = [formData.text];\n }\n }\n\n // Handle quick_replies (store as array)\n const quickReplies = (formData.quick_replies || [])\n .map((reply: any) =>\n typeof reply === 'string' ? reply : reply.value || reply.name || reply\n )\n .filter((reply: string) => reply && reply.trim() !== '');\n\n // Only save if there are quick replies and different from base action\n if (quickReplies.length > 0) {\n if (\n JSON.stringify(quickReplies) !==\n JSON.stringify(action.quick_replies || [])\n ) {\n localization.quick_replies = quickReplies;\n }\n }\n\n // Handle attachments (combine static and runtime attachments)\n const staticAttachments = (formData.attachments || []).filter(\n (att: string) => att && att.trim() !== ''\n );\n const runtimeAttachments = (formData.runtime_attachments || [])\n .filter(\n (item: {\n type: [{ name: string; value: string }];\n expression: string;\n }) =>\n item && item.type && item.expression && item.expression.trim() !== ''\n )\n .map(\n (item: {\n type: [{ name: string; value: string }];\n expression: string;\n }) => `${item.type[0].value}:${item.expression}`\n );\n\n const allAttachments = [...staticAttachments, ...runtimeAttachments];\n\n // Only save if there are attachments and different from base action\n if (allAttachments.length > 0) {\n if (\n JSON.stringify(allAttachments) !==\n JSON.stringify(action.attachments || [])\n ) {\n localization.attachments = allAttachments;\n }\n }\n\n return localization;\n }\n};\n"]}
|
|
1
|
+
{"version":3,"file":"send_msg.js","sourceRoot":"","sources":["../../../../src/flow/actions/send_msg.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport { unsafeHTML } from 'lit-html/directives/unsafe-html.js';\nimport {\n ActionConfig,\n ACTION_GROUPS,\n FormData,\n ValidationResult,\n FlowTypes\n} from '../types';\nimport { Node, SendMsg } from '../../store/flow-definition';\nimport { titleCase } from '../../utils';\nimport { renderClamped } from '../utils';\n\nexport const send_msg: ActionConfig = {\n name: 'Send Message',\n group: ACTION_GROUPS.send,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n hideFromActions: true,\n render: (_node: Node, action: SendMsg) => {\n const text = action.text.replace(/\\n/g, '<br>');\n return html`\n ${action.template\n ? html`<div\n style=\"border: 1px solid #7dc8bc;padding: 0.5em;margin-bottom: 0.5em;border-radius: 4px; display:flex;align-items: flex-start;background: #f0faf7;color: #128C7E;font-size: 0.85em;\"\n >\n <temba-icon\n name=\"channel_wac\"\n style=\"--icon-size: 14px;\"\n ></temba-icon>\n <div style=\"margin-left:0.4em\">${action.template.name}</div>\n </div>`\n : null}\n ${renderClamped(html`${unsafeHTML(text)}`, action.text)}\n ${(action.quick_replies || [])?.length > 0\n ? html`<div class=\"quick-replies\">\n ${(action.quick_replies || []).map((reply) => {\n return html`<div class=\"quick-reply\">${reply}</div>`;\n })}\n </div>`\n : null}\n `;\n },\n form: {\n text: {\n type: 'message-editor',\n label: 'Message',\n helpText:\n 'Enter the message to send with optional attachments. You can use expressions like @contact.name',\n required: true,\n evaluated: true,\n placeholder: 'Type your message here...',\n maxAttachments: 10,\n accept: '',\n endpoint: '/api/v2/media.json',\n counter: 'temba-charcount',\n gsm: true,\n autogrow: true\n },\n quick_replies: {\n type: 'select',\n options: [],\n multi: true,\n tags: true,\n searchable: true,\n placeholder: 'Add quick replies...',\n maxItems: 10,\n evaluated: true\n },\n template: {\n type: 'template-editor',\n endpoint: '/api/internal/templates.json'\n },\n runtime_attachments: {\n type: 'array',\n itemLabel: 'Attachment',\n sortable: true,\n maxItems: 10,\n isEmptyItem: (item: any) => {\n return !item.expression || item.expression.trim() === '';\n },\n itemConfig: {\n type: {\n type: 'select',\n width: '140px',\n options: [\n { value: 'image', name: 'Image' },\n { value: 'audio', name: 'Audio' },\n { value: 'video', name: 'Video' },\n { value: 'document', name: 'Document' }\n ],\n required: true,\n searchable: false\n },\n expression: {\n type: 'text',\n placeholder: 'Expression (e.g. @contact.photo)',\n required: true,\n evaluated: true\n }\n }\n }\n },\n layout: [\n 'text',\n {\n type: 'accordion',\n sections: [\n {\n label: 'Quick Replies',\n collapsed: true,\n getValueCount: (formData: FormData) => {\n return formData.quick_replies?.length || 0;\n },\n items: ['quick_replies']\n },\n {\n label: 'WhatsApp Template',\n collapsed: true,\n getValueCount: (formData: FormData) => {\n return !!formData.template;\n },\n items: ['template']\n },\n {\n label: 'Runtime Attachments',\n collapsed: true,\n getValueCount: (formData: FormData) => {\n return (\n formData.runtime_attachments?.filter(\n (item: any) =>\n item && item.expression && item.expression.trim() !== ''\n ).length || 0\n );\n },\n items: ['runtime_attachments']\n }\n ]\n }\n ],\n toFormData: (action: SendMsg) => {\n // Extract runtime attachments from the text field attachments\n const runtimeAttachments: {\n type: { name: string; value: string };\n expression: string;\n }[] = [];\n const staticAttachments: string[] = [];\n\n if (action.attachments && Array.isArray(action.attachments)) {\n action.attachments.forEach((attachment) => {\n if (typeof attachment === 'string' && attachment.includes(':')) {\n const colonIndex = attachment.indexOf(':');\n const contentType = attachment.substring(0, colonIndex);\n const value = attachment.substring(colonIndex + 1);\n\n if (!contentType.includes('/')) {\n runtimeAttachments.push({\n type: { name: titleCase(contentType), value: contentType },\n expression: value\n });\n } else {\n staticAttachments.push(attachment);\n }\n }\n });\n }\n\n return {\n uuid: action.uuid,\n text: action.text || '',\n attachments: staticAttachments,\n runtime_attachments: runtimeAttachments,\n quick_replies: (action.quick_replies || []).map((reply) => ({\n name: reply,\n value: reply\n })),\n template: action.template || null,\n template_variables: action.template_variables || []\n };\n },\n fromFormData: (data: FormData) => {\n const result = {\n uuid: data.uuid,\n type: 'send_msg',\n text: data.text || '',\n attachments: [],\n quick_replies: (data.quick_replies || []).map((reply: any) =>\n typeof reply === 'string' ? reply : reply.value || reply.name || reply\n )\n };\n\n // Combine static attachments from text field with runtime attachments\n const staticAttachments = data.attachments || [];\n const runtimeAttachments = (data.runtime_attachments || [])\n .filter(\n (item: {\n type: [{ name: string; value: string }];\n expression: string;\n }) => item && item.type && item.expression\n ) // Filter out invalid items\n .map(\n (item: {\n type: [{ name: string; value: string }];\n expression: string;\n }) => `${item.type[0].value}:${item.expression}`\n );\n\n result.attachments = [...staticAttachments, ...runtimeAttachments];\n\n // Remove quick_replies if empty to match original format\n if (result.quick_replies.length === 0) {\n delete (result as any).quick_replies;\n }\n\n // Add template and template_variables if a template is selected\n if (data.template) {\n (result as any).template = data.template;\n (result as any).template_variables = data.template_variables || [];\n }\n\n return result as SendMsg;\n },\n sanitize: (formData: FormData): void => {\n if (formData.text && typeof formData.text === 'string') {\n formData.text = formData.text.trim();\n }\n },\n validate: (formData: FormData): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n // Check total attachment count (static + runtime should not exceed 10)\n const staticAttachments = formData.attachments || [];\n const runtimeAttachments = (formData.runtime_attachments || []).filter(\n (item: any) => item && item.expression && item.expression.trim() !== ''\n );\n\n const totalAttachments =\n staticAttachments.length + runtimeAttachments.length;\n if (totalAttachments > 10) {\n if (runtimeAttachments.length > 0) {\n errors.runtime_attachments =\n 'Each message can only have up to 10 attachments';\n }\n if (staticAttachments.length > 0) {\n errors.text = 'Each message can only have up to 10 total attachments';\n }\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n localizable: ['text', 'quick_replies', 'attachments'],\n toLocalizationFormData: (\n action: SendMsg,\n localization: Record<string, any>\n ) => {\n // Convert localized values to form data format\n // Localized values are stored as arrays even for single values\n const formData: FormData = {\n uuid: action.uuid\n };\n\n // Handle text (single value, but stored as array in localization)\n if (localization.text && Array.isArray(localization.text)) {\n formData.text = localization.text[0] || '';\n } else {\n // Fall back to empty string if no localization\n formData.text = '';\n }\n\n // Handle attachments (already an array)\n if (localization.attachments && Array.isArray(localization.attachments)) {\n formData.attachments = localization.attachments;\n }\n\n // Handle quick_replies (already an array)\n if (\n localization.quick_replies &&\n Array.isArray(localization.quick_replies)\n ) {\n formData.quick_replies = localization.quick_replies.map((reply) => ({\n name: reply,\n value: reply\n }));\n }\n\n // Extract runtime attachments from localized attachments\n const runtimeAttachments: {\n type: { name: string; value: string };\n expression: string;\n }[] = [];\n const staticAttachments: string[] = [];\n\n if (formData.attachments && Array.isArray(formData.attachments)) {\n formData.attachments.forEach((attachment) => {\n if (typeof attachment === 'string' && attachment.includes(':')) {\n const colonIndex = attachment.indexOf(':');\n const contentType = attachment.substring(0, colonIndex);\n const value = attachment.substring(colonIndex + 1);\n\n if (!contentType.includes('/')) {\n runtimeAttachments.push({\n type: { name: titleCase(contentType), value: contentType },\n expression: value\n });\n } else {\n staticAttachments.push(attachment);\n }\n }\n });\n }\n\n formData.attachments = staticAttachments;\n formData.runtime_attachments = runtimeAttachments;\n\n return formData;\n },\n fromLocalizationFormData: (formData: FormData, action: SendMsg) => {\n // Convert form data to localization format\n // All values must be stored as arrays\n const localization: Record<string, any> = {};\n\n // Handle text (store as single-element array)\n // Only save if not empty and different from base action\n if (formData.text && formData.text.trim() !== '') {\n if (formData.text !== action.text) {\n localization.text = [formData.text];\n }\n }\n\n // Handle quick_replies (store as array)\n const quickReplies = (formData.quick_replies || [])\n .map((reply: any) =>\n typeof reply === 'string' ? reply : reply.value || reply.name || reply\n )\n .filter((reply: string) => reply && reply.trim() !== '');\n\n // Only save if there are quick replies and different from base action\n if (quickReplies.length > 0) {\n if (\n JSON.stringify(quickReplies) !==\n JSON.stringify(action.quick_replies || [])\n ) {\n localization.quick_replies = quickReplies;\n }\n }\n\n // Handle attachments (combine static and runtime attachments)\n const staticAttachments = (formData.attachments || []).filter(\n (att: string) => att && att.trim() !== ''\n );\n const runtimeAttachments = (formData.runtime_attachments || [])\n .filter(\n (item: {\n type: [{ name: string; value: string }];\n expression: string;\n }) =>\n item && item.type && item.expression && item.expression.trim() !== ''\n )\n .map(\n (item: {\n type: [{ name: string; value: string }];\n expression: string;\n }) => `${item.type[0].value}:${item.expression}`\n );\n\n const allAttachments = [...staticAttachments, ...runtimeAttachments];\n\n // Only save if there are attachments and different from base action\n if (allAttachments.length > 0) {\n if (\n JSON.stringify(allAttachments) !==\n JSON.stringify(action.attachments || [])\n ) {\n localization.attachments = allAttachments;\n }\n }\n\n return localization;\n }\n};\n"]}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { html } from 'lit-html';
|
|
2
2
|
import { ACTION_GROUPS, FlowTypes } from '../types';
|
|
3
|
+
import { renderClamped } from '../utils';
|
|
3
4
|
export const set_contact_channel = {
|
|
4
5
|
name: 'Update Channel',
|
|
5
6
|
group: ACTION_GROUPS.contacts,
|
|
6
7
|
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
|
|
7
8
|
render: (_node, action) => {
|
|
8
|
-
return html
|
|
9
|
+
return renderClamped(html `Set to <strong>${action.channel.name}</strong>`, `Set to ${action.channel.name}`);
|
|
9
10
|
},
|
|
10
11
|
form: {
|
|
11
12
|
channel: {
|