@strapi/admin 5.16.1 → 5.17.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/components/UnstableGuidedTour/Context.js +1 -0
- package/dist/admin/admin/src/components/UnstableGuidedTour/Context.js.map +1 -1
- package/dist/admin/admin/src/components/UnstableGuidedTour/Context.mjs +1 -0
- package/dist/admin/admin/src/components/UnstableGuidedTour/Context.mjs.map +1 -1
- package/dist/admin/admin/src/components/UnstableGuidedTour/Tours.js +31 -4
- package/dist/admin/admin/src/components/UnstableGuidedTour/Tours.js.map +1 -1
- package/dist/admin/admin/src/components/UnstableGuidedTour/Tours.mjs +31 -4
- package/dist/admin/admin/src/components/UnstableGuidedTour/Tours.mjs.map +1 -1
- package/dist/admin/admin/src/features/Tracking.js +0 -33
- package/dist/admin/admin/src/features/Tracking.js.map +1 -1
- package/dist/admin/admin/src/features/Tracking.mjs +0 -33
- package/dist/admin/admin/src/features/Tracking.mjs.map +1 -1
- package/dist/admin/admin/src/layouts/AuthenticatedLayout.js +15 -8
- package/dist/admin/admin/src/layouts/AuthenticatedLayout.js.map +1 -1
- package/dist/admin/admin/src/layouts/AuthenticatedLayout.mjs +15 -8
- package/dist/admin/admin/src/layouts/AuthenticatedLayout.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/Users/ListPage.js +3 -3
- package/dist/admin/admin/src/pages/Settings/pages/Users/ListPage.js.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/Users/ListPage.mjs +3 -3
- package/dist/admin/admin/src/pages/Settings/pages/Users/ListPage.mjs.map +1 -1
- package/dist/admin/admin/src/services/admin.js +17 -3
- package/dist/admin/admin/src/services/admin.js.map +1 -1
- package/dist/admin/admin/src/services/admin.mjs +17 -4
- package/dist/admin/admin/src/services/admin.mjs.map +1 -1
- package/dist/admin/admin/src/services/apiTokens.js +4 -2
- package/dist/admin/admin/src/services/apiTokens.js.map +1 -1
- package/dist/admin/admin/src/services/apiTokens.mjs +4 -2
- package/dist/admin/admin/src/services/apiTokens.mjs.map +1 -1
- package/dist/admin/admin/src/utils/rulesEngine.js +75 -0
- package/dist/admin/admin/src/utils/rulesEngine.js.map +1 -0
- package/dist/admin/admin/src/utils/rulesEngine.mjs +72 -0
- package/dist/admin/admin/src/utils/rulesEngine.mjs.map +1 -0
- package/dist/admin/index.js +3 -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/UnstableGuidedTour/Context.d.ts +6 -5
- package/dist/admin/src/components/UnstableGuidedTour/Tours.d.ts +4 -1
- package/dist/admin/src/features/Tracking.d.ts +9 -2
- package/dist/admin/src/index.d.ts +1 -0
- package/dist/admin/src/services/admin.d.ts +8 -8
- package/dist/admin/src/services/apiTokens.d.ts +1 -1
- package/dist/admin/src/utils/rulesEngine.d.ts +23 -0
- package/dist/ee/server/src/index.d.ts +2 -12
- package/dist/ee/server/src/index.d.ts.map +1 -1
- package/dist/ee/server/src/routes/index.d.ts +1 -6
- package/dist/ee/server/src/routes/index.d.ts.map +1 -1
- package/dist/ee/server/src/routes/license-limit.d.ts +1 -6
- package/dist/ee/server/src/routes/license-limit.d.ts.map +1 -1
- package/dist/server/ee/server/src/routes/license-limit.js +1 -12
- package/dist/server/ee/server/src/routes/license-limit.js.map +1 -1
- package/dist/server/ee/server/src/routes/license-limit.mjs +1 -12
- package/dist/server/ee/server/src/routes/license-limit.mjs.map +1 -1
- package/dist/server/server/src/bootstrap.js +4 -12
- package/dist/server/server/src/bootstrap.js.map +1 -1
- package/dist/server/server/src/bootstrap.mjs +4 -12
- package/dist/server/server/src/bootstrap.mjs.map +1 -1
- package/dist/server/server/src/controllers/admin.js +12 -1
- package/dist/server/server/src/controllers/admin.js.map +1 -1
- package/dist/server/server/src/controllers/admin.mjs +12 -1
- package/dist/server/server/src/controllers/admin.mjs.map +1 -1
- package/dist/server/server/src/routes/admin.js +10 -0
- package/dist/server/server/src/routes/admin.js.map +1 -1
- package/dist/server/server/src/routes/admin.mjs +10 -0
- package/dist/server/server/src/routes/admin.mjs.map +1 -1
- package/dist/server/server/src/services/constants.js +14 -0
- package/dist/server/server/src/services/constants.js.map +1 -1
- package/dist/server/server/src/services/constants.mjs +14 -0
- package/dist/server/server/src/services/constants.mjs.map +1 -1
- package/dist/server/server/src/services/guided-tour.js +43 -0
- package/dist/server/server/src/services/guided-tour.js.map +1 -0
- package/dist/server/server/src/services/guided-tour.mjs +41 -0
- package/dist/server/server/src/services/guided-tour.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/server/src/services/user.js +28 -1
- package/dist/server/server/src/services/user.js.map +1 -1
- package/dist/server/server/src/services/user.mjs +28 -1
- package/dist/server/server/src/services/user.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/controllers/admin.d.ts +6 -1
- package/dist/server/src/controllers/admin.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts +6 -0
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +12 -0
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/routes/admin.d.ts.map +1 -1
- package/dist/server/src/services/constants.d.ts +11 -1
- package/dist/server/src/services/constants.d.ts.map +1 -1
- package/dist/server/src/services/guided-tour.d.ts +12 -0
- package/dist/server/src/services/guided-tour.d.ts.map +1 -0
- package/dist/server/src/services/index.d.ts +6 -0
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/user.d.ts +1 -0
- package/dist/server/src/services/user.d.ts.map +1 -1
- package/dist/shared/contracts/admin.d.ts +15 -0
- package/dist/shared/contracts/admin.d.ts.map +1 -1
- package/package.json +9 -7
|
@@ -40,6 +40,7 @@ function reducer(state, action) {
|
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
42
|
const UnstableGuidedTourContext = ({ children, tours: registeredTours })=>{
|
|
43
|
+
// TODO: Get local storage to init state
|
|
43
44
|
// Derive the tour state from the tours object
|
|
44
45
|
const tours = Object.keys(registeredTours).reduce((acc, tourName)=>{
|
|
45
46
|
const tourLength = Object.keys(registeredTours[tourName]).length;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Context.js","sources":["../../../../../../admin/src/components/UnstableGuidedTour/Context.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { produce } from 'immer';\n\nimport { createContext } from '../Context';\n\nimport type { Tours } from './Tours';\n\n/* -------------------------------------------------------------------------------------------------\n * GuidedTourProvider\n * -----------------------------------------------------------------------------------------------*/\n\ntype ValidTourName = keyof Tours;\n\ntype Action =\n | {\n type: 'next_step';\n payload: ValidTourName;\n }\n | {\n type: 'skip_tour';\n payload: ValidTourName;\n };\n\ntype
|
|
1
|
+
{"version":3,"file":"Context.js","sources":["../../../../../../admin/src/components/UnstableGuidedTour/Context.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { produce } from 'immer';\n\nimport { createContext } from '../Context';\n\nimport type { Tours } from './Tours';\n\n/* -------------------------------------------------------------------------------------------------\n * GuidedTourProvider\n * -----------------------------------------------------------------------------------------------*/\n\ntype ValidTourName = keyof Tours;\n\ntype Action =\n | {\n type: 'next_step';\n payload: ValidTourName;\n }\n | {\n type: 'skip_tour';\n payload: ValidTourName;\n };\n\ntype Tour = Record<ValidTourName, { currentStep: number; length: number; isCompleted: boolean }>;\ntype State = {\n tours: Tour;\n};\n\nconst [GuidedTourProviderImpl, unstableUseGuidedTour] = createContext<{\n state: State;\n dispatch: React.Dispatch<Action>;\n}>('UnstableGuidedTour');\n\nfunction reducer(state: State, action: Action): State {\n return produce(state, (draft) => {\n if (action.type === 'next_step') {\n const nextStep = draft.tours[action.payload].currentStep + 1;\n draft.tours[action.payload].currentStep = nextStep;\n draft.tours[action.payload].isCompleted = nextStep === draft.tours[action.payload].length;\n // TODO: Update local storage\n }\n\n if (action.type === 'skip_tour') {\n draft.tours[action.payload].isCompleted = true;\n // TODO: Update local storage\n }\n });\n}\n\nconst UnstableGuidedTourContext = ({\n children,\n tours: registeredTours,\n}: {\n children: React.ReactNode;\n // NOTE: Maybe we just import this directly instead of a prop?\n tours: Tours;\n}) => {\n // TODO: Get local storage to init state\n // Derive the tour state from the tours object\n const tours = Object.keys(registeredTours).reduce((acc, tourName) => {\n const tourLength = Object.keys(registeredTours[tourName as ValidTourName]).length;\n\n acc[tourName as ValidTourName] = {\n currentStep: 0,\n length: tourLength,\n isCompleted: false,\n };\n\n return acc;\n }, {} as Tour);\n\n const [state, dispatch] = React.useReducer(reducer, {\n tours,\n });\n\n return (\n <GuidedTourProviderImpl state={state} dispatch={dispatch}>\n {children}\n </GuidedTourProviderImpl>\n );\n};\n\nexport type { Action, State, ValidTourName };\nexport { UnstableGuidedTourContext, unstableUseGuidedTour, reducer };\n"],"names":["GuidedTourProviderImpl","unstableUseGuidedTour","createContext","reducer","state","action","produce","draft","type","nextStep","tours","payload","currentStep","isCompleted","length","UnstableGuidedTourContext","children","registeredTours","Object","keys","reduce","acc","tourName","tourLength","dispatch","React","useReducer","_jsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,MAAM,CAACA,sBAAAA,EAAwBC,qBAAsB,CAAA,GAAGC,qBAGrD,CAAA,oBAAA;AAEH,SAASC,OAAAA,CAAQC,KAAY,EAAEC,MAAc,EAAA;IAC3C,OAAOC,aAAAA,CAAQF,OAAO,CAACG,KAAAA,GAAAA;QACrB,IAAIF,MAAAA,CAAOG,IAAI,KAAK,WAAa,EAAA;YAC/B,MAAMC,QAAAA,GAAWF,MAAMG,KAAK,CAACL,OAAOM,OAAO,CAAC,CAACC,WAAW,GAAG,CAAA;AAC3DL,YAAAA,KAAAA,CAAMG,KAAK,CAACL,MAAAA,CAAOM,OAAO,CAAC,CAACC,WAAW,GAAGH,QAAAA;AAC1CF,YAAAA,KAAAA,CAAMG,KAAK,CAACL,MAAAA,CAAOM,OAAO,CAAC,CAACE,WAAW,GAAGJ,QAAaF,KAAAA,KAAAA,CAAMG,KAAK,CAACL,MAAAA,CAAOM,OAAO,CAAC,CAACG,MAAM;;AAE3F;QAEA,IAAIT,MAAAA,CAAOG,IAAI,KAAK,WAAa,EAAA;AAC/BD,YAAAA,KAAAA,CAAMG,KAAK,CAACL,MAAAA,CAAOM,OAAO,CAAC,CAACE,WAAW,GAAG,IAAA;;AAE5C;AACF,KAAA,CAAA;AACF;AAEA,MAAME,4BAA4B,CAAC,EACjCC,QAAQ,EACRN,KAAAA,EAAOO,eAAe,EAKvB,GAAA;;;IAGC,MAAMP,KAAAA,GAAQQ,OAAOC,IAAI,CAACF,iBAAiBG,MAAM,CAAC,CAACC,GAAKC,EAAAA,QAAAA,GAAAA;QACtD,MAAMC,UAAAA,GAAaL,OAAOC,IAAI,CAACF,eAAe,CAACK,QAAAA,CAA0B,EAAER,MAAM;QAEjFO,GAAG,CAACC,SAA0B,GAAG;YAC/BV,WAAa,EAAA,CAAA;YACbE,MAAQS,EAAAA,UAAAA;YACRV,WAAa,EAAA;AACf,SAAA;QAEA,OAAOQ,GAAAA;AACT,KAAA,EAAG,EAAC,CAAA;AAEJ,IAAA,MAAM,CAACjB,KAAOoB,EAAAA,QAAAA,CAAS,GAAGC,gBAAMC,CAAAA,UAAU,CAACvB,OAAS,EAAA;AAClDO,QAAAA;AACF,KAAA,CAAA;AAEA,IAAA,qBACEiB,cAAC3B,CAAAA,sBAAAA,EAAAA;QAAuBI,KAAOA,EAAAA,KAAAA;QAAOoB,QAAUA,EAAAA,QAAAA;AAC7CR,QAAAA,QAAAA,EAAAA;;AAGP;;;;;;"}
|
|
@@ -19,6 +19,7 @@ function reducer(state, action) {
|
|
|
19
19
|
});
|
|
20
20
|
}
|
|
21
21
|
const UnstableGuidedTourContext = ({ children, tours: registeredTours })=>{
|
|
22
|
+
// TODO: Get local storage to init state
|
|
22
23
|
// Derive the tour state from the tours object
|
|
23
24
|
const tours = Object.keys(registeredTours).reduce((acc, tourName)=>{
|
|
24
25
|
const tourLength = Object.keys(registeredTours[tourName]).length;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Context.mjs","sources":["../../../../../../admin/src/components/UnstableGuidedTour/Context.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { produce } from 'immer';\n\nimport { createContext } from '../Context';\n\nimport type { Tours } from './Tours';\n\n/* -------------------------------------------------------------------------------------------------\n * GuidedTourProvider\n * -----------------------------------------------------------------------------------------------*/\n\ntype ValidTourName = keyof Tours;\n\ntype Action =\n | {\n type: 'next_step';\n payload: ValidTourName;\n }\n | {\n type: 'skip_tour';\n payload: ValidTourName;\n };\n\ntype
|
|
1
|
+
{"version":3,"file":"Context.mjs","sources":["../../../../../../admin/src/components/UnstableGuidedTour/Context.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { produce } from 'immer';\n\nimport { createContext } from '../Context';\n\nimport type { Tours } from './Tours';\n\n/* -------------------------------------------------------------------------------------------------\n * GuidedTourProvider\n * -----------------------------------------------------------------------------------------------*/\n\ntype ValidTourName = keyof Tours;\n\ntype Action =\n | {\n type: 'next_step';\n payload: ValidTourName;\n }\n | {\n type: 'skip_tour';\n payload: ValidTourName;\n };\n\ntype Tour = Record<ValidTourName, { currentStep: number; length: number; isCompleted: boolean }>;\ntype State = {\n tours: Tour;\n};\n\nconst [GuidedTourProviderImpl, unstableUseGuidedTour] = createContext<{\n state: State;\n dispatch: React.Dispatch<Action>;\n}>('UnstableGuidedTour');\n\nfunction reducer(state: State, action: Action): State {\n return produce(state, (draft) => {\n if (action.type === 'next_step') {\n const nextStep = draft.tours[action.payload].currentStep + 1;\n draft.tours[action.payload].currentStep = nextStep;\n draft.tours[action.payload].isCompleted = nextStep === draft.tours[action.payload].length;\n // TODO: Update local storage\n }\n\n if (action.type === 'skip_tour') {\n draft.tours[action.payload].isCompleted = true;\n // TODO: Update local storage\n }\n });\n}\n\nconst UnstableGuidedTourContext = ({\n children,\n tours: registeredTours,\n}: {\n children: React.ReactNode;\n // NOTE: Maybe we just import this directly instead of a prop?\n tours: Tours;\n}) => {\n // TODO: Get local storage to init state\n // Derive the tour state from the tours object\n const tours = Object.keys(registeredTours).reduce((acc, tourName) => {\n const tourLength = Object.keys(registeredTours[tourName as ValidTourName]).length;\n\n acc[tourName as ValidTourName] = {\n currentStep: 0,\n length: tourLength,\n isCompleted: false,\n };\n\n return acc;\n }, {} as Tour);\n\n const [state, dispatch] = React.useReducer(reducer, {\n tours,\n });\n\n return (\n <GuidedTourProviderImpl state={state} dispatch={dispatch}>\n {children}\n </GuidedTourProviderImpl>\n );\n};\n\nexport type { Action, State, ValidTourName };\nexport { UnstableGuidedTourContext, unstableUseGuidedTour, reducer };\n"],"names":["GuidedTourProviderImpl","unstableUseGuidedTour","createContext","reducer","state","action","produce","draft","type","nextStep","tours","payload","currentStep","isCompleted","length","UnstableGuidedTourContext","children","registeredTours","Object","keys","reduce","acc","tourName","tourLength","dispatch","React","useReducer","_jsx"],"mappings":";;;;;AA6BA,MAAM,CAACA,sBAAAA,EAAwBC,qBAAsB,CAAA,GAAGC,aAGrD,CAAA,oBAAA;AAEH,SAASC,OAAAA,CAAQC,KAAY,EAAEC,MAAc,EAAA;IAC3C,OAAOC,OAAAA,CAAQF,OAAO,CAACG,KAAAA,GAAAA;QACrB,IAAIF,MAAAA,CAAOG,IAAI,KAAK,WAAa,EAAA;YAC/B,MAAMC,QAAAA,GAAWF,MAAMG,KAAK,CAACL,OAAOM,OAAO,CAAC,CAACC,WAAW,GAAG,CAAA;AAC3DL,YAAAA,KAAAA,CAAMG,KAAK,CAACL,MAAAA,CAAOM,OAAO,CAAC,CAACC,WAAW,GAAGH,QAAAA;AAC1CF,YAAAA,KAAAA,CAAMG,KAAK,CAACL,MAAAA,CAAOM,OAAO,CAAC,CAACE,WAAW,GAAGJ,QAAaF,KAAAA,KAAAA,CAAMG,KAAK,CAACL,MAAAA,CAAOM,OAAO,CAAC,CAACG,MAAM;;AAE3F;QAEA,IAAIT,MAAAA,CAAOG,IAAI,KAAK,WAAa,EAAA;AAC/BD,YAAAA,KAAAA,CAAMG,KAAK,CAACL,MAAAA,CAAOM,OAAO,CAAC,CAACE,WAAW,GAAG,IAAA;;AAE5C;AACF,KAAA,CAAA;AACF;AAEA,MAAME,4BAA4B,CAAC,EACjCC,QAAQ,EACRN,KAAAA,EAAOO,eAAe,EAKvB,GAAA;;;IAGC,MAAMP,KAAAA,GAAQQ,OAAOC,IAAI,CAACF,iBAAiBG,MAAM,CAAC,CAACC,GAAKC,EAAAA,QAAAA,GAAAA;QACtD,MAAMC,UAAAA,GAAaL,OAAOC,IAAI,CAACF,eAAe,CAACK,QAAAA,CAA0B,EAAER,MAAM;QAEjFO,GAAG,CAACC,SAA0B,GAAG;YAC/BV,WAAa,EAAA,CAAA;YACbE,MAAQS,EAAAA,UAAAA;YACRV,WAAa,EAAA;AACf,SAAA;QAEA,OAAOQ,GAAAA;AACT,KAAA,EAAG,EAAC,CAAA;AAEJ,IAAA,MAAM,CAACjB,KAAOoB,EAAAA,QAAAA,CAAS,GAAGC,KAAMC,CAAAA,UAAU,CAACvB,OAAS,EAAA;AAClDO,QAAAA;AACF,KAAA,CAAA;AAEA,IAAA,qBACEiB,GAAC3B,CAAAA,sBAAAA,EAAAA;QAAuBI,KAAOA,EAAAA,KAAAA;QAAOoB,QAAUA,EAAAA,QAAAA;AAC7CR,QAAAA,QAAAA,EAAAA;;AAGP;;;;"}
|
|
@@ -4,6 +4,7 @@ var jsxRuntime = require('react/jsx-runtime');
|
|
|
4
4
|
var React = require('react');
|
|
5
5
|
var designSystem = require('@strapi/design-system');
|
|
6
6
|
var styled = require('styled-components');
|
|
7
|
+
var admin = require('../../services/admin.js');
|
|
7
8
|
var Context = require('./Context.js');
|
|
8
9
|
var Step = require('./Step.js');
|
|
9
10
|
|
|
@@ -29,7 +30,7 @@ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
|
29
30
|
/* -------------------------------------------------------------------------------------------------
|
|
30
31
|
* Tours
|
|
31
32
|
* -----------------------------------------------------------------------------------------------*/ const tours = {
|
|
32
|
-
|
|
33
|
+
TEST: createTour('TEST', [
|
|
33
34
|
{
|
|
34
35
|
name: 'Introduction',
|
|
35
36
|
content: (Step)=>/*#__PURE__*/ jsxRuntime.jsxs(Step.Root, {
|
|
@@ -48,6 +49,26 @@ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
|
48
49
|
})
|
|
49
50
|
]
|
|
50
51
|
})
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: 'Done',
|
|
55
|
+
requiredActions: [
|
|
56
|
+
'didCreateApiToken'
|
|
57
|
+
],
|
|
58
|
+
content: (Step)=>/*#__PURE__*/ jsxRuntime.jsxs(Step.Root, {
|
|
59
|
+
align: "start",
|
|
60
|
+
children: [
|
|
61
|
+
/*#__PURE__*/ jsxRuntime.jsx(Step.Title, {
|
|
62
|
+
id: "tours.contentManager.CreateEntry.title",
|
|
63
|
+
defaultMessage: "Create entry"
|
|
64
|
+
}),
|
|
65
|
+
/*#__PURE__*/ jsxRuntime.jsx(Step.Content, {
|
|
66
|
+
id: "tours.contentManager.CreateEntry.content",
|
|
67
|
+
defaultMessage: "Click this button to create an entry"
|
|
68
|
+
}),
|
|
69
|
+
/*#__PURE__*/ jsxRuntime.jsx(Step.Actions, {})
|
|
70
|
+
]
|
|
71
|
+
})
|
|
51
72
|
}
|
|
52
73
|
])
|
|
53
74
|
};
|
|
@@ -56,16 +77,21 @@ const GuidedTourOverlay = styled.styled(designSystem.Box)`
|
|
|
56
77
|
inset: 0;
|
|
57
78
|
background-color: rgba(50, 50, 77, 0.2);
|
|
58
79
|
z-index: 10;
|
|
59
|
-
pointer-events: none;
|
|
60
80
|
`;
|
|
61
|
-
const UnstableGuidedTourTooltip = ({ children, content, tourName, step })=>{
|
|
81
|
+
const UnstableGuidedTourTooltip = ({ children, content, tourName, step, requiredActions })=>{
|
|
82
|
+
const { data: guidedTourMeta } = admin.useGetGuidedTourMetaQuery();
|
|
62
83
|
const state = Context.unstableUseGuidedTour('UnstableGuidedTourTooltip', (s)=>s.state);
|
|
63
84
|
const dispatch = Context.unstableUseGuidedTour('UnstableGuidedTourTooltip', (s)=>s.dispatch);
|
|
64
85
|
const Step$1 = React__namespace.useMemo(()=>Step.createStepComponents(tourName), [
|
|
65
86
|
tourName
|
|
66
87
|
]);
|
|
67
88
|
const isCurrentStep = state.tours[tourName].currentStep === step;
|
|
68
|
-
const
|
|
89
|
+
const hasCompletedRequiredActions = requiredActions?.every((action)=>{
|
|
90
|
+
return guidedTourMeta?.data?.completedActions.includes(action);
|
|
91
|
+
}) ?? true;
|
|
92
|
+
const hasFutureFlag = window.strapi.future.isEnabled('unstableGuidedTour');
|
|
93
|
+
const isEnabled = guidedTourMeta?.data?.isFirstSuperAdminUser && !state.tours[tourName].isCompleted && hasFutureFlag;
|
|
94
|
+
const isPopoverOpen = isEnabled && isCurrentStep && hasCompletedRequiredActions;
|
|
69
95
|
// Lock the scroll
|
|
70
96
|
React__namespace.useEffect(()=>{
|
|
71
97
|
if (!isPopoverOpen) return;
|
|
@@ -104,6 +130,7 @@ function createTour(tourName, steps) {
|
|
|
104
130
|
tourName: tourName,
|
|
105
131
|
step: index,
|
|
106
132
|
content: step.content,
|
|
133
|
+
requiredActions: step.requiredActions,
|
|
107
134
|
children: children
|
|
108
135
|
});
|
|
109
136
|
return acc;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tours.js","sources":["../../../../../../admin/src/components/UnstableGuidedTour/Tours.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box, Popover } from '@strapi/design-system';\nimport { styled } from 'styled-components';\n\nimport {
|
|
1
|
+
{"version":3,"file":"Tours.js","sources":["../../../../../../admin/src/components/UnstableGuidedTour/Tours.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box, Popover } from '@strapi/design-system';\nimport { styled } from 'styled-components';\n\nimport { type GetGuidedTourMeta } from '../../../../shared/contracts/admin';\nimport { useGetGuidedTourMetaQuery } from '../../services/admin';\n\nimport { type State, type Action, unstableUseGuidedTour, ValidTourName } from './Context';\nimport { Step, createStepComponents } from './Step';\n\n/* -------------------------------------------------------------------------------------------------\n * Tours\n * -----------------------------------------------------------------------------------------------*/\n\nconst tours = {\n TEST: createTour('TEST', [\n {\n name: 'Introduction',\n content: (Step) => (\n <Step.Root sideOffset={-36}>\n <Step.Title\n id=\"tours.contentManager.Introduction.title\"\n defaultMessage=\"Content manager\"\n />\n <Step.Content\n id=\"tours.contentManager.Introduction.content\"\n defaultMessage=\"Create and manage content from your collection types and single types.\"\n />\n <Step.Actions showSkip />\n </Step.Root>\n ),\n },\n {\n name: 'Done',\n requiredActions: ['didCreateApiToken'],\n content: (Step) => (\n <Step.Root align=\"start\">\n <Step.Title id=\"tours.contentManager.CreateEntry.title\" defaultMessage=\"Create entry\" />\n <Step.Content\n id=\"tours.contentManager.CreateEntry.content\"\n defaultMessage=\"Click this button to create an entry\"\n />\n <Step.Actions />\n </Step.Root>\n ),\n },\n ]),\n} as const;\n\ntype Tours = typeof tours;\n\n/* -------------------------------------------------------------------------------------------------\n * GuidedTourTooltip\n * -----------------------------------------------------------------------------------------------*/\n\ntype Content = (\n Step: Step,\n {\n state,\n dispatch,\n }: {\n state: State;\n dispatch: React.Dispatch<Action>;\n }\n) => React.ReactNode;\n\nexport const GuidedTourOverlay = styled(Box)`\n position: fixed;\n inset: 0;\n background-color: rgba(50, 50, 77, 0.2);\n z-index: 10;\n`;\n\nconst UnstableGuidedTourTooltip = ({\n children,\n content,\n tourName,\n step,\n requiredActions,\n}: {\n children: React.ReactNode;\n content: Content;\n tourName: ValidTourName;\n step: number;\n requiredActions?: GetGuidedTourMeta.Response['data']['completedActions'];\n}) => {\n const { data: guidedTourMeta } = useGetGuidedTourMetaQuery();\n\n const state = unstableUseGuidedTour('UnstableGuidedTourTooltip', (s) => s.state);\n const dispatch = unstableUseGuidedTour('UnstableGuidedTourTooltip', (s) => s.dispatch);\n\n const Step = React.useMemo(() => createStepComponents(tourName), [tourName]);\n\n const isCurrentStep = state.tours[tourName].currentStep === step;\n const hasCompletedRequiredActions =\n requiredActions?.every((action) => {\n return guidedTourMeta?.data?.completedActions.includes(action);\n }) ?? true;\n const hasFutureFlag = window.strapi.future.isEnabled('unstableGuidedTour');\n const isEnabled =\n guidedTourMeta?.data?.isFirstSuperAdminUser &&\n !state.tours[tourName].isCompleted &&\n hasFutureFlag;\n\n const isPopoverOpen = isEnabled && isCurrentStep && hasCompletedRequiredActions;\n\n // Lock the scroll\n React.useEffect(() => {\n if (!isPopoverOpen) return;\n\n const originalStyle = window.getComputedStyle(document.body).overflow;\n document.body.style.overflow = 'hidden';\n\n return () => {\n document.body.style.overflow = originalStyle;\n };\n }, [isPopoverOpen]);\n\n return (\n <>\n {isPopoverOpen && <GuidedTourOverlay />}\n <Popover.Root open={isPopoverOpen}>\n <Popover.Anchor>{children}</Popover.Anchor>\n {content(Step, { state, dispatch })}\n </Popover.Root>\n </>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Tour factory\n * -----------------------------------------------------------------------------------------------*/\n\ntype TourStep<P extends string> = {\n name: P;\n content: Content;\n requiredActions?: GetGuidedTourMeta.Response['data']['completedActions'];\n};\n\nfunction createTour<const T extends ReadonlyArray<TourStep<string>>>(tourName: string, steps: T) {\n type Components = {\n [K in T[number]['name']]: React.ComponentType<{ children: React.ReactNode }>;\n };\n\n const tour = steps.reduce((acc, step, index) => {\n if (step.name in acc) {\n throw Error(`The tour: ${tourName} with step: ${step.name} has already been registered`);\n }\n\n acc[step.name as keyof Components] = ({ children }: { children: React.ReactNode }) => (\n <UnstableGuidedTourTooltip\n tourName={tourName as ValidTourName}\n step={index}\n content={step.content}\n requiredActions={step.requiredActions}\n >\n {children}\n </UnstableGuidedTourTooltip>\n );\n\n return acc;\n }, {} as Components);\n\n return tour;\n}\n\nexport type { Content, Tours };\nexport { tours };\n"],"names":["tours","TEST","createTour","name","content","Step","_jsxs","Root","sideOffset","_jsx","Title","id","defaultMessage","Content","Actions","showSkip","requiredActions","align","GuidedTourOverlay","styled","Box","UnstableGuidedTourTooltip","children","tourName","step","data","guidedTourMeta","useGetGuidedTourMetaQuery","state","unstableUseGuidedTour","s","dispatch","React","useMemo","createStepComponents","isCurrentStep","currentStep","hasCompletedRequiredActions","every","action","completedActions","includes","hasFutureFlag","window","strapi","future","isEnabled","isFirstSuperAdminUser","isCompleted","isPopoverOpen","useEffect","originalStyle","getComputedStyle","document","body","overflow","style","_Fragment","Popover","open","Anchor","steps","tour","reduce","acc","index","Error"],"mappings":"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"}
|
|
@@ -2,13 +2,14 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { Box, Popover } from '@strapi/design-system';
|
|
4
4
|
import { styled } from 'styled-components';
|
|
5
|
+
import { useGetGuidedTourMetaQuery } from '../../services/admin.mjs';
|
|
5
6
|
import { unstableUseGuidedTour } from './Context.mjs';
|
|
6
7
|
import { createStepComponents } from './Step.mjs';
|
|
7
8
|
|
|
8
9
|
/* -------------------------------------------------------------------------------------------------
|
|
9
10
|
* Tours
|
|
10
11
|
* -----------------------------------------------------------------------------------------------*/ const tours = {
|
|
11
|
-
|
|
12
|
+
TEST: createTour('TEST', [
|
|
12
13
|
{
|
|
13
14
|
name: 'Introduction',
|
|
14
15
|
content: (Step)=>/*#__PURE__*/ jsxs(Step.Root, {
|
|
@@ -27,6 +28,26 @@ import { createStepComponents } from './Step.mjs';
|
|
|
27
28
|
})
|
|
28
29
|
]
|
|
29
30
|
})
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'Done',
|
|
34
|
+
requiredActions: [
|
|
35
|
+
'didCreateApiToken'
|
|
36
|
+
],
|
|
37
|
+
content: (Step)=>/*#__PURE__*/ jsxs(Step.Root, {
|
|
38
|
+
align: "start",
|
|
39
|
+
children: [
|
|
40
|
+
/*#__PURE__*/ jsx(Step.Title, {
|
|
41
|
+
id: "tours.contentManager.CreateEntry.title",
|
|
42
|
+
defaultMessage: "Create entry"
|
|
43
|
+
}),
|
|
44
|
+
/*#__PURE__*/ jsx(Step.Content, {
|
|
45
|
+
id: "tours.contentManager.CreateEntry.content",
|
|
46
|
+
defaultMessage: "Click this button to create an entry"
|
|
47
|
+
}),
|
|
48
|
+
/*#__PURE__*/ jsx(Step.Actions, {})
|
|
49
|
+
]
|
|
50
|
+
})
|
|
30
51
|
}
|
|
31
52
|
])
|
|
32
53
|
};
|
|
@@ -35,16 +56,21 @@ const GuidedTourOverlay = styled(Box)`
|
|
|
35
56
|
inset: 0;
|
|
36
57
|
background-color: rgba(50, 50, 77, 0.2);
|
|
37
58
|
z-index: 10;
|
|
38
|
-
pointer-events: none;
|
|
39
59
|
`;
|
|
40
|
-
const UnstableGuidedTourTooltip = ({ children, content, tourName, step })=>{
|
|
60
|
+
const UnstableGuidedTourTooltip = ({ children, content, tourName, step, requiredActions })=>{
|
|
61
|
+
const { data: guidedTourMeta } = useGetGuidedTourMetaQuery();
|
|
41
62
|
const state = unstableUseGuidedTour('UnstableGuidedTourTooltip', (s)=>s.state);
|
|
42
63
|
const dispatch = unstableUseGuidedTour('UnstableGuidedTourTooltip', (s)=>s.dispatch);
|
|
43
64
|
const Step = React.useMemo(()=>createStepComponents(tourName), [
|
|
44
65
|
tourName
|
|
45
66
|
]);
|
|
46
67
|
const isCurrentStep = state.tours[tourName].currentStep === step;
|
|
47
|
-
const
|
|
68
|
+
const hasCompletedRequiredActions = requiredActions?.every((action)=>{
|
|
69
|
+
return guidedTourMeta?.data?.completedActions.includes(action);
|
|
70
|
+
}) ?? true;
|
|
71
|
+
const hasFutureFlag = window.strapi.future.isEnabled('unstableGuidedTour');
|
|
72
|
+
const isEnabled = guidedTourMeta?.data?.isFirstSuperAdminUser && !state.tours[tourName].isCompleted && hasFutureFlag;
|
|
73
|
+
const isPopoverOpen = isEnabled && isCurrentStep && hasCompletedRequiredActions;
|
|
48
74
|
// Lock the scroll
|
|
49
75
|
React.useEffect(()=>{
|
|
50
76
|
if (!isPopoverOpen) return;
|
|
@@ -83,6 +109,7 @@ function createTour(tourName, steps) {
|
|
|
83
109
|
tourName: tourName,
|
|
84
110
|
step: index,
|
|
85
111
|
content: step.content,
|
|
112
|
+
requiredActions: step.requiredActions,
|
|
86
113
|
children: children
|
|
87
114
|
});
|
|
88
115
|
return acc;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tours.mjs","sources":["../../../../../../admin/src/components/UnstableGuidedTour/Tours.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box, Popover } from '@strapi/design-system';\nimport { styled } from 'styled-components';\n\nimport {
|
|
1
|
+
{"version":3,"file":"Tours.mjs","sources":["../../../../../../admin/src/components/UnstableGuidedTour/Tours.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box, Popover } from '@strapi/design-system';\nimport { styled } from 'styled-components';\n\nimport { type GetGuidedTourMeta } from '../../../../shared/contracts/admin';\nimport { useGetGuidedTourMetaQuery } from '../../services/admin';\n\nimport { type State, type Action, unstableUseGuidedTour, ValidTourName } from './Context';\nimport { Step, createStepComponents } from './Step';\n\n/* -------------------------------------------------------------------------------------------------\n * Tours\n * -----------------------------------------------------------------------------------------------*/\n\nconst tours = {\n TEST: createTour('TEST', [\n {\n name: 'Introduction',\n content: (Step) => (\n <Step.Root sideOffset={-36}>\n <Step.Title\n id=\"tours.contentManager.Introduction.title\"\n defaultMessage=\"Content manager\"\n />\n <Step.Content\n id=\"tours.contentManager.Introduction.content\"\n defaultMessage=\"Create and manage content from your collection types and single types.\"\n />\n <Step.Actions showSkip />\n </Step.Root>\n ),\n },\n {\n name: 'Done',\n requiredActions: ['didCreateApiToken'],\n content: (Step) => (\n <Step.Root align=\"start\">\n <Step.Title id=\"tours.contentManager.CreateEntry.title\" defaultMessage=\"Create entry\" />\n <Step.Content\n id=\"tours.contentManager.CreateEntry.content\"\n defaultMessage=\"Click this button to create an entry\"\n />\n <Step.Actions />\n </Step.Root>\n ),\n },\n ]),\n} as const;\n\ntype Tours = typeof tours;\n\n/* -------------------------------------------------------------------------------------------------\n * GuidedTourTooltip\n * -----------------------------------------------------------------------------------------------*/\n\ntype Content = (\n Step: Step,\n {\n state,\n dispatch,\n }: {\n state: State;\n dispatch: React.Dispatch<Action>;\n }\n) => React.ReactNode;\n\nexport const GuidedTourOverlay = styled(Box)`\n position: fixed;\n inset: 0;\n background-color: rgba(50, 50, 77, 0.2);\n z-index: 10;\n`;\n\nconst UnstableGuidedTourTooltip = ({\n children,\n content,\n tourName,\n step,\n requiredActions,\n}: {\n children: React.ReactNode;\n content: Content;\n tourName: ValidTourName;\n step: number;\n requiredActions?: GetGuidedTourMeta.Response['data']['completedActions'];\n}) => {\n const { data: guidedTourMeta } = useGetGuidedTourMetaQuery();\n\n const state = unstableUseGuidedTour('UnstableGuidedTourTooltip', (s) => s.state);\n const dispatch = unstableUseGuidedTour('UnstableGuidedTourTooltip', (s) => s.dispatch);\n\n const Step = React.useMemo(() => createStepComponents(tourName), [tourName]);\n\n const isCurrentStep = state.tours[tourName].currentStep === step;\n const hasCompletedRequiredActions =\n requiredActions?.every((action) => {\n return guidedTourMeta?.data?.completedActions.includes(action);\n }) ?? true;\n const hasFutureFlag = window.strapi.future.isEnabled('unstableGuidedTour');\n const isEnabled =\n guidedTourMeta?.data?.isFirstSuperAdminUser &&\n !state.tours[tourName].isCompleted &&\n hasFutureFlag;\n\n const isPopoverOpen = isEnabled && isCurrentStep && hasCompletedRequiredActions;\n\n // Lock the scroll\n React.useEffect(() => {\n if (!isPopoverOpen) return;\n\n const originalStyle = window.getComputedStyle(document.body).overflow;\n document.body.style.overflow = 'hidden';\n\n return () => {\n document.body.style.overflow = originalStyle;\n };\n }, [isPopoverOpen]);\n\n return (\n <>\n {isPopoverOpen && <GuidedTourOverlay />}\n <Popover.Root open={isPopoverOpen}>\n <Popover.Anchor>{children}</Popover.Anchor>\n {content(Step, { state, dispatch })}\n </Popover.Root>\n </>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Tour factory\n * -----------------------------------------------------------------------------------------------*/\n\ntype TourStep<P extends string> = {\n name: P;\n content: Content;\n requiredActions?: GetGuidedTourMeta.Response['data']['completedActions'];\n};\n\nfunction createTour<const T extends ReadonlyArray<TourStep<string>>>(tourName: string, steps: T) {\n type Components = {\n [K in T[number]['name']]: React.ComponentType<{ children: React.ReactNode }>;\n };\n\n const tour = steps.reduce((acc, step, index) => {\n if (step.name in acc) {\n throw Error(`The tour: ${tourName} with step: ${step.name} has already been registered`);\n }\n\n acc[step.name as keyof Components] = ({ children }: { children: React.ReactNode }) => (\n <UnstableGuidedTourTooltip\n tourName={tourName as ValidTourName}\n step={index}\n content={step.content}\n requiredActions={step.requiredActions}\n >\n {children}\n </UnstableGuidedTourTooltip>\n );\n\n return acc;\n }, {} as Components);\n\n return tour;\n}\n\nexport type { Content, Tours };\nexport { tours };\n"],"names":["tours","TEST","createTour","name","content","Step","_jsxs","Root","sideOffset","_jsx","Title","id","defaultMessage","Content","Actions","showSkip","requiredActions","align","GuidedTourOverlay","styled","Box","UnstableGuidedTourTooltip","children","tourName","step","data","guidedTourMeta","useGetGuidedTourMetaQuery","state","unstableUseGuidedTour","s","dispatch","React","useMemo","createStepComponents","isCurrentStep","currentStep","hasCompletedRequiredActions","every","action","completedActions","includes","hasFutureFlag","window","strapi","future","isEnabled","isFirstSuperAdminUser","isCompleted","isPopoverOpen","useEffect","originalStyle","getComputedStyle","document","body","overflow","style","_Fragment","Popover","open","Anchor","steps","tour","reduce","acc","index","Error"],"mappings":"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"}
|
|
@@ -6,7 +6,6 @@ var axios = require('axios');
|
|
|
6
6
|
var admin = require('../services/admin.js');
|
|
7
7
|
var AppInfo = require('./AppInfo.js');
|
|
8
8
|
var Auth = require('./Auth.js');
|
|
9
|
-
var StrapiApp = require('./StrapiApp.js');
|
|
10
9
|
|
|
11
10
|
function _interopNamespaceDefault(e) {
|
|
12
11
|
var n = Object.create(null);
|
|
@@ -34,43 +33,11 @@ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
|
34
33
|
});
|
|
35
34
|
const TrackingProvider = ({ children })=>{
|
|
36
35
|
const token = Auth.useAuth('App', (state)=>state.token);
|
|
37
|
-
const getAllWidgets = StrapiApp.useStrapiApp('TrackingProvider', (state)=>state.widgets.getAll);
|
|
38
36
|
const { data: initData } = admin.useInitQuery();
|
|
39
37
|
const { uuid } = initData ?? {};
|
|
40
38
|
const { data } = admin.useTelemetryPropertiesQuery(undefined, {
|
|
41
39
|
skip: !initData?.uuid || !token
|
|
42
40
|
});
|
|
43
|
-
React__namespace.useEffect(()=>{
|
|
44
|
-
if (uuid && data) {
|
|
45
|
-
const event = 'didInitializeAdministration';
|
|
46
|
-
try {
|
|
47
|
-
fetch('https://analytics.strapi.io/api/v2/track', {
|
|
48
|
-
method: 'POST',
|
|
49
|
-
body: JSON.stringify({
|
|
50
|
-
// This event is anonymous
|
|
51
|
-
event,
|
|
52
|
-
userId: '',
|
|
53
|
-
eventPropeties: {},
|
|
54
|
-
groupProperties: {
|
|
55
|
-
...data,
|
|
56
|
-
projectId: uuid,
|
|
57
|
-
registeredWidgets: getAllWidgets().map((widget)=>widget.uid)
|
|
58
|
-
}
|
|
59
|
-
}),
|
|
60
|
-
headers: {
|
|
61
|
-
'Content-Type': 'application/json',
|
|
62
|
-
'X-Strapi-Event': event
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
} catch {
|
|
66
|
-
// silence is golden
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}, [
|
|
70
|
-
data,
|
|
71
|
-
uuid,
|
|
72
|
-
getAllWidgets
|
|
73
|
-
]);
|
|
74
41
|
const value = React__namespace.useMemo(()=>({
|
|
75
42
|
uuid,
|
|
76
43
|
telemetryProperties: data
|
|
@@ -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 { 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 getAllWidgets = useStrapiApp('TrackingProvider', (state) => state.widgets.getAll);\n const { data: initData } = useInitQuery();\n const { uuid } = initData ?? {};\n\n const { data } = useTelemetryPropertiesQuery(undefined, {\n skip: !initData?.uuid || !token,\n });\n\n React.useEffect(() => {\n if (uuid && data) {\n const event = 'didInitializeAdministration';\n try {\n fetch('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\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 */\ninterface EventWithoutProperties {\n name:\n | 'changeComponentsOrder'\n | 'didAccessAuthenticatedAdministration'\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 properties?: never;\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\ntype EventsWithProperties =\n | CreateEntryEvents\n | PublishEntryEvents\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\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 '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","getAllWidgets","useStrapiApp","widgets","getAll","data","initData","useInitQuery","useTelemetryPropertiesQuery","undefined","skip","useEffect","event","fetch","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 { useInitQuery, useTelemetryPropertiesQuery } from '../services/admin';\n\nimport { useAppInfo } from './AppInfo';\nimport { useAuth } from './Auth';\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\n const { data } = useTelemetryPropertiesQuery(undefined, {\n skip: !initData?.uuid || !token,\n });\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 */\ninterface 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 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\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\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 '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","useTelemetryPropertiesQuery","undefined","skip","value","useMemo","telemetryProperties","_jsx","Provider","useTracking","useContext","userId","useAppInfo","trackUsage","useCallback","event","properties","window","strapi","telemetryDisabled","res","axios","post","eventProperties","userProperties","groupProperties","projectId","projectType","headers","err"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuBA;;AAEkG,qGAElG,MAAMA,eAAAA,iBAAkBC,gBAAMC,CAAAA,aAAa,CAAuB;IAChEC,IAAM,EAAA;AACR,CAAA,CAAA;AAUA,MAAMC,gBAAmB,GAAA,CAAC,EAAEC,QAAQ,EAAyB,GAAA;AAC3D,IAAA,MAAMC,QAAQC,YAAQ,CAAA,KAAA,EAAO,CAACC,KAAAA,GAAUA,MAAMF,KAAK,CAAA;AACnD,IAAA,MAAM,EAAEG,IAAAA,EAAMC,QAAQ,EAAE,GAAGC,kBAAAA,EAAAA;AAC3B,IAAA,MAAM,EAAER,IAAI,EAAE,GAAGO,YAAY,EAAC;AAE9B,IAAA,MAAM,EAAED,IAAI,EAAE,GAAGG,kCAA4BC,SAAW,EAAA;QACtDC,IAAM,EAAA,CAACJ,QAAUP,EAAAA,IAAAA,IAAQ,CAACG;AAC5B,KAAA,CAAA;AACA,IAAA,MAAMS,KAAQd,GAAAA,gBAAAA,CAAMe,OAAO,CACzB,KAAO;AACLb,YAAAA,IAAAA;YACAc,mBAAqBR,EAAAA;AACvB,SAAA,CACA,EAAA;AAACN,QAAAA,IAAAA;AAAMM,QAAAA;AAAK,KAAA,CAAA;IAGd,qBAAOS,cAAA,CAAClB,gBAAgBmB,QAAQ,EAAA;QAACJ,KAAOA,EAAAA,KAAAA;AAAQV,QAAAA,QAAAA,EAAAA;;AAClD;AA4VA;;;;;;;;;;;;;;;;;AAiBC,UACKe,WAAc,GAAA,IAAA;IAClB,MAAM,EAAEjB,IAAI,EAAEc,mBAAmB,EAAE,GAAGhB,gBAAAA,CAAMoB,UAAU,CAACrB,eAAAA,CAAAA;AACvD,IAAA,MAAMsB,SAASC,kBAAW,CAAA,aAAA,EAAe,CAACf,KAAAA,GAAUA,MAAMc,MAAM,CAAA;AAChE,IAAA,MAAME,UAAavB,GAAAA,gBAAAA,CAAMwB,WAAW,CAClC,OACEC,KACAC,EAAAA,UAAAA,GAAAA;QAEA,IAAI;AACF,YAAA,IAAIxB,QAAQ,CAACyB,MAAAA,CAAOC,MAAM,CAACC,iBAAiB,EAAE;AAC5C,gBAAA,MAAMC,GAAM,GAAA,MAAMC,KAAMC,CAAAA,IAAI,CAC1B,0CACA,EAAA;AACEP,oBAAAA,KAAAA;AACAJ,oBAAAA,MAAAA;oBACAY,eAAiB,EAAA;AAAE,wBAAA,GAAGP;AAAW,qBAAA;AACjCQ,oBAAAA,cAAAA,EAAgB,EAAC;oBACjBC,eAAiB,EAAA;AACf,wBAAA,GAAGnB,mBAAmB;wBACtBoB,SAAWlC,EAAAA,IAAAA;wBACXmC,WAAaV,EAAAA,MAAAA,CAAOC,MAAM,CAACS;AAC7B;iBAEF,EAAA;oBACEC,OAAS,EAAA;wBACP,cAAgB,EAAA,kBAAA;wBAChB,gBAAkBb,EAAAA;AACpB;AACF,iBAAA,CAAA;gBAGF,OAAOK,GAAAA;AACT;AACF,SAAA,CAAE,OAAOS,GAAK,EAAA;;AAEd;QAEA,OAAO,IAAA;KAET,EAAA;AAACvB,QAAAA,mBAAAA;AAAqBK,QAAAA,MAAAA;AAAQnB,QAAAA;AAAK,KAAA,CAAA;IAGrC,OAAO;AAAEqB,QAAAA;AAAW,KAAA;AACtB;;;;;"}
|
|
@@ -4,7 +4,6 @@ import axios from 'axios';
|
|
|
4
4
|
import { useInitQuery, useTelemetryPropertiesQuery } from '../services/admin.mjs';
|
|
5
5
|
import { useAppInfo } from './AppInfo.mjs';
|
|
6
6
|
import { useAuth } from './Auth.mjs';
|
|
7
|
-
import { useStrapiApp } from './StrapiApp.mjs';
|
|
8
7
|
|
|
9
8
|
/* -------------------------------------------------------------------------------------------------
|
|
10
9
|
* Context
|
|
@@ -13,43 +12,11 @@ import { useStrapiApp } from './StrapiApp.mjs';
|
|
|
13
12
|
});
|
|
14
13
|
const TrackingProvider = ({ children })=>{
|
|
15
14
|
const token = useAuth('App', (state)=>state.token);
|
|
16
|
-
const getAllWidgets = useStrapiApp('TrackingProvider', (state)=>state.widgets.getAll);
|
|
17
15
|
const { data: initData } = useInitQuery();
|
|
18
16
|
const { uuid } = initData ?? {};
|
|
19
17
|
const { data } = useTelemetryPropertiesQuery(undefined, {
|
|
20
18
|
skip: !initData?.uuid || !token
|
|
21
19
|
});
|
|
22
|
-
React.useEffect(()=>{
|
|
23
|
-
if (uuid && data) {
|
|
24
|
-
const event = 'didInitializeAdministration';
|
|
25
|
-
try {
|
|
26
|
-
fetch('https://analytics.strapi.io/api/v2/track', {
|
|
27
|
-
method: 'POST',
|
|
28
|
-
body: JSON.stringify({
|
|
29
|
-
// This event is anonymous
|
|
30
|
-
event,
|
|
31
|
-
userId: '',
|
|
32
|
-
eventPropeties: {},
|
|
33
|
-
groupProperties: {
|
|
34
|
-
...data,
|
|
35
|
-
projectId: uuid,
|
|
36
|
-
registeredWidgets: getAllWidgets().map((widget)=>widget.uid)
|
|
37
|
-
}
|
|
38
|
-
}),
|
|
39
|
-
headers: {
|
|
40
|
-
'Content-Type': 'application/json',
|
|
41
|
-
'X-Strapi-Event': event
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
} catch {
|
|
45
|
-
// silence is golden
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}, [
|
|
49
|
-
data,
|
|
50
|
-
uuid,
|
|
51
|
-
getAllWidgets
|
|
52
|
-
]);
|
|
53
20
|
const value = React.useMemo(()=>({
|
|
54
21
|
uuid,
|
|
55
22
|
telemetryProperties: data
|
|
@@ -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 { 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 getAllWidgets = useStrapiApp('TrackingProvider', (state) => state.widgets.getAll);\n const { data: initData } = useInitQuery();\n const { uuid } = initData ?? {};\n\n const { data } = useTelemetryPropertiesQuery(undefined, {\n skip: !initData?.uuid || !token,\n });\n\n React.useEffect(() => {\n if (uuid && data) {\n const event = 'didInitializeAdministration';\n try {\n fetch('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\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 */\ninterface EventWithoutProperties {\n name:\n | 'changeComponentsOrder'\n | 'didAccessAuthenticatedAdministration'\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 properties?: never;\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\ntype EventsWithProperties =\n | CreateEntryEvents\n | PublishEntryEvents\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\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 '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","getAllWidgets","useStrapiApp","widgets","getAll","data","initData","useInitQuery","useTelemetryPropertiesQuery","undefined","skip","useEffect","event","fetch","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 { useInitQuery, useTelemetryPropertiesQuery } from '../services/admin';\n\nimport { useAppInfo } from './AppInfo';\nimport { useAuth } from './Auth';\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\n const { data } = useTelemetryPropertiesQuery(undefined, {\n skip: !initData?.uuid || !token,\n });\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 */\ninterface 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 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\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\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 '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","useTelemetryPropertiesQuery","undefined","skip","value","useMemo","telemetryProperties","_jsx","Provider","useTracking","useContext","userId","useAppInfo","trackUsage","useCallback","event","properties","window","strapi","telemetryDisabled","res","axios","post","eventProperties","userProperties","groupProperties","projectId","projectType","headers","err"],"mappings":";;;;;;;AAuBA;;AAEkG,qGAElG,MAAMA,eAAAA,iBAAkBC,KAAMC,CAAAA,aAAa,CAAuB;IAChEC,IAAM,EAAA;AACR,CAAA,CAAA;AAUA,MAAMC,gBAAmB,GAAA,CAAC,EAAEC,QAAQ,EAAyB,GAAA;AAC3D,IAAA,MAAMC,QAAQC,OAAQ,CAAA,KAAA,EAAO,CAACC,KAAAA,GAAUA,MAAMF,KAAK,CAAA;AACnD,IAAA,MAAM,EAAEG,IAAAA,EAAMC,QAAQ,EAAE,GAAGC,YAAAA,EAAAA;AAC3B,IAAA,MAAM,EAAER,IAAI,EAAE,GAAGO,YAAY,EAAC;AAE9B,IAAA,MAAM,EAAED,IAAI,EAAE,GAAGG,4BAA4BC,SAAW,EAAA;QACtDC,IAAM,EAAA,CAACJ,QAAUP,EAAAA,IAAAA,IAAQ,CAACG;AAC5B,KAAA,CAAA;AACA,IAAA,MAAMS,KAAQd,GAAAA,KAAAA,CAAMe,OAAO,CACzB,KAAO;AACLb,YAAAA,IAAAA;YACAc,mBAAqBR,EAAAA;AACvB,SAAA,CACA,EAAA;AAACN,QAAAA,IAAAA;AAAMM,QAAAA;AAAK,KAAA,CAAA;IAGd,qBAAOS,GAAA,CAAClB,gBAAgBmB,QAAQ,EAAA;QAACJ,KAAOA,EAAAA,KAAAA;AAAQV,QAAAA,QAAAA,EAAAA;;AAClD;AA4VA;;;;;;;;;;;;;;;;;AAiBC,UACKe,WAAc,GAAA,IAAA;IAClB,MAAM,EAAEjB,IAAI,EAAEc,mBAAmB,EAAE,GAAGhB,KAAAA,CAAMoB,UAAU,CAACrB,eAAAA,CAAAA;AACvD,IAAA,MAAMsB,SAASC,UAAW,CAAA,aAAA,EAAe,CAACf,KAAAA,GAAUA,MAAMc,MAAM,CAAA;AAChE,IAAA,MAAME,UAAavB,GAAAA,KAAAA,CAAMwB,WAAW,CAClC,OACEC,KACAC,EAAAA,UAAAA,GAAAA;QAEA,IAAI;AACF,YAAA,IAAIxB,QAAQ,CAACyB,MAAAA,CAAOC,MAAM,CAACC,iBAAiB,EAAE;AAC5C,gBAAA,MAAMC,GAAM,GAAA,MAAMC,KAAMC,CAAAA,IAAI,CAC1B,0CACA,EAAA;AACEP,oBAAAA,KAAAA;AACAJ,oBAAAA,MAAAA;oBACAY,eAAiB,EAAA;AAAE,wBAAA,GAAGP;AAAW,qBAAA;AACjCQ,oBAAAA,cAAAA,EAAgB,EAAC;oBACjBC,eAAiB,EAAA;AACf,wBAAA,GAAGnB,mBAAmB;wBACtBoB,SAAWlC,EAAAA,IAAAA;wBACXmC,WAAaV,EAAAA,MAAAA,CAAOC,MAAM,CAACS;AAC7B;iBAEF,EAAA;oBACEC,OAAS,EAAA;wBACP,cAAgB,EAAA,kBAAA;wBAChB,gBAAkBb,EAAAA;AACpB;AACF,iBAAA,CAAA;gBAGF,OAAOK,GAAAA;AACT;AACF,SAAA,CAAE,OAAOS,GAAK,EAAA;;AAEd;QAEA,OAAO,IAAA;KAET,EAAA;AAACvB,QAAAA,mBAAAA;AAAqBK,QAAAA,MAAAA;AAAQnB,QAAAA;AAAK,KAAA,CAAA;IAGrC,OAAO;AAAEqB,QAAAA;AAAW,KAAA;AACtB;;;;"}
|