@strapi/admin 4.12.6 → 4.13.0-alpha.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 (211) hide show
  1. package/admin/src/StrapiApp.js +1 -1
  2. package/admin/src/components/AuthenticatedApp/index.js +118 -0
  3. package/admin/src/components/AuthenticatedApp/utils/api.js +85 -0
  4. package/admin/src/components/AuthenticatedApp/utils/checkLatestStrapiVersion.js +11 -0
  5. package/admin/src/components/GuidedTour/Modal/index.js +3 -1
  6. package/admin/src/components/NpsSurvey/hooks/useNpsSurveySettings.js +17 -0
  7. package/admin/src/components/NpsSurvey/index.js +365 -0
  8. package/admin/src/components/PluginsInitializer/index.js +68 -0
  9. package/admin/src/components/PluginsInitializer/init.js +11 -0
  10. package/admin/src/components/PluginsInitializer/reducer.js +22 -0
  11. package/admin/src/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/getTableColumns.js +2 -0
  12. package/admin/src/content-manager/components/DynamicZone/components/DynamicZoneLabel.js +1 -1
  13. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +8 -1
  14. package/admin/src/content-manager/components/Filter/CustomInputs/AdminUsersFilter.js +42 -0
  15. package/admin/src/content-manager/components/Filter/Filter.js +54 -0
  16. package/admin/src/content-manager/components/Filter/index.js +1 -0
  17. package/admin/src/content-manager/components/InputUID/index.js +222 -216
  18. package/admin/src/content-manager/components/RelationInput/RelationInput.js +4 -0
  19. package/admin/src/content-manager/components/RepeatableComponent/index.js +32 -2
  20. package/admin/src/content-manager/components/Wysiwyg/Editor.js +432 -68
  21. package/admin/src/content-manager/components/Wysiwyg/WysiwygStyles.js +0 -7
  22. package/admin/src/content-manager/components/Wysiwyg/index.js +147 -152
  23. package/admin/src/content-manager/hooks/useAllowedAttributes.js +47 -0
  24. package/admin/src/content-manager/pages/App/index.js +16 -5
  25. package/admin/src/content-manager/pages/EditView/Information/index.js +9 -8
  26. package/admin/src/content-manager/pages/ListSettingsView/components/Settings.js +40 -7
  27. package/admin/src/content-manager/pages/ListSettingsView/index.js +6 -2
  28. package/admin/src/content-manager/pages/ListView/components/BulkActionButtons/SelectedEntriesModal/index.js +2 -2
  29. package/admin/src/content-manager/pages/ListView/components/FieldPicker/index.js +67 -69
  30. package/admin/src/content-manager/pages/ListView/components/TableRows/index.js +1 -1
  31. package/admin/src/content-manager/pages/ListView/components/ViewSettingsMenu/index.js +80 -0
  32. package/admin/src/content-manager/pages/ListView/index.js +236 -67
  33. package/admin/src/content-manager/utils/getDisplayName.js +33 -0
  34. package/admin/src/content-manager/utils/index.js +1 -0
  35. package/admin/src/hooks/useSettingsForm/index.js +3 -14
  36. package/admin/src/hooks/useSettingsMenu/index.js +2 -2
  37. package/admin/src/hooks/useSettingsMenu/utils/formatLinks.js +3 -1
  38. package/admin/src/hooks/useSettingsMenu/utils/sortLinks.js +3 -1
  39. package/admin/src/index.js +1 -1
  40. package/admin/src/layouts/AppLayout/index.js +33 -0
  41. package/admin/src/pages/Admin/Onboarding/index.js +3 -1
  42. package/admin/src/pages/Admin/index.js +73 -77
  43. package/admin/src/pages/App/constants.js +1 -1
  44. package/admin/src/pages/App/index.js +122 -160
  45. package/admin/src/pages/AuthPage/components/Register/index.js +5 -0
  46. package/admin/src/pages/AuthPage/index.js +4 -2
  47. package/admin/src/pages/HomePage/index.js +3 -1
  48. package/admin/src/pages/InstalledPluginsPage/index.js +3 -1
  49. package/admin/src/pages/{InternalErrorPage.js → InternalErrorPage/index.js} +4 -3
  50. package/admin/src/pages/{NotFoundPage.js → NotFoundPage/index.js} +3 -1
  51. package/admin/src/pages/ProfilePage/index.js +4 -2
  52. package/admin/src/pages/SettingsPage/constants.js +132 -67
  53. package/admin/src/pages/SettingsPage/index.js +18 -23
  54. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +1 -1
  55. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +1 -1
  56. package/admin/src/pages/SettingsPage/pages/Users/EditPage/index.js +1 -2
  57. package/admin/src/pages/SettingsPage/pages/Users/ListPage/DynamicTable/TableRows/index.js +1 -1
  58. package/admin/src/pages/UseCasePage/index.js +175 -0
  59. package/admin/src/plugins.js +7 -8
  60. package/admin/src/translations/en.json +10 -1
  61. package/admin/src/utils/checkFormValidity.js +15 -0
  62. package/admin/src/utils/createRoute.js +7 -5
  63. package/admin/src/utils/formatAPIErrors.js +3 -1
  64. package/admin/src/utils/getAttributesToDisplay.js +19 -0
  65. package/admin/src/utils/getExistingActions.js +32 -0
  66. package/admin/src/utils/getFullName.js +1 -1
  67. package/admin/src/utils/index.js +9 -0
  68. package/admin/src/utils/makeUniqueRoutes.js +6 -0
  69. package/admin/src/utils/sortLinks.js +3 -1
  70. package/admin/src/utils/uniqueAdminHash.js +9 -2
  71. package/build/{1049.9d69d231.chunk.js → 1049.ec69f5e0.chunk.js} +1 -1
  72. package/build/1227.9f37e1dc.chunk.js +1 -0
  73. package/build/1386.ea73b677.chunk.js +7 -0
  74. package/build/{2225.33287e1b.chunk.js → 2225.649fb7bc.chunk.js} +2 -2
  75. package/build/{2237.03792b63.chunk.js → 2237.b832ae6e.chunk.js} +4 -4
  76. package/build/{2379.401f56f3.chunk.js → 2379.1f98a31a.chunk.js} +1 -1
  77. package/build/{2395.e6a79fbb.chunk.js → 2395.0e5e8ded.chunk.js} +1 -1
  78. package/build/{2801.31393ffe.chunk.js → 2801.8e1aa82a.chunk.js} +1 -1
  79. package/build/3483.19381b40.chunk.js +1 -0
  80. package/build/3739.63e352f1.chunk.js +103 -0
  81. package/build/4174.f1f39e40.chunk.js +1 -0
  82. package/build/448.829e1344.chunk.js +1 -0
  83. package/build/4546.a5946d22.chunk.js +1 -0
  84. package/build/4724.aea5c8c1.chunk.js +6 -0
  85. package/build/{502.8dd074ff.chunk.js → 502.7bba43b1.chunk.js} +1 -1
  86. package/build/6158.c3c13c20.chunk.js +1 -0
  87. package/build/6691.4985ef22.chunk.js +105 -0
  88. package/build/{7464.592a9295.chunk.js → 7464.eb057bec.chunk.js} +1 -1
  89. package/build/78.dcc6df5c.chunk.js +1 -0
  90. package/build/{8276.e519a707.chunk.js → 8276.be3ed581.chunk.js} +2 -2
  91. package/build/{2747.d1442a90.chunk.js → 9806.5d5a0e8d.chunk.js} +64 -72
  92. package/build/9944.7af075a5.chunk.js +26 -0
  93. package/build/Admin-authenticatedApp.43b6ec9a.chunk.js +79 -0
  94. package/build/Admin_InternalErrorPage.38155af3.chunk.js +1 -0
  95. package/build/Admin_homePage.6f128523.chunk.js +81 -0
  96. package/build/Admin_marketplace.061a6e5a.chunk.js +55 -0
  97. package/build/Admin_pluginsPage.16f837b8.chunk.js +6 -0
  98. package/build/Admin_profilePage.678bce24.chunk.js +13 -0
  99. package/build/Admin_settingsPage.af7309e4.chunk.js +111 -0
  100. package/build/{Upload_ConfigureTheView.345ac1e0.chunk.js → Upload_ConfigureTheView.3fc1c100.chunk.js} +1 -1
  101. package/build/admin-app.d63bd229.chunk.js +36 -0
  102. package/build/{admin-edit-roles-page.24bdf746.chunk.js → admin-edit-roles-page.38a6c863.chunk.js} +3 -3
  103. package/build/admin-edit-users.545fc882.chunk.js +10 -0
  104. package/build/{admin-roles-list.23ddff26.chunk.js → admin-roles-list.1e2e814d.chunk.js} +1 -1
  105. package/build/admin-users.b8ea5677.chunk.js +11 -0
  106. package/build/{api-tokens-create-page.46c2ea84.chunk.js → api-tokens-create-page.e0c15627.chunk.js} +1 -1
  107. package/build/{api-tokens-edit-page.58139df9.chunk.js → api-tokens-edit-page.9f2dce47.chunk.js} +1 -1
  108. package/build/{api-tokens-list-page.0af7d431.chunk.js → api-tokens-list-page.d747051c.chunk.js} +2 -2
  109. package/build/{audit-logs-settings-page.0f73ccf8.chunk.js → audit-logs-settings-page.96f9d608.chunk.js} +1 -1
  110. package/build/content-manager.ccff1078.chunk.js +1097 -0
  111. package/build/{content-type-builder-list-view.bf9be456.chunk.js → content-type-builder-list-view.b71cf240.chunk.js} +1 -1
  112. package/build/{content-type-builder.66066281.chunk.js → content-type-builder.e5669749.chunk.js} +18 -18
  113. package/build/{email-settings-page.2f7e35c0.chunk.js → email-settings-page.2809f0bf.chunk.js} +1 -1
  114. package/build/en-json.e12fd5fc.chunk.js +1 -0
  115. package/build/{i18n-settings-page.47f78016.chunk.js → i18n-settings-page.5f716172.chunk.js} +1 -1
  116. package/build/index.html +1 -1
  117. package/build/main.c6c9e04c.js +2859 -0
  118. package/build/{review-workflows-settings-create-view.d24a32b9.chunk.js → review-workflows-settings-create-view.4a156a19.chunk.js} +1 -1
  119. package/build/{review-workflows-settings-edit-view.6044b022.chunk.js → review-workflows-settings-edit-view.ce984d1f.chunk.js} +1 -1
  120. package/build/{review-workflows-settings-list-view.3f0ef4bc.chunk.js → review-workflows-settings-list-view.419b8deb.chunk.js} +2 -2
  121. package/build/runtime~main.dcf1cb45.js +2 -0
  122. package/build/{sso-settings-page.4dba0670.chunk.js → sso-settings-page.45153df5.chunk.js} +1 -1
  123. package/build/{transfer-tokens-create-page.1597e6ab.chunk.js → transfer-tokens-create-page.ebba16d8.chunk.js} +1 -1
  124. package/build/{transfer-tokens-edit-page.8741529f.chunk.js → transfer-tokens-edit-page.d7bb2b3e.chunk.js} +1 -1
  125. package/build/{transfer-tokens-list-page.d6986b03.chunk.js → transfer-tokens-list-page.cfe1736c.chunk.js} +2 -2
  126. package/build/{upload-settings.7f93d4c0.chunk.js → upload-settings.cc5ad813.chunk.js} +1 -1
  127. package/build/{upload.37488080.chunk.js → upload.756efc28.chunk.js} +1 -1
  128. package/build/{users-advanced-settings-page.17052d72.chunk.js → users-advanced-settings-page.818d84eb.chunk.js} +1 -1
  129. package/build/{users-email-settings-page.3de8ea50.chunk.js → users-email-settings-page.c1967c09.chunk.js} +1 -1
  130. package/build/{users-providers-settings-page.0eaa916d.chunk.js → users-providers-settings-page.11893e08.chunk.js} +1 -1
  131. package/build/{users-roles-settings-page.957ad48b.chunk.js → users-roles-settings-page.2b051e6a.chunk.js} +1 -1
  132. package/build/webhook-edit-page.de45c635.chunk.js +33 -0
  133. package/build/{webhook-list-page.65e1b5bb.chunk.js → webhook-list-page.ca91df8b.chunk.js} +1 -1
  134. package/ee/admin/content-manager/components/Filter/CustomInputs/ReviewWorkflows/AssigneeFilter.js +42 -0
  135. package/ee/admin/content-manager/components/Filter/CustomInputs/ReviewWorkflows/StageFilter.js +70 -0
  136. package/ee/admin/content-manager/components/Filter/CustomInputs/ReviewWorkflows/constants.js +71 -0
  137. package/ee/admin/content-manager/pages/EditView/InformationBox/InformationBoxEE.js +9 -217
  138. package/ee/admin/content-manager/pages/EditView/InformationBox/components/AssigneeSelect/AssigneeSelect.js +147 -0
  139. package/ee/admin/content-manager/pages/EditView/InformationBox/components/AssigneeSelect/index.js +1 -0
  140. package/ee/admin/content-manager/pages/EditView/InformationBox/components/StageSelect/StageSelect.js +243 -0
  141. package/ee/admin/content-manager/pages/EditView/InformationBox/components/StageSelect/index.js +1 -0
  142. package/ee/admin/content-manager/pages/EditView/InformationBox/constants.js +2 -0
  143. package/ee/admin/content-manager/pages/ListSettingsView/constants.js +7 -0
  144. package/ee/admin/content-manager/pages/ListView/ReviewWorkflowsColumn/ReviewWorkflowsAssigneeEE.js +21 -0
  145. package/ee/admin/content-manager/pages/ListView/ReviewWorkflowsColumn/constants.js +44 -17
  146. package/ee/admin/content-manager/pages/ListView/ReviewWorkflowsColumn/index.js +1 -0
  147. package/ee/admin/pages/App/constants.js +5 -6
  148. package/ee/admin/pages/SettingsPage/constants.js +42 -27
  149. package/ee/server/constants/workflows.js +1 -0
  150. package/ee/server/controllers/index.js +1 -0
  151. package/ee/server/controllers/workflows/assignees/index.js +44 -0
  152. package/ee/server/routes/review-workflows.js +17 -0
  153. package/ee/server/services/index.js +1 -0
  154. package/ee/server/services/review-workflows/assignees.js +54 -0
  155. package/ee/server/services/review-workflows/metrics/index.js +5 -0
  156. package/ee/server/services/review-workflows/review-workflows.js +20 -11
  157. package/ee/server/validation/review-workflows.js +8 -0
  158. package/index.js +2 -6
  159. package/package.json +9 -9
  160. package/scripts/build.js +15 -15
  161. package/scripts/create-dev-plugins-file.js +5 -38
  162. package/server/controllers/role.js +2 -0
  163. package/server/controllers/user.js +2 -0
  164. package/server/services/permission/permissions-manager/index.js +3 -1
  165. package/server/services/permission/permissions-manager/sanitize.js +19 -7
  166. package/server/services/permission/permissions-manager/validate.js +218 -0
  167. package/utils/create-cache-dir.js +62 -16
  168. package/utils/create-plugins-exclude-path.js +3 -23
  169. package/utils/get-plugins.js +110 -0
  170. package/utils/index.js +1 -1
  171. package/webpack.config.js +10 -13
  172. package/admin/src/components/AuthenticatedApp.js +0 -229
  173. package/admin/src/content-manager/components/AttributeFilter/Filters.js +0 -58
  174. package/admin/src/content-manager/components/AttributeFilter/hooks/useAllowedAttributes.js +0 -42
  175. package/admin/src/content-manager/components/AttributeFilter/index.js +0 -40
  176. package/admin/src/content-manager/components/Wysiwyg/EditorStylesContainer.js +0 -344
  177. package/admin/src/pages/UseCasePage.js +0 -174
  178. package/build/2166.c837469a.chunk.js +0 -1
  179. package/build/3483.8517171f.chunk.js +0 -1
  180. package/build/3984.dda474f7.chunk.js +0 -1
  181. package/build/4546.7a3c0d03.chunk.js +0 -1
  182. package/build/5483.5bfbb00d.chunk.js +0 -6
  183. package/build/6158.c974fd83.chunk.js +0 -1
  184. package/build/748.fd2e5afd.chunk.js +0 -105
  185. package/build/773.6381d62d.chunk.js +0 -18
  186. package/build/7826.399afe81.chunk.js +0 -103
  187. package/build/8261.2525d35c.chunk.js +0 -7
  188. package/build/8299.62b67c72.chunk.js +0 -1
  189. package/build/Admin-AuthPage.90d64342.chunk.js +0 -35
  190. package/build/Admin-AuthenticatedApp.379ac945.chunk.js +0 -24
  191. package/build/Admin-UseCasePage.1f757db5.chunk.js +0 -13
  192. package/build/Admin_GuidedTourModal.8ccf1fbc.chunk.js +0 -12
  193. package/build/Admin_InternalErrorPage.9de92c6d.chunk.js +0 -9
  194. package/build/Admin_NotFoundPage.21620424.chunk.js +0 -9
  195. package/build/Admin_Onboarding.dbfa32f6.chunk.js +0 -43
  196. package/build/Admin_homePage.2000cbe9.chunk.js +0 -86
  197. package/build/Admin_marketplace.ec80e29b.chunk.js +0 -63
  198. package/build/Admin_pluginsPage.0c6851f8.chunk.js +0 -14
  199. package/build/Admin_profilePage.78cd8495.chunk.js +0 -21
  200. package/build/Admin_settingsPage.1760c3ce.chunk.js +0 -119
  201. package/build/StrapiApp.221fac30.chunk.js +0 -5
  202. package/build/admin-edit-users.5d10d444.chunk.js +0 -10
  203. package/build/admin-users.2b3e4305.chunk.js +0 -11
  204. package/build/content-manager.fb0833bd.chunk.js +0 -1099
  205. package/build/en-json.08c05fcf.chunk.js +0 -1
  206. package/build/main.ee3c1938.js +0 -2859
  207. package/build/runtime~main.397ee447.js +0 -2
  208. package/build/webhook-edit-page.665210af.chunk.js +0 -33
  209. package/scripts/create-plugins-file.js +0 -92
  210. package/utils/get-plugins-path.js +0 -41
  211. /package/server/services/permission/permissions-manager/{query-builers.js → query-builders.js} +0 -0
@@ -0,0 +1,33 @@
1
+ "use strict";(self.webpackChunk_strapi_admin=self.webpackChunk_strapi_admin||[]).push([[5162],{36795:function(G,P,t){var e=t(32735),T=t(29397),g=t(87933),b=t(76437),W=t(23866),K=t(31121),U=t(35197),i=t(38837),se=t(3685),re=t(49372),j=t(40801),X=t(8284),S=t(82884),Q=t(92802),ie=t(60216),f=t.n(ie),_=t(67879),D=t(8471),de=t(90769);const u=s=>s.reduce((r,d)=>{const M=d.split(".")[0];return r[M]||(r[M]=[]),r[M].push(d),r},{}),B=(0,D.ZP)(T.w)`
2
+ tbody tr:nth-child(odd) {
3
+ background: ${({theme:s})=>s.colors.neutral100};
4
+ }
5
+
6
+ thead th span {
7
+ color: ${({theme:s})=>s.colors.neutral500};
8
+ }
9
+
10
+ td,
11
+ th {
12
+ padding-block-start: ${({theme:s})=>s.spaces[3]};
13
+ padding-block-end: ${({theme:s})=>s.spaces[3]};
14
+ width: 10%;
15
+ vertical-align: middle;
16
+ text-align: center;
17
+ }
18
+
19
+ tbody tr td:first-child {
20
+ /**
21
+ * Add padding to the start of the first column to avoid the checkbox appearing
22
+ * too close to the edge of the table
23
+ */
24
+ padding-inline-start: ${({theme:s})=>s.spaces[2]};
25
+ }
26
+ `,oe=s=>{const r=[{id:"Settings.webhooks.events.create",defaultMessage:"Create"},{id:"Settings.webhooks.events.update",defaultMessage:"Update"},{id:"app.utils.delete",defaultMessage:"Delete"}];return s&&(r.push({id:"app.utils.publish",defaultMessage:"Publish"}),r.push({id:"app.utils.unpublish",defaultMessage:"Unpublish"})),r},Y=s=>{const r=["entry.create","entry.update","entry.delete"];return s&&r.push("entry.publish","entry.unpublish"),{entry:r,media:["media.create","media.update","media.delete"]}},J=e.createContext(),le=({children:s})=>{const{formatMessage:r}=(0,_.Z)(),{collectionTypes:d,isLoading:M}=(0,de.G)(),y=e.useMemo(()=>d.some(L=>L.options.draftAndPublish===!0),[d]),v=r({id:"Settings.webhooks.form.events",defaultMessage:"Events"});return e.createElement(J.Provider,{value:{isDraftAndPublish:y}},e.createElement(g.k,{direction:"column",alignItems:"stretch",gap:1},e.createElement(b.Q,{"aria-hidden":!0},v),M&&e.createElement(W.a,null,r({id:"Settings.webhooks.events.isLoading",defaultMessage:"Events loading"})),e.createElement(B,{"aria-label":v},s)))};le.propTypes={children:f().oneOfType([f().arrayOf(f().node),f().node]).isRequired};const q=({getHeaders:s=oe})=>{const{isDraftAndPublish:r}=e.useContext(J),{formatMessage:d}=(0,_.Z)(),M=s(r);return e.createElement(K.S,null,e.createElement(U.Z,null,e.createElement(i.g,null,e.createElement(se.T,null,d({id:"Settings.webhooks.event.select",defaultMessage:"Select event"}))),M.map(y=>["app.utils.publish","app.utils.unpublish"].includes(y.id)?e.createElement(i.g,{key:y.id,title:d({id:"Settings.webhooks.event.publish-tooltip",defaultMessage:"This event only exists for content with draft & publish enabled"})},e.createElement(re.Z,{variant:"sigma",textColor:"neutral600"},d(y))):e.createElement(i.g,{key:y.id},e.createElement(re.Z,{variant:"sigma",textColor:"neutral600"},d(y))))))};q.defaultProps={getHeaders:oe},q.propTypes={getHeaders:f().func};const ee=({providedEvents:s})=>{const{isDraftAndPublish:r}=e.useContext(J),d=s||Y(r),{values:M,handleChange:y}=(0,Q.u6)(),v="events",L=M.events,w=[],te=u(L),A=({target:{name:E,value:m}})=>{let C=new Set(L);m?C.add(E):C.delete(E),y({target:{name:v,value:Array.from(C)}})},$=({target:{name:E,value:m}})=>{let C=new Set(L);m?d[E].forEach(N=>{w.includes(N)||C.add(N)}):d[E].forEach(N=>C.delete(N)),y({target:{name:v,value:Array.from(C)}})};return e.createElement(j.X,null,Object.entries(d).map(([E,m])=>e.createElement(F,{disabledEvents:w,key:E,name:E,events:m,inputValue:te[E],handleSelect:A,handleSelectAll:$})))};ee.defaultProps={providedEvents:null},ee.propTypes={providedEvents:f().object};const ce=s=>s.replace(/-/g," ").split(" ").map(r=>r.charAt(0).toUpperCase()+r.slice(1).toLowerCase()).join(" "),F=({disabledEvents:s,name:r,events:d,inputValue:M,handleSelect:y,handleSelectAll:v})=>{const{formatMessage:L}=(0,_.Z)(),w=d.filter(m=>!s.includes(m)),te=M.length>0,A=M.length===w.length,$=({target:{name:m}})=>{v({target:{name:m,value:!A}})},E=5;return e.createElement(U.Z,null,e.createElement(i.f,null,e.createElement(X.X,{indeterminate:te&&!A,"aria-label":L({id:"global.select-all-entries",defaultMessage:"Select all entries"}),name:r,onChange:$,value:A},ce(r))),d.map(m=>e.createElement(i.f,{key:m},e.createElement(S.C,{disabled:s.includes(m),"aria-label":m,name:m,value:M.includes(m),onValueChange:C=>y({target:{name:m,value:C}})}))),d.length<E&&e.createElement(i.f,{colSpan:E-d.length}))};F.defaultProps={disabledEvents:[],events:[],inputValue:[],handleSelect(){},handleSelectAll(){}},F.propTypes={disabledEvents:f().array,events:f().array,inputValue:f().array,handleSelect:f().func,handleSelectAll:f().func,name:f().string.isRequired},P.Z={Root:le,Headers:q,Body:ee,EventRow:F}},77476:function(G,P,t){t.d(P,{Z:function(){return fe}});var e=t(32735),T=t(27649),g=t(45509),b=t(20108),W=t(53038),K=t(90769),U=t(82055),i=t(87933),se=t(41415),re=t(17e3),j=t(72850),X=t(15335),S=t(5803),Q=t(10369),ie=t(2438),f=t(66456),_=t(29439),D=t(92802),de=t(60216),u=t.n(de),B=t(67879),oe=t(9592),Y=t(36795);function J(){return e.createElement(Y.Z.Root,null,e.createElement(Y.Z.Headers,null),e.createElement(Y.Z.Body,null))}var le=t(76437),q=t(7563),ee=t(19406),ce=t(21428),F=t(90333);const s=["A-IM","Accept","Accept-Charset","Accept-Encoding","Accept-Language","Accept-Datetime","Access-Control-Request-Method","Access-Control-Request-Headers","Authorization","Cache-Control","Connection","Content-Length","Content-Type","Cookie","Date","Expect","Forwarded","From","Host","If-Match","If-Modified-Since","If-None-Match","If-Range","If-Unmodified-Since","Max-Forwards","Origin","Pragma","Proxy-Authorization","Range","Referer","TE","User-Agent","Upgrade","Via","Warning"],r=({name:n,onChange:a,value:o,...c})=>{const{values:{headers:h}}=(0,D.u6)(),[O,l]=(0,e.useState)(s);(0,e.useEffect)(()=>{l(s.filter(p=>!h?.some(x=>x.key!==o&&x.key===p)))},[h,o]);const H=p=>{a({target:{name:n,value:p}})},z=p=>{l(x=>[...x,p]),H(p)};return e.createElement(ce.XU,{...c,onClear:()=>H(""),onChange:H,onCreateOption:z,placeholder:"",value:o},O.map(p=>e.createElement(F.O,{value:p,key:p},p)))};r.defaultProps={value:void 0},r.propTypes={name:u().string.isRequired,onChange:u().func.isRequired,value:u().string};var d=r,y=()=>{const{formatMessage:n}=(0,B.Z)(),{values:a,errors:o}=(0,D.u6)();return e.createElement(i.k,{direction:"column",alignItems:"stretch",gap:1},e.createElement(le.Q,null,n({id:"Settings.webhooks.form.headers",defaultMessage:"Headers"})),e.createElement(j.x,{padding:8,background:"neutral100",hasRadius:!0},e.createElement(D.F2,{validateOnChange:!1,name:"headers",render:({push:c,remove:h})=>e.createElement(X.r,{gap:4},a.headers.map((O,l)=>e.createElement(e.Fragment,{key:`${l}.${O.key}`},e.createElement(S.P,{col:6},e.createElement(D.gN,{as:d,name:`headers.${l}.key`,"aria-label":`row ${l+1} key`,label:n({id:"Settings.webhooks.key",defaultMessage:"Key"}),error:o.headers?.[l]?.key&&o.headers[l].key})),e.createElement(S.P,{col:6},e.createElement(i.k,{alignItems:"flex-end"},e.createElement(j.x,{style:{flex:1}},e.createElement(D.gN,{as:Q.o,name:`headers.${l}.value`,"aria-label":`row ${l+1} value`,label:n({id:"Settings.webhooks.value",defaultMessage:"Value"}),error:o.headers?.[l]?.value&&o.headers[l].value})),e.createElement(i.k,{paddingLeft:2,style:{alignSelf:"center"},paddingTop:o.headers?.[l]?.value?0:5},e.createElement(g.fG,{disabled:a.headers.length===1,onClick:()=>h(l),label:n({id:"Settings.webhooks.headers.remove",defaultMessage:"Remove header row {number}"},{number:l+1})})))))),e.createElement(S.P,{col:12},e.createElement(q.A,{type:"button",onClick:()=>{c({key:"",value:""})},startIcon:e.createElement(ee.Z,null)},n({id:"Settings.webhooks.create.header",defaultMessage:"Create new header"}))))})))},v=t(49372),L=t(27169),w=t(35331),te=t(8471);const A=te.ZP.svg(({theme:n,color:a})=>`
27
+ width: ${12/16}rem;
28
+ height: ${12/16}rem;
29
+
30
+ path {
31
+ fill: ${n.colors[a]};
32
+ }
33
+ `),$=({isPending:n,statusCode:a})=>{const{formatMessage:o}=(0,B.Z)();return n?e.createElement(i.k,{gap:2,alignItems:"center"},e.createElement(A,{as:L.Z}),e.createElement(v.Z,null,o({id:"Settings.webhooks.trigger.pending",defaultMessage:"pending"}))):a>=200&&a<300?e.createElement(i.k,{gap:2,alignItems:"center"},e.createElement(A,{as:f.Z,color:"success700"}),e.createElement(v.Z,null,o({id:"Settings.webhooks.trigger.success",defaultMessage:"success"}))):a>=300?e.createElement(i.k,{gap:2,alignItems:"center"},e.createElement(A,{as:w.Z,color:"danger700"}),e.createElement(v.Z,null,o({id:"Settings.error",defaultMessage:"error"})," ",a)):null};$.propTypes={isPending:u().bool.isRequired,statusCode:u().number},$.defaultProps={statusCode:void 0};const E=({statusCode:n,message:a})=>{const{formatMessage:o}=(0,B.Z)();return n>=200&&n<300?e.createElement(i.k,{justifyContent:"flex-end"},e.createElement(v.Z,{textColor:"neutral600",ellipsis:!0},o({id:"Settings.webhooks.trigger.success.label",defaultMessage:"Trigger succeeded"}))):n>=300?e.createElement(i.k,{justifyContent:"flex-end"},e.createElement(i.k,{maxWidth:(0,g.Q1)(250),justifyContent:"flex-end",title:a},e.createElement(v.Z,{ellipsis:!0,textColor:"neutral600"},a))):null};E.propTypes={statusCode:u().number,message:u().string},E.defaultProps={statusCode:void 0,message:void 0};const m=({onCancel:n})=>{const{formatMessage:a}=(0,B.Z)();return e.createElement(i.k,{justifyContent:"flex-end"},e.createElement("button",{onClick:n,type:"button"},e.createElement(i.k,{gap:2,alignItems:"center"},e.createElement(v.Z,{textColor:"neutral400"},a({id:"Settings.webhooks.trigger.cancel",defaultMessage:"cancel"})),e.createElement(A,{as:w.Z,color:"neutral400"}))))};m.propTypes={onCancel:u().func.isRequired};const C=({isPending:n,onCancel:a,response:o})=>{const{statusCode:c,message:h}=o,{formatMessage:O}=(0,B.Z)();return e.createElement(j.x,{background:"neutral0",padding:5,shadow:"filterShadow",hasRadius:!0},e.createElement(X.r,{gap:4,style:{alignItems:"center"}},e.createElement(S.P,{col:3},e.createElement(v.Z,null,O({id:"Settings.webhooks.trigger.test",defaultMessage:"Test-trigger"}))),e.createElement(S.P,{col:3},e.createElement($,{isPending:n,statusCode:c})),e.createElement(S.P,{col:6},n?e.createElement(m,{onCancel:a}):e.createElement(E,{statusCode:c,message:h}))))};C.defaultProps={isPending:!1,onCancel(){},response:{}},C.propTypes={isPending:u().bool,onCancel:u().func,response:u().object};var N=C,k=t(24346);const ge=/(^$)|(^[A-Za-z][_0-9A-Za-z ]*$)/,Ee=/(^$)|((https?:\/\/.*)(d*)\/?(.*))/,he=({formatMessage:n})=>k.Ry().shape({name:k.Z_().required(n({id:"Settings.webhooks.validation.name.required",defaultMessage:"Name is required"})).matches(ge,n({id:"Settings.webhooks.validation.name.regex",defaultMessage:"The name must start with a letter and only contain letters, numbers, spaces and underscores"})),url:k.Z_().required(n({id:"Settings.webhooks.validation.url.required",defaultMessage:"Url is required"})).matches(Ee,n({id:"Settings.webhooks.validation.url.regex",defaultMessage:"The value must be a valid Url"})),headers:k.Vo(a=>{let o=k.IX();if(a.length===1){const{key:c,value:h}=a[0];if(!c&&!h)return o}return o.of(k.Ry().shape({key:k.Z_().required(n({id:"Settings.webhooks.validation.key",defaultMessage:"Key is required"})),value:k.Z_().required(n({id:"Settings.webhooks.validation.value",defaultMessage:"Value is required"}))}))}),events:k.IX()}),ue=({handleSubmit:n,triggerWebhook:a,isCreating:o,isTriggering:c,triggerResponse:h,data:O})=>{const{formatMessage:l}=(0,B.Z)(),[H,z]=(0,e.useState)(!1),p=(0,oe.c)(J,async()=>(await t.e(7030).then(t.bind(t,61442))).EventTableEE),x=Z=>Object.keys(Z).length?Object.entries(Z).map(([ne,ae])=>({key:ne,value:ae})):[{key:"",value:""}],R=(0,D.TA)({initialValues:{name:O?.name||"",url:O?.url||"",headers:x(O?.headers||{}),events:O?.events||[]},onSubmit(Z,{resetForm:ne,setSubmitting:ae}){n(Z),ne({values:Z}),ae(!1)},validationSchema:he({formatMessage:l}),validateOnChange:!1,validateOnBlur:!1});return p?e.createElement(D.Hy,{value:R},e.createElement(g.l0,{onSubmit:R.handleSubmit},e.createElement(U.T,{primaryAction:e.createElement(i.k,{gap:2},e.createElement(se.z,{onClick:()=>{a(),z(!0)},variant:"tertiary",startIcon:e.createElement(ie.Z,null),disabled:o||c,size:"L"},l({id:"Settings.webhooks.trigger",defaultMessage:"Trigger"})),e.createElement(se.z,{startIcon:e.createElement(f.Z,null),type:"submit",size:"L",disabled:!R.dirty,loading:R.isSubmitting},l({id:"global.save",defaultMessage:"Save"}))),title:o?l({id:"Settings.webhooks.create",defaultMessage:"Create a webhook"}):O?.name,navigationAction:e.createElement(g.rU,{startIcon:e.createElement(_.Z,null),to:"/settings/webhooks"},l({id:"global.back",defaultMessage:"Back"}))}),e.createElement(re.D,null,e.createElement(i.k,{direction:"column",alignItems:"stretch",gap:4},H&&e.createElement(N,{isPending:c,response:h,onCancel:()=>z(!1)}),e.createElement(j.x,{background:"neutral0",padding:8,shadow:"filterShadow",hasRadius:!0},e.createElement(i.k,{direction:"column",alignItems:"stretch",gap:6},e.createElement(X.r,{gap:6},e.createElement(S.P,{col:6},e.createElement(D.gN,{as:Q.o,name:"name",error:R?.errors?.name&&R.errors.name,label:l({id:"global.name",defaultMessage:"Name"}),required:!0})),e.createElement(S.P,{col:12},e.createElement(D.gN,{as:Q.o,name:"url",error:R?.errors?.url&&R.errors.url,label:l({id:"Settings.roles.form.input.url",defaultMessage:"Url"}),required:!0}))),e.createElement(y,null),e.createElement(p,null))))))):null};ue.propTypes={data:u().object,handleSubmit:u().func.isRequired,triggerWebhook:u().func.isRequired,isCreating:u().bool.isRequired,isTriggering:u().bool.isRequired,triggerResponse:u().object},ue.defaultProps={data:void 0,triggerResponse:void 0};var pe=ue;const me=n=>({...n,headers:n.headers.reduce((a,{key:o,value:c})=>(o!==""&&(a[o]=c),a),{})});var fe=()=>{const{params:{id:n}}=(0,W.$B)("/settings/webhooks/:id"),a=n==="create",{replace:o}=(0,W.k6)(),c=(0,g.lm)(),{formatAPIError:h}=(0,g.So)(),O=(0,b.useQueryClient)(),{isLoading:l}=(0,K.G)(),{put:H,get:z,post:p}=(0,g.kY)(),{isLoading:x,data:R,error:Z}=(0,b.useQuery)(["webhooks",n],async()=>{const{data:{data:I}}=await z(`/admin/webhooks/${n}`);return I},{enabled:!a});e.useEffect(()=>{Z&&c({type:"warning",message:h(Z)})},[Z,c,h]);const{isLoading:ne,data:ae,isIdle:ve,mutate:Me}=(0,b.useMutation)(()=>p(`/admin/webhooks/${n}/trigger`)),ye=()=>Me(null,{onError(I){c({type:"warning",message:h(I)})}}),Ce=(0,b.useMutation)(I=>p("/admin/webhooks",I)),Pe=(0,b.useMutation)(({id:I,body:V})=>H(`/admin/webhooks/${I}`,V)),be=async I=>{if(a){Ce.mutate(me(I),{onSuccess({data:V}){c({type:"success",message:{id:"Settings.webhooks.created"}}),o(`/settings/webhooks/${V.data.id}`)},onError(V){c({type:"warning",message:h(V)})}});return}Pe.mutate({id:n,body:me(I)},{onSuccess(){O.invalidateQueries(["webhooks",n]),c({type:"success",message:{id:"notification.form.success.fields"}})},onError(V){c({type:"warning",message:h(V)})}})};return x||l?e.createElement(g.dO,null):e.createElement(T.o,null,e.createElement(g.SL,{name:"Webhooks"}),e.createElement(pe,{data:R,handleSubmit:be,triggerWebhook:ye,isCreating:a,isTriggering:ne,isTriggerIdle:ve,triggerResponse:ae?.data.data}))}},5722:function(G,P,t){t.r(P);var e=t(32735),T=t(45509),g=t(15062),b=t(30305),W=t(77476);const K=()=>{const U=(0,g.v9)(b._);return e.createElement(T.O4,{permissions:U.settings.webhooks.create},e.createElement(W.Z,null))};P.default=K},63939:function(G,P,t){t.r(P);var e=t(32735),T=t(45509),g=t(15062),b=t(30305),W=t(77476);const K=()=>{const U=(0,g.v9)(b._);return e.createElement(T.O4,{permissions:U.settings.webhooks.update},e.createElement(W.Z,null))};P.default=K},90333:function(G,P,t){t.d(P,{O:function(){return T}});var e=t(21428);const T=e.Wx},29439:function(G,P,t){t.d(P,{Z:function(){return g}});var e=t(74512);const T=b=>(0,e.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"1rem",height:"1rem",fill:"none",viewBox:"0 0 24 24",...b,children:(0,e.jsx)("path",{fill:"#212134",d:"M24 13.3a.2.2 0 0 1-.2.2H5.74l8.239 8.239a.2.2 0 0 1 0 .282L12.14 23.86a.2.2 0 0 1-.282 0L.14 12.14a.2.2 0 0 1 0-.282L11.86.14a.2.2 0 0 1 .282 0L13.98 1.98a.2.2 0 0 1 0 .282L5.74 10.5H23.8c.11 0 .2.09.2.2v2.6Z"})}),g=T}}]);
@@ -1,4 +1,4 @@
1
- "use strict";(self.webpackChunk_strapi_admin=self.webpackChunk_strapi_admin||[]).push([[4121],{93826:function(I,h,t){t.r(h),t.d(h,{default:function(){return me}});var e=t(32735),s=t(19565),c=t(15062),m=t(30305),g=t(94638),T=t(96709),D=t(27649),S=t(82055),P=t(99223),l=t(49372),y=t(41415),j=t(17e3),U=t(72850),_=t(56755),ee=t(73269),te=t(33827),K=t(94547),i=t(19786),V=t(82884),ne=t(3685),ae=t(35658),k=t(87933),E=t(74512),F=t(8471);const $=F.ZP.div`
1
+ "use strict";(self.webpackChunk_strapi_admin=self.webpackChunk_strapi_admin||[]).push([[4121],{93826:function(I,h,t){t.r(h),t.d(h,{default:function(){return me}});var e=t(32735),s=t(45509),c=t(15062),m=t(30305),g=t(94638),T=t(96709),D=t(27649),S=t(82055),P=t(99223),l=t(49372),y=t(41415),j=t(17e3),U=t(72850),_=t(56755),ee=t(73269),te=t(33827),K=t(94547),i=t(19786),V=t(82884),ne=t(3685),ae=t(35658),k=t(87933),E=t(74512),F=t(8471);const $=F.ZP.div`
2
2
  background: ${({theme:o})=>o.colors.danger500};
3
3
  border: none;
4
4
  border-radius: 16px;
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+
3
+ import { Combobox, ComboboxOption } from '@strapi/design-system';
4
+ import PropTypes from 'prop-types';
5
+ import { useIntl } from 'react-intl';
6
+
7
+ import { getDisplayName } from '../../../../../../../admin/src/content-manager/utils/getDisplayName';
8
+ import { useAdminUsers } from '../../../../../../../admin/src/hooks/useAdminUsers';
9
+
10
+ export const AssigneeFilter = ({ value, onChange }) => {
11
+ const { formatMessage } = useIntl();
12
+ const { users, isLoading } = useAdminUsers();
13
+
14
+ return (
15
+ <Combobox
16
+ value={value}
17
+ aria-label={formatMessage({
18
+ id: 'content-manager.components.Filters.usersSelect.label',
19
+ defaultMessage: 'Search and select an user to filter',
20
+ })}
21
+ onChange={onChange}
22
+ loading={isLoading}
23
+ >
24
+ {users.map((user) => {
25
+ return (
26
+ <ComboboxOption key={user.id} value={user.id.toString()}>
27
+ {getDisplayName(user, formatMessage)}
28
+ </ComboboxOption>
29
+ );
30
+ })}
31
+ </Combobox>
32
+ );
33
+ };
34
+
35
+ AssigneeFilter.propTypes = {
36
+ onChange: PropTypes.func.isRequired,
37
+ value: PropTypes.string,
38
+ };
39
+
40
+ AssigneeFilter.defaultProps = {
41
+ value: '',
42
+ };
@@ -0,0 +1,70 @@
1
+ import * as React from 'react';
2
+
3
+ import { Flex, Loader, SingleSelect, SingleSelectOption, Typography } from '@strapi/design-system';
4
+ import PropTypes from 'prop-types';
5
+ import { useIntl } from 'react-intl';
6
+
7
+ import { useReviewWorkflows } from '../../../../../pages/SettingsPage/pages/ReviewWorkflows/hooks/useReviewWorkflows';
8
+ import { getStageColorByHex } from '../../../../../pages/SettingsPage/pages/ReviewWorkflows/utils/colors';
9
+
10
+ export const StageFilter = ({ value, onChange, uid }) => {
11
+ const { formatMessage } = useIntl();
12
+ const {
13
+ workflows: [workflow],
14
+ isLoading,
15
+ } = useReviewWorkflows({ filters: { contentTypes: uid } });
16
+
17
+ return (
18
+ <SingleSelect
19
+ aria-label={formatMessage({
20
+ id: 'content-manager.components.Filters.reviewWorkflows.label',
21
+ defaultMessage: 'Search and select an workflow stage to filter',
22
+ })}
23
+ value={value}
24
+ onChange={onChange}
25
+ loading={isLoading}
26
+ // eslint-disable-next-line react/no-unstable-nested-components
27
+ customizeContent={() => (
28
+ <Flex as="span" justifyContent="space-between" alignItems="center" width="100%">
29
+ <Typography textColor="neutral800" ellipsis>
30
+ {value}
31
+ </Typography>
32
+ {isLoading ? <Loader small style={{ display: 'flex' }} /> : null}
33
+ </Flex>
34
+ )}
35
+ >
36
+ {(workflow?.stages ?? []).map(({ id, color, name }) => {
37
+ const { themeColorName } = getStageColorByHex(color);
38
+
39
+ return (
40
+ <SingleSelectOption
41
+ key={id}
42
+ startIcon={
43
+ <Flex
44
+ height={2}
45
+ background={color}
46
+ borderColor={themeColorName === 'neutral0' ? 'neutral150' : 'transparent'}
47
+ hasRadius
48
+ shrink={0}
49
+ width={2}
50
+ />
51
+ }
52
+ value={name}
53
+ >
54
+ {name}
55
+ </SingleSelectOption>
56
+ );
57
+ })}
58
+ </SingleSelect>
59
+ );
60
+ };
61
+
62
+ StageFilter.defaultProps = {
63
+ value: '',
64
+ };
65
+
66
+ StageFilter.propTypes = {
67
+ onChange: PropTypes.func.isRequired,
68
+ uid: PropTypes.string.isRequired,
69
+ value: PropTypes.string,
70
+ };
@@ -0,0 +1,71 @@
1
+ import { getTrad } from '../../../../../../../admin/src/content-manager/utils';
2
+
3
+ import { AssigneeFilter } from './AssigneeFilter';
4
+ import { StageFilter } from './StageFilter';
5
+
6
+ export const REVIEW_WORKFLOW_FILTERS = [
7
+ {
8
+ fieldSchema: {
9
+ type: 'relation',
10
+ mainField: {
11
+ name: 'name',
12
+
13
+ schema: {
14
+ type: 'string',
15
+ },
16
+ },
17
+ },
18
+
19
+ metadatas: {
20
+ customInput: StageFilter,
21
+
22
+ label: {
23
+ id: getTrad(`containers.ListPage.table-headers.reviewWorkflows.stage`),
24
+ defaultMessage: 'Review stage',
25
+ },
26
+ },
27
+
28
+ name: 'strapi_stage',
29
+ },
30
+
31
+ {
32
+ fieldSchema: {
33
+ type: 'relation',
34
+ mainField: {
35
+ name: 'id',
36
+
37
+ schema: {
38
+ type: 'int',
39
+ },
40
+ },
41
+ },
42
+
43
+ metadatas: {
44
+ customInput: AssigneeFilter,
45
+
46
+ customOperators: [
47
+ {
48
+ intlLabel: {
49
+ id: 'components.FilterOptions.FILTER_TYPES.$eq',
50
+ defaultMessage: 'is',
51
+ },
52
+ value: '$eq',
53
+ },
54
+ {
55
+ intlLabel: {
56
+ id: 'components.FilterOptions.FILTER_TYPES.$ne',
57
+ defaultMessage: 'is not',
58
+ },
59
+ value: '$ne',
60
+ },
61
+ ],
62
+
63
+ label: {
64
+ id: getTrad(`containers.ListPage.table-headers.reviewWorkflows.assignee.label`),
65
+ defaultMessage: 'Assignee',
66
+ },
67
+ },
68
+
69
+ name: 'strapi_assignee',
70
+ },
71
+ ];
@@ -1,238 +1,30 @@
1
1
  import React from 'react';
2
2
 
3
- import { Flex, Loader, SingleSelect, SingleSelectOption, Typography } from '@strapi/design-system';
4
- import {
5
- useAPIErrorHandler,
6
- useCMEditViewDataManager,
7
- useFetchClient,
8
- useNotification,
9
- } from '@strapi/helper-plugin';
10
- import { useIntl } from 'react-intl';
11
- import { useMutation } from 'react-query';
3
+ import { useCMEditViewDataManager } from '@strapi/helper-plugin';
12
4
 
13
5
  import { Information } from '../../../../../../admin/src/content-manager/pages/EditView/Information';
14
- import { useLicenseLimits } from '../../../../hooks/useLicenseLimits';
15
- import * as LimitsModal from '../../../../pages/SettingsPage/pages/ReviewWorkflows/components/LimitsModal';
16
- import {
17
- CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME,
18
- CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME,
19
- } from '../../../../pages/SettingsPage/pages/ReviewWorkflows/constants';
20
- import { useReviewWorkflows } from '../../../../pages/SettingsPage/pages/ReviewWorkflows/hooks/useReviewWorkflows';
21
- import { getStageColorByHex } from '../../../../pages/SettingsPage/pages/ReviewWorkflows/utils/colors';
22
6
 
23
- const ATTRIBUTE_NAME = 'strapi_stage';
7
+ import { AssigneeSelect } from './components/AssigneeSelect';
8
+ import { StageSelect } from './components/StageSelect';
24
9
 
25
10
  export function InformationBoxEE() {
26
11
  const {
27
- initialData,
28
12
  isCreatingEntry,
29
- layout: { uid, options },
30
- isSingleType,
31
- onChange,
13
+ layout: { options },
32
14
  } = useCMEditViewDataManager();
33
- const { put } = useFetchClient();
34
- // it is possible to rely on initialData here, because it always will
35
- // be updated at the same time when modifiedData is updated, otherwise
36
- // the entity is flagged as modified
37
- const activeWorkflowStage = initialData?.[ATTRIBUTE_NAME] ?? null;
38
- const hasReviewWorkflowsEnabled = options?.reviewWorkflows ?? false;
39
- const { formatMessage } = useIntl();
40
- const { formatAPIError } = useAPIErrorHandler();
41
- const toggleNotification = useNotification();
42
- const { getFeature } = useLicenseLimits();
43
- const [showLimitModal, setShowLimitModal] = React.useState(false);
44
-
45
- const {
46
- meta,
47
- workflows: [workflow],
48
- isLoading: isWorkflowLoading,
49
- } = useReviewWorkflows({ filters: { contentTypes: uid } });
50
-
51
- const { error, isLoading, mutateAsync } = useMutation(
52
- async ({ entityId, stageId, uid }) => {
53
- const typeSlug = isSingleType ? 'single-types' : 'collection-types';
54
-
55
- const {
56
- data: { data: createdEntity },
57
- } = await put(`/admin/content-manager/${typeSlug}/${uid}/${entityId}/stage`, {
58
- data: { id: stageId },
59
- });
60
-
61
- // initialData and modifiedData have to stay in sync, otherwise the entity would be flagged
62
- // as modified, which is what the boolean flag is for
63
- onChange({ target: { name: ATTRIBUTE_NAME, value: createdEntity[ATTRIBUTE_NAME] } }, true);
64
-
65
- return createdEntity;
66
- },
67
- {
68
- onSuccess() {
69
- toggleNotification({
70
- type: 'success',
71
- message: {
72
- id: 'content-manager.reviewWorkflows.stage.notification.saved',
73
- defaultMessage: 'Review stage updated',
74
- },
75
- });
76
- },
77
- }
78
- );
79
-
80
- const limits = getFeature('review-workflows');
81
- const formattedError = (error && formatAPIError(error)) || null;
82
-
83
- const handleStageChange = async ({ value: stageId }) => {
84
- try {
85
- /**
86
- * If the current license has a limit:
87
- * check if the total count of workflows exceeds that limit and display
88
- * the limits modal.
89
- *
90
- * If the current license does not have a limit (e.g. offline license):
91
- * do nothing (for now).
92
- *
93
- */
94
15
 
95
- if (
96
- limits?.[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME] &&
97
- parseInt(limits[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME], 10) < meta.workflowCount
98
- ) {
99
- setShowLimitModal('workflow');
100
-
101
- /**
102
- * If the current license has a limit:
103
- * check if the total count of stages exceeds that limit and display
104
- * the limits modal.
105
- *
106
- * If the current license does not have a limit (e.g. offline license):
107
- * do nothing (for now).
108
- *
109
- */
110
- } else if (
111
- limits?.[CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME] &&
112
- parseInt(limits[CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME], 10) <
113
- workflow.stages.length
114
- ) {
115
- setShowLimitModal('stage');
116
- } else {
117
- await mutateAsync({
118
- entityId: initialData.id,
119
- stageId,
120
- uid,
121
- });
122
- }
123
- } catch (error) {
124
- // react-query@v3: the error doesn't have to be handled here
125
- // see: https://github.com/TanStack/query/issues/121
126
- }
127
- };
128
-
129
- const { themeColorName } = activeWorkflowStage?.color
130
- ? getStageColorByHex(activeWorkflowStage?.color)
131
- : {};
16
+ const hasReviewWorkflowsEnabled = options?.reviewWorkflows ?? false;
132
17
 
133
18
  return (
134
19
  <Information.Root>
135
20
  <Information.Title />
136
-
137
21
  {hasReviewWorkflowsEnabled && !isCreatingEntry && (
138
- <SingleSelect
139
- error={formattedError}
140
- name={ATTRIBUTE_NAME}
141
- id={ATTRIBUTE_NAME}
142
- value={activeWorkflowStage?.id}
143
- onChange={(value) => handleStageChange({ value })}
144
- label={formatMessage({
145
- id: 'content-manager.reviewWorkflows.stage.label',
146
- defaultMessage: 'Review stage',
147
- })}
148
- startIcon={
149
- <Flex
150
- as="span"
151
- height={2}
152
- background={activeWorkflowStage?.color}
153
- borderColor={themeColorName === 'neutral0' ? 'neutral150' : 'transparent'}
154
- hasRadius
155
- shrink={0}
156
- width={2}
157
- marginRight="-3px"
158
- />
159
- }
160
- // eslint-disable-next-line react/no-unstable-nested-components
161
- customizeContent={() => (
162
- <Flex as="span" justifyContent="space-between" alignItems="center" width="100%">
163
- <Typography textColor="neutral800" ellipsis>
164
- {activeWorkflowStage?.name}
165
- </Typography>
166
- {isWorkflowLoading || isLoading ? <Loader small style={{ display: 'flex' }} /> : null}
167
- </Flex>
168
- )}
169
- >
170
- {workflow
171
- ? workflow.stages.map(({ id, color, name }) => {
172
- const { themeColorName } = getStageColorByHex(color);
173
-
174
- return (
175
- <SingleSelectOption
176
- startIcon={
177
- <Flex
178
- height={2}
179
- background={color}
180
- borderColor={themeColorName === 'neutral0' ? 'neutral150' : 'transparent'}
181
- hasRadius
182
- shrink={0}
183
- width={2}
184
- />
185
- }
186
- value={id}
187
- textValue={name}
188
- >
189
- {name}
190
- </SingleSelectOption>
191
- );
192
- })
193
- : []}
194
- </SingleSelect>
22
+ <>
23
+ <StageSelect />
24
+ <AssigneeSelect />
25
+ </>
195
26
  )}
196
-
197
27
  <Information.Body />
198
-
199
- <LimitsModal.Root
200
- isOpen={showLimitModal === 'workflow'}
201
- onClose={() => setShowLimitModal(false)}
202
- >
203
- <LimitsModal.Title>
204
- {formatMessage({
205
- id: 'content-manager.reviewWorkflows.workflows.limit.title',
206
- defaultMessage: 'You’ve reached the limit of workflows in your plan',
207
- })}
208
- </LimitsModal.Title>
209
-
210
- <LimitsModal.Body>
211
- {formatMessage({
212
- id: 'content-manager.reviewWorkflows.workflows.limit.body',
213
- defaultMessage: 'Delete a workflow or contact Sales to enable more workflows.',
214
- })}
215
- </LimitsModal.Body>
216
- </LimitsModal.Root>
217
-
218
- <LimitsModal.Root
219
- isOpen={showLimitModal === 'stage'}
220
- onClose={() => setShowLimitModal(false)}
221
- >
222
- <LimitsModal.Title>
223
- {formatMessage({
224
- id: 'content-manager.reviewWorkflows.stages.limit.title',
225
- defaultMessage: 'You have reached the limit of stages for this workflow in your plan',
226
- })}
227
- </LimitsModal.Title>
228
-
229
- <LimitsModal.Body>
230
- {formatMessage({
231
- id: 'content-manager.reviewWorkflows.stages.limit.body',
232
- defaultMessage: 'Try deleting some stages or contact Sales to enable more stages.',
233
- })}
234
- </LimitsModal.Body>
235
- </LimitsModal.Root>
236
28
  </Information.Root>
237
29
  );
238
30
  }
@@ -0,0 +1,147 @@
1
+ import * as React from 'react';
2
+
3
+ import { Combobox, ComboboxOption, Field, Flex, Loader, Typography } from '@strapi/design-system';
4
+ import {
5
+ useCMEditViewDataManager,
6
+ useAPIErrorHandler,
7
+ useFetchClient,
8
+ useNotification,
9
+ useRBAC,
10
+ } from '@strapi/helper-plugin';
11
+ import { useIntl } from 'react-intl';
12
+ import { useMutation } from 'react-query';
13
+ import { useSelector } from 'react-redux';
14
+
15
+ import { getDisplayName } from '../../../../../../../../admin/src/content-manager/utils';
16
+ import { useAdminUsers } from '../../../../../../../../admin/src/hooks/useAdminUsers';
17
+ import { selectAdminPermissions } from '../../../../../../../../admin/src/pages/App/selectors';
18
+ import { ASSIGNEE_ATTRIBUTE_NAME } from '../../constants';
19
+
20
+ export function AssigneeSelect() {
21
+ const {
22
+ initialData,
23
+ layout: { uid },
24
+ isSingleType,
25
+ onChange,
26
+ } = useCMEditViewDataManager();
27
+ const permissions = useSelector(selectAdminPermissions);
28
+ const { formatMessage } = useIntl();
29
+ const { formatAPIError } = useAPIErrorHandler();
30
+ const toggleNotification = useNotification();
31
+ const { put } = useFetchClient();
32
+ const {
33
+ allowedActions: { canReadUsers },
34
+ } = useRBAC({
35
+ readUsers: permissions.settings.users.read,
36
+ });
37
+ const { users, isLoading, isError } = useAdminUsers(
38
+ {},
39
+ {
40
+ enabled: canReadUsers,
41
+ }
42
+ );
43
+
44
+ const currentAssignee = initialData?.[ASSIGNEE_ATTRIBUTE_NAME] ?? null;
45
+
46
+ const handleChange = async ({ value: assigneeId }) => {
47
+ mutation.mutate({
48
+ entityId: initialData.id,
49
+ assigneeId: parseInt(assigneeId, 10),
50
+ uid,
51
+ });
52
+ };
53
+
54
+ const mutation = useMutation(
55
+ async ({ entityId, assigneeId, uid }) => {
56
+ const typeSlug = isSingleType ? 'single-types' : 'collection-types';
57
+
58
+ const {
59
+ data: { data: createdEntity },
60
+ } = await put(`/admin/content-manager/${typeSlug}/${uid}/${entityId}/assignee`, {
61
+ data: { id: assigneeId },
62
+ });
63
+
64
+ // initialData and modifiedData have to stay in sync, otherwise the entity would be flagged
65
+ // as modified, which is what the boolean flag is for
66
+ onChange(
67
+ {
68
+ target: { name: ASSIGNEE_ATTRIBUTE_NAME, value: createdEntity[ASSIGNEE_ATTRIBUTE_NAME] },
69
+ },
70
+ true
71
+ );
72
+
73
+ return createdEntity;
74
+ },
75
+ {
76
+ onSuccess() {
77
+ toggleNotification({
78
+ type: 'success',
79
+ message: {
80
+ id: 'content-manager.reviewWorkflows.assignee.notification.saved',
81
+ defaultMessage: 'Assignee updated',
82
+ },
83
+ });
84
+ },
85
+ }
86
+ );
87
+
88
+ return (
89
+ <Field name={ASSIGNEE_ATTRIBUTE_NAME} id={ASSIGNEE_ATTRIBUTE_NAME}>
90
+ <Flex direction="column" gap={2} alignItems="stretch">
91
+ <Combobox
92
+ clearLabel={formatMessage({
93
+ id: 'content-manager.reviewWorkflows.assignee.clear',
94
+ defaultMessage: 'Clear assignee',
95
+ })}
96
+ error={
97
+ (isError &&
98
+ canReadUsers &&
99
+ formatMessage({
100
+ id: 'content-manager.reviewWorkflows.assignee.error',
101
+ defaultMessage: 'An error occurred while fetching users',
102
+ })) ||
103
+ (mutation.error && formatAPIError(mutation.error))
104
+ }
105
+ disabled={!isLoading && users.length === 0}
106
+ name={ASSIGNEE_ATTRIBUTE_NAME}
107
+ id={ASSIGNEE_ATTRIBUTE_NAME}
108
+ value={currentAssignee ? currentAssignee.id : null}
109
+ onChange={(value) => handleChange({ value })}
110
+ onClear={() => handleChange({ value: null })}
111
+ placeholder={formatMessage({
112
+ id: 'content-manager.reviewWorkflows.assignee.placeholder',
113
+ defaultMessage: 'Select …',
114
+ })}
115
+ label={formatMessage({
116
+ id: 'content-manager.reviewWorkflows.assignee.label',
117
+ defaultMessage: 'Assignee',
118
+ })}
119
+ // eslint-disable-next-line react/no-unstable-nested-components
120
+ customizeContent={() => (
121
+ <Flex as="span" justifyContent="space-between" alignItems="center" width="100%">
122
+ <Typography textColor="neutral800" ellipsis>
123
+ {currentAssignee ? getDisplayName(currentAssignee, formatMessage) : null}
124
+ </Typography>
125
+
126
+ {isLoading || mutation.isLoading ? (
127
+ <Loader small style={{ display: 'flex' }} />
128
+ ) : null}
129
+ </Flex>
130
+ )}
131
+ >
132
+ {users.map((user) => {
133
+ return (
134
+ <ComboboxOption
135
+ key={user.id}
136
+ value={user.id}
137
+ textValue={getDisplayName(user, formatMessage)}
138
+ >
139
+ {getDisplayName(user, formatMessage)}
140
+ </ComboboxOption>
141
+ );
142
+ })}
143
+ </Combobox>
144
+ </Flex>
145
+ </Field>
146
+ );
147
+ }