@inspirer-dev/crm-dashboard 1.0.80 → 1.0.82
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/admin/src/components/ButtonsBuilder/index.tsx +3 -3
- package/admin/src/components/CancelConditionsField/index.tsx +7 -6
- package/admin/src/components/RulesBuilder/index.tsx +9 -8
- package/admin/src/components/StepFlowBuilder/constants.ts +2 -0
- package/admin/src/components/StepFlowBuilder/index.tsx +1 -1
- package/admin/src/components/StepFlowBuilder/nodes/EventTriggerNode.tsx +29 -1
- package/admin/src/components/StepFlowBuilder/panels/EventTriggerConfig.tsx +97 -9
- package/admin/src/components/StepFlowBuilder/panels/NodeEditPanel.tsx +1 -1
- package/admin/src/components/StepFlowBuilder/panels/WaitConfig.tsx +1 -3
- package/admin/src/components/StepFlowBuilder/types.ts +2 -0
- package/admin/src/components/TriggerConfigField/index.tsx +11 -10
- package/admin/src/components/TriggerParamsField/constants.ts +109 -0
- package/admin/src/components/TriggerParamsField/index.tsx +292 -0
- package/admin/src/index.ts +26 -1
- package/admin/src/pages/HomePage/components/CampaignBuilder/index.tsx +4 -0
- package/admin/src/pages/HomePage/components/FlowBuilderTest.tsx +3 -3
- package/admin/src/pages/HomePage/components/SendTimeHeatMap.tsx +2 -2
- package/admin/src/pages/HomePage/components/StatsView.tsx +2 -2
- package/admin/src/translations/en.json +4 -1
- package/admin/src/translations/ru.json +4 -1
- package/admin/tsconfig.json +12 -1
- package/admin/tsconfig.tsbuildinfo +1 -1
- package/dist/_chunks/{en-DEUgX5uV.mjs → en-B5BgIROW.mjs} +3 -1
- package/dist/_chunks/{en-D2kTkBns.js → en-GKZo4lia.js} +3 -1
- package/dist/_chunks/{index-C-1xCfqJ.js → index-354YMebI.js} +152 -38
- package/dist/_chunks/{index-BydXrDhA.mjs → index-BKfFI_Jo.mjs} +2 -2
- package/dist/_chunks/{index-D1kMmlrA.js → index-BQcRoIJr.js} +5 -4
- package/dist/_chunks/{index-BJzk6xNb.mjs → index-BgwX1xYS.mjs} +7 -6
- package/dist/_chunks/{index-pJUyH-Qr.js → index-Cg0G_bTE.js} +2 -2
- package/dist/_chunks/index-CuMY0eo5.js +310 -0
- package/dist/_chunks/{index-unxa4Q_H.mjs → index-DKJtyGq7.mjs} +5 -4
- package/dist/_chunks/{index-BFRbyVHC.js → index-DRXMKPXI.js} +1 -1
- package/dist/_chunks/{index-Xa_4jez0.mjs → index-Dhj0KzCX.mjs} +5 -4
- package/dist/_chunks/{index-Dv1tGmDT.mjs → index-LXBoz7PC.mjs} +1 -1
- package/dist/_chunks/index-NvFKi6er.mjs +310 -0
- package/dist/_chunks/{index-BKrTVHBr.js → index-T7VXjklK.js} +5 -4
- package/dist/_chunks/{index-CWSibOAr.mjs → index-gR86Z3uh.mjs} +152 -38
- package/dist/_chunks/{index-CAwynvu7.js → index-xDSMnUMp.js} +7 -6
- package/dist/_chunks/{ru-BKzplvmu.js → ru-bj5iiIPr.js} +3 -1
- package/dist/_chunks/{ru-DOt1yfNm.mjs → ru-h22ZdPCS.mjs} +3 -1
- package/dist/admin/index.js +31 -7
- package/dist/admin/index.mjs +32 -8
- package/dist/server/index.js +5 -0
- package/dist/server/index.mjs +5 -0
- package/package.json +3 -3
- package/server/src/register.ts +6 -0
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
+
const React = require("react");
|
|
5
|
+
const designSystem = require("@strapi/design-system");
|
|
6
|
+
const icons = require("@strapi/icons");
|
|
7
|
+
const styledComponents = require("styled-components");
|
|
8
|
+
const TRIGGER_PARAMS = [
|
|
9
|
+
{
|
|
10
|
+
key: "delaySeconds",
|
|
11
|
+
label: "Задержка",
|
|
12
|
+
description: "Задержка перед показом после срабатывания триггера",
|
|
13
|
+
unit: "сек",
|
|
14
|
+
min: 0,
|
|
15
|
+
placeholder: "7",
|
|
16
|
+
stageTypes: ["side_hint", "modal", "retry"]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
key: "timeOnSiteSeconds",
|
|
20
|
+
label: "Время на сайте",
|
|
21
|
+
description: "Мин. время на сайте для срабатывания",
|
|
22
|
+
unit: "сек",
|
|
23
|
+
min: 0,
|
|
24
|
+
placeholder: "120",
|
|
25
|
+
stageTypes: ["exit_intent", "side_hint", "modal"]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
key: "scrollThresholdPx",
|
|
29
|
+
label: "Порог скролла",
|
|
30
|
+
description: "Скролл в пикселях для срабатывания",
|
|
31
|
+
unit: "px",
|
|
32
|
+
min: 0,
|
|
33
|
+
placeholder: "200",
|
|
34
|
+
stageTypes: ["side_hint"]
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
key: "idleSeconds",
|
|
38
|
+
label: "Бездействие",
|
|
39
|
+
description: "Время без кликов/скролла",
|
|
40
|
+
unit: "сек",
|
|
41
|
+
min: 0,
|
|
42
|
+
placeholder: "15",
|
|
43
|
+
stageTypes: ["side_hint"]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
key: "caseViewSeconds",
|
|
47
|
+
label: "Просмотр кейса",
|
|
48
|
+
description: "Время на странице кейса",
|
|
49
|
+
unit: "сек",
|
|
50
|
+
min: 0,
|
|
51
|
+
placeholder: "12",
|
|
52
|
+
stageTypes: ["modal", "side_hint"]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
key: "activePlayMinutes",
|
|
56
|
+
label: "Активная игра",
|
|
57
|
+
description: "Время активной игры",
|
|
58
|
+
unit: "мин",
|
|
59
|
+
min: 0,
|
|
60
|
+
placeholder: "10",
|
|
61
|
+
stageTypes: ["modal"]
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
key: "actionCountThreshold",
|
|
65
|
+
label: "Порог действий",
|
|
66
|
+
description: "Кол-во значимых действий + низкий баланс",
|
|
67
|
+
unit: "",
|
|
68
|
+
min: 0,
|
|
69
|
+
placeholder: "2",
|
|
70
|
+
stageTypes: ["modal"]
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
key: "balanceThresholdMultiplier",
|
|
74
|
+
label: "Множитель баланса",
|
|
75
|
+
description: 'Множитель мин. цены кейса для "низкого баланса"',
|
|
76
|
+
unit: "×",
|
|
77
|
+
min: 0,
|
|
78
|
+
placeholder: "1.5",
|
|
79
|
+
stageTypes: ["modal", "side_hint"]
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
key: "abandonedTimeoutMinutes",
|
|
83
|
+
label: "Таймаут заброшенного депозита",
|
|
84
|
+
description: "Через сколько минут депозит считается заброшенным",
|
|
85
|
+
unit: "мин",
|
|
86
|
+
min: 1,
|
|
87
|
+
placeholder: "10",
|
|
88
|
+
stageTypes: ["retry"]
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
key: "minDepositAmount",
|
|
92
|
+
label: "Мин. сумма депозита",
|
|
93
|
+
description: "Подстановка в {{min_deposit}} в текстах",
|
|
94
|
+
unit: "₽",
|
|
95
|
+
min: 0,
|
|
96
|
+
placeholder: "250",
|
|
97
|
+
stageTypes: ["modal", "side_hint", "retry"]
|
|
98
|
+
}
|
|
99
|
+
];
|
|
100
|
+
const STAGE_TYPE_LABELS = {
|
|
101
|
+
side_hint: "Side-hint",
|
|
102
|
+
modal: "Modal",
|
|
103
|
+
exit_intent: "Exit intent",
|
|
104
|
+
retry: "Retry"
|
|
105
|
+
};
|
|
106
|
+
const parseValue = (value) => {
|
|
107
|
+
if (!value) return {};
|
|
108
|
+
if (typeof value === "object" && !Array.isArray(value)) return value;
|
|
109
|
+
if (typeof value === "string") {
|
|
110
|
+
try {
|
|
111
|
+
const parsed = JSON.parse(value);
|
|
112
|
+
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) return parsed;
|
|
113
|
+
} catch {
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return {};
|
|
117
|
+
};
|
|
118
|
+
const serialize = (params) => {
|
|
119
|
+
const clean = {};
|
|
120
|
+
for (const [key, val] of Object.entries(params)) {
|
|
121
|
+
if (val !== void 0 && val !== null) {
|
|
122
|
+
clean[key] = val;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return JSON.stringify(clean);
|
|
126
|
+
};
|
|
127
|
+
const useThemeColors = () => {
|
|
128
|
+
const theme = styledComponents.useTheme();
|
|
129
|
+
const isDark = theme?.colors?.neutral0 === "#212134";
|
|
130
|
+
return React.useMemo(
|
|
131
|
+
() => ({
|
|
132
|
+
isDark,
|
|
133
|
+
emptyBorder: isDark ? "#32324d" : "#dcdce4",
|
|
134
|
+
cardBorder: isDark ? "#32324d" : "#eaeaef",
|
|
135
|
+
tagBg: isDark ? "#2d2d4a" : "#f0f0ff"
|
|
136
|
+
}),
|
|
137
|
+
[isDark]
|
|
138
|
+
);
|
|
139
|
+
};
|
|
140
|
+
const TriggerParamsField = React.forwardRef(
|
|
141
|
+
({ name, value, onChange, intlLabel, disabled, error, required, hint }, ref) => {
|
|
142
|
+
const [params, setParams] = React.useState(() => parseValue(value));
|
|
143
|
+
const colors = useThemeColors();
|
|
144
|
+
React.useEffect(() => {
|
|
145
|
+
setParams(parseValue(value));
|
|
146
|
+
}, [value]);
|
|
147
|
+
const update = (next) => {
|
|
148
|
+
setParams(next);
|
|
149
|
+
onChange({ target: { name, value: serialize(next) } });
|
|
150
|
+
};
|
|
151
|
+
const activeKeys = Object.keys(params).filter(
|
|
152
|
+
(k) => params[k] !== void 0 && params[k] !== null
|
|
153
|
+
);
|
|
154
|
+
const availableParams = TRIGGER_PARAMS.filter((p) => !activeKeys.includes(p.key));
|
|
155
|
+
const addParam = (key) => {
|
|
156
|
+
const def = TRIGGER_PARAMS.find((p) => p.key === key);
|
|
157
|
+
if (!def) return;
|
|
158
|
+
update({ ...params, [key]: void 0 });
|
|
159
|
+
};
|
|
160
|
+
const removeParam = (key) => {
|
|
161
|
+
const next = { ...params };
|
|
162
|
+
delete next[key];
|
|
163
|
+
update(next);
|
|
164
|
+
};
|
|
165
|
+
const setParamValue = (key, val) => {
|
|
166
|
+
update({ ...params, [key]: val });
|
|
167
|
+
};
|
|
168
|
+
const getParamDef = (key) => TRIGGER_PARAMS.find((p) => p.key === key);
|
|
169
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Root, { name, error, required, hint, ref, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 3, children: [
|
|
170
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
|
|
171
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: intlLabel?.defaultMessage || "Trigger Params" }),
|
|
172
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", children: "Настройте параметры срабатывания для этого этапа" })
|
|
173
|
+
] }) }),
|
|
174
|
+
activeKeys.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
175
|
+
designSystem.Box,
|
|
176
|
+
{
|
|
177
|
+
padding: 5,
|
|
178
|
+
background: "neutral100",
|
|
179
|
+
hasRadius: true,
|
|
180
|
+
style: {
|
|
181
|
+
border: `2px dashed ${colors.emptyBorder}`,
|
|
182
|
+
textAlign: "center"
|
|
183
|
+
},
|
|
184
|
+
children: [
|
|
185
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", textColor: "neutral500", children: "Параметры не настроены" }),
|
|
186
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
187
|
+
designSystem.Typography,
|
|
188
|
+
{
|
|
189
|
+
variant: "pi",
|
|
190
|
+
textColor: "neutral400",
|
|
191
|
+
style: { display: "block", marginTop: 4 },
|
|
192
|
+
children: "Добавьте параметры триггера, чтобы управлять условиями показа этапа"
|
|
193
|
+
}
|
|
194
|
+
)
|
|
195
|
+
]
|
|
196
|
+
}
|
|
197
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", gap: 2, children: activeKeys.map((key) => {
|
|
198
|
+
const def = getParamDef(key);
|
|
199
|
+
if (!def) return null;
|
|
200
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
201
|
+
designSystem.Card,
|
|
202
|
+
{
|
|
203
|
+
background: "neutral0",
|
|
204
|
+
style: {
|
|
205
|
+
border: `1px solid ${colors.cardBorder}`
|
|
206
|
+
},
|
|
207
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.CardContent, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "center", padding: 3, children: [
|
|
208
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: 1, minWidth: 0 }, children: [
|
|
209
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", marginBottom: 1, children: [
|
|
210
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: def.label }),
|
|
211
|
+
def.unit && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral500", children: [
|
|
212
|
+
"(",
|
|
213
|
+
def.unit,
|
|
214
|
+
")"
|
|
215
|
+
] })
|
|
216
|
+
] }),
|
|
217
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", children: def.description }),
|
|
218
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, marginTop: 1, wrap: "wrap", children: def.stageTypes.map((st) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
219
|
+
designSystem.Box,
|
|
220
|
+
{
|
|
221
|
+
style: {
|
|
222
|
+
padding: "1px 6px",
|
|
223
|
+
borderRadius: "4px",
|
|
224
|
+
backgroundColor: colors.tagBg,
|
|
225
|
+
fontSize: "11px"
|
|
226
|
+
},
|
|
227
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "primary600", children: STAGE_TYPE_LABELS[st] || st })
|
|
228
|
+
},
|
|
229
|
+
st
|
|
230
|
+
)) })
|
|
231
|
+
] }),
|
|
232
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { width: 120, flexShrink: 0 }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
233
|
+
designSystem.NumberInput,
|
|
234
|
+
{
|
|
235
|
+
placeholder: def.placeholder,
|
|
236
|
+
value: params[key] ?? "",
|
|
237
|
+
onValueChange: (val) => setParamValue(key, val),
|
|
238
|
+
disabled,
|
|
239
|
+
size: "S",
|
|
240
|
+
step: key === "balanceThresholdMultiplier" ? 0.1 : 1
|
|
241
|
+
}
|
|
242
|
+
) }),
|
|
243
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { label: "Удалить параметр", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
244
|
+
designSystem.IconButton,
|
|
245
|
+
{
|
|
246
|
+
onClick: () => removeParam(key),
|
|
247
|
+
label: "Delete",
|
|
248
|
+
variant: "ghost",
|
|
249
|
+
size: "S",
|
|
250
|
+
disabled,
|
|
251
|
+
style: { color: "#d02b20", flexShrink: 0 },
|
|
252
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, { width: 16, height: 16 })
|
|
253
|
+
}
|
|
254
|
+
) })
|
|
255
|
+
] }) })
|
|
256
|
+
},
|
|
257
|
+
key
|
|
258
|
+
);
|
|
259
|
+
}) }),
|
|
260
|
+
availableParams.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
261
|
+
AddParamSelect,
|
|
262
|
+
{
|
|
263
|
+
available: availableParams,
|
|
264
|
+
onAdd: addParam,
|
|
265
|
+
disabled
|
|
266
|
+
}
|
|
267
|
+
),
|
|
268
|
+
error && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {}),
|
|
269
|
+
hint && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
|
|
270
|
+
] }) });
|
|
271
|
+
}
|
|
272
|
+
);
|
|
273
|
+
TriggerParamsField.displayName = "TriggerParamsField";
|
|
274
|
+
const AddParamSelect = ({ available, onAdd, disabled }) => {
|
|
275
|
+
const [selected, setSelected] = React.useState(null);
|
|
276
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "flex-end", children: [
|
|
277
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { flex: 1 }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
278
|
+
designSystem.SingleSelect,
|
|
279
|
+
{
|
|
280
|
+
placeholder: "Выберите параметр...",
|
|
281
|
+
value: selected,
|
|
282
|
+
onChange: (val) => setSelected(val),
|
|
283
|
+
disabled,
|
|
284
|
+
size: "S",
|
|
285
|
+
children: available.map((p) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.SingleSelectOption, { value: p.key, children: [
|
|
286
|
+
p.label,
|
|
287
|
+
" — ",
|
|
288
|
+
p.description
|
|
289
|
+
] }, p.key))
|
|
290
|
+
}
|
|
291
|
+
) }),
|
|
292
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
293
|
+
designSystem.Button,
|
|
294
|
+
{
|
|
295
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}),
|
|
296
|
+
onClick: () => {
|
|
297
|
+
if (selected) {
|
|
298
|
+
onAdd(selected);
|
|
299
|
+
setSelected(null);
|
|
300
|
+
}
|
|
301
|
+
},
|
|
302
|
+
disabled: disabled || !selected,
|
|
303
|
+
variant: "secondary",
|
|
304
|
+
size: "S",
|
|
305
|
+
children: "Добавить"
|
|
306
|
+
}
|
|
307
|
+
)
|
|
308
|
+
] });
|
|
309
|
+
};
|
|
310
|
+
exports.default = TriggerParamsField;
|
|
@@ -53,8 +53,9 @@ const ValueInput = ({
|
|
|
53
53
|
/* @__PURE__ */ jsx(
|
|
54
54
|
Switch,
|
|
55
55
|
{
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
onLabel: "",
|
|
57
|
+
offLabel: "",
|
|
58
|
+
checked: boolVal,
|
|
58
59
|
onChange: () => onChange(!boolVal),
|
|
59
60
|
disabled
|
|
60
61
|
}
|
|
@@ -104,7 +105,7 @@ const ValueInput = ({
|
|
|
104
105
|
SingleSelect,
|
|
105
106
|
{
|
|
106
107
|
value: unit,
|
|
107
|
-
onChange: (val) => onChange(createTimeAgoValue(amount, val)),
|
|
108
|
+
onChange: (val) => onChange(createTimeAgoValue(amount, String(val))),
|
|
108
109
|
disabled,
|
|
109
110
|
size: "S",
|
|
110
111
|
children: TIME_UNITS.map((u) => /* @__PURE__ */ jsx(SingleSelectOption, { value: u.value, children: u.label }, u.value))
|
|
@@ -231,7 +232,7 @@ const RuleRow = ({ rule, onUpdate, onDelete, disabled }) => {
|
|
|
231
232
|
SingleSelect,
|
|
232
233
|
{
|
|
233
234
|
value: rule.field,
|
|
234
|
-
onChange: (val) => handleFieldChange(val),
|
|
235
|
+
onChange: (val) => handleFieldChange(String(val)),
|
|
235
236
|
disabled,
|
|
236
237
|
size: "S",
|
|
237
238
|
children: Object.entries(METRICS_BY_CATEGORY).map(([category, metrics]) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
@@ -2826,7 +2826,7 @@ const StatsView = () => {
|
|
|
2826
2826
|
}
|
|
2827
2827
|
return chips;
|
|
2828
2828
|
}, [filters, campaigns, segments]);
|
|
2829
|
-
const totals = stats?.totals || { sent: 0, clicks: 0, click_rate: 0, deposits_1h: 0, deposit_sum_1h: 0, deposit_rate: 0 };
|
|
2829
|
+
const totals = stats?.totals || { sent: 0, clicks: 0, unique_clickers: 0, click_rate: 0, deposits_1h: 0, deposit_sum_1h: 0, deposit_rate: 0, unique_users_sent: 0 };
|
|
2830
2830
|
const previousTotals = stats?.previous_totals;
|
|
2831
2831
|
const funnel = stats?.funnel;
|
|
2832
2832
|
const timeSeries = stats?.time_series || [];
|
|
@@ -435,6 +435,7 @@ const TriggerConfigField = forwardRef(
|
|
|
435
435
|
creatable: true,
|
|
436
436
|
createMessage: (v) => `Use custom event: "${v}"`,
|
|
437
437
|
onCreateOption: (v) => {
|
|
438
|
+
if (!v) return;
|
|
438
439
|
const eventValue = extractEventValue(v);
|
|
439
440
|
handleUpdate({ eventName: eventValue });
|
|
440
441
|
setInputText(getEventLabel(eventValue));
|
|
@@ -517,7 +518,7 @@ const TriggerConfigField = forwardRef(
|
|
|
517
518
|
SingleSelect,
|
|
518
519
|
{
|
|
519
520
|
value: config.delayUnit || "minutes",
|
|
520
|
-
onChange: (val) => handleUpdate({ delayUnit: val }),
|
|
521
|
+
onChange: (val) => handleUpdate({ delayUnit: String(val) }),
|
|
521
522
|
disabled,
|
|
522
523
|
size: "S",
|
|
523
524
|
children: [
|
|
@@ -640,7 +641,7 @@ const TriggerConfigField = forwardRef(
|
|
|
640
641
|
SingleSelect,
|
|
641
642
|
{
|
|
642
643
|
value: String(config.scheduleEveryMinutes ?? 5),
|
|
643
|
-
onChange: (val) => handleUpdate({ scheduleEveryMinutes: parseInt(val, 10) || 5 }),
|
|
644
|
+
onChange: (val) => handleUpdate({ scheduleEveryMinutes: parseInt(String(val), 10) || 5 }),
|
|
644
645
|
disabled,
|
|
645
646
|
size: "S",
|
|
646
647
|
children: [
|
|
@@ -758,8 +759,8 @@ const TriggerConfigField = forwardRef(
|
|
|
758
759
|
]
|
|
759
760
|
}
|
|
760
761
|
),
|
|
761
|
-
error && /* @__PURE__ */ jsx(Field.Error, {
|
|
762
|
-
hint && /* @__PURE__ */ jsx(Field.Hint, {
|
|
762
|
+
error && /* @__PURE__ */ jsx(Field.Error, {}),
|
|
763
|
+
hint && /* @__PURE__ */ jsx(Field.Hint, {})
|
|
763
764
|
] }) });
|
|
764
765
|
}
|
|
765
766
|
);
|
|
@@ -2822,7 +2822,7 @@ const StatsView = () => {
|
|
|
2822
2822
|
}
|
|
2823
2823
|
return chips;
|
|
2824
2824
|
}, [filters, campaigns, segments]);
|
|
2825
|
-
const totals = stats?.totals || { sent: 0, clicks: 0, click_rate: 0, deposits_1h: 0, deposit_sum_1h: 0, deposit_rate: 0 };
|
|
2825
|
+
const totals = stats?.totals || { sent: 0, clicks: 0, unique_clickers: 0, click_rate: 0, deposits_1h: 0, deposit_sum_1h: 0, deposit_rate: 0, unique_users_sent: 0 };
|
|
2826
2826
|
const previousTotals = stats?.previous_totals;
|
|
2827
2827
|
const funnel = stats?.funnel;
|
|
2828
2828
|
const timeSeries = stats?.time_series || [];
|