@inspirer-dev/crm-dashboard 1.0.84 → 1.0.85
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 +94 -58
- package/admin/src/components/TriggerParamsField/index.tsx +2 -2
- package/admin/src/types/crm.ts +3 -1
- package/dist/_chunks/{index-Cmo9If32.js → index-CqRPcaXV.js} +1 -1
- package/dist/_chunks/{index-BKfFI_Jo.mjs → index-DRhcN7TG.mjs} +72 -50
- package/dist/_chunks/{index-Bot_XlI2.mjs → index-DnyoVNLo.mjs} +1 -1
- package/dist/_chunks/{index-Cg0G_bTE.js → index-u-jR-zfs.js} +70 -48
- package/dist/admin/index.js +2 -2
- package/dist/admin/index.mjs +2 -2
- package/package.json +1 -1
|
@@ -10,16 +10,20 @@ import {
|
|
|
10
10
|
Tooltip,
|
|
11
11
|
Card,
|
|
12
12
|
CardContent,
|
|
13
|
+
SingleSelect,
|
|
14
|
+
SingleSelectOption,
|
|
13
15
|
} from '@strapi/design-system';
|
|
14
|
-
import { Plus, Trash, ArrowUp, ArrowDown, Link as LinkIcon } from '@strapi/icons';
|
|
16
|
+
import { Plus, Trash, ArrowUp, ArrowDown, Link as LinkIcon, Layout } from '@strapi/icons';
|
|
15
17
|
import { useTheme } from 'styled-components';
|
|
16
18
|
import { generateId } from '../RulesBuilder/utils';
|
|
17
19
|
|
|
18
20
|
type TelegramButton = {
|
|
19
21
|
id: string;
|
|
20
22
|
text: string;
|
|
21
|
-
url
|
|
23
|
+
url?: string;
|
|
22
24
|
row?: number;
|
|
25
|
+
type?: 'url' | 'screen';
|
|
26
|
+
screenSlug?: string;
|
|
23
27
|
};
|
|
24
28
|
|
|
25
29
|
interface ButtonsBuilderProps {
|
|
@@ -37,26 +41,25 @@ interface ButtonsBuilderProps {
|
|
|
37
41
|
hint?: string;
|
|
38
42
|
}
|
|
39
43
|
|
|
44
|
+
const mapRawButton = (b: any): TelegramButton => ({
|
|
45
|
+
id: typeof b?.id === 'string' ? b.id : generateId(),
|
|
46
|
+
text: typeof b?.text === 'string' ? b.text : '',
|
|
47
|
+
url: typeof b?.url === 'string' ? b.url : '',
|
|
48
|
+
row: typeof b?.row === 'number' ? b.row : 0,
|
|
49
|
+
type: b?.type === 'screen' ? 'screen' : 'url',
|
|
50
|
+
screenSlug: typeof b?.screenSlug === 'string' ? b.screenSlug : '',
|
|
51
|
+
});
|
|
52
|
+
|
|
40
53
|
const parseButtons = (value: string | TelegramButton[] | null | undefined): TelegramButton[] => {
|
|
41
54
|
if (!value) return [];
|
|
42
55
|
if (Array.isArray(value)) {
|
|
43
|
-
return value.map(
|
|
44
|
-
id: typeof b?.id === 'string' ? b.id : generateId(),
|
|
45
|
-
text: typeof b?.text === 'string' ? b.text : '',
|
|
46
|
-
url: typeof b?.url === 'string' ? b.url : '',
|
|
47
|
-
row: typeof b?.row === 'number' ? b.row : 0,
|
|
48
|
-
}));
|
|
56
|
+
return value.map(mapRawButton);
|
|
49
57
|
}
|
|
50
58
|
if (typeof value === 'string') {
|
|
51
59
|
try {
|
|
52
60
|
const parsed = JSON.parse(value);
|
|
53
61
|
if (!Array.isArray(parsed)) return [];
|
|
54
|
-
return parsed.map(
|
|
55
|
-
id: typeof b?.id === 'string' ? b.id : generateId(),
|
|
56
|
-
text: typeof b?.text === 'string' ? b.text : '',
|
|
57
|
-
url: typeof b?.url === 'string' ? b.url : '',
|
|
58
|
-
row: typeof b?.row === 'number' ? b.row : 0,
|
|
59
|
-
}));
|
|
62
|
+
return parsed.map(mapRawButton);
|
|
60
63
|
} catch {
|
|
61
64
|
return [];
|
|
62
65
|
}
|
|
@@ -103,35 +106,39 @@ const useThemeColors = () => {
|
|
|
103
106
|
}), [isDark]);
|
|
104
107
|
};
|
|
105
108
|
|
|
106
|
-
const TelegramButtonPreview: React.FC<{ text: string; url
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
109
|
+
const TelegramButtonPreview: React.FC<{ text: string; btnType?: 'url' | 'screen' }> = ({ text, btnType }) => {
|
|
110
|
+
const isScreen = btnType === 'screen';
|
|
111
|
+
const bgColor = isScreen ? '#7c3aed' : '#3390ec';
|
|
112
|
+
const bgHover = isScreen ? '#6d28d9' : '#2b7ed8';
|
|
113
|
+
return (
|
|
114
|
+
<span
|
|
115
|
+
style={{
|
|
116
|
+
display: 'inline-flex',
|
|
117
|
+
alignItems: 'center',
|
|
118
|
+
justifyContent: 'center',
|
|
119
|
+
gap: '6px',
|
|
120
|
+
padding: '8px 16px',
|
|
121
|
+
backgroundColor: bgColor,
|
|
122
|
+
color: '#ffffff',
|
|
123
|
+
borderRadius: '8px',
|
|
124
|
+
textDecoration: 'none',
|
|
125
|
+
fontSize: '14px',
|
|
126
|
+
fontWeight: 500,
|
|
127
|
+
cursor: 'default',
|
|
128
|
+
transition: 'background-color 0.15s ease',
|
|
129
|
+
minWidth: '80px',
|
|
130
|
+
}}
|
|
131
|
+
onMouseEnter={(e) => (e.currentTarget.style.backgroundColor = bgHover)}
|
|
132
|
+
onMouseLeave={(e) => (e.currentTarget.style.backgroundColor = bgColor)}
|
|
133
|
+
>
|
|
134
|
+
{isScreen
|
|
135
|
+
? <Layout width={14} height={14} style={{ opacity: 0.9 }} />
|
|
136
|
+
: <LinkIcon width={14} height={14} style={{ opacity: 0.9 }} />
|
|
137
|
+
}
|
|
138
|
+
<span>{text || '(empty)'}</span>
|
|
139
|
+
</span>
|
|
140
|
+
);
|
|
141
|
+
};
|
|
135
142
|
|
|
136
143
|
const ButtonsBuilder = forwardRef<HTMLDivElement, ButtonsBuilderProps>(
|
|
137
144
|
({ name, value, onChange, intlLabel, disabled, error, required, hint }, ref) => {
|
|
@@ -150,7 +157,7 @@ const ButtonsBuilder = forwardRef<HTMLDivElement, ButtonsBuilderProps>(
|
|
|
150
157
|
const addButton = () => {
|
|
151
158
|
update([
|
|
152
159
|
...buttons,
|
|
153
|
-
{ id: generateId(), text: 'Button', url: 'https://cases.gg', row: 0 },
|
|
160
|
+
{ id: generateId(), text: 'Button', url: 'https://cases.gg', row: 0, type: 'url', screenSlug: '' },
|
|
154
161
|
]);
|
|
155
162
|
};
|
|
156
163
|
|
|
@@ -222,7 +229,8 @@ const ButtonsBuilder = forwardRef<HTMLDivElement, ButtonsBuilderProps>(
|
|
|
222
229
|
) : (
|
|
223
230
|
<Flex direction="column" gap={2}>
|
|
224
231
|
{buttons.map((btn, idx) => {
|
|
225
|
-
const
|
|
232
|
+
const isScreen = btn.type === 'screen';
|
|
233
|
+
const urlOk = isScreen || (btn.url ?? '').length === 0 || isValidUrl(btn.url ?? '');
|
|
226
234
|
return (
|
|
227
235
|
<Card
|
|
228
236
|
key={btn.id}
|
|
@@ -251,31 +259,59 @@ const ButtonsBuilder = forwardRef<HTMLDivElement, ButtonsBuilderProps>(
|
|
|
251
259
|
</Typography>
|
|
252
260
|
</Box>
|
|
253
261
|
|
|
254
|
-
<Box style={{
|
|
255
|
-
<
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
updateButton(btn.id, { text: e.target.value })
|
|
262
|
+
<Box style={{ width: 100, flexShrink: 0 }}>
|
|
263
|
+
<SingleSelect
|
|
264
|
+
value={btn.type || 'url'}
|
|
265
|
+
onChange={(val: string) =>
|
|
266
|
+
updateButton(btn.id, { type: val as 'url' | 'screen' })
|
|
260
267
|
}
|
|
261
268
|
disabled={disabled}
|
|
262
269
|
size="S"
|
|
263
|
-
|
|
270
|
+
>
|
|
271
|
+
<SingleSelectOption value="url">URL</SingleSelectOption>
|
|
272
|
+
<SingleSelectOption value="screen">Screen</SingleSelectOption>
|
|
273
|
+
</SingleSelect>
|
|
264
274
|
</Box>
|
|
265
275
|
|
|
266
|
-
<Box style={{ flex:
|
|
276
|
+
<Box style={{ flex: 1, minWidth: 120 }}>
|
|
267
277
|
<TextInput
|
|
268
|
-
placeholder="
|
|
269
|
-
value={btn.
|
|
278
|
+
placeholder="Button text"
|
|
279
|
+
value={btn.text}
|
|
270
280
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
271
|
-
updateButton(btn.id, {
|
|
281
|
+
updateButton(btn.id, { text: e.target.value })
|
|
272
282
|
}
|
|
273
283
|
disabled={disabled}
|
|
274
284
|
size="S"
|
|
275
|
-
hasError={!urlOk}
|
|
276
285
|
/>
|
|
277
286
|
</Box>
|
|
278
287
|
|
|
288
|
+
{isScreen ? (
|
|
289
|
+
<Box style={{ flex: 2, minWidth: 180 }}>
|
|
290
|
+
<TextInput
|
|
291
|
+
placeholder="screen-slug"
|
|
292
|
+
value={btn.screenSlug ?? ''}
|
|
293
|
+
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
294
|
+
updateButton(btn.id, { screenSlug: e.target.value })
|
|
295
|
+
}
|
|
296
|
+
disabled={disabled}
|
|
297
|
+
size="S"
|
|
298
|
+
/>
|
|
299
|
+
</Box>
|
|
300
|
+
) : (
|
|
301
|
+
<Box style={{ flex: 2, minWidth: 180 }}>
|
|
302
|
+
<TextInput
|
|
303
|
+
placeholder="https://..."
|
|
304
|
+
value={btn.url ?? ''}
|
|
305
|
+
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
306
|
+
updateButton(btn.id, { url: e.target.value })
|
|
307
|
+
}
|
|
308
|
+
disabled={disabled}
|
|
309
|
+
size="S"
|
|
310
|
+
hasError={!urlOk}
|
|
311
|
+
/>
|
|
312
|
+
</Box>
|
|
313
|
+
)}
|
|
314
|
+
|
|
279
315
|
<Box style={{ width: 60 }}>
|
|
280
316
|
<TextInput
|
|
281
317
|
type="number"
|
|
@@ -359,7 +395,7 @@ const ButtonsBuilder = forwardRef<HTMLDivElement, ButtonsBuilderProps>(
|
|
|
359
395
|
{previewRows.map((row) => (
|
|
360
396
|
<Flex key={row.row} gap={2} wrap="wrap" justifyContent="center">
|
|
361
397
|
{row.items.map((b) => (
|
|
362
|
-
<TelegramButtonPreview key={b.id} text={b.text}
|
|
398
|
+
<TelegramButtonPreview key={b.id} text={b.text} btnType={b.type} />
|
|
363
399
|
))}
|
|
364
400
|
</Flex>
|
|
365
401
|
))}
|
|
@@ -47,9 +47,9 @@ const parseValue = (value: string | TriggerParamsValue | null | undefined): Trig
|
|
|
47
47
|
};
|
|
48
48
|
|
|
49
49
|
const serialize = (params: TriggerParamsValue): string => {
|
|
50
|
-
const out: Record<string, number
|
|
50
|
+
const out: Record<string, number> = {};
|
|
51
51
|
for (const [key, val] of Object.entries(params)) {
|
|
52
|
-
|
|
52
|
+
if (typeof val === 'number') out[key] = val;
|
|
53
53
|
}
|
|
54
54
|
return JSON.stringify(out);
|
|
55
55
|
};
|
package/admin/src/types/crm.ts
CHANGED
|
@@ -118,7 +118,7 @@ const parseValue = (value) => {
|
|
|
118
118
|
const serialize = (params) => {
|
|
119
119
|
const out = {};
|
|
120
120
|
for (const [key, val] of Object.entries(params)) {
|
|
121
|
-
|
|
121
|
+
if (typeof val === "number") out[key] = val;
|
|
122
122
|
}
|
|
123
123
|
return JSON.stringify(out);
|
|
124
124
|
};
|
|
@@ -1,29 +1,27 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef, useState, useEffect, useMemo } from "react";
|
|
3
|
-
import { Field, Flex, Box, Typography, Button, Card, CardContent, TextInput, Tooltip, IconButton } from "@strapi/design-system";
|
|
4
|
-
import { Plus, ArrowUp, ArrowDown, Trash, Link } from "@strapi/icons";
|
|
3
|
+
import { Field, Flex, Box, Typography, Button, Card, CardContent, SingleSelect, SingleSelectOption, TextInput, Tooltip, IconButton } from "@strapi/design-system";
|
|
4
|
+
import { Plus, ArrowUp, ArrowDown, Trash, Layout, Link } from "@strapi/icons";
|
|
5
5
|
import { useTheme } from "styled-components";
|
|
6
6
|
import { m as generateId } from "./utils-BHneBJ7U.mjs";
|
|
7
|
+
const mapRawButton = (b) => ({
|
|
8
|
+
id: typeof b?.id === "string" ? b.id : generateId(),
|
|
9
|
+
text: typeof b?.text === "string" ? b.text : "",
|
|
10
|
+
url: typeof b?.url === "string" ? b.url : "",
|
|
11
|
+
row: typeof b?.row === "number" ? b.row : 0,
|
|
12
|
+
type: b?.type === "screen" ? "screen" : "url",
|
|
13
|
+
screenSlug: typeof b?.screenSlug === "string" ? b.screenSlug : ""
|
|
14
|
+
});
|
|
7
15
|
const parseButtons = (value) => {
|
|
8
16
|
if (!value) return [];
|
|
9
17
|
if (Array.isArray(value)) {
|
|
10
|
-
return value.map(
|
|
11
|
-
id: typeof b?.id === "string" ? b.id : generateId(),
|
|
12
|
-
text: typeof b?.text === "string" ? b.text : "",
|
|
13
|
-
url: typeof b?.url === "string" ? b.url : "",
|
|
14
|
-
row: typeof b?.row === "number" ? b.row : 0
|
|
15
|
-
}));
|
|
18
|
+
return value.map(mapRawButton);
|
|
16
19
|
}
|
|
17
20
|
if (typeof value === "string") {
|
|
18
21
|
try {
|
|
19
22
|
const parsed = JSON.parse(value);
|
|
20
23
|
if (!Array.isArray(parsed)) return [];
|
|
21
|
-
return parsed.map(
|
|
22
|
-
id: typeof b?.id === "string" ? b.id : generateId(),
|
|
23
|
-
text: typeof b?.text === "string" ? b.text : "",
|
|
24
|
-
url: typeof b?.url === "string" ? b.url : "",
|
|
25
|
-
row: typeof b?.row === "number" ? b.row : 0
|
|
26
|
-
}));
|
|
24
|
+
return parsed.map(mapRawButton);
|
|
27
25
|
} catch {
|
|
28
26
|
return [];
|
|
29
27
|
}
|
|
@@ -59,37 +57,38 @@ const useThemeColors = () => {
|
|
|
59
57
|
}
|
|
60
58
|
}), [isDark]);
|
|
61
59
|
};
|
|
62
|
-
const TelegramButtonPreview = ({ text,
|
|
63
|
-
"
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
);
|
|
60
|
+
const TelegramButtonPreview = ({ text, btnType }) => {
|
|
61
|
+
const isScreen = btnType === "screen";
|
|
62
|
+
const bgColor = isScreen ? "#7c3aed" : "#3390ec";
|
|
63
|
+
const bgHover = isScreen ? "#6d28d9" : "#2b7ed8";
|
|
64
|
+
return /* @__PURE__ */ jsxs(
|
|
65
|
+
"span",
|
|
66
|
+
{
|
|
67
|
+
style: {
|
|
68
|
+
display: "inline-flex",
|
|
69
|
+
alignItems: "center",
|
|
70
|
+
justifyContent: "center",
|
|
71
|
+
gap: "6px",
|
|
72
|
+
padding: "8px 16px",
|
|
73
|
+
backgroundColor: bgColor,
|
|
74
|
+
color: "#ffffff",
|
|
75
|
+
borderRadius: "8px",
|
|
76
|
+
textDecoration: "none",
|
|
77
|
+
fontSize: "14px",
|
|
78
|
+
fontWeight: 500,
|
|
79
|
+
cursor: "default",
|
|
80
|
+
transition: "background-color 0.15s ease",
|
|
81
|
+
minWidth: "80px"
|
|
82
|
+
},
|
|
83
|
+
onMouseEnter: (e) => e.currentTarget.style.backgroundColor = bgHover,
|
|
84
|
+
onMouseLeave: (e) => e.currentTarget.style.backgroundColor = bgColor,
|
|
85
|
+
children: [
|
|
86
|
+
isScreen ? /* @__PURE__ */ jsx(Layout, { width: 14, height: 14, style: { opacity: 0.9 } }) : /* @__PURE__ */ jsx(Link, { width: 14, height: 14, style: { opacity: 0.9 } }),
|
|
87
|
+
/* @__PURE__ */ jsx("span", { children: text || "(empty)" })
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
};
|
|
93
92
|
const ButtonsBuilder = forwardRef(
|
|
94
93
|
({ name, value, onChange, intlLabel, disabled, error, required, hint }, ref) => {
|
|
95
94
|
const [buttons, setButtons] = useState(() => parseButtons(value));
|
|
@@ -104,7 +103,7 @@ const ButtonsBuilder = forwardRef(
|
|
|
104
103
|
const addButton = () => {
|
|
105
104
|
update([
|
|
106
105
|
...buttons,
|
|
107
|
-
{ id: generateId(), text: "Button", url: "https://cases.gg", row: 0 }
|
|
106
|
+
{ id: generateId(), text: "Button", url: "https://cases.gg", row: 0, type: "url", screenSlug: "" }
|
|
108
107
|
]);
|
|
109
108
|
};
|
|
110
109
|
const updateButton = (id, patch) => {
|
|
@@ -162,7 +161,8 @@ const ButtonsBuilder = forwardRef(
|
|
|
162
161
|
]
|
|
163
162
|
}
|
|
164
163
|
) : /* @__PURE__ */ jsx(Flex, { direction: "column", gap: 2, children: buttons.map((btn, idx) => {
|
|
165
|
-
const
|
|
164
|
+
const isScreen = btn.type === "screen";
|
|
165
|
+
const urlOk = isScreen || (btn.url ?? "").length === 0 || isValidUrl(btn.url ?? "");
|
|
166
166
|
return /* @__PURE__ */ jsx(
|
|
167
167
|
Card,
|
|
168
168
|
{
|
|
@@ -189,6 +189,19 @@ const ButtonsBuilder = forwardRef(
|
|
|
189
189
|
children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "primary600", children: idx + 1 })
|
|
190
190
|
}
|
|
191
191
|
),
|
|
192
|
+
/* @__PURE__ */ jsx(Box, { style: { width: 100, flexShrink: 0 }, children: /* @__PURE__ */ jsxs(
|
|
193
|
+
SingleSelect,
|
|
194
|
+
{
|
|
195
|
+
value: btn.type || "url",
|
|
196
|
+
onChange: (val) => updateButton(btn.id, { type: val }),
|
|
197
|
+
disabled,
|
|
198
|
+
size: "S",
|
|
199
|
+
children: [
|
|
200
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "url", children: "URL" }),
|
|
201
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "screen", children: "Screen" })
|
|
202
|
+
]
|
|
203
|
+
}
|
|
204
|
+
) }),
|
|
192
205
|
/* @__PURE__ */ jsx(Box, { style: { flex: 1, minWidth: 120 }, children: /* @__PURE__ */ jsx(
|
|
193
206
|
TextInput,
|
|
194
207
|
{
|
|
@@ -199,11 +212,20 @@ const ButtonsBuilder = forwardRef(
|
|
|
199
212
|
size: "S"
|
|
200
213
|
}
|
|
201
214
|
) }),
|
|
202
|
-
/* @__PURE__ */ jsx(Box, { style: { flex: 2, minWidth: 180 }, children: /* @__PURE__ */ jsx(
|
|
215
|
+
isScreen ? /* @__PURE__ */ jsx(Box, { style: { flex: 2, minWidth: 180 }, children: /* @__PURE__ */ jsx(
|
|
216
|
+
TextInput,
|
|
217
|
+
{
|
|
218
|
+
placeholder: "screen-slug",
|
|
219
|
+
value: btn.screenSlug ?? "",
|
|
220
|
+
onChange: (e) => updateButton(btn.id, { screenSlug: e.target.value }),
|
|
221
|
+
disabled,
|
|
222
|
+
size: "S"
|
|
223
|
+
}
|
|
224
|
+
) }) : /* @__PURE__ */ jsx(Box, { style: { flex: 2, minWidth: 180 }, children: /* @__PURE__ */ jsx(
|
|
203
225
|
TextInput,
|
|
204
226
|
{
|
|
205
227
|
placeholder: "https://...",
|
|
206
|
-
value: btn.url,
|
|
228
|
+
value: btn.url ?? "",
|
|
207
229
|
onChange: (e) => updateButton(btn.id, { url: e.target.value }),
|
|
208
230
|
disabled,
|
|
209
231
|
size: "S",
|
|
@@ -282,7 +304,7 @@ const ButtonsBuilder = forwardRef(
|
|
|
282
304
|
children: "PREVIEW"
|
|
283
305
|
}
|
|
284
306
|
),
|
|
285
|
-
/* @__PURE__ */ jsx(Flex, { direction: "column", gap: 2, alignItems: "center", children: previewRows.map((row) => /* @__PURE__ */ jsx(Flex, { gap: 2, wrap: "wrap", justifyContent: "center", children: row.items.map((b) => /* @__PURE__ */ jsx(TelegramButtonPreview, { text: b.text,
|
|
307
|
+
/* @__PURE__ */ jsx(Flex, { direction: "column", gap: 2, alignItems: "center", children: previewRows.map((row) => /* @__PURE__ */ jsx(Flex, { gap: 2, wrap: "wrap", justifyContent: "center", children: row.items.map((b) => /* @__PURE__ */ jsx(TelegramButtonPreview, { text: b.text, btnType: b.type }, b.id)) }, row.row)) })
|
|
286
308
|
]
|
|
287
309
|
}
|
|
288
310
|
),
|
|
@@ -116,7 +116,7 @@ const parseValue = (value) => {
|
|
|
116
116
|
const serialize = (params) => {
|
|
117
117
|
const out = {};
|
|
118
118
|
for (const [key, val] of Object.entries(params)) {
|
|
119
|
-
|
|
119
|
+
if (typeof val === "number") out[key] = val;
|
|
120
120
|
}
|
|
121
121
|
return JSON.stringify(out);
|
|
122
122
|
};
|
|
@@ -6,26 +6,24 @@ const designSystem = require("@strapi/design-system");
|
|
|
6
6
|
const icons = require("@strapi/icons");
|
|
7
7
|
const styledComponents = require("styled-components");
|
|
8
8
|
const utils = require("./utils-CAs_GSGv.js");
|
|
9
|
+
const mapRawButton = (b) => ({
|
|
10
|
+
id: typeof b?.id === "string" ? b.id : utils.generateId(),
|
|
11
|
+
text: typeof b?.text === "string" ? b.text : "",
|
|
12
|
+
url: typeof b?.url === "string" ? b.url : "",
|
|
13
|
+
row: typeof b?.row === "number" ? b.row : 0,
|
|
14
|
+
type: b?.type === "screen" ? "screen" : "url",
|
|
15
|
+
screenSlug: typeof b?.screenSlug === "string" ? b.screenSlug : ""
|
|
16
|
+
});
|
|
9
17
|
const parseButtons = (value) => {
|
|
10
18
|
if (!value) return [];
|
|
11
19
|
if (Array.isArray(value)) {
|
|
12
|
-
return value.map(
|
|
13
|
-
id: typeof b?.id === "string" ? b.id : utils.generateId(),
|
|
14
|
-
text: typeof b?.text === "string" ? b.text : "",
|
|
15
|
-
url: typeof b?.url === "string" ? b.url : "",
|
|
16
|
-
row: typeof b?.row === "number" ? b.row : 0
|
|
17
|
-
}));
|
|
20
|
+
return value.map(mapRawButton);
|
|
18
21
|
}
|
|
19
22
|
if (typeof value === "string") {
|
|
20
23
|
try {
|
|
21
24
|
const parsed = JSON.parse(value);
|
|
22
25
|
if (!Array.isArray(parsed)) return [];
|
|
23
|
-
return parsed.map(
|
|
24
|
-
id: typeof b?.id === "string" ? b.id : utils.generateId(),
|
|
25
|
-
text: typeof b?.text === "string" ? b.text : "",
|
|
26
|
-
url: typeof b?.url === "string" ? b.url : "",
|
|
27
|
-
row: typeof b?.row === "number" ? b.row : 0
|
|
28
|
-
}));
|
|
26
|
+
return parsed.map(mapRawButton);
|
|
29
27
|
} catch {
|
|
30
28
|
return [];
|
|
31
29
|
}
|
|
@@ -61,37 +59,38 @@ const useThemeColors = () => {
|
|
|
61
59
|
}
|
|
62
60
|
}), [isDark]);
|
|
63
61
|
};
|
|
64
|
-
const TelegramButtonPreview = ({ text,
|
|
65
|
-
"
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
);
|
|
62
|
+
const TelegramButtonPreview = ({ text, btnType }) => {
|
|
63
|
+
const isScreen = btnType === "screen";
|
|
64
|
+
const bgColor = isScreen ? "#7c3aed" : "#3390ec";
|
|
65
|
+
const bgHover = isScreen ? "#6d28d9" : "#2b7ed8";
|
|
66
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
67
|
+
"span",
|
|
68
|
+
{
|
|
69
|
+
style: {
|
|
70
|
+
display: "inline-flex",
|
|
71
|
+
alignItems: "center",
|
|
72
|
+
justifyContent: "center",
|
|
73
|
+
gap: "6px",
|
|
74
|
+
padding: "8px 16px",
|
|
75
|
+
backgroundColor: bgColor,
|
|
76
|
+
color: "#ffffff",
|
|
77
|
+
borderRadius: "8px",
|
|
78
|
+
textDecoration: "none",
|
|
79
|
+
fontSize: "14px",
|
|
80
|
+
fontWeight: 500,
|
|
81
|
+
cursor: "default",
|
|
82
|
+
transition: "background-color 0.15s ease",
|
|
83
|
+
minWidth: "80px"
|
|
84
|
+
},
|
|
85
|
+
onMouseEnter: (e) => e.currentTarget.style.backgroundColor = bgHover,
|
|
86
|
+
onMouseLeave: (e) => e.currentTarget.style.backgroundColor = bgColor,
|
|
87
|
+
children: [
|
|
88
|
+
isScreen ? /* @__PURE__ */ jsxRuntime.jsx(icons.Layout, { width: 14, height: 14, style: { opacity: 0.9 } }) : /* @__PURE__ */ jsxRuntime.jsx(icons.Link, { width: 14, height: 14, style: { opacity: 0.9 } }),
|
|
89
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: text || "(empty)" })
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
};
|
|
95
94
|
const ButtonsBuilder = React.forwardRef(
|
|
96
95
|
({ name, value, onChange, intlLabel, disabled, error, required, hint }, ref) => {
|
|
97
96
|
const [buttons, setButtons] = React.useState(() => parseButtons(value));
|
|
@@ -106,7 +105,7 @@ const ButtonsBuilder = React.forwardRef(
|
|
|
106
105
|
const addButton = () => {
|
|
107
106
|
update([
|
|
108
107
|
...buttons,
|
|
109
|
-
{ id: utils.generateId(), text: "Button", url: "https://cases.gg", row: 0 }
|
|
108
|
+
{ id: utils.generateId(), text: "Button", url: "https://cases.gg", row: 0, type: "url", screenSlug: "" }
|
|
110
109
|
]);
|
|
111
110
|
};
|
|
112
111
|
const updateButton = (id, patch) => {
|
|
@@ -164,7 +163,8 @@ const ButtonsBuilder = React.forwardRef(
|
|
|
164
163
|
]
|
|
165
164
|
}
|
|
166
165
|
) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", gap: 2, children: buttons.map((btn, idx) => {
|
|
167
|
-
const
|
|
166
|
+
const isScreen = btn.type === "screen";
|
|
167
|
+
const urlOk = isScreen || (btn.url ?? "").length === 0 || isValidUrl(btn.url ?? "");
|
|
168
168
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
169
169
|
designSystem.Card,
|
|
170
170
|
{
|
|
@@ -191,6 +191,19 @@ const ButtonsBuilder = React.forwardRef(
|
|
|
191
191
|
children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "primary600", children: idx + 1 })
|
|
192
192
|
}
|
|
193
193
|
),
|
|
194
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { width: 100, flexShrink: 0 }, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
195
|
+
designSystem.SingleSelect,
|
|
196
|
+
{
|
|
197
|
+
value: btn.type || "url",
|
|
198
|
+
onChange: (val) => updateButton(btn.id, { type: val }),
|
|
199
|
+
disabled,
|
|
200
|
+
size: "S",
|
|
201
|
+
children: [
|
|
202
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "url", children: "URL" }),
|
|
203
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "screen", children: "Screen" })
|
|
204
|
+
]
|
|
205
|
+
}
|
|
206
|
+
) }),
|
|
194
207
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { flex: 1, minWidth: 120 }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
195
208
|
designSystem.TextInput,
|
|
196
209
|
{
|
|
@@ -201,11 +214,20 @@ const ButtonsBuilder = React.forwardRef(
|
|
|
201
214
|
size: "S"
|
|
202
215
|
}
|
|
203
216
|
) }),
|
|
204
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { flex: 2, minWidth: 180 }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
217
|
+
isScreen ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { flex: 2, minWidth: 180 }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
218
|
+
designSystem.TextInput,
|
|
219
|
+
{
|
|
220
|
+
placeholder: "screen-slug",
|
|
221
|
+
value: btn.screenSlug ?? "",
|
|
222
|
+
onChange: (e) => updateButton(btn.id, { screenSlug: e.target.value }),
|
|
223
|
+
disabled,
|
|
224
|
+
size: "S"
|
|
225
|
+
}
|
|
226
|
+
) }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { flex: 2, minWidth: 180 }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
205
227
|
designSystem.TextInput,
|
|
206
228
|
{
|
|
207
229
|
placeholder: "https://...",
|
|
208
|
-
value: btn.url,
|
|
230
|
+
value: btn.url ?? "",
|
|
209
231
|
onChange: (e) => updateButton(btn.id, { url: e.target.value }),
|
|
210
232
|
disabled,
|
|
211
233
|
size: "S",
|
|
@@ -284,7 +306,7 @@ const ButtonsBuilder = React.forwardRef(
|
|
|
284
306
|
children: "PREVIEW"
|
|
285
307
|
}
|
|
286
308
|
),
|
|
287
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", gap: 2, alignItems: "center", children: previewRows.map((row) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, wrap: "wrap", justifyContent: "center", children: row.items.map((b) => /* @__PURE__ */ jsxRuntime.jsx(TelegramButtonPreview, { text: b.text,
|
|
309
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", gap: 2, alignItems: "center", children: previewRows.map((row) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, wrap: "wrap", justifyContent: "center", children: row.items.map((b) => /* @__PURE__ */ jsxRuntime.jsx(TelegramButtonPreview, { text: b.text, btnType: b.type }, b.id)) }, row.row)) })
|
|
288
310
|
]
|
|
289
311
|
}
|
|
290
312
|
),
|
package/dist/admin/index.js
CHANGED
|
@@ -107,7 +107,7 @@ const index = {
|
|
|
107
107
|
components: {
|
|
108
108
|
Input: async () => Promise.resolve().then(() => require(
|
|
109
109
|
/* webpackChunkName: "crm-telegram-buttons" */
|
|
110
|
-
"../_chunks/index-
|
|
110
|
+
"../_chunks/index-u-jR-zfs.js"
|
|
111
111
|
))
|
|
112
112
|
},
|
|
113
113
|
options: {
|
|
@@ -155,7 +155,7 @@ const index = {
|
|
|
155
155
|
components: {
|
|
156
156
|
Input: async () => Promise.resolve().then(() => require(
|
|
157
157
|
/* webpackChunkName: "crm-trigger-params" */
|
|
158
|
-
"../_chunks/index-
|
|
158
|
+
"../_chunks/index-CqRPcaXV.js"
|
|
159
159
|
))
|
|
160
160
|
},
|
|
161
161
|
options: {
|
package/dist/admin/index.mjs
CHANGED
|
@@ -106,7 +106,7 @@ const index = {
|
|
|
106
106
|
components: {
|
|
107
107
|
Input: async () => import(
|
|
108
108
|
/* webpackChunkName: "crm-telegram-buttons" */
|
|
109
|
-
"../_chunks/index-
|
|
109
|
+
"../_chunks/index-DRhcN7TG.mjs"
|
|
110
110
|
)
|
|
111
111
|
},
|
|
112
112
|
options: {
|
|
@@ -154,7 +154,7 @@ const index = {
|
|
|
154
154
|
components: {
|
|
155
155
|
Input: async () => import(
|
|
156
156
|
/* webpackChunkName: "crm-trigger-params" */
|
|
157
|
-
"../_chunks/index-
|
|
157
|
+
"../_chunks/index-DnyoVNLo.mjs"
|
|
158
158
|
)
|
|
159
159
|
},
|
|
160
160
|
options: {
|