@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
package/src/display/Chat.ts
CHANGED
|
@@ -4,7 +4,6 @@ import { RapidElement } from '../RapidElement';
|
|
|
4
4
|
import { CustomEventType } from '../interfaces';
|
|
5
5
|
import { DEFAULT_AVATAR } from '../webchat/assets';
|
|
6
6
|
import { hashCode } from '../utils';
|
|
7
|
-
import { renderMarkdown } from '../markdown';
|
|
8
7
|
|
|
9
8
|
const BATCH_TIME_WINDOW = 60 * 60 * 1000;
|
|
10
9
|
const SCROLL_FETCH_BUFFER = 0.05;
|
|
@@ -28,7 +27,7 @@ interface User {
|
|
|
28
27
|
export interface ChatEvent {
|
|
29
28
|
id?: string;
|
|
30
29
|
type: MessageType;
|
|
31
|
-
text:
|
|
30
|
+
text: TemplateResult;
|
|
32
31
|
date: Date;
|
|
33
32
|
user?: User;
|
|
34
33
|
popup?: TemplateResult;
|
|
@@ -534,7 +533,10 @@ export class Chat extends RapidElement {
|
|
|
534
533
|
// make sure our messages have ids
|
|
535
534
|
messages.forEach((m) => {
|
|
536
535
|
if (!m.id) {
|
|
537
|
-
m.id =
|
|
536
|
+
m.id =
|
|
537
|
+
hashCode((m.text.strings || []).join('')) +
|
|
538
|
+
'_' +
|
|
539
|
+
m.date.toISOString();
|
|
538
540
|
}
|
|
539
541
|
});
|
|
540
542
|
|
|
@@ -764,7 +766,7 @@ export class Chat extends RapidElement {
|
|
|
764
766
|
event.type === MessageType.Collapse ||
|
|
765
767
|
event.type === MessageType.Inline
|
|
766
768
|
) {
|
|
767
|
-
return html`<div class="event">${
|
|
769
|
+
return html`<div class="event">${event.text}</div>`;
|
|
768
770
|
}
|
|
769
771
|
|
|
770
772
|
const message = event as Message;
|
package/src/events.ts
CHANGED
|
@@ -10,7 +10,8 @@ export interface ContactEvent {
|
|
|
10
10
|
uuid?: string;
|
|
11
11
|
type: string;
|
|
12
12
|
created_on: string;
|
|
13
|
-
created_by?: User;
|
|
13
|
+
created_by?: User; // deprecated
|
|
14
|
+
_user?: ObjectReference;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
export interface ChannelEvent extends ContactEvent {
|
|
@@ -75,16 +76,15 @@ export interface URNsChangedEvent extends ContactEvent {
|
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
export interface TicketEvent extends ContactEvent {
|
|
78
|
-
note?: string;
|
|
79
|
-
assignee?: User;
|
|
80
79
|
ticket: {
|
|
80
|
+
// ticket_opened
|
|
81
81
|
uuid: string;
|
|
82
82
|
topic?: ObjectReference;
|
|
83
|
-
closed_on?: string;
|
|
84
|
-
opened_on?: string;
|
|
85
83
|
};
|
|
84
|
+
ticket_uuid?: string; // all other event types
|
|
85
|
+
assignee?: User;
|
|
86
|
+
note?: string;
|
|
86
87
|
topic?: ObjectReference;
|
|
87
|
-
created_by?: User;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
export interface NameChangedEvent extends ContactEvent {
|
package/src/flow/CanvasNode.ts
CHANGED
|
@@ -78,60 +78,43 @@ export class CanvasNode extends RapidElement {
|
|
|
78
78
|
|
|
79
79
|
.action {
|
|
80
80
|
position: relative;
|
|
81
|
-
font-size: 13px;
|
|
82
81
|
}
|
|
83
82
|
|
|
84
|
-
.action .remove-button {
|
|
85
|
-
position: absolute;
|
|
86
|
-
top: 5px;
|
|
87
|
-
right: 5px;
|
|
88
|
-
width: 16px;
|
|
89
|
-
height: 16px;
|
|
90
|
-
border-radius: 50%;
|
|
91
|
-
background: var(--color-error, #dc3545);
|
|
92
|
-
color: white;
|
|
93
|
-
border: none;
|
|
94
|
-
cursor: pointer;
|
|
95
|
-
display: none;
|
|
96
|
-
align-items: center;
|
|
97
|
-
justify-content: center;
|
|
98
|
-
font-size: 10px;
|
|
99
|
-
line-height: 1;
|
|
100
|
-
z-index: 10;
|
|
101
|
-
}
|
|
102
83
|
|
|
103
|
-
.action:hover .remove-button,
|
|
84
|
+
.action .cn-title:hover .remove-button,
|
|
104
85
|
.router:hover .remove-button {
|
|
105
|
-
|
|
86
|
+
opacity: 0.7;
|
|
106
87
|
}
|
|
107
88
|
|
|
108
|
-
.action.removing .title,
|
|
109
|
-
.router .title.removing {
|
|
89
|
+
.action.removing .cn-title,
|
|
90
|
+
.router .cn-title.removing {
|
|
110
91
|
background-color: var(--color-error, #dc3545) !important;
|
|
111
92
|
}
|
|
112
93
|
|
|
113
|
-
.action.removing .title .name,
|
|
114
|
-
.router .title.removing .name {
|
|
94
|
+
.action.removing .cn-title .name,
|
|
95
|
+
.router .cn-title.removing .name {
|
|
115
96
|
color: white;
|
|
116
97
|
}
|
|
117
98
|
|
|
118
|
-
.
|
|
119
|
-
|
|
120
|
-
top: 5px;
|
|
121
|
-
right: 5px;
|
|
122
|
-
width: 16px;
|
|
123
|
-
height: 16px;
|
|
124
|
-
border-radius: 50%;
|
|
125
|
-
background: var(--color-error, #dc3545);
|
|
99
|
+
.remove-button {
|
|
100
|
+
background: transparent;
|
|
126
101
|
color: white;
|
|
127
|
-
|
|
102
|
+
opacity: 0;
|
|
128
103
|
cursor: pointer;
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
justify-content: center;
|
|
132
|
-
font-size: 10px;
|
|
104
|
+
font-size: 1em;
|
|
105
|
+
font-weight: 600;
|
|
133
106
|
line-height: 1;
|
|
134
107
|
z-index: 10;
|
|
108
|
+
transition: all 100ms ease-in-out;
|
|
109
|
+
align-self: center;
|
|
110
|
+
padding:0.25em;
|
|
111
|
+
border: 0px solid red;
|
|
112
|
+
width: 1em;
|
|
113
|
+
pointer-events: auto; /* Ensure remove button can receive events */
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.remove-button:hover {
|
|
117
|
+
opacity: 1;
|
|
135
118
|
}
|
|
136
119
|
|
|
137
120
|
.action.sortable {
|
|
@@ -165,14 +148,24 @@ export class CanvasNode extends RapidElement {
|
|
|
165
148
|
transition: all 200ms ease-in-out;
|
|
166
149
|
cursor: move;
|
|
167
150
|
background: rgba(0, 0, 0, 0.02);
|
|
168
|
-
|
|
169
|
-
|
|
151
|
+
width: 1em;
|
|
152
|
+
padding: 0.25em;
|
|
153
|
+
border: 0px solid red;
|
|
154
|
+
pointer-events: auto; /* Ensure drag handle can receive events */
|
|
155
|
+
}
|
|
156
|
+
.title-spacer {
|
|
157
|
+
width: 2em;
|
|
158
|
+
|
|
170
159
|
}
|
|
171
160
|
|
|
172
161
|
.action:hover .drag-handle {
|
|
173
|
-
opacity: 0.
|
|
174
|
-
|
|
175
|
-
|
|
162
|
+
opacity: 0.7;
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
strong {
|
|
168
|
+
font-weight: 500;
|
|
176
169
|
}
|
|
177
170
|
|
|
178
171
|
.action .drag-handle:hover {
|
|
@@ -180,20 +173,27 @@ export class CanvasNode extends RapidElement {
|
|
|
180
173
|
|
|
181
174
|
}
|
|
182
175
|
|
|
183
|
-
.action .title,
|
|
184
|
-
.router .title {
|
|
176
|
+
.action .cn-title,
|
|
177
|
+
.router .cn-title {
|
|
185
178
|
display: flex;
|
|
186
179
|
color: #fff;
|
|
187
|
-
padding: 5px 1px;
|
|
188
180
|
text-align: center;
|
|
189
181
|
font-size: 1em;
|
|
190
|
-
font-weight:
|
|
182
|
+
font-weight: 500;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.cn-title .name {
|
|
186
|
+
padding: 0.3em 0;
|
|
191
187
|
|
|
192
188
|
}
|
|
193
189
|
|
|
194
|
-
.
|
|
190
|
+
.router .cn-title {
|
|
191
|
+
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.cn-title .name {
|
|
195
195
|
flex-grow: 1;
|
|
196
|
-
|
|
196
|
+
}
|
|
197
197
|
|
|
198
198
|
.quick-replies {
|
|
199
199
|
margin-top: 0.5em;
|
|
@@ -230,7 +230,7 @@ export class CanvasNode extends RapidElement {
|
|
|
230
230
|
margin-top: -0.8em;
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
-
.category .title {
|
|
233
|
+
.category .cn-title {
|
|
234
234
|
font-weight: normal;
|
|
235
235
|
font-size: 1em;
|
|
236
236
|
max-width: 150px;
|
|
@@ -244,7 +244,7 @@ export class CanvasNode extends RapidElement {
|
|
|
244
244
|
}
|
|
245
245
|
|
|
246
246
|
.result-name {
|
|
247
|
-
font-weight:
|
|
247
|
+
font-weight: 500;
|
|
248
248
|
display: inline-block;
|
|
249
249
|
}
|
|
250
250
|
|
|
@@ -320,7 +320,7 @@ export class CanvasNode extends RapidElement {
|
|
|
320
320
|
border-bottom-right-radius: var(--curvature);
|
|
321
321
|
}
|
|
322
322
|
|
|
323
|
-
.router .title {
|
|
323
|
+
.router .cn-title {
|
|
324
324
|
border-top-left-radius: var(--curvature);
|
|
325
325
|
border-top-right-radius: var(--curvature);
|
|
326
326
|
}
|
|
@@ -329,7 +329,7 @@ export class CanvasNode extends RapidElement {
|
|
|
329
329
|
overflow: hidden;
|
|
330
330
|
}
|
|
331
331
|
|
|
332
|
-
.action:first-child .title {
|
|
332
|
+
.action:first-child .cn-title {
|
|
333
333
|
border-top-left-radius: var(--curvature);
|
|
334
334
|
border-top-right-radius: var(--curvature);
|
|
335
335
|
}
|
|
@@ -610,10 +610,11 @@ export class CanvasNode extends RapidElement {
|
|
|
610
610
|
}
|
|
611
611
|
|
|
612
612
|
private handleActionMouseDown(event: MouseEvent, action: Action): void {
|
|
613
|
-
// Don't handle clicks on the remove button or when action is in removing state
|
|
613
|
+
// Don't handle clicks on the remove button, drag handle, or when action is in removing state
|
|
614
614
|
const target = event.target as HTMLElement;
|
|
615
615
|
if (
|
|
616
616
|
target.closest('.remove-button') ||
|
|
617
|
+
target.closest('.drag-handle') ||
|
|
617
618
|
this.actionRemovingState.has(action.uuid)
|
|
618
619
|
) {
|
|
619
620
|
return;
|
|
@@ -636,10 +637,11 @@ export class CanvasNode extends RapidElement {
|
|
|
636
637
|
return;
|
|
637
638
|
}
|
|
638
639
|
|
|
639
|
-
// Don't handle clicks on the remove button or when action is in removing state
|
|
640
|
+
// Don't handle clicks on the remove button, drag handle, or when action is in removing state
|
|
640
641
|
const target = event.target as HTMLElement;
|
|
641
642
|
if (
|
|
642
643
|
target.closest('.remove-button') ||
|
|
644
|
+
target.closest('.drag-handle') ||
|
|
643
645
|
this.actionRemovingState.has(action.uuid)
|
|
644
646
|
) {
|
|
645
647
|
this.actionClickStartPos = null;
|
|
@@ -727,12 +729,13 @@ export class CanvasNode extends RapidElement {
|
|
|
727
729
|
}
|
|
728
730
|
|
|
729
731
|
private handleNodeMouseDown(event: MouseEvent): void {
|
|
730
|
-
// Don't handle clicks on the remove button, exits, or when node is in removing state
|
|
732
|
+
// Don't handle clicks on the remove button, exits, drag handle, or when node is in removing state
|
|
731
733
|
const target = event.target as HTMLElement;
|
|
732
734
|
if (
|
|
733
735
|
target.closest('.remove-button') ||
|
|
734
736
|
target.closest('.exit') ||
|
|
735
737
|
target.closest('.exit-wrapper') ||
|
|
738
|
+
target.closest('.drag-handle') ||
|
|
736
739
|
this.actionRemovingState.has(this.node.uuid)
|
|
737
740
|
) {
|
|
738
741
|
return;
|
|
@@ -752,12 +755,13 @@ export class CanvasNode extends RapidElement {
|
|
|
752
755
|
return;
|
|
753
756
|
}
|
|
754
757
|
|
|
755
|
-
// Don't handle clicks on the remove button, exits, or when node is in removing state
|
|
758
|
+
// Don't handle clicks on the remove button, exits, drag handle, or when node is in removing state
|
|
756
759
|
const target = event.target as HTMLElement;
|
|
757
760
|
if (
|
|
758
761
|
target.closest('.remove-button') ||
|
|
759
762
|
target.closest('.exit') ||
|
|
760
763
|
target.closest('.exit-wrapper') ||
|
|
764
|
+
target.closest('.drag-handle') ||
|
|
761
765
|
this.actionRemovingState.has(this.node.uuid)
|
|
762
766
|
) {
|
|
763
767
|
this.nodeClickStartPos = null;
|
|
@@ -803,22 +807,43 @@ export class CanvasNode extends RapidElement {
|
|
|
803
807
|
this.pendingNodeClick = null;
|
|
804
808
|
}
|
|
805
809
|
|
|
806
|
-
private renderTitle(
|
|
807
|
-
|
|
810
|
+
private renderTitle(
|
|
811
|
+
config: ActionConfig,
|
|
812
|
+
action: Action,
|
|
813
|
+
index: number,
|
|
814
|
+
isRemoving: boolean = false
|
|
815
|
+
) {
|
|
816
|
+
return html`<div class="cn-title" style="background:${config.color}">
|
|
808
817
|
${this.node?.actions?.length > 1
|
|
809
818
|
? html`<temba-icon class="drag-handle" name="sort"></temba-icon>`
|
|
810
819
|
: null}
|
|
811
820
|
|
|
812
821
|
<div class="name">${isRemoving ? 'Remove?' : config.name}</div>
|
|
822
|
+
<div
|
|
823
|
+
class="remove-button"
|
|
824
|
+
@click=${(e: MouseEvent) =>
|
|
825
|
+
this.handleActionRemoveClick(e, action, index)}
|
|
826
|
+
title="Remove action"
|
|
827
|
+
>
|
|
828
|
+
✕
|
|
829
|
+
</div>
|
|
813
830
|
</div>`;
|
|
814
831
|
}
|
|
815
832
|
|
|
816
833
|
private renderNodeTitle(config: NodeConfig, isRemoving: boolean = false) {
|
|
817
834
|
return html`<div
|
|
818
|
-
class="title ${isRemoving ? 'removing' : ''}"
|
|
835
|
+
class="cn-title ${isRemoving ? 'removing' : ''}"
|
|
819
836
|
style="background:${config.color}"
|
|
820
837
|
>
|
|
838
|
+
<div class="title-spacer"></div>
|
|
821
839
|
<div class="name">${isRemoving ? 'Remove?' : config.name}</div>
|
|
840
|
+
<div
|
|
841
|
+
class="remove-button"
|
|
842
|
+
@click=${(e: MouseEvent) => this.handleNodeRemoveClick(e)}
|
|
843
|
+
title="Remove node"
|
|
844
|
+
>
|
|
845
|
+
✕
|
|
846
|
+
</div>
|
|
822
847
|
</div>`;
|
|
823
848
|
}
|
|
824
849
|
|
|
@@ -831,21 +856,13 @@ export class CanvasNode extends RapidElement {
|
|
|
831
856
|
class="action sortable ${action.type} ${isRemoving ? 'removing' : ''}"
|
|
832
857
|
id="action-${index}"
|
|
833
858
|
>
|
|
834
|
-
<button
|
|
835
|
-
class="remove-button"
|
|
836
|
-
@click=${(e: MouseEvent) =>
|
|
837
|
-
this.handleActionRemoveClick(e, action, index)}
|
|
838
|
-
title="Remove action"
|
|
839
|
-
>
|
|
840
|
-
✕
|
|
841
|
-
</button>
|
|
842
859
|
<div
|
|
843
860
|
class="action-content"
|
|
844
861
|
@mousedown=${(e: MouseEvent) => this.handleActionMouseDown(e, action)}
|
|
845
862
|
@mouseup=${(e: MouseEvent) => this.handleActionMouseUp(e, action)}
|
|
846
863
|
style="cursor: pointer;"
|
|
847
864
|
>
|
|
848
|
-
${this.renderTitle(config, isRemoving)}
|
|
865
|
+
${this.renderTitle(config, action, index, isRemoving)}
|
|
849
866
|
<div class="body">
|
|
850
867
|
${config.render
|
|
851
868
|
? config.render(node, action)
|
|
@@ -858,14 +875,14 @@ export class CanvasNode extends RapidElement {
|
|
|
858
875
|
class="action sortable ${isRemoving ? 'removing' : ''}"
|
|
859
876
|
id="action-${index}"
|
|
860
877
|
>
|
|
861
|
-
<
|
|
878
|
+
<div
|
|
862
879
|
class="remove-button"
|
|
863
880
|
@click=${(e: MouseEvent) =>
|
|
864
881
|
this.handleActionRemoveClick(e, action, index)}
|
|
865
882
|
title="Remove action"
|
|
866
883
|
>
|
|
867
884
|
✕
|
|
868
|
-
</
|
|
885
|
+
</div>
|
|
869
886
|
${action.type}
|
|
870
887
|
</div>`;
|
|
871
888
|
}
|
|
@@ -909,7 +926,7 @@ export class CanvasNode extends RapidElement {
|
|
|
909
926
|
@mouseup=${(e: MouseEvent) => this.handleNodeMouseUp(e)}
|
|
910
927
|
style="cursor: pointer;"
|
|
911
928
|
>
|
|
912
|
-
<div class="title">${category.name}</div>
|
|
929
|
+
<div class="cn-title">${category.name}</div>
|
|
913
930
|
${this.renderExit(exit)}
|
|
914
931
|
</div>`;
|
|
915
932
|
}
|
|
@@ -948,13 +965,6 @@ export class CanvasNode extends RapidElement {
|
|
|
948
965
|
>
|
|
949
966
|
${nodeConfig && nodeConfig.type !== 'execute_actions'
|
|
950
967
|
? html`<div class="router" style="position: relative;">
|
|
951
|
-
<button
|
|
952
|
-
class="remove-button"
|
|
953
|
-
@click=${(e: MouseEvent) => this.handleNodeRemoveClick(e)}
|
|
954
|
-
title="Remove node"
|
|
955
|
-
>
|
|
956
|
-
✕
|
|
957
|
-
</button>
|
|
958
968
|
<div
|
|
959
969
|
@mousedown=${(e: MouseEvent) => this.handleNodeMouseDown(e)}
|
|
960
970
|
@mouseup=${(e: MouseEvent) => this.handleNodeMouseUp(e)}
|
package/src/flow/Editor.ts
CHANGED
package/src/flow/NodeEditor.ts
CHANGED
|
@@ -85,7 +85,7 @@ export class NodeEditor extends RapidElement {
|
|
|
85
85
|
.form-row {
|
|
86
86
|
display: grid;
|
|
87
87
|
gap: 1rem;
|
|
88
|
-
align-items:
|
|
88
|
+
align-items: center;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
.form-group {
|
|
@@ -257,6 +257,25 @@ export class NodeEditor extends RapidElement {
|
|
|
257
257
|
display: flex;
|
|
258
258
|
align-items: center;
|
|
259
259
|
}
|
|
260
|
+
|
|
261
|
+
.gutter-fields {
|
|
262
|
+
display: flex;
|
|
263
|
+
flex-direction: column;
|
|
264
|
+
gap: 10px;
|
|
265
|
+
align-items: flex-start;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.gutter-fields .form-row {
|
|
269
|
+
margin: 0;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.gutter-fields temba-checkbox {
|
|
273
|
+
align-self: flex-start;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.gutter-fields temba-select {
|
|
277
|
+
min-width: 120px;
|
|
278
|
+
}
|
|
260
279
|
`;
|
|
261
280
|
}
|
|
262
281
|
|
|
@@ -1059,6 +1078,7 @@ export class NodeEditor extends RapidElement {
|
|
|
1059
1078
|
}
|
|
1060
1079
|
},
|
|
1061
1080
|
showLabel: true,
|
|
1081
|
+
formData: this.formData,
|
|
1062
1082
|
additionalData: {
|
|
1063
1083
|
attachments: this.formData.attachments || []
|
|
1064
1084
|
}
|
|
@@ -1420,14 +1440,24 @@ export class NodeEditor extends RapidElement {
|
|
|
1420
1440
|
if (config.layout) {
|
|
1421
1441
|
const renderedFields = new Set<string>();
|
|
1422
1442
|
|
|
1443
|
+
// Also collect fields from gutter to avoid rendering them in main form
|
|
1444
|
+
const gutterFields = new Set<string>();
|
|
1445
|
+
if (config.gutter) {
|
|
1446
|
+
const gutterFieldNames = this.collectFieldsFromItems(config.gutter);
|
|
1447
|
+
gutterFieldNames.forEach((field) => gutterFields.add(field));
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1423
1450
|
return html`
|
|
1424
1451
|
${config.layout.map((item) =>
|
|
1425
1452
|
this.renderLayoutItem(item, config, renderedFields)
|
|
1426
1453
|
)}
|
|
1427
1454
|
${
|
|
1428
|
-
/* Render any fields not explicitly placed in layout */
|
|
1455
|
+
/* Render any fields not explicitly placed in layout or gutter */
|
|
1429
1456
|
Object.entries(config.form).map(([fieldName, fieldConfig]) => {
|
|
1430
|
-
if (
|
|
1457
|
+
if (
|
|
1458
|
+
!renderedFields.has(fieldName) &&
|
|
1459
|
+
!gutterFields.has(fieldName)
|
|
1460
|
+
) {
|
|
1431
1461
|
return this.renderNewField(
|
|
1432
1462
|
fieldName,
|
|
1433
1463
|
fieldConfig as FieldConfig,
|
|
@@ -1460,6 +1490,24 @@ export class NodeEditor extends RapidElement {
|
|
|
1460
1490
|
}
|
|
1461
1491
|
}
|
|
1462
1492
|
|
|
1493
|
+
private renderGutter(): TemplateResult {
|
|
1494
|
+
const config = this.getConfig();
|
|
1495
|
+
if (!config?.gutter || config.gutter.length === 0) {
|
|
1496
|
+
return html``;
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
// Use the same layout rendering system for gutter fields
|
|
1500
|
+
const renderedFields = new Set<string>();
|
|
1501
|
+
|
|
1502
|
+
return html`
|
|
1503
|
+
<div class="gutter-fields">
|
|
1504
|
+
${config.gutter.map((item) =>
|
|
1505
|
+
this.renderLayoutItem(item, config, renderedFields)
|
|
1506
|
+
)}
|
|
1507
|
+
</div>
|
|
1508
|
+
`;
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1463
1511
|
private renderActionSection(): TemplateResult {
|
|
1464
1512
|
if (!this.node || this.node.actions.length === 0) {
|
|
1465
1513
|
return html``;
|
|
@@ -1531,6 +1579,7 @@ export class NodeEditor extends RapidElement {
|
|
|
1531
1579
|
|
|
1532
1580
|
const headerColor = this.getHeaderColor();
|
|
1533
1581
|
const config = this.getConfig();
|
|
1582
|
+
const dialogSize = config?.dialogSize || 'medium'; // Default to 'large' if not specified
|
|
1534
1583
|
|
|
1535
1584
|
return html`
|
|
1536
1585
|
<temba-dialog
|
|
@@ -1540,6 +1589,7 @@ export class NodeEditor extends RapidElement {
|
|
|
1540
1589
|
primaryButtonName="Save"
|
|
1541
1590
|
cancelButtonName="Cancel"
|
|
1542
1591
|
style="--header-bg: ${headerColor}"
|
|
1592
|
+
size="${dialogSize}"
|
|
1543
1593
|
>
|
|
1544
1594
|
<div class="node-editor-form">
|
|
1545
1595
|
${this.renderFields()}
|
|
@@ -1547,6 +1597,8 @@ export class NodeEditor extends RapidElement {
|
|
|
1547
1597
|
? this.renderRouterSection()
|
|
1548
1598
|
: null}
|
|
1549
1599
|
</div>
|
|
1600
|
+
|
|
1601
|
+
<div slot="gutter">${this.renderGutter()}</div>
|
|
1550
1602
|
</temba-dialog>
|
|
1551
1603
|
`;
|
|
1552
1604
|
}
|
|
@@ -11,7 +11,7 @@ export const add_contact_urn: ActionConfig = {
|
|
|
11
11
|
return html`<div
|
|
12
12
|
style="word-wrap: break-word; overflow-wrap: break-word; hyphens: auto;"
|
|
13
13
|
>
|
|
14
|
-
Add ${friendlyScheme} <
|
|
14
|
+
Add ${friendlyScheme} <strong>${action.path}</strong>
|
|
15
15
|
</div>`;
|
|
16
16
|
}
|
|
17
17
|
};
|
|
@@ -6,7 +6,7 @@ export const set_contact_channel: ActionConfig = {
|
|
|
6
6
|
name: 'Update Channel',
|
|
7
7
|
color: COLORS.update,
|
|
8
8
|
render: (_node: Node, action: SetContactChannel) => {
|
|
9
|
-
return html`<div>Set to <
|
|
9
|
+
return html`<div>Set to <strong>${action.channel.name}</strong></div>`;
|
|
10
10
|
},
|
|
11
11
|
form: {
|
|
12
12
|
channel: {
|
|
@@ -7,7 +7,8 @@ export const set_contact_field: ActionConfig = {
|
|
|
7
7
|
color: COLORS.update,
|
|
8
8
|
render: (_node: Node, action: SetContactField) => {
|
|
9
9
|
return html`<div>
|
|
10
|
-
Set <
|
|
10
|
+
Set <strong>${action.field.name}</strong> to
|
|
11
|
+
<strong>${action.value}</strong>
|
|
11
12
|
</div>`;
|
|
12
13
|
},
|
|
13
14
|
form: {
|
|
@@ -10,7 +10,9 @@ export const set_contact_language: ActionConfig = {
|
|
|
10
10
|
const languageNames = new Intl.DisplayNames(['en'], {
|
|
11
11
|
type: 'language'
|
|
12
12
|
});
|
|
13
|
-
return html`<div>
|
|
13
|
+
return html`<div>
|
|
14
|
+
Set to <strong>${languageNames.of(action.language)}</strong>
|
|
15
|
+
</div>`;
|
|
14
16
|
},
|
|
15
17
|
form: {
|
|
16
18
|
language: {
|
|
@@ -6,7 +6,7 @@ export const set_contact_name: ActionConfig = {
|
|
|
6
6
|
name: 'Update Name',
|
|
7
7
|
color: COLORS.update,
|
|
8
8
|
render: (_node: Node, action: SetContactName) => {
|
|
9
|
-
return html`<div>Set to <
|
|
9
|
+
return html`<div>Set to <strong>${action.name}</strong></div>`;
|
|
10
10
|
},
|
|
11
11
|
form: {
|
|
12
12
|
name: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { html } from 'lit-html';
|
|
2
|
-
import { ActionConfig, COLORS
|
|
2
|
+
import { ActionConfig, COLORS } from '../types';
|
|
3
3
|
import { Node, SetContactStatus } from '../../store/flow-definition';
|
|
4
4
|
import { titleCase } from '../../utils';
|
|
5
5
|
|
|
@@ -7,7 +7,23 @@ export const set_contact_status: ActionConfig = {
|
|
|
7
7
|
name: 'Update Status',
|
|
8
8
|
color: COLORS.update,
|
|
9
9
|
render: (_node: Node, action: SetContactStatus) => {
|
|
10
|
-
return html`<div>Set to <
|
|
10
|
+
return html`<div>Set to <strong>${titleCase(action.status)}</strong></div>`;
|
|
11
|
+
},
|
|
12
|
+
toFormData: (action: SetContactStatus) => {
|
|
13
|
+
return {
|
|
14
|
+
...action,
|
|
15
|
+
status: {
|
|
16
|
+
name: titleCase(action.status || 'active'),
|
|
17
|
+
value: action.status || 'active'
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
fromFormData: (formData: any): SetContactStatus => {
|
|
22
|
+
return {
|
|
23
|
+
status: formData.status[0].value,
|
|
24
|
+
type: 'set_contact_status',
|
|
25
|
+
uuid: formData.uuid
|
|
26
|
+
};
|
|
11
27
|
},
|
|
12
28
|
form: {
|
|
13
29
|
status: {
|
|
@@ -24,21 +40,5 @@ export const set_contact_status: ActionConfig = {
|
|
|
24
40
|
],
|
|
25
41
|
helpText: 'Select the status to set for the contact'
|
|
26
42
|
}
|
|
27
|
-
},
|
|
28
|
-
validate: (formData: SetContactStatus): ValidationResult => {
|
|
29
|
-
const errors: { [key: string]: string } = {};
|
|
30
|
-
|
|
31
|
-
if (!formData.status) {
|
|
32
|
-
errors.status = 'Status is required';
|
|
33
|
-
} else if (
|
|
34
|
-
!['active', 'archived', 'stopped', 'blocked'].includes(formData.status)
|
|
35
|
-
) {
|
|
36
|
-
errors.status = 'Invalid status selected';
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return {
|
|
40
|
-
valid: Object.keys(errors).length === 0,
|
|
41
|
-
errors
|
|
42
|
-
};
|
|
43
43
|
}
|
|
44
44
|
};
|
|
@@ -8,7 +8,7 @@ export const set_run_result: ActionConfig = {
|
|
|
8
8
|
color: COLORS.save,
|
|
9
9
|
render: (_node: Node, action: SetRunResult) => {
|
|
10
10
|
return html`<div>
|
|
11
|
-
Save <
|
|
11
|
+
Save <strong>${action.value}</strong> as <strong>${action.name}</strong>
|
|
12
12
|
</div>`;
|
|
13
13
|
},
|
|
14
14
|
form: {
|