@embedreach/components 0.3.12 → 0.3.14
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/dist/chunks/index.js +1736 -480
- package/dist/chunks/sandbox-loading-screen.js +10 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.umd.js +14 -14
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/chunks/index.js
CHANGED
|
@@ -2788,6 +2788,57 @@ const duplicateBusinessAutomation = async (automationId, name, description2) =>
|
|
|
2788
2788
|
);
|
|
2789
2789
|
return response.data;
|
|
2790
2790
|
};
|
|
2791
|
+
const findSegmentByName = async (name) => {
|
|
2792
|
+
const response = await baseRequest(
|
|
2793
|
+
`/automations/internal/segments/find-by-name?name=${encodeURIComponent(name)}`,
|
|
2794
|
+
{
|
|
2795
|
+
method: "GET"
|
|
2796
|
+
}
|
|
2797
|
+
);
|
|
2798
|
+
return response.data;
|
|
2799
|
+
};
|
|
2800
|
+
var AutomationTriggerType = /* @__PURE__ */ ((AutomationTriggerType2) => {
|
|
2801
|
+
AutomationTriggerType2["ONE_TIME"] = "one_time";
|
|
2802
|
+
AutomationTriggerType2["TRIGGER_BASED"] = "trigger_based";
|
|
2803
|
+
AutomationTriggerType2["DATE_BASED"] = "date_based";
|
|
2804
|
+
return AutomationTriggerType2;
|
|
2805
|
+
})(AutomationTriggerType || {});
|
|
2806
|
+
var ReachEventNamesEnum = /* @__PURE__ */ ((ReachEventNamesEnum2) => {
|
|
2807
|
+
ReachEventNamesEnum2["USER_ENTERS_SEGMENT"] = "USER_ENTERS_SEGMENT";
|
|
2808
|
+
return ReachEventNamesEnum2;
|
|
2809
|
+
})(ReachEventNamesEnum || {});
|
|
2810
|
+
var BusinessAutomationTypeEnum = /* @__PURE__ */ ((BusinessAutomationTypeEnum2) => {
|
|
2811
|
+
BusinessAutomationTypeEnum2["MANAGED"] = "managed";
|
|
2812
|
+
BusinessAutomationTypeEnum2["CUSTOM"] = "custom";
|
|
2813
|
+
return BusinessAutomationTypeEnum2;
|
|
2814
|
+
})(BusinessAutomationTypeEnum || {});
|
|
2815
|
+
var ActionType = /* @__PURE__ */ ((ActionType2) => {
|
|
2816
|
+
ActionType2["SEND_COMMUNICATION"] = "send_communication";
|
|
2817
|
+
ActionType2["WAIT_UNTIL_NEXT_FIXED_TIME"] = "wait_until_next_fixed_time";
|
|
2818
|
+
return ActionType2;
|
|
2819
|
+
})(ActionType || {});
|
|
2820
|
+
var AutomationStatus = /* @__PURE__ */ ((AutomationStatus2) => {
|
|
2821
|
+
AutomationStatus2["DRAFT"] = "draft";
|
|
2822
|
+
AutomationStatus2["ACTIVE"] = "active";
|
|
2823
|
+
AutomationStatus2["RUNNING"] = "running";
|
|
2824
|
+
AutomationStatus2["COMPLETED"] = "completed";
|
|
2825
|
+
AutomationStatus2["FAILED"] = "failed";
|
|
2826
|
+
AutomationStatus2["DEACTIVATED"] = "deactivated";
|
|
2827
|
+
AutomationStatus2["SENDING"] = "sending";
|
|
2828
|
+
AutomationStatus2["SCHEDULED"] = "scheduled";
|
|
2829
|
+
AutomationStatus2["PARTIALLY_CANCELLED"] = "partially_cancelled";
|
|
2830
|
+
AutomationStatus2["CANCELLED"] = "cancelled";
|
|
2831
|
+
AutomationStatus2["ARCHIVED"] = "archived";
|
|
2832
|
+
return AutomationStatus2;
|
|
2833
|
+
})(AutomationStatus || {});
|
|
2834
|
+
var ChannelIntegrationTypeEnum = /* @__PURE__ */ ((ChannelIntegrationTypeEnum2) => {
|
|
2835
|
+
ChannelIntegrationTypeEnum2["EMAIL"] = "email";
|
|
2836
|
+
ChannelIntegrationTypeEnum2["SMS"] = "sms";
|
|
2837
|
+
return ChannelIntegrationTypeEnum2;
|
|
2838
|
+
})(ChannelIntegrationTypeEnum || {});
|
|
2839
|
+
const shouldPoll = (automationStatus) => {
|
|
2840
|
+
return automationStatus !== AutomationStatus.DRAFT && automationStatus !== AutomationStatus.COMPLETED && automationStatus !== AutomationStatus.PARTIALLY_CANCELLED && automationStatus !== AutomationStatus.CANCELLED;
|
|
2841
|
+
};
|
|
2791
2842
|
const TOAST_LIMIT = 1;
|
|
2792
2843
|
const TOAST_REMOVE_DELAY = 1e6;
|
|
2793
2844
|
let count$8 = 0;
|
|
@@ -2961,6 +3012,16 @@ const resetCommunicationGroupToDefault = async (args) => {
|
|
|
2961
3012
|
);
|
|
2962
3013
|
return response.data;
|
|
2963
3014
|
};
|
|
3015
|
+
const postBusinessMergeFieldFallbacks = async (mergeFieldFallbacks) => {
|
|
3016
|
+
const response = await baseRequest(
|
|
3017
|
+
`/businesses/merge-field-fallbacks`,
|
|
3018
|
+
{
|
|
3019
|
+
method: "PATCH",
|
|
3020
|
+
body: JSON.stringify({ mergeFieldFallbacks })
|
|
3021
|
+
}
|
|
3022
|
+
);
|
|
3023
|
+
return response.data;
|
|
3024
|
+
};
|
|
2964
3025
|
const getLinkClickStats = async (automationId) => {
|
|
2965
3026
|
const response = await baseRequest(
|
|
2966
3027
|
`${COMMUNICATION_GROUP_PATH}/${automationId}/link-click-stats`
|
|
@@ -3079,6 +3140,36 @@ const useResetCommunicationGroupToDefault = () => {
|
|
|
3079
3140
|
isPending: resetCommunicationGroupToDefaultMutation.isPending
|
|
3080
3141
|
};
|
|
3081
3142
|
};
|
|
3143
|
+
const usePostBusinessMergeFieldFallbacks = () => {
|
|
3144
|
+
const queryClient = useQueryClient();
|
|
3145
|
+
const { toast: toast2 } = useToast();
|
|
3146
|
+
const mutation = useMutation({
|
|
3147
|
+
mutationFn: ({
|
|
3148
|
+
mergeFieldFallbacks
|
|
3149
|
+
}) => postBusinessMergeFieldFallbacks(mergeFieldFallbacks),
|
|
3150
|
+
onSuccess: () => {
|
|
3151
|
+
queryClient.invalidateQueries({
|
|
3152
|
+
queryKey: communicationGroupQueryKeys.all
|
|
3153
|
+
});
|
|
3154
|
+
toast2({
|
|
3155
|
+
title: "Merge field fallbacks updated",
|
|
3156
|
+
description: "Merge field fallbacks have been updated"
|
|
3157
|
+
});
|
|
3158
|
+
},
|
|
3159
|
+
onError: () => {
|
|
3160
|
+
toast2({
|
|
3161
|
+
title: "Failed to update merge field fallbacks",
|
|
3162
|
+
description: "Please reach out to your administrator"
|
|
3163
|
+
});
|
|
3164
|
+
}
|
|
3165
|
+
});
|
|
3166
|
+
return {
|
|
3167
|
+
postBusinessMergeFieldFallbacks: mutation.mutate,
|
|
3168
|
+
isPosting: mutation.isPending,
|
|
3169
|
+
postError: mutation.error,
|
|
3170
|
+
isPostSuccess: mutation.isSuccess
|
|
3171
|
+
};
|
|
3172
|
+
};
|
|
3082
3173
|
const useGetLinkClickStats = (automationId) => {
|
|
3083
3174
|
const query = useQuery({
|
|
3084
3175
|
queryKey: ["link-click-stats", automationId],
|
|
@@ -3096,7 +3187,14 @@ const useGetBusinessAutomation = (automationId) => {
|
|
|
3096
3187
|
const queryClient = useQueryClient();
|
|
3097
3188
|
const getAutomationQuery = useQuery({
|
|
3098
3189
|
queryKey: automationKeys.single(automationId),
|
|
3099
|
-
queryFn: () => getAutomation(automationId)
|
|
3190
|
+
queryFn: () => getAutomation(automationId),
|
|
3191
|
+
refetchInterval: (data) => {
|
|
3192
|
+
const shouldPollResult = shouldPoll(data?.state.data?.status);
|
|
3193
|
+
if (shouldPollResult) {
|
|
3194
|
+
return 2e3;
|
|
3195
|
+
}
|
|
3196
|
+
return false;
|
|
3197
|
+
}
|
|
3100
3198
|
});
|
|
3101
3199
|
return {
|
|
3102
3200
|
// Get automation query
|
|
@@ -3124,7 +3222,13 @@ const useGetBusinessAutomationSentCommunications = (args) => {
|
|
|
3124
3222
|
// It will be false if placeholder data is being shown, even though a new fetch is in progress (`isFetching` will be true).
|
|
3125
3223
|
// This provides a much smoother UX, as the UI doesn't jump to a loading state on pagination or filter changes
|
|
3126
3224
|
// if previous data is available to show in the meantime.
|
|
3127
|
-
placeholderData: keepPreviousData
|
|
3225
|
+
placeholderData: keepPreviousData,
|
|
3226
|
+
refetchInterval: () => {
|
|
3227
|
+
if (shouldPoll(args.automationStatus)) {
|
|
3228
|
+
return 2e3;
|
|
3229
|
+
}
|
|
3230
|
+
return false;
|
|
3231
|
+
}
|
|
3128
3232
|
});
|
|
3129
3233
|
return {
|
|
3130
3234
|
// Get automation sent communications query
|
|
@@ -3255,45 +3359,6 @@ const useDuplicateBusinessAutomation = () => {
|
|
|
3255
3359
|
isDuplicateSuccess: duplicateAutomationMutation.isSuccess
|
|
3256
3360
|
};
|
|
3257
3361
|
};
|
|
3258
|
-
var AutomationTriggerType = /* @__PURE__ */ ((AutomationTriggerType2) => {
|
|
3259
|
-
AutomationTriggerType2["ONE_TIME"] = "one_time";
|
|
3260
|
-
AutomationTriggerType2["TRIGGER_BASED"] = "trigger_based";
|
|
3261
|
-
AutomationTriggerType2["DATE_BASED"] = "date_based";
|
|
3262
|
-
return AutomationTriggerType2;
|
|
3263
|
-
})(AutomationTriggerType || {});
|
|
3264
|
-
var ReachEventNamesEnum = /* @__PURE__ */ ((ReachEventNamesEnum2) => {
|
|
3265
|
-
ReachEventNamesEnum2["USER_ENTERS_SEGMENT"] = "USER_ENTERS_SEGMENT";
|
|
3266
|
-
return ReachEventNamesEnum2;
|
|
3267
|
-
})(ReachEventNamesEnum || {});
|
|
3268
|
-
var BusinessAutomationTypeEnum = /* @__PURE__ */ ((BusinessAutomationTypeEnum2) => {
|
|
3269
|
-
BusinessAutomationTypeEnum2["MANAGED"] = "managed";
|
|
3270
|
-
BusinessAutomationTypeEnum2["CUSTOM"] = "custom";
|
|
3271
|
-
return BusinessAutomationTypeEnum2;
|
|
3272
|
-
})(BusinessAutomationTypeEnum || {});
|
|
3273
|
-
var ActionType = /* @__PURE__ */ ((ActionType2) => {
|
|
3274
|
-
ActionType2["SEND_COMMUNICATION"] = "send_communication";
|
|
3275
|
-
ActionType2["WAIT_UNTIL_NEXT_FIXED_TIME"] = "wait_until_next_fixed_time";
|
|
3276
|
-
return ActionType2;
|
|
3277
|
-
})(ActionType || {});
|
|
3278
|
-
var AutomationStatus = /* @__PURE__ */ ((AutomationStatus2) => {
|
|
3279
|
-
AutomationStatus2["DRAFT"] = "draft";
|
|
3280
|
-
AutomationStatus2["ACTIVE"] = "active";
|
|
3281
|
-
AutomationStatus2["RUNNING"] = "running";
|
|
3282
|
-
AutomationStatus2["COMPLETED"] = "completed";
|
|
3283
|
-
AutomationStatus2["FAILED"] = "failed";
|
|
3284
|
-
AutomationStatus2["DEACTIVATED"] = "deactivated";
|
|
3285
|
-
AutomationStatus2["SENDING"] = "sending";
|
|
3286
|
-
AutomationStatus2["SCHEDULED"] = "scheduled";
|
|
3287
|
-
AutomationStatus2["PARTIALLY_CANCELLED"] = "partially_cancelled";
|
|
3288
|
-
AutomationStatus2["CANCELLED"] = "cancelled";
|
|
3289
|
-
AutomationStatus2["ARCHIVED"] = "archived";
|
|
3290
|
-
return AutomationStatus2;
|
|
3291
|
-
})(AutomationStatus || {});
|
|
3292
|
-
var ChannelIntegrationTypeEnum = /* @__PURE__ */ ((ChannelIntegrationTypeEnum2) => {
|
|
3293
|
-
ChannelIntegrationTypeEnum2["EMAIL"] = "email";
|
|
3294
|
-
ChannelIntegrationTypeEnum2["SMS"] = "sms";
|
|
3295
|
-
return ChannelIntegrationTypeEnum2;
|
|
3296
|
-
})(ChannelIntegrationTypeEnum || {});
|
|
3297
3362
|
class InvalidTokenError extends Error {
|
|
3298
3363
|
}
|
|
3299
3364
|
InvalidTokenError.prototype.name = "InvalidTokenError";
|
|
@@ -25678,6 +25743,16 @@ const Info = createLucideIcon("Info", [
|
|
|
25678
25743
|
["path", { d: "M12 16v-4", key: "1dtifu" }],
|
|
25679
25744
|
["path", { d: "M12 8h.01", key: "e9boi3" }]
|
|
25680
25745
|
]);
|
|
25746
|
+
/**
|
|
25747
|
+
* @license lucide-react v0.464.0 - ISC
|
|
25748
|
+
*
|
|
25749
|
+
* This source code is licensed under the ISC license.
|
|
25750
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
25751
|
+
*/
|
|
25752
|
+
const Link$1 = createLucideIcon("Link", [
|
|
25753
|
+
["path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71", key: "1cjeqo" }],
|
|
25754
|
+
["path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71", key: "19qd67" }]
|
|
25755
|
+
]);
|
|
25681
25756
|
/**
|
|
25682
25757
|
* @license lucide-react v0.464.0 - ISC
|
|
25683
25758
|
*
|
|
@@ -29244,6 +29319,47 @@ const applyThemeStyles = (styles2, darkStyles) => {
|
|
|
29244
29319
|
if (existingStyles) {
|
|
29245
29320
|
existingStyles.remove();
|
|
29246
29321
|
}
|
|
29322
|
+
const isGoogleFont = (font) => {
|
|
29323
|
+
if (!font) return null;
|
|
29324
|
+
const match2 = font.match(/^["']?([\w\s]+)["']?/);
|
|
29325
|
+
if (!match2) return null;
|
|
29326
|
+
const fontName = match2[1].trim();
|
|
29327
|
+
const systemFonts = [
|
|
29328
|
+
"Inter",
|
|
29329
|
+
"system-ui",
|
|
29330
|
+
"-apple-system",
|
|
29331
|
+
"BlinkMacSystemFont",
|
|
29332
|
+
"Segoe UI",
|
|
29333
|
+
"Roboto",
|
|
29334
|
+
"sans-serif",
|
|
29335
|
+
"serif",
|
|
29336
|
+
"monospace",
|
|
29337
|
+
"Arial",
|
|
29338
|
+
"Georgia",
|
|
29339
|
+
"Times New Roman",
|
|
29340
|
+
"Courier New",
|
|
29341
|
+
"Plus Jakarta Sans"
|
|
29342
|
+
];
|
|
29343
|
+
if (systemFonts.some((sys) => fontName === sys)) return null;
|
|
29344
|
+
return fontName;
|
|
29345
|
+
};
|
|
29346
|
+
const googleFonts = /* @__PURE__ */ new Set();
|
|
29347
|
+
const fontBody = styles2["font-body"];
|
|
29348
|
+
const fontHeading = styles2["font-heading"];
|
|
29349
|
+
const bodyFont = isGoogleFont(fontBody);
|
|
29350
|
+
const headingFont = isGoogleFont(fontHeading);
|
|
29351
|
+
if (bodyFont) googleFonts.add(bodyFont);
|
|
29352
|
+
if (headingFont) googleFonts.add(headingFont);
|
|
29353
|
+
googleFonts.forEach((fontName) => {
|
|
29354
|
+
const fontId = `reach-google-font-${fontName.replace(/\s+/g, "-")}`;
|
|
29355
|
+
if (!document.getElementById(fontId)) {
|
|
29356
|
+
const link2 = document.createElement("link");
|
|
29357
|
+
link2.id = fontId;
|
|
29358
|
+
link2.rel = "stylesheet";
|
|
29359
|
+
link2.href = `https://fonts.googleapis.com/css?family=${encodeURIComponent(fontName)}:400,500,700&display=swap`;
|
|
29360
|
+
document.head.appendChild(link2);
|
|
29361
|
+
}
|
|
29362
|
+
});
|
|
29247
29363
|
const styleElement2 = document.createElement("style");
|
|
29248
29364
|
styleElement2.id = "reach-theme-styles";
|
|
29249
29365
|
let cssText = `
|
|
@@ -32360,6 +32476,8 @@ const measure$1 = {
|
|
|
32360
32476
|
total_revenue: "Total Revenue",
|
|
32361
32477
|
total_revenue_description: "The complete revenue generated by your business during the selected period from all sources, not just advertising campaigns. \n\nThis includes revenue from direct traffic, organic search, referrals, and any other channels in addition to paid advertising.",
|
|
32362
32478
|
website_visitors: "Website Visitors",
|
|
32479
|
+
unknown_revenue: "Unknown Revenue",
|
|
32480
|
+
unknown_revenue_description: "Revenue from purchases where we were unable to find customer interactions (like site visits or phone calls) in the 90 days before buying.",
|
|
32363
32481
|
website_visitors_description: "The number of unique visitors who came to your website from your advertising campaigns during the selected period. \n\nThis metric is tracked using analytics tools and represents actual people who successfully navigated from your ads to your website."
|
|
32364
32482
|
},
|
|
32365
32483
|
settings: {
|
|
@@ -32367,7 +32485,6 @@ const measure$1 = {
|
|
|
32367
32485
|
description: "Manage your account settings",
|
|
32368
32486
|
connected_accounts: "Connected Accounts",
|
|
32369
32487
|
not_running_paid_ads: "Not running paid ads? Use AI to create a Google Ads campaign",
|
|
32370
|
-
not_running_paid_ads_tooltip: "Contact your administrator to learn more about this feature and how to activate it for your account",
|
|
32371
32488
|
privacy_policy: "Privacy Policy",
|
|
32372
32489
|
quick_links: "Quick Links",
|
|
32373
32490
|
setup_tracking_pixel: "Setup tracking pixel",
|
|
@@ -32388,7 +32505,11 @@ const measure$1 = {
|
|
|
32388
32505
|
purchases_tooltip: "Purchases are the number of times a user made a purchase after clicking on your ad. \n\nThe percentage is calculated by dividing the number of purchases by the number of clicks (from the previous bar line)"
|
|
32389
32506
|
},
|
|
32390
32507
|
roas_chart: {
|
|
32391
|
-
title: "Return on Ad Spend Trends"
|
|
32508
|
+
title: "Return on Ad Spend Trends",
|
|
32509
|
+
attribution_tooltip_title: "How revenue is counted in this chart",
|
|
32510
|
+
attribution_tooltip_description: "For each day, we show the total ad spend, revenue, and ROAS (return on ad spend) from people who clicked an ad that day.\n\nIf someone clicks an ad and buys within 90 days, their purchase is counted for the day they clicked the ad.\n\nThe most recent 90 days may look low, since more purchases can still come in.",
|
|
32511
|
+
incomplete_banner: "Revenue and ROAS for recent days may be lower than their final values, since we continue to count purchases made up to 90 days after someone clicks an ad.",
|
|
32512
|
+
incomplete_tooltip: "Still updating (<90 days)"
|
|
32392
32513
|
}
|
|
32393
32514
|
},
|
|
32394
32515
|
campaigns: {
|
|
@@ -32466,7 +32587,8 @@ const dates$1 = {
|
|
|
32466
32587
|
last_week: "Last week",
|
|
32467
32588
|
last_month: "Last month",
|
|
32468
32589
|
last_quarter: "Last 90 days",
|
|
32469
|
-
last_year: "Last year"
|
|
32590
|
+
last_year: "Last year",
|
|
32591
|
+
all_time: "All time"
|
|
32470
32592
|
};
|
|
32471
32593
|
const campaigns$1 = {
|
|
32472
32594
|
setup: {
|
|
@@ -32545,16 +32667,15 @@ const analytics$1 = {
|
|
|
32545
32667
|
google_tag_manager: {
|
|
32546
32668
|
step_1: "Go to https://tagmanager.google.com",
|
|
32547
32669
|
step_2: "Sign in to your Google Account",
|
|
32548
|
-
step_3:
|
|
32549
|
-
step_4: "
|
|
32550
|
-
step_5: "
|
|
32551
|
-
step_6:
|
|
32552
|
-
step_7: "
|
|
32553
|
-
step_8: "
|
|
32554
|
-
step_9: "
|
|
32555
|
-
step_10: "
|
|
32556
|
-
step_11: "
|
|
32557
|
-
step_12: 'Select "Google Analytics: Universal Analytics" as the tag type',
|
|
32670
|
+
step_3: 'In the Tags tab, click the "New" button to create a new tag',
|
|
32671
|
+
step_4: 'Choose "Custom HTML" as the tag type',
|
|
32672
|
+
step_5: "Paste the tracking code above into the HTML field",
|
|
32673
|
+
step_6: "Click anywhere in the triggering section to edit this setting",
|
|
32674
|
+
step_7: 'Select "Initialization - All Pages" as the trigger',
|
|
32675
|
+
step_8: "Click Save to save the tag",
|
|
32676
|
+
step_9: "Click Submit in the top right",
|
|
32677
|
+
step_10: "Add a version name and description",
|
|
32678
|
+
step_11: "Click Publish to deploy your changes",
|
|
32558
32679
|
special_note: "Make sure you have the Google Tag Manager container code already installed on your site before adding this tag."
|
|
32559
32680
|
},
|
|
32560
32681
|
hubspot: {
|
|
@@ -32774,6 +32895,8 @@ const broadcast_other$1 = "Broadcasts";
|
|
|
32774
32895
|
const trigger_based$1 = "Trigger Based";
|
|
32775
32896
|
const insight$1 = "Insight";
|
|
32776
32897
|
const insight_other$1 = "Insights";
|
|
32898
|
+
const merge_field$1 = "Merge Field";
|
|
32899
|
+
const merge_field_other$1 = "Merge Fields";
|
|
32777
32900
|
const enEngage = {
|
|
32778
32901
|
user: user$1,
|
|
32779
32902
|
user_other: user_other$1,
|
|
@@ -32785,7 +32908,9 @@ const enEngage = {
|
|
|
32785
32908
|
broadcast_other: broadcast_other$1,
|
|
32786
32909
|
trigger_based: trigger_based$1,
|
|
32787
32910
|
insight: insight$1,
|
|
32788
|
-
insight_other: insight_other$1
|
|
32911
|
+
insight_other: insight_other$1,
|
|
32912
|
+
merge_field: merge_field$1,
|
|
32913
|
+
merge_field_other: merge_field_other$1
|
|
32789
32914
|
};
|
|
32790
32915
|
const account_id = "ID de cuenta";
|
|
32791
32916
|
const account_name = "Nombre de cuenta";
|
|
@@ -32908,6 +33033,8 @@ const measure = {
|
|
|
32908
33033
|
total_revenue: "Ingresos totales",
|
|
32909
33034
|
total_revenue_description: "Los ingresos totales generados por tu negocio durante el período seleccionado, no solo a través de campañas de anuncios. \n\nEsto incluye ingresos de tráfico directo, búsqueda orgánica, referencias y cualquier otro canal además de campañas de anuncios.",
|
|
32910
33035
|
website_visitors: "Visitantes de tu sitio web",
|
|
33036
|
+
unknown_revenue: "Ingresos desconocidos",
|
|
33037
|
+
unknown_revenue_description: "Ingresos de compras donde no pudimos encontrar interacciones del cliente (como visitas al sitio o llamadas telefónicas) en los 90 días antes de la compra.",
|
|
32911
33038
|
website_visitors_description: "El número de visitantes únicos que llegaron a tu sitio web a través de tus campañas de anuncios durante el período seleccionado. \n\nEsta métrica se rastrea usando herramientas de analytics y representa a las personas que realmente navegaron desde tus anuncios a tu sitio web."
|
|
32912
33039
|
},
|
|
32913
33040
|
settings: {
|
|
@@ -32915,7 +33042,6 @@ const measure = {
|
|
|
32915
33042
|
description: "Gestiona tus ajustes de cuenta",
|
|
32916
33043
|
connected_accounts: "Cuentas conectadas",
|
|
32917
33044
|
not_running_paid_ads: "¿No estás ejecutando anuncios pagados? Usa IA para crear una campaña de Google Ads",
|
|
32918
|
-
not_running_paid_ads_tooltip: "Contacta a tu administrador para aprender más sobre esta función y cómo activarla para tu cuenta",
|
|
32919
33045
|
privacy_policy: "Política de privacidad",
|
|
32920
33046
|
quick_links: "Enlaces rápidos",
|
|
32921
33047
|
setup_tracking_pixel: "Configurar pixel de seguimiento",
|
|
@@ -32936,7 +33062,11 @@ const measure = {
|
|
|
32936
33062
|
purchases_tooltip: "Las compras son el número de veces que un usuario hizo una compra después de hacer clic en tu anuncio. \n\nEl porcentaje se calcula dividiendo el número de compras por el número de clics (de la línea anterior)"
|
|
32937
33063
|
},
|
|
32938
33064
|
roas_chart: {
|
|
32939
|
-
title: "Tendencias de Retorno de Inversión en Anuncios"
|
|
33065
|
+
title: "Tendencias de Retorno de Inversión en Anuncios",
|
|
33066
|
+
attribution_tooltip_title: "Cómo se cuentan los ingresos en este gráfico",
|
|
33067
|
+
attribution_tooltip_description: "Para cada día, mostramos el gasto total en anuncios, ingresos y ROAS (retorno de inversión en anuncios) de personas que hicieron clic en un anuncio ese día.\n\nSi alguien hace clic en un anuncio y compra dentro de 90 días, su compra se cuenta para el día en que hizo clic en el anuncio.\n\nLos últimos 90 días pueden parecer bajos, ya que pueden seguir llegando más compras.",
|
|
33068
|
+
incomplete_banner: "Los ingresos y ROAS de los días más recientes pueden ser inferiores a sus valores finales, ya que seguimos contando compras realizadas hasta 90 días después de que alguien haga clic en un anuncio.",
|
|
33069
|
+
incomplete_tooltip: "Aún actualizando (<90 días)"
|
|
32940
33070
|
}
|
|
32941
33071
|
},
|
|
32942
33072
|
campaigns: {
|
|
@@ -33014,7 +33144,8 @@ const dates = {
|
|
|
33014
33144
|
last_week: "Semana pasada",
|
|
33015
33145
|
last_month: "Mes pasado",
|
|
33016
33146
|
last_quarter: "Últimos 90 días",
|
|
33017
|
-
last_year: "Año pasado"
|
|
33147
|
+
last_year: "Año pasado",
|
|
33148
|
+
all_time: "Todo el tiempo"
|
|
33018
33149
|
};
|
|
33019
33150
|
const campaigns = {
|
|
33020
33151
|
setup: {
|
|
@@ -33093,16 +33224,15 @@ const analytics = {
|
|
|
33093
33224
|
google_tag_manager: {
|
|
33094
33225
|
step_1: "Ve a https://tagmanager.google.com",
|
|
33095
33226
|
step_2: "Inicia sesión en tu cuenta de Google",
|
|
33096
|
-
step_3:
|
|
33097
|
-
step_4: "
|
|
33098
|
-
step_5: "
|
|
33099
|
-
step_6:
|
|
33100
|
-
step_7: "
|
|
33101
|
-
step_8: "
|
|
33102
|
-
step_9: "
|
|
33103
|
-
step_10: "
|
|
33104
|
-
step_11: "
|
|
33105
|
-
step_12: 'Selecciona "Google Analytics: Universal Analytics" como tipo de etiqueta',
|
|
33227
|
+
step_3: 'En la pestaña de Etiquetas, haz click en el botón "Nuevo" para crear una nueva etiqueta',
|
|
33228
|
+
step_4: 'Elige "Código personalizado" como tipo de etiqueta',
|
|
33229
|
+
step_5: "Pega el código de seguimiento en el campo HTML",
|
|
33230
|
+
step_6: "Haz click en cualquier sección del trigger para editar esta configuración",
|
|
33231
|
+
step_7: 'Elige "Inicialización - Todas las páginas" como trigger',
|
|
33232
|
+
step_8: "Haz click en Guardar para guardar la etiqueta",
|
|
33233
|
+
step_9: "Haz click en Enviar en la parte superior derecha",
|
|
33234
|
+
step_10: "Añade un nombre y descripción de la versión",
|
|
33235
|
+
step_11: "Haz click en Publicar para desplegar tus cambios",
|
|
33106
33236
|
special_note: "Asegúrate de tener el código del contenedor de Google Tag Manager instalado en tu sitio web antes de agregar esta etiqueta."
|
|
33107
33237
|
},
|
|
33108
33238
|
hubspot: {
|
|
@@ -33322,6 +33452,8 @@ const broadcast_other = "Transmisiones";
|
|
|
33322
33452
|
const trigger_based = "Basado en un disparador";
|
|
33323
33453
|
const insight = "Estadísticas";
|
|
33324
33454
|
const insight_other = "Estadísticas";
|
|
33455
|
+
const merge_field = "Campo de fusión";
|
|
33456
|
+
const merge_field_other = "Campos de fusión";
|
|
33325
33457
|
const esEngage = {
|
|
33326
33458
|
user,
|
|
33327
33459
|
user_other,
|
|
@@ -33333,7 +33465,9 @@ const esEngage = {
|
|
|
33333
33465
|
broadcast_other,
|
|
33334
33466
|
trigger_based,
|
|
33335
33467
|
insight,
|
|
33336
|
-
insight_other
|
|
33468
|
+
insight_other,
|
|
33469
|
+
merge_field,
|
|
33470
|
+
merge_field_other
|
|
33337
33471
|
};
|
|
33338
33472
|
const transaction_table_id_header$1 = "Transaction ID";
|
|
33339
33473
|
const transaction_table_created_header$1 = "Transaction Created";
|
|
@@ -33521,6 +33655,8 @@ const defaultTranslations = {
|
|
|
33521
33655
|
total_revenue: "Total Revenue",
|
|
33522
33656
|
total_revenue_description: "The complete revenue generated by your business during the selected period from all sources, not just advertising campaigns. \n\nThis includes revenue from direct traffic, organic search, referrals, and any other channels in addition to paid advertising.",
|
|
33523
33657
|
website_visitors: "Website Visitors",
|
|
33658
|
+
unknown_revenue: "Unknown Revenue",
|
|
33659
|
+
unknown_revenue_description: "Revenue from purchases where we were unable to find customer interactions (like site visits or phone calls) in the 90 days before buying.",
|
|
33524
33660
|
website_visitors_description: "The number of unique visitors who came to your website from your advertising campaigns during the selected period. \n\nThis metric is tracked using analytics tools and represents actual people who successfully navigated from your ads to your website."
|
|
33525
33661
|
},
|
|
33526
33662
|
settings: {
|
|
@@ -33528,7 +33664,6 @@ const defaultTranslations = {
|
|
|
33528
33664
|
description: "Manage your account settings",
|
|
33529
33665
|
connected_accounts: "Connected Accounts",
|
|
33530
33666
|
not_running_paid_ads: "Not running paid ads? Use AI to create a Google Ads campaign",
|
|
33531
|
-
not_running_paid_ads_tooltip: "Contact your administrator to learn more about this feature and how to activate it for your account",
|
|
33532
33667
|
privacy_policy: "Privacy Policy",
|
|
33533
33668
|
quick_links: "Quick Links",
|
|
33534
33669
|
setup_tracking_pixel: "Setup tracking pixel",
|
|
@@ -33549,7 +33684,11 @@ const defaultTranslations = {
|
|
|
33549
33684
|
purchases_tooltip: "Purchases are the number of times a user made a purchase after clicking on your ad. \n\nThe percentage is calculated by dividing the number of purchases by the number of clicks (from the previous bar line)"
|
|
33550
33685
|
},
|
|
33551
33686
|
roas_chart: {
|
|
33552
|
-
title: "Return on Ad Spend Trends"
|
|
33687
|
+
title: "Return on Ad Spend Trends",
|
|
33688
|
+
attribution_tooltip_title: "How revenue is counted in this chart",
|
|
33689
|
+
attribution_tooltip_description: "For each day, we show the total ad spend, revenue, and ROAS (return on ad spend) from people who clicked an ad that day.\n\nIf someone clicks an ad and buys within 90 days, their purchase is counted for the day they clicked the ad.\n\nThe most recent 90 days may look low, since more purchases can still come in.",
|
|
33690
|
+
incomplete_banner: "Revenue and ROAS for recent days may be lower than their final values, since we continue to count purchases made up to 90 days after someone clicks an ad.",
|
|
33691
|
+
incomplete_tooltip: "Still updating (<90 days)"
|
|
33553
33692
|
}
|
|
33554
33693
|
},
|
|
33555
33694
|
campaigns: {
|
|
@@ -33628,7 +33767,8 @@ const defaultTranslations = {
|
|
|
33628
33767
|
last_week: "Last week",
|
|
33629
33768
|
last_month: "Last month",
|
|
33630
33769
|
last_quarter: "Last 90 days",
|
|
33631
|
-
last_year: "Last year"
|
|
33770
|
+
last_year: "Last year",
|
|
33771
|
+
all_time: "All time"
|
|
33632
33772
|
},
|
|
33633
33773
|
campaigns: {
|
|
33634
33774
|
setup: {
|
|
@@ -33707,16 +33847,15 @@ const defaultTranslations = {
|
|
|
33707
33847
|
google_tag_manager: {
|
|
33708
33848
|
step_1: "Go to https://tagmanager.google.com",
|
|
33709
33849
|
step_2: "Sign in to your Google Account",
|
|
33710
|
-
step_3:
|
|
33711
|
-
step_4: "
|
|
33712
|
-
step_5: "
|
|
33713
|
-
step_6:
|
|
33714
|
-
step_7: "
|
|
33715
|
-
step_8: "
|
|
33716
|
-
step_9: "
|
|
33717
|
-
step_10: "
|
|
33718
|
-
step_11: "
|
|
33719
|
-
step_12: 'Select "Google Analytics: Universal Analytics" as the tag type',
|
|
33850
|
+
step_3: 'In the Tags tab, click the "New" button to create a new tag',
|
|
33851
|
+
step_4: 'Choose "Custom HTML" as the tag type',
|
|
33852
|
+
step_5: "Paste the tracking code above into the HTML field",
|
|
33853
|
+
step_6: "Click anywhere in the triggering section to edit this setting",
|
|
33854
|
+
step_7: 'Select "Initialization - All Pages" as the trigger',
|
|
33855
|
+
step_8: "Click Save to save the tag",
|
|
33856
|
+
step_9: "Click Submit in the top right",
|
|
33857
|
+
step_10: "Add a version name and description",
|
|
33858
|
+
step_11: "Click Publish to deploy your changes",
|
|
33720
33859
|
special_note: "Make sure you have the Google Tag Manager container code already installed on your site before adding this tag."
|
|
33721
33860
|
},
|
|
33722
33861
|
hubspot: {
|
|
@@ -48907,16 +49046,16 @@ const getSegment = async (segmentId) => {
|
|
|
48907
49046
|
return null;
|
|
48908
49047
|
}
|
|
48909
49048
|
const response = await baseRequest(
|
|
48910
|
-
`${BUSINESS_SEGMENT_PATH}/${segmentId}
|
|
49049
|
+
`${BUSINESS_SEGMENT_PATH}/${segmentId}`,
|
|
49050
|
+
{
|
|
49051
|
+
method: "GET"
|
|
49052
|
+
}
|
|
48911
49053
|
);
|
|
48912
49054
|
return response.data;
|
|
48913
49055
|
};
|
|
48914
|
-
const updateSegment = async (
|
|
48915
|
-
if (!segmentId) {
|
|
48916
|
-
return null;
|
|
48917
|
-
}
|
|
49056
|
+
const updateSegment = async (id2, params) => {
|
|
48918
49057
|
const response = await baseRequest(
|
|
48919
|
-
`${BUSINESS_SEGMENT_PATH}/${
|
|
49058
|
+
`${BUSINESS_SEGMENT_PATH}/${id2}`,
|
|
48920
49059
|
{
|
|
48921
49060
|
method: "PATCH",
|
|
48922
49061
|
body: JSON.stringify(params)
|
|
@@ -48924,16 +49063,12 @@ const updateSegment = async (params, segmentId) => {
|
|
|
48924
49063
|
);
|
|
48925
49064
|
return response.data;
|
|
48926
49065
|
};
|
|
48927
|
-
const textToSegment = async (
|
|
48928
|
-
const { userInput, userCustomVerb } = args;
|
|
49066
|
+
const textToSegment = async (params) => {
|
|
48929
49067
|
const response = await baseRequest(
|
|
48930
49068
|
`${BUSINESS_SEGMENT_PATH}/text-to-segment`,
|
|
48931
49069
|
{
|
|
48932
49070
|
method: "POST",
|
|
48933
|
-
body: JSON.stringify(
|
|
48934
|
-
text: userInput,
|
|
48935
|
-
userCustomVerb: userCustomVerb || "user"
|
|
48936
|
-
})
|
|
49071
|
+
body: JSON.stringify(params)
|
|
48937
49072
|
}
|
|
48938
49073
|
);
|
|
48939
49074
|
return response.data;
|
|
@@ -49047,7 +49182,12 @@ const useGetSegment = (segmentId) => {
|
|
|
49047
49182
|
const useUpdateSegment = (segmentId) => {
|
|
49048
49183
|
const queryClient = useQueryClient();
|
|
49049
49184
|
const updateSegmentMutation = useMutation({
|
|
49050
|
-
mutationFn: (params) =>
|
|
49185
|
+
mutationFn: (params) => {
|
|
49186
|
+
if (!segmentId) {
|
|
49187
|
+
throw new Error("Segment ID is required");
|
|
49188
|
+
}
|
|
49189
|
+
return updateSegment(segmentId, params);
|
|
49190
|
+
},
|
|
49051
49191
|
onSuccess: () => {
|
|
49052
49192
|
queryClient.invalidateQueries({ queryKey: segmentKeys.all });
|
|
49053
49193
|
}
|
|
@@ -49074,6 +49214,7 @@ var BusinessSegmentTypeEnum = /* @__PURE__ */ ((BusinessSegmentTypeEnum2) => {
|
|
|
49074
49214
|
BusinessSegmentTypeEnum2["ALL_USERS"] = "all_users";
|
|
49075
49215
|
BusinessSegmentTypeEnum2["MANAGED"] = "managed";
|
|
49076
49216
|
BusinessSegmentTypeEnum2["CUSTOM"] = "custom";
|
|
49217
|
+
BusinessSegmentTypeEnum2["ONE_OFF"] = "one_off";
|
|
49077
49218
|
return BusinessSegmentTypeEnum2;
|
|
49078
49219
|
})(BusinessSegmentTypeEnum || {});
|
|
49079
49220
|
var ConditionOperatorEnumType = /* @__PURE__ */ ((ConditionOperatorEnumType2) => {
|
|
@@ -49131,20 +49272,29 @@ const useValidationStats = () => {
|
|
|
49131
49272
|
const { state } = useViewAutomationContext();
|
|
49132
49273
|
return state.recipientStats;
|
|
49133
49274
|
};
|
|
49134
|
-
const useRecipientStatsTracking = (
|
|
49135
|
-
const { setRecipientStats: setRecipientStats2 } = useViewAutomationContext();
|
|
49275
|
+
const useRecipientStatsTracking = (existingAutomation) => {
|
|
49276
|
+
const { setRecipientStats: setRecipientStats2, state } = useViewAutomationContext();
|
|
49277
|
+
const automation2 = state.automation || existingAutomation;
|
|
49136
49278
|
const { estimatedMatchesStats } = useRecipientStats$1(automation2);
|
|
49137
49279
|
useEffect(() => {
|
|
49138
49280
|
if (estimatedMatchesStats) {
|
|
49139
49281
|
setRecipientStats2(estimatedMatchesStats);
|
|
49140
49282
|
}
|
|
49141
|
-
}, [estimatedMatchesStats, setRecipientStats2]);
|
|
49283
|
+
}, [estimatedMatchesStats, setRecipientStats2, automation2]);
|
|
49142
49284
|
};
|
|
49143
49285
|
const ViewAutomationProvider = ({
|
|
49144
49286
|
automationId,
|
|
49287
|
+
existingAutomation,
|
|
49145
49288
|
children
|
|
49146
49289
|
}) => {
|
|
49147
|
-
return /* @__PURE__ */ jsx(Provider$2, { children: /* @__PURE__ */ jsx(
|
|
49290
|
+
return /* @__PURE__ */ jsx(Provider$2, { children: /* @__PURE__ */ jsx(
|
|
49291
|
+
ViewAutomationContent$1,
|
|
49292
|
+
{
|
|
49293
|
+
automationId,
|
|
49294
|
+
existingAutomation,
|
|
49295
|
+
children
|
|
49296
|
+
}
|
|
49297
|
+
) });
|
|
49148
49298
|
};
|
|
49149
49299
|
const ViewAutomationContent$1 = ({ automationId, existingAutomation, children }) => {
|
|
49150
49300
|
useAutomationFetching(automationId);
|
|
@@ -49288,22 +49438,29 @@ const ActionButtons = ({
|
|
|
49288
49438
|
)
|
|
49289
49439
|
] }) });
|
|
49290
49440
|
};
|
|
49291
|
-
const BigSelector = ({
|
|
49441
|
+
const BigSelector = ({
|
|
49442
|
+
onClick,
|
|
49443
|
+
title: title2,
|
|
49444
|
+
subtitle,
|
|
49445
|
+
icon,
|
|
49446
|
+
selected,
|
|
49447
|
+
disabled = false,
|
|
49448
|
+
hideSelectedText = false
|
|
49449
|
+
}) => {
|
|
49292
49450
|
return /* @__PURE__ */ jsxs(
|
|
49293
49451
|
"button",
|
|
49294
49452
|
{
|
|
49295
49453
|
onClick,
|
|
49296
|
-
className: `relative flex flex-col items-center justify-center rounded-lg border-2 p-6 transition-all duration-300 ease-in-out hover:shadow-lg ${selected ? "border-
|
|
49454
|
+
className: `relative flex flex-col items-center justify-center rounded-lg border-2 p-6 transition-all duration-300 ease-in-out hover:shadow-lg ${selected ? "[border-color:hsl(var(--reach-primary))] shadow-lg" : "border-gray-200 "} ${disabled ? "opacity-50 cursor-not-allowed hover:shadow-none" : "hover:scale-[1.04] scale-[1.02]"} ${!selected && !disabled && "hover:[border-color:hsl(var(--reach-primary))] hover:bg-gray-50"}`,
|
|
49297
49455
|
children: [
|
|
49298
49456
|
icon,
|
|
49299
49457
|
/* @__PURE__ */ jsxs("div", { className: "text-center mt-3", children: [
|
|
49300
49458
|
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium text-primary", children: title2 }),
|
|
49301
49459
|
/* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground mt-1", children: subtitle })
|
|
49302
49460
|
] }),
|
|
49303
|
-
selected &&
|
|
49304
|
-
|
|
49305
|
-
/* @__PURE__ */ jsx(
|
|
49306
|
-
/* @__PURE__ */ jsx("span", { className: "text-card text-xs hidden md:inline", children: "Selected" })
|
|
49461
|
+
selected && /* @__PURE__ */ jsxs("div", { className: "absolute top-1 right-1 bg-card rounded-full px-3 py-1 flex items-center gap-1", children: [
|
|
49462
|
+
/* @__PURE__ */ jsx(Check, { className: "w-4 h-4 text-card-foreground" }),
|
|
49463
|
+
!hideSelectedText && /* @__PURE__ */ jsx("span", { className: "text-card-foreground text-xs hidden md:inline", children: "Selected" })
|
|
49307
49464
|
] })
|
|
49308
49465
|
]
|
|
49309
49466
|
}
|
|
@@ -49468,6 +49625,7 @@ const statusArchived = "reach-styles-module__statusArchived___XlN-L";
|
|
|
49468
49625
|
const segmentAllUsers = "reach-styles-module__segmentAllUsers___1aXpc";
|
|
49469
49626
|
const segmentManaged = "reach-styles-module__segmentManaged___o0gOu";
|
|
49470
49627
|
const segmentCustom = "reach-styles-module__segmentCustom___xc3lG";
|
|
49628
|
+
const beta = "reach-styles-module__beta___n9qPf";
|
|
49471
49629
|
const styles$5 = {
|
|
49472
49630
|
base: base$4,
|
|
49473
49631
|
"default": "reach-styles-module__default___zeGU1",
|
|
@@ -49494,7 +49652,8 @@ const styles$5 = {
|
|
|
49494
49652
|
statusArchived,
|
|
49495
49653
|
segmentAllUsers,
|
|
49496
49654
|
segmentManaged,
|
|
49497
|
-
segmentCustom
|
|
49655
|
+
segmentCustom,
|
|
49656
|
+
beta
|
|
49498
49657
|
};
|
|
49499
49658
|
const badgeVariants = cva([styles$5.base], {
|
|
49500
49659
|
variants: {
|
|
@@ -49514,11 +49673,14 @@ const badgeVariants = cva([styles$5.base], {
|
|
|
49514
49673
|
segmentAllUsers: styles$5.segmentAllUsers,
|
|
49515
49674
|
segmentManaged: styles$5.segmentManaged,
|
|
49516
49675
|
segmentCustom: styles$5.segmentCustom,
|
|
49676
|
+
// Not real since we'll never show it
|
|
49677
|
+
segmentOneOff: styles$5.segmentManaged,
|
|
49517
49678
|
statusScheduled: styles$5.statusScheduled,
|
|
49518
49679
|
statusQueued: styles$5.statusQueued,
|
|
49519
49680
|
statusPartiallyCancelled: styles$5.statusPartiallyCancelled,
|
|
49520
49681
|
statusCancelled: styles$5.statusCancelled,
|
|
49521
|
-
statusArchived: styles$5.statusArchived
|
|
49682
|
+
statusArchived: styles$5.statusArchived,
|
|
49683
|
+
beta: styles$5.beta
|
|
49522
49684
|
},
|
|
49523
49685
|
size: {
|
|
49524
49686
|
default: styles$5.sizeDefault,
|
|
@@ -67053,6 +67215,8 @@ const getTypeDescription = (type) => {
|
|
|
67053
67215
|
return `System-defined ${t$2("engage:segment").toLowerCase()} that are not editable or deletable.`;
|
|
67054
67216
|
case BusinessSegmentTypeEnum.CUSTOM:
|
|
67055
67217
|
return `Custom ${t$2("engage:segment").toLowerCase()} that you can edit and delete as needed.`;
|
|
67218
|
+
case BusinessSegmentTypeEnum.ONE_OFF:
|
|
67219
|
+
return `One-off ${t$2("engage:segment").toLowerCase()} that is not editable or deletable.`;
|
|
67056
67220
|
default:
|
|
67057
67221
|
throw UnreachableCaseStatement(type, BusinessSegmentTypeEnum);
|
|
67058
67222
|
}
|
|
@@ -67065,6 +67229,8 @@ const getSegmentTypeVariant = (type) => {
|
|
|
67065
67229
|
return "segmentManaged";
|
|
67066
67230
|
case BusinessSegmentTypeEnum.CUSTOM:
|
|
67067
67231
|
return "segmentCustom";
|
|
67232
|
+
case BusinessSegmentTypeEnum.ONE_OFF:
|
|
67233
|
+
return "segmentOneOff";
|
|
67068
67234
|
default:
|
|
67069
67235
|
throw UnreachableCaseStatement(type, BusinessSegmentTypeEnum);
|
|
67070
67236
|
}
|
|
@@ -67100,7 +67266,9 @@ function createNameColumn(nameAccessor = "name", headerText, showDescription = f
|
|
|
67100
67266
|
const typeDotStyles = {
|
|
67101
67267
|
[BusinessSegmentTypeEnum.ALL_USERS]: "bg-purple-500",
|
|
67102
67268
|
[BusinessSegmentTypeEnum.MANAGED]: "bg-teal-500",
|
|
67103
|
-
[BusinessSegmentTypeEnum.CUSTOM]: "bg-amber-500"
|
|
67269
|
+
[BusinessSegmentTypeEnum.CUSTOM]: "bg-amber-500",
|
|
67270
|
+
// Not real since we'll never show it
|
|
67271
|
+
[BusinessSegmentTypeEnum.ONE_OFF]: "bg-gray-500"
|
|
67104
67272
|
};
|
|
67105
67273
|
const dotColor = type ? typeDotStyles[type] : status ? badgeStyles[status] : "bg-blue-500";
|
|
67106
67274
|
return /* @__PURE__ */ jsx("div", { className: "w-full flex gap-6 justify-between items-center", children: /* @__PURE__ */ jsxs("div", { className: "flex gap-1 items-center w-full", children: [
|
|
@@ -67478,16 +67646,16 @@ const AttributionDialogContent = () => {
|
|
|
67478
67646
|
return /* @__PURE__ */ jsxs(
|
|
67479
67647
|
motion.div,
|
|
67480
67648
|
{
|
|
67481
|
-
className: "space-y-8 p-
|
|
67649
|
+
className: "space-y-8 p-2",
|
|
67482
67650
|
variants: containerVariants,
|
|
67483
67651
|
initial: "hidden",
|
|
67484
67652
|
animate: "visible",
|
|
67485
67653
|
children: [
|
|
67486
|
-
/* @__PURE__ */ jsxs(motion.div, { className: "
|
|
67654
|
+
/* @__PURE__ */ jsxs(motion.div, { className: "space-y-3", variants: itemVariants, children: [
|
|
67487
67655
|
/* @__PURE__ */ jsxs(
|
|
67488
67656
|
motion.h2,
|
|
67489
67657
|
{
|
|
67490
|
-
className: "text-2xl font-semibold flex items-center justify-
|
|
67658
|
+
className: "text-2xl font-semibold flex items-center justify-start gap-2",
|
|
67491
67659
|
initial: { scale: 0.9 },
|
|
67492
67660
|
animate: { scale: 1 },
|
|
67493
67661
|
transition: { duration: 0.5, ease: "easeOut" },
|
|
@@ -67621,6 +67789,41 @@ const AttributionDialogContent = () => {
|
|
|
67621
67789
|
] })
|
|
67622
67790
|
] }, scenario.id)) }) })
|
|
67623
67791
|
] }),
|
|
67792
|
+
/* @__PURE__ */ jsxs(Card, { children: [
|
|
67793
|
+
/* @__PURE__ */ jsxs(CardHeader, { children: [
|
|
67794
|
+
/* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center gap-2", children: [
|
|
67795
|
+
/* @__PURE__ */ jsx(Eye, { className: "h-5 w-5" }),
|
|
67796
|
+
'Understanding "Unknown" Revenue'
|
|
67797
|
+
] }),
|
|
67798
|
+
/* @__PURE__ */ jsx(CardDescription, { children: "Sometimes purchases can't be attributed to specific marketing touchpoints" })
|
|
67799
|
+
] }),
|
|
67800
|
+
/* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
|
|
67801
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: `Revenue appears as "Unknown" when we can't connect a purchase to any marketing touchpoint within our 90-day attribution window. Here are common scenarios:` }),
|
|
67802
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
67803
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
|
|
67804
|
+
/* @__PURE__ */ jsx("div", { className: "w-2 h-2 rounded-full bg-amber-500 mt-2 flex-shrink-0" }),
|
|
67805
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
67806
|
+
/* @__PURE__ */ jsx("h5", { className: "font-medium text-sm", children: "Attribution Window Expired" }),
|
|
67807
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Customer clicked an ad and purchased 91+ days later, outside our tracking window" })
|
|
67808
|
+
] })
|
|
67809
|
+
] }),
|
|
67810
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
|
|
67811
|
+
/* @__PURE__ */ jsx("div", { className: "w-2 h-2 rounded-full bg-amber-500 mt-2 flex-shrink-0" }),
|
|
67812
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
67813
|
+
/* @__PURE__ */ jsx("h5", { className: "font-medium text-sm", children: "Identity Mismatch" }),
|
|
67814
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Customer used different email/phone or didn't provide contact information when they visited your site vs. when they made the purchase." })
|
|
67815
|
+
] })
|
|
67816
|
+
] }),
|
|
67817
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
|
|
67818
|
+
/* @__PURE__ */ jsx("div", { className: "w-2 h-2 rounded-full bg-amber-500 mt-2 flex-shrink-0" }),
|
|
67819
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
67820
|
+
/* @__PURE__ */ jsx("h5", { className: "font-medium text-sm", children: "Technical Limitations" }),
|
|
67821
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Ad blockers, privacy settings, or technical issues prevented tracking" })
|
|
67822
|
+
] })
|
|
67823
|
+
] })
|
|
67824
|
+
] })
|
|
67825
|
+
] })
|
|
67826
|
+
] }),
|
|
67624
67827
|
/* @__PURE__ */ jsx(Card, { className: "bg-blue-50 border-blue-200", children: /* @__PURE__ */ jsx(CardContent, { className: "pt-6", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
|
|
67625
67828
|
/* @__PURE__ */ jsx(Clock, { className: "h-5 w-5 text-blue-600 mt-0.5 flex-shrink-0" }),
|
|
67626
67829
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
@@ -67729,7 +67932,7 @@ const InfoTooltip = ({
|
|
|
67729
67932
|
onClick: handleAttributionClick,
|
|
67730
67933
|
variant: "ghost",
|
|
67731
67934
|
size: "sm",
|
|
67732
|
-
className: "flex justify-start w-full items-start gap-2 text-xs text-blue-400 hover:text-blue-200 hover:bg-transparent underline my-1 py-2 px-0 h-auto text-pretty",
|
|
67935
|
+
className: "flex justify-start w-full items-start gap-2 text-xs text-blue-400 hover:text-blue-200 hover:bg-transparent underline my-1 py-2 px-0 h-auto text-pretty text-left",
|
|
67733
67936
|
children: [
|
|
67734
67937
|
/* @__PURE__ */ jsx(ExternalLink, { className: "text-blue-400 h-3 w-3" }),
|
|
67735
67938
|
t3("measure.dashboard.methodology.tooltip")
|
|
@@ -90204,9 +90407,9 @@ var ChannelType = /* @__PURE__ */ ((ChannelType2) => {
|
|
|
90204
90407
|
return ChannelType2;
|
|
90205
90408
|
})(ChannelType || {});
|
|
90206
90409
|
const HEIGHT_BUFFER = 10;
|
|
90207
|
-
const CHECK_DELAYS = [0, 100, 500];
|
|
90410
|
+
const CHECK_DELAYS = [0, 100, 500, 1e3, 2e3];
|
|
90208
90411
|
const DEFAULT_EMAIL_PREVIEW_HEIGHT = 400;
|
|
90209
|
-
const EMAIL_PREVIEW_HEIGHT_CALCULATION_TIMEOUT =
|
|
90412
|
+
const EMAIL_PREVIEW_HEIGHT_CALCULATION_TIMEOUT = 5e3;
|
|
90210
90413
|
const SMS_LIMITS = {
|
|
90211
90414
|
RECOMMENDED_LIMIT: 320
|
|
90212
90415
|
};
|
|
@@ -90267,53 +90470,146 @@ const createHeightMonitor = () => {
|
|
|
90267
90470
|
return `
|
|
90268
90471
|
(function() {
|
|
90269
90472
|
let lastHeight = 0;
|
|
90473
|
+
let checkCount = 0;
|
|
90474
|
+
const MAX_CHECKS = 20; // Prevent infinite loops
|
|
90270
90475
|
|
|
90271
|
-
// Calculate max height from various measurements
|
|
90476
|
+
// Calculate max height from various measurements with better error handling
|
|
90272
90477
|
function getContentHeight() {
|
|
90273
|
-
|
|
90274
|
-
|
|
90275
|
-
body
|
|
90276
|
-
|
|
90277
|
-
|
|
90278
|
-
|
|
90279
|
-
|
|
90280
|
-
|
|
90478
|
+
try {
|
|
90479
|
+
const { body, documentElement: html } = document;
|
|
90480
|
+
if (!body || !html) {
|
|
90481
|
+
return 0;
|
|
90482
|
+
}
|
|
90483
|
+
|
|
90484
|
+
const measurements = [
|
|
90485
|
+
body.scrollHeight,
|
|
90486
|
+
body.offsetHeight,
|
|
90487
|
+
html.clientHeight,
|
|
90488
|
+
html.scrollHeight,
|
|
90489
|
+
html.offsetHeight
|
|
90490
|
+
].filter(h => h > 0 && isFinite(h));
|
|
90491
|
+
|
|
90492
|
+
if (measurements.length === 0) {
|
|
90493
|
+
console.warn('HeightMonitor: No valid height measurements found');
|
|
90494
|
+
return 0;
|
|
90495
|
+
}
|
|
90496
|
+
|
|
90497
|
+
return Math.max(...measurements);
|
|
90498
|
+
} catch (error) {
|
|
90499
|
+
console.warn('HeightMonitor: Error calculating height', error);
|
|
90500
|
+
return 0;
|
|
90501
|
+
}
|
|
90281
90502
|
}
|
|
90282
90503
|
|
|
90283
90504
|
function reportHeight() {
|
|
90284
|
-
|
|
90285
|
-
|
|
90286
|
-
|
|
90287
|
-
|
|
90288
|
-
|
|
90289
|
-
|
|
90290
|
-
|
|
90505
|
+
try {
|
|
90506
|
+
const height = getContentHeight();
|
|
90507
|
+
if (height > 0 && height !== lastHeight) {
|
|
90508
|
+
lastHeight = height;
|
|
90509
|
+
window.parent.postMessage({
|
|
90510
|
+
type: 'IFRAME_HEIGHT_UPDATE',
|
|
90511
|
+
height: height + ${HEIGHT_BUFFER}
|
|
90512
|
+
}, '*');
|
|
90513
|
+
}
|
|
90514
|
+
} catch (error) {
|
|
90515
|
+
console.warn('HeightMonitor: Error reporting height', error);
|
|
90516
|
+
}
|
|
90517
|
+
}
|
|
90518
|
+
|
|
90519
|
+
// Enhanced height monitoring with multiple strategies
|
|
90520
|
+
function setupHeightMonitoring() {
|
|
90521
|
+
try {
|
|
90522
|
+
// Strategy 1: ResizeObserver for real-time monitoring
|
|
90523
|
+
if (window.ResizeObserver) {
|
|
90524
|
+
const observer = new ResizeObserver(() => {
|
|
90525
|
+
requestAnimationFrame(() => {
|
|
90526
|
+
reportHeight();
|
|
90527
|
+
checkCount++;
|
|
90528
|
+
});
|
|
90529
|
+
});
|
|
90530
|
+
observer.observe(document.body);
|
|
90531
|
+
observer.observe(document.documentElement);
|
|
90532
|
+
} else {
|
|
90533
|
+
console.warn('HeightMonitor: ResizeObserver not available, using fallback');
|
|
90534
|
+
}
|
|
90535
|
+
|
|
90536
|
+
// Strategy 2: Handle image loading with better error handling
|
|
90537
|
+
const images = document.querySelectorAll('img');
|
|
90538
|
+
images.forEach(img => {
|
|
90539
|
+
if (!img.complete) {
|
|
90540
|
+
img.addEventListener('load', () => {
|
|
90541
|
+
setTimeout(reportHeight, 100); // Small delay to ensure layout is complete
|
|
90542
|
+
});
|
|
90543
|
+
img.addEventListener('error', () => {
|
|
90544
|
+
setTimeout(reportHeight, 100);
|
|
90545
|
+
});
|
|
90546
|
+
}
|
|
90547
|
+
});
|
|
90548
|
+
|
|
90549
|
+
// Strategy 3: Watch for DOM changes with throttling
|
|
90550
|
+
let mutationTimeout;
|
|
90551
|
+
new MutationObserver(() => {
|
|
90552
|
+
if (mutationTimeout) clearTimeout(mutationTimeout);
|
|
90553
|
+
mutationTimeout = setTimeout(() => {
|
|
90554
|
+
requestAnimationFrame(reportHeight);
|
|
90555
|
+
checkCount++;
|
|
90556
|
+
}, 100); // Throttle mutations
|
|
90557
|
+
}).observe(document.body, {
|
|
90558
|
+
childList: true,
|
|
90559
|
+
subtree: true,
|
|
90560
|
+
attributes: true,
|
|
90561
|
+
attributeFilter: ['style', 'class']
|
|
90562
|
+
});
|
|
90563
|
+
|
|
90564
|
+
// Strategy 4: Periodic checks with exponential backoff
|
|
90565
|
+
let checkDelay = 100;
|
|
90566
|
+
const periodicCheck = () => {
|
|
90567
|
+
if (checkCount >= MAX_CHECKS) {
|
|
90568
|
+
console.warn('HeightMonitor: Max checks reached, stopping periodic checks');
|
|
90569
|
+
return;
|
|
90570
|
+
}
|
|
90571
|
+
|
|
90572
|
+
reportHeight();
|
|
90573
|
+
checkCount++;
|
|
90574
|
+
|
|
90575
|
+
// Exponential backoff for periodic checks
|
|
90576
|
+
checkDelay = Math.min(checkDelay * 1.5, 2000);
|
|
90577
|
+
setTimeout(periodicCheck, checkDelay);
|
|
90578
|
+
};
|
|
90579
|
+
|
|
90580
|
+
// Start periodic checks after initial setup
|
|
90581
|
+
setTimeout(periodicCheck, 500);
|
|
90582
|
+
|
|
90583
|
+
} catch (error) {
|
|
90584
|
+
console.warn('HeightMonitor: Error setting up monitoring', error);
|
|
90291
90585
|
}
|
|
90292
90586
|
}
|
|
90293
90587
|
|
|
90294
|
-
//
|
|
90295
|
-
if (
|
|
90296
|
-
|
|
90297
|
-
|
|
90298
|
-
|
|
90588
|
+
// Initial setup with multiple triggers
|
|
90589
|
+
if (document.readyState === 'loading') {
|
|
90590
|
+
document.addEventListener('DOMContentLoaded', setupHeightMonitoring);
|
|
90591
|
+
} else {
|
|
90592
|
+
setupHeightMonitoring();
|
|
90299
90593
|
}
|
|
90300
90594
|
|
|
90301
|
-
|
|
90302
|
-
|
|
90303
|
-
|
|
90304
|
-
|
|
90305
|
-
|
|
90306
|
-
}
|
|
90595
|
+
window.addEventListener('load', () => {
|
|
90596
|
+
setTimeout(() => {
|
|
90597
|
+
reportHeight();
|
|
90598
|
+
checkCount++;
|
|
90599
|
+
}, 100);
|
|
90307
90600
|
});
|
|
90308
90601
|
|
|
90309
|
-
// Watch for DOM changes
|
|
90310
|
-
new MutationObserver(() => requestAnimationFrame(reportHeight))
|
|
90311
|
-
.observe(document.body, { childList: true, subtree: true });
|
|
90312
|
-
|
|
90313
90602
|
// Initial checks with progressive delays
|
|
90314
|
-
|
|
90315
|
-
|
|
90316
|
-
|
|
90603
|
+
${CHECK_DELAYS.map((delay2) => `setTimeout(() => { reportHeight(); checkCount++; }, ${delay2});`).join("\n ")}
|
|
90604
|
+
|
|
90605
|
+
// Final fallback check
|
|
90606
|
+
setTimeout(() => {
|
|
90607
|
+
if (lastHeight === 0) {
|
|
90608
|
+
console.warn('HeightMonitor: No height reported, forcing final check');
|
|
90609
|
+
reportHeight();
|
|
90610
|
+
}
|
|
90611
|
+
}, 4000);
|
|
90612
|
+
|
|
90317
90613
|
})();
|
|
90318
90614
|
`;
|
|
90319
90615
|
};
|
|
@@ -90321,9 +90617,16 @@ const EmailPreviewHtmlRenderer = ({
|
|
|
90321
90617
|
html,
|
|
90322
90618
|
onHeightChange
|
|
90323
90619
|
}) => {
|
|
90324
|
-
const iframeRef = useRef(null);
|
|
90325
90620
|
const timeoutRef = useRef();
|
|
90326
90621
|
const [state, setState] = useState({ type: "loading" });
|
|
90622
|
+
const [iframeElement, setIframeElement] = useState(
|
|
90623
|
+
null
|
|
90624
|
+
);
|
|
90625
|
+
const setIframeRef = useCallback((element) => {
|
|
90626
|
+
if (element) {
|
|
90627
|
+
setIframeElement(element);
|
|
90628
|
+
}
|
|
90629
|
+
}, []);
|
|
90327
90630
|
const communicationGroup = useCommunicationGroup();
|
|
90328
90631
|
const { getMergeFields: getMergeFields2, isGetting: isGettingMergeFields } = useGetMergeFields(
|
|
90329
90632
|
communicationGroup?.id ?? void 0
|
|
@@ -90348,6 +90651,24 @@ const EmailPreviewHtmlRenderer = ({
|
|
|
90348
90651
|
},
|
|
90349
90652
|
[onHeightChange]
|
|
90350
90653
|
);
|
|
90654
|
+
const handleFallback = useCallback(() => {
|
|
90655
|
+
setState({ type: "error", fallbackHeight: DEFAULT_EMAIL_PREVIEW_HEIGHT });
|
|
90656
|
+
handleHeightUpdate(DEFAULT_EMAIL_PREVIEW_HEIGHT);
|
|
90657
|
+
}, [handleHeightUpdate]);
|
|
90658
|
+
const estimateHeightFromContent = useCallback((htmlContent) => {
|
|
90659
|
+
try {
|
|
90660
|
+
const lines = htmlContent.split("\n").length;
|
|
90661
|
+
const estimatedHeight = Math.max(200, Math.min(800, lines * 20));
|
|
90662
|
+
return estimatedHeight;
|
|
90663
|
+
} catch (error2) {
|
|
90664
|
+
return DEFAULT_EMAIL_PREVIEW_HEIGHT;
|
|
90665
|
+
}
|
|
90666
|
+
}, []);
|
|
90667
|
+
const forceStateChange = useCallback(() => {
|
|
90668
|
+
const estimatedHeight = estimateHeightFromContent(prettyHtml);
|
|
90669
|
+
setState({ type: "error", fallbackHeight: estimatedHeight });
|
|
90670
|
+
handleHeightUpdate(estimatedHeight);
|
|
90671
|
+
}, [prettyHtml, estimateHeightFromContent, handleHeightUpdate]);
|
|
90351
90672
|
useEffect(() => {
|
|
90352
90673
|
if (prettyHtml) {
|
|
90353
90674
|
setState({ type: "calculating" });
|
|
@@ -90357,68 +90678,83 @@ const EmailPreviewHtmlRenderer = ({
|
|
|
90357
90678
|
}
|
|
90358
90679
|
}, [prettyHtml]);
|
|
90359
90680
|
useEffect(() => {
|
|
90360
|
-
if (!prettyHtml || !
|
|
90361
|
-
|
|
90681
|
+
if (!prettyHtml || !iframeElement) {
|
|
90682
|
+
return;
|
|
90683
|
+
}
|
|
90684
|
+
if (state.type === "ready") {
|
|
90685
|
+
return;
|
|
90686
|
+
}
|
|
90687
|
+
const iframe = iframeElement;
|
|
90688
|
+
const timeoutDuration = Math.max(
|
|
90689
|
+
EMAIL_PREVIEW_HEIGHT_CALCULATION_TIMEOUT,
|
|
90690
|
+
5e3
|
|
90691
|
+
);
|
|
90362
90692
|
timeoutRef.current = setTimeout(() => {
|
|
90363
|
-
|
|
90364
|
-
|
|
90365
|
-
|
|
90693
|
+
handleFallback();
|
|
90694
|
+
}, timeoutDuration);
|
|
90695
|
+
const aggressiveTimeout = setTimeout(() => {
|
|
90696
|
+
if (state.type === "calculating") {
|
|
90697
|
+
forceStateChange();
|
|
90698
|
+
}
|
|
90699
|
+
}, 1e4);
|
|
90700
|
+
const estimatedHeight = estimateHeightFromContent(prettyHtml);
|
|
90366
90701
|
const setupHeightMonitoring = () => {
|
|
90367
90702
|
try {
|
|
90368
90703
|
const doc2 = iframe.contentDocument || iframe.contentWindow?.document;
|
|
90369
90704
|
if (!doc2) {
|
|
90370
|
-
setState({
|
|
90371
|
-
|
|
90372
|
-
fallbackHeight: DEFAULT_EMAIL_PREVIEW_HEIGHT
|
|
90373
|
-
});
|
|
90705
|
+
setState({ type: "error", fallbackHeight: estimatedHeight });
|
|
90706
|
+
handleHeightUpdate(estimatedHeight);
|
|
90374
90707
|
return;
|
|
90375
90708
|
}
|
|
90376
90709
|
const injectStyles2 = () => {
|
|
90377
|
-
|
|
90378
|
-
|
|
90379
|
-
|
|
90380
|
-
|
|
90381
|
-
|
|
90382
|
-
|
|
90383
|
-
|
|
90384
|
-
|
|
90385
|
-
|
|
90386
|
-
|
|
90387
|
-
.
|
|
90388
|
-
|
|
90389
|
-
|
|
90390
|
-
|
|
90391
|
-
|
|
90392
|
-
|
|
90393
|
-
|
|
90394
|
-
|
|
90395
|
-
|
|
90396
|
-
|
|
90397
|
-
|
|
90398
|
-
|
|
90399
|
-
|
|
90400
|
-
|
|
90401
|
-
|
|
90402
|
-
|
|
90403
|
-
|
|
90404
|
-
|
|
90405
|
-
|
|
90406
|
-
|
|
90407
|
-
|
|
90408
|
-
|
|
90409
|
-
|
|
90410
|
-
|
|
90411
|
-
|
|
90412
|
-
|
|
90413
|
-
|
|
90414
|
-
|
|
90415
|
-
|
|
90416
|
-
|
|
90417
|
-
|
|
90418
|
-
|
|
90419
|
-
|
|
90420
|
-
|
|
90421
|
-
|
|
90710
|
+
try {
|
|
90711
|
+
const existingStyles = doc2.querySelectorAll(
|
|
90712
|
+
"style[data-merge-field-pills]"
|
|
90713
|
+
);
|
|
90714
|
+
existingStyles.forEach((style22) => style22.remove());
|
|
90715
|
+
const style2 = doc2.createElement("style");
|
|
90716
|
+
style2.textContent = "html, body { height: auto !important; min-height: 0 !important; }";
|
|
90717
|
+
doc2.head.appendChild(style2);
|
|
90718
|
+
const pillStyle = doc2.createElement("style");
|
|
90719
|
+
pillStyle.setAttribute("data-merge-field-pills", "true");
|
|
90720
|
+
pillStyle.textContent = `
|
|
90721
|
+
.merge-field-pill {
|
|
90722
|
+
display: inline-block !important;
|
|
90723
|
+
padding: 4px 8px !important;
|
|
90724
|
+
border-radius: 6px !important;
|
|
90725
|
+
background: #f3f4f6 !important;
|
|
90726
|
+
color: #6b7280 !important;
|
|
90727
|
+
font-size: 0.875rem !important;
|
|
90728
|
+
border: 1px solid #e5e7eb !important;
|
|
90729
|
+
font-weight: 500 !important;
|
|
90730
|
+
margin: 0 2px !important;
|
|
90731
|
+
vertical-align: middle !important;
|
|
90732
|
+
line-height: 1.2 !important;
|
|
90733
|
+
white-space: nowrap !important;
|
|
90734
|
+
box-sizing: border-box !important;
|
|
90735
|
+
}
|
|
90736
|
+
|
|
90737
|
+
/* Ensure pills are visible even with conflicting styles */
|
|
90738
|
+
span.merge-field-pill {
|
|
90739
|
+
display: inline-block !important;
|
|
90740
|
+
background: #f3f4f6 !important;
|
|
90741
|
+
color: #6b7280 !important;
|
|
90742
|
+
border: 1px solid #e5e7eb !important;
|
|
90743
|
+
}
|
|
90744
|
+
|
|
90745
|
+
/* Force override any inherited styles */
|
|
90746
|
+
* .merge-field-pill {
|
|
90747
|
+
display: inline-block !important;
|
|
90748
|
+
background: #f3f4f6 !important;
|
|
90749
|
+
color: #6b7280 !important;
|
|
90750
|
+
border: 1px solid #e5e7eb !important;
|
|
90751
|
+
padding: 4px 8px !important;
|
|
90752
|
+
border-radius: 6px !important;
|
|
90753
|
+
}
|
|
90754
|
+
`;
|
|
90755
|
+
doc2.head.appendChild(pillStyle);
|
|
90756
|
+
} catch (styleError) {
|
|
90757
|
+
}
|
|
90422
90758
|
};
|
|
90423
90759
|
if (doc2.readyState === "complete" || doc2.readyState === "interactive") {
|
|
90424
90760
|
injectStyles2();
|
|
@@ -90426,14 +90762,57 @@ const EmailPreviewHtmlRenderer = ({
|
|
|
90426
90762
|
doc2.addEventListener("DOMContentLoaded", injectStyles2);
|
|
90427
90763
|
doc2.addEventListener("load", injectStyles2);
|
|
90428
90764
|
}
|
|
90429
|
-
|
|
90430
|
-
|
|
90431
|
-
|
|
90765
|
+
try {
|
|
90766
|
+
const script = doc2.createElement("script");
|
|
90767
|
+
script.textContent = createHeightMonitor();
|
|
90768
|
+
doc2.body.appendChild(script);
|
|
90769
|
+
setTimeout(() => {
|
|
90770
|
+
if (state.type === "calculating") {
|
|
90771
|
+
try {
|
|
90772
|
+
const iframeDoc = iframe.contentDocument || iframe.contentWindow?.document;
|
|
90773
|
+
if (iframeDoc) {
|
|
90774
|
+
const bodyHeight = iframeDoc.body?.scrollHeight || iframeDoc.body?.offsetHeight;
|
|
90775
|
+
if (bodyHeight && bodyHeight > 0) {
|
|
90776
|
+
handleHeightUpdate(bodyHeight + 10);
|
|
90777
|
+
} else {
|
|
90778
|
+
setState({
|
|
90779
|
+
type: "error",
|
|
90780
|
+
fallbackHeight: estimatedHeight
|
|
90781
|
+
});
|
|
90782
|
+
handleHeightUpdate(estimatedHeight);
|
|
90783
|
+
}
|
|
90784
|
+
}
|
|
90785
|
+
} catch (directError) {
|
|
90786
|
+
setState({ type: "error", fallbackHeight: estimatedHeight });
|
|
90787
|
+
handleHeightUpdate(estimatedHeight);
|
|
90788
|
+
}
|
|
90789
|
+
}
|
|
90790
|
+
}, 2e3);
|
|
90791
|
+
} catch (scriptError) {
|
|
90792
|
+
setTimeout(() => {
|
|
90793
|
+
try {
|
|
90794
|
+
const iframeDoc = iframe.contentDocument || iframe.contentWindow?.document;
|
|
90795
|
+
if (iframeDoc) {
|
|
90796
|
+
const bodyHeight = iframeDoc.body?.scrollHeight || iframeDoc.body?.offsetHeight;
|
|
90797
|
+
if (bodyHeight && bodyHeight > 0) {
|
|
90798
|
+
handleHeightUpdate(bodyHeight + 10);
|
|
90799
|
+
} else {
|
|
90800
|
+
setState({ type: "error", fallbackHeight: estimatedHeight });
|
|
90801
|
+
handleHeightUpdate(estimatedHeight);
|
|
90802
|
+
}
|
|
90803
|
+
} else {
|
|
90804
|
+
setState({ type: "error", fallbackHeight: estimatedHeight });
|
|
90805
|
+
handleHeightUpdate(estimatedHeight);
|
|
90806
|
+
}
|
|
90807
|
+
} catch (error2) {
|
|
90808
|
+
setState({ type: "error", fallbackHeight: estimatedHeight });
|
|
90809
|
+
handleHeightUpdate(estimatedHeight);
|
|
90810
|
+
}
|
|
90811
|
+
}, 1e3);
|
|
90812
|
+
}
|
|
90432
90813
|
} catch (error2) {
|
|
90433
|
-
setState({
|
|
90434
|
-
|
|
90435
|
-
fallbackHeight: DEFAULT_EMAIL_PREVIEW_HEIGHT
|
|
90436
|
-
});
|
|
90814
|
+
setState({ type: "error", fallbackHeight: estimatedHeight });
|
|
90815
|
+
handleHeightUpdate(estimatedHeight);
|
|
90437
90816
|
}
|
|
90438
90817
|
};
|
|
90439
90818
|
const handleHeightMessage = (event) => {
|
|
@@ -90448,20 +90827,49 @@ const EmailPreviewHtmlRenderer = ({
|
|
|
90448
90827
|
}
|
|
90449
90828
|
};
|
|
90450
90829
|
const handleError = () => {
|
|
90451
|
-
setState({ type: "error", fallbackHeight:
|
|
90830
|
+
setState({ type: "error", fallbackHeight: estimatedHeight });
|
|
90831
|
+
handleHeightUpdate(estimatedHeight);
|
|
90452
90832
|
};
|
|
90453
|
-
|
|
90833
|
+
const handleLoad = () => {
|
|
90834
|
+
setupHeightMonitoring();
|
|
90835
|
+
};
|
|
90836
|
+
iframe.addEventListener("load", handleLoad);
|
|
90454
90837
|
iframe.addEventListener("error", handleError);
|
|
90455
90838
|
window.addEventListener("message", handleHeightMessage);
|
|
90839
|
+
setTimeout(() => {
|
|
90840
|
+
if (state.type === "calculating") {
|
|
90841
|
+
try {
|
|
90842
|
+
const iframeDoc = iframe.contentDocument || iframe.contentWindow?.document;
|
|
90843
|
+
if (iframeDoc && iframeDoc.readyState === "complete") {
|
|
90844
|
+
setupHeightMonitoring();
|
|
90845
|
+
} else {
|
|
90846
|
+
setState({ type: "error", fallbackHeight: estimatedHeight });
|
|
90847
|
+
handleHeightUpdate(estimatedHeight);
|
|
90848
|
+
}
|
|
90849
|
+
} catch (error2) {
|
|
90850
|
+
setState({ type: "error", fallbackHeight: estimatedHeight });
|
|
90851
|
+
handleHeightUpdate(estimatedHeight);
|
|
90852
|
+
}
|
|
90853
|
+
}
|
|
90854
|
+
}, 1e3);
|
|
90456
90855
|
return () => {
|
|
90457
|
-
iframe.removeEventListener("load",
|
|
90856
|
+
iframe.removeEventListener("load", handleLoad);
|
|
90458
90857
|
iframe.removeEventListener("error", handleError);
|
|
90459
90858
|
window.removeEventListener("message", handleHeightMessage);
|
|
90460
90859
|
if (timeoutRef.current) {
|
|
90461
90860
|
clearTimeout(timeoutRef.current);
|
|
90462
90861
|
}
|
|
90862
|
+
clearTimeout(aggressiveTimeout);
|
|
90463
90863
|
};
|
|
90464
|
-
}, [
|
|
90864
|
+
}, [
|
|
90865
|
+
prettyHtml,
|
|
90866
|
+
handleHeightUpdate,
|
|
90867
|
+
handleFallback,
|
|
90868
|
+
forceStateChange,
|
|
90869
|
+
estimateHeightFromContent,
|
|
90870
|
+
state.type,
|
|
90871
|
+
iframeElement
|
|
90872
|
+
]);
|
|
90465
90873
|
if (isGettingMergeFields && getMergeFields2 === void 0) {
|
|
90466
90874
|
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-5", children: /* @__PURE__ */ jsx(BasicLoader, { text: "Fetching merge fields..." }) });
|
|
90467
90875
|
}
|
|
@@ -90474,7 +90882,7 @@ const EmailPreviewHtmlRenderer = ({
|
|
|
90474
90882
|
/* @__PURE__ */ jsx(
|
|
90475
90883
|
"iframe",
|
|
90476
90884
|
{
|
|
90477
|
-
ref:
|
|
90885
|
+
ref: setIframeRef,
|
|
90478
90886
|
title: "Email Preview",
|
|
90479
90887
|
srcDoc: prettyHtml,
|
|
90480
90888
|
className: "w-full block",
|
|
@@ -90542,32 +90950,32 @@ const EmailPreviewHtmlRenderer = ({
|
|
|
90542
90950
|
) })
|
|
90543
90951
|
] });
|
|
90544
90952
|
};
|
|
90545
|
-
const HELP_TOPICS = [
|
|
90546
|
-
{
|
|
90547
|
-
id: "dynamic-content",
|
|
90548
|
-
title: "Dynamic Content",
|
|
90549
|
-
image: "https://cdn.embedreach.com/assets/engage/merge-tags-demo.gif",
|
|
90550
|
-
imageAlt: "Merge Tags Demo",
|
|
90551
|
-
imageDesc: "Demonstration: Adding merge tags to personalize your emails",
|
|
90552
|
-
selectorTitle: "Dynamic Content",
|
|
90553
|
-
selectorSubtitle: "Dynamic content is a way to insert dynamic content into your email like name, email, or other details.",
|
|
90554
|
-
selectorIcon: /* @__PURE__ */ jsx(Merge, {})
|
|
90555
|
-
},
|
|
90556
|
-
{
|
|
90557
|
-
id: "responsive-design",
|
|
90558
|
-
title: "Responsive Design",
|
|
90559
|
-
image: "https://cdn.embedreach.com/assets/engage/layout-mobile-desktop.gif",
|
|
90560
|
-
imageAlt: "Mobile Desktop Switch Demo",
|
|
90561
|
-
imageDesc: "Demonstration: Switching between mobile and desktop preview modes",
|
|
90562
|
-
selectorTitle: "Responsive Design",
|
|
90563
|
-
selectorSubtitle: "Switch between mobile and desktop preview modes to ensure your emails look great on all devices.",
|
|
90564
|
-
selectorIcon: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
90565
|
-
/* @__PURE__ */ jsx(Smartphone, { className: "w-4 h-4" }),
|
|
90566
|
-
/* @__PURE__ */ jsx(Monitor, { className: "w-4 h-4" })
|
|
90567
|
-
] })
|
|
90568
|
-
}
|
|
90569
|
-
];
|
|
90570
90953
|
const EmailPreviewHelpDialog = () => {
|
|
90954
|
+
const HELP_TOPICS = [
|
|
90955
|
+
{
|
|
90956
|
+
id: "dynamic-content",
|
|
90957
|
+
title: "Dynamic Content",
|
|
90958
|
+
image: "https://cdn.embedreach.com/assets/engage/merge-tags-demo.gif",
|
|
90959
|
+
imageAlt: `${t$2("engage:merge_field")} Demo`,
|
|
90960
|
+
imageDesc: `Demonstration: Adding ${t$2("engage:merge_field").toLowerCase()} to personalize your emails`,
|
|
90961
|
+
selectorTitle: "Dynamic Content",
|
|
90962
|
+
selectorSubtitle: "Dynamic content is a way to insert dynamic content into your email like name, email, or other details.",
|
|
90963
|
+
selectorIcon: /* @__PURE__ */ jsx(Merge, {})
|
|
90964
|
+
},
|
|
90965
|
+
{
|
|
90966
|
+
id: "responsive-design",
|
|
90967
|
+
title: "Responsive Design",
|
|
90968
|
+
image: "https://cdn.embedreach.com/assets/engage/layout-mobile-desktop.gif",
|
|
90969
|
+
imageAlt: "Mobile Desktop Switch Demo",
|
|
90970
|
+
imageDesc: "Demonstration: Switching between mobile and desktop preview modes",
|
|
90971
|
+
selectorTitle: "Responsive Design",
|
|
90972
|
+
selectorSubtitle: "Switch between mobile and desktop preview modes to ensure your emails look great on all devices.",
|
|
90973
|
+
selectorIcon: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
90974
|
+
/* @__PURE__ */ jsx(Smartphone, { className: "w-4 h-4" }),
|
|
90975
|
+
/* @__PURE__ */ jsx(Monitor, { className: "w-4 h-4" })
|
|
90976
|
+
] })
|
|
90977
|
+
}
|
|
90978
|
+
];
|
|
90571
90979
|
const { toggleEmailHelpDialog: toggleEmailHelpDialog2, data: business } = useBusiness$1();
|
|
90572
90980
|
const { toast: toast2 } = useToast();
|
|
90573
90981
|
const [selectedTopic, setSelectedTopic] = useState("dynamic-content");
|
|
@@ -90578,7 +90986,7 @@ const EmailPreviewHelpDialog = () => {
|
|
|
90578
90986
|
});
|
|
90579
90987
|
};
|
|
90580
90988
|
const shouldShowDontShowAgainButton = business?.uiDefaults?.emailHelpDialogShow !== false;
|
|
90581
|
-
const topic = HELP_TOPICS.find((
|
|
90989
|
+
const topic = HELP_TOPICS.find((t22) => t22.id === selectedTopic) ?? HELP_TOPICS[0];
|
|
90582
90990
|
return /* @__PURE__ */ jsxs("div", { className: "p-6 overflow-y-auto", children: [
|
|
90583
90991
|
/* @__PURE__ */ jsxs("div", { className: "mb-8 text-center", children: [
|
|
90584
90992
|
/* @__PURE__ */ jsx("h2", { className: "text-2xl font-semibold mb-2", children: "Email Editor Help Center" }),
|
|
@@ -90609,16 +91017,16 @@ const EmailPreviewHelpDialog = () => {
|
|
|
90609
91017
|
},
|
|
90610
91018
|
topic.id
|
|
90611
91019
|
) }) }),
|
|
90612
|
-
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4 sm:flex-row sm:gap-6 max-w-xl mx-auto", children: HELP_TOPICS.map((
|
|
91020
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4 sm:flex-row sm:gap-6 max-w-xl mx-auto", children: HELP_TOPICS.map((t22) => /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
|
|
90613
91021
|
BigSelector,
|
|
90614
91022
|
{
|
|
90615
|
-
onClick: () => setSelectedTopic(
|
|
90616
|
-
title:
|
|
90617
|
-
subtitle:
|
|
90618
|
-
icon:
|
|
90619
|
-
selected: selectedTopic ===
|
|
91023
|
+
onClick: () => setSelectedTopic(t22.id),
|
|
91024
|
+
title: t22.selectorTitle,
|
|
91025
|
+
subtitle: t22.selectorSubtitle,
|
|
91026
|
+
icon: t22.selectorIcon,
|
|
91027
|
+
selected: selectedTopic === t22.id
|
|
90620
91028
|
}
|
|
90621
|
-
) },
|
|
91029
|
+
) }, t22.id)) }),
|
|
90622
91030
|
shouldShowDontShowAgainButton && /* @__PURE__ */ jsx("div", { className: "flex justify-center pt-4", children: /* @__PURE__ */ jsx(Button$1, { size: "sm", onClick: handleDontShowAgain, children: "Don't show me again" }) })
|
|
90623
91031
|
] });
|
|
90624
91032
|
};
|
|
@@ -90781,6 +91189,17 @@ const StripoEditor = ({ containerRef, stripoDialogDimensions, showSaving }) => {
|
|
|
90781
91189
|
}
|
|
90782
91190
|
});
|
|
90783
91191
|
});
|
|
91192
|
+
const mergeTagsElements = shadowRoot.querySelectorAll(
|
|
91193
|
+
"span.service-element.caption.ng-star-inserted"
|
|
91194
|
+
);
|
|
91195
|
+
mergeTagsElements.forEach((element) => {
|
|
91196
|
+
const htmlElement = element;
|
|
91197
|
+
if (htmlElement.textContent?.trim() === "Merge Tags") {
|
|
91198
|
+
htmlElement.textContent = t$2("engage:merge_field", {
|
|
91199
|
+
count: 2
|
|
91200
|
+
});
|
|
91201
|
+
}
|
|
91202
|
+
});
|
|
90784
91203
|
};
|
|
90785
91204
|
let shadowObserver = null;
|
|
90786
91205
|
const setupShadowObserver = () => {
|
|
@@ -90928,115 +91347,174 @@ const StripoWrapper = ({
|
|
|
90928
91347
|
mergeFieldsResponse,
|
|
90929
91348
|
cancelClicked,
|
|
90930
91349
|
setCancelClicked,
|
|
90931
|
-
actionId
|
|
91350
|
+
actionId,
|
|
91351
|
+
onEditorReadyChange
|
|
90932
91352
|
}) => {
|
|
91353
|
+
const [stripoEmailSaved, setStripoEmailSaved] = useState(false);
|
|
91354
|
+
const [stripoEmailCompiled, setStripoEmailCompiled] = useState(false);
|
|
91355
|
+
const [isEditorReady, setIsEditorReady] = useState(false);
|
|
90933
91356
|
const stripoOpenedOnce = useRef(false);
|
|
90934
91357
|
const containerRef = useRef(null);
|
|
90935
|
-
const
|
|
91358
|
+
const editorReadyCheckInterval = useRef(null);
|
|
91359
|
+
const {
|
|
91360
|
+
data: template,
|
|
91361
|
+
isLoading: isTemplateLoading,
|
|
91362
|
+
error: templateError
|
|
91363
|
+
} = useStripoTemplateForActionId({
|
|
90936
91364
|
automationId: automation2.id,
|
|
90937
91365
|
actionId
|
|
90938
91366
|
});
|
|
90939
|
-
const {
|
|
90940
|
-
|
|
90941
|
-
|
|
91367
|
+
const {
|
|
91368
|
+
data: editorData,
|
|
91369
|
+
isLoading: isEditorDataLoading,
|
|
91370
|
+
error: editorDataError
|
|
91371
|
+
} = useStripoEditorData();
|
|
90942
91372
|
const { updateCommunicationGroup: updateCommunicationGroup2 } = useUpdateCommunicationGroup();
|
|
91373
|
+
const checkEditorReady = useCallback(() => {
|
|
91374
|
+
const isReady = !!(window.StripoEditorApi?.actionsApi && typeof window.StripoEditorApi.actionsApi.save === "function" && typeof window.StripoEditorApi.actionsApi.compileEmail === "function");
|
|
91375
|
+
if (isReady && !isEditorReady) {
|
|
91376
|
+
setIsEditorReady(true);
|
|
91377
|
+
onEditorReadyChange?.(true);
|
|
91378
|
+
if (editorReadyCheckInterval.current) {
|
|
91379
|
+
clearInterval(editorReadyCheckInterval.current);
|
|
91380
|
+
editorReadyCheckInterval.current = null;
|
|
91381
|
+
}
|
|
91382
|
+
}
|
|
91383
|
+
return isReady;
|
|
91384
|
+
}, [isEditorReady, onEditorReadyChange]);
|
|
90943
91385
|
const resetAndCloseEditor = useCallback(() => {
|
|
90944
91386
|
setSaveClicked(false);
|
|
90945
91387
|
setCancelClicked(false);
|
|
90946
91388
|
setStripoEmailSaved(false);
|
|
90947
91389
|
setStripoEmailCompiled(false);
|
|
91390
|
+
setIsEditorReady(false);
|
|
91391
|
+
onEditorReadyChange?.(false);
|
|
90948
91392
|
setShowStripoEditor(false);
|
|
91393
|
+
if (editorReadyCheckInterval.current) {
|
|
91394
|
+
clearInterval(editorReadyCheckInterval.current);
|
|
91395
|
+
editorReadyCheckInterval.current = null;
|
|
91396
|
+
}
|
|
90949
91397
|
}, [
|
|
90950
91398
|
setSaveClicked,
|
|
90951
91399
|
setCancelClicked,
|
|
90952
91400
|
setStripoEmailSaved,
|
|
90953
91401
|
setStripoEmailCompiled,
|
|
91402
|
+
setIsEditorReady,
|
|
91403
|
+
onEditorReadyChange,
|
|
90954
91404
|
setShowStripoEditor
|
|
90955
91405
|
]);
|
|
90956
|
-
|
|
90957
|
-
if (
|
|
90958
|
-
|
|
90959
|
-
|
|
90960
|
-
|
|
90961
|
-
|
|
90962
|
-
|
|
90963
|
-
|
|
90964
|
-
|
|
90965
|
-
|
|
90966
|
-
|
|
91406
|
+
const executeSave = useCallback(async () => {
|
|
91407
|
+
if (!isEditorReady) {
|
|
91408
|
+
console.warn("Save operation blocked - editor not ready yet");
|
|
91409
|
+
return;
|
|
91410
|
+
}
|
|
91411
|
+
if (!window.StripoEditorApi?.actionsApi || !template?.communicationGroupId) {
|
|
91412
|
+
console.warn("Save operation blocked - preconditions not met");
|
|
91413
|
+
return;
|
|
91414
|
+
}
|
|
91415
|
+
try {
|
|
91416
|
+
const saveOperation = () => new Promise((resolve, reject) => {
|
|
91417
|
+
const compileEmailCallback = async function(error2, html) {
|
|
91418
|
+
if (error2) {
|
|
91419
|
+
reject(new Error(`Compile failed: ${error2}`));
|
|
91420
|
+
return;
|
|
91421
|
+
}
|
|
91422
|
+
try {
|
|
91423
|
+
await updateCommunicationGroup2({
|
|
91424
|
+
groupId: template.communicationGroupId,
|
|
91425
|
+
params: { emailHtmlBody: html }
|
|
91426
|
+
});
|
|
91427
|
+
} catch (err) {
|
|
91428
|
+
reject(err);
|
|
90967
91429
|
}
|
|
91430
|
+
setStripoEmailCompiled(true);
|
|
91431
|
+
resolve();
|
|
91432
|
+
};
|
|
91433
|
+
const saveCallback = function(error2) {
|
|
91434
|
+
if (error2) {
|
|
91435
|
+
reject(new Error(`Save failed: ${error2}`));
|
|
91436
|
+
return;
|
|
91437
|
+
}
|
|
91438
|
+
setStripoEmailSaved(true);
|
|
91439
|
+
};
|
|
91440
|
+
window.StripoEditorApi.actionsApi.compileEmail({
|
|
91441
|
+
callback: compileEmailCallback,
|
|
91442
|
+
minimize: true,
|
|
91443
|
+
mergeTags: [],
|
|
91444
|
+
forceAmp: false,
|
|
91445
|
+
resetDataSavedFlag: false,
|
|
91446
|
+
disableLineHeightsReplace: true
|
|
90968
91447
|
});
|
|
90969
|
-
|
|
90970
|
-
};
|
|
90971
|
-
window.StripoEditorApi.actionsApi.compileEmail({
|
|
90972
|
-
callback: compileEmailCallback,
|
|
90973
|
-
minimize: true,
|
|
90974
|
-
mergeTags: [],
|
|
90975
|
-
forceAmp: false,
|
|
90976
|
-
resetDataSavedFlag: false,
|
|
90977
|
-
disableLineHeightsReplace: true
|
|
91448
|
+
window.StripoEditorApi.actionsApi.save(saveCallback);
|
|
90978
91449
|
});
|
|
90979
|
-
|
|
90980
|
-
|
|
90981
|
-
|
|
90982
|
-
return;
|
|
90983
|
-
}
|
|
90984
|
-
setStripoEmailSaved(true);
|
|
90985
|
-
};
|
|
90986
|
-
window.StripoEditorApi.actionsApi.save(saveCallback);
|
|
91450
|
+
await saveOperation();
|
|
91451
|
+
} catch (error2) {
|
|
91452
|
+
console.error("Save operation failed:", error2);
|
|
90987
91453
|
}
|
|
90988
|
-
}, [
|
|
90989
|
-
saveClicked,
|
|
90990
|
-
containerRef,
|
|
90991
|
-
setSaveClicked,
|
|
90992
|
-
setShowStripoEditor,
|
|
90993
|
-
template,
|
|
90994
|
-
updateCommunicationGroup2
|
|
90995
|
-
]);
|
|
91454
|
+
}, [template, updateCommunicationGroup2, isEditorReady]);
|
|
90996
91455
|
useEffect(() => {
|
|
90997
|
-
|
|
90998
|
-
|
|
90999
|
-
|
|
91000
|
-
|
|
91001
|
-
|
|
91002
|
-
|
|
91003
|
-
|
|
91004
|
-
|
|
91005
|
-
|
|
91456
|
+
if (saveClicked && isEditorReady) {
|
|
91457
|
+
executeSave();
|
|
91458
|
+
} else if (saveClicked && !isEditorReady) {
|
|
91459
|
+
console.warn("Save clicked but editor not ready - ignoring save request");
|
|
91460
|
+
setSaveClicked(false);
|
|
91461
|
+
}
|
|
91462
|
+
}, [saveClicked, executeSave, isEditorReady, setSaveClicked]);
|
|
91463
|
+
useEffect(() => {
|
|
91464
|
+
if (stripoEmailSaved && stripoEmailCompiled || showStripoEditor === false) {
|
|
91465
|
+
resetAndCloseEditor();
|
|
91466
|
+
}
|
|
91006
91467
|
}, [
|
|
91007
91468
|
stripoEmailSaved,
|
|
91008
91469
|
stripoEmailCompiled,
|
|
91009
91470
|
showStripoEditor,
|
|
91010
|
-
setShowStripoEditor,
|
|
91011
|
-
setSaveClicked,
|
|
91012
91471
|
resetAndCloseEditor
|
|
91013
91472
|
]);
|
|
91014
91473
|
useEffect(() => {
|
|
91015
91474
|
if (cancelClicked) {
|
|
91016
|
-
if (window.UIEditor && window.UIEditor.removeEditor && typeof window.UIEditor.removeEditor === "function") {
|
|
91017
|
-
window.UIEditor.removeEditor();
|
|
91018
|
-
}
|
|
91019
91475
|
resetAndCloseEditor();
|
|
91020
91476
|
}
|
|
91021
91477
|
}, [cancelClicked, resetAndCloseEditor]);
|
|
91022
91478
|
useEffect(() => {
|
|
91023
|
-
if (editorData?.businessId && containerRef.current && template) {
|
|
91024
|
-
|
|
91025
|
-
|
|
91026
|
-
|
|
91027
|
-
|
|
91028
|
-
|
|
91029
|
-
|
|
91030
|
-
|
|
91031
|
-
|
|
91032
|
-
|
|
91033
|
-
|
|
91034
|
-
|
|
91035
|
-
|
|
91036
|
-
|
|
91037
|
-
|
|
91479
|
+
if (editorData?.businessId && containerRef.current && template && !stripoOpenedOnce.current) {
|
|
91480
|
+
const initializeEditor = async () => {
|
|
91481
|
+
try {
|
|
91482
|
+
await initStripo({
|
|
91483
|
+
emailId: template.communicationGroupId,
|
|
91484
|
+
html: template.html || "<div></div>",
|
|
91485
|
+
css: template.css || "",
|
|
91486
|
+
container: containerRef.current,
|
|
91487
|
+
businessId: editorData.businessId,
|
|
91488
|
+
mergeFields: mergeFieldsResponse.mergeFields || [],
|
|
91489
|
+
forceRecreate: template.forceRecreate
|
|
91490
|
+
});
|
|
91491
|
+
stripoOpenedOnce.current = true;
|
|
91492
|
+
console.log(
|
|
91493
|
+
"Stripo initStripo completed, starting readiness check..."
|
|
91494
|
+
);
|
|
91495
|
+
editorReadyCheckInterval.current = setInterval(() => {
|
|
91496
|
+
checkEditorReady();
|
|
91497
|
+
}, 500);
|
|
91498
|
+
} catch (error2) {
|
|
91499
|
+
console.error("Failed to initialize Stripo editor:", error2);
|
|
91500
|
+
}
|
|
91501
|
+
};
|
|
91502
|
+
initializeEditor();
|
|
91038
91503
|
}
|
|
91039
|
-
}, [editorData, mergeFieldsResponse, template]);
|
|
91504
|
+
}, [editorData, mergeFieldsResponse, template, checkEditorReady]);
|
|
91505
|
+
useEffect(() => {
|
|
91506
|
+
return () => {
|
|
91507
|
+
if (editorReadyCheckInterval.current) {
|
|
91508
|
+
clearInterval(editorReadyCheckInterval.current);
|
|
91509
|
+
}
|
|
91510
|
+
};
|
|
91511
|
+
}, []);
|
|
91512
|
+
if (templateError || editorDataError) {
|
|
91513
|
+
return /* @__PURE__ */ jsxs("div", { className: "w-full h-full flex flex-col items-center justify-center", children: [
|
|
91514
|
+
/* @__PURE__ */ jsx("div", { className: "text-red-500 mb-4", children: "Failed to load editor data" }),
|
|
91515
|
+
/* @__PURE__ */ jsx(Button$1, { onClick: () => window.location.reload(), variant: "outline", children: "Retry" })
|
|
91516
|
+
] });
|
|
91517
|
+
}
|
|
91040
91518
|
if (isTemplateLoading || isEditorDataLoading || !editorData || !template) {
|
|
91041
91519
|
return /* @__PURE__ */ jsx("div", { className: "w-full h-full flex flex-col items-center justify-center", children: /* @__PURE__ */ jsx(BasicLoader, { text: ["Loading editor..."] }) });
|
|
91042
91520
|
}
|
|
@@ -91045,7 +91523,7 @@ const StripoWrapper = ({
|
|
|
91045
91523
|
{
|
|
91046
91524
|
containerRef,
|
|
91047
91525
|
stripoDialogDimensions,
|
|
91048
|
-
showSaving: saveClicked
|
|
91526
|
+
showSaving: saveClicked && isEditorReady
|
|
91049
91527
|
}
|
|
91050
91528
|
) });
|
|
91051
91529
|
};
|
|
@@ -91091,6 +91569,7 @@ const EmailPreview = ({
|
|
|
91091
91569
|
const [showStripoEditor, setShowStripoEditor] = useState(false);
|
|
91092
91570
|
const [saveClicked, setSaveClicked] = useState(false);
|
|
91093
91571
|
const [cancelClicked, setCancelClicked] = useState(false);
|
|
91572
|
+
const [isEditorReady, setIsEditorReady] = useState(false);
|
|
91094
91573
|
const [fromName, setFromName] = useState("");
|
|
91095
91574
|
const [replyToEmail, setReplyToEmail] = useState("");
|
|
91096
91575
|
const [showHelpDialog, setShowHelpDialog] = useState(null);
|
|
@@ -91310,6 +91789,7 @@ const EmailPreview = ({
|
|
|
91310
91789
|
{
|
|
91311
91790
|
onClick: () => setSaveClicked(true),
|
|
91312
91791
|
className: "text-sm px-3 py-1 rounded",
|
|
91792
|
+
disabled: !isEditorReady,
|
|
91313
91793
|
children: "Save"
|
|
91314
91794
|
}
|
|
91315
91795
|
)
|
|
@@ -91327,7 +91807,8 @@ const EmailPreview = ({
|
|
|
91327
91807
|
setSaveClicked,
|
|
91328
91808
|
stripoDialogDimensions,
|
|
91329
91809
|
mergeFieldsResponse,
|
|
91330
|
-
actionId: selectedActionId
|
|
91810
|
+
actionId: selectedActionId,
|
|
91811
|
+
onEditorReadyChange: setIsEditorReady
|
|
91331
91812
|
}
|
|
91332
91813
|
)
|
|
91333
91814
|
] })
|
|
@@ -94237,6 +94718,7 @@ var ENGAGE_STEPS = /* @__PURE__ */ ((ENGAGE_STEPS2) => {
|
|
|
94237
94718
|
ENGAGE_STEPS2["BUSINESS"] = "business";
|
|
94238
94719
|
ENGAGE_STEPS2["EMAIL"] = "email";
|
|
94239
94720
|
ENGAGE_STEPS2["SMS"] = "sms";
|
|
94721
|
+
ENGAGE_STEPS2["MERGE_FIELDS"] = "merge-fields";
|
|
94240
94722
|
ENGAGE_STEPS2["SPLASH"] = "splash";
|
|
94241
94723
|
ENGAGE_STEPS2["BUSINESS_SKIP_INTERSTITIAL"] = "business-skip-interstitial";
|
|
94242
94724
|
ENGAGE_STEPS2["SMS_INTERSTITIAL"] = "sms-interstitial";
|
|
@@ -94254,6 +94736,7 @@ const ENGAGE_STRINGS = {
|
|
|
94254
94736
|
BUSINESS_INFORMATION_TITLE: "Business Information",
|
|
94255
94737
|
EMAIL_CHANNEL_TITLE: "Email Channel",
|
|
94256
94738
|
SMS_CHANNEL_TITLE: "SMS Channel",
|
|
94739
|
+
MERGE_FIELDS_TITLE: "Merge Fields",
|
|
94257
94740
|
// Step titles - Onboarding mode
|
|
94258
94741
|
BRAND_ONBOARDING_TITLE: "Customize Your Brand",
|
|
94259
94742
|
BUSINESS_ONBOARDING_TITLE: "Business Settings",
|
|
@@ -94292,7 +94775,11 @@ const SHARED_STEP_CONFIGS = {
|
|
|
94292
94775
|
[
|
|
94293
94776
|
"sms"
|
|
94294
94777
|
/* SMS */
|
|
94295
|
-
]: { label: ENGAGE_STRINGS.SMS_CHANNEL_TITLE }
|
|
94778
|
+
]: { label: ENGAGE_STRINGS.SMS_CHANNEL_TITLE },
|
|
94779
|
+
[
|
|
94780
|
+
"merge-fields"
|
|
94781
|
+
/* MERGE_FIELDS */
|
|
94782
|
+
]: { label: ENGAGE_STRINGS.MERGE_FIELDS_TITLE }
|
|
94296
94783
|
};
|
|
94297
94784
|
const SETTINGS_STEP_CONFIGS = [
|
|
94298
94785
|
{
|
|
@@ -94322,6 +94809,13 @@ const SETTINGS_STEP_CONFIGS = [
|
|
|
94322
94809
|
"sms"
|
|
94323
94810
|
/* SMS */
|
|
94324
94811
|
].label
|
|
94812
|
+
},
|
|
94813
|
+
{
|
|
94814
|
+
key: "merge-fields",
|
|
94815
|
+
label: SHARED_STEP_CONFIGS[
|
|
94816
|
+
"merge-fields"
|
|
94817
|
+
/* MERGE_FIELDS */
|
|
94818
|
+
].label
|
|
94325
94819
|
}
|
|
94326
94820
|
];
|
|
94327
94821
|
const ONBOARDING_STEP_CONFIGS = [
|
|
@@ -94353,6 +94847,13 @@ const ONBOARDING_STEP_CONFIGS = [
|
|
|
94353
94847
|
/* SMS */
|
|
94354
94848
|
].label
|
|
94355
94849
|
},
|
|
94850
|
+
{
|
|
94851
|
+
key: "merge-fields",
|
|
94852
|
+
label: SHARED_STEP_CONFIGS[
|
|
94853
|
+
"merge-fields"
|
|
94854
|
+
/* MERGE_FIELDS */
|
|
94855
|
+
].label
|
|
94856
|
+
},
|
|
94356
94857
|
{
|
|
94357
94858
|
key: "completion",
|
|
94358
94859
|
label: ENGAGE_STRINGS.COMPLETION_TITLE
|
|
@@ -94892,6 +95393,20 @@ function extractBase64Data(dataUrl) {
|
|
|
94892
95393
|
}
|
|
94893
95394
|
return parts[1];
|
|
94894
95395
|
}
|
|
95396
|
+
const capitalize = (str) => {
|
|
95397
|
+
if (!str) return str;
|
|
95398
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
95399
|
+
};
|
|
95400
|
+
const getMergeFieldsFromUrl = (url, getMergeFields2) => {
|
|
95401
|
+
if (!url || !getMergeFields2) return [];
|
|
95402
|
+
const regex = /\{\{([^}]+)\}\}/g;
|
|
95403
|
+
const matches2 = [...url.matchAll(regex)];
|
|
95404
|
+
return matches2.map((match2) => {
|
|
95405
|
+
const mergeFieldValue = match2[1];
|
|
95406
|
+
const mergeField = getMergeFields2.mergeFields?.flatMap((f2) => f2.entries).find((entry) => entry.value === `{{${mergeFieldValue}}}`);
|
|
95407
|
+
return mergeField ? mergeField.label : mergeFieldValue;
|
|
95408
|
+
}).filter(Boolean);
|
|
95409
|
+
};
|
|
94895
95410
|
const convertToHtml = (text2, mergeFields, variant) => {
|
|
94896
95411
|
if (!text2) return "";
|
|
94897
95412
|
const regex = /\{\{.*?\}\}/g;
|
|
@@ -94955,13 +95470,28 @@ const SMSPreview = ({ body, imageUrls }) => {
|
|
|
94955
95470
|
const { getMergeFields: getMergeFields2, isGetting } = useGetMergeFields(
|
|
94956
95471
|
communicationGroup?.id ?? void 0
|
|
94957
95472
|
);
|
|
95473
|
+
const hasMergeFieldsInUrl = React__default.useCallback((url) => {
|
|
95474
|
+
return /\{\{[^}]+\}\}/.test(url);
|
|
95475
|
+
}, []);
|
|
94958
95476
|
if (isGetting || getMergeFields2 === void 0) {
|
|
94959
95477
|
return null;
|
|
94960
95478
|
}
|
|
94961
95479
|
return /* @__PURE__ */ jsx("div", { className: "sms-preview-outer @container", children: /* @__PURE__ */ jsxs("div", { className: "sms-phone-mockup", children: [
|
|
94962
95480
|
/* @__PURE__ */ jsx("div", { className: "sms-phone-notch" }),
|
|
94963
95481
|
/* @__PURE__ */ jsxs("div", { className: "sms-phone-inner", children: [
|
|
94964
|
-
imageUrls && imageUrls.length > 0 && imageUrls.map((url, idx) => /* @__PURE__ */ jsx("div", { className: "sms-message-row", children: /* @__PURE__ */ jsx("div", { className: "sms-message-bubble", children: /* @__PURE__ */ jsx(
|
|
95482
|
+
imageUrls && imageUrls.length > 0 && imageUrls.map((url, idx) => /* @__PURE__ */ jsx("div", { className: "sms-message-row", children: /* @__PURE__ */ jsx("div", { className: "sms-message-bubble", children: hasMergeFieldsInUrl(url) ? /* @__PURE__ */ jsx("div", { className: "sms-message-image-placeholder", children: /* @__PURE__ */ jsxs("div", { className: "text-center text-white text-[10px] leading-tight", children: [
|
|
95483
|
+
/* @__PURE__ */ jsx("div", { className: "font-medium mb-1", children: "Image will be populated at send time based on the following merge fields:" }),
|
|
95484
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1 justify-center", children: getMergeFieldsFromUrl(url, getMergeFields2).map(
|
|
95485
|
+
(fieldName, fieldIndex) => /* @__PURE__ */ jsx(
|
|
95486
|
+
"span",
|
|
95487
|
+
{
|
|
95488
|
+
className: "inline-flex items-center px-1 py-0.5 rounded text-[10px] bg-green-500/30 text-white font-medium border border-green-400/40",
|
|
95489
|
+
children: fieldName
|
|
95490
|
+
},
|
|
95491
|
+
fieldIndex
|
|
95492
|
+
)
|
|
95493
|
+
) })
|
|
95494
|
+
] }) }) : /* @__PURE__ */ jsx(
|
|
94965
95495
|
"img",
|
|
94966
95496
|
{
|
|
94967
95497
|
src: url,
|
|
@@ -97321,9 +97851,16 @@ const SMSEditor = ({
|
|
|
97321
97851
|
initialImageUrls,
|
|
97322
97852
|
imageBase64,
|
|
97323
97853
|
isUpdating,
|
|
97324
|
-
hasUnsavedChanges
|
|
97854
|
+
hasUnsavedChanges,
|
|
97855
|
+
communicationGroupId
|
|
97325
97856
|
}) => {
|
|
97326
97857
|
const [characterCount, setCharacterCount] = useState(0);
|
|
97858
|
+
const [isAddImagePopoverOpen, setIsAddImagePopoverOpen] = useState(false);
|
|
97859
|
+
const [isUrlDialogOpen, setIsUrlDialogOpen] = useState(false);
|
|
97860
|
+
const [imageUrl, setImageUrl] = useState("");
|
|
97861
|
+
const [isSavingUrl, setIsSavingUrl] = useState(false);
|
|
97862
|
+
const { updateCommunicationGroup: updateCommunicationGroup2 } = useUpdateCommunicationGroup();
|
|
97863
|
+
const { toast: toast2 } = useToast();
|
|
97327
97864
|
const allMergeFields = useMemo(
|
|
97328
97865
|
() => mergeFieldsResponse?.mergeFields?.flatMap((f2) => f2.entries) ?? [],
|
|
97329
97866
|
[mergeFieldsResponse]
|
|
@@ -97398,6 +97935,43 @@ const SMSEditor = ({
|
|
|
97398
97935
|
characterCount,
|
|
97399
97936
|
maxLength
|
|
97400
97937
|
);
|
|
97938
|
+
const handleAddImageFromFile = useCallback(() => {
|
|
97939
|
+
setIsAddImagePopoverOpen(false);
|
|
97940
|
+
onAddImage?.();
|
|
97941
|
+
}, [onAddImage]);
|
|
97942
|
+
const handleAddImageFromUrl = useCallback(() => {
|
|
97943
|
+
setIsAddImagePopoverOpen(false);
|
|
97944
|
+
setIsUrlDialogOpen(true);
|
|
97945
|
+
}, []);
|
|
97946
|
+
const handleUrlSubmit = useCallback(async () => {
|
|
97947
|
+
if (!imageUrl.trim() || !communicationGroupId) {
|
|
97948
|
+
return;
|
|
97949
|
+
}
|
|
97950
|
+
setIsSavingUrl(true);
|
|
97951
|
+
try {
|
|
97952
|
+
await updateCommunicationGroup2({
|
|
97953
|
+
groupId: communicationGroupId,
|
|
97954
|
+
params: {
|
|
97955
|
+
textMessageMediaUrls: [imageUrl.trim()]
|
|
97956
|
+
}
|
|
97957
|
+
});
|
|
97958
|
+
setImageUrl("");
|
|
97959
|
+
setIsUrlDialogOpen(false);
|
|
97960
|
+
toast2({
|
|
97961
|
+
title: "Image URL added",
|
|
97962
|
+
description: "The image URL has been added to your SMS message."
|
|
97963
|
+
});
|
|
97964
|
+
} catch (error2) {
|
|
97965
|
+
console.error("Failed to save image URL:", error2);
|
|
97966
|
+
toast2({
|
|
97967
|
+
title: "Failed to add image URL",
|
|
97968
|
+
description: "Please try again.",
|
|
97969
|
+
variant: "destructive"
|
|
97970
|
+
});
|
|
97971
|
+
} finally {
|
|
97972
|
+
setIsSavingUrl(false);
|
|
97973
|
+
}
|
|
97974
|
+
}, [imageUrl, communicationGroupId, updateCommunicationGroup2, toast2]);
|
|
97401
97975
|
if (!editor) {
|
|
97402
97976
|
return /* @__PURE__ */ jsx("div", { children: "Loading editor..." });
|
|
97403
97977
|
}
|
|
@@ -97413,15 +97987,98 @@ const SMSEditor = ({
|
|
|
97413
97987
|
disabled: isRemovingImage || isUpdatingCommunicationGroup,
|
|
97414
97988
|
children: "Remove Image"
|
|
97415
97989
|
}
|
|
97416
|
-
) : /* @__PURE__ */
|
|
97417
|
-
|
|
97990
|
+
) : /* @__PURE__ */ jsxs(
|
|
97991
|
+
Popover,
|
|
97418
97992
|
{
|
|
97419
|
-
|
|
97420
|
-
|
|
97421
|
-
|
|
97422
|
-
children:
|
|
97993
|
+
modal: true,
|
|
97994
|
+
open: isAddImagePopoverOpen,
|
|
97995
|
+
onOpenChange: setIsAddImagePopoverOpen,
|
|
97996
|
+
children: [
|
|
97997
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
97998
|
+
Button$1,
|
|
97999
|
+
{
|
|
98000
|
+
variant: "outline",
|
|
98001
|
+
disabled: (initialImageUrls?.length || 0) >= 1 || isRemovingImage || imageBase64 !== null || isUpdatingCommunicationGroup,
|
|
98002
|
+
className: "flex items-center gap-2",
|
|
98003
|
+
children: [
|
|
98004
|
+
"Add Image",
|
|
98005
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: "h-3 w-3" })
|
|
98006
|
+
]
|
|
98007
|
+
}
|
|
98008
|
+
) }),
|
|
98009
|
+
/* @__PURE__ */ jsx(PopoverContent, { className: "w-56 p-3 z-[100]", align: "start", children: /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
98010
|
+
/* @__PURE__ */ jsxs(
|
|
98011
|
+
Button$1,
|
|
98012
|
+
{
|
|
98013
|
+
variant: "ghost",
|
|
98014
|
+
size: "sm",
|
|
98015
|
+
onClick: handleAddImageFromFile,
|
|
98016
|
+
className: "w-full justify-start gap-2 h-9",
|
|
98017
|
+
children: [
|
|
98018
|
+
/* @__PURE__ */ jsx(Upload, { className: "h-4 w-4" }),
|
|
98019
|
+
"Upload from file"
|
|
98020
|
+
]
|
|
98021
|
+
}
|
|
98022
|
+
),
|
|
98023
|
+
/* @__PURE__ */ jsxs(
|
|
98024
|
+
Button$1,
|
|
98025
|
+
{
|
|
98026
|
+
variant: "ghost",
|
|
98027
|
+
size: "sm",
|
|
98028
|
+
onClick: handleAddImageFromUrl,
|
|
98029
|
+
className: "w-full justify-start gap-2 h-9",
|
|
98030
|
+
children: [
|
|
98031
|
+
/* @__PURE__ */ jsx(Link$1, { className: "h-4 w-4" }),
|
|
98032
|
+
"Add from URL"
|
|
98033
|
+
]
|
|
98034
|
+
}
|
|
98035
|
+
),
|
|
98036
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground pt-1 border-t", children: "Maximum file size: 5MB. We will try to compress the image if possible." })
|
|
98037
|
+
] }) })
|
|
98038
|
+
]
|
|
97423
98039
|
}
|
|
97424
98040
|
),
|
|
98041
|
+
/* @__PURE__ */ jsx(Dialog, { open: isUrlDialogOpen, onOpenChange: setIsUrlDialogOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-md", children: [
|
|
98042
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
98043
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: "Add Image from URL" }),
|
|
98044
|
+
/* @__PURE__ */ jsxs(DialogDescription, { children: [
|
|
98045
|
+
"Enter the URL of the image you want to add to your SMS message. You can use merge fields to make the URL dynamic (e.g., https://example.com/images/{{customer_name}}.jpg).",
|
|
98046
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
98047
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
98048
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Maximum file size: 5MB. We will try to compress the image if possible." })
|
|
98049
|
+
] })
|
|
98050
|
+
] }),
|
|
98051
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
98052
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
98053
|
+
/* @__PURE__ */ jsx(Label$1, { htmlFor: "image-url", children: "Image URL" }),
|
|
98054
|
+
/* @__PURE__ */ jsx(
|
|
98055
|
+
RichTextInputWithMergeFields,
|
|
98056
|
+
{
|
|
98057
|
+
value: imageUrl,
|
|
98058
|
+
onChange: setImageUrl,
|
|
98059
|
+
mergeFieldsResponse,
|
|
98060
|
+
placeholder: "https://example.com/image.jpg",
|
|
98061
|
+
className: "bg-background hover:bg-accent/50 focus:bg-accent transition-colors placeholder:text-muted-foreground/50",
|
|
98062
|
+
ariaLabel: "Insert merge field into image URL"
|
|
98063
|
+
}
|
|
98064
|
+
)
|
|
98065
|
+
] }),
|
|
98066
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
|
|
98067
|
+
/* @__PURE__ */ jsx(
|
|
98068
|
+
Button$1,
|
|
98069
|
+
{
|
|
98070
|
+
variant: "outline",
|
|
98071
|
+
onClick: () => {
|
|
98072
|
+
setImageUrl("");
|
|
98073
|
+
setIsUrlDialogOpen(false);
|
|
98074
|
+
},
|
|
98075
|
+
children: "Cancel"
|
|
98076
|
+
}
|
|
98077
|
+
),
|
|
98078
|
+
/* @__PURE__ */ jsx(Button$1, { onClick: handleUrlSubmit, disabled: isSavingUrl, children: isSavingUrl ? "Adding..." : "Add Image" })
|
|
98079
|
+
] })
|
|
98080
|
+
] })
|
|
98081
|
+
] }) }),
|
|
97425
98082
|
/* @__PURE__ */ jsx(
|
|
97426
98083
|
MultiSelectDialog,
|
|
97427
98084
|
{
|
|
@@ -97430,7 +98087,7 @@ const SMSEditor = ({
|
|
|
97430
98087
|
setSelectedValues: () => {
|
|
97431
98088
|
},
|
|
97432
98089
|
onValueChange: handleMergeFieldInsert,
|
|
97433
|
-
placeholder:
|
|
98090
|
+
placeholder: `Add ${t$2("engage:merge_field")}`,
|
|
97434
98091
|
title: "Merge Fields",
|
|
97435
98092
|
searchPlaceholder: "Search merge fields...",
|
|
97436
98093
|
emptyMessage: "No merge fields found",
|
|
@@ -97693,6 +98350,9 @@ const SMSEditorContent = ({
|
|
|
97693
98350
|
const { toast: toast2 } = useToast();
|
|
97694
98351
|
const { updateCommunicationGroup: updateCommunicationGroup2, isUpdating: isUpdatingCommunicationGroup } = useUpdateCommunicationGroup();
|
|
97695
98352
|
const { getMergeFields: getMergeFields2 } = useGetMergeFields(communicationGroupId);
|
|
98353
|
+
const hasMergeFieldsInUrl = useCallback((url) => {
|
|
98354
|
+
return /\{\{[^}]+\}\}/.test(url);
|
|
98355
|
+
}, []);
|
|
97696
98356
|
const [editingMessage, setEditingMessage] = useState(initialMessage);
|
|
97697
98357
|
const [imagePreview, setImagePreview] = useState(
|
|
97698
98358
|
initialImageUrls.length > 0 ? initialImageUrls[0] : null
|
|
@@ -97709,6 +98369,7 @@ const SMSEditorContent = ({
|
|
|
97709
98369
|
const lastSavedStateRef = useRef({
|
|
97710
98370
|
message: initialMessage
|
|
97711
98371
|
});
|
|
98372
|
+
const { communicationGroup } = useGetCommunicationGroup(communicationGroupId);
|
|
97712
98373
|
const debouncedMessage = useDebounce(editingMessage, 1e3);
|
|
97713
98374
|
const autoSave = useCallback(async () => {
|
|
97714
98375
|
if (isInitialMountRef.current) {
|
|
@@ -97826,6 +98487,16 @@ const SMSEditorContent = ({
|
|
|
97826
98487
|
if (fileInputRef.current) {
|
|
97827
98488
|
fileInputRef.current.value = "";
|
|
97828
98489
|
}
|
|
98490
|
+
const MAX_FILE_SIZE = 20 * 1024 * 1024;
|
|
98491
|
+
if (file.size > MAX_FILE_SIZE) {
|
|
98492
|
+
console.log("File too large", file.size, MAX_FILE_SIZE);
|
|
98493
|
+
toast2({
|
|
98494
|
+
title: "File too large",
|
|
98495
|
+
description: `Image must be 5MB or smaller. Your file is ${(file.size / (1024 * 1024)).toFixed(1)}MB.`,
|
|
98496
|
+
variant: "destructive"
|
|
98497
|
+
});
|
|
98498
|
+
return;
|
|
98499
|
+
}
|
|
97829
98500
|
setIsUploadingImage(true);
|
|
97830
98501
|
try {
|
|
97831
98502
|
const reader = new FileReader();
|
|
@@ -97833,19 +98504,40 @@ const SMSEditorContent = ({
|
|
|
97833
98504
|
try {
|
|
97834
98505
|
const pngDataUrl = await convertToPng(reader.result);
|
|
97835
98506
|
const base64String = extractBase64Data(pngDataUrl);
|
|
97836
|
-
|
|
97837
|
-
|
|
97838
|
-
|
|
97839
|
-
|
|
98507
|
+
updateCommunicationGroup2(
|
|
98508
|
+
{
|
|
98509
|
+
groupId: communicationGroupId,
|
|
98510
|
+
params: {
|
|
98511
|
+
textMessageMedia: [base64String]
|
|
98512
|
+
}
|
|
98513
|
+
},
|
|
98514
|
+
{
|
|
98515
|
+
onSuccess: () => {
|
|
98516
|
+
setImageBase64(base64String);
|
|
98517
|
+
setImagePreview(pngDataUrl);
|
|
98518
|
+
setIsRemovingImage(false);
|
|
98519
|
+
toast2({
|
|
98520
|
+
title: "Image uploaded",
|
|
98521
|
+
description: "The image has been added to your SMS"
|
|
98522
|
+
});
|
|
98523
|
+
},
|
|
98524
|
+
onError: (data) => {
|
|
98525
|
+
if (data.message.includes("Image is still too large")) {
|
|
98526
|
+
toast2({
|
|
98527
|
+
title: "Image too large",
|
|
98528
|
+
description: "The image is too large. Please try again with a smaller image.",
|
|
98529
|
+
variant: "destructive"
|
|
98530
|
+
});
|
|
98531
|
+
} else {
|
|
98532
|
+
toast2({
|
|
98533
|
+
title: "Error uploading image",
|
|
98534
|
+
description: "Failed to process or upload the image",
|
|
98535
|
+
variant: "destructive"
|
|
98536
|
+
});
|
|
98537
|
+
}
|
|
98538
|
+
}
|
|
97840
98539
|
}
|
|
97841
|
-
|
|
97842
|
-
setImageBase64(base64String);
|
|
97843
|
-
setImagePreview(pngDataUrl);
|
|
97844
|
-
setIsRemovingImage(false);
|
|
97845
|
-
toast2({
|
|
97846
|
-
title: "Image uploaded",
|
|
97847
|
-
description: "The image has been added to your SMS"
|
|
97848
|
-
});
|
|
98540
|
+
);
|
|
97849
98541
|
} catch (error2) {
|
|
97850
98542
|
console.error("Failed to convert or upload image:", error2);
|
|
97851
98543
|
toast2({
|
|
@@ -97877,6 +98569,22 @@ const SMSEditorContent = ({
|
|
|
97877
98569
|
return /* @__PURE__ */ jsx("div", { className: "flex justify-center items-center p-8", children: /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: "Loading editor..." }) });
|
|
97878
98570
|
}
|
|
97879
98571
|
return /* @__PURE__ */ jsxs("div", { className: cn$2("w-full @container", className), children: [
|
|
98572
|
+
!communicationGroup?.smsChannelSenderId && /* @__PURE__ */ jsx("div", { className: "mb-6 p-4 bg-amber-50 border border-amber-200 rounded-lg", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
|
|
98573
|
+
/* @__PURE__ */ jsx(
|
|
98574
|
+
InfoTooltip,
|
|
98575
|
+
{
|
|
98576
|
+
title: "SMS Sender Required",
|
|
98577
|
+
description: "You need to select an SMS sender before you can send SMS messages. Click 'Edit Sender & Company' above to configure your SMS sender.",
|
|
98578
|
+
alertText: "Action Required",
|
|
98579
|
+
size: "medium",
|
|
98580
|
+
iconColor: "text-amber-500"
|
|
98581
|
+
}
|
|
98582
|
+
),
|
|
98583
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
98584
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-medium text-amber-800 mb-1", children: "SMS Sender Not Selected" }),
|
|
98585
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-amber-700", children: 'Please select an SMS sender to enable SMS messaging. Click the "Edit Sender & Company" button to configure your sender.' })
|
|
98586
|
+
] })
|
|
98587
|
+
] }) }),
|
|
97880
98588
|
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-between mb-6", children: /* @__PURE__ */ jsx(
|
|
97881
98589
|
MemoizedSMSSenderAndCompanyEditor$1,
|
|
97882
98590
|
{
|
|
@@ -97887,7 +98595,20 @@ const SMSEditorContent = ({
|
|
|
97887
98595
|
) }),
|
|
97888
98596
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col lg:flex-row gap-6 h-full", children: [
|
|
97889
98597
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
97890
|
-
imagePreview && /* @__PURE__ */ jsx("div", { className: "flex justify-center mb-6", children: /* @__PURE__ */ jsx("div", { className: "relative group w-fit", children: /* @__PURE__ */ jsx(
|
|
98598
|
+
imagePreview && /* @__PURE__ */ jsx("div", { className: "flex justify-center mb-6", children: /* @__PURE__ */ jsx("div", { className: "relative group w-fit", children: hasMergeFieldsInUrl(imagePreview) ? /* @__PURE__ */ jsx("div", { className: "max-h-48 max-w-xs rounded-xl shadow-lg border border-gray-200 bg-gray-50 p-4 flex items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
98599
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium text-gray-700 mb-2", children: "Image will be populated at send time based on the following merge fields:" }),
|
|
98600
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1 justify-center", children: getMergeFieldsFromUrl(
|
|
98601
|
+
imagePreview,
|
|
98602
|
+
getMergeFields2
|
|
98603
|
+
).map((fieldName, index2) => /* @__PURE__ */ jsx(
|
|
98604
|
+
"span",
|
|
98605
|
+
{
|
|
98606
|
+
className: "inline-flex items-center px-2 py-1 rounded text-xs bg-blue-100 text-blue-800 font-medium border border-blue-200",
|
|
98607
|
+
children: fieldName
|
|
98608
|
+
},
|
|
98609
|
+
index2
|
|
98610
|
+
)) })
|
|
98611
|
+
] }) }) : /* @__PURE__ */ jsx(
|
|
97891
98612
|
"img",
|
|
97892
98613
|
{
|
|
97893
98614
|
src: imagePreview,
|
|
@@ -97923,7 +98644,8 @@ const SMSEditorContent = ({
|
|
|
97923
98644
|
initialImageUrls,
|
|
97924
98645
|
imageBase64,
|
|
97925
98646
|
isUpdating: isUpdatingCommunicationGroup || isUploadingImage,
|
|
97926
|
-
hasUnsavedChanges
|
|
98647
|
+
hasUnsavedChanges,
|
|
98648
|
+
communicationGroupId
|
|
97927
98649
|
}
|
|
97928
98650
|
)
|
|
97929
98651
|
] }),
|
|
@@ -99817,6 +100539,7 @@ const AutomationEditorEmailPreview = ({
|
|
|
99817
100539
|
const [showHelpDialog, setShowHelpDialog] = useState(null);
|
|
99818
100540
|
const [saveClicked, setSaveClicked] = useState(false);
|
|
99819
100541
|
const [cancelClicked, setCancelClicked] = useState(false);
|
|
100542
|
+
const [isEditorReady, setIsEditorReady] = useState(false);
|
|
99820
100543
|
const [stripoDialogDimensions, setStripoDialogDimensions] = useState({
|
|
99821
100544
|
width: 0,
|
|
99822
100545
|
height: 0
|
|
@@ -99959,6 +100682,7 @@ const AutomationEditorEmailPreview = ({
|
|
|
99959
100682
|
Button$1,
|
|
99960
100683
|
{
|
|
99961
100684
|
onClick: () => setSaveClicked(true),
|
|
100685
|
+
disabled: !isEditorReady,
|
|
99962
100686
|
className: "text-sm px-3 py-1 rounded",
|
|
99963
100687
|
children: "Save"
|
|
99964
100688
|
}
|
|
@@ -99977,7 +100701,8 @@ const AutomationEditorEmailPreview = ({
|
|
|
99977
100701
|
setSaveClicked,
|
|
99978
100702
|
stripoDialogDimensions,
|
|
99979
100703
|
mergeFieldsResponse: getMergeFields2,
|
|
99980
|
-
actionId: selectedActionId
|
|
100704
|
+
actionId: selectedActionId,
|
|
100705
|
+
onEditorReadyChange: setIsEditorReady
|
|
99981
100706
|
}
|
|
99982
100707
|
)
|
|
99983
100708
|
] })
|
|
@@ -100078,12 +100803,6 @@ const SMSDetailField = ({ label: label2, value, className }) => /* @__PURE__ */
|
|
|
100078
100803
|
] }),
|
|
100079
100804
|
/* @__PURE__ */ jsx("span", { className: cn$2("truncate", className), children: value })
|
|
100080
100805
|
] });
|
|
100081
|
-
const MemoizedTriggerButton = React__default.memo(
|
|
100082
|
-
React__default.forwardRef((props2, ref) => /* @__PURE__ */ jsxs(Button$1, { size: "sm", variant: "outline", ref, ...props2, children: [
|
|
100083
|
-
/* @__PURE__ */ jsx(IconDefinitions.EditIcon, { className: "w-3 h-3" }),
|
|
100084
|
-
"Edit"
|
|
100085
|
-
] }))
|
|
100086
|
-
);
|
|
100087
100806
|
const MemoizedSMSSenderAndCompanyEditor = React__default.memo(
|
|
100088
100807
|
({
|
|
100089
100808
|
trigger,
|
|
@@ -100102,7 +100821,7 @@ const MemoizedSMSSenderAndCompanyEditor = React__default.memo(
|
|
|
100102
100821
|
);
|
|
100103
100822
|
}
|
|
100104
100823
|
);
|
|
100105
|
-
const SMSDetailsPreview = ({ disableEditContent }) => {
|
|
100824
|
+
const SMSDetailsPreview = ({ disableEditContent, mergeFieldsResponse }) => {
|
|
100106
100825
|
const automation2 = useAutomation();
|
|
100107
100826
|
const communicationGroup = useCommunicationGroup();
|
|
100108
100827
|
const { channelSenders } = useChannelSender();
|
|
@@ -100126,6 +100845,22 @@ const SMSDetailsPreview = ({ disableEditContent }) => {
|
|
|
100126
100845
|
return null;
|
|
100127
100846
|
}
|
|
100128
100847
|
const messagePreview = messageBody ? messageBody.length > 50 ? messageBody.substring(0, 50) + "..." : messageBody : null;
|
|
100848
|
+
const MemoizedTriggerButton = React__default.memo(
|
|
100849
|
+
React__default.forwardRef((props2, ref) => /* @__PURE__ */ jsxs(
|
|
100850
|
+
Button$1,
|
|
100851
|
+
{
|
|
100852
|
+
size: "sm",
|
|
100853
|
+
variant: "outline",
|
|
100854
|
+
ref,
|
|
100855
|
+
...props2,
|
|
100856
|
+
disabled: automation2?.status !== AutomationStatus.DRAFT,
|
|
100857
|
+
children: [
|
|
100858
|
+
/* @__PURE__ */ jsx(IconDefinitions.EditIcon, { className: "w-3 h-3" }),
|
|
100859
|
+
"Edit"
|
|
100860
|
+
]
|
|
100861
|
+
}
|
|
100862
|
+
))
|
|
100863
|
+
);
|
|
100129
100864
|
return /* @__PURE__ */ jsx("div", { className: "w-full bg-background rounded-lg p-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
100130
100865
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 overflow-hidden flex-1", children: [
|
|
100131
100866
|
fromPhone && /* @__PURE__ */ jsx(
|
|
@@ -100148,7 +100883,15 @@ const SMSDetailsPreview = ({ disableEditContent }) => {
|
|
|
100148
100883
|
SMSDetailField,
|
|
100149
100884
|
{
|
|
100150
100885
|
label: "Message",
|
|
100151
|
-
value:
|
|
100886
|
+
value: /* @__PURE__ */ jsx(
|
|
100887
|
+
MergeFieldRenderer,
|
|
100888
|
+
{
|
|
100889
|
+
content: messagePreview,
|
|
100890
|
+
mergeFieldsResponse,
|
|
100891
|
+
variant: "minimal",
|
|
100892
|
+
className: "text-muted-foreground/50 italic"
|
|
100893
|
+
}
|
|
100894
|
+
),
|
|
100152
100895
|
className: "text-muted-foreground/50 italic"
|
|
100153
100896
|
}
|
|
100154
100897
|
)
|
|
@@ -100191,6 +100934,9 @@ const AutomationEditorSMSPreview = ({
|
|
|
100191
100934
|
[communicationGroup?.textMessageMediaUrls]
|
|
100192
100935
|
);
|
|
100193
100936
|
const smsBody = communicationGroup?.smsMessageBody || "";
|
|
100937
|
+
const { getMergeFields: getMergeFields2 } = useGetMergeFields(
|
|
100938
|
+
communicationGroup?.id ?? void 0
|
|
100939
|
+
);
|
|
100194
100940
|
const hasAnySMSsenders = smsChannelSenders.length > 0;
|
|
100195
100941
|
useEffect(() => {
|
|
100196
100942
|
if (hasProcessedInitialSetupRef.current) {
|
|
@@ -100341,7 +101087,8 @@ const AutomationEditorSMSPreview = ({
|
|
|
100341
101087
|
/* @__PURE__ */ jsx("div", { className: "w-full flex-shrink-0 max-w-2xl mx-auto rounded-md", children: /* @__PURE__ */ jsx(
|
|
100342
101088
|
SMSDetailsPreview,
|
|
100343
101089
|
{
|
|
100344
|
-
disableEditContent
|
|
101090
|
+
disableEditContent,
|
|
101091
|
+
mergeFieldsResponse: getMergeFields2
|
|
100345
101092
|
}
|
|
100346
101093
|
) }),
|
|
100347
101094
|
/* @__PURE__ */ jsxs("div", { className: "rounded-lg bg-background flex-1 min-h-0 flex flex-col items-center max-w-2xl mx-auto w-full", children: [
|
|
@@ -104355,6 +105102,15 @@ const AutomationSelectTimeMain = ({ title: title2 = "Edit Schedule Time" }) => {
|
|
|
104355
105102
|
const Schedule = () => {
|
|
104356
105103
|
return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(AutomationSelectTimeMain, { title: "Set Schedule Time" }) });
|
|
104357
105104
|
};
|
|
105105
|
+
var AutomationAudienceSelectorType = /* @__PURE__ */ ((AutomationAudienceSelectorType2) => {
|
|
105106
|
+
AutomationAudienceSelectorType2["ALL"] = "all";
|
|
105107
|
+
AutomationAudienceSelectorType2["SEGMENTS"] = "segments";
|
|
105108
|
+
AutomationAudienceSelectorType2["INDIVIDUAL"] = "individual";
|
|
105109
|
+
return AutomationAudienceSelectorType2;
|
|
105110
|
+
})(AutomationAudienceSelectorType || {});
|
|
105111
|
+
const generateOneOffSegmentName = (automationId) => {
|
|
105112
|
+
return `ONE-OFF-SEGMENT-${automationId}`;
|
|
105113
|
+
};
|
|
104358
105114
|
var DateUnit = /* @__PURE__ */ ((DateUnit2) => {
|
|
104359
105115
|
DateUnit2["DAYS"] = "days";
|
|
104360
105116
|
return DateUnit2;
|
|
@@ -104422,7 +105178,7 @@ const operatorToHumanReadable = (operator, type) => {
|
|
|
104422
105178
|
return "Less than";
|
|
104423
105179
|
}
|
|
104424
105180
|
case ConditionOperatorEnumType.EXISTS:
|
|
104425
|
-
return "
|
|
105181
|
+
return "Is Known";
|
|
104426
105182
|
case ConditionOperatorEnumType.EQUALS_MONTH_DAY:
|
|
104427
105183
|
return "Month and Day Matches";
|
|
104428
105184
|
case ConditionOperatorEnumType.EQUALS_MONTH_DAY_YEAR:
|
|
@@ -105410,6 +106166,39 @@ const ConditionRow = ({
|
|
|
105410
106166
|
] })
|
|
105411
106167
|
] });
|
|
105412
106168
|
};
|
|
106169
|
+
const BetaTag = React.forwardRef(
|
|
106170
|
+
({
|
|
106171
|
+
children = "BETA",
|
|
106172
|
+
size: size2 = "default",
|
|
106173
|
+
animated = false,
|
|
106174
|
+
className,
|
|
106175
|
+
...props2
|
|
106176
|
+
}, ref) => {
|
|
106177
|
+
const sizeClasses = {
|
|
106178
|
+
sm: "px-1.5 py-0.5 text-[10px]",
|
|
106179
|
+
default: "px-2 py-0.5 text-xs",
|
|
106180
|
+
lg: "px-2.5 py-1 text-sm"
|
|
106181
|
+
};
|
|
106182
|
+
return /* @__PURE__ */ jsx(
|
|
106183
|
+
"span",
|
|
106184
|
+
{
|
|
106185
|
+
ref,
|
|
106186
|
+
className: cn$2(
|
|
106187
|
+
"inline-flex items-center justify-center rounded-full font-medium leading-none",
|
|
106188
|
+
"bg-gray-100 text-gray-600 border border-gray-200",
|
|
106189
|
+
"dark:bg-gray-800 dark:text-gray-300 dark:border-gray-700",
|
|
106190
|
+
"relative select-none",
|
|
106191
|
+
sizeClasses[size2],
|
|
106192
|
+
animated && "animate-pulse",
|
|
106193
|
+
className
|
|
106194
|
+
),
|
|
106195
|
+
...props2,
|
|
106196
|
+
children
|
|
106197
|
+
}
|
|
106198
|
+
);
|
|
106199
|
+
}
|
|
106200
|
+
);
|
|
106201
|
+
BetaTag.displayName = "BetaTag";
|
|
105413
106202
|
const PromptBuilderStyle = ({ onSelectStyle }) => {
|
|
105414
106203
|
const [selectedStyle, setSelectedStyle] = useState(
|
|
105415
106204
|
null
|
|
@@ -105422,7 +106211,10 @@ const PromptBuilderStyle = ({ onSelectStyle }) => {
|
|
|
105422
106211
|
setSelectedStyle("ai");
|
|
105423
106212
|
onSelectStyle("ai");
|
|
105424
106213
|
},
|
|
105425
|
-
title: "
|
|
106214
|
+
title: /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-2", children: [
|
|
106215
|
+
/* @__PURE__ */ jsx("span", { children: "Build with AI" }),
|
|
106216
|
+
/* @__PURE__ */ jsx(BetaTag, { size: "sm" })
|
|
106217
|
+
] }),
|
|
105426
106218
|
subtitle: "Describe your audience in plain language and let AI create the conditions",
|
|
105427
106219
|
icon: /* @__PURE__ */ jsx("div", { className: "h-12 w-12 rounded-full bg-primary/10 flex items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "w-6 h-6 text-[hsl(var(--reach-primary))]", children: /* @__PURE__ */ jsx(Sparkles, { className: "w-full h-full" }) }) }),
|
|
105428
106220
|
selected: selectedStyle === "ai"
|
|
@@ -105502,6 +106294,7 @@ const TextToSegment = ({ setTextToSegment, setSegment }) => {
|
|
|
105502
106294
|
const [userInput, setUserInput] = React__default.useState("");
|
|
105503
106295
|
const [isLoading, setIsLoading] = React__default.useState(false);
|
|
105504
106296
|
const { toast: toast2 } = useToast();
|
|
106297
|
+
const { sendNotificationAsync } = useSlackNotification();
|
|
105505
106298
|
const getSegment2 = async () => {
|
|
105506
106299
|
if (!userInput) {
|
|
105507
106300
|
toast2({
|
|
@@ -105513,9 +106306,14 @@ const TextToSegment = ({ setTextToSegment, setSegment }) => {
|
|
|
105513
106306
|
}
|
|
105514
106307
|
setIsLoading(true);
|
|
105515
106308
|
const response = await textToSegment({
|
|
105516
|
-
userInput,
|
|
106309
|
+
text: userInput,
|
|
105517
106310
|
userCustomVerb: t$2("engage:user")
|
|
105518
106311
|
});
|
|
106312
|
+
sendNotificationAsync({
|
|
106313
|
+
message: "💬 New AI Segment requested",
|
|
106314
|
+
product: "engage",
|
|
106315
|
+
details: { userInput, response }
|
|
106316
|
+
});
|
|
105519
106317
|
if (response.success && response.conditions) {
|
|
105520
106318
|
toast2({
|
|
105521
106319
|
title: `${t$2("engage:segment")} conditions built successfully 🚀`,
|
|
@@ -106082,9 +106880,14 @@ const TotalExplanationTooltip = () => {
|
|
|
106082
106880
|
return /* @__PURE__ */ jsx(
|
|
106083
106881
|
InfoTooltip,
|
|
106084
106882
|
{
|
|
106085
|
-
title: `
|
|
106883
|
+
title: `The total number of ${t$2("engage:user", {
|
|
106086
106884
|
count: 2
|
|
106087
|
-
}).toLocaleLowerCase()}
|
|
106885
|
+
}).toLocaleLowerCase()} may not match your SMS and email counts because some ${t$2(
|
|
106886
|
+
"engage:user",
|
|
106887
|
+
{
|
|
106888
|
+
count: 2
|
|
106889
|
+
}
|
|
106890
|
+
).toLocaleLowerCase()} may have unsubscribed, invalid contact information, or haven't opted into marketing messages.`
|
|
106088
106891
|
}
|
|
106089
106892
|
);
|
|
106090
106893
|
};
|
|
@@ -106095,7 +106898,8 @@ const StatCard$1 = ({
|
|
|
106095
106898
|
variant,
|
|
106096
106899
|
isLoading,
|
|
106097
106900
|
selected,
|
|
106098
|
-
onClick
|
|
106901
|
+
onClick,
|
|
106902
|
+
tooltip
|
|
106099
106903
|
}) => {
|
|
106100
106904
|
const variantStyles = {
|
|
106101
106905
|
default: "bg-gray-100/50 text-gray-700",
|
|
@@ -106114,13 +106918,16 @@ const StatCard$1 = ({
|
|
|
106114
106918
|
children: [
|
|
106115
106919
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 items-start w-full min-w-0", children: [
|
|
106116
106920
|
/* @__PURE__ */ jsx("div", { className: "flex items-baseline gap-2 w-full min-w-0 @container/num", children: isLoading ? /* @__PURE__ */ jsx("span", { className: "animate-pulse", children: "..." }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
106117
|
-
/* @__PURE__ */
|
|
106118
|
-
|
|
106119
|
-
|
|
106120
|
-
|
|
106121
|
-
|
|
106122
|
-
|
|
106123
|
-
|
|
106921
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
106922
|
+
/* @__PURE__ */ jsx(
|
|
106923
|
+
"span",
|
|
106924
|
+
{
|
|
106925
|
+
className: "font-semibold pl-2 break-words max-w-full min-w-0 truncate\n text-xl @[250px]/card:text-2xl @[350px]/card:text-3xl @[500px]/card:text-4xl text-primary",
|
|
106926
|
+
children: value.toLocaleString()
|
|
106927
|
+
}
|
|
106928
|
+
),
|
|
106929
|
+
tooltip && /* @__PURE__ */ jsx(InfoTooltip, { title: tooltip })
|
|
106930
|
+
] }),
|
|
106124
106931
|
percentage2 !== void 0 && value.toLocaleString().replace(/,/g, "").length < 5 && /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground/50 text-sm hidden @[120px]/num:inline", children: [
|
|
106125
106932
|
"(",
|
|
106126
106933
|
percentage2,
|
|
@@ -106153,11 +106960,28 @@ const EstimatedMatchesView = ({ countResponse, selectedFilter = "all", onFilterC
|
|
|
106153
106960
|
);
|
|
106154
106961
|
}, [countResponse]);
|
|
106155
106962
|
const calculatePercentage = (value) => Math.round(value / (stats.total || 1) * 100);
|
|
106963
|
+
const showReassuranceBanner = stats.total > Math.max(stats.emails, stats.phones);
|
|
106156
106964
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
106157
106965
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
106158
106966
|
/* @__PURE__ */ jsx(MinorText, { children: "Estimated Matches" }),
|
|
106159
106967
|
/* @__PURE__ */ jsx(TotalExplanationTooltip, {})
|
|
106160
106968
|
] }),
|
|
106969
|
+
showReassuranceBanner && /* @__PURE__ */ jsx("div", { className: "mt-2 p-3 bg-secondary/50 border border-border rounded-lg", children: /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
106970
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: "Total vs. Subscribed mismatch?" }),
|
|
106971
|
+
" ",
|
|
106972
|
+
"Some ",
|
|
106973
|
+
t$2("engage:user", { count: 2 }).toLowerCase(),
|
|
106974
|
+
" may have unsubscribed or had hard bounces.",
|
|
106975
|
+
/* @__PURE__ */ jsx(
|
|
106976
|
+
InfoTooltip,
|
|
106977
|
+
{
|
|
106978
|
+
description: "This can happen when customers unsubscribe, emails bounces, or contact info is missing. This is normal and expected.",
|
|
106979
|
+
size: "small",
|
|
106980
|
+
iconColor: "text-muted-foreground",
|
|
106981
|
+
children: /* @__PURE__ */ jsx("span", { className: "underline cursor-help", children: "Learn more" })
|
|
106982
|
+
}
|
|
106983
|
+
)
|
|
106984
|
+
] }) }),
|
|
106161
106985
|
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-3 md:mb-6 w-full gap-4 mt-3 px-1", children: [
|
|
106162
106986
|
/* @__PURE__ */ jsx(
|
|
106163
106987
|
StatCard$1,
|
|
@@ -106167,7 +106991,15 @@ const EstimatedMatchesView = ({ countResponse, selectedFilter = "all", onFilterC
|
|
|
106167
106991
|
variant: "default",
|
|
106168
106992
|
isLoading: countResponse === void 0,
|
|
106169
106993
|
selected: selectedFilter === "all",
|
|
106170
|
-
onClick: onFilterChange ? () => onFilterChange("all") : void 0
|
|
106994
|
+
onClick: onFilterChange ? () => onFilterChange("all") : void 0,
|
|
106995
|
+
tooltip: `Total includes all ${t$2("engage:user", {
|
|
106996
|
+
count: 2
|
|
106997
|
+
}).toLocaleLowerCase()} in your system. This does not factor in ${t$2(
|
|
106998
|
+
"engage:user",
|
|
106999
|
+
{
|
|
107000
|
+
count: 2
|
|
107001
|
+
}
|
|
107002
|
+
).toLocaleLowerCase()} who might have opted out of email or sms.`
|
|
106171
107003
|
}
|
|
106172
107004
|
),
|
|
106173
107005
|
/* @__PURE__ */ jsx(
|
|
@@ -106197,7 +107029,7 @@ const EstimatedMatchesView = ({ countResponse, selectedFilter = "all", onFilterC
|
|
|
106197
107029
|
] })
|
|
106198
107030
|
] });
|
|
106199
107031
|
};
|
|
106200
|
-
const getDisplayName = (recipient) => {
|
|
107032
|
+
const getDisplayName$1 = (recipient) => {
|
|
106201
107033
|
const fullName = `${recipient.firstName || ""} ${recipient.lastName || ""}`.trim();
|
|
106202
107034
|
if (fullName) return fullName;
|
|
106203
107035
|
if (recipient.firstName) return recipient.firstName;
|
|
@@ -106206,7 +107038,7 @@ const getDisplayName = (recipient) => {
|
|
|
106206
107038
|
if (recipient.phone) return recipient.phone;
|
|
106207
107039
|
return `Unnamed ${t$2("engage:user")}`;
|
|
106208
107040
|
};
|
|
106209
|
-
const RecipientsTable = ({ recipients, filter: filter2 = "all" }) => {
|
|
107041
|
+
const RecipientsTable = ({ recipients, filter: filter2 = "all", audienceMode }) => {
|
|
106210
107042
|
const filteredRecipients = recipients?.filter((recipient) => {
|
|
106211
107043
|
const hasEmail = !!recipient.email;
|
|
106212
107044
|
const hasPhone = !!recipient.phone;
|
|
@@ -106221,14 +107053,45 @@ const RecipientsTable = ({ recipients, filter: filter2 = "all" }) => {
|
|
|
106221
107053
|
return true;
|
|
106222
107054
|
}
|
|
106223
107055
|
});
|
|
106224
|
-
if (!filteredRecipients?.length)
|
|
107056
|
+
if (!filteredRecipients?.length) {
|
|
107057
|
+
return /* @__PURE__ */ jsx("div", { className: "bg-foreground/5 rounded-lg h-full relative overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "absolute inset-0 w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "text-center max-w-sm", children: /* @__PURE__ */ jsxs("div", { className: "text-gray-400 text-sm mb-2", children: [
|
|
107058
|
+
filter2 === "email" && "No recipients with email addresses",
|
|
107059
|
+
filter2 === "phone" && "No recipients with phone numbers",
|
|
107060
|
+
filter2 === "all" && (audienceMode === "segments" ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
107061
|
+
/* @__PURE__ */ jsxs("div", { className: "text-gray-500 font-medium mb-1", children: [
|
|
107062
|
+
"No ",
|
|
107063
|
+
t$2("engage:segment").toLowerCase(),
|
|
107064
|
+
" selected"
|
|
107065
|
+
] }),
|
|
107066
|
+
/* @__PURE__ */ jsxs("div", { className: "text-gray-400 text-xs", children: [
|
|
107067
|
+
"Select one or more",
|
|
107068
|
+
" ",
|
|
107069
|
+
t$2("engage:segment", { count: 2 }).toLowerCase(),
|
|
107070
|
+
" from the list above to see your recipients"
|
|
107071
|
+
] })
|
|
107072
|
+
] }) : audienceMode === "individual" ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
107073
|
+
/* @__PURE__ */ jsxs("div", { className: "text-gray-500 font-medium mb-1", children: [
|
|
107074
|
+
"No individual",
|
|
107075
|
+
" ",
|
|
107076
|
+
t$2("engage:user", { count: 2 }).toLowerCase(),
|
|
107077
|
+
" selected"
|
|
107078
|
+
] }),
|
|
107079
|
+
/* @__PURE__ */ jsxs("div", { className: "text-gray-400 text-xs", children: [
|
|
107080
|
+
"Choose specific",
|
|
107081
|
+
" ",
|
|
107082
|
+
t$2("engage:user", { count: 2 }).toLowerCase(),
|
|
107083
|
+
"from the dropdown above to see your recipients"
|
|
107084
|
+
] })
|
|
107085
|
+
] }) : "No recipients found")
|
|
107086
|
+
] }) }) }) });
|
|
107087
|
+
}
|
|
106225
107088
|
return /* @__PURE__ */ jsx("div", { className: "bg-foreground/5 rounded-lg h-full relative overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "absolute inset-0 w-full h-full overflow-y-auto", children: /* @__PURE__ */ jsxs("table", { className: "w-full", children: [
|
|
106226
107089
|
/* @__PURE__ */ jsx("thead", { className: "sticky top-0 bg-foreground/5 backdrop-blur-sm", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
106227
107090
|
/* @__PURE__ */ jsx("th", { className: "px-3 sm:px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wide", children: "Name" }),
|
|
106228
107091
|
/* @__PURE__ */ jsx("th", { className: "px-3 sm:px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wide", children: "Contact" })
|
|
106229
107092
|
] }) }),
|
|
106230
107093
|
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-gray-200/50", children: filteredRecipients.map((recipient, index2) => /* @__PURE__ */ jsxs("tr", { className: "hover:bg-white/50 transition-colors", children: [
|
|
106231
|
-
/* @__PURE__ */ jsx("td", { className: "px-3 sm:px-4 py-3 text-sm text-gray-900", children: getDisplayName(recipient) }),
|
|
107094
|
+
/* @__PURE__ */ jsx("td", { className: "px-3 sm:px-4 py-3 text-sm text-gray-900", children: getDisplayName$1(recipient) }),
|
|
106232
107095
|
/* @__PURE__ */ jsx("td", { className: "px-3 sm:px-4 py-3", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1.5 sm:gap-2", children: [
|
|
106233
107096
|
recipient.email && /* @__PURE__ */ jsx("span", { className: "px-2 sm:px-2.5 py-1 text-xs font-medium bg-blue-100/50 text-blue-700 rounded-lg", children: "Email" }),
|
|
106234
107097
|
recipient.phone && /* @__PURE__ */ jsx("span", { className: "px-2 sm:px-2.5 py-1 text-xs font-medium bg-green-100/50 text-green-700 rounded-lg", children: "Phone" })
|
|
@@ -106236,7 +107099,11 @@ const RecipientsTable = ({ recipients, filter: filter2 = "all" }) => {
|
|
|
106236
107099
|
] }, index2)) })
|
|
106237
107100
|
] }) }) });
|
|
106238
107101
|
};
|
|
106239
|
-
const AllOrSelectSegmentPicker = ({
|
|
107102
|
+
const AllOrSelectSegmentPicker = ({
|
|
107103
|
+
onSelectionChange,
|
|
107104
|
+
defaultValue = AutomationAudienceSelectorType.ALL,
|
|
107105
|
+
canEditAudience = true
|
|
107106
|
+
}) => {
|
|
106240
107107
|
const [selected, setSelected] = useState(defaultValue);
|
|
106241
107108
|
const handleSelect = (value) => {
|
|
106242
107109
|
if (!canEditAudience) return;
|
|
@@ -106248,32 +107115,124 @@ const AllOrSelectSegmentPicker = ({ onSelectionChange, defaultValue = "all", can
|
|
|
106248
107115
|
/* @__PURE__ */ jsx(MinorText, { children: "Filter" }),
|
|
106249
107116
|
!canEditAudience && /* @__PURE__ */ jsx(InfoTooltip, { title: "You cannot edit the audience unless you are in draft mode" })
|
|
106250
107117
|
] }),
|
|
106251
|
-
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-
|
|
107118
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-4 p-1", children: [
|
|
106252
107119
|
/* @__PURE__ */ jsx(
|
|
106253
107120
|
BigSelector,
|
|
106254
107121
|
{
|
|
106255
|
-
onClick: () => handleSelect(
|
|
107122
|
+
onClick: () => handleSelect(AutomationAudienceSelectorType.ALL),
|
|
106256
107123
|
title: `All ${t$2("engage:user", { count: 2 })}`,
|
|
106257
107124
|
subtitle: "Send to everyone",
|
|
106258
107125
|
icon: /* @__PURE__ */ jsx(IconDefinitions.UsersIcon, { className: "w-5 h-5 mb-2 text-gray-600" }),
|
|
106259
107126
|
selected: selected === "all",
|
|
106260
|
-
disabled: !canEditAudience
|
|
107127
|
+
disabled: !canEditAudience,
|
|
107128
|
+
hideSelectedText: true
|
|
106261
107129
|
}
|
|
106262
107130
|
),
|
|
106263
107131
|
/* @__PURE__ */ jsx(
|
|
106264
107132
|
BigSelector,
|
|
106265
107133
|
{
|
|
106266
|
-
onClick: () => handleSelect(
|
|
106267
|
-
title: `Select ${t$2("engage:
|
|
107134
|
+
onClick: () => handleSelect(AutomationAudienceSelectorType.SEGMENTS),
|
|
107135
|
+
title: `Select ${t$2("engage:segment", { count: 2 })}`,
|
|
106268
107136
|
subtitle: `Choose from ${t$2("engage:segment", { count: 2 })}`,
|
|
106269
107137
|
icon: /* @__PURE__ */ jsx(IconDefinitions.UserEdit, { className: "w-5 h-5 mb-2 text-gray-600" }),
|
|
106270
107138
|
selected: selected === "segments",
|
|
106271
|
-
disabled: !canEditAudience
|
|
107139
|
+
disabled: !canEditAudience,
|
|
107140
|
+
hideSelectedText: true
|
|
107141
|
+
}
|
|
107142
|
+
),
|
|
107143
|
+
/* @__PURE__ */ jsx(
|
|
107144
|
+
BigSelector,
|
|
107145
|
+
{
|
|
107146
|
+
onClick: () => handleSelect(AutomationAudienceSelectorType.INDIVIDUAL),
|
|
107147
|
+
title: "Select Individual",
|
|
107148
|
+
subtitle: `Pick ${t$2("engage:user", { count: 2 }).toLowerCase()} one by one`,
|
|
107149
|
+
icon: /* @__PURE__ */ jsx(IconDefinitions.UserIcon, { className: "w-5 h-5 mb-2 text-gray-600" }),
|
|
107150
|
+
selected: selected === "individual",
|
|
107151
|
+
disabled: !canEditAudience,
|
|
107152
|
+
hideSelectedText: true
|
|
106272
107153
|
}
|
|
106273
107154
|
)
|
|
106274
107155
|
] })
|
|
106275
107156
|
] });
|
|
106276
107157
|
};
|
|
107158
|
+
const getDisplayName = (recipient) => {
|
|
107159
|
+
const fullName = `${recipient.firstName || ""} ${recipient.lastName || ""}`.trim();
|
|
107160
|
+
if (fullName) return fullName;
|
|
107161
|
+
if (recipient.firstName) return recipient.firstName;
|
|
107162
|
+
if (recipient.lastName) return recipient.lastName;
|
|
107163
|
+
if (recipient.email) return recipient.email;
|
|
107164
|
+
if (recipient.phone) return recipient.phone;
|
|
107165
|
+
return `Unnamed User`;
|
|
107166
|
+
};
|
|
107167
|
+
const SelectIndividualUsersContent = ({ selectedUserIds, onUserSelectionChange, canEditAudience = true }) => {
|
|
107168
|
+
const [tempSelectedUserIds, setTempSelectedUserIds] = useState(selectedUserIds);
|
|
107169
|
+
const [allUsersForDropdown, setAllUsersForDropdown] = useState();
|
|
107170
|
+
const { segments } = useListSegments();
|
|
107171
|
+
useEffect(() => {
|
|
107172
|
+
setTempSelectedUserIds(selectedUserIds);
|
|
107173
|
+
}, [selectedUserIds]);
|
|
107174
|
+
useEffect(() => {
|
|
107175
|
+
const fetchAllUsers = async () => {
|
|
107176
|
+
if (!segments) return;
|
|
107177
|
+
const allUsersSegment = segments.find(
|
|
107178
|
+
(segment2) => segment2.type === BusinessSegmentTypeEnum.ALL_USERS
|
|
107179
|
+
);
|
|
107180
|
+
if (allUsersSegment) {
|
|
107181
|
+
try {
|
|
107182
|
+
const allUsersResponse = await getCountOfBusinessAutomationRecipients(
|
|
107183
|
+
{
|
|
107184
|
+
includeSegments: [allUsersSegment.id],
|
|
107185
|
+
excludeSegments: []
|
|
107186
|
+
}
|
|
107187
|
+
);
|
|
107188
|
+
setAllUsersForDropdown(allUsersResponse);
|
|
107189
|
+
} catch (error2) {
|
|
107190
|
+
console.error("Error fetching all users for dropdown:", error2);
|
|
107191
|
+
}
|
|
107192
|
+
}
|
|
107193
|
+
};
|
|
107194
|
+
fetchAllUsers();
|
|
107195
|
+
}, [segments]);
|
|
107196
|
+
const userOptions = React__default.useMemo(() => {
|
|
107197
|
+
if (!allUsersForDropdown?.recipients) return [];
|
|
107198
|
+
return allUsersForDropdown.recipients.map((recipient) => ({
|
|
107199
|
+
label: getDisplayName(recipient),
|
|
107200
|
+
value: recipient.externalId
|
|
107201
|
+
}));
|
|
107202
|
+
}, [allUsersForDropdown?.recipients]);
|
|
107203
|
+
const handleUserSelectionChange = (newSelectedUserIds) => {
|
|
107204
|
+
setTempSelectedUserIds(newSelectedUserIds);
|
|
107205
|
+
onUserSelectionChange(newSelectedUserIds);
|
|
107206
|
+
};
|
|
107207
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
107208
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
107209
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
107210
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-medium text-gray-900", children: "Select Individual Users" }),
|
|
107211
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500", children: "Choose specific users to include in your automation" })
|
|
107212
|
+
] }),
|
|
107213
|
+
selectedUserIds.length > 0 && /* @__PURE__ */ jsxs("div", { className: "text-sm text-gray-500", children: [
|
|
107214
|
+
selectedUserIds.length,
|
|
107215
|
+
" user",
|
|
107216
|
+
selectedUserIds.length !== 1 ? "s" : "",
|
|
107217
|
+
" selected"
|
|
107218
|
+
] })
|
|
107219
|
+
] }),
|
|
107220
|
+
/* @__PURE__ */ jsx(
|
|
107221
|
+
MultiSelectDialog,
|
|
107222
|
+
{
|
|
107223
|
+
options: userOptions,
|
|
107224
|
+
onValueChange: handleUserSelectionChange,
|
|
107225
|
+
selectedValues: tempSelectedUserIds,
|
|
107226
|
+
setSelectedValues: setTempSelectedUserIds,
|
|
107227
|
+
placeholder: "Select users...",
|
|
107228
|
+
title: "Select Individual Users",
|
|
107229
|
+
searchPlaceholder: "Search users...",
|
|
107230
|
+
emptyMessage: "No users found",
|
|
107231
|
+
canOpen: canEditAudience
|
|
107232
|
+
}
|
|
107233
|
+
)
|
|
107234
|
+
] });
|
|
107235
|
+
};
|
|
106277
107236
|
const SegmentSection = ({
|
|
106278
107237
|
segments,
|
|
106279
107238
|
allSegments,
|
|
@@ -106304,8 +107263,9 @@ const SegmentSection = ({
|
|
|
106304
107263
|
setSelectedValues: setSegmentSelectedIds,
|
|
106305
107264
|
options,
|
|
106306
107265
|
onValueChange: handleValueChange,
|
|
106307
|
-
placeholder:
|
|
107266
|
+
placeholder: `Select ${t$2("engage:segment", { count: 2 })}`,
|
|
106308
107267
|
maxCount: 5,
|
|
107268
|
+
title: `Select ${t$2("engage:segment", { count: 2 })}`,
|
|
106309
107269
|
extraCommandItems: [
|
|
106310
107270
|
(closePopup) => /* @__PURE__ */ jsxs(
|
|
106311
107271
|
CommandItem,
|
|
@@ -106399,7 +107359,7 @@ const SelectSegmentsContent = ({
|
|
|
106399
107359
|
const AutomationAudienceSelectorMain = ({ title: title2 = "Preview Audience" }) => {
|
|
106400
107360
|
const automation2 = useAutomation();
|
|
106401
107361
|
const [selectedAudience, setSelectedAudience] = useState(
|
|
106402
|
-
|
|
107362
|
+
AutomationAudienceSelectorType.ALL
|
|
106403
107363
|
);
|
|
106404
107364
|
const [includedSegments, setIncludedSegments] = useState(
|
|
106405
107365
|
automation2?.includeSegmentIds || []
|
|
@@ -106407,6 +107367,7 @@ const AutomationAudienceSelectorMain = ({ title: title2 = "Preview Audience" })
|
|
|
106407
107367
|
const [excludedSegments, setExcludedSegments] = useState(
|
|
106408
107368
|
automation2?.excludeSegmentIds || []
|
|
106409
107369
|
);
|
|
107370
|
+
const [selectedIndividualUserIds, setSelectedIndividualUserIds] = useState([]);
|
|
106410
107371
|
const [openCreateSegmentDialog, setOpenCreateSegmentDialog] = useState(false);
|
|
106411
107372
|
const [initialStateSet, setInitialStateSet] = useState(false);
|
|
106412
107373
|
const [selectedFilter, setSelectedFilter] = useState("all");
|
|
@@ -106418,35 +107379,58 @@ const AutomationAudienceSelectorMain = ({ title: title2 = "Preview Audience" })
|
|
|
106418
107379
|
const allUsersSelected = includedSegments.length === 1 && excludedSegments.length === 0 && segments?.find(
|
|
106419
107380
|
(segment2) => segment2.type === BusinessSegmentTypeEnum.ALL_USERS && segment2.id === includedSegments[0]
|
|
106420
107381
|
) !== void 0;
|
|
107382
|
+
const segmentIdToFetch = includedSegments.length === 1 && excludedSegments.length === 0 && !allUsersSelected ? includedSegments[0] : "";
|
|
107383
|
+
const { segment: singleSegment } = useGetSegment(segmentIdToFetch);
|
|
107384
|
+
const oneOffSegmentSelected = singleSegment?.type === BusinessSegmentTypeEnum.ONE_OFF;
|
|
106421
107385
|
useEffect(() => {
|
|
106422
|
-
|
|
106423
|
-
if (
|
|
106424
|
-
(
|
|
106425
|
-
|
|
106426
|
-
|
|
106427
|
-
|
|
106428
|
-
|
|
107386
|
+
const initializeState = async () => {
|
|
107387
|
+
if (automation2 && !initialStateSet && isLoading === false) {
|
|
107388
|
+
if (includedSegments.length === 1 && segments.find(
|
|
107389
|
+
(segment2) => segment2.type === BusinessSegmentTypeEnum.ALL_USERS && segment2.id === includedSegments[0]
|
|
107390
|
+
) !== void 0) {
|
|
107391
|
+
setSelectedAudience(AutomationAudienceSelectorType.ALL);
|
|
107392
|
+
} else if (oneOffSegmentSelected && singleSegment) {
|
|
107393
|
+
setSelectedAudience(AutomationAudienceSelectorType.INDIVIDUAL);
|
|
107394
|
+
if (singleSegment.conditions) {
|
|
107395
|
+
const userIds = [];
|
|
107396
|
+
singleSegment.conditions.forEach((condition) => {
|
|
107397
|
+
if (condition.field === "userId" && condition.operator === ConditionOperatorEnumType.EQUALS) {
|
|
107398
|
+
condition.value.forEach((val) => {
|
|
107399
|
+
if (typeof val === "string") {
|
|
107400
|
+
userIds.push(val);
|
|
107401
|
+
}
|
|
107402
|
+
});
|
|
107403
|
+
}
|
|
107404
|
+
});
|
|
107405
|
+
setSelectedIndividualUserIds(userIds);
|
|
107406
|
+
}
|
|
107407
|
+
} else {
|
|
107408
|
+
setSelectedAudience(AutomationAudienceSelectorType.SEGMENTS);
|
|
107409
|
+
}
|
|
107410
|
+
getCountOfBusinessAutomationRecipients({
|
|
107411
|
+
includeSegments: includedSegments,
|
|
107412
|
+
excludeSegments: excludedSegments
|
|
107413
|
+
}).then((response) => {
|
|
107414
|
+
setCountResponse(response);
|
|
107415
|
+
});
|
|
107416
|
+
setInitialStateSet(true);
|
|
106429
107417
|
}
|
|
106430
|
-
|
|
106431
|
-
|
|
106432
|
-
excludeSegments: excludedSegments
|
|
106433
|
-
}).then((response) => {
|
|
106434
|
-
setCountResponse(response);
|
|
106435
|
-
});
|
|
106436
|
-
setInitialStateSet(true);
|
|
106437
|
-
}
|
|
107418
|
+
};
|
|
107419
|
+
initializeState();
|
|
106438
107420
|
}, [
|
|
106439
107421
|
automation2,
|
|
106440
107422
|
allUsersSelected,
|
|
107423
|
+
oneOffSegmentSelected,
|
|
106441
107424
|
initialStateSet,
|
|
106442
107425
|
includedSegments,
|
|
106443
107426
|
excludedSegments,
|
|
106444
107427
|
segments,
|
|
106445
|
-
isLoading
|
|
107428
|
+
isLoading,
|
|
107429
|
+
singleSegment
|
|
106446
107430
|
]);
|
|
106447
|
-
const handleAudienceSelectionChange = (value) => {
|
|
107431
|
+
const handleAudienceSelectionChange = async (value) => {
|
|
106448
107432
|
setSelectedAudience(value);
|
|
106449
|
-
if (value ===
|
|
107433
|
+
if (value === AutomationAudienceSelectorType.ALL) {
|
|
106450
107434
|
const allUsersSegment = segments?.find(
|
|
106451
107435
|
(segment2) => segment2.type === BusinessSegmentTypeEnum.ALL_USERS
|
|
106452
107436
|
);
|
|
@@ -106456,6 +107440,61 @@ const AutomationAudienceSelectorMain = ({ title: title2 = "Preview Audience" })
|
|
|
106456
107440
|
}
|
|
106457
107441
|
setIncludedSegments([allUsersSegment.id]);
|
|
106458
107442
|
setExcludedSegments([]);
|
|
107443
|
+
setSelectedIndividualUserIds([]);
|
|
107444
|
+
} else if (value === AutomationAudienceSelectorType.INDIVIDUAL) {
|
|
107445
|
+
if (automation2?.id) {
|
|
107446
|
+
try {
|
|
107447
|
+
const segmentName = generateOneOffSegmentName(automation2.id);
|
|
107448
|
+
let segment2;
|
|
107449
|
+
try {
|
|
107450
|
+
segment2 = await findSegmentByName(segmentName);
|
|
107451
|
+
} catch (error2) {
|
|
107452
|
+
}
|
|
107453
|
+
if (segment2) {
|
|
107454
|
+
setIncludedSegments([segment2.id]);
|
|
107455
|
+
setExcludedSegments([]);
|
|
107456
|
+
if (segment2.conditions) {
|
|
107457
|
+
const userIds = [];
|
|
107458
|
+
segment2.conditions.forEach((condition) => {
|
|
107459
|
+
if (condition.field === "userId" && condition.operator === ConditionOperatorEnumType.EQUALS) {
|
|
107460
|
+
condition.value.forEach((val) => {
|
|
107461
|
+
if (typeof val === "string") {
|
|
107462
|
+
userIds.push(val);
|
|
107463
|
+
}
|
|
107464
|
+
});
|
|
107465
|
+
}
|
|
107466
|
+
});
|
|
107467
|
+
setSelectedIndividualUserIds(userIds);
|
|
107468
|
+
}
|
|
107469
|
+
} else {
|
|
107470
|
+
const newSegment = await createSegment({
|
|
107471
|
+
name: segmentName,
|
|
107472
|
+
description: "One-off segment for individual user selection",
|
|
107473
|
+
type: BusinessSegmentTypeEnum.ONE_OFF,
|
|
107474
|
+
conditions: [
|
|
107475
|
+
{
|
|
107476
|
+
field: "userId",
|
|
107477
|
+
operator: ConditionOperatorEnumType.EQUALS,
|
|
107478
|
+
value: []
|
|
107479
|
+
}
|
|
107480
|
+
]
|
|
107481
|
+
});
|
|
107482
|
+
if (newSegment?.id) {
|
|
107483
|
+
setIncludedSegments([newSegment.id]);
|
|
107484
|
+
setExcludedSegments([]);
|
|
107485
|
+
}
|
|
107486
|
+
}
|
|
107487
|
+
} catch (error2) {
|
|
107488
|
+
console.error("Error creating ONE_OFF segment:", error2);
|
|
107489
|
+
}
|
|
107490
|
+
}
|
|
107491
|
+
} else if (value === AutomationAudienceSelectorType.SEGMENTS) {
|
|
107492
|
+
setIncludedSegments([]);
|
|
107493
|
+
setExcludedSegments([]);
|
|
107494
|
+
setCountResponse({
|
|
107495
|
+
count: 0,
|
|
107496
|
+
recipients: []
|
|
107497
|
+
});
|
|
106459
107498
|
}
|
|
106460
107499
|
};
|
|
106461
107500
|
const handleAddSegment = (segmentId, type) => {
|
|
@@ -106472,8 +107511,75 @@ const AutomationAudienceSelectorMain = ({ title: title2 = "Preview Audience" })
|
|
|
106472
107511
|
setExcludedSegments((prev) => prev.filter((id2) => id2 !== segmentId));
|
|
106473
107512
|
}
|
|
106474
107513
|
};
|
|
107514
|
+
const handleIndividualUserSelectionChange = async (userIds) => {
|
|
107515
|
+
setSelectedIndividualUserIds(userIds);
|
|
107516
|
+
if (automation2?.id) {
|
|
107517
|
+
try {
|
|
107518
|
+
const segmentName = generateOneOffSegmentName(automation2.id);
|
|
107519
|
+
let segment2;
|
|
107520
|
+
try {
|
|
107521
|
+
segment2 = await findSegmentByName(segmentName);
|
|
107522
|
+
} catch (error2) {
|
|
107523
|
+
}
|
|
107524
|
+
if (segment2) {
|
|
107525
|
+
const updatedSegment = await updateSegment(segment2.id, {
|
|
107526
|
+
conditions: userIds.length > 0 ? [
|
|
107527
|
+
{
|
|
107528
|
+
field: "userId",
|
|
107529
|
+
operator: ConditionOperatorEnumType.EQUALS,
|
|
107530
|
+
value: userIds
|
|
107531
|
+
}
|
|
107532
|
+
] : [
|
|
107533
|
+
{
|
|
107534
|
+
field: "userId",
|
|
107535
|
+
operator: ConditionOperatorEnumType.EQUALS,
|
|
107536
|
+
value: []
|
|
107537
|
+
}
|
|
107538
|
+
]
|
|
107539
|
+
});
|
|
107540
|
+
segment2 = updatedSegment;
|
|
107541
|
+
} else {
|
|
107542
|
+
segment2 = await createSegment({
|
|
107543
|
+
name: segmentName,
|
|
107544
|
+
description: "One-off segment for individual user selection",
|
|
107545
|
+
type: BusinessSegmentTypeEnum.ONE_OFF,
|
|
107546
|
+
conditions: userIds.length > 0 ? [
|
|
107547
|
+
{
|
|
107548
|
+
field: "userId",
|
|
107549
|
+
operator: ConditionOperatorEnumType.EQUALS,
|
|
107550
|
+
value: userIds
|
|
107551
|
+
}
|
|
107552
|
+
] : [
|
|
107553
|
+
{
|
|
107554
|
+
field: "userId",
|
|
107555
|
+
operator: ConditionOperatorEnumType.EQUALS,
|
|
107556
|
+
value: []
|
|
107557
|
+
}
|
|
107558
|
+
]
|
|
107559
|
+
});
|
|
107560
|
+
}
|
|
107561
|
+
if (segment2?.id) {
|
|
107562
|
+
await updateAutomation2({
|
|
107563
|
+
includeSegments: [segment2.id],
|
|
107564
|
+
excludeSegments: []
|
|
107565
|
+
});
|
|
107566
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
107567
|
+
const countResponse2 = await getCountOfBusinessAutomationRecipients({
|
|
107568
|
+
includeSegments: [segment2.id],
|
|
107569
|
+
excludeSegments: []
|
|
107570
|
+
});
|
|
107571
|
+
setCountResponse(countResponse2);
|
|
107572
|
+
}
|
|
107573
|
+
} catch (error2) {
|
|
107574
|
+
console.error("Error creating/updating ONE_OFF segment:", error2);
|
|
107575
|
+
}
|
|
107576
|
+
}
|
|
107577
|
+
};
|
|
106475
107578
|
useEffect(() => {
|
|
106476
107579
|
if (automation2 && initialStateSet) {
|
|
107580
|
+
if (selectedAudience === AutomationAudienceSelectorType.INDIVIDUAL && includedSegments.length === 0 && excludedSegments.length === 0) {
|
|
107581
|
+
return;
|
|
107582
|
+
}
|
|
106477
107583
|
if (JSON.stringify(includedSegments) !== JSON.stringify(automation2.includeSegmentIds) || JSON.stringify(excludedSegments) !== JSON.stringify(automation2.excludeSegmentIds)) {
|
|
106478
107584
|
updateAutomation2({
|
|
106479
107585
|
includeSegments: includedSegments,
|
|
@@ -106492,7 +107598,8 @@ const AutomationAudienceSelectorMain = ({ title: title2 = "Preview Audience" })
|
|
|
106492
107598
|
excludedSegments,
|
|
106493
107599
|
automation2,
|
|
106494
107600
|
initialStateSet,
|
|
106495
|
-
updateAutomation2
|
|
107601
|
+
updateAutomation2,
|
|
107602
|
+
selectedAudience
|
|
106496
107603
|
]);
|
|
106497
107604
|
const onSegmentUpdated = (id2) => {
|
|
106498
107605
|
if (id2) {
|
|
@@ -106519,7 +107626,7 @@ const AutomationAudienceSelectorMain = ({ title: title2 = "Preview Audience" })
|
|
|
106519
107626
|
canEditAudience
|
|
106520
107627
|
}
|
|
106521
107628
|
),
|
|
106522
|
-
/* @__PURE__ */ jsx(AnimatePresence, { children: selectedAudience ===
|
|
107629
|
+
/* @__PURE__ */ jsx(AnimatePresence, { children: selectedAudience === AutomationAudienceSelectorType.SEGMENTS && /* @__PURE__ */ jsx(
|
|
106523
107630
|
motion.div,
|
|
106524
107631
|
{
|
|
106525
107632
|
initial: { opacity: 0, height: 0 },
|
|
@@ -106541,13 +107648,33 @@ const AutomationAudienceSelectorMain = ({ title: title2 = "Preview Audience" })
|
|
|
106541
107648
|
}
|
|
106542
107649
|
)
|
|
106543
107650
|
}
|
|
107651
|
+
) }),
|
|
107652
|
+
/* @__PURE__ */ jsx(AnimatePresence, { children: selectedAudience === AutomationAudienceSelectorType.INDIVIDUAL && /* @__PURE__ */ jsx(
|
|
107653
|
+
motion.div,
|
|
107654
|
+
{
|
|
107655
|
+
initial: { opacity: 0, height: 0 },
|
|
107656
|
+
animate: { opacity: 1, height: "auto" },
|
|
107657
|
+
exit: { opacity: 0, height: 0 },
|
|
107658
|
+
transition: { duration: 0.3, ease: "easeInOut" },
|
|
107659
|
+
className: "w-full pt-4",
|
|
107660
|
+
children: /* @__PURE__ */ jsx(
|
|
107661
|
+
SelectIndividualUsersContent,
|
|
107662
|
+
{
|
|
107663
|
+
countResponse,
|
|
107664
|
+
selectedUserIds: selectedIndividualUserIds,
|
|
107665
|
+
onUserSelectionChange: handleIndividualUserSelectionChange,
|
|
107666
|
+
canEditAudience
|
|
107667
|
+
}
|
|
107668
|
+
)
|
|
107669
|
+
}
|
|
106544
107670
|
) })
|
|
106545
107671
|
] }),
|
|
106546
107672
|
/* @__PURE__ */ jsx("div", { className: "flex flex-col flex-1 relative overflow-hidden", children: countResponse?.recipients && /* @__PURE__ */ jsx(
|
|
106547
107673
|
RecipientsTable,
|
|
106548
107674
|
{
|
|
106549
107675
|
recipients: countResponse.recipients,
|
|
106550
|
-
filter: selectedFilter
|
|
107676
|
+
filter: selectedFilter,
|
|
107677
|
+
audienceMode: selectedAudience
|
|
106551
107678
|
}
|
|
106552
107679
|
) })
|
|
106553
107680
|
] }),
|
|
@@ -106927,7 +108054,7 @@ const getAutomationSteps = ({
|
|
|
106927
108054
|
];
|
|
106928
108055
|
};
|
|
106929
108056
|
const useRecipientStats = (automation2) => {
|
|
106930
|
-
const { data: estimatedMatches } = useGetCountOfBusinessAutomationRecipients({
|
|
108057
|
+
const { data: estimatedMatches, isLoading } = useGetCountOfBusinessAutomationRecipients({
|
|
106931
108058
|
automationId: automation2?.id ?? "",
|
|
106932
108059
|
includeSegments: automation2?.includeSegmentIds ?? [],
|
|
106933
108060
|
excludeSegments: automation2?.excludeSegmentIds ?? []
|
|
@@ -106944,7 +108071,8 @@ const useRecipientStats = (automation2) => {
|
|
|
106944
108071
|
}, [estimatedMatches?.recipients]);
|
|
106945
108072
|
return {
|
|
106946
108073
|
estimatedMatches,
|
|
106947
|
-
estimatedMatchesStats
|
|
108074
|
+
estimatedMatchesStats,
|
|
108075
|
+
isLoading
|
|
106948
108076
|
};
|
|
106949
108077
|
};
|
|
106950
108078
|
const DEFAULT_LOGO_URL = "https://assets.embedreach.com/defaults/logo-placeholder-128.png";
|
|
@@ -106987,7 +108115,7 @@ const validateAutomationStep = async (args) => {
|
|
|
106987
108115
|
const smsChannelSender = smsChannelSenders.find(
|
|
106988
108116
|
(sender) => sender.channelSender.id === communicationGroup.smsChannelSenderId
|
|
106989
108117
|
);
|
|
106990
|
-
if (!smsChannelSender) {
|
|
108118
|
+
if (!smsChannelSender && !communicationGroup.emailChannelSenderId) {
|
|
106991
108119
|
return {
|
|
106992
108120
|
canMove: false,
|
|
106993
108121
|
errorMessage: "Please ensure you have selected a text sender"
|
|
@@ -106999,7 +108127,7 @@ const validateAutomationStep = async (args) => {
|
|
|
106999
108127
|
errorMessage: "Please ensure you have a text body"
|
|
107000
108128
|
};
|
|
107001
108129
|
}
|
|
107002
|
-
if (smsChannelSender.smsApplication && smsChannelSender.smsApplication.status !== SmsRegistrationApplicationStatus.APPROVED) {
|
|
108130
|
+
if (smsChannelSender && smsChannelSender.smsApplication && smsChannelSender.smsApplication.status !== SmsRegistrationApplicationStatus.APPROVED) {
|
|
107003
108131
|
return {
|
|
107004
108132
|
canMove: true,
|
|
107005
108133
|
errorMessage: null,
|
|
@@ -107027,10 +108155,10 @@ const validateAutomationStep = async (args) => {
|
|
|
107027
108155
|
errorMessage: "Please ensure you have selected a communication group"
|
|
107028
108156
|
};
|
|
107029
108157
|
}
|
|
107030
|
-
if (!communicationGroup.emailChannelSenderId) {
|
|
108158
|
+
if (!communicationGroup.emailChannelSenderId && !communicationGroup.smsChannelSenderId) {
|
|
107031
108159
|
return {
|
|
107032
108160
|
canMove: false,
|
|
107033
|
-
errorMessage: "Please ensure you have selected
|
|
108161
|
+
errorMessage: "Please ensure you have selected an email or SMS sender"
|
|
107034
108162
|
};
|
|
107035
108163
|
}
|
|
107036
108164
|
if (!communicationGroup.emailHtmlBody || !communicationGroup.emailSubject) {
|
|
@@ -107154,7 +108282,7 @@ const OneTimeWizardMain = ({ onFinish, getExtraMergeFields, onBeforeSchedule })
|
|
|
107154
108282
|
const { updateAutomation: updateAutomation2 } = useUpdateBusinessAutomation(
|
|
107155
108283
|
automation2?.id || ""
|
|
107156
108284
|
);
|
|
107157
|
-
const { estimatedMatchesStats } = useRecipientStats(automation2 ?? void 0);
|
|
108285
|
+
const { estimatedMatchesStats, isLoading: isLoadingRecipientStats } = useRecipientStats(automation2 ?? void 0);
|
|
107158
108286
|
const {
|
|
107159
108287
|
state: { selectedChannels }
|
|
107160
108288
|
} = useContext(Context);
|
|
@@ -107243,6 +108371,11 @@ const OneTimeWizardMain = ({ onFinish, getExtraMergeFields, onBeforeSchedule })
|
|
|
107243
108371
|
}
|
|
107244
108372
|
if (onBeforeSchedule) {
|
|
107245
108373
|
try {
|
|
108374
|
+
let attempts = 0;
|
|
108375
|
+
while (isLoadingRecipientStats && attempts < 10) {
|
|
108376
|
+
await new Promise((resolve) => setTimeout(resolve, 250));
|
|
108377
|
+
attempts++;
|
|
108378
|
+
}
|
|
107246
108379
|
const result = await onBeforeSchedule({
|
|
107247
108380
|
estimatedEmailRecipients: estimatedMatchesStats?.emails || 0,
|
|
107248
108381
|
estimatedSmsRecipients: estimatedMatchesStats?.phones || 0
|
|
@@ -107344,6 +108477,8 @@ const OneTimeWizardMain = ({ onFinish, getExtraMergeFields, onBeforeSchedule })
|
|
|
107344
108477
|
if (currentStep > AutomationSteps.SelectAudience) {
|
|
107345
108478
|
if (currentStep === AutomationSteps.EditSmsContent && selectedChannels.length === 1 && selectedChannels[0] === "sms") {
|
|
107346
108479
|
setCurrentStep(currentStep - 2);
|
|
108480
|
+
} else if (currentStep === AutomationSteps.Schedule && selectedChannels.length === 1 && selectedChannels[0] === "email") {
|
|
108481
|
+
setCurrentStep(currentStep - 2);
|
|
107347
108482
|
} else {
|
|
107348
108483
|
setCurrentStep(currentStep - 1);
|
|
107349
108484
|
}
|
|
@@ -107739,8 +108874,7 @@ function CreateAutomationDialog({
|
|
|
107739
108874
|
replyToSettingsText,
|
|
107740
108875
|
replyToSettingsLink,
|
|
107741
108876
|
fromNameSettingsText,
|
|
107742
|
-
fromNameSettingsLink
|
|
107743
|
-
onBeforeSchedule
|
|
108877
|
+
fromNameSettingsLink
|
|
107744
108878
|
}) {
|
|
107745
108879
|
const onCloseInner = (createdAutomation) => {
|
|
107746
108880
|
onClose?.(createdAutomation);
|
|
@@ -107780,8 +108914,7 @@ function CreateAutomationDialog({
|
|
|
107780
108914
|
automationType,
|
|
107781
108915
|
currentStep,
|
|
107782
108916
|
setCurrentStep,
|
|
107783
|
-
getExtraMergeFields
|
|
107784
|
-
onBeforeSchedule
|
|
108917
|
+
getExtraMergeFields
|
|
107785
108918
|
}
|
|
107786
108919
|
)
|
|
107787
108920
|
]
|
|
@@ -108001,14 +109134,20 @@ const generateBrandSettings = async () => {
|
|
|
108001
109134
|
return response.data;
|
|
108002
109135
|
};
|
|
108003
109136
|
const useBrandSettingsMutation = () => {
|
|
109137
|
+
const { sendNotificationAsync } = useSlackNotification();
|
|
108004
109138
|
return useMutation({
|
|
108005
109139
|
mutationFn: generateBrandSettings,
|
|
108006
109140
|
mutationKey: websiteContentKeys.brandSettings(),
|
|
108007
|
-
onSuccess: () => {
|
|
109141
|
+
onSuccess: (data) => {
|
|
108008
109142
|
toast({
|
|
108009
109143
|
title: "Brand settings generated successfully!",
|
|
108010
109144
|
description: "Your brand identity has been analyzed."
|
|
108011
109145
|
});
|
|
109146
|
+
sendNotificationAsync({
|
|
109147
|
+
message: "💬 New brand settings generated",
|
|
109148
|
+
product: "engage",
|
|
109149
|
+
details: { brandSettingsResponse: data }
|
|
109150
|
+
});
|
|
108012
109151
|
},
|
|
108013
109152
|
onError: () => {
|
|
108014
109153
|
toast({
|
|
@@ -109445,6 +110584,123 @@ const EmailChannelStep = ({
|
|
|
109445
110584
|
}
|
|
109446
110585
|
);
|
|
109447
110586
|
};
|
|
110587
|
+
const MergeFieldForm = forwardRef(({ onSubmit }, ref) => {
|
|
110588
|
+
const { getMergeFields: getMergeFields2, isGetting, getError } = useGetMergeFields("all");
|
|
110589
|
+
const { data: business } = useBusiness();
|
|
110590
|
+
const [fallbacks, setFallbacks] = useState([]);
|
|
110591
|
+
useEffect(() => {
|
|
110592
|
+
if (getMergeFields2?.mergeFields && business) {
|
|
110593
|
+
setFallbacks(
|
|
110594
|
+
getMergeFields2.mergeFields.flatMap(
|
|
110595
|
+
(category) => category.entries.map((entry) => ({
|
|
110596
|
+
label: entry.label,
|
|
110597
|
+
value: entry.value,
|
|
110598
|
+
// Keep the template name (value) for backend
|
|
110599
|
+
fallbackValue: business.merge_field_fallbacks[entry.label] || ""
|
|
110600
|
+
}))
|
|
110601
|
+
)
|
|
110602
|
+
);
|
|
110603
|
+
}
|
|
110604
|
+
}, [getMergeFields2, business]);
|
|
110605
|
+
const handleFallbackChange = (index2, value) => {
|
|
110606
|
+
setFallbacks(
|
|
110607
|
+
(fallbacks2) => fallbacks2.map(
|
|
110608
|
+
(f2, i3) => i3 === index2 ? { ...f2, fallbackValue: value } : f2
|
|
110609
|
+
)
|
|
110610
|
+
);
|
|
110611
|
+
};
|
|
110612
|
+
const handleSubmit = (e4) => {
|
|
110613
|
+
e4.preventDefault();
|
|
110614
|
+
onSubmit(fallbacks);
|
|
110615
|
+
};
|
|
110616
|
+
useImperativeHandle(
|
|
110617
|
+
ref,
|
|
110618
|
+
() => ({
|
|
110619
|
+
submit: () => {
|
|
110620
|
+
onSubmit(fallbacks);
|
|
110621
|
+
},
|
|
110622
|
+
getData: () => fallbacks
|
|
110623
|
+
}),
|
|
110624
|
+
[fallbacks, onSubmit]
|
|
110625
|
+
);
|
|
110626
|
+
const hasMergeFields = Array.isArray(getMergeFields2?.mergeFields) && getMergeFields2.mergeFields.some(
|
|
110627
|
+
(category) => Array.isArray(category.entries) && category.entries.length > 0
|
|
110628
|
+
);
|
|
110629
|
+
if (isGetting) {
|
|
110630
|
+
return /* @__PURE__ */ jsx("div", { className: "py-8", children: /* @__PURE__ */ jsx(BasicLoader, { text: "Loading merge fields..." }) });
|
|
110631
|
+
}
|
|
110632
|
+
if (getError) {
|
|
110633
|
+
return /* @__PURE__ */ jsx("div", { className: "py-8 text-center text-destructive", children: "Error loading merge fields" });
|
|
110634
|
+
}
|
|
110635
|
+
if (!hasMergeFields) {
|
|
110636
|
+
return /* @__PURE__ */ jsx("div", { className: "py-8 text-center text-muted-foreground", children: "No merge fields available" });
|
|
110637
|
+
}
|
|
110638
|
+
return /* @__PURE__ */ jsx("form", { onSubmit: handleSubmit, className: "space-y-6 p-8", children: /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full border-separate border-spacing-y-2", children: [
|
|
110639
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
110640
|
+
/* @__PURE__ */ jsx("th", { className: "text-left text-sm font-semibold text-foreground pb-2", children: "Merge Field" }),
|
|
110641
|
+
/* @__PURE__ */ jsx("th", { className: "text-left text-sm font-semibold text-foreground pb-2", children: "Fallback Value" })
|
|
110642
|
+
] }) }),
|
|
110643
|
+
/* @__PURE__ */ jsx("tbody", { children: fallbacks.map((field, idx) => /* @__PURE__ */ jsxs("tr", { className: "align-top", children: [
|
|
110644
|
+
/* @__PURE__ */ jsx("td", { className: "pr-4 py-1 text-base text-foreground whitespace-nowrap", children: field.label }),
|
|
110645
|
+
/* @__PURE__ */ jsx("td", { className: "py-1", children: /* @__PURE__ */ jsx(
|
|
110646
|
+
Input,
|
|
110647
|
+
{
|
|
110648
|
+
value: field.fallbackValue,
|
|
110649
|
+
onChange: (e4) => handleFallbackChange(idx, e4.target.value),
|
|
110650
|
+
placeholder: "Enter fallback value",
|
|
110651
|
+
className: "w-full max-w-xs"
|
|
110652
|
+
}
|
|
110653
|
+
) })
|
|
110654
|
+
] }, field.value)) })
|
|
110655
|
+
] }) }) });
|
|
110656
|
+
});
|
|
110657
|
+
const MergeFieldSettings = ({
|
|
110658
|
+
onBack,
|
|
110659
|
+
title: title2,
|
|
110660
|
+
description: description2
|
|
110661
|
+
}) => {
|
|
110662
|
+
const { navigation } = useEngageSettingsContext();
|
|
110663
|
+
const { postBusinessMergeFieldFallbacks: postBusinessMergeFieldFallbacks2, isPosting, postError } = usePostBusinessMergeFieldFallbacks();
|
|
110664
|
+
const wizardContext = useContext(
|
|
110665
|
+
WizardContext
|
|
110666
|
+
);
|
|
110667
|
+
const goToPreviousStep = onBack || wizardContext?.goToPreviousStep || navigation?.goToPreviousStep || (() => {
|
|
110668
|
+
});
|
|
110669
|
+
const stepTitle = title2 || ENGAGE_STRINGS.MERGE_FIELDS_TITLE;
|
|
110670
|
+
const stepDescription = description2 || "Manage merge fields for personalizing your communications with dynamic content.";
|
|
110671
|
+
const formRef = useRef(null);
|
|
110672
|
+
const handleFormSubmit = () => {
|
|
110673
|
+
if (formRef.current) {
|
|
110674
|
+
const mergeFields = formRef.current.getData();
|
|
110675
|
+
const mapping = Object.fromEntries(
|
|
110676
|
+
mergeFields.filter((field) => field.fallbackValue.trim()).map((field) => [
|
|
110677
|
+
field.value.replace(/[{}]/g, ""),
|
|
110678
|
+
// Remove {{}} syntax
|
|
110679
|
+
field.fallbackValue.trim()
|
|
110680
|
+
])
|
|
110681
|
+
);
|
|
110682
|
+
postBusinessMergeFieldFallbacks2({
|
|
110683
|
+
mergeFieldFallbacks: mapping
|
|
110684
|
+
});
|
|
110685
|
+
}
|
|
110686
|
+
};
|
|
110687
|
+
return /* @__PURE__ */ jsxs(
|
|
110688
|
+
WizardFormWrapper,
|
|
110689
|
+
{
|
|
110690
|
+
title: stepTitle,
|
|
110691
|
+
description: stepDescription,
|
|
110692
|
+
onBack: goToPreviousStep,
|
|
110693
|
+
onNext: handleFormSubmit,
|
|
110694
|
+
submitLabel: "Save",
|
|
110695
|
+
mode: "settings",
|
|
110696
|
+
isSubmitting: isPosting,
|
|
110697
|
+
children: [
|
|
110698
|
+
postError && /* @__PURE__ */ jsx("div", { className: "text-destructive text-center py-2", children: "Error saving merge fields" }),
|
|
110699
|
+
/* @__PURE__ */ jsx(MergeFieldForm, { ref: formRef, onSubmit: handleFormSubmit })
|
|
110700
|
+
]
|
|
110701
|
+
}
|
|
110702
|
+
);
|
|
110703
|
+
};
|
|
109448
110704
|
const SMSChannelSettings = ({
|
|
109449
110705
|
hideSubmitButton = false,
|
|
109450
110706
|
formRef,
|
|
@@ -109709,7 +110965,8 @@ const EngageSettings = () => {
|
|
|
109709
110965
|
[ENGAGE_STEPS.BRAND]: /* @__PURE__ */ jsx(BrandSettingsStep, {}),
|
|
109710
110966
|
[ENGAGE_STEPS.BUSINESS]: /* @__PURE__ */ jsx(BusinessSettingsStep, {}),
|
|
109711
110967
|
[ENGAGE_STEPS.EMAIL]: /* @__PURE__ */ jsx(EmailChannelStep, {}),
|
|
109712
|
-
[ENGAGE_STEPS.SMS]: /* @__PURE__ */ jsx(SMSChannelStep, {})
|
|
110968
|
+
[ENGAGE_STEPS.SMS]: /* @__PURE__ */ jsx(SMSChannelStep, {}),
|
|
110969
|
+
[ENGAGE_STEPS.MERGE_FIELDS]: /* @__PURE__ */ jsx(MergeFieldSettings, {})
|
|
109713
110970
|
}[currentStep] || null
|
|
109714
110971
|
}
|
|
109715
110972
|
);
|
|
@@ -110093,6 +111350,7 @@ const EngageOnboarding = () => {
|
|
|
110093
111350
|
[ENGAGE_STEPS.BUSINESS_SKIP_INTERSTITIAL]: /* @__PURE__ */ jsx(BusinessSkipInterstitialStep, {}),
|
|
110094
111351
|
[ENGAGE_STEPS.SMS_INTERSTITIAL]: /* @__PURE__ */ jsx(SMSInterstitialStep, {}),
|
|
110095
111352
|
[ENGAGE_STEPS.SMS]: /* @__PURE__ */ jsx(SMSChannelStep, {}),
|
|
111353
|
+
[ENGAGE_STEPS.MERGE_FIELDS]: /* @__PURE__ */ jsx(MergeFieldSettings, { isOnboarding: true }),
|
|
110096
111354
|
[ENGAGE_STEPS.COMPLETION]: /* @__PURE__ */ jsx(CompletionStep, {})
|
|
110097
111355
|
};
|
|
110098
111356
|
const handleOpenChange = (isOpen) => {
|
|
@@ -110794,6 +112052,9 @@ function SegmentList() {
|
|
|
110794
112052
|
case BusinessSegmentTypeEnum.MANAGED:
|
|
110795
112053
|
typeOfSegment = "Managed";
|
|
110796
112054
|
break;
|
|
112055
|
+
case BusinessSegmentTypeEnum.ONE_OFF:
|
|
112056
|
+
typeOfSegment = "One-off";
|
|
112057
|
+
break;
|
|
110797
112058
|
default:
|
|
110798
112059
|
throw UnreachableCaseStatement(
|
|
110799
112060
|
row.type,
|
|
@@ -111204,10 +112465,6 @@ function InlineEditor({
|
|
|
111204
112465
|
}
|
|
111205
112466
|
) });
|
|
111206
112467
|
}
|
|
111207
|
-
const capitalize = (str) => {
|
|
111208
|
-
if (!str) return str;
|
|
111209
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
111210
|
-
};
|
|
111211
112468
|
function AutomationCancelRunningDialog({
|
|
111212
112469
|
open,
|
|
111213
112470
|
onOpenChange
|
|
@@ -111723,6 +112980,7 @@ const AutomationsEditorHeader = ({ showBackButton, onDuplicationCreated, onBefor
|
|
|
111723
112980
|
);
|
|
111724
112981
|
const noEmailSubjectORnoEmailHtmlBody = communicationGroup?.emailChannelSenderId && (!communicationGroup?.emailSubject || !communicationGroup?.emailHtmlBody);
|
|
111725
112982
|
const noSmsMessageBody = communicationGroup?.smsChannelSenderId && !communicationGroup?.smsMessageBody;
|
|
112983
|
+
const noIncludeSegments = automation2.includeSegmentIds?.length === 0;
|
|
111726
112984
|
const missingScheduledAt = automationOneTime && (!automation2.triggerMetadata || !("scheduledAt" in automation2.triggerMetadata) || !automation2.triggerMetadata?.scheduledAt);
|
|
111727
112985
|
let disableSwitch = false;
|
|
111728
112986
|
let showSwitch = true;
|
|
@@ -111736,7 +112994,7 @@ const AutomationsEditorHeader = ({ showBackButton, onDuplicationCreated, onBefor
|
|
|
111736
112994
|
/**
|
|
111737
112995
|
* If we have a emailChannelSenderId, we need to have a emailSubject and emailHtmlBody
|
|
111738
112996
|
*/
|
|
111739
|
-
noEmailANDnoSmsSender || noEmailSubjectORnoEmailHtmlBody || noSmsMessageBody
|
|
112997
|
+
noEmailANDnoSmsSender || noEmailSubjectORnoEmailHtmlBody || noSmsMessageBody || noIncludeSegments
|
|
111740
112998
|
) {
|
|
111741
112999
|
disableSwitch = true;
|
|
111742
113000
|
if (noEmailSubjectORnoEmailHtmlBody) {
|
|
@@ -111745,6 +113003,9 @@ const AutomationsEditorHeader = ({ showBackButton, onDuplicationCreated, onBefor
|
|
|
111745
113003
|
if (noSmsMessageBody) {
|
|
111746
113004
|
infoOnDisabled = "Missing SMS message in SMS communication";
|
|
111747
113005
|
}
|
|
113006
|
+
if (noIncludeSegments) {
|
|
113007
|
+
infoOnDisabled = "Missing include segment";
|
|
113008
|
+
}
|
|
111748
113009
|
}
|
|
111749
113010
|
if (missingScheduledAt) {
|
|
111750
113011
|
disableSwitch = true;
|
|
@@ -111843,7 +113104,7 @@ const AutomationsEditorHeader = ({ showBackButton, onDuplicationCreated, onBefor
|
|
|
111843
113104
|
}
|
|
111844
113105
|
);
|
|
111845
113106
|
}
|
|
111846
|
-
if (noTriggerMetadata || oneTimeNoScheduledAt || noEmailANDnoSmsSender || smsApplicationNotApproved || noEmailSubjectORnoEmailHtmlBody || noSmsMessageBody) {
|
|
113107
|
+
if (noTriggerMetadata || oneTimeNoScheduledAt || noEmailANDnoSmsSender || smsApplicationNotApproved || noEmailSubjectORnoEmailHtmlBody || noSmsMessageBody || noIncludeSegments) {
|
|
111847
113108
|
const renderInfoTooltip = () => {
|
|
111848
113109
|
const sendText = automation2.triggerMetadata && "scheduledAt" in automation2.triggerMetadata && automation2.triggerMetadata?.scheduledAt === "now" ? `Start ${automationLanguage}` : "Schedule Send";
|
|
111849
113110
|
if (automation2.status !== AutomationStatus.DRAFT) {
|
|
@@ -111885,6 +113146,13 @@ const AutomationsEditorHeader = ({ showBackButton, onDuplicationCreated, onBefor
|
|
|
111885
113146
|
"Please add a message to your SMS communication"
|
|
111886
113147
|
);
|
|
111887
113148
|
}
|
|
113149
|
+
if (noIncludeSegments) {
|
|
113150
|
+
alertMessages.push(
|
|
113151
|
+
`Please select at least one ${t$2("engage:segment", {
|
|
113152
|
+
count: 1
|
|
113153
|
+
}).toLowerCase()}`
|
|
113154
|
+
);
|
|
113155
|
+
}
|
|
111888
113156
|
const formattedMessages = alertMessages.map(
|
|
111889
113157
|
(msg) => capitalize(msg)
|
|
111890
113158
|
);
|
|
@@ -112159,7 +113427,8 @@ const AutomationRecipientsTable = () => {
|
|
|
112159
113427
|
automationId: automation2?.id ?? "",
|
|
112160
113428
|
cursor: cursorForQuery,
|
|
112161
113429
|
limit: pageSizeForQuery,
|
|
112162
|
-
search: searchQuery || void 0
|
|
113430
|
+
search: searchQuery || void 0,
|
|
113431
|
+
automationStatus: automation2?.status
|
|
112163
113432
|
});
|
|
112164
113433
|
const handleQueryParametersChange = useCallback(
|
|
112165
113434
|
(params) => {
|
|
@@ -114569,47 +115838,32 @@ const AutomationAudienceSelector = () => {
|
|
|
114569
115838
|
setActionId: setActionId2,
|
|
114570
115839
|
state: { selectedActionId }
|
|
114571
115840
|
} = useContext(Context$1);
|
|
114572
|
-
const [includeSegmentIds, setIncludeSegmentIds] = useState(
|
|
114573
|
-
automation2?.includeSegmentIds || null
|
|
114574
|
-
);
|
|
114575
|
-
const [excludeSegmentIds, setExcludeSegmentIds] = useState(
|
|
114576
|
-
automation2?.excludeSegmentIds || null
|
|
114577
|
-
);
|
|
114578
115841
|
const { segments } = useListSegments();
|
|
114579
|
-
const
|
|
114580
|
-
|
|
114581
|
-
|
|
114582
|
-
);
|
|
114583
|
-
}, [segments]);
|
|
114584
|
-
useEffect(() => {
|
|
114585
|
-
if (!automation2 || !segments) {
|
|
114586
|
-
return;
|
|
114587
|
-
}
|
|
114588
|
-
if (includeSegmentIds === null && excludeSegmentIds === null) {
|
|
114589
|
-
setIncludeSegmentIds(automation2?.includeSegmentIds || null);
|
|
114590
|
-
setExcludeSegmentIds(automation2?.excludeSegmentIds || null);
|
|
114591
|
-
if (automation2.includeSegmentIds.length === 0 && automation2.excludeSegmentIds.length === 0) {
|
|
114592
|
-
setIncludeSegmentIds([getAllUsersSegment()?.id || ""]);
|
|
114593
|
-
setExcludeSegmentIds([]);
|
|
114594
|
-
}
|
|
114595
|
-
} else {
|
|
114596
|
-
if (JSON.stringify(automation2.includeSegmentIds) !== JSON.stringify(includeSegmentIds)) {
|
|
114597
|
-
setIncludeSegmentIds(automation2.includeSegmentIds);
|
|
114598
|
-
}
|
|
114599
|
-
if (JSON.stringify(automation2.excludeSegmentIds) !== JSON.stringify(excludeSegmentIds)) {
|
|
114600
|
-
setExcludeSegmentIds(automation2.excludeSegmentIds);
|
|
114601
|
-
}
|
|
114602
|
-
}
|
|
114603
|
-
}, [
|
|
114604
|
-
automation2,
|
|
114605
|
-
excludeSegmentIds,
|
|
114606
|
-
includeSegmentIds,
|
|
114607
|
-
segments,
|
|
114608
|
-
getAllUsersSegment
|
|
114609
|
-
]);
|
|
114610
|
-
if (!automation2 || !includeSegmentIds || !excludeSegmentIds) {
|
|
115842
|
+
const segmentIdToFetch = automation2?.includeSegmentIds?.length === 1 && automation2?.excludeSegmentIds?.length === 0 ? automation2.includeSegmentIds[0] : "";
|
|
115843
|
+
const { segment: singleSegment } = useGetSegment(segmentIdToFetch);
|
|
115844
|
+
if (!automation2 || !segments) {
|
|
114611
115845
|
return null;
|
|
114612
115846
|
}
|
|
115847
|
+
const includeSegmentIds = automation2.includeSegmentIds;
|
|
115848
|
+
let copyText;
|
|
115849
|
+
let showSegmentPills = true;
|
|
115850
|
+
if (singleSegment?.type === BusinessSegmentTypeEnum.ALL_USERS) {
|
|
115851
|
+
copyText = `Send to all ${t$2("engage:user", { count: 2 })}`;
|
|
115852
|
+
showSegmentPills = false;
|
|
115853
|
+
} else if (singleSegment?.type === BusinessSegmentTypeEnum.ONE_OFF) {
|
|
115854
|
+
copyText = `Send to specific ${t$2("engage:user", { count: 2 })}`;
|
|
115855
|
+
showSegmentPills = false;
|
|
115856
|
+
} else {
|
|
115857
|
+
copyText = `Send to all ${t$2("engage:user", {
|
|
115858
|
+
count: 2
|
|
115859
|
+
})} in ${includeSegmentIds.length === 1 ? "this" : "these"} ${t$2(
|
|
115860
|
+
"engage:segment",
|
|
115861
|
+
{
|
|
115862
|
+
count: includeSegmentIds.length
|
|
115863
|
+
}
|
|
115864
|
+
).toLowerCase()}`;
|
|
115865
|
+
showSegmentPills = true;
|
|
115866
|
+
}
|
|
114613
115867
|
return /* @__PURE__ */ jsx(Fragment$1, { children: /* @__PURE__ */ jsx(
|
|
114614
115868
|
BasicsButton,
|
|
114615
115869
|
{
|
|
@@ -114623,20 +115877,8 @@ const AutomationAudienceSelector = () => {
|
|
|
114623
115877
|
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5 flex-1", children: [
|
|
114624
115878
|
/* @__PURE__ */ jsx(MinorText, { children: "Audience" }),
|
|
114625
115879
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
|
|
114626
|
-
/* @__PURE__ */ jsx(
|
|
114627
|
-
|
|
114628
|
-
{
|
|
114629
|
-
copyText: `Send to all ${t$2("engage:user", {
|
|
114630
|
-
count: 2
|
|
114631
|
-
})} in ${includeSegmentIds.length === 1 ? "this" : "these"} ${t$2(
|
|
114632
|
-
"engage:segment",
|
|
114633
|
-
{
|
|
114634
|
-
count: includeSegmentIds.length
|
|
114635
|
-
}
|
|
114636
|
-
).toLowerCase()}`
|
|
114637
|
-
}
|
|
114638
|
-
),
|
|
114639
|
-
/* @__PURE__ */ jsx("div", { className: "flex gap-1 flex-wrap", children: includeSegmentIds.map((id2) => {
|
|
115880
|
+
/* @__PURE__ */ jsx(AutomationFlowLabel, { copyText }),
|
|
115881
|
+
showSegmentPills && /* @__PURE__ */ jsx("div", { className: "flex gap-1 flex-wrap", children: includeSegmentIds.map((id2) => {
|
|
114640
115882
|
const segment2 = segments?.find((segment22) => segment22.id === id2);
|
|
114641
115883
|
if (!segment2) return null;
|
|
114642
115884
|
return /* @__PURE__ */ jsx(SegmentPill, { segmentName: segment2.name }, id2);
|
|
@@ -115013,7 +116255,10 @@ const AutomationEditorSubStep = ({
|
|
|
115013
116255
|
return;
|
|
115014
116256
|
}
|
|
115015
116257
|
try {
|
|
115016
|
-
const params = {
|
|
116258
|
+
const params = {
|
|
116259
|
+
emailChannelSenderId: communicationGroup.emailChannelSenderId,
|
|
116260
|
+
smsChannelSenderId: communicationGroup.smsChannelSenderId
|
|
116261
|
+
};
|
|
115017
116262
|
switch (type) {
|
|
115018
116263
|
case CommunicationSubStepType.EMAIL:
|
|
115019
116264
|
if (channelEnabled && communicationGroup.emailChannelSenderId) {
|
|
@@ -115036,10 +116281,21 @@ const AutomationEditorSubStep = ({
|
|
|
115036
116281
|
}
|
|
115037
116282
|
break;
|
|
115038
116283
|
}
|
|
115039
|
-
await updateCommunicationGroup2(
|
|
115040
|
-
|
|
115041
|
-
|
|
115042
|
-
|
|
116284
|
+
await updateCommunicationGroup2(
|
|
116285
|
+
{
|
|
116286
|
+
groupId: communicationGroup.id,
|
|
116287
|
+
params
|
|
116288
|
+
},
|
|
116289
|
+
{
|
|
116290
|
+
onError: () => {
|
|
116291
|
+
toast2({
|
|
116292
|
+
title: "Error toggling channel",
|
|
116293
|
+
description: "Please contact your administrator",
|
|
116294
|
+
variant: "destructive"
|
|
116295
|
+
});
|
|
116296
|
+
}
|
|
116297
|
+
}
|
|
116298
|
+
);
|
|
115043
116299
|
} catch (error2) {
|
|
115044
116300
|
console.error("Error toggling channel:", error2);
|
|
115045
116301
|
}
|