@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.
Files changed (100) hide show
  1. package/dist/admin/admin/src/components/UnstableGuidedTour/Context.js +1 -0
  2. package/dist/admin/admin/src/components/UnstableGuidedTour/Context.js.map +1 -1
  3. package/dist/admin/admin/src/components/UnstableGuidedTour/Context.mjs +1 -0
  4. package/dist/admin/admin/src/components/UnstableGuidedTour/Context.mjs.map +1 -1
  5. package/dist/admin/admin/src/components/UnstableGuidedTour/Tours.js +31 -4
  6. package/dist/admin/admin/src/components/UnstableGuidedTour/Tours.js.map +1 -1
  7. package/dist/admin/admin/src/components/UnstableGuidedTour/Tours.mjs +31 -4
  8. package/dist/admin/admin/src/components/UnstableGuidedTour/Tours.mjs.map +1 -1
  9. package/dist/admin/admin/src/features/Tracking.js +0 -33
  10. package/dist/admin/admin/src/features/Tracking.js.map +1 -1
  11. package/dist/admin/admin/src/features/Tracking.mjs +0 -33
  12. package/dist/admin/admin/src/features/Tracking.mjs.map +1 -1
  13. package/dist/admin/admin/src/layouts/AuthenticatedLayout.js +15 -8
  14. package/dist/admin/admin/src/layouts/AuthenticatedLayout.js.map +1 -1
  15. package/dist/admin/admin/src/layouts/AuthenticatedLayout.mjs +15 -8
  16. package/dist/admin/admin/src/layouts/AuthenticatedLayout.mjs.map +1 -1
  17. package/dist/admin/admin/src/pages/Settings/pages/Users/ListPage.js +3 -3
  18. package/dist/admin/admin/src/pages/Settings/pages/Users/ListPage.js.map +1 -1
  19. package/dist/admin/admin/src/pages/Settings/pages/Users/ListPage.mjs +3 -3
  20. package/dist/admin/admin/src/pages/Settings/pages/Users/ListPage.mjs.map +1 -1
  21. package/dist/admin/admin/src/services/admin.js +17 -3
  22. package/dist/admin/admin/src/services/admin.js.map +1 -1
  23. package/dist/admin/admin/src/services/admin.mjs +17 -4
  24. package/dist/admin/admin/src/services/admin.mjs.map +1 -1
  25. package/dist/admin/admin/src/services/apiTokens.js +4 -2
  26. package/dist/admin/admin/src/services/apiTokens.js.map +1 -1
  27. package/dist/admin/admin/src/services/apiTokens.mjs +4 -2
  28. package/dist/admin/admin/src/services/apiTokens.mjs.map +1 -1
  29. package/dist/admin/admin/src/utils/rulesEngine.js +75 -0
  30. package/dist/admin/admin/src/utils/rulesEngine.js.map +1 -0
  31. package/dist/admin/admin/src/utils/rulesEngine.mjs +72 -0
  32. package/dist/admin/admin/src/utils/rulesEngine.mjs.map +1 -0
  33. package/dist/admin/index.js +3 -0
  34. package/dist/admin/index.js.map +1 -1
  35. package/dist/admin/index.mjs +1 -0
  36. package/dist/admin/index.mjs.map +1 -1
  37. package/dist/admin/src/components/UnstableGuidedTour/Context.d.ts +6 -5
  38. package/dist/admin/src/components/UnstableGuidedTour/Tours.d.ts +4 -1
  39. package/dist/admin/src/features/Tracking.d.ts +9 -2
  40. package/dist/admin/src/index.d.ts +1 -0
  41. package/dist/admin/src/services/admin.d.ts +8 -8
  42. package/dist/admin/src/services/apiTokens.d.ts +1 -1
  43. package/dist/admin/src/utils/rulesEngine.d.ts +23 -0
  44. package/dist/ee/server/src/index.d.ts +2 -12
  45. package/dist/ee/server/src/index.d.ts.map +1 -1
  46. package/dist/ee/server/src/routes/index.d.ts +1 -6
  47. package/dist/ee/server/src/routes/index.d.ts.map +1 -1
  48. package/dist/ee/server/src/routes/license-limit.d.ts +1 -6
  49. package/dist/ee/server/src/routes/license-limit.d.ts.map +1 -1
  50. package/dist/server/ee/server/src/routes/license-limit.js +1 -12
  51. package/dist/server/ee/server/src/routes/license-limit.js.map +1 -1
  52. package/dist/server/ee/server/src/routes/license-limit.mjs +1 -12
  53. package/dist/server/ee/server/src/routes/license-limit.mjs.map +1 -1
  54. package/dist/server/server/src/bootstrap.js +4 -12
  55. package/dist/server/server/src/bootstrap.js.map +1 -1
  56. package/dist/server/server/src/bootstrap.mjs +4 -12
  57. package/dist/server/server/src/bootstrap.mjs.map +1 -1
  58. package/dist/server/server/src/controllers/admin.js +12 -1
  59. package/dist/server/server/src/controllers/admin.js.map +1 -1
  60. package/dist/server/server/src/controllers/admin.mjs +12 -1
  61. package/dist/server/server/src/controllers/admin.mjs.map +1 -1
  62. package/dist/server/server/src/routes/admin.js +10 -0
  63. package/dist/server/server/src/routes/admin.js.map +1 -1
  64. package/dist/server/server/src/routes/admin.mjs +10 -0
  65. package/dist/server/server/src/routes/admin.mjs.map +1 -1
  66. package/dist/server/server/src/services/constants.js +14 -0
  67. package/dist/server/server/src/services/constants.js.map +1 -1
  68. package/dist/server/server/src/services/constants.mjs +14 -0
  69. package/dist/server/server/src/services/constants.mjs.map +1 -1
  70. package/dist/server/server/src/services/guided-tour.js +43 -0
  71. package/dist/server/server/src/services/guided-tour.js.map +1 -0
  72. package/dist/server/server/src/services/guided-tour.mjs +41 -0
  73. package/dist/server/server/src/services/guided-tour.mjs.map +1 -0
  74. package/dist/server/server/src/services/index.js +3 -1
  75. package/dist/server/server/src/services/index.js.map +1 -1
  76. package/dist/server/server/src/services/index.mjs +3 -1
  77. package/dist/server/server/src/services/index.mjs.map +1 -1
  78. package/dist/server/server/src/services/user.js +28 -1
  79. package/dist/server/server/src/services/user.js.map +1 -1
  80. package/dist/server/server/src/services/user.mjs +28 -1
  81. package/dist/server/server/src/services/user.mjs.map +1 -1
  82. package/dist/server/src/bootstrap.d.ts.map +1 -1
  83. package/dist/server/src/controllers/admin.d.ts +6 -1
  84. package/dist/server/src/controllers/admin.d.ts.map +1 -1
  85. package/dist/server/src/controllers/index.d.ts +6 -0
  86. package/dist/server/src/controllers/index.d.ts.map +1 -1
  87. package/dist/server/src/index.d.ts +12 -0
  88. package/dist/server/src/index.d.ts.map +1 -1
  89. package/dist/server/src/routes/admin.d.ts.map +1 -1
  90. package/dist/server/src/services/constants.d.ts +11 -1
  91. package/dist/server/src/services/constants.d.ts.map +1 -1
  92. package/dist/server/src/services/guided-tour.d.ts +12 -0
  93. package/dist/server/src/services/guided-tour.d.ts.map +1 -0
  94. package/dist/server/src/services/index.d.ts +6 -0
  95. package/dist/server/src/services/index.d.ts.map +1 -1
  96. package/dist/server/src/services/user.d.ts +1 -0
  97. package/dist/server/src/services/user.d.ts.map +1 -1
  98. package/dist/shared/contracts/admin.d.ts +15 -0
  99. package/dist/shared/contracts/admin.d.ts.map +1 -1
  100. 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 State = {\n tours: Record<ValidTourName, { currentStep: number; length: number; isCompleted: boolean }>;\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 // Derive the tour state from the tours object\n const tours = Object.keys(registeredTours).reduce(\n (acc, tourName) => {\n const tourLength = Object.keys(registeredTours[tourName as ValidTourName]).length;\n acc[tourName as ValidTourName] = {\n currentStep: 0,\n length: tourLength,\n isCompleted: false,\n };\n return acc;\n },\n {} as Record<ValidTourName, { currentStep: number; length: number; isCompleted: boolean }>\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":";;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,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;;IAEC,MAAMP,KAAAA,GAAQQ,OAAOC,IAAI,CAACF,iBAAiBG,MAAM,CAC/C,CAACC,GAAKC,EAAAA,QAAAA,GAAAA;QACJ,MAAMC,UAAAA,GAAaL,OAAOC,IAAI,CAACF,eAAe,CAACK,QAAAA,CAA0B,EAAER,MAAM;QACjFO,GAAG,CAACC,SAA0B,GAAG;YAC/BV,WAAa,EAAA,CAAA;YACbE,MAAQS,EAAAA,UAAAA;YACRV,WAAa,EAAA;AACf,SAAA;QACA,OAAOQ,GAAAA;AACT,KAAA,EACA,EAAC,CAAA;AAEH,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;;;;;;"}
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 State = {\n tours: Record<ValidTourName, { currentStep: number; length: number; isCompleted: boolean }>;\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 // Derive the tour state from the tours object\n const tours = Object.keys(registeredTours).reduce(\n (acc, tourName) => {\n const tourLength = Object.keys(registeredTours[tourName as ValidTourName]).length;\n acc[tourName as ValidTourName] = {\n currentStep: 0,\n length: tourLength,\n isCompleted: false,\n };\n return acc;\n },\n {} as Record<ValidTourName, { currentStep: number; length: number; isCompleted: boolean }>\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":";;;;;AA4BA,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;;IAEC,MAAMP,KAAAA,GAAQQ,OAAOC,IAAI,CAACF,iBAAiBG,MAAM,CAC/C,CAACC,GAAKC,EAAAA,QAAAA,GAAAA;QACJ,MAAMC,UAAAA,GAAaL,OAAOC,IAAI,CAACF,eAAe,CAACK,QAAAA,CAA0B,EAAER,MAAM;QACjFO,GAAG,CAACC,SAA0B,GAAG;YAC/BV,WAAa,EAAA,CAAA;YACbE,MAAQS,EAAAA,UAAAA;YACRV,WAAa,EAAA;AACf,SAAA;QACA,OAAOQ,GAAAA;AACT,KAAA,EACA,EAAC,CAAA;AAEH,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;;;;"}
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
- contentManager: createTour('contentManager', [
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 isPopoverOpen = isCurrentStep && !state.tours[tourName].isCompleted;
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 { useAuth } from '../../features/Auth';\n\nimport { type State, type Action, unstableUseGuidedTour, ValidTourName } from './Context';\nimport { Step, createStepComponents } from './Step';\n\n/* -------------------------------------------------------------------------------------------------\n * Tours\n * -----------------------------------------------------------------------------------------------*/\n\nconst tours = {\n contentManager: createTour('contentManager', [\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} 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 pointer-events: none;\n`;\n\nconst UnstableGuidedTourTooltip = ({\n children,\n content,\n tourName,\n step,\n}: {\n children: React.ReactNode;\n content: Content;\n tourName: ValidTourName;\n step: number;\n}) => {\n const state = unstableUseGuidedTour('UnstableGuidedTourTooltip', (s) => s.state);\n const dispatch = unstableUseGuidedTour('UnstableGuidedTourTooltip', (s) => s.dispatch);\n const Step = React.useMemo(() => createStepComponents(tourName), [tourName]);\n\n const isCurrentStep = state.tours[tourName].currentStep === step;\n const isPopoverOpen = isCurrentStep && !state.tours[tourName].isCompleted;\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};\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 >\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","contentManager","createTour","name","content","Step","_jsxs","Root","sideOffset","_jsx","Title","id","defaultMessage","Content","Actions","showSkip","GuidedTourOverlay","styled","Box","UnstableGuidedTourTooltip","children","tourName","step","state","unstableUseGuidedTour","s","dispatch","React","useMemo","createStepComponents","isCurrentStep","currentStep","isPopoverOpen","isCompleted","useEffect","originalStyle","window","getComputedStyle","document","body","overflow","style","_Fragment","Popover","open","Anchor","steps","tour","reduce","acc","index","Error"],"mappings":"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"}
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
- contentManager: createTour('contentManager', [
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 isPopoverOpen = isCurrentStep && !state.tours[tourName].isCompleted;
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 { useAuth } from '../../features/Auth';\n\nimport { type State, type Action, unstableUseGuidedTour, ValidTourName } from './Context';\nimport { Step, createStepComponents } from './Step';\n\n/* -------------------------------------------------------------------------------------------------\n * Tours\n * -----------------------------------------------------------------------------------------------*/\n\nconst tours = {\n contentManager: createTour('contentManager', [\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} 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 pointer-events: none;\n`;\n\nconst UnstableGuidedTourTooltip = ({\n children,\n content,\n tourName,\n step,\n}: {\n children: React.ReactNode;\n content: Content;\n tourName: ValidTourName;\n step: number;\n}) => {\n const state = unstableUseGuidedTour('UnstableGuidedTourTooltip', (s) => s.state);\n const dispatch = unstableUseGuidedTour('UnstableGuidedTourTooltip', (s) => s.dispatch);\n const Step = React.useMemo(() => createStepComponents(tourName), [tourName]);\n\n const isCurrentStep = state.tours[tourName].currentStep === step;\n const isPopoverOpen = isCurrentStep && !state.tours[tourName].isCompleted;\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};\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 >\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","contentManager","createTour","name","content","Step","_jsxs","Root","sideOffset","_jsx","Title","id","defaultMessage","Content","Actions","showSkip","GuidedTourOverlay","styled","Box","UnstableGuidedTourTooltip","children","tourName","step","state","unstableUseGuidedTour","s","dispatch","React","useMemo","createStepComponents","isCurrentStep","currentStep","isPopoverOpen","isCompleted","useEffect","originalStyle","window","getComputedStyle","document","body","overflow","style","_Fragment","Popover","open","Anchor","steps","tour","reduce","acc","index","Error"],"mappings":"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"}
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;;;;"}