@strapi/admin 5.20.0 → 5.22.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.
- package/dist/admin/admin/src/StrapiApp.js +54 -8
- package/dist/admin/admin/src/StrapiApp.js.map +1 -1
- package/dist/admin/admin/src/StrapiApp.mjs +52 -6
- package/dist/admin/admin/src/StrapiApp.mjs.map +1 -1
- package/dist/admin/admin/src/components/GuidedTour/Tours.js +2 -0
- package/dist/admin/admin/src/components/GuidedTour/Tours.js.map +1 -1
- package/dist/admin/admin/src/components/GuidedTour/Tours.mjs +2 -0
- package/dist/admin/admin/src/components/GuidedTour/Tours.mjs.map +1 -1
- package/dist/admin/admin/src/components/Widgets.js +199 -0
- package/dist/admin/admin/src/components/Widgets.js.map +1 -1
- package/dist/admin/admin/src/components/Widgets.mjs +200 -2
- package/dist/admin/admin/src/components/Widgets.mjs.map +1 -1
- package/dist/admin/admin/src/core/apis/Widgets.js.map +1 -1
- package/dist/admin/admin/src/core/apis/Widgets.mjs.map +1 -1
- package/dist/admin/admin/src/features/Tracking.js.map +1 -1
- package/dist/admin/admin/src/features/Tracking.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Home/HomePage.js +32 -30
- package/dist/admin/admin/src/pages/Home/HomePage.js.map +1 -1
- package/dist/admin/admin/src/pages/Home/HomePage.mjs +33 -31
- package/dist/admin/admin/src/pages/Home/HomePage.mjs.map +1 -1
- package/dist/admin/admin/src/services/admin.js +1 -2
- package/dist/admin/admin/src/services/admin.js.map +1 -1
- package/dist/admin/admin/src/services/admin.mjs +1 -2
- package/dist/admin/admin/src/services/admin.mjs.map +1 -1
- package/dist/admin/admin/src/services/api.js +4 -1
- package/dist/admin/admin/src/services/api.js.map +1 -1
- package/dist/admin/admin/src/services/api.mjs +4 -1
- package/dist/admin/admin/src/services/api.mjs.map +1 -1
- package/dist/admin/admin/src/services/apiTokens.js +5 -4
- package/dist/admin/admin/src/services/apiTokens.js.map +1 -1
- package/dist/admin/admin/src/services/apiTokens.mjs +5 -4
- package/dist/admin/admin/src/services/apiTokens.mjs.map +1 -1
- package/dist/admin/admin/src/services/homepage.js +31 -0
- package/dist/admin/admin/src/services/homepage.js.map +1 -0
- package/dist/admin/admin/src/services/homepage.mjs +28 -0
- package/dist/admin/admin/src/services/homepage.mjs.map +1 -0
- package/dist/admin/admin/src/services/users.js +4 -2
- package/dist/admin/admin/src/services/users.js.map +1 -1
- package/dist/admin/admin/src/services/users.mjs +4 -2
- package/dist/admin/admin/src/services/users.mjs.map +1 -1
- package/dist/admin/admin/src/services/webhooks.js +9 -5
- package/dist/admin/admin/src/services/webhooks.js.map +1 -1
- package/dist/admin/admin/src/services/webhooks.mjs +9 -5
- package/dist/admin/admin/src/services/webhooks.mjs.map +1 -1
- package/dist/admin/admin/src/translations/en.json.js +12 -0
- package/dist/admin/admin/src/translations/en.json.js.map +1 -1
- package/dist/admin/admin/src/translations/en.json.mjs +12 -0
- package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
- package/dist/admin/admin/src/translations/es.json.js +9 -0
- package/dist/admin/admin/src/translations/es.json.js.map +1 -1
- package/dist/admin/admin/src/translations/es.json.mjs +9 -0
- package/dist/admin/admin/src/translations/es.json.mjs.map +1 -1
- package/dist/admin/admin/src/translations/fr.json.js +9 -0
- package/dist/admin/admin/src/translations/fr.json.js.map +1 -1
- package/dist/admin/admin/src/translations/fr.json.mjs +9 -0
- package/dist/admin/admin/src/translations/fr.json.mjs.map +1 -1
- package/dist/admin/ee/admin/src/components/AuditLogs/Widgets.js +131 -0
- package/dist/admin/ee/admin/src/components/AuditLogs/Widgets.js.map +1 -0
- package/dist/admin/ee/admin/src/components/AuditLogs/Widgets.mjs +129 -0
- package/dist/admin/ee/admin/src/components/AuditLogs/Widgets.mjs.map +1 -0
- package/dist/admin/ee/admin/src/constants.js +3 -1
- package/dist/admin/ee/admin/src/constants.js.map +1 -1
- package/dist/admin/ee/admin/src/constants.mjs +3 -2
- package/dist/admin/ee/admin/src/constants.mjs.map +1 -1
- package/dist/admin/index.js +2 -0
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +1 -0
- package/dist/admin/index.mjs.map +1 -1
- package/dist/admin/src/components/Widgets.d.ts +2 -1
- package/dist/admin/src/core/apis/Widgets.d.ts +1 -0
- package/dist/admin/src/core/store/configure.d.ts +2 -2
- package/dist/admin/src/core/store/hooks.d.ts +2 -2
- package/dist/admin/src/features/Tracking.d.ts +1 -1
- package/dist/admin/src/hooks/useAdminRoles.d.ts +1 -1
- package/dist/admin/src/index.d.ts +1 -0
- package/dist/admin/src/pages/Home/HomePage.d.ts +1 -1
- package/dist/admin/src/pages/Settings/pages/Webhooks/hooks/useWebhooks.d.ts +4 -4
- package/dist/admin/src/selectors.d.ts +2 -2
- package/dist/admin/src/services/admin.d.ts +6 -6
- package/dist/admin/src/services/api.d.ts +1 -1
- package/dist/admin/src/services/apiTokens.d.ts +1 -1
- package/dist/admin/src/services/auth.d.ts +10 -10
- package/dist/admin/src/services/contentApi.d.ts +1 -1
- package/dist/admin/src/services/contentManager.d.ts +1 -1
- package/dist/admin/src/services/homepage.d.ts +14 -0
- package/dist/admin/src/services/transferTokens.d.ts +1 -1
- package/dist/admin/src/services/users.d.ts +8 -8
- package/dist/admin/src/services/webhooks.d.ts +2 -2
- package/dist/admin/tests/utils.d.ts +1 -1
- package/dist/ee/admin/src/components/AuditLogs/Widgets.d.ts +2 -0
- package/dist/ee/admin/src/constants.d.ts +1 -0
- package/dist/ee/admin/src/services/auditLogs.d.ts +1 -1
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.js +1 -1
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.js.map +1 -1
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.mjs +1 -1
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.mjs.map +1 -1
- package/dist/server/server/src/controllers/homepage.js +15 -0
- package/dist/server/server/src/controllers/homepage.js.map +1 -0
- package/dist/server/server/src/controllers/homepage.mjs +13 -0
- package/dist/server/server/src/controllers/homepage.mjs.map +1 -0
- package/dist/server/server/src/controllers/index.js +3 -1
- package/dist/server/server/src/controllers/index.js.map +1 -1
- package/dist/server/server/src/controllers/index.mjs +3 -1
- package/dist/server/server/src/controllers/index.mjs.map +1 -1
- package/dist/server/server/src/routes/homepage.js +17 -0
- package/dist/server/server/src/routes/homepage.js.map +1 -0
- package/dist/server/server/src/routes/homepage.mjs +15 -0
- package/dist/server/server/src/routes/homepage.mjs.map +1 -0
- package/dist/server/server/src/routes/index.js +3 -1
- package/dist/server/server/src/routes/index.js.map +1 -1
- package/dist/server/server/src/routes/index.mjs +3 -1
- package/dist/server/server/src/routes/index.mjs.map +1 -1
- package/dist/server/server/src/services/homepage.js +34 -0
- package/dist/server/server/src/services/homepage.js.map +1 -0
- package/dist/server/server/src/services/homepage.mjs +32 -0
- package/dist/server/server/src/services/homepage.mjs.map +1 -0
- package/dist/server/server/src/services/index.js +3 -1
- package/dist/server/server/src/services/index.js.map +1 -1
- package/dist/server/server/src/services/index.mjs +3 -1
- package/dist/server/server/src/services/index.mjs.map +1 -1
- package/dist/server/src/controllers/homepage.d.ts +15 -0
- package/dist/server/src/controllers/homepage.d.ts.map +1 -0
- package/dist/server/src/controllers/index.d.ts +13 -0
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +26 -0
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/routes/homepage.d.ts +10 -0
- package/dist/server/src/routes/homepage.d.ts.map +1 -0
- package/dist/server/src/routes/index.d.ts.map +1 -1
- package/dist/server/src/services/homepage.d.ts +15 -0
- package/dist/server/src/services/homepage.d.ts.map +1 -0
- package/dist/server/src/services/index.d.ts +13 -0
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/shared/contracts/homepage.d.ts +30 -0
- package/dist/shared/contracts/homepage.d.ts.map +1 -1
- package/package.json +7 -7
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { useAuth } from '@strapi/admin/strapi-admin';
|
|
3
|
-
import { Typography, Flex, Avatar, Badge } from '@strapi/design-system';
|
|
3
|
+
import { Typography, Flex, Avatar, Badge, Box } from '@strapi/design-system';
|
|
4
|
+
import { Files, Images, Layout, Graph, Earth, User, Webhooks, Key } from '@strapi/icons';
|
|
5
|
+
import { useIntl } from 'react-intl';
|
|
6
|
+
import { Link } from 'react-router-dom';
|
|
4
7
|
import { styled } from 'styled-components';
|
|
8
|
+
import { useGetCountDocumentsQuery, useGetKeyStatisticsQuery } from '../services/homepage.mjs';
|
|
5
9
|
import { getInitials, getDisplayName } from '../utils/users.mjs';
|
|
10
|
+
import { Widget } from './WidgetHelpers.mjs';
|
|
6
11
|
|
|
7
12
|
/* -------------------------------------------------------------------------------------------------
|
|
8
13
|
* ProfileWidget
|
|
@@ -45,6 +50,199 @@ const ProfileWidget = ()=>{
|
|
|
45
50
|
]
|
|
46
51
|
});
|
|
47
52
|
};
|
|
53
|
+
/* -------------------------------------------------------------------------------------------------
|
|
54
|
+
* Key Statistics
|
|
55
|
+
* -----------------------------------------------------------------------------------------------*/ const Grid = styled(Box)`
|
|
56
|
+
display: grid;
|
|
57
|
+
grid-template-columns: 1fr 1fr;
|
|
58
|
+
gap: 0;
|
|
59
|
+
border: 1px solid ${({ theme })=>theme.colors.neutral200};
|
|
60
|
+
border-radius: ${({ theme })=>theme.borderRadius};
|
|
61
|
+
overflow: hidden;
|
|
62
|
+
`;
|
|
63
|
+
const GridCell = styled(Box)`
|
|
64
|
+
border-bottom: 1px solid ${({ theme })=>theme.colors.neutral200};
|
|
65
|
+
border-right: 1px solid ${({ theme })=>theme.colors.neutral200};
|
|
66
|
+
display: flex;
|
|
67
|
+
flex-direction: row;
|
|
68
|
+
align-items: flex-start;
|
|
69
|
+
|
|
70
|
+
&:nth-child(2n) {
|
|
71
|
+
border-right: none;
|
|
72
|
+
}
|
|
73
|
+
&:nth-last-child(-n + 2) {
|
|
74
|
+
border-bottom: none;
|
|
75
|
+
}
|
|
76
|
+
`;
|
|
77
|
+
const formatNumber = ({ locale, number })=>{
|
|
78
|
+
return new Intl.NumberFormat(locale, {
|
|
79
|
+
notation: 'compact',
|
|
80
|
+
maximumFractionDigits: 1
|
|
81
|
+
}).format(number);
|
|
82
|
+
};
|
|
83
|
+
const LinkCell = styled(Link)`
|
|
84
|
+
text-decoration: none;
|
|
85
|
+
padding: ${({ theme })=>theme.spaces[3]};
|
|
86
|
+
`;
|
|
87
|
+
const KeyStatisticsWidget = ()=>{
|
|
88
|
+
const { formatMessage, locale } = useIntl();
|
|
89
|
+
const { data: countDocuments, isLoading: isLoadingCountDocuments } = useGetCountDocumentsQuery();
|
|
90
|
+
const { data: countKeyStatistics, isLoading: isLoadingKeyStatistics } = useGetKeyStatisticsQuery();
|
|
91
|
+
if (isLoadingKeyStatistics || isLoadingCountDocuments) {
|
|
92
|
+
return /*#__PURE__*/ jsx(Widget.Loading, {});
|
|
93
|
+
}
|
|
94
|
+
if (!countKeyStatistics || !countDocuments) {
|
|
95
|
+
return /*#__PURE__*/ jsx(Widget.Error, {});
|
|
96
|
+
}
|
|
97
|
+
const keyStatisticsList = {
|
|
98
|
+
entries: {
|
|
99
|
+
label: {
|
|
100
|
+
id: 'widget.key-statistics.list.entries',
|
|
101
|
+
defaultMessage: 'Entries'
|
|
102
|
+
},
|
|
103
|
+
icon: {
|
|
104
|
+
component: /*#__PURE__*/ jsx(Files, {}),
|
|
105
|
+
background: 'primary100',
|
|
106
|
+
color: 'primary600'
|
|
107
|
+
},
|
|
108
|
+
link: '/content-manager'
|
|
109
|
+
},
|
|
110
|
+
assets: {
|
|
111
|
+
label: {
|
|
112
|
+
id: 'widget.key-statistics.list.assets',
|
|
113
|
+
defaultMessage: 'Assets'
|
|
114
|
+
},
|
|
115
|
+
icon: {
|
|
116
|
+
component: /*#__PURE__*/ jsx(Images, {}),
|
|
117
|
+
background: 'warning100',
|
|
118
|
+
color: 'warning600'
|
|
119
|
+
},
|
|
120
|
+
link: '/plugins/upload'
|
|
121
|
+
},
|
|
122
|
+
contentTypes: {
|
|
123
|
+
label: {
|
|
124
|
+
id: 'widget.key-statistics.list.contentTypes',
|
|
125
|
+
defaultMessage: 'Content-Types'
|
|
126
|
+
},
|
|
127
|
+
icon: {
|
|
128
|
+
component: /*#__PURE__*/ jsx(Layout, {}),
|
|
129
|
+
background: 'secondary100',
|
|
130
|
+
color: 'secondary600'
|
|
131
|
+
},
|
|
132
|
+
link: '/plugins/content-type-builder'
|
|
133
|
+
},
|
|
134
|
+
components: {
|
|
135
|
+
label: {
|
|
136
|
+
id: 'widget.key-statistics.list.components',
|
|
137
|
+
defaultMessage: 'Components'
|
|
138
|
+
},
|
|
139
|
+
icon: {
|
|
140
|
+
component: /*#__PURE__*/ jsx(Graph, {}),
|
|
141
|
+
background: 'alternative100',
|
|
142
|
+
color: 'alternative600'
|
|
143
|
+
},
|
|
144
|
+
link: '/plugins/content-type-builder'
|
|
145
|
+
},
|
|
146
|
+
locales: {
|
|
147
|
+
label: {
|
|
148
|
+
id: 'widget.key-statistics.list.locales',
|
|
149
|
+
defaultMessage: 'Locales'
|
|
150
|
+
},
|
|
151
|
+
icon: {
|
|
152
|
+
component: /*#__PURE__*/ jsx(Earth, {}),
|
|
153
|
+
background: 'success100',
|
|
154
|
+
color: 'success600'
|
|
155
|
+
},
|
|
156
|
+
link: '/settings/internationalization'
|
|
157
|
+
},
|
|
158
|
+
admins: {
|
|
159
|
+
label: {
|
|
160
|
+
id: 'widget.key-statistics.list.admins',
|
|
161
|
+
defaultMessage: 'Admins'
|
|
162
|
+
},
|
|
163
|
+
icon: {
|
|
164
|
+
component: /*#__PURE__*/ jsx(User, {}),
|
|
165
|
+
background: 'danger100',
|
|
166
|
+
color: 'danger600'
|
|
167
|
+
},
|
|
168
|
+
link: '/settings/users?pageSize=10&page=1&sort=firstname'
|
|
169
|
+
},
|
|
170
|
+
webhooks: {
|
|
171
|
+
label: {
|
|
172
|
+
id: 'widget.key-statistics.list.webhooks',
|
|
173
|
+
defaultMessage: 'Webhooks'
|
|
174
|
+
},
|
|
175
|
+
icon: {
|
|
176
|
+
component: /*#__PURE__*/ jsx(Webhooks, {}),
|
|
177
|
+
background: 'alternative100',
|
|
178
|
+
color: 'alternative600'
|
|
179
|
+
},
|
|
180
|
+
link: '/settings/webhooks'
|
|
181
|
+
},
|
|
182
|
+
apiTokens: {
|
|
183
|
+
label: {
|
|
184
|
+
id: 'widget.key-statistics.list.apiTokens',
|
|
185
|
+
defaultMessage: 'API Tokens'
|
|
186
|
+
},
|
|
187
|
+
icon: {
|
|
188
|
+
component: /*#__PURE__*/ jsx(Key, {}),
|
|
189
|
+
background: 'neutral100',
|
|
190
|
+
color: 'neutral600'
|
|
191
|
+
},
|
|
192
|
+
link: '/settings/api-tokens?sort=name:ASC'
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
const { draft, published, modified } = countDocuments ?? {
|
|
196
|
+
draft: 0,
|
|
197
|
+
published: 0,
|
|
198
|
+
modified: 0
|
|
199
|
+
};
|
|
200
|
+
const totalCountEntries = draft + published + modified;
|
|
201
|
+
return /*#__PURE__*/ jsx(Grid, {
|
|
202
|
+
children: Object.entries(keyStatisticsList).map(([key, item])=>{
|
|
203
|
+
const value = countKeyStatistics?.[key];
|
|
204
|
+
return value !== null && /*#__PURE__*/ jsx(GridCell, {
|
|
205
|
+
as: LinkCell,
|
|
206
|
+
to: item.link,
|
|
207
|
+
"data-testid": `stat-${key}`,
|
|
208
|
+
children: /*#__PURE__*/ jsxs(Flex, {
|
|
209
|
+
alignItems: "center",
|
|
210
|
+
gap: 2,
|
|
211
|
+
children: [
|
|
212
|
+
/*#__PURE__*/ jsx(Flex, {
|
|
213
|
+
padding: 2,
|
|
214
|
+
borderRadius: 1,
|
|
215
|
+
background: item.icon.background,
|
|
216
|
+
color: item.icon.color,
|
|
217
|
+
children: item.icon.component
|
|
218
|
+
}),
|
|
219
|
+
/*#__PURE__*/ jsxs(Flex, {
|
|
220
|
+
direction: "column",
|
|
221
|
+
alignItems: "flex-start",
|
|
222
|
+
children: [
|
|
223
|
+
/*#__PURE__*/ jsx(Typography, {
|
|
224
|
+
variant: "pi",
|
|
225
|
+
fontWeight: "bold",
|
|
226
|
+
textColor: "neutral500",
|
|
227
|
+
children: formatMessage(item.label)
|
|
228
|
+
}),
|
|
229
|
+
/*#__PURE__*/ jsx(Typography, {
|
|
230
|
+
variant: "omega",
|
|
231
|
+
fontWeight: "bold",
|
|
232
|
+
textColor: "neutral800",
|
|
233
|
+
children: formatNumber({
|
|
234
|
+
locale,
|
|
235
|
+
number: key === 'entries' ? totalCountEntries : value
|
|
236
|
+
})
|
|
237
|
+
})
|
|
238
|
+
]
|
|
239
|
+
})
|
|
240
|
+
]
|
|
241
|
+
})
|
|
242
|
+
}, `key-statistics-${key}`);
|
|
243
|
+
})
|
|
244
|
+
});
|
|
245
|
+
};
|
|
48
246
|
|
|
49
|
-
export { ProfileWidget };
|
|
247
|
+
export { KeyStatisticsWidget, ProfileWidget };
|
|
50
248
|
//# sourceMappingURL=Widgets.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Widgets.mjs","sources":["../../../../../admin/src/components/Widgets.tsx"],"sourcesContent":["import { useAuth } from '@strapi/admin/strapi-admin';\nimport { Avatar, Badge, Flex, Typography } from '@strapi/design-system';\nimport { styled } from 'styled-components';\n\nimport { getDisplayName, getInitials } from '../utils/users';\n\n/* -------------------------------------------------------------------------------------------------\n * ProfileWidget\n * -----------------------------------------------------------------------------------------------*/\n\nconst DisplayNameTypography = styled(Typography)`\n font-size: 2.4rem;\n`;\n\nconst ProfileWidget = () => {\n const user = useAuth('User', (state) => state.user);\n const userDisplayName = getDisplayName(user);\n const initials = getInitials(user);\n\n return (\n <Flex direction=\"column\" gap={3} height=\"100%\" justifyContent=\"center\">\n <Avatar.Item delayMs={0} fallback={initials} />\n {userDisplayName && (\n <DisplayNameTypography fontWeight=\"bold\" textTransform=\"none\" textAlign=\"center\">\n {userDisplayName}\n </DisplayNameTypography>\n )}\n {user?.email && (\n <Typography variant=\"omega\" textColor=\"neutral600\">\n {user?.email}\n </Typography>\n )}\n {user?.roles?.length && (\n <Flex marginTop={2} gap={1} wrap=\"wrap\">\n {user?.roles?.map((role) => <Badge key={role.id}>{role.name}</Badge>)}\n </Flex>\n )}\n </Flex>\n );\n};\n\nexport { ProfileWidget };\n"],"names":["DisplayNameTypography","styled","Typography","ProfileWidget","user","useAuth","state","userDisplayName","getDisplayName","initials","getInitials","_jsxs","Flex","direction","gap","height","justifyContent","_jsx","Avatar","Item","delayMs","fallback","fontWeight","textTransform","textAlign","email","variant","textColor","roles","length","marginTop","wrap","map","role","Badge","name","id"],"mappings":";;;;;;AAMA;;AAEkG,qGAElG,MAAMA,qBAAAA,GAAwBC,MAAOC,CAAAA,UAAAA,CAAW;;AAEhD,CAAC;AAED,MAAMC,aAAgB,GAAA,IAAA;AACpB,IAAA,MAAMC,OAAOC,OAAQ,CAAA,MAAA,EAAQ,CAACC,KAAAA,GAAUA,MAAMF,IAAI,CAAA;AAClD,IAAA,MAAMG,kBAAkBC,cAAeJ,CAAAA,IAAAA,CAAAA;AACvC,IAAA,MAAMK,WAAWC,WAAYN,CAAAA,IAAAA,CAAAA;AAE7B,IAAA,qBACEO,IAACC,CAAAA,IAAAA,EAAAA;QAAKC,SAAU,EAAA,QAAA;QAASC,GAAK,EAAA,CAAA;QAAGC,MAAO,EAAA,MAAA;QAAOC,cAAe,EAAA,QAAA;;AAC5D,0BAAAC,GAAA,CAACC,OAAOC,IAAI,EAAA;gBAACC,OAAS,EAAA,CAAA;gBAAGC,QAAUZ,EAAAA;;AAClCF,YAAAA,eAAAA,kBACCU,GAACjB,CAAAA,qBAAAA,EAAAA;gBAAsBsB,UAAW,EAAA,MAAA;gBAAOC,aAAc,EAAA,MAAA;gBAAOC,SAAU,EAAA,QAAA;AACrEjB,gBAAAA,QAAAA,EAAAA;;AAGJH,YAAAA,IAAAA,EAAMqB,uBACLR,GAACf,CAAAA,UAAAA,EAAAA;gBAAWwB,OAAQ,EAAA,OAAA;gBAAQC,SAAU,EAAA,YAAA;0BACnCvB,IAAMqB,EAAAA;;YAGVrB,IAAMwB,EAAAA,KAAAA,EAAOC,wBACZZ,GAACL,CAAAA,IAAAA,EAAAA;gBAAKkB,SAAW,EAAA,CAAA;gBAAGhB,GAAK,EAAA,CAAA;gBAAGiB,IAAK,EAAA,MAAA;AAC9B3B,gBAAAA,QAAAA,EAAAA,IAAAA,EAAMwB,KAAOI,EAAAA,GAAAA,CAAI,CAACC,IAAAA,iBAAShB,GAACiB,CAAAA,KAAAA,EAAAA;AAAqBD,wBAAAA,QAAAA,EAAAA,IAAAA,CAAKE;AAAfF,qBAAAA,EAAAA,IAAAA,CAAKG,EAAE,CAAA;;;;AAKzD;;;;"}
|
|
1
|
+
{"version":3,"file":"Widgets.mjs","sources":["../../../../../admin/src/components/Widgets.tsx"],"sourcesContent":["import { useAuth } from '@strapi/admin/strapi-admin';\nimport { Avatar, Badge, Box, Flex, Typography } from '@strapi/design-system';\nimport { Earth, Images, User, Key, Files, Layout, Graph, Webhooks } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { Link } from 'react-router-dom';\nimport { styled } from 'styled-components';\n\nimport { useGetCountDocumentsQuery, useGetKeyStatisticsQuery } from '../services/homepage';\nimport { getDisplayName, getInitials } from '../utils/users';\n\nimport { Widget } from './WidgetHelpers';\n\n/* -------------------------------------------------------------------------------------------------\n * ProfileWidget\n * -----------------------------------------------------------------------------------------------*/\n\nconst DisplayNameTypography = styled(Typography)`\n font-size: 2.4rem;\n`;\n\nconst ProfileWidget = () => {\n const user = useAuth('User', (state) => state.user);\n const userDisplayName = getDisplayName(user);\n const initials = getInitials(user);\n\n return (\n <Flex direction=\"column\" gap={3} height=\"100%\" justifyContent=\"center\">\n <Avatar.Item delayMs={0} fallback={initials} />\n {userDisplayName && (\n <DisplayNameTypography fontWeight=\"bold\" textTransform=\"none\" textAlign=\"center\">\n {userDisplayName}\n </DisplayNameTypography>\n )}\n {user?.email && (\n <Typography variant=\"omega\" textColor=\"neutral600\">\n {user?.email}\n </Typography>\n )}\n {user?.roles?.length && (\n <Flex marginTop={2} gap={1} wrap=\"wrap\">\n {user?.roles?.map((role) => <Badge key={role.id}>{role.name}</Badge>)}\n </Flex>\n )}\n </Flex>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Key Statistics\n * -----------------------------------------------------------------------------------------------*/\nconst Grid = styled(Box)`\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 0;\n border: 1px solid ${({ theme }) => theme.colors.neutral200};\n border-radius: ${({ theme }) => theme.borderRadius};\n overflow: hidden;\n`;\n\nconst GridCell = styled(Box)`\n border-bottom: 1px solid ${({ theme }) => theme.colors.neutral200};\n border-right: 1px solid ${({ theme }) => theme.colors.neutral200};\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n\n &:nth-child(2n) {\n border-right: none;\n }\n &:nth-last-child(-n + 2) {\n border-bottom: none;\n }\n`;\n\nconst formatNumber = ({ locale, number }: { locale: string; number: number }) => {\n return new Intl.NumberFormat(locale, {\n notation: 'compact',\n maximumFractionDigits: 1,\n }).format(number);\n};\n\nconst LinkCell = styled(Link)`\n text-decoration: none;\n padding: ${({ theme }) => theme.spaces[3]};\n`;\n\nconst KeyStatisticsWidget = () => {\n const { formatMessage, locale } = useIntl();\n const { data: countDocuments, isLoading: isLoadingCountDocuments } = useGetCountDocumentsQuery();\n const { data: countKeyStatistics, isLoading: isLoadingKeyStatistics } =\n useGetKeyStatisticsQuery();\n\n if (isLoadingKeyStatistics || isLoadingCountDocuments) {\n return <Widget.Loading />;\n }\n\n if (!countKeyStatistics || !countDocuments) {\n return <Widget.Error />;\n }\n\n const keyStatisticsList = {\n entries: {\n label: {\n id: 'widget.key-statistics.list.entries',\n defaultMessage: 'Entries',\n },\n icon: {\n component: <Files />,\n background: 'primary100',\n color: 'primary600',\n },\n link: '/content-manager',\n },\n assets: {\n label: {\n id: 'widget.key-statistics.list.assets',\n defaultMessage: 'Assets',\n },\n icon: {\n component: <Images />,\n background: 'warning100',\n color: 'warning600',\n },\n link: '/plugins/upload',\n },\n contentTypes: {\n label: {\n id: 'widget.key-statistics.list.contentTypes',\n defaultMessage: 'Content-Types',\n },\n icon: {\n component: <Layout />,\n background: 'secondary100',\n color: 'secondary600',\n },\n link: '/plugins/content-type-builder',\n },\n components: {\n label: {\n id: 'widget.key-statistics.list.components',\n defaultMessage: 'Components',\n },\n icon: {\n component: <Graph />,\n background: 'alternative100',\n color: 'alternative600',\n },\n link: '/plugins/content-type-builder',\n },\n locales: {\n label: {\n id: 'widget.key-statistics.list.locales',\n defaultMessage: 'Locales',\n },\n icon: {\n component: <Earth />,\n background: 'success100',\n color: 'success600',\n },\n link: '/settings/internationalization',\n },\n admins: {\n label: {\n id: 'widget.key-statistics.list.admins',\n defaultMessage: 'Admins',\n },\n icon: {\n component: <User />,\n background: 'danger100',\n color: 'danger600',\n },\n link: '/settings/users?pageSize=10&page=1&sort=firstname',\n },\n webhooks: {\n label: {\n id: 'widget.key-statistics.list.webhooks',\n defaultMessage: 'Webhooks',\n },\n icon: {\n component: <Webhooks />,\n background: 'alternative100',\n color: 'alternative600',\n },\n link: '/settings/webhooks',\n },\n apiTokens: {\n label: {\n id: 'widget.key-statistics.list.apiTokens',\n defaultMessage: 'API Tokens',\n },\n icon: {\n component: <Key />,\n background: 'neutral100',\n color: 'neutral600',\n },\n link: '/settings/api-tokens?sort=name:ASC',\n },\n };\n\n const { draft, published, modified } = countDocuments ?? {\n draft: 0,\n published: 0,\n modified: 0,\n };\n\n const totalCountEntries = draft + published + modified;\n\n return (\n <Grid>\n {Object.entries(keyStatisticsList).map(([key, item]) => {\n const value = countKeyStatistics?.[key as keyof typeof countKeyStatistics];\n return (\n value !== null && (\n <GridCell\n as={LinkCell}\n to={item.link}\n key={`key-statistics-${key}`}\n data-testid={`stat-${key}`}\n >\n <Flex alignItems=\"center\" gap={2}>\n <Flex\n padding={2}\n borderRadius={1}\n background={item.icon.background}\n color={item.icon.color}\n >\n {item.icon.component}\n </Flex>\n <Flex direction=\"column\" alignItems=\"flex-start\">\n <Typography variant=\"pi\" fontWeight=\"bold\" textColor=\"neutral500\">\n {formatMessage(item.label)}\n </Typography>\n <Typography variant=\"omega\" fontWeight=\"bold\" textColor=\"neutral800\">\n {formatNumber({\n locale,\n number: key === 'entries' ? totalCountEntries : value,\n })}\n </Typography>\n </Flex>\n </Flex>\n </GridCell>\n )\n );\n })}\n </Grid>\n );\n};\n\nexport { ProfileWidget, KeyStatisticsWidget };\n"],"names":["DisplayNameTypography","styled","Typography","ProfileWidget","user","useAuth","state","userDisplayName","getDisplayName","initials","getInitials","_jsxs","Flex","direction","gap","height","justifyContent","_jsx","Avatar","Item","delayMs","fallback","fontWeight","textTransform","textAlign","email","variant","textColor","roles","length","marginTop","wrap","map","role","Badge","name","id","Grid","Box","theme","colors","neutral200","borderRadius","GridCell","formatNumber","locale","number","Intl","NumberFormat","notation","maximumFractionDigits","format","LinkCell","Link","spaces","KeyStatisticsWidget","formatMessage","useIntl","data","countDocuments","isLoading","isLoadingCountDocuments","useGetCountDocumentsQuery","countKeyStatistics","isLoadingKeyStatistics","useGetKeyStatisticsQuery","Widget","Loading","Error","keyStatisticsList","entries","label","defaultMessage","icon","component","Files","background","color","link","assets","Images","contentTypes","Layout","components","Graph","locales","Earth","admins","User","webhooks","Webhooks","apiTokens","Key","draft","published","modified","totalCountEntries","Object","key","item","value","as","to","data-testid","alignItems","padding"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Widgets.js","sources":["../../../../../../admin/src/core/apis/Widgets.ts"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\n\nimport invariant from 'invariant';\nimport { To } from 'react-router-dom';\n\nimport { Permission } from '../../../../shared/contracts/shared';\n\nimport type { Internal, Utils } from '@strapi/types';\nimport type { MessageDescriptor } from 'react-intl';\n\ntype WidgetUID = Utils.String.Suffix<\n | Internal.Namespace.WithSeparator<Internal.Namespace.Plugin>\n | Internal.Namespace.WithSeparator<Internal.Namespace.Global>,\n string\n>;\n\ntype WidgetArgs = {\n icon?: typeof import('@strapi/icons').PuzzlePiece;\n title: MessageDescriptor;\n link?: {\n label: MessageDescriptor;\n href: To;\n };\n component: () => Promise<React.ComponentType>;\n pluginId?: string;\n id: string;\n permissions?: Array<Pick<Permission, 'action'> & Partial<Omit<Permission, 'action'>>>;\n};\n\ntype WidgetWithUID = Omit<WidgetArgs, 'id' | 'pluginId'> & { uid: WidgetUID };\n\ntype DescriptionReducer = (prev: WidgetArgs[]) => WidgetArgs[];\n\nclass Widgets {\n widgets: WidgetArgs[];\n\n constructor() {\n this.widgets = [];\n }\n\n private generateUid = (widget: WidgetArgs): WidgetUID => {\n return widget.pluginId ? `plugin::${widget.pluginId}.${widget.id}` : `global::${widget.id}`;\n };\n\n private checkWidgets = (widgets: WidgetArgs[]): void => {\n widgets.forEach((widget) => {\n invariant(widget.id, 'An id must be provided');\n invariant(widget.component, 'A component must be provided');\n invariant(widget.title, 'A title must be provided');\n invariant(widget.icon, 'An icon must be provided');\n });\n };\n\n register(widgets: WidgetArgs | WidgetArgs[] | DescriptionReducer) {\n if (Array.isArray(widgets)) {\n this.checkWidgets(widgets);\n this.widgets = [...this.widgets, ...widgets];\n } else if (typeof widgets === 'function') {\n const newWidgets = widgets(this.widgets);\n this.checkWidgets(newWidgets);\n this.widgets = newWidgets;\n } else if (typeof widgets === 'object') {\n this.checkWidgets([widgets]);\n this.widgets.push(widgets);\n } else {\n throw new Error('Expected widgets to be an array or a reducer function');\n }\n }\n\n getAll = (): WidgetWithUID[] => {\n return this.widgets.map((widget) => {\n const { id, pluginId, ...widgetBase } = widget;\n return {\n ...widgetBase,\n uid: this.generateUid(widget),\n };\n });\n };\n}\n\nexport { Widgets };\nexport type { WidgetArgs, WidgetWithUID };\n"],"names":["Widgets","register","widgets","Array","isArray","checkWidgets","newWidgets","push","Error","constructor","generateUid","widget","pluginId","id","forEach","invariant","component","title","icon","getAll","map","widgetBase","uid"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"Widgets.js","sources":["../../../../../../admin/src/core/apis/Widgets.ts"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\n\nimport invariant from 'invariant';\nimport { To } from 'react-router-dom';\n\nimport { Permission } from '../../../../shared/contracts/shared';\n\nimport type { Internal, Utils } from '@strapi/types';\nimport type { MessageDescriptor } from 'react-intl';\n\ntype WidgetUID = Utils.String.Suffix<\n | Internal.Namespace.WithSeparator<Internal.Namespace.Plugin>\n | Internal.Namespace.WithSeparator<Internal.Namespace.Global>,\n string\n>;\n\ntype WidgetArgs = {\n icon?: typeof import('@strapi/icons').PuzzlePiece;\n title: MessageDescriptor;\n link?: {\n label: MessageDescriptor;\n href: To;\n };\n component: () => Promise<React.ComponentType>;\n pluginId?: string;\n id: string;\n permissions?: Array<Pick<Permission, 'action'> & Partial<Omit<Permission, 'action'>>>;\n roles?: string[];\n};\n\ntype WidgetWithUID = Omit<WidgetArgs, 'id' | 'pluginId'> & { uid: WidgetUID };\n\ntype DescriptionReducer = (prev: WidgetArgs[]) => WidgetArgs[];\n\nclass Widgets {\n widgets: WidgetArgs[];\n\n constructor() {\n this.widgets = [];\n }\n\n private generateUid = (widget: WidgetArgs): WidgetUID => {\n return widget.pluginId ? `plugin::${widget.pluginId}.${widget.id}` : `global::${widget.id}`;\n };\n\n private checkWidgets = (widgets: WidgetArgs[]): void => {\n widgets.forEach((widget) => {\n invariant(widget.id, 'An id must be provided');\n invariant(widget.component, 'A component must be provided');\n invariant(widget.title, 'A title must be provided');\n invariant(widget.icon, 'An icon must be provided');\n });\n };\n\n register(widgets: WidgetArgs | WidgetArgs[] | DescriptionReducer) {\n if (Array.isArray(widgets)) {\n this.checkWidgets(widgets);\n this.widgets = [...this.widgets, ...widgets];\n } else if (typeof widgets === 'function') {\n const newWidgets = widgets(this.widgets);\n this.checkWidgets(newWidgets);\n this.widgets = newWidgets;\n } else if (typeof widgets === 'object') {\n this.checkWidgets([widgets]);\n this.widgets.push(widgets);\n } else {\n throw new Error('Expected widgets to be an array or a reducer function');\n }\n }\n\n getAll = (): WidgetWithUID[] => {\n return this.widgets.map((widget) => {\n const { id, pluginId, ...widgetBase } = widget;\n return {\n ...widgetBase,\n uid: this.generateUid(widget),\n };\n });\n };\n}\n\nexport { Widgets };\nexport type { WidgetArgs, WidgetWithUID };\n"],"names":["Widgets","register","widgets","Array","isArray","checkWidgets","newWidgets","push","Error","constructor","generateUid","widget","pluginId","id","forEach","invariant","component","title","icon","getAll","map","widgetBase","uid"],"mappings":";;;;AAkCA,MAAMA,OAAAA,CAAAA;AAoBJC,IAAAA,QAAAA,CAASC,OAAuD,EAAE;QAChE,IAAIC,KAAAA,CAAMC,OAAO,CAACF,OAAU,CAAA,EAAA;YAC1B,IAAI,CAACG,YAAY,CAACH,OAAAA,CAAAA;YAClB,IAAI,CAACA,OAAO,GAAG;AAAI,gBAAA,GAAA,IAAI,CAACA,OAAO;AAAKA,gBAAAA,GAAAA;AAAQ,aAAA;SACvC,MAAA,IAAI,OAAOA,OAAAA,KAAY,UAAY,EAAA;AACxC,YAAA,MAAMI,UAAaJ,GAAAA,OAAAA,CAAQ,IAAI,CAACA,OAAO,CAAA;YACvC,IAAI,CAACG,YAAY,CAACC,UAAAA,CAAAA;YAClB,IAAI,CAACJ,OAAO,GAAGI,UAAAA;SACV,MAAA,IAAI,OAAOJ,OAAAA,KAAY,QAAU,EAAA;YACtC,IAAI,CAACG,YAAY,CAAC;AAACH,gBAAAA;AAAQ,aAAA,CAAA;AAC3B,YAAA,IAAI,CAACA,OAAO,CAACK,IAAI,CAACL,OAAAA,CAAAA;SACb,MAAA;AACL,YAAA,MAAM,IAAIM,KAAM,CAAA,uDAAA,CAAA;AAClB;AACF;IA/BAC,WAAc,EAAA;AAINC,QAAAA,IAAAA,CAAAA,WAAAA,GAAc,CAACC,MAAAA,GAAAA;YACrB,OAAOA,MAAAA,CAAOC,QAAQ,GAAG,CAAC,QAAQ,EAAED,MAAAA,CAAOC,QAAQ,CAAC,CAAC,EAAED,OAAOE,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAEF,MAAAA,CAAOE,EAAE,CAAC,CAAC;AAC7F,SAAA;AAEQR,QAAAA,IAAAA,CAAAA,YAAAA,GAAe,CAACH,OAAAA,GAAAA;YACtBA,OAAQY,CAAAA,OAAO,CAAC,CAACH,MAAAA,GAAAA;gBACfI,SAAUJ,CAAAA,MAAAA,CAAOE,EAAE,EAAE,wBAAA,CAAA;gBACrBE,SAAUJ,CAAAA,MAAAA,CAAOK,SAAS,EAAE,8BAAA,CAAA;gBAC5BD,SAAUJ,CAAAA,MAAAA,CAAOM,KAAK,EAAE,0BAAA,CAAA;gBACxBF,SAAUJ,CAAAA,MAAAA,CAAOO,IAAI,EAAE,0BAAA,CAAA;AACzB,aAAA,CAAA;AACF,SAAA;aAkBAC,MAAS,GAAA,IAAA;AACP,YAAA,OAAO,IAAI,CAACjB,OAAO,CAACkB,GAAG,CAAC,CAACT,MAAAA,GAAAA;AACvB,gBAAA,MAAM,EAAEE,EAAE,EAAED,QAAQ,EAAE,GAAGS,YAAY,GAAGV,MAAAA;gBACxC,OAAO;AACL,oBAAA,GAAGU,UAAU;oBACbC,GAAK,EAAA,IAAI,CAACZ,WAAW,CAACC,MAAAA;AACxB,iBAAA;AACF,aAAA,CAAA;AACF,SAAA;QAxCE,IAAI,CAACT,OAAO,GAAG,EAAE;AACnB;AAwCF;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Widgets.mjs","sources":["../../../../../../admin/src/core/apis/Widgets.ts"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\n\nimport invariant from 'invariant';\nimport { To } from 'react-router-dom';\n\nimport { Permission } from '../../../../shared/contracts/shared';\n\nimport type { Internal, Utils } from '@strapi/types';\nimport type { MessageDescriptor } from 'react-intl';\n\ntype WidgetUID = Utils.String.Suffix<\n | Internal.Namespace.WithSeparator<Internal.Namespace.Plugin>\n | Internal.Namespace.WithSeparator<Internal.Namespace.Global>,\n string\n>;\n\ntype WidgetArgs = {\n icon?: typeof import('@strapi/icons').PuzzlePiece;\n title: MessageDescriptor;\n link?: {\n label: MessageDescriptor;\n href: To;\n };\n component: () => Promise<React.ComponentType>;\n pluginId?: string;\n id: string;\n permissions?: Array<Pick<Permission, 'action'> & Partial<Omit<Permission, 'action'>>>;\n};\n\ntype WidgetWithUID = Omit<WidgetArgs, 'id' | 'pluginId'> & { uid: WidgetUID };\n\ntype DescriptionReducer = (prev: WidgetArgs[]) => WidgetArgs[];\n\nclass Widgets {\n widgets: WidgetArgs[];\n\n constructor() {\n this.widgets = [];\n }\n\n private generateUid = (widget: WidgetArgs): WidgetUID => {\n return widget.pluginId ? `plugin::${widget.pluginId}.${widget.id}` : `global::${widget.id}`;\n };\n\n private checkWidgets = (widgets: WidgetArgs[]): void => {\n widgets.forEach((widget) => {\n invariant(widget.id, 'An id must be provided');\n invariant(widget.component, 'A component must be provided');\n invariant(widget.title, 'A title must be provided');\n invariant(widget.icon, 'An icon must be provided');\n });\n };\n\n register(widgets: WidgetArgs | WidgetArgs[] | DescriptionReducer) {\n if (Array.isArray(widgets)) {\n this.checkWidgets(widgets);\n this.widgets = [...this.widgets, ...widgets];\n } else if (typeof widgets === 'function') {\n const newWidgets = widgets(this.widgets);\n this.checkWidgets(newWidgets);\n this.widgets = newWidgets;\n } else if (typeof widgets === 'object') {\n this.checkWidgets([widgets]);\n this.widgets.push(widgets);\n } else {\n throw new Error('Expected widgets to be an array or a reducer function');\n }\n }\n\n getAll = (): WidgetWithUID[] => {\n return this.widgets.map((widget) => {\n const { id, pluginId, ...widgetBase } = widget;\n return {\n ...widgetBase,\n uid: this.generateUid(widget),\n };\n });\n };\n}\n\nexport { Widgets };\nexport type { WidgetArgs, WidgetWithUID };\n"],"names":["Widgets","register","widgets","Array","isArray","checkWidgets","newWidgets","push","Error","constructor","generateUid","widget","pluginId","id","forEach","invariant","component","title","icon","getAll","map","widgetBase","uid"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"Widgets.mjs","sources":["../../../../../../admin/src/core/apis/Widgets.ts"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\n\nimport invariant from 'invariant';\nimport { To } from 'react-router-dom';\n\nimport { Permission } from '../../../../shared/contracts/shared';\n\nimport type { Internal, Utils } from '@strapi/types';\nimport type { MessageDescriptor } from 'react-intl';\n\ntype WidgetUID = Utils.String.Suffix<\n | Internal.Namespace.WithSeparator<Internal.Namespace.Plugin>\n | Internal.Namespace.WithSeparator<Internal.Namespace.Global>,\n string\n>;\n\ntype WidgetArgs = {\n icon?: typeof import('@strapi/icons').PuzzlePiece;\n title: MessageDescriptor;\n link?: {\n label: MessageDescriptor;\n href: To;\n };\n component: () => Promise<React.ComponentType>;\n pluginId?: string;\n id: string;\n permissions?: Array<Pick<Permission, 'action'> & Partial<Omit<Permission, 'action'>>>;\n roles?: string[];\n};\n\ntype WidgetWithUID = Omit<WidgetArgs, 'id' | 'pluginId'> & { uid: WidgetUID };\n\ntype DescriptionReducer = (prev: WidgetArgs[]) => WidgetArgs[];\n\nclass Widgets {\n widgets: WidgetArgs[];\n\n constructor() {\n this.widgets = [];\n }\n\n private generateUid = (widget: WidgetArgs): WidgetUID => {\n return widget.pluginId ? `plugin::${widget.pluginId}.${widget.id}` : `global::${widget.id}`;\n };\n\n private checkWidgets = (widgets: WidgetArgs[]): void => {\n widgets.forEach((widget) => {\n invariant(widget.id, 'An id must be provided');\n invariant(widget.component, 'A component must be provided');\n invariant(widget.title, 'A title must be provided');\n invariant(widget.icon, 'An icon must be provided');\n });\n };\n\n register(widgets: WidgetArgs | WidgetArgs[] | DescriptionReducer) {\n if (Array.isArray(widgets)) {\n this.checkWidgets(widgets);\n this.widgets = [...this.widgets, ...widgets];\n } else if (typeof widgets === 'function') {\n const newWidgets = widgets(this.widgets);\n this.checkWidgets(newWidgets);\n this.widgets = newWidgets;\n } else if (typeof widgets === 'object') {\n this.checkWidgets([widgets]);\n this.widgets.push(widgets);\n } else {\n throw new Error('Expected widgets to be an array or a reducer function');\n }\n }\n\n getAll = (): WidgetWithUID[] => {\n return this.widgets.map((widget) => {\n const { id, pluginId, ...widgetBase } = widget;\n return {\n ...widgetBase,\n uid: this.generateUid(widget),\n };\n });\n };\n}\n\nexport { Widgets };\nexport type { WidgetArgs, WidgetWithUID };\n"],"names":["Widgets","register","widgets","Array","isArray","checkWidgets","newWidgets","push","Error","constructor","generateUid","widget","pluginId","id","forEach","invariant","component","title","icon","getAll","map","widgetBase","uid"],"mappings":";;AAkCA,MAAMA,OAAAA,CAAAA;AAoBJC,IAAAA,QAAAA,CAASC,OAAuD,EAAE;QAChE,IAAIC,KAAAA,CAAMC,OAAO,CAACF,OAAU,CAAA,EAAA;YAC1B,IAAI,CAACG,YAAY,CAACH,OAAAA,CAAAA;YAClB,IAAI,CAACA,OAAO,GAAG;AAAI,gBAAA,GAAA,IAAI,CAACA,OAAO;AAAKA,gBAAAA,GAAAA;AAAQ,aAAA;SACvC,MAAA,IAAI,OAAOA,OAAAA,KAAY,UAAY,EAAA;AACxC,YAAA,MAAMI,UAAaJ,GAAAA,OAAAA,CAAQ,IAAI,CAACA,OAAO,CAAA;YACvC,IAAI,CAACG,YAAY,CAACC,UAAAA,CAAAA;YAClB,IAAI,CAACJ,OAAO,GAAGI,UAAAA;SACV,MAAA,IAAI,OAAOJ,OAAAA,KAAY,QAAU,EAAA;YACtC,IAAI,CAACG,YAAY,CAAC;AAACH,gBAAAA;AAAQ,aAAA,CAAA;AAC3B,YAAA,IAAI,CAACA,OAAO,CAACK,IAAI,CAACL,OAAAA,CAAAA;SACb,MAAA;AACL,YAAA,MAAM,IAAIM,KAAM,CAAA,uDAAA,CAAA;AAClB;AACF;IA/BAC,WAAc,EAAA;AAINC,QAAAA,IAAAA,CAAAA,WAAAA,GAAc,CAACC,MAAAA,GAAAA;YACrB,OAAOA,MAAAA,CAAOC,QAAQ,GAAG,CAAC,QAAQ,EAAED,MAAAA,CAAOC,QAAQ,CAAC,CAAC,EAAED,OAAOE,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAEF,MAAAA,CAAOE,EAAE,CAAC,CAAC;AAC7F,SAAA;AAEQR,QAAAA,IAAAA,CAAAA,YAAAA,GAAe,CAACH,OAAAA,GAAAA;YACtBA,OAAQY,CAAAA,OAAO,CAAC,CAACH,MAAAA,GAAAA;gBACfI,SAAUJ,CAAAA,MAAAA,CAAOE,EAAE,EAAE,wBAAA,CAAA;gBACrBE,SAAUJ,CAAAA,MAAAA,CAAOK,SAAS,EAAE,8BAAA,CAAA;gBAC5BD,SAAUJ,CAAAA,MAAAA,CAAOM,KAAK,EAAE,0BAAA,CAAA;gBACxBF,SAAUJ,CAAAA,MAAAA,CAAOO,IAAI,EAAE,0BAAA,CAAA;AACzB,aAAA,CAAA;AACF,SAAA;aAkBAC,MAAS,GAAA,IAAA;AACP,YAAA,OAAO,IAAI,CAACjB,OAAO,CAACkB,GAAG,CAAC,CAACT,MAAAA,GAAAA;AACvB,gBAAA,MAAM,EAAEE,EAAE,EAAED,QAAQ,EAAE,GAAGS,YAAY,GAAGV,MAAAA;gBACxC,OAAO;AACL,oBAAA,GAAGU,UAAU;oBACbC,GAAK,EAAA,IAAI,CAACZ,WAAW,CAACC,MAAAA;AACxB,iBAAA;AACF,aAAA,CAAA;AACF,SAAA;QAxCE,IAAI,CAACT,OAAO,GAAG,EAAE;AACnB;AAwCF;;;;"}
|
|
@@ -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 { 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 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 | 'willEditEntryFromHome'\n | 'willEditEntryFromList'\n | 'willEditFieldOfContentType'\n | 'willEditMediaLibraryConfig'\n | 'willEditNameOfContentType'\n | 'willEditNameOfSingleType'\n | 'willEditAuthenticationProvider'\n | 'willEditFieldNameOnContentType'\n | 'willEditStage'\n | 'willFilterEntries'\n | 'willInstallPlugin'\n | 'willUnpublishEntry'\n | 'willSaveComponent'\n | 'willSaveContentType'\n | 'willSaveContentTypeLayout'\n | 'didEditFieldNameOnContentType'\n | 'didCreateRelease'\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 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;\n };\n}\n\ninterface DidStartGuidedTour {\n name: 'didStartGuidedTourFromHomepage';\n properties: {\n name: keyof Tours;\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 | LogoEvent\n | TokenEvents\n | UpdateEntryEvents\n | WillModifyTokenEvent\n | WillNavigateEvent\n | DidPublishRelease\n | MediaEvents\n | DidUpdateCTBSchema\n | DidSkipGuidedTour\n | DidCompleteGuidedTour\n | DidStartGuidedTour;\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 { 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 groupProperties: {\n ...telemetryProperties,\n projectId: uuid,\n projectType: window.strapi.projectType,\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","useContext","useAppInfo","trackUsage","useCallback","properties","window","strapi","telemetryDisabled","res","axios","post","eventProperties","userProperties","projectType","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 { 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 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 | 'willEditEntryFromHome'\n | 'willEditEntryFromList'\n | 'willEditReleaseFromHome'\n | 'willEditFieldOfContentType'\n | 'willEditMediaLibraryConfig'\n | 'willEditNameOfContentType'\n | 'willEditNameOfSingleType'\n | 'willEditAuthenticationProvider'\n | 'willEditFieldNameOnContentType'\n | 'willEditStage'\n | 'willFilterEntries'\n | 'willInstallPlugin'\n | 'willOpenAuditLogDetails'\n | 'willUnpublishEntry'\n | 'willSaveComponent'\n | 'willSaveContentType'\n | 'willSaveContentTypeLayout'\n | 'didEditFieldNameOnContentType'\n | 'didCreateRelease'\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 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;\n };\n}\n\ninterface DidStartGuidedTour {\n name: 'didStartGuidedTourFromHomepage';\n properties: {\n name: keyof Tours;\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 | LogoEvent\n | TokenEvents\n | UpdateEntryEvents\n | WillModifyTokenEvent\n | WillNavigateEvent\n | DidPublishRelease\n | MediaEvents\n | DidUpdateCTBSchema\n | DidSkipGuidedTour\n | DidCompleteGuidedTour\n | DidStartGuidedTour;\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 { 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 groupProperties: {\n ...telemetryProperties,\n projectId: uuid,\n projectType: window.strapi.projectType,\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","useContext","useAppInfo","trackUsage","useCallback","properties","window","strapi","telemetryDisabled","res","axios","post","eventProperties","userProperties","projectType","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 { 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 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 | 'willEditEntryFromHome'\n | 'willEditEntryFromList'\n | 'willEditFieldOfContentType'\n | 'willEditMediaLibraryConfig'\n | 'willEditNameOfContentType'\n | 'willEditNameOfSingleType'\n | 'willEditAuthenticationProvider'\n | 'willEditFieldNameOnContentType'\n | 'willEditStage'\n | 'willFilterEntries'\n | 'willInstallPlugin'\n | 'willUnpublishEntry'\n | 'willSaveComponent'\n | 'willSaveContentType'\n | 'willSaveContentTypeLayout'\n | 'didEditFieldNameOnContentType'\n | 'didCreateRelease'\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 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;\n };\n}\n\ninterface DidStartGuidedTour {\n name: 'didStartGuidedTourFromHomepage';\n properties: {\n name: keyof Tours;\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 | LogoEvent\n | TokenEvents\n | UpdateEntryEvents\n | WillModifyTokenEvent\n | WillNavigateEvent\n | DidPublishRelease\n | MediaEvents\n | DidUpdateCTBSchema\n | DidSkipGuidedTour\n | DidCompleteGuidedTour\n | DidStartGuidedTour;\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 { 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 groupProperties: {\n ...telemetryProperties,\n projectId: uuid,\n projectType: window.strapi.projectType,\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","useContext","useAppInfo","trackUsage","useCallback","properties","window","strapi","telemetryDisabled","res","axios","post","eventProperties","userProperties","projectType","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 { 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 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 | 'willEditEntryFromHome'\n | 'willEditEntryFromList'\n | 'willEditReleaseFromHome'\n | 'willEditFieldOfContentType'\n | 'willEditMediaLibraryConfig'\n | 'willEditNameOfContentType'\n | 'willEditNameOfSingleType'\n | 'willEditAuthenticationProvider'\n | 'willEditFieldNameOnContentType'\n | 'willEditStage'\n | 'willFilterEntries'\n | 'willInstallPlugin'\n | 'willOpenAuditLogDetails'\n | 'willUnpublishEntry'\n | 'willSaveComponent'\n | 'willSaveContentType'\n | 'willSaveContentTypeLayout'\n | 'didEditFieldNameOnContentType'\n | 'didCreateRelease'\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 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;\n };\n}\n\ninterface DidStartGuidedTour {\n name: 'didStartGuidedTourFromHomepage';\n properties: {\n name: keyof Tours;\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 | LogoEvent\n | TokenEvents\n | UpdateEntryEvents\n | WillModifyTokenEvent\n | WillNavigateEvent\n | DidPublishRelease\n | MediaEvents\n | DidUpdateCTBSchema\n | DidSkipGuidedTour\n | DidCompleteGuidedTour\n | DidStartGuidedTour;\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 { 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 groupProperties: {\n ...telemetryProperties,\n projectId: uuid,\n projectType: window.strapi.projectType,\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","useContext","useAppInfo","trackUsage","useCallback","properties","window","strapi","telemetryDisabled","res","axios","post","eventProperties","userProperties","projectType","err"],"mappings":"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"}
|
|
@@ -36,27 +36,10 @@ function _interopNamespaceDefault(e) {
|
|
|
36
36
|
|
|
37
37
|
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
38
38
|
|
|
39
|
-
const WidgetRoot = ({ title, icon = icons.PuzzlePiece,
|
|
39
|
+
const WidgetRoot = ({ title, icon = icons.PuzzlePiece, children, link })=>{
|
|
40
40
|
const { formatMessage } = reactIntl.useIntl();
|
|
41
41
|
const id = React__namespace.useId();
|
|
42
42
|
const Icon = icon;
|
|
43
|
-
const [permissionStatus, setPermissionStatus] = React__namespace.useState('loading');
|
|
44
|
-
const checkUserHasPermissions = Auth.useAuth('WidgetRoot', (state)=>state.checkUserHasPermissions);
|
|
45
|
-
React__namespace.useEffect(()=>{
|
|
46
|
-
const checkPermissions = async ()=>{
|
|
47
|
-
const matchingPermissions = await checkUserHasPermissions(permissions);
|
|
48
|
-
const shouldGrant = matchingPermissions.length >= permissions.length;
|
|
49
|
-
setPermissionStatus(shouldGrant ? 'granted' : 'forbidden');
|
|
50
|
-
};
|
|
51
|
-
if (!permissions || permissions.length === 0) {
|
|
52
|
-
setPermissionStatus('granted');
|
|
53
|
-
} else {
|
|
54
|
-
checkPermissions();
|
|
55
|
-
}
|
|
56
|
-
}, [
|
|
57
|
-
checkUserHasPermissions,
|
|
58
|
-
permissions
|
|
59
|
-
]);
|
|
60
43
|
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
|
61
44
|
width: "100%",
|
|
62
45
|
hasRadius: true,
|
|
@@ -106,16 +89,12 @@ const WidgetRoot = ({ title, icon = icons.PuzzlePiece, permissions = [], childre
|
|
|
106
89
|
})
|
|
107
90
|
]
|
|
108
91
|
}),
|
|
109
|
-
/*#__PURE__*/ jsxRuntime.
|
|
92
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
|
|
110
93
|
width: "100%",
|
|
111
94
|
height: "261px",
|
|
112
95
|
overflow: "auto",
|
|
113
96
|
tag: "main",
|
|
114
|
-
children:
|
|
115
|
-
permissionStatus === 'loading' && /*#__PURE__*/ jsxRuntime.jsx(WidgetHelpers.Widget.Loading, {}),
|
|
116
|
-
permissionStatus === 'forbidden' && /*#__PURE__*/ jsxRuntime.jsx(WidgetHelpers.Widget.NoPermissions, {}),
|
|
117
|
-
permissionStatus === 'granted' && children
|
|
118
|
-
]
|
|
97
|
+
children: children
|
|
119
98
|
})
|
|
120
99
|
]
|
|
121
100
|
});
|
|
@@ -146,6 +125,25 @@ const WidgetRoot = ({ title, icon = icons.PuzzlePiece, permissions = [], childre
|
|
|
146
125
|
const user = Auth.useAuth('HomePageCE', (state)=>state.user);
|
|
147
126
|
const displayName = user?.firstname ?? user?.username ?? user?.email;
|
|
148
127
|
const getAllWidgets = StrapiApp.useStrapiApp('UnstableHomepageCe', (state)=>state.widgets.getAll);
|
|
128
|
+
const checkUserHasPermissions = Auth.useAuth('WidgetRoot', (state)=>state.checkUserHasPermissions);
|
|
129
|
+
const [filteredWidgets, setFilteredWidgets] = React__namespace.useState([]);
|
|
130
|
+
const [loading, setLoading] = React__namespace.useState(true);
|
|
131
|
+
React__namespace.useEffect(()=>{
|
|
132
|
+
const checkWidgetsPermissions = async ()=>{
|
|
133
|
+
const allWidgets = getAllWidgets();
|
|
134
|
+
const authorizedWidgets = await Promise.all(allWidgets.map(async (widget)=>{
|
|
135
|
+
if (!widget.permissions || widget.permissions.length === 0) return true;
|
|
136
|
+
const matchingPermissions = await checkUserHasPermissions(widget.permissions);
|
|
137
|
+
return matchingPermissions.length >= widget.permissions.length;
|
|
138
|
+
}));
|
|
139
|
+
setFilteredWidgets(allWidgets.filter((_, i)=>authorizedWidgets[i]));
|
|
140
|
+
setLoading(false);
|
|
141
|
+
};
|
|
142
|
+
checkWidgetsPermissions();
|
|
143
|
+
}, [
|
|
144
|
+
checkUserHasPermissions,
|
|
145
|
+
getAllWidgets
|
|
146
|
+
]);
|
|
149
147
|
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Main, {
|
|
150
148
|
children: [
|
|
151
149
|
/*#__PURE__*/ jsxRuntime.jsx(PageHelpers.Page.Title, {
|
|
@@ -176,23 +174,27 @@ const WidgetRoot = ({ title, icon = icons.PuzzlePiece, permissions = [], childre
|
|
|
176
174
|
paddingBottom: 10,
|
|
177
175
|
children: [
|
|
178
176
|
/*#__PURE__*/ jsxRuntime.jsx(Overview.GuidedTourHomepageOverview, {}),
|
|
179
|
-
/*#__PURE__*/ jsxRuntime.jsx(designSystem.
|
|
177
|
+
loading ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
|
|
178
|
+
position: "absolute",
|
|
179
|
+
top: 0,
|
|
180
|
+
left: 0,
|
|
181
|
+
right: 0,
|
|
182
|
+
bottom: 0,
|
|
183
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(PageHelpers.Page.Loading, {})
|
|
184
|
+
}) : /*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Root, {
|
|
180
185
|
gap: 5,
|
|
181
|
-
children:
|
|
182
|
-
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Item, {
|
|
186
|
+
children: filteredWidgets.map((widget)=>/*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Item, {
|
|
183
187
|
col: 6,
|
|
184
188
|
s: 12,
|
|
185
189
|
children: /*#__PURE__*/ jsxRuntime.jsx(WidgetRoot, {
|
|
186
190
|
title: widget.title,
|
|
187
191
|
icon: widget.icon,
|
|
188
|
-
permissions: widget.permissions,
|
|
189
192
|
link: widget.link,
|
|
190
193
|
children: /*#__PURE__*/ jsxRuntime.jsx(WidgetComponent, {
|
|
191
194
|
component: widget.component
|
|
192
195
|
})
|
|
193
196
|
})
|
|
194
|
-
}, widget.uid)
|
|
195
|
-
})
|
|
197
|
+
}, widget.uid))
|
|
196
198
|
})
|
|
197
199
|
]
|
|
198
200
|
})
|