@strapi/admin 5.27.0 → 5.28.0

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.
Files changed (81) hide show
  1. package/dist/admin/admin/src/components/DragLayer.js +67 -0
  2. package/dist/admin/admin/src/components/DragLayer.js.map +1 -0
  3. package/dist/admin/admin/src/components/DragLayer.mjs +64 -0
  4. package/dist/admin/admin/src/components/DragLayer.mjs.map +1 -0
  5. package/dist/admin/admin/src/components/GapDropZone.js +292 -0
  6. package/dist/admin/admin/src/components/GapDropZone.js.map +1 -0
  7. package/dist/admin/admin/src/components/GapDropZone.mjs +268 -0
  8. package/dist/admin/admin/src/components/GapDropZone.mjs.map +1 -0
  9. package/dist/admin/admin/src/components/ResizeIndicator.js +353 -0
  10. package/dist/admin/admin/src/components/ResizeIndicator.js.map +1 -0
  11. package/dist/admin/admin/src/components/ResizeIndicator.mjs +332 -0
  12. package/dist/admin/admin/src/components/ResizeIndicator.mjs.map +1 -0
  13. package/dist/admin/admin/src/components/WidgetRoot.js +216 -0
  14. package/dist/admin/admin/src/components/WidgetRoot.js.map +1 -0
  15. package/dist/admin/admin/src/components/WidgetRoot.mjs +195 -0
  16. package/dist/admin/admin/src/components/WidgetRoot.mjs.map +1 -0
  17. package/dist/admin/admin/src/features/Tracking.js.map +1 -1
  18. package/dist/admin/admin/src/features/Tracking.mjs.map +1 -1
  19. package/dist/admin/admin/src/features/Widgets.js +276 -0
  20. package/dist/admin/admin/src/features/Widgets.js.map +1 -0
  21. package/dist/admin/admin/src/features/Widgets.mjs +255 -0
  22. package/dist/admin/admin/src/features/Widgets.mjs.map +1 -0
  23. package/dist/admin/admin/src/hooks/useAPIErrorHandler.js +1 -1
  24. package/dist/admin/admin/src/hooks/useAPIErrorHandler.js.map +1 -1
  25. package/dist/admin/admin/src/hooks/useAPIErrorHandler.mjs +1 -1
  26. package/dist/admin/admin/src/hooks/useAPIErrorHandler.mjs.map +1 -1
  27. package/dist/admin/admin/src/pages/Home/HomePage.js +160 -91
  28. package/dist/admin/admin/src/pages/Home/HomePage.js.map +1 -1
  29. package/dist/admin/admin/src/pages/Home/HomePage.mjs +162 -93
  30. package/dist/admin/admin/src/pages/Home/HomePage.mjs.map +1 -1
  31. package/dist/admin/admin/src/pages/Home/components/AddWidgetModal.js +189 -0
  32. package/dist/admin/admin/src/pages/Home/components/AddWidgetModal.js.map +1 -0
  33. package/dist/admin/admin/src/pages/Home/components/AddWidgetModal.mjs +168 -0
  34. package/dist/admin/admin/src/pages/Home/components/AddWidgetModal.mjs.map +1 -0
  35. package/dist/admin/admin/src/services/homepage.js +11 -4
  36. package/dist/admin/admin/src/services/homepage.js.map +1 -1
  37. package/dist/admin/admin/src/services/homepage.mjs +11 -4
  38. package/dist/admin/admin/src/services/homepage.mjs.map +1 -1
  39. package/dist/admin/admin/src/translations/en.json.js +6 -1
  40. package/dist/admin/admin/src/translations/en.json.js.map +1 -1
  41. package/dist/admin/admin/src/translations/en.json.mjs +6 -1
  42. package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
  43. package/dist/admin/admin/src/translations/uk.json.js +9 -9
  44. package/dist/admin/admin/src/translations/uk.json.mjs +9 -9
  45. package/dist/admin/admin/src/utils/resizeHandlers.js +109 -0
  46. package/dist/admin/admin/src/utils/resizeHandlers.js.map +1 -0
  47. package/dist/admin/admin/src/utils/resizeHandlers.mjs +100 -0
  48. package/dist/admin/admin/src/utils/resizeHandlers.mjs.map +1 -0
  49. package/dist/admin/admin/src/utils/widgetLayout.js +293 -0
  50. package/dist/admin/admin/src/utils/widgetLayout.js.map +1 -0
  51. package/dist/admin/admin/src/utils/widgetLayout.mjs +273 -0
  52. package/dist/admin/admin/src/utils/widgetLayout.mjs.map +1 -0
  53. package/dist/admin/src/components/DragLayer.d.ts +8 -4
  54. package/dist/admin/src/components/GapDropZone.d.ts +36 -0
  55. package/dist/admin/src/components/ResizeIndicator.d.ts +12 -0
  56. package/dist/admin/src/components/WidgetRoot.d.ts +14 -0
  57. package/dist/admin/src/features/Tracking.d.ts +1 -1
  58. package/dist/admin/src/features/Widgets.d.ts +29 -0
  59. package/dist/admin/src/pages/Home/HomePage.d.ts +4 -5
  60. package/dist/admin/src/pages/Home/components/AddWidgetModal.d.ts +10 -0
  61. package/dist/admin/src/services/homepage.d.ts +3 -3
  62. package/dist/admin/src/utils/resizeHandlers.d.ts +58 -0
  63. package/dist/admin/src/utils/widgetLayout.d.ts +78 -0
  64. package/dist/ee/server/src/controllers/authentication-utils/middlewares.d.ts.map +1 -1
  65. package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.js +4 -2
  66. package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.js.map +1 -1
  67. package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.mjs +4 -2
  68. package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.mjs.map +1 -1
  69. package/dist/server/server/src/bootstrap.js +5 -0
  70. package/dist/server/server/src/bootstrap.js.map +1 -1
  71. package/dist/server/server/src/bootstrap.mjs +5 -0
  72. package/dist/server/server/src/bootstrap.mjs.map +1 -1
  73. package/dist/server/shared/utils/session-auth.js +4 -2
  74. package/dist/server/shared/utils/session-auth.js.map +1 -1
  75. package/dist/server/shared/utils/session-auth.mjs +4 -2
  76. package/dist/server/shared/utils/session-auth.mjs.map +1 -1
  77. package/dist/server/src/bootstrap.d.ts.map +1 -1
  78. package/dist/shared/contracts/homepage.d.ts +8 -4
  79. package/dist/shared/contracts/homepage.d.ts.map +1 -1
  80. package/dist/shared/utils/session-auth.d.ts.map +1 -1
  81. package/package.json +7 -7
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WidgetRoot.js","sources":["../../../../../admin/src/components/WidgetRoot.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box, Flex, Typography, ScrollArea, IconButton } from '@strapi/design-system';\nimport { PuzzlePiece, Trash, Drag } from '@strapi/icons';\nimport { useDrag } from 'react-dnd';\nimport { getEmptyImage } from 'react-dnd-html5-backend';\nimport { useIntl } from 'react-intl';\nimport { Link as ReactRouterLink } from 'react-router-dom';\nimport styled from 'styled-components';\n\nimport { useTracking } from '../features/Tracking';\nimport { WIDGET_DATA_ATTRIBUTES } from '../utils/widgetLayout';\n\nimport type { FindWidgetFunction, WidgetIdFunction, DragEndFunction } from '../features/Widgets';\nimport type { WidgetType } from '@strapi/admin/strapi-admin';\n\nexport interface BaseWidgetProps\n extends Pick<WidgetType, 'title' | 'icon' | 'permissions' | 'link' | 'uid'> {\n findWidget?: FindWidgetFunction;\n deleteWidget?: WidgetIdFunction;\n onDragStart?: WidgetIdFunction;\n onDragEnd?: DragEndFunction;\n}\n\nexport interface WidgetRootProps extends BaseWidgetProps {\n children: React.ReactNode;\n component?: () => Promise<React.ComponentType>;\n}\n\nconst WidgetActions = styled(Flex)`\n display: flex;\n\n @media (hover: hover) and (pointer: fine) {\n display: none;\n }\n`;\n\nconst DragIconButton = styled(IconButton)`\n display: none;\n\n @media (hover: hover) and (pointer: fine) {\n display: flex;\n }\n`;\n\nconst WidgetContainer = styled(Flex)`\n @media (hover: hover) and (pointer: fine) {\n &:hover ${WidgetActions} {\n display: flex;\n }\n }\n\n &:focus-within ${WidgetActions} {\n display: flex;\n }\n\n &:focus-within ${DragIconButton} {\n pointer-events: none;\n\n ${({ theme }) => theme.breakpoints.medium} {\n pointer-events: auto;\n }\n }\n`;\n\nexport const WidgetRoot = ({\n title,\n icon = PuzzlePiece,\n children,\n link,\n uid,\n findWidget,\n deleteWidget,\n onDragStart,\n onDragEnd,\n component,\n}: WidgetRootProps) => {\n const { trackUsage } = useTracking();\n const { formatMessage } = useIntl();\n const Icon = icon;\n\n const handleClickOnLink = () => {\n trackUsage('didOpenHomeWidgetLink', { widgetUID: uid });\n };\n\n const handleDeleteWidget = () => {\n deleteWidget?.(uid);\n };\n\n const [, drag, preview] = useDrag(\n () => ({\n type: 'widget',\n item: () => {\n onDragStart?.(uid);\n return {\n id: uid,\n originalIndex: findWidget?.(uid)?.index ?? 0,\n title,\n icon,\n link,\n component,\n };\n },\n collect: (monitor) => ({\n isDragging: monitor.isDragging(),\n }),\n end: () => {\n onDragEnd?.();\n },\n }),\n [uid, findWidget, onDragStart, onDragEnd, title, icon, link, component]\n );\n\n // Suppress default drag preview\n React.useEffect(() => {\n preview(getEmptyImage(), { captureDraggingState: true });\n }, [preview]);\n\n return (\n <WidgetContainer\n width=\"100%\"\n hasRadius\n direction=\"column\"\n alignItems=\"flex-start\"\n background={'neutral0'}\n borderColor={'neutral150'}\n shadow=\"tableShadow\"\n tag=\"section\"\n gap={4}\n padding={6}\n position=\"relative\"\n aria-labelledby={uid}\n tabIndex={0}\n {...{ [WIDGET_DATA_ATTRIBUTES.WIDGET_ID]: uid }}\n style={{\n transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',\n }}\n >\n <Flex\n direction=\"row\"\n gap={2}\n width=\"100%\"\n tag=\"header\"\n alignItems=\"center\"\n minHeight=\"2.25rem\"\n >\n <Flex gap={2} marginRight=\"auto\">\n <Icon fill=\"neutral500\" aria-hidden />\n <Typography textColor=\"neutral500\" variant=\"sigma\" tag=\"h2\" id={uid}>\n {formatMessage(title)}\n </Typography>\n </Flex>\n {link && (\n <Typography\n tag={ReactRouterLink}\n variant=\"omega\"\n textColor=\"primary600\"\n style={{ textDecoration: 'none' }}\n textAlign=\"right\"\n to={link.href}\n onClick={handleClickOnLink}\n >\n {formatMessage(link.label)}\n </Typography>\n )}\n <WidgetActions gap={2}>\n <IconButton\n variant=\"danger-light\"\n size=\"XS\"\n onClick={handleDeleteWidget}\n label={formatMessage({\n id: 'HomePage.widget.delete',\n defaultMessage: 'Delete',\n })}\n cursor=\"pointer\"\n >\n <Trash />\n </IconButton>\n <DragIconButton\n variant=\"tertiary\"\n size=\"XS\"\n ref={drag}\n tabIndex={-1}\n label={formatMessage({\n id: 'HomePage.widget.drag',\n defaultMessage: 'Drag to move',\n })}\n cursor=\"grab\"\n >\n <Drag />\n </DragIconButton>\n </WidgetActions>\n </Flex>\n <ScrollArea>\n <Box width=\"100%\" height=\"261px\" overflow=\"auto\" tag=\"main\">\n {children}\n </Box>\n </ScrollArea>\n </WidgetContainer>\n );\n};\n"],"names":["WidgetActions","styled","Flex","DragIconButton","IconButton","WidgetContainer","theme","breakpoints","medium","WidgetRoot","title","icon","PuzzlePiece","children","link","uid","findWidget","deleteWidget","onDragStart","onDragEnd","component","trackUsage","useTracking","formatMessage","useIntl","Icon","handleClickOnLink","widgetUID","handleDeleteWidget","drag","preview","useDrag","type","item","id","originalIndex","index","collect","monitor","isDragging","end","React","useEffect","getEmptyImage","captureDraggingState","_jsxs","width","hasRadius","direction","alignItems","background","borderColor","shadow","tag","gap","padding","position","aria-labelledby","tabIndex","WIDGET_DATA_ATTRIBUTES","WIDGET_ID","style","transition","minHeight","marginRight","_jsx","fill","aria-hidden","Typography","textColor","variant","ReactRouterLink","textDecoration","textAlign","to","href","onClick","label","size","defaultMessage","cursor","Trash","ref","Drag","ScrollArea","Box","height","overflow"],"mappings":"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"}
@@ -0,0 +1,195 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { Flex, IconButton, Typography, ScrollArea, Box } from '@strapi/design-system';
4
+ import { Trash, Drag, PuzzlePiece } from '@strapi/icons';
5
+ import { useDrag } from 'react-dnd';
6
+ import { getEmptyImage } from 'react-dnd-html5-backend';
7
+ import { useIntl } from 'react-intl';
8
+ import { Link } from 'react-router-dom';
9
+ import styled from 'styled-components';
10
+ import { useTracking } from '../features/Tracking.mjs';
11
+ import { WIDGET_DATA_ATTRIBUTES } from '../utils/widgetLayout.mjs';
12
+
13
+ const WidgetActions = styled(Flex)`
14
+ display: flex;
15
+
16
+ @media (hover: hover) and (pointer: fine) {
17
+ display: none;
18
+ }
19
+ `;
20
+ const DragIconButton = styled(IconButton)`
21
+ display: none;
22
+
23
+ @media (hover: hover) and (pointer: fine) {
24
+ display: flex;
25
+ }
26
+ `;
27
+ const WidgetContainer = styled(Flex)`
28
+ @media (hover: hover) and (pointer: fine) {
29
+ &:hover ${WidgetActions} {
30
+ display: flex;
31
+ }
32
+ }
33
+
34
+ &:focus-within ${WidgetActions} {
35
+ display: flex;
36
+ }
37
+
38
+ &:focus-within ${DragIconButton} {
39
+ pointer-events: none;
40
+
41
+ ${({ theme })=>theme.breakpoints.medium} {
42
+ pointer-events: auto;
43
+ }
44
+ }
45
+ `;
46
+ const WidgetRoot = ({ title, icon = PuzzlePiece, children, link, uid, findWidget, deleteWidget, onDragStart, onDragEnd, component })=>{
47
+ const { trackUsage } = useTracking();
48
+ const { formatMessage } = useIntl();
49
+ const Icon = icon;
50
+ const handleClickOnLink = ()=>{
51
+ trackUsage('didOpenHomeWidgetLink', {
52
+ widgetUID: uid
53
+ });
54
+ };
55
+ const handleDeleteWidget = ()=>{
56
+ deleteWidget?.(uid);
57
+ };
58
+ const [, drag, preview] = useDrag(()=>({
59
+ type: 'widget',
60
+ item: ()=>{
61
+ onDragStart?.(uid);
62
+ return {
63
+ id: uid,
64
+ originalIndex: findWidget?.(uid)?.index ?? 0,
65
+ title,
66
+ icon,
67
+ link,
68
+ component
69
+ };
70
+ },
71
+ collect: (monitor)=>({
72
+ isDragging: monitor.isDragging()
73
+ }),
74
+ end: ()=>{
75
+ onDragEnd?.();
76
+ }
77
+ }), [
78
+ uid,
79
+ findWidget,
80
+ onDragStart,
81
+ onDragEnd,
82
+ title,
83
+ icon,
84
+ link,
85
+ component
86
+ ]);
87
+ // Suppress default drag preview
88
+ React.useEffect(()=>{
89
+ preview(getEmptyImage(), {
90
+ captureDraggingState: true
91
+ });
92
+ }, [
93
+ preview
94
+ ]);
95
+ return /*#__PURE__*/ jsxs(WidgetContainer, {
96
+ width: "100%",
97
+ hasRadius: true,
98
+ direction: "column",
99
+ alignItems: "flex-start",
100
+ background: 'neutral0',
101
+ borderColor: 'neutral150',
102
+ shadow: "tableShadow",
103
+ tag: "section",
104
+ gap: 4,
105
+ padding: 6,
106
+ position: "relative",
107
+ "aria-labelledby": uid,
108
+ tabIndex: 0,
109
+ [WIDGET_DATA_ATTRIBUTES.WIDGET_ID]: uid,
110
+ style: {
111
+ transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)'
112
+ },
113
+ children: [
114
+ /*#__PURE__*/ jsxs(Flex, {
115
+ direction: "row",
116
+ gap: 2,
117
+ width: "100%",
118
+ tag: "header",
119
+ alignItems: "center",
120
+ minHeight: "2.25rem",
121
+ children: [
122
+ /*#__PURE__*/ jsxs(Flex, {
123
+ gap: 2,
124
+ marginRight: "auto",
125
+ children: [
126
+ /*#__PURE__*/ jsx(Icon, {
127
+ fill: "neutral500",
128
+ "aria-hidden": true
129
+ }),
130
+ /*#__PURE__*/ jsx(Typography, {
131
+ textColor: "neutral500",
132
+ variant: "sigma",
133
+ tag: "h2",
134
+ id: uid,
135
+ children: formatMessage(title)
136
+ })
137
+ ]
138
+ }),
139
+ link && /*#__PURE__*/ jsx(Typography, {
140
+ tag: Link,
141
+ variant: "omega",
142
+ textColor: "primary600",
143
+ style: {
144
+ textDecoration: 'none'
145
+ },
146
+ textAlign: "right",
147
+ to: link.href,
148
+ onClick: handleClickOnLink,
149
+ children: formatMessage(link.label)
150
+ }),
151
+ /*#__PURE__*/ jsxs(WidgetActions, {
152
+ gap: 2,
153
+ children: [
154
+ /*#__PURE__*/ jsx(IconButton, {
155
+ variant: "danger-light",
156
+ size: "XS",
157
+ onClick: handleDeleteWidget,
158
+ label: formatMessage({
159
+ id: 'HomePage.widget.delete',
160
+ defaultMessage: 'Delete'
161
+ }),
162
+ cursor: "pointer",
163
+ children: /*#__PURE__*/ jsx(Trash, {})
164
+ }),
165
+ /*#__PURE__*/ jsx(DragIconButton, {
166
+ variant: "tertiary",
167
+ size: "XS",
168
+ ref: drag,
169
+ tabIndex: -1,
170
+ label: formatMessage({
171
+ id: 'HomePage.widget.drag',
172
+ defaultMessage: 'Drag to move'
173
+ }),
174
+ cursor: "grab",
175
+ children: /*#__PURE__*/ jsx(Drag, {})
176
+ })
177
+ ]
178
+ })
179
+ ]
180
+ }),
181
+ /*#__PURE__*/ jsx(ScrollArea, {
182
+ children: /*#__PURE__*/ jsx(Box, {
183
+ width: "100%",
184
+ height: "261px",
185
+ overflow: "auto",
186
+ tag: "main",
187
+ children: children
188
+ })
189
+ })
190
+ ]
191
+ });
192
+ };
193
+
194
+ export { WidgetRoot };
195
+ //# sourceMappingURL=WidgetRoot.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WidgetRoot.mjs","sources":["../../../../../admin/src/components/WidgetRoot.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box, Flex, Typography, ScrollArea, IconButton } from '@strapi/design-system';\nimport { PuzzlePiece, Trash, Drag } from '@strapi/icons';\nimport { useDrag } from 'react-dnd';\nimport { getEmptyImage } from 'react-dnd-html5-backend';\nimport { useIntl } from 'react-intl';\nimport { Link as ReactRouterLink } from 'react-router-dom';\nimport styled from 'styled-components';\n\nimport { useTracking } from '../features/Tracking';\nimport { WIDGET_DATA_ATTRIBUTES } from '../utils/widgetLayout';\n\nimport type { FindWidgetFunction, WidgetIdFunction, DragEndFunction } from '../features/Widgets';\nimport type { WidgetType } from '@strapi/admin/strapi-admin';\n\nexport interface BaseWidgetProps\n extends Pick<WidgetType, 'title' | 'icon' | 'permissions' | 'link' | 'uid'> {\n findWidget?: FindWidgetFunction;\n deleteWidget?: WidgetIdFunction;\n onDragStart?: WidgetIdFunction;\n onDragEnd?: DragEndFunction;\n}\n\nexport interface WidgetRootProps extends BaseWidgetProps {\n children: React.ReactNode;\n component?: () => Promise<React.ComponentType>;\n}\n\nconst WidgetActions = styled(Flex)`\n display: flex;\n\n @media (hover: hover) and (pointer: fine) {\n display: none;\n }\n`;\n\nconst DragIconButton = styled(IconButton)`\n display: none;\n\n @media (hover: hover) and (pointer: fine) {\n display: flex;\n }\n`;\n\nconst WidgetContainer = styled(Flex)`\n @media (hover: hover) and (pointer: fine) {\n &:hover ${WidgetActions} {\n display: flex;\n }\n }\n\n &:focus-within ${WidgetActions} {\n display: flex;\n }\n\n &:focus-within ${DragIconButton} {\n pointer-events: none;\n\n ${({ theme }) => theme.breakpoints.medium} {\n pointer-events: auto;\n }\n }\n`;\n\nexport const WidgetRoot = ({\n title,\n icon = PuzzlePiece,\n children,\n link,\n uid,\n findWidget,\n deleteWidget,\n onDragStart,\n onDragEnd,\n component,\n}: WidgetRootProps) => {\n const { trackUsage } = useTracking();\n const { formatMessage } = useIntl();\n const Icon = icon;\n\n const handleClickOnLink = () => {\n trackUsage('didOpenHomeWidgetLink', { widgetUID: uid });\n };\n\n const handleDeleteWidget = () => {\n deleteWidget?.(uid);\n };\n\n const [, drag, preview] = useDrag(\n () => ({\n type: 'widget',\n item: () => {\n onDragStart?.(uid);\n return {\n id: uid,\n originalIndex: findWidget?.(uid)?.index ?? 0,\n title,\n icon,\n link,\n component,\n };\n },\n collect: (monitor) => ({\n isDragging: monitor.isDragging(),\n }),\n end: () => {\n onDragEnd?.();\n },\n }),\n [uid, findWidget, onDragStart, onDragEnd, title, icon, link, component]\n );\n\n // Suppress default drag preview\n React.useEffect(() => {\n preview(getEmptyImage(), { captureDraggingState: true });\n }, [preview]);\n\n return (\n <WidgetContainer\n width=\"100%\"\n hasRadius\n direction=\"column\"\n alignItems=\"flex-start\"\n background={'neutral0'}\n borderColor={'neutral150'}\n shadow=\"tableShadow\"\n tag=\"section\"\n gap={4}\n padding={6}\n position=\"relative\"\n aria-labelledby={uid}\n tabIndex={0}\n {...{ [WIDGET_DATA_ATTRIBUTES.WIDGET_ID]: uid }}\n style={{\n transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',\n }}\n >\n <Flex\n direction=\"row\"\n gap={2}\n width=\"100%\"\n tag=\"header\"\n alignItems=\"center\"\n minHeight=\"2.25rem\"\n >\n <Flex gap={2} marginRight=\"auto\">\n <Icon fill=\"neutral500\" aria-hidden />\n <Typography textColor=\"neutral500\" variant=\"sigma\" tag=\"h2\" id={uid}>\n {formatMessage(title)}\n </Typography>\n </Flex>\n {link && (\n <Typography\n tag={ReactRouterLink}\n variant=\"omega\"\n textColor=\"primary600\"\n style={{ textDecoration: 'none' }}\n textAlign=\"right\"\n to={link.href}\n onClick={handleClickOnLink}\n >\n {formatMessage(link.label)}\n </Typography>\n )}\n <WidgetActions gap={2}>\n <IconButton\n variant=\"danger-light\"\n size=\"XS\"\n onClick={handleDeleteWidget}\n label={formatMessage({\n id: 'HomePage.widget.delete',\n defaultMessage: 'Delete',\n })}\n cursor=\"pointer\"\n >\n <Trash />\n </IconButton>\n <DragIconButton\n variant=\"tertiary\"\n size=\"XS\"\n ref={drag}\n tabIndex={-1}\n label={formatMessage({\n id: 'HomePage.widget.drag',\n defaultMessage: 'Drag to move',\n })}\n cursor=\"grab\"\n >\n <Drag />\n </DragIconButton>\n </WidgetActions>\n </Flex>\n <ScrollArea>\n <Box width=\"100%\" height=\"261px\" overflow=\"auto\" tag=\"main\">\n {children}\n </Box>\n </ScrollArea>\n </WidgetContainer>\n );\n};\n"],"names":["WidgetActions","styled","Flex","DragIconButton","IconButton","WidgetContainer","theme","breakpoints","medium","WidgetRoot","title","icon","PuzzlePiece","children","link","uid","findWidget","deleteWidget","onDragStart","onDragEnd","component","trackUsage","useTracking","formatMessage","useIntl","Icon","handleClickOnLink","widgetUID","handleDeleteWidget","drag","preview","useDrag","type","item","id","originalIndex","index","collect","monitor","isDragging","end","React","useEffect","getEmptyImage","captureDraggingState","_jsxs","width","hasRadius","direction","alignItems","background","borderColor","shadow","tag","gap","padding","position","aria-labelledby","tabIndex","WIDGET_DATA_ATTRIBUTES","WIDGET_ID","style","transition","minHeight","marginRight","_jsx","fill","aria-hidden","Typography","textColor","variant","ReactRouterLink","textDecoration","textAlign","to","href","onClick","label","size","defaultMessage","cursor","Trash","ref","Drag","ScrollArea","Box","height","overflow"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tracking.js","sources":["../../../../../admin/src/features/Tracking.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport axios, { AxiosResponse } from 'axios';\n\nimport { Tours } from '../components/GuidedTour/Tours';\nimport { useDeviceType } from '../hooks/useDeviceType';\nimport { useInitQuery, useTelemetryPropertiesQuery } from '../services/admin';\n\nimport { useAppInfo } from './AppInfo';\nimport { useAuth } from './Auth';\nimport { useStrapiApp } from './StrapiApp';\n\nexport interface TelemetryProperties {\n useTypescriptOnServer?: boolean;\n useTypescriptOnAdmin?: boolean;\n isHostedOnStrapiCloud?: boolean;\n aiLicenseKey?: string;\n numberOfAllContentTypes?: number;\n numberOfComponents?: number;\n numberOfDynamicZones?: number;\n}\n\nexport interface TrackingContextValue {\n uuid?: string | boolean;\n telemetryProperties?: TelemetryProperties;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Context\n * -----------------------------------------------------------------------------------------------*/\n\nconst TrackingContext = React.createContext<TrackingContextValue>({\n uuid: false,\n});\n\n/* -------------------------------------------------------------------------------------------------\n * Provider\n * -----------------------------------------------------------------------------------------------*/\n\nexport interface TrackingProviderProps {\n children: React.ReactNode;\n}\n\nconst TrackingProvider = ({ children }: TrackingProviderProps) => {\n const token = useAuth('App', (state) => state.token);\n const { data: initData } = useInitQuery();\n const { uuid } = initData ?? {};\n const getAllWidgets = useStrapiApp('TrackingProvider', (state) => state.widgets.getAll);\n\n const { data } = useTelemetryPropertiesQuery(undefined, {\n skip: !initData?.uuid || !token,\n });\n React.useEffect(() => {\n if (uuid && data) {\n const event = 'didInitializeAdministration';\n try {\n fetch(`${process.env.STRAPI_ANALYTICS_URL || 'https://analytics.strapi.io'}/api/v2/track`, {\n method: 'POST',\n body: JSON.stringify({\n // This event is anonymous\n event,\n userId: '',\n eventPropeties: {},\n groupProperties: {\n ...data,\n projectId: uuid,\n registeredWidgets: getAllWidgets().map((widget) => widget.uid),\n },\n }),\n headers: {\n 'Content-Type': 'application/json',\n 'X-Strapi-Event': event,\n },\n });\n } catch {\n // silence is golden\n }\n }\n }, [data, uuid, getAllWidgets]);\n const value = React.useMemo(\n () => ({\n uuid,\n telemetryProperties: data,\n }),\n [uuid, data]\n );\n\n return <TrackingContext.Provider value={value}>{children}</TrackingContext.Provider>;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Hook\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * We can group these events together because none have properties so there's no benefit\n * to having them as separate types.\n *\n * Meanwhile those with properties have different property shapes corresponding to the specific\n * event so understanding which properties go with which event is very helpful.\n */\nexport interface EventWithoutProperties {\n name:\n | 'changeComponentsOrder'\n | 'didAddComponentToDynamicZone'\n | 'didBulkDeleteEntries'\n | 'didNotBulkDeleteEntries'\n | 'didChangeDisplayedFields'\n | 'didCheckDraftRelations'\n | 'didClickGuidedTourHomepageApiTokens'\n | 'didClickGuidedTourHomepageContentManager'\n | 'didClickGuidedTourHomepageContentTypeBuilder'\n | 'didClickGuidedTourStep1CollectionType'\n | 'didClickGuidedTourStep2ContentManager'\n | 'didClickGuidedTourStep3ApiTokens'\n | 'didClickonBlogSection'\n | 'didClickonCodeExampleSection'\n | 'didClickonReadTheDocumentationSection'\n | 'didClickOnTryStrapiCloudSection'\n | 'didClickonTutorialSection'\n | 'didCreateGuidedTourCollectionType'\n | 'didCreateGuidedTourEntry'\n | 'didCreateNewRole'\n | 'didCreateRole'\n | 'didDeleteToken'\n | 'didDuplicateRole'\n | 'didEditEditSettings'\n | 'didEditEmailTemplates'\n | 'didEditFieldNameOnContentType'\n | 'didEditListSettings'\n | 'didEditMediaLibraryConfig'\n | 'didEditNameOfContentType'\n | 'didGenerateGuidedTourApiTokens'\n | 'didGoToMarketplace'\n | 'didLaunchGuidedtour'\n | 'didMissMarketplacePlugin'\n | 'didNotCreateFirstAdmin'\n | 'didNotSaveComponent'\n | 'didPluginLearnMore'\n | 'didBulkPublishEntries'\n | 'didNotBulkPublishEntries'\n | 'didUnpublishEntry'\n | 'didBulkUnpublishEntries'\n | 'didNotBulkUnpublishEntries'\n | 'didSaveComponent'\n | 'didSaveContentType'\n | 'didSearch'\n | 'didSkipGuidedtour'\n | 'didSubmitPlugin'\n | 'didSubmitProvider'\n | 'didUpdateConditions'\n | 'didSelectAllMediaLibraryElements'\n | 'didSelectContentTypeFieldSettings'\n | 'didSelectContentTypeSettings'\n | 'didEditAuthenticationProvider'\n | 'didRestoreHistoryVersion'\n | 'hasClickedCTBAddFieldBanner'\n | 'removeComponentFromDynamicZone'\n | 'willAddMoreFieldToContentType'\n | 'willBulkDeleteEntries'\n | 'willBulkPublishEntries'\n | 'willBulkUnpublishEntries'\n | 'willChangeNumberOfEntriesPerPage'\n | 'willCheckDraftRelations'\n | 'willCreateComponent'\n | 'willCreateComponentFromAttributesModal'\n | 'willCreateContentType'\n | 'willCreateFirstAdmin'\n | 'willCreateNewRole'\n | 'willCreateRole'\n | 'willCreateSingleType'\n | 'willCreateStage'\n | 'willCreateWorkflow'\n | 'willDeleteEntryFromList'\n | 'willDeleteFieldOfContentType'\n | 'willDuplicateRole'\n | 'willEditEditLayout'\n | 'willEditEmailTemplates'\n | 'willEditEntryFromButton'\n | 'willEditEntryFromList'\n | 'willEditReleaseFromHome'\n | 'willEditFieldOfContentType'\n | 'willEditMediaLibraryConfig'\n | 'willEditNameOfContentType'\n | 'willEditNameOfSingleType'\n | 'willEditAuthenticationProvider'\n | 'willEditFieldNameOnContentType'\n | 'willEditStage'\n | 'willFilterEntries'\n | 'willInstallPlugin'\n | 'willOpenAuditLogDetailsFromHome'\n | 'willUnpublishEntry'\n | 'willSaveComponent'\n | 'willSaveContentType'\n | 'willSaveContentTypeLayout'\n | 'didEditFieldNameOnContentType'\n | 'didCreateRelease'\n | 'didStartNewChat'\n | 'didLaunchGuidedtour';\n properties?: never;\n}\n\ninterface DidAccessAuthenticatedAdministrationEvent {\n name: 'didAccessAuthenticatedAdministration';\n properties: {\n registeredWidgets: string[];\n projectId: string;\n };\n}\n\ninterface DidFilterMediaLibraryElementsEvent {\n name: 'didFilterMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n filter: string;\n };\n}\n\ninterface DidSortMediaLibraryElementsEvent {\n name: 'didSortMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n sort: string;\n };\n}\n\ninterface DidCropFileEvent {\n name: 'didCropFile';\n properties: MediaEvents['properties'] & {\n duplicatedFile: null | boolean;\n };\n}\n\ninterface DidSelectFile {\n name: 'didSelectFile';\n properties: MediaEvents['properties'] & {\n source: 'url' | 'computer';\n };\n}\n\ninterface DidEditMediaLibraryElementsEvent {\n name: 'didEditMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n type: string;\n changeLocation: string | boolean;\n };\n}\n\ninterface MediaEvents {\n name:\n | 'didSearchMediaLibraryElements'\n | 'didReplaceMedia'\n | 'didAddMediaLibraryFolders'\n | 'willAddMediaLibraryAssets';\n properties: {\n location: string;\n };\n}\n\ninterface DidSelectContentTypeFieldTypeEvent {\n name: 'didSelectContentTypeFieldType';\n properties: {\n type?: string;\n };\n}\n\ninterface DidChangeModeEvent {\n name: 'didChangeMode';\n properties: {\n newMode: string;\n };\n}\ninterface DidSubmitWithErrorsFirstAdminEvent {\n name: 'didSubmitWithErrorsFirstAdmin';\n properties: {\n count: string;\n };\n}\n\ninterface WillNavigateEvent {\n name: 'willNavigate';\n properties: {\n from: string;\n to: string;\n };\n}\n\ninterface DidAccessTokenListEvent {\n name: 'didAccessTokenList';\n properties: {\n tokenType: TokenEvents['properties']['tokenType'];\n number: number;\n };\n}\ninterface LogoEvent {\n name: 'didChangeLogo' | 'didClickResetLogo';\n properties: {\n logo: 'menu' | 'auth';\n };\n}\n\ninterface TokenEvents {\n name:\n | 'didCopyTokenKey'\n | 'didAddTokenFromList'\n | 'didEditTokenFromList'\n | 'willAccessTokenList'\n | 'willAddTokenFromList'\n | 'willCreateToken'\n | 'willDeleteToken'\n | 'willEditToken'\n | 'willEditTokenFromList';\n properties: {\n tokenType: 'api-token' | 'transfer-token';\n };\n}\n\ninterface WillModifyTokenEvent {\n name: 'didCreateToken' | 'didEditToken';\n properties: {\n tokenType: TokenEvents['properties']['tokenType'];\n type: 'custom' | 'full-access' | 'read-only' | Array<'push' | 'pull' | 'push-pull'>;\n };\n}\n\ninterface DeleteEntryEvents {\n name: 'willDeleteEntry' | 'didDeleteEntry' | 'didNotDeleteEntry';\n properties: {\n status?: string;\n error?: unknown;\n };\n}\n\ninterface CreateEntryEvents {\n name: 'willCreateEntry' | 'didCreateEntry' | 'didNotCreateEntry';\n properties: {\n documentId?: string;\n status?: string;\n error?: unknown;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface PublishEntryEvents {\n name: 'willPublishEntry' | 'didPublishEntry';\n properties: {\n documentId?: string;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface UpdateEntryEvents {\n name: 'willEditEntry' | 'didEditEntry' | 'didNotEditEntry';\n properties: {\n documentId?: string;\n status?: string;\n error?: unknown;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface DidFilterEntriesEvent {\n name: 'didFilterEntries';\n properties: {\n useRelation: boolean;\n };\n}\n\ninterface DidPublishRelease {\n name: 'didPublishRelease';\n properties: {\n totalEntries: number;\n totalPublishedEntries: number;\n totalUnpublishedEntries: number;\n };\n}\n\ninterface DidUsePresetPromptEvent {\n name: 'didUsePresetPrompt';\n properties: {\n promptType:\n | 'generate-product-schema'\n | 'tell-me-about-the-content-type-builder'\n | 'tell-me-about-strapi';\n };\n}\n\ninterface DidAnswerMessageEvent {\n name: 'didAnswerMessage';\n properties: {\n successful: boolean;\n };\n}\n\ninterface DidVoteAnswerEvent {\n name: 'didVoteAnswer';\n properties: {\n value: 'positive' | 'negative';\n };\n}\n\ninterface DidUpdateCTBSchema {\n name: 'didUpdateCTBSchema';\n properties: {\n success: boolean;\n newContentTypes: number;\n editedContentTypes: number;\n deletedContentTypes: number;\n newComponents: number;\n editedComponents: number;\n deletedComponents: number;\n newFields: number;\n editedFields: number;\n deletedFields: number;\n };\n}\n\ninterface DidSkipGuidedTour {\n name: 'didSkipGuidedTour';\n properties: {\n name: keyof Tours | 'all';\n };\n}\n\ninterface DidCompleteGuidedTour {\n name: 'didCompleteGuidedTour';\n properties: {\n name: keyof Tours | 'all';\n };\n}\n\ninterface DidStartGuidedTour {\n name: 'didStartGuidedTour';\n properties: {\n name: keyof Tours;\n fromHomepage?: boolean;\n };\n}\n\ninterface WillEditEntryFromHome {\n name: 'willEditEntryFromHome';\n properties: {\n entryType: 'edited' | 'published' | 'assigned';\n };\n}\n\ninterface DidOpenHomeWidgetLink {\n name: 'didOpenHomeWidgetLink';\n properties: {\n widgetUID: string;\n };\n}\n\ninterface DidOpenKeyStatisticsWidgetLink {\n name: 'didOpenKeyStatisticsWidgetLink';\n properties: {\n itemKey: string;\n };\n}\n\ntype EventsWithProperties =\n | CreateEntryEvents\n | PublishEntryEvents\n | DidAccessAuthenticatedAdministrationEvent\n | DidAccessTokenListEvent\n | DidChangeModeEvent\n | DidCropFileEvent\n | DeleteEntryEvents\n | DidEditMediaLibraryElementsEvent\n | DidFilterMediaLibraryElementsEvent\n | DidFilterEntriesEvent\n | DidSelectContentTypeFieldTypeEvent\n | DidSelectFile\n | DidSortMediaLibraryElementsEvent\n | DidSubmitWithErrorsFirstAdminEvent\n | DidUsePresetPromptEvent\n | DidAnswerMessageEvent\n | DidVoteAnswerEvent\n | LogoEvent\n | TokenEvents\n | UpdateEntryEvents\n | WillModifyTokenEvent\n | WillNavigateEvent\n | DidPublishRelease\n | MediaEvents\n | DidUpdateCTBSchema\n | DidSkipGuidedTour\n | DidCompleteGuidedTour\n | DidStartGuidedTour\n | DidOpenHomeWidgetLink\n | DidOpenKeyStatisticsWidgetLink\n | WillEditEntryFromHome;\n\nexport type TrackingEvent = EventWithoutProperties | EventsWithProperties;\nexport interface UseTrackingReturn {\n /**\n * This type helps show all the available event names before you start typing,\n * however autocomplete isn't great.\n */\n trackUsage<TEvent extends TrackingEvent>(\n event: TEvent['name'],\n properties: TEvent['properties']\n ): Promise<null | AxiosResponse<string>>;\n trackUsage<TEvent extends Extract<TrackingEvent, { properties?: never }>>(\n event: TEvent['name'],\n properties?: never\n ): Promise<null | AxiosResponse<string>>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n trackUsage<TEvent extends Extract<TrackingEvent, { properties: object }>>(\n event: TEvent['name'],\n properties: TEvent['properties']\n ): Promise<null | AxiosResponse<string>>;\n}\n\n/**\n * @description Used to send amplitude events to the Strapi Tracking hub.\n *\n * @example\n * ```tsx\n * import { useTracking } from '@strapi/strapi/admin';\n *\n * const MyComponent = () => {\n * const { trackUsage } = useTracking();\n *\n * const handleClick = () => {\n * trackUsage('my-event', { myProperty: 'myValue' });\n * }\n *\n * return <button onClick={handleClick}>Send Event</button>\n * }\n * ```\n */\nconst useTracking = (): UseTrackingReturn => {\n const deviceType = useDeviceType();\n const { uuid, telemetryProperties } = React.useContext(TrackingContext);\n const userId = useAppInfo('useTracking', (state) => state.userId);\n const trackUsage = React.useCallback(\n async <TEvent extends TrackingEvent>(\n event: TEvent['name'],\n properties?: TEvent['properties']\n ) => {\n try {\n if (uuid && !window.strapi.telemetryDisabled) {\n const res = await axios.post<string>(\n `${process.env.STRAPI_ANALYTICS_URL || 'https://analytics.strapi.io'}/api/v2/track`,\n {\n event,\n userId,\n eventProperties: { ...properties },\n userProperties: {\n deviceType,\n },\n groupProperties: {\n ...telemetryProperties,\n projectId: uuid,\n projectType: window.strapi.projectType,\n aiLicenseKey: window.strapi.aiLicenseKey,\n },\n },\n {\n headers: {\n 'Content-Type': 'application/json',\n 'X-Strapi-Event': event,\n },\n }\n );\n\n return res;\n }\n } catch (err) {\n // Silence is golden\n }\n\n return null;\n },\n [telemetryProperties, userId, uuid]\n );\n\n return { trackUsage };\n};\n\nexport { TrackingProvider, useTracking };\n"],"names":["TrackingContext","React","createContext","uuid","TrackingProvider","children","token","useAuth","state","data","initData","useInitQuery","getAllWidgets","useStrapiApp","widgets","getAll","useTelemetryPropertiesQuery","undefined","skip","useEffect","event","fetch","process","env","STRAPI_ANALYTICS_URL","method","body","JSON","stringify","userId","eventPropeties","groupProperties","projectId","registeredWidgets","map","widget","uid","headers","value","useMemo","telemetryProperties","_jsx","Provider","useTracking","deviceType","useDeviceType","useContext","useAppInfo","trackUsage","useCallback","properties","window","strapi","telemetryDisabled","res","axios","post","eventProperties","userProperties","projectType","aiLicenseKey","err"],"mappings":"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"}
1
+ {"version":3,"file":"Tracking.js","sources":["../../../../../admin/src/features/Tracking.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport axios, { AxiosResponse } from 'axios';\n\nimport { Tours } from '../components/GuidedTour/Tours';\nimport { useDeviceType } from '../hooks/useDeviceType';\nimport { useInitQuery, useTelemetryPropertiesQuery } from '../services/admin';\n\nimport { useAppInfo } from './AppInfo';\nimport { useAuth } from './Auth';\nimport { useStrapiApp } from './StrapiApp';\n\nexport interface TelemetryProperties {\n useTypescriptOnServer?: boolean;\n useTypescriptOnAdmin?: boolean;\n isHostedOnStrapiCloud?: boolean;\n aiLicenseKey?: string;\n numberOfAllContentTypes?: number;\n numberOfComponents?: number;\n numberOfDynamicZones?: number;\n}\n\nexport interface TrackingContextValue {\n uuid?: string | boolean;\n telemetryProperties?: TelemetryProperties;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Context\n * -----------------------------------------------------------------------------------------------*/\n\nconst TrackingContext = React.createContext<TrackingContextValue>({\n uuid: false,\n});\n\n/* -------------------------------------------------------------------------------------------------\n * Provider\n * -----------------------------------------------------------------------------------------------*/\n\nexport interface TrackingProviderProps {\n children: React.ReactNode;\n}\n\nconst TrackingProvider = ({ children }: TrackingProviderProps) => {\n const token = useAuth('App', (state) => state.token);\n const { data: initData } = useInitQuery();\n const { uuid } = initData ?? {};\n const getAllWidgets = useStrapiApp('TrackingProvider', (state) => state.widgets.getAll);\n\n const { data } = useTelemetryPropertiesQuery(undefined, {\n skip: !initData?.uuid || !token,\n });\n React.useEffect(() => {\n if (uuid && data) {\n const event = 'didInitializeAdministration';\n try {\n fetch(`${process.env.STRAPI_ANALYTICS_URL || 'https://analytics.strapi.io'}/api/v2/track`, {\n method: 'POST',\n body: JSON.stringify({\n // This event is anonymous\n event,\n userId: '',\n eventPropeties: {},\n groupProperties: {\n ...data,\n projectId: uuid,\n registeredWidgets: getAllWidgets().map((widget) => widget.uid),\n },\n }),\n headers: {\n 'Content-Type': 'application/json',\n 'X-Strapi-Event': event,\n },\n });\n } catch {\n // silence is golden\n }\n }\n }, [data, uuid, getAllWidgets]);\n const value = React.useMemo(\n () => ({\n uuid,\n telemetryProperties: data,\n }),\n [uuid, data]\n );\n\n return <TrackingContext.Provider value={value}>{children}</TrackingContext.Provider>;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Hook\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * We can group these events together because none have properties so there's no benefit\n * to having them as separate types.\n *\n * Meanwhile those with properties have different property shapes corresponding to the specific\n * event so understanding which properties go with which event is very helpful.\n */\nexport interface EventWithoutProperties {\n name:\n | 'changeComponentsOrder'\n | 'didAddComponentToDynamicZone'\n | 'didBulkDeleteEntries'\n | 'didNotBulkDeleteEntries'\n | 'didChangeDisplayedFields'\n | 'didCheckDraftRelations'\n | 'didClickGuidedTourHomepageApiTokens'\n | 'didClickGuidedTourHomepageContentManager'\n | 'didClickGuidedTourHomepageContentTypeBuilder'\n | 'didClickGuidedTourStep1CollectionType'\n | 'didClickGuidedTourStep2ContentManager'\n | 'didClickGuidedTourStep3ApiTokens'\n | 'didClickonBlogSection'\n | 'didClickonCodeExampleSection'\n | 'didClickonReadTheDocumentationSection'\n | 'didClickOnTryStrapiCloudSection'\n | 'didClickonTutorialSection'\n | 'didCreateGuidedTourCollectionType'\n | 'didCreateGuidedTourEntry'\n | 'didCreateNewRole'\n | 'didCreateRole'\n | 'didDeleteToken'\n | 'didDuplicateRole'\n | 'didEditEditSettings'\n | 'didEditEmailTemplates'\n | 'didEditFieldNameOnContentType'\n | 'didEditListSettings'\n | 'didEditMediaLibraryConfig'\n | 'didEditNameOfContentType'\n | 'didGenerateGuidedTourApiTokens'\n | 'didGoToMarketplace'\n | 'didLaunchGuidedtour'\n | 'didMissMarketplacePlugin'\n | 'didNotCreateFirstAdmin'\n | 'didNotSaveComponent'\n | 'didPluginLearnMore'\n | 'didBulkPublishEntries'\n | 'didNotBulkPublishEntries'\n | 'didUnpublishEntry'\n | 'didBulkUnpublishEntries'\n | 'didNotBulkUnpublishEntries'\n | 'didSaveComponent'\n | 'didSaveContentType'\n | 'didSearch'\n | 'didSkipGuidedtour'\n | 'didSubmitPlugin'\n | 'didSubmitProvider'\n | 'didUpdateConditions'\n | 'didSelectAllMediaLibraryElements'\n | 'didSelectContentTypeFieldSettings'\n | 'didSelectContentTypeSettings'\n | 'didEditAuthenticationProvider'\n | 'didRestoreHistoryVersion'\n | 'hasClickedCTBAddFieldBanner'\n | 'removeComponentFromDynamicZone'\n | 'willAddMoreFieldToContentType'\n | 'willBulkDeleteEntries'\n | 'willBulkPublishEntries'\n | 'willBulkUnpublishEntries'\n | 'willChangeNumberOfEntriesPerPage'\n | 'willCheckDraftRelations'\n | 'willCreateComponent'\n | 'willCreateComponentFromAttributesModal'\n | 'willCreateContentType'\n | 'willCreateFirstAdmin'\n | 'willCreateNewRole'\n | 'willCreateRole'\n | 'willCreateSingleType'\n | 'willCreateStage'\n | 'willCreateWorkflow'\n | 'willDeleteEntryFromList'\n | 'willDeleteFieldOfContentType'\n | 'willDuplicateRole'\n | 'willEditEditLayout'\n | 'willEditEmailTemplates'\n | 'willEditEntryFromButton'\n | 'willEditEntryFromList'\n | 'willEditReleaseFromHome'\n | 'willEditFieldOfContentType'\n | 'willEditMediaLibraryConfig'\n | 'willEditNameOfContentType'\n | 'willEditNameOfSingleType'\n | 'willEditAuthenticationProvider'\n | 'willEditFieldNameOnContentType'\n | 'willEditStage'\n | 'willFilterEntries'\n | 'willInstallPlugin'\n | 'willOpenAuditLogDetailsFromHome'\n | 'willUnpublishEntry'\n | 'willSaveComponent'\n | 'willSaveContentType'\n | 'willSaveContentTypeLayout'\n | 'didEditFieldNameOnContentType'\n | 'didCreateRelease'\n | 'didStartNewChat'\n | 'didLaunchGuidedtour'\n | 'didEditAICaption'\n | 'didEditAIAlternativeText';\n properties?: never;\n}\n\ninterface DidAccessAuthenticatedAdministrationEvent {\n name: 'didAccessAuthenticatedAdministration';\n properties: {\n registeredWidgets: string[];\n projectId: string;\n };\n}\n\ninterface DidFilterMediaLibraryElementsEvent {\n name: 'didFilterMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n filter: string;\n };\n}\n\ninterface DidSortMediaLibraryElementsEvent {\n name: 'didSortMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n sort: string;\n };\n}\n\ninterface DidCropFileEvent {\n name: 'didCropFile';\n properties: MediaEvents['properties'] & {\n duplicatedFile: null | boolean;\n };\n}\n\ninterface DidSelectFile {\n name: 'didSelectFile';\n properties: MediaEvents['properties'] & {\n source: 'url' | 'computer';\n };\n}\n\ninterface DidEditMediaLibraryElementsEvent {\n name: 'didEditMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n type: string;\n changeLocation: string | boolean;\n };\n}\n\ninterface MediaEvents {\n name:\n | 'didSearchMediaLibraryElements'\n | 'didReplaceMedia'\n | 'didAddMediaLibraryFolders'\n | 'willAddMediaLibraryAssets';\n properties: {\n location: string;\n };\n}\n\ninterface DidSelectContentTypeFieldTypeEvent {\n name: 'didSelectContentTypeFieldType';\n properties: {\n type?: string;\n };\n}\n\ninterface DidChangeModeEvent {\n name: 'didChangeMode';\n properties: {\n newMode: string;\n };\n}\ninterface DidSubmitWithErrorsFirstAdminEvent {\n name: 'didSubmitWithErrorsFirstAdmin';\n properties: {\n count: string;\n };\n}\n\ninterface WillNavigateEvent {\n name: 'willNavigate';\n properties: {\n from: string;\n to: string;\n };\n}\n\ninterface DidAccessTokenListEvent {\n name: 'didAccessTokenList';\n properties: {\n tokenType: TokenEvents['properties']['tokenType'];\n number: number;\n };\n}\ninterface LogoEvent {\n name: 'didChangeLogo' | 'didClickResetLogo';\n properties: {\n logo: 'menu' | 'auth';\n };\n}\n\ninterface TokenEvents {\n name:\n | 'didCopyTokenKey'\n | 'didAddTokenFromList'\n | 'didEditTokenFromList'\n | 'willAccessTokenList'\n | 'willAddTokenFromList'\n | 'willCreateToken'\n | 'willDeleteToken'\n | 'willEditToken'\n | 'willEditTokenFromList';\n properties: {\n tokenType: 'api-token' | 'transfer-token';\n };\n}\n\ninterface WillModifyTokenEvent {\n name: 'didCreateToken' | 'didEditToken';\n properties: {\n tokenType: TokenEvents['properties']['tokenType'];\n type: 'custom' | 'full-access' | 'read-only' | Array<'push' | 'pull' | 'push-pull'>;\n };\n}\n\ninterface DeleteEntryEvents {\n name: 'willDeleteEntry' | 'didDeleteEntry' | 'didNotDeleteEntry';\n properties: {\n status?: string;\n error?: unknown;\n };\n}\n\ninterface CreateEntryEvents {\n name: 'willCreateEntry' | 'didCreateEntry' | 'didNotCreateEntry';\n properties: {\n documentId?: string;\n status?: string;\n error?: unknown;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface PublishEntryEvents {\n name: 'willPublishEntry' | 'didPublishEntry';\n properties: {\n documentId?: string;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface UpdateEntryEvents {\n name: 'willEditEntry' | 'didEditEntry' | 'didNotEditEntry';\n properties: {\n documentId?: string;\n status?: string;\n error?: unknown;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface DidFilterEntriesEvent {\n name: 'didFilterEntries';\n properties: {\n useRelation: boolean;\n };\n}\n\ninterface DidPublishRelease {\n name: 'didPublishRelease';\n properties: {\n totalEntries: number;\n totalPublishedEntries: number;\n totalUnpublishedEntries: number;\n };\n}\n\ninterface DidUsePresetPromptEvent {\n name: 'didUsePresetPrompt';\n properties: {\n promptType:\n | 'generate-product-schema'\n | 'tell-me-about-the-content-type-builder'\n | 'tell-me-about-strapi';\n };\n}\n\ninterface DidAnswerMessageEvent {\n name: 'didAnswerMessage';\n properties: {\n successful: boolean;\n };\n}\n\ninterface DidVoteAnswerEvent {\n name: 'didVoteAnswer';\n properties: {\n value: 'positive' | 'negative';\n };\n}\n\ninterface DidUpdateCTBSchema {\n name: 'didUpdateCTBSchema';\n properties: {\n success: boolean;\n newContentTypes: number;\n editedContentTypes: number;\n deletedContentTypes: number;\n newComponents: number;\n editedComponents: number;\n deletedComponents: number;\n newFields: number;\n editedFields: number;\n deletedFields: number;\n };\n}\n\ninterface DidSkipGuidedTour {\n name: 'didSkipGuidedTour';\n properties: {\n name: keyof Tours | 'all';\n };\n}\n\ninterface DidCompleteGuidedTour {\n name: 'didCompleteGuidedTour';\n properties: {\n name: keyof Tours | 'all';\n };\n}\n\ninterface DidStartGuidedTour {\n name: 'didStartGuidedTour';\n properties: {\n name: keyof Tours;\n fromHomepage?: boolean;\n };\n}\n\ninterface WillEditEntryFromHome {\n name: 'willEditEntryFromHome';\n properties: {\n entryType: 'edited' | 'published' | 'assigned';\n };\n}\n\ninterface DidOpenHomeWidgetLink {\n name: 'didOpenHomeWidgetLink';\n properties: {\n widgetUID: string;\n };\n}\n\ninterface DidOpenKeyStatisticsWidgetLink {\n name: 'didOpenKeyStatisticsWidgetLink';\n properties: {\n itemKey: string;\n };\n}\n\ntype EventsWithProperties =\n | CreateEntryEvents\n | PublishEntryEvents\n | DidAccessAuthenticatedAdministrationEvent\n | DidAccessTokenListEvent\n | DidChangeModeEvent\n | DidCropFileEvent\n | DeleteEntryEvents\n | DidEditMediaLibraryElementsEvent\n | DidFilterMediaLibraryElementsEvent\n | DidFilterEntriesEvent\n | DidSelectContentTypeFieldTypeEvent\n | DidSelectFile\n | DidSortMediaLibraryElementsEvent\n | DidSubmitWithErrorsFirstAdminEvent\n | DidUsePresetPromptEvent\n | DidAnswerMessageEvent\n | DidVoteAnswerEvent\n | LogoEvent\n | TokenEvents\n | UpdateEntryEvents\n | WillModifyTokenEvent\n | WillNavigateEvent\n | DidPublishRelease\n | MediaEvents\n | DidUpdateCTBSchema\n | DidSkipGuidedTour\n | DidCompleteGuidedTour\n | DidStartGuidedTour\n | DidOpenHomeWidgetLink\n | DidOpenKeyStatisticsWidgetLink\n | WillEditEntryFromHome;\n\nexport type TrackingEvent = EventWithoutProperties | EventsWithProperties;\nexport interface UseTrackingReturn {\n /**\n * This type helps show all the available event names before you start typing,\n * however autocomplete isn't great.\n */\n trackUsage<TEvent extends TrackingEvent>(\n event: TEvent['name'],\n properties: TEvent['properties']\n ): Promise<null | AxiosResponse<string>>;\n trackUsage<TEvent extends Extract<TrackingEvent, { properties?: never }>>(\n event: TEvent['name'],\n properties?: never\n ): Promise<null | AxiosResponse<string>>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n trackUsage<TEvent extends Extract<TrackingEvent, { properties: object }>>(\n event: TEvent['name'],\n properties: TEvent['properties']\n ): Promise<null | AxiosResponse<string>>;\n}\n\n/**\n * @description Used to send amplitude events to the Strapi Tracking hub.\n *\n * @example\n * ```tsx\n * import { useTracking } from '@strapi/strapi/admin';\n *\n * const MyComponent = () => {\n * const { trackUsage } = useTracking();\n *\n * const handleClick = () => {\n * trackUsage('my-event', { myProperty: 'myValue' });\n * }\n *\n * return <button onClick={handleClick}>Send Event</button>\n * }\n * ```\n */\nconst useTracking = (): UseTrackingReturn => {\n const deviceType = useDeviceType();\n const { uuid, telemetryProperties } = React.useContext(TrackingContext);\n const userId = useAppInfo('useTracking', (state) => state.userId);\n const trackUsage = React.useCallback(\n async <TEvent extends TrackingEvent>(\n event: TEvent['name'],\n properties?: TEvent['properties']\n ) => {\n try {\n if (uuid && !window.strapi.telemetryDisabled) {\n const res = await axios.post<string>(\n `${process.env.STRAPI_ANALYTICS_URL || 'https://analytics.strapi.io'}/api/v2/track`,\n {\n event,\n userId,\n eventProperties: { ...properties },\n userProperties: {\n deviceType,\n },\n groupProperties: {\n ...telemetryProperties,\n projectId: uuid,\n projectType: window.strapi.projectType,\n aiLicenseKey: window.strapi.aiLicenseKey,\n },\n },\n {\n headers: {\n 'Content-Type': 'application/json',\n 'X-Strapi-Event': event,\n },\n }\n );\n\n return res;\n }\n } catch (err) {\n // Silence is golden\n }\n\n return null;\n },\n [telemetryProperties, userId, uuid]\n );\n\n return { trackUsage };\n};\n\nexport { TrackingProvider, useTracking };\n"],"names":["TrackingContext","React","createContext","uuid","TrackingProvider","children","token","useAuth","state","data","initData","useInitQuery","getAllWidgets","useStrapiApp","widgets","getAll","useTelemetryPropertiesQuery","undefined","skip","useEffect","event","fetch","process","env","STRAPI_ANALYTICS_URL","method","body","JSON","stringify","userId","eventPropeties","groupProperties","projectId","registeredWidgets","map","widget","uid","headers","value","useMemo","telemetryProperties","_jsx","Provider","useTracking","deviceType","useDeviceType","useContext","useAppInfo","trackUsage","useCallback","properties","window","strapi","telemetryDisabled","res","axios","post","eventProperties","userProperties","projectType","aiLicenseKey","err"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tracking.mjs","sources":["../../../../../admin/src/features/Tracking.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport axios, { AxiosResponse } from 'axios';\n\nimport { Tours } from '../components/GuidedTour/Tours';\nimport { useDeviceType } from '../hooks/useDeviceType';\nimport { useInitQuery, useTelemetryPropertiesQuery } from '../services/admin';\n\nimport { useAppInfo } from './AppInfo';\nimport { useAuth } from './Auth';\nimport { useStrapiApp } from './StrapiApp';\n\nexport interface TelemetryProperties {\n useTypescriptOnServer?: boolean;\n useTypescriptOnAdmin?: boolean;\n isHostedOnStrapiCloud?: boolean;\n aiLicenseKey?: string;\n numberOfAllContentTypes?: number;\n numberOfComponents?: number;\n numberOfDynamicZones?: number;\n}\n\nexport interface TrackingContextValue {\n uuid?: string | boolean;\n telemetryProperties?: TelemetryProperties;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Context\n * -----------------------------------------------------------------------------------------------*/\n\nconst TrackingContext = React.createContext<TrackingContextValue>({\n uuid: false,\n});\n\n/* -------------------------------------------------------------------------------------------------\n * Provider\n * -----------------------------------------------------------------------------------------------*/\n\nexport interface TrackingProviderProps {\n children: React.ReactNode;\n}\n\nconst TrackingProvider = ({ children }: TrackingProviderProps) => {\n const token = useAuth('App', (state) => state.token);\n const { data: initData } = useInitQuery();\n const { uuid } = initData ?? {};\n const getAllWidgets = useStrapiApp('TrackingProvider', (state) => state.widgets.getAll);\n\n const { data } = useTelemetryPropertiesQuery(undefined, {\n skip: !initData?.uuid || !token,\n });\n React.useEffect(() => {\n if (uuid && data) {\n const event = 'didInitializeAdministration';\n try {\n fetch(`${process.env.STRAPI_ANALYTICS_URL || 'https://analytics.strapi.io'}/api/v2/track`, {\n method: 'POST',\n body: JSON.stringify({\n // This event is anonymous\n event,\n userId: '',\n eventPropeties: {},\n groupProperties: {\n ...data,\n projectId: uuid,\n registeredWidgets: getAllWidgets().map((widget) => widget.uid),\n },\n }),\n headers: {\n 'Content-Type': 'application/json',\n 'X-Strapi-Event': event,\n },\n });\n } catch {\n // silence is golden\n }\n }\n }, [data, uuid, getAllWidgets]);\n const value = React.useMemo(\n () => ({\n uuid,\n telemetryProperties: data,\n }),\n [uuid, data]\n );\n\n return <TrackingContext.Provider value={value}>{children}</TrackingContext.Provider>;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Hook\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * We can group these events together because none have properties so there's no benefit\n * to having them as separate types.\n *\n * Meanwhile those with properties have different property shapes corresponding to the specific\n * event so understanding which properties go with which event is very helpful.\n */\nexport interface EventWithoutProperties {\n name:\n | 'changeComponentsOrder'\n | 'didAddComponentToDynamicZone'\n | 'didBulkDeleteEntries'\n | 'didNotBulkDeleteEntries'\n | 'didChangeDisplayedFields'\n | 'didCheckDraftRelations'\n | 'didClickGuidedTourHomepageApiTokens'\n | 'didClickGuidedTourHomepageContentManager'\n | 'didClickGuidedTourHomepageContentTypeBuilder'\n | 'didClickGuidedTourStep1CollectionType'\n | 'didClickGuidedTourStep2ContentManager'\n | 'didClickGuidedTourStep3ApiTokens'\n | 'didClickonBlogSection'\n | 'didClickonCodeExampleSection'\n | 'didClickonReadTheDocumentationSection'\n | 'didClickOnTryStrapiCloudSection'\n | 'didClickonTutorialSection'\n | 'didCreateGuidedTourCollectionType'\n | 'didCreateGuidedTourEntry'\n | 'didCreateNewRole'\n | 'didCreateRole'\n | 'didDeleteToken'\n | 'didDuplicateRole'\n | 'didEditEditSettings'\n | 'didEditEmailTemplates'\n | 'didEditFieldNameOnContentType'\n | 'didEditListSettings'\n | 'didEditMediaLibraryConfig'\n | 'didEditNameOfContentType'\n | 'didGenerateGuidedTourApiTokens'\n | 'didGoToMarketplace'\n | 'didLaunchGuidedtour'\n | 'didMissMarketplacePlugin'\n | 'didNotCreateFirstAdmin'\n | 'didNotSaveComponent'\n | 'didPluginLearnMore'\n | 'didBulkPublishEntries'\n | 'didNotBulkPublishEntries'\n | 'didUnpublishEntry'\n | 'didBulkUnpublishEntries'\n | 'didNotBulkUnpublishEntries'\n | 'didSaveComponent'\n | 'didSaveContentType'\n | 'didSearch'\n | 'didSkipGuidedtour'\n | 'didSubmitPlugin'\n | 'didSubmitProvider'\n | 'didUpdateConditions'\n | 'didSelectAllMediaLibraryElements'\n | 'didSelectContentTypeFieldSettings'\n | 'didSelectContentTypeSettings'\n | 'didEditAuthenticationProvider'\n | 'didRestoreHistoryVersion'\n | 'hasClickedCTBAddFieldBanner'\n | 'removeComponentFromDynamicZone'\n | 'willAddMoreFieldToContentType'\n | 'willBulkDeleteEntries'\n | 'willBulkPublishEntries'\n | 'willBulkUnpublishEntries'\n | 'willChangeNumberOfEntriesPerPage'\n | 'willCheckDraftRelations'\n | 'willCreateComponent'\n | 'willCreateComponentFromAttributesModal'\n | 'willCreateContentType'\n | 'willCreateFirstAdmin'\n | 'willCreateNewRole'\n | 'willCreateRole'\n | 'willCreateSingleType'\n | 'willCreateStage'\n | 'willCreateWorkflow'\n | 'willDeleteEntryFromList'\n | 'willDeleteFieldOfContentType'\n | 'willDuplicateRole'\n | 'willEditEditLayout'\n | 'willEditEmailTemplates'\n | 'willEditEntryFromButton'\n | 'willEditEntryFromList'\n | 'willEditReleaseFromHome'\n | 'willEditFieldOfContentType'\n | 'willEditMediaLibraryConfig'\n | 'willEditNameOfContentType'\n | 'willEditNameOfSingleType'\n | 'willEditAuthenticationProvider'\n | 'willEditFieldNameOnContentType'\n | 'willEditStage'\n | 'willFilterEntries'\n | 'willInstallPlugin'\n | 'willOpenAuditLogDetailsFromHome'\n | 'willUnpublishEntry'\n | 'willSaveComponent'\n | 'willSaveContentType'\n | 'willSaveContentTypeLayout'\n | 'didEditFieldNameOnContentType'\n | 'didCreateRelease'\n | 'didStartNewChat'\n | 'didLaunchGuidedtour';\n properties?: never;\n}\n\ninterface DidAccessAuthenticatedAdministrationEvent {\n name: 'didAccessAuthenticatedAdministration';\n properties: {\n registeredWidgets: string[];\n projectId: string;\n };\n}\n\ninterface DidFilterMediaLibraryElementsEvent {\n name: 'didFilterMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n filter: string;\n };\n}\n\ninterface DidSortMediaLibraryElementsEvent {\n name: 'didSortMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n sort: string;\n };\n}\n\ninterface DidCropFileEvent {\n name: 'didCropFile';\n properties: MediaEvents['properties'] & {\n duplicatedFile: null | boolean;\n };\n}\n\ninterface DidSelectFile {\n name: 'didSelectFile';\n properties: MediaEvents['properties'] & {\n source: 'url' | 'computer';\n };\n}\n\ninterface DidEditMediaLibraryElementsEvent {\n name: 'didEditMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n type: string;\n changeLocation: string | boolean;\n };\n}\n\ninterface MediaEvents {\n name:\n | 'didSearchMediaLibraryElements'\n | 'didReplaceMedia'\n | 'didAddMediaLibraryFolders'\n | 'willAddMediaLibraryAssets';\n properties: {\n location: string;\n };\n}\n\ninterface DidSelectContentTypeFieldTypeEvent {\n name: 'didSelectContentTypeFieldType';\n properties: {\n type?: string;\n };\n}\n\ninterface DidChangeModeEvent {\n name: 'didChangeMode';\n properties: {\n newMode: string;\n };\n}\ninterface DidSubmitWithErrorsFirstAdminEvent {\n name: 'didSubmitWithErrorsFirstAdmin';\n properties: {\n count: string;\n };\n}\n\ninterface WillNavigateEvent {\n name: 'willNavigate';\n properties: {\n from: string;\n to: string;\n };\n}\n\ninterface DidAccessTokenListEvent {\n name: 'didAccessTokenList';\n properties: {\n tokenType: TokenEvents['properties']['tokenType'];\n number: number;\n };\n}\ninterface LogoEvent {\n name: 'didChangeLogo' | 'didClickResetLogo';\n properties: {\n logo: 'menu' | 'auth';\n };\n}\n\ninterface TokenEvents {\n name:\n | 'didCopyTokenKey'\n | 'didAddTokenFromList'\n | 'didEditTokenFromList'\n | 'willAccessTokenList'\n | 'willAddTokenFromList'\n | 'willCreateToken'\n | 'willDeleteToken'\n | 'willEditToken'\n | 'willEditTokenFromList';\n properties: {\n tokenType: 'api-token' | 'transfer-token';\n };\n}\n\ninterface WillModifyTokenEvent {\n name: 'didCreateToken' | 'didEditToken';\n properties: {\n tokenType: TokenEvents['properties']['tokenType'];\n type: 'custom' | 'full-access' | 'read-only' | Array<'push' | 'pull' | 'push-pull'>;\n };\n}\n\ninterface DeleteEntryEvents {\n name: 'willDeleteEntry' | 'didDeleteEntry' | 'didNotDeleteEntry';\n properties: {\n status?: string;\n error?: unknown;\n };\n}\n\ninterface CreateEntryEvents {\n name: 'willCreateEntry' | 'didCreateEntry' | 'didNotCreateEntry';\n properties: {\n documentId?: string;\n status?: string;\n error?: unknown;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface PublishEntryEvents {\n name: 'willPublishEntry' | 'didPublishEntry';\n properties: {\n documentId?: string;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface UpdateEntryEvents {\n name: 'willEditEntry' | 'didEditEntry' | 'didNotEditEntry';\n properties: {\n documentId?: string;\n status?: string;\n error?: unknown;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface DidFilterEntriesEvent {\n name: 'didFilterEntries';\n properties: {\n useRelation: boolean;\n };\n}\n\ninterface DidPublishRelease {\n name: 'didPublishRelease';\n properties: {\n totalEntries: number;\n totalPublishedEntries: number;\n totalUnpublishedEntries: number;\n };\n}\n\ninterface DidUsePresetPromptEvent {\n name: 'didUsePresetPrompt';\n properties: {\n promptType:\n | 'generate-product-schema'\n | 'tell-me-about-the-content-type-builder'\n | 'tell-me-about-strapi';\n };\n}\n\ninterface DidAnswerMessageEvent {\n name: 'didAnswerMessage';\n properties: {\n successful: boolean;\n };\n}\n\ninterface DidVoteAnswerEvent {\n name: 'didVoteAnswer';\n properties: {\n value: 'positive' | 'negative';\n };\n}\n\ninterface DidUpdateCTBSchema {\n name: 'didUpdateCTBSchema';\n properties: {\n success: boolean;\n newContentTypes: number;\n editedContentTypes: number;\n deletedContentTypes: number;\n newComponents: number;\n editedComponents: number;\n deletedComponents: number;\n newFields: number;\n editedFields: number;\n deletedFields: number;\n };\n}\n\ninterface DidSkipGuidedTour {\n name: 'didSkipGuidedTour';\n properties: {\n name: keyof Tours | 'all';\n };\n}\n\ninterface DidCompleteGuidedTour {\n name: 'didCompleteGuidedTour';\n properties: {\n name: keyof Tours | 'all';\n };\n}\n\ninterface DidStartGuidedTour {\n name: 'didStartGuidedTour';\n properties: {\n name: keyof Tours;\n fromHomepage?: boolean;\n };\n}\n\ninterface WillEditEntryFromHome {\n name: 'willEditEntryFromHome';\n properties: {\n entryType: 'edited' | 'published' | 'assigned';\n };\n}\n\ninterface DidOpenHomeWidgetLink {\n name: 'didOpenHomeWidgetLink';\n properties: {\n widgetUID: string;\n };\n}\n\ninterface DidOpenKeyStatisticsWidgetLink {\n name: 'didOpenKeyStatisticsWidgetLink';\n properties: {\n itemKey: string;\n };\n}\n\ntype EventsWithProperties =\n | CreateEntryEvents\n | PublishEntryEvents\n | DidAccessAuthenticatedAdministrationEvent\n | DidAccessTokenListEvent\n | DidChangeModeEvent\n | DidCropFileEvent\n | DeleteEntryEvents\n | DidEditMediaLibraryElementsEvent\n | DidFilterMediaLibraryElementsEvent\n | DidFilterEntriesEvent\n | DidSelectContentTypeFieldTypeEvent\n | DidSelectFile\n | DidSortMediaLibraryElementsEvent\n | DidSubmitWithErrorsFirstAdminEvent\n | DidUsePresetPromptEvent\n | DidAnswerMessageEvent\n | DidVoteAnswerEvent\n | LogoEvent\n | TokenEvents\n | UpdateEntryEvents\n | WillModifyTokenEvent\n | WillNavigateEvent\n | DidPublishRelease\n | MediaEvents\n | DidUpdateCTBSchema\n | DidSkipGuidedTour\n | DidCompleteGuidedTour\n | DidStartGuidedTour\n | DidOpenHomeWidgetLink\n | DidOpenKeyStatisticsWidgetLink\n | WillEditEntryFromHome;\n\nexport type TrackingEvent = EventWithoutProperties | EventsWithProperties;\nexport interface UseTrackingReturn {\n /**\n * This type helps show all the available event names before you start typing,\n * however autocomplete isn't great.\n */\n trackUsage<TEvent extends TrackingEvent>(\n event: TEvent['name'],\n properties: TEvent['properties']\n ): Promise<null | AxiosResponse<string>>;\n trackUsage<TEvent extends Extract<TrackingEvent, { properties?: never }>>(\n event: TEvent['name'],\n properties?: never\n ): Promise<null | AxiosResponse<string>>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n trackUsage<TEvent extends Extract<TrackingEvent, { properties: object }>>(\n event: TEvent['name'],\n properties: TEvent['properties']\n ): Promise<null | AxiosResponse<string>>;\n}\n\n/**\n * @description Used to send amplitude events to the Strapi Tracking hub.\n *\n * @example\n * ```tsx\n * import { useTracking } from '@strapi/strapi/admin';\n *\n * const MyComponent = () => {\n * const { trackUsage } = useTracking();\n *\n * const handleClick = () => {\n * trackUsage('my-event', { myProperty: 'myValue' });\n * }\n *\n * return <button onClick={handleClick}>Send Event</button>\n * }\n * ```\n */\nconst useTracking = (): UseTrackingReturn => {\n const deviceType = useDeviceType();\n const { uuid, telemetryProperties } = React.useContext(TrackingContext);\n const userId = useAppInfo('useTracking', (state) => state.userId);\n const trackUsage = React.useCallback(\n async <TEvent extends TrackingEvent>(\n event: TEvent['name'],\n properties?: TEvent['properties']\n ) => {\n try {\n if (uuid && !window.strapi.telemetryDisabled) {\n const res = await axios.post<string>(\n `${process.env.STRAPI_ANALYTICS_URL || 'https://analytics.strapi.io'}/api/v2/track`,\n {\n event,\n userId,\n eventProperties: { ...properties },\n userProperties: {\n deviceType,\n },\n groupProperties: {\n ...telemetryProperties,\n projectId: uuid,\n projectType: window.strapi.projectType,\n aiLicenseKey: window.strapi.aiLicenseKey,\n },\n },\n {\n headers: {\n 'Content-Type': 'application/json',\n 'X-Strapi-Event': event,\n },\n }\n );\n\n return res;\n }\n } catch (err) {\n // Silence is golden\n }\n\n return null;\n },\n [telemetryProperties, userId, uuid]\n );\n\n return { trackUsage };\n};\n\nexport { TrackingProvider, useTracking };\n"],"names":["TrackingContext","React","createContext","uuid","TrackingProvider","children","token","useAuth","state","data","initData","useInitQuery","getAllWidgets","useStrapiApp","widgets","getAll","useTelemetryPropertiesQuery","undefined","skip","useEffect","event","fetch","process","env","STRAPI_ANALYTICS_URL","method","body","JSON","stringify","userId","eventPropeties","groupProperties","projectId","registeredWidgets","map","widget","uid","headers","value","useMemo","telemetryProperties","_jsx","Provider","useTracking","deviceType","useDeviceType","useContext","useAppInfo","trackUsage","useCallback","properties","window","strapi","telemetryDisabled","res","axios","post","eventProperties","userProperties","projectType","aiLicenseKey","err"],"mappings":"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"}
1
+ {"version":3,"file":"Tracking.mjs","sources":["../../../../../admin/src/features/Tracking.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport axios, { AxiosResponse } from 'axios';\n\nimport { Tours } from '../components/GuidedTour/Tours';\nimport { useDeviceType } from '../hooks/useDeviceType';\nimport { useInitQuery, useTelemetryPropertiesQuery } from '../services/admin';\n\nimport { useAppInfo } from './AppInfo';\nimport { useAuth } from './Auth';\nimport { useStrapiApp } from './StrapiApp';\n\nexport interface TelemetryProperties {\n useTypescriptOnServer?: boolean;\n useTypescriptOnAdmin?: boolean;\n isHostedOnStrapiCloud?: boolean;\n aiLicenseKey?: string;\n numberOfAllContentTypes?: number;\n numberOfComponents?: number;\n numberOfDynamicZones?: number;\n}\n\nexport interface TrackingContextValue {\n uuid?: string | boolean;\n telemetryProperties?: TelemetryProperties;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Context\n * -----------------------------------------------------------------------------------------------*/\n\nconst TrackingContext = React.createContext<TrackingContextValue>({\n uuid: false,\n});\n\n/* -------------------------------------------------------------------------------------------------\n * Provider\n * -----------------------------------------------------------------------------------------------*/\n\nexport interface TrackingProviderProps {\n children: React.ReactNode;\n}\n\nconst TrackingProvider = ({ children }: TrackingProviderProps) => {\n const token = useAuth('App', (state) => state.token);\n const { data: initData } = useInitQuery();\n const { uuid } = initData ?? {};\n const getAllWidgets = useStrapiApp('TrackingProvider', (state) => state.widgets.getAll);\n\n const { data } = useTelemetryPropertiesQuery(undefined, {\n skip: !initData?.uuid || !token,\n });\n React.useEffect(() => {\n if (uuid && data) {\n const event = 'didInitializeAdministration';\n try {\n fetch(`${process.env.STRAPI_ANALYTICS_URL || 'https://analytics.strapi.io'}/api/v2/track`, {\n method: 'POST',\n body: JSON.stringify({\n // This event is anonymous\n event,\n userId: '',\n eventPropeties: {},\n groupProperties: {\n ...data,\n projectId: uuid,\n registeredWidgets: getAllWidgets().map((widget) => widget.uid),\n },\n }),\n headers: {\n 'Content-Type': 'application/json',\n 'X-Strapi-Event': event,\n },\n });\n } catch {\n // silence is golden\n }\n }\n }, [data, uuid, getAllWidgets]);\n const value = React.useMemo(\n () => ({\n uuid,\n telemetryProperties: data,\n }),\n [uuid, data]\n );\n\n return <TrackingContext.Provider value={value}>{children}</TrackingContext.Provider>;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Hook\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * We can group these events together because none have properties so there's no benefit\n * to having them as separate types.\n *\n * Meanwhile those with properties have different property shapes corresponding to the specific\n * event so understanding which properties go with which event is very helpful.\n */\nexport interface EventWithoutProperties {\n name:\n | 'changeComponentsOrder'\n | 'didAddComponentToDynamicZone'\n | 'didBulkDeleteEntries'\n | 'didNotBulkDeleteEntries'\n | 'didChangeDisplayedFields'\n | 'didCheckDraftRelations'\n | 'didClickGuidedTourHomepageApiTokens'\n | 'didClickGuidedTourHomepageContentManager'\n | 'didClickGuidedTourHomepageContentTypeBuilder'\n | 'didClickGuidedTourStep1CollectionType'\n | 'didClickGuidedTourStep2ContentManager'\n | 'didClickGuidedTourStep3ApiTokens'\n | 'didClickonBlogSection'\n | 'didClickonCodeExampleSection'\n | 'didClickonReadTheDocumentationSection'\n | 'didClickOnTryStrapiCloudSection'\n | 'didClickonTutorialSection'\n | 'didCreateGuidedTourCollectionType'\n | 'didCreateGuidedTourEntry'\n | 'didCreateNewRole'\n | 'didCreateRole'\n | 'didDeleteToken'\n | 'didDuplicateRole'\n | 'didEditEditSettings'\n | 'didEditEmailTemplates'\n | 'didEditFieldNameOnContentType'\n | 'didEditListSettings'\n | 'didEditMediaLibraryConfig'\n | 'didEditNameOfContentType'\n | 'didGenerateGuidedTourApiTokens'\n | 'didGoToMarketplace'\n | 'didLaunchGuidedtour'\n | 'didMissMarketplacePlugin'\n | 'didNotCreateFirstAdmin'\n | 'didNotSaveComponent'\n | 'didPluginLearnMore'\n | 'didBulkPublishEntries'\n | 'didNotBulkPublishEntries'\n | 'didUnpublishEntry'\n | 'didBulkUnpublishEntries'\n | 'didNotBulkUnpublishEntries'\n | 'didSaveComponent'\n | 'didSaveContentType'\n | 'didSearch'\n | 'didSkipGuidedtour'\n | 'didSubmitPlugin'\n | 'didSubmitProvider'\n | 'didUpdateConditions'\n | 'didSelectAllMediaLibraryElements'\n | 'didSelectContentTypeFieldSettings'\n | 'didSelectContentTypeSettings'\n | 'didEditAuthenticationProvider'\n | 'didRestoreHistoryVersion'\n | 'hasClickedCTBAddFieldBanner'\n | 'removeComponentFromDynamicZone'\n | 'willAddMoreFieldToContentType'\n | 'willBulkDeleteEntries'\n | 'willBulkPublishEntries'\n | 'willBulkUnpublishEntries'\n | 'willChangeNumberOfEntriesPerPage'\n | 'willCheckDraftRelations'\n | 'willCreateComponent'\n | 'willCreateComponentFromAttributesModal'\n | 'willCreateContentType'\n | 'willCreateFirstAdmin'\n | 'willCreateNewRole'\n | 'willCreateRole'\n | 'willCreateSingleType'\n | 'willCreateStage'\n | 'willCreateWorkflow'\n | 'willDeleteEntryFromList'\n | 'willDeleteFieldOfContentType'\n | 'willDuplicateRole'\n | 'willEditEditLayout'\n | 'willEditEmailTemplates'\n | 'willEditEntryFromButton'\n | 'willEditEntryFromList'\n | 'willEditReleaseFromHome'\n | 'willEditFieldOfContentType'\n | 'willEditMediaLibraryConfig'\n | 'willEditNameOfContentType'\n | 'willEditNameOfSingleType'\n | 'willEditAuthenticationProvider'\n | 'willEditFieldNameOnContentType'\n | 'willEditStage'\n | 'willFilterEntries'\n | 'willInstallPlugin'\n | 'willOpenAuditLogDetailsFromHome'\n | 'willUnpublishEntry'\n | 'willSaveComponent'\n | 'willSaveContentType'\n | 'willSaveContentTypeLayout'\n | 'didEditFieldNameOnContentType'\n | 'didCreateRelease'\n | 'didStartNewChat'\n | 'didLaunchGuidedtour'\n | 'didEditAICaption'\n | 'didEditAIAlternativeText';\n properties?: never;\n}\n\ninterface DidAccessAuthenticatedAdministrationEvent {\n name: 'didAccessAuthenticatedAdministration';\n properties: {\n registeredWidgets: string[];\n projectId: string;\n };\n}\n\ninterface DidFilterMediaLibraryElementsEvent {\n name: 'didFilterMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n filter: string;\n };\n}\n\ninterface DidSortMediaLibraryElementsEvent {\n name: 'didSortMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n sort: string;\n };\n}\n\ninterface DidCropFileEvent {\n name: 'didCropFile';\n properties: MediaEvents['properties'] & {\n duplicatedFile: null | boolean;\n };\n}\n\ninterface DidSelectFile {\n name: 'didSelectFile';\n properties: MediaEvents['properties'] & {\n source: 'url' | 'computer';\n };\n}\n\ninterface DidEditMediaLibraryElementsEvent {\n name: 'didEditMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n type: string;\n changeLocation: string | boolean;\n };\n}\n\ninterface MediaEvents {\n name:\n | 'didSearchMediaLibraryElements'\n | 'didReplaceMedia'\n | 'didAddMediaLibraryFolders'\n | 'willAddMediaLibraryAssets';\n properties: {\n location: string;\n };\n}\n\ninterface DidSelectContentTypeFieldTypeEvent {\n name: 'didSelectContentTypeFieldType';\n properties: {\n type?: string;\n };\n}\n\ninterface DidChangeModeEvent {\n name: 'didChangeMode';\n properties: {\n newMode: string;\n };\n}\ninterface DidSubmitWithErrorsFirstAdminEvent {\n name: 'didSubmitWithErrorsFirstAdmin';\n properties: {\n count: string;\n };\n}\n\ninterface WillNavigateEvent {\n name: 'willNavigate';\n properties: {\n from: string;\n to: string;\n };\n}\n\ninterface DidAccessTokenListEvent {\n name: 'didAccessTokenList';\n properties: {\n tokenType: TokenEvents['properties']['tokenType'];\n number: number;\n };\n}\ninterface LogoEvent {\n name: 'didChangeLogo' | 'didClickResetLogo';\n properties: {\n logo: 'menu' | 'auth';\n };\n}\n\ninterface TokenEvents {\n name:\n | 'didCopyTokenKey'\n | 'didAddTokenFromList'\n | 'didEditTokenFromList'\n | 'willAccessTokenList'\n | 'willAddTokenFromList'\n | 'willCreateToken'\n | 'willDeleteToken'\n | 'willEditToken'\n | 'willEditTokenFromList';\n properties: {\n tokenType: 'api-token' | 'transfer-token';\n };\n}\n\ninterface WillModifyTokenEvent {\n name: 'didCreateToken' | 'didEditToken';\n properties: {\n tokenType: TokenEvents['properties']['tokenType'];\n type: 'custom' | 'full-access' | 'read-only' | Array<'push' | 'pull' | 'push-pull'>;\n };\n}\n\ninterface DeleteEntryEvents {\n name: 'willDeleteEntry' | 'didDeleteEntry' | 'didNotDeleteEntry';\n properties: {\n status?: string;\n error?: unknown;\n };\n}\n\ninterface CreateEntryEvents {\n name: 'willCreateEntry' | 'didCreateEntry' | 'didNotCreateEntry';\n properties: {\n documentId?: string;\n status?: string;\n error?: unknown;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface PublishEntryEvents {\n name: 'willPublishEntry' | 'didPublishEntry';\n properties: {\n documentId?: string;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface UpdateEntryEvents {\n name: 'willEditEntry' | 'didEditEntry' | 'didNotEditEntry';\n properties: {\n documentId?: string;\n status?: string;\n error?: unknown;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface DidFilterEntriesEvent {\n name: 'didFilterEntries';\n properties: {\n useRelation: boolean;\n };\n}\n\ninterface DidPublishRelease {\n name: 'didPublishRelease';\n properties: {\n totalEntries: number;\n totalPublishedEntries: number;\n totalUnpublishedEntries: number;\n };\n}\n\ninterface DidUsePresetPromptEvent {\n name: 'didUsePresetPrompt';\n properties: {\n promptType:\n | 'generate-product-schema'\n | 'tell-me-about-the-content-type-builder'\n | 'tell-me-about-strapi';\n };\n}\n\ninterface DidAnswerMessageEvent {\n name: 'didAnswerMessage';\n properties: {\n successful: boolean;\n };\n}\n\ninterface DidVoteAnswerEvent {\n name: 'didVoteAnswer';\n properties: {\n value: 'positive' | 'negative';\n };\n}\n\ninterface DidUpdateCTBSchema {\n name: 'didUpdateCTBSchema';\n properties: {\n success: boolean;\n newContentTypes: number;\n editedContentTypes: number;\n deletedContentTypes: number;\n newComponents: number;\n editedComponents: number;\n deletedComponents: number;\n newFields: number;\n editedFields: number;\n deletedFields: number;\n };\n}\n\ninterface DidSkipGuidedTour {\n name: 'didSkipGuidedTour';\n properties: {\n name: keyof Tours | 'all';\n };\n}\n\ninterface DidCompleteGuidedTour {\n name: 'didCompleteGuidedTour';\n properties: {\n name: keyof Tours | 'all';\n };\n}\n\ninterface DidStartGuidedTour {\n name: 'didStartGuidedTour';\n properties: {\n name: keyof Tours;\n fromHomepage?: boolean;\n };\n}\n\ninterface WillEditEntryFromHome {\n name: 'willEditEntryFromHome';\n properties: {\n entryType: 'edited' | 'published' | 'assigned';\n };\n}\n\ninterface DidOpenHomeWidgetLink {\n name: 'didOpenHomeWidgetLink';\n properties: {\n widgetUID: string;\n };\n}\n\ninterface DidOpenKeyStatisticsWidgetLink {\n name: 'didOpenKeyStatisticsWidgetLink';\n properties: {\n itemKey: string;\n };\n}\n\ntype EventsWithProperties =\n | CreateEntryEvents\n | PublishEntryEvents\n | DidAccessAuthenticatedAdministrationEvent\n | DidAccessTokenListEvent\n | DidChangeModeEvent\n | DidCropFileEvent\n | DeleteEntryEvents\n | DidEditMediaLibraryElementsEvent\n | DidFilterMediaLibraryElementsEvent\n | DidFilterEntriesEvent\n | DidSelectContentTypeFieldTypeEvent\n | DidSelectFile\n | DidSortMediaLibraryElementsEvent\n | DidSubmitWithErrorsFirstAdminEvent\n | DidUsePresetPromptEvent\n | DidAnswerMessageEvent\n | DidVoteAnswerEvent\n | LogoEvent\n | TokenEvents\n | UpdateEntryEvents\n | WillModifyTokenEvent\n | WillNavigateEvent\n | DidPublishRelease\n | MediaEvents\n | DidUpdateCTBSchema\n | DidSkipGuidedTour\n | DidCompleteGuidedTour\n | DidStartGuidedTour\n | DidOpenHomeWidgetLink\n | DidOpenKeyStatisticsWidgetLink\n | WillEditEntryFromHome;\n\nexport type TrackingEvent = EventWithoutProperties | EventsWithProperties;\nexport interface UseTrackingReturn {\n /**\n * This type helps show all the available event names before you start typing,\n * however autocomplete isn't great.\n */\n trackUsage<TEvent extends TrackingEvent>(\n event: TEvent['name'],\n properties: TEvent['properties']\n ): Promise<null | AxiosResponse<string>>;\n trackUsage<TEvent extends Extract<TrackingEvent, { properties?: never }>>(\n event: TEvent['name'],\n properties?: never\n ): Promise<null | AxiosResponse<string>>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n trackUsage<TEvent extends Extract<TrackingEvent, { properties: object }>>(\n event: TEvent['name'],\n properties: TEvent['properties']\n ): Promise<null | AxiosResponse<string>>;\n}\n\n/**\n * @description Used to send amplitude events to the Strapi Tracking hub.\n *\n * @example\n * ```tsx\n * import { useTracking } from '@strapi/strapi/admin';\n *\n * const MyComponent = () => {\n * const { trackUsage } = useTracking();\n *\n * const handleClick = () => {\n * trackUsage('my-event', { myProperty: 'myValue' });\n * }\n *\n * return <button onClick={handleClick}>Send Event</button>\n * }\n * ```\n */\nconst useTracking = (): UseTrackingReturn => {\n const deviceType = useDeviceType();\n const { uuid, telemetryProperties } = React.useContext(TrackingContext);\n const userId = useAppInfo('useTracking', (state) => state.userId);\n const trackUsage = React.useCallback(\n async <TEvent extends TrackingEvent>(\n event: TEvent['name'],\n properties?: TEvent['properties']\n ) => {\n try {\n if (uuid && !window.strapi.telemetryDisabled) {\n const res = await axios.post<string>(\n `${process.env.STRAPI_ANALYTICS_URL || 'https://analytics.strapi.io'}/api/v2/track`,\n {\n event,\n userId,\n eventProperties: { ...properties },\n userProperties: {\n deviceType,\n },\n groupProperties: {\n ...telemetryProperties,\n projectId: uuid,\n projectType: window.strapi.projectType,\n aiLicenseKey: window.strapi.aiLicenseKey,\n },\n },\n {\n headers: {\n 'Content-Type': 'application/json',\n 'X-Strapi-Event': event,\n },\n }\n );\n\n return res;\n }\n } catch (err) {\n // Silence is golden\n }\n\n return null;\n },\n [telemetryProperties, userId, uuid]\n );\n\n return { trackUsage };\n};\n\nexport { TrackingProvider, useTracking };\n"],"names":["TrackingContext","React","createContext","uuid","TrackingProvider","children","token","useAuth","state","data","initData","useInitQuery","getAllWidgets","useStrapiApp","widgets","getAll","useTelemetryPropertiesQuery","undefined","skip","useEffect","event","fetch","process","env","STRAPI_ANALYTICS_URL","method","body","JSON","stringify","userId","eventPropeties","groupProperties","projectId","registeredWidgets","map","widget","uid","headers","value","useMemo","telemetryProperties","_jsx","Provider","useTracking","deviceType","useDeviceType","useContext","useAppInfo","trackUsage","useCallback","properties","window","strapi","telemetryDisabled","res","axios","post","eventProperties","userProperties","projectType","aiLicenseKey","err"],"mappings":"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"}