@strapi/content-manager 0.0.0-experimental.a65a85fdea97faae8679d3ffc5f9d79af61abd26 → 0.0.0-experimental.a687a6977f91492ccfc6771bf398a5236ece3c94

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 (260) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/{CardDragPreview-DSVYodBX.js → CardDragPreview-C0QyJgRA.js} +10 -14
  3. package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -0
  4. package/dist/_chunks/{CardDragPreview-ikSG4M46.mjs → CardDragPreview-DOxamsuj.mjs} +7 -9
  5. package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -0
  6. package/dist/_chunks/{ComponentConfigurationPage-43KmCNQE.js → ComponentConfigurationPage-BebDdCkl.js} +4 -4
  7. package/dist/_chunks/{ComponentConfigurationPage-43KmCNQE.js.map → ComponentConfigurationPage-BebDdCkl.js.map} +1 -1
  8. package/dist/_chunks/{ComponentConfigurationPage--2aLCv-G.mjs → ComponentConfigurationPage-XdGcgtZh.mjs} +4 -4
  9. package/dist/_chunks/{ComponentConfigurationPage--2aLCv-G.mjs.map → ComponentConfigurationPage-XdGcgtZh.mjs.map} +1 -1
  10. package/dist/_chunks/{ComponentIcon-BBQsYCVn.js → ComponentIcon-BXdiCGQp.js} +8 -2
  11. package/dist/_chunks/ComponentIcon-BXdiCGQp.js.map +1 -0
  12. package/dist/_chunks/{ComponentIcon-BOFnK76n.mjs → ComponentIcon-u4bIXTFY.mjs} +9 -3
  13. package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -0
  14. package/dist/_chunks/{EditConfigurationPage-CUcGHHvQ.mjs → EditConfigurationPage-DaNf9MoK.mjs} +4 -4
  15. package/dist/_chunks/{EditConfigurationPage-CUcGHHvQ.mjs.map → EditConfigurationPage-DaNf9MoK.mjs.map} +1 -1
  16. package/dist/_chunks/{EditConfigurationPage-BfFzJ4Br.js → EditConfigurationPage-sdGi-bna.js} +4 -4
  17. package/dist/_chunks/{EditConfigurationPage-BfFzJ4Br.js.map → EditConfigurationPage-sdGi-bna.js.map} +1 -1
  18. package/dist/_chunks/{EditViewPage-CzOT5Kpj.js → EditViewPage-BRA-JSnw.js} +101 -52
  19. package/dist/_chunks/EditViewPage-BRA-JSnw.js.map +1 -0
  20. package/dist/_chunks/EditViewPage-DtbTsNeX.mjs +254 -0
  21. package/dist/_chunks/EditViewPage-DtbTsNeX.mjs.map +1 -0
  22. package/dist/_chunks/{Field-Dlh0uGnL.mjs → Field-CDmB9zqh.mjs} +1075 -812
  23. package/dist/_chunks/Field-CDmB9zqh.mjs.map +1 -0
  24. package/dist/_chunks/{Field-Caef4JjM.js → Field-DoVRA4co.js} +1120 -858
  25. package/dist/_chunks/Field-DoVRA4co.js.map +1 -0
  26. package/dist/_chunks/{Form-BzuAjtRq.js → Form-BEh514bg.js} +69 -49
  27. package/dist/_chunks/Form-BEh514bg.js.map +1 -0
  28. package/dist/_chunks/{Form-EnaQL_6L.mjs → Form-Cle2X-4n.mjs} +70 -49
  29. package/dist/_chunks/Form-Cle2X-4n.mjs.map +1 -0
  30. package/dist/_chunks/{History-C17LiyRg.js → History-BsPXl1XH.js} +182 -146
  31. package/dist/_chunks/History-BsPXl1XH.js.map +1 -0
  32. package/dist/_chunks/{History-D6sbCJvo.mjs → History-ktAPcvHJ.mjs} +182 -145
  33. package/dist/_chunks/History-ktAPcvHJ.mjs.map +1 -0
  34. package/dist/_chunks/{ListConfigurationPage-Ce4qs7qE.mjs → ListConfigurationPage-BNAS_v2s.mjs} +71 -60
  35. package/dist/_chunks/ListConfigurationPage-BNAS_v2s.mjs.map +1 -0
  36. package/dist/_chunks/{ListConfigurationPage-Dks5SX6f.js → ListConfigurationPage-CN1-7Pgi.js} +73 -63
  37. package/dist/_chunks/ListConfigurationPage-CN1-7Pgi.js.map +1 -0
  38. package/dist/_chunks/{ListViewPage-Be7S5aKL.mjs → ListViewPage-B15c_0Vt.mjs} +143 -139
  39. package/dist/_chunks/ListViewPage-B15c_0Vt.mjs.map +1 -0
  40. package/dist/_chunks/{ListViewPage-BwrZrPsh.js → ListViewPage-BUKFOJuS.js} +146 -142
  41. package/dist/_chunks/ListViewPage-BUKFOJuS.js.map +1 -0
  42. package/dist/_chunks/{NoContentTypePage-CIPmYQMm.mjs → NoContentTypePage-CAgdmhlo.mjs} +7 -7
  43. package/dist/_chunks/NoContentTypePage-CAgdmhlo.mjs.map +1 -0
  44. package/dist/_chunks/{NoContentTypePage-Cu5r1-JT.js → NoContentTypePage-Cs7Kk9EW.js} +5 -5
  45. package/dist/_chunks/NoContentTypePage-Cs7Kk9EW.js.map +1 -0
  46. package/dist/_chunks/{NoPermissionsPage-C-j6TEUF.js → NoPermissionsPage-DRPnEq9t.js} +4 -5
  47. package/dist/_chunks/NoPermissionsPage-DRPnEq9t.js.map +1 -0
  48. package/dist/_chunks/{NoPermissionsPage-DhJ7LYrr.mjs → NoPermissionsPage-JxX4Y4RJ.mjs} +5 -6
  49. package/dist/_chunks/NoPermissionsPage-JxX4Y4RJ.mjs.map +1 -0
  50. package/dist/_chunks/Preview-BKuVG1dV.js +286 -0
  51. package/dist/_chunks/Preview-BKuVG1dV.js.map +1 -0
  52. package/dist/_chunks/Preview-CQlTtbLc.mjs +267 -0
  53. package/dist/_chunks/Preview-CQlTtbLc.mjs.map +1 -0
  54. package/dist/_chunks/{Relations-CY7AtkDA.mjs → Relations-DMQ93R3L.mjs} +135 -89
  55. package/dist/_chunks/Relations-DMQ93R3L.mjs.map +1 -0
  56. package/dist/_chunks/{Relations-Czs-uZ-s.js → Relations-DTEGSaM_.js} +138 -93
  57. package/dist/_chunks/Relations-DTEGSaM_.js.map +1 -0
  58. package/dist/_chunks/{en-MBPul9Su.mjs → en-CfIXaZf9.mjs} +36 -17
  59. package/dist/_chunks/{en-MBPul9Su.mjs.map → en-CfIXaZf9.mjs.map} +1 -1
  60. package/dist/_chunks/{en-C-V1_90f.js → en-DTWPCdTS.js} +36 -17
  61. package/dist/_chunks/{en-C-V1_90f.js.map → en-DTWPCdTS.js.map} +1 -1
  62. package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
  63. package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
  64. package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
  65. package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
  66. package/dist/_chunks/{fr-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
  67. package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
  68. package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
  69. package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
  70. package/dist/_chunks/{index-DNVx8ssZ.mjs → index-BdUq-Dtg.mjs} +1839 -831
  71. package/dist/_chunks/index-BdUq-Dtg.mjs.map +1 -0
  72. package/dist/_chunks/{index-X_2tafck.js → index-DjV7tyGu.js} +1826 -818
  73. package/dist/_chunks/index-DjV7tyGu.js.map +1 -0
  74. package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
  75. package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
  76. package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
  77. package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
  78. package/dist/_chunks/{layout-Dnh0PNp9.mjs → layout-BJ8CpEJu.mjs} +47 -29
  79. package/dist/_chunks/layout-BJ8CpEJu.mjs.map +1 -0
  80. package/dist/_chunks/{layout-dBc7wN7L.js → layout-Cx9LHtH5.js} +47 -31
  81. package/dist/_chunks/layout-Cx9LHtH5.js.map +1 -0
  82. package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
  83. package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
  84. package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
  85. package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
  86. package/dist/_chunks/{relations-4pHtBrHJ.js → relations-5bc76OJz.js} +6 -7
  87. package/dist/_chunks/relations-5bc76OJz.js.map +1 -0
  88. package/dist/_chunks/{relations-Dx7tMKJN.mjs → relations-BeezTo41.mjs} +6 -7
  89. package/dist/_chunks/relations-BeezTo41.mjs.map +1 -0
  90. package/dist/_chunks/useDebounce-CtcjDB3L.js +28 -0
  91. package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
  92. package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
  93. package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
  94. package/dist/_chunks/useDragAndDrop-DdHgKsqq.mjs.map +1 -1
  95. package/dist/_chunks/useDragAndDrop-J0TUUbR6.js.map +1 -1
  96. package/dist/admin/index.js +3 -1
  97. package/dist/admin/index.js.map +1 -1
  98. package/dist/admin/index.mjs +9 -7
  99. package/dist/admin/src/components/ComponentIcon.d.ts +6 -3
  100. package/dist/admin/src/content-manager.d.ts +3 -3
  101. package/dist/admin/src/exports.d.ts +2 -1
  102. package/dist/admin/src/history/components/VersionInputRenderer.d.ts +1 -1
  103. package/dist/admin/src/history/index.d.ts +3 -0
  104. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  105. package/dist/admin/src/hooks/useDocument.d.ts +37 -9
  106. package/dist/admin/src/hooks/useDocumentActions.d.ts +24 -3
  107. package/dist/admin/src/hooks/useDocumentLayout.d.ts +2 -2
  108. package/dist/admin/src/hooks/useDragAndDrop.d.ts +4 -4
  109. package/dist/admin/src/hooks/useKeyboardDragAndDrop.d.ts +1 -1
  110. package/dist/admin/src/index.d.ts +1 -0
  111. package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
  112. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +11 -4
  113. package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +2 -2
  114. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.d.ts +3 -3
  115. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
  116. package/dist/admin/src/pages/EditView/components/FormInputs/Component/Input.d.ts +2 -2
  117. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.d.ts +3 -5
  118. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +1 -1
  119. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +30 -18
  120. package/dist/admin/src/pages/EditView/components/FormInputs/UID.d.ts +2 -2
  121. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +3 -49
  122. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/Field.d.ts +2 -2
  123. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  124. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +16 -53
  125. package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
  126. package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +2 -10
  127. package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
  128. package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
  129. package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +9 -26
  130. package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
  131. package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
  132. package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
  133. package/dist/admin/src/preview/constants.d.ts +1 -0
  134. package/dist/admin/src/preview/index.d.ts +4 -0
  135. package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
  136. package/dist/admin/src/preview/routes.d.ts +3 -0
  137. package/dist/admin/src/preview/services/preview.d.ts +3 -0
  138. package/dist/admin/src/router.d.ts +1 -1
  139. package/dist/admin/src/services/api.d.ts +2 -3
  140. package/dist/admin/src/services/components.d.ts +2 -2
  141. package/dist/admin/src/services/contentTypes.d.ts +5 -5
  142. package/dist/admin/src/services/documents.d.ts +31 -20
  143. package/dist/admin/src/services/init.d.ts +2 -2
  144. package/dist/admin/src/services/relations.d.ts +3 -3
  145. package/dist/admin/src/services/uid.d.ts +3 -3
  146. package/dist/admin/src/utils/api.d.ts +4 -18
  147. package/dist/admin/src/utils/validation.d.ts +5 -7
  148. package/dist/server/index.js +1008 -594
  149. package/dist/server/index.js.map +1 -1
  150. package/dist/server/index.mjs +1014 -600
  151. package/dist/server/index.mjs.map +1 -1
  152. package/dist/server/src/bootstrap.d.ts.map +1 -1
  153. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  154. package/dist/server/src/controllers/index.d.ts.map +1 -1
  155. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  156. package/dist/server/src/controllers/single-types.d.ts.map +1 -1
  157. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  158. package/dist/server/src/controllers/utils/metadata.d.ts +22 -0
  159. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -0
  160. package/dist/server/src/controllers/validation/dimensions.d.ts +11 -0
  161. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -0
  162. package/dist/server/src/controllers/validation/index.d.ts +1 -1
  163. package/dist/server/src/history/services/history.d.ts +2 -4
  164. package/dist/server/src/history/services/history.d.ts.map +1 -1
  165. package/dist/server/src/history/services/index.d.ts +6 -2
  166. package/dist/server/src/history/services/index.d.ts.map +1 -1
  167. package/dist/server/src/history/services/lifecycles.d.ts +9 -0
  168. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -0
  169. package/dist/server/src/history/services/utils.d.ts +41 -9
  170. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  171. package/dist/server/src/history/utils.d.ts +6 -2
  172. package/dist/server/src/history/utils.d.ts.map +1 -1
  173. package/dist/server/src/index.d.ts +21 -42
  174. package/dist/server/src/index.d.ts.map +1 -1
  175. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  176. package/dist/server/src/preview/constants.d.ts +2 -0
  177. package/dist/server/src/preview/constants.d.ts.map +1 -0
  178. package/dist/server/src/preview/controllers/index.d.ts +2 -0
  179. package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
  180. package/dist/server/src/preview/controllers/preview.d.ts +13 -0
  181. package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
  182. package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
  183. package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
  184. package/dist/server/src/preview/index.d.ts +4 -0
  185. package/dist/server/src/preview/index.d.ts.map +1 -0
  186. package/dist/server/src/preview/routes/index.d.ts +8 -0
  187. package/dist/server/src/preview/routes/index.d.ts.map +1 -0
  188. package/dist/server/src/preview/routes/preview.d.ts +4 -0
  189. package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
  190. package/dist/server/src/preview/services/index.d.ts +15 -0
  191. package/dist/server/src/preview/services/index.d.ts.map +1 -0
  192. package/dist/server/src/preview/services/preview-config.d.ts +30 -0
  193. package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
  194. package/dist/server/src/preview/services/preview.d.ts +12 -0
  195. package/dist/server/src/preview/services/preview.d.ts.map +1 -0
  196. package/dist/server/src/preview/utils.d.ts +18 -0
  197. package/dist/server/src/preview/utils.d.ts.map +1 -0
  198. package/dist/server/src/routes/index.d.ts.map +1 -1
  199. package/dist/server/src/services/document-manager.d.ts +13 -12
  200. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  201. package/dist/server/src/services/document-metadata.d.ts +14 -35
  202. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  203. package/dist/server/src/services/index.d.ts +21 -42
  204. package/dist/server/src/services/index.d.ts.map +1 -1
  205. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  206. package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
  207. package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
  208. package/dist/server/src/services/utils/populate.d.ts +8 -1
  209. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  210. package/dist/server/src/utils/index.d.ts +2 -0
  211. package/dist/server/src/utils/index.d.ts.map +1 -1
  212. package/dist/shared/contracts/collection-types.d.ts +17 -7
  213. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  214. package/dist/shared/contracts/index.d.ts +1 -0
  215. package/dist/shared/contracts/index.d.ts.map +1 -1
  216. package/dist/shared/contracts/preview.d.ts +27 -0
  217. package/dist/shared/contracts/preview.d.ts.map +1 -0
  218. package/dist/shared/contracts/relations.d.ts +2 -2
  219. package/dist/shared/contracts/relations.d.ts.map +1 -1
  220. package/dist/shared/index.js +4 -0
  221. package/dist/shared/index.js.map +1 -1
  222. package/dist/shared/index.mjs +4 -0
  223. package/dist/shared/index.mjs.map +1 -1
  224. package/package.json +19 -20
  225. package/dist/_chunks/CardDragPreview-DSVYodBX.js.map +0 -1
  226. package/dist/_chunks/CardDragPreview-ikSG4M46.mjs.map +0 -1
  227. package/dist/_chunks/ComponentIcon-BBQsYCVn.js.map +0 -1
  228. package/dist/_chunks/ComponentIcon-BOFnK76n.mjs.map +0 -1
  229. package/dist/_chunks/EditViewPage-Bm8lgcm6.mjs +0 -203
  230. package/dist/_chunks/EditViewPage-Bm8lgcm6.mjs.map +0 -1
  231. package/dist/_chunks/EditViewPage-CzOT5Kpj.js.map +0 -1
  232. package/dist/_chunks/Field-Caef4JjM.js.map +0 -1
  233. package/dist/_chunks/Field-Dlh0uGnL.mjs.map +0 -1
  234. package/dist/_chunks/Form-BzuAjtRq.js.map +0 -1
  235. package/dist/_chunks/Form-EnaQL_6L.mjs.map +0 -1
  236. package/dist/_chunks/History-C17LiyRg.js.map +0 -1
  237. package/dist/_chunks/History-D6sbCJvo.mjs.map +0 -1
  238. package/dist/_chunks/ListConfigurationPage-Ce4qs7qE.mjs.map +0 -1
  239. package/dist/_chunks/ListConfigurationPage-Dks5SX6f.js.map +0 -1
  240. package/dist/_chunks/ListViewPage-Be7S5aKL.mjs.map +0 -1
  241. package/dist/_chunks/ListViewPage-BwrZrPsh.js.map +0 -1
  242. package/dist/_chunks/NoContentTypePage-CIPmYQMm.mjs.map +0 -1
  243. package/dist/_chunks/NoContentTypePage-Cu5r1-JT.js.map +0 -1
  244. package/dist/_chunks/NoPermissionsPage-C-j6TEUF.js.map +0 -1
  245. package/dist/_chunks/NoPermissionsPage-DhJ7LYrr.mjs.map +0 -1
  246. package/dist/_chunks/Relations-CY7AtkDA.mjs.map +0 -1
  247. package/dist/_chunks/Relations-Czs-uZ-s.js.map +0 -1
  248. package/dist/_chunks/index-DNVx8ssZ.mjs.map +0 -1
  249. package/dist/_chunks/index-X_2tafck.js.map +0 -1
  250. package/dist/_chunks/layout-Dnh0PNp9.mjs.map +0 -1
  251. package/dist/_chunks/layout-dBc7wN7L.js.map +0 -1
  252. package/dist/_chunks/relations-4pHtBrHJ.js.map +0 -1
  253. package/dist/_chunks/relations-Dx7tMKJN.mjs.map +0 -1
  254. package/dist/_chunks/urls-CbOsUOoW.mjs +0 -7
  255. package/dist/_chunks/urls-CbOsUOoW.mjs.map +0 -1
  256. package/dist/_chunks/urls-DzZya_gm.js +0 -6
  257. package/dist/_chunks/urls-DzZya_gm.js.map +0 -1
  258. package/dist/server/src/controllers/utils/dimensions.d.ts +0 -5
  259. package/dist/server/src/controllers/utils/dimensions.d.ts.map +0 -1
  260. package/strapi-server.js +0 -3
@@ -2,15 +2,14 @@
2
2
  const Icons = require("@strapi/icons");
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const strapiAdmin = require("@strapi/admin/strapi-admin");
5
- const qs = require("qs");
6
- const reactIntl = require("react-intl");
7
- const reactRouterDom = require("react-router-dom");
8
5
  const React = require("react");
9
6
  const designSystem = require("@strapi/design-system");
10
- const styled = require("styled-components");
7
+ const mapValues = require("lodash/fp/mapValues");
8
+ const reactIntl = require("react-intl");
9
+ const reactRouterDom = require("react-router-dom");
10
+ const styledComponents = require("styled-components");
11
11
  const yup = require("yup");
12
- const react = require("@reduxjs/toolkit/query/react");
13
- const axios = require("axios");
12
+ const qs = require("qs");
14
13
  const pipe = require("lodash/fp/pipe");
15
14
  const dateFns = require("date-fns");
16
15
  const toolkit = require("@reduxjs/toolkit");
@@ -34,7 +33,7 @@ function _interopNamespace(e) {
34
33
  return Object.freeze(n);
35
34
  }
36
35
  const React__namespace = /* @__PURE__ */ _interopNamespace(React);
37
- const styled__default = /* @__PURE__ */ _interopDefault(styled);
36
+ const mapValues__default = /* @__PURE__ */ _interopDefault(mapValues);
38
37
  const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
39
38
  const pipe__default = /* @__PURE__ */ _interopDefault(pipe);
40
39
  const __variableDynamicImportRuntimeHelper = (glob, path) => {
@@ -73,42 +72,6 @@ const useInjectionZone = (area) => {
73
72
  const [page, position] = area.split(".");
74
73
  return contentManagerPlugin.getInjectedComponents(page, position);
75
74
  };
76
- const HistoryAction = ({ model, document }) => {
77
- const { formatMessage } = reactIntl.useIntl();
78
- const [{ query }] = strapiAdmin.useQueryParams();
79
- const navigate = reactRouterDom.useNavigate();
80
- const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
81
- if (!window.strapi.features.isEnabled("cms-content-history")) {
82
- return null;
83
- }
84
- return {
85
- icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
86
- label: formatMessage({
87
- id: "content-manager.history.document-action",
88
- defaultMessage: "Content History"
89
- }),
90
- onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
91
- disabled: (
92
- /**
93
- * The user is creating a new document.
94
- * It hasn't been saved yet, so there's no history to go to
95
- */
96
- !document || /**
97
- * The document has been created but the current dimension has never been saved.
98
- * For example, the user is creating a new locale in an existing document,
99
- * so there's no history for the document in that locale
100
- */
101
- !document.id || /**
102
- * History is only available for content types created by the user.
103
- * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
104
- * which start with `admin::` or `plugin::`
105
- */
106
- !model.startsWith("api::")
107
- ),
108
- position: "header"
109
- };
110
- };
111
- HistoryAction.type = "history";
112
75
  const ID = "id";
113
76
  const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
114
77
  const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
@@ -160,6 +123,7 @@ const DocumentRBAC = ({ children, permissions }) => {
160
123
  if (!slug) {
161
124
  throw new Error("Cannot find the slug param in the URL");
162
125
  }
126
+ const [{ rawQuery }] = strapiAdmin.useQueryParams();
163
127
  const userPermissions = strapiAdmin.useAuth("DocumentRBAC", (state) => state.permissions);
164
128
  const contentTypePermissions = React__namespace.useMemo(() => {
165
129
  const contentTypePermissions2 = userPermissions.filter(
@@ -170,7 +134,14 @@ const DocumentRBAC = ({ children, permissions }) => {
170
134
  return { ...acc, [action]: [permission] };
171
135
  }, {});
172
136
  }, [slug, userPermissions]);
173
- const { isLoading, allowedActions } = strapiAdmin.useRBAC(contentTypePermissions, permissions ?? void 0);
137
+ const { isLoading, allowedActions } = strapiAdmin.useRBAC(
138
+ contentTypePermissions,
139
+ permissions ?? void 0,
140
+ // TODO: useRBAC context should be typed and built differently
141
+ // We are passing raw query as context to the hook so that it can
142
+ // rely on the locale provided from DocumentRBAC for its permission calculations.
143
+ rawQuery
144
+ );
174
145
  const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
175
146
  const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
176
147
  const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
@@ -179,9 +150,8 @@ const DocumentRBAC = ({ children, permissions }) => {
179
150
  const name = removeNumericalStrings(fieldName.split("."));
180
151
  const componentFieldNames = fieldsUserCanAction.filter((field) => field.split(".").length > 1);
181
152
  if (fieldType === "component") {
182
- const componentOrDynamicZoneFields = componentFieldNames.map((field) => field.split("."));
183
- return componentOrDynamicZoneFields.some((field) => {
184
- return field.includes(fieldName);
153
+ return componentFieldNames.some((field) => {
154
+ return field.includes(name.join("."));
185
155
  });
186
156
  }
187
157
  if (name.length > 1) {
@@ -211,89 +181,20 @@ const extractAndDedupeFields = (permissions = []) => permissions.flatMap((permis
211
181
  (field, index2, arr) => arr.indexOf(field) === index2 && typeof field === "string"
212
182
  );
213
183
  const removeNumericalStrings = (arr) => arr.filter((item) => isNaN(Number(item)));
214
- const buildValidParams = (query) => {
215
- if (!query)
216
- return query;
217
- const { plugins: _, ...validQueryParams } = {
218
- ...query,
219
- ...Object.values(query?.plugins ?? {}).reduce(
220
- (acc, current) => Object.assign(acc, current),
221
- {}
222
- )
223
- };
224
- if ("_q" in validQueryParams) {
225
- validQueryParams._q = encodeURIComponent(validQueryParams._q);
226
- }
227
- return validQueryParams;
228
- };
229
- const axiosBaseQuery = () => async (query, { signal }) => {
230
- try {
231
- const { get, post, del, put } = strapiAdmin.getFetchClient();
232
- if (typeof query === "string") {
233
- const result = await get(query, { signal });
234
- return { data: result.data };
235
- } else {
236
- const { url, method = "GET", data, config } = query;
237
- if (method === "POST") {
238
- const result2 = await post(url, data, { ...config, signal });
239
- return { data: result2.data };
240
- }
241
- if (method === "DELETE") {
242
- const result2 = await del(url, { ...config, signal });
243
- return { data: result2.data };
244
- }
245
- if (method === "PUT") {
246
- const result2 = await put(url, data, { ...config, signal });
247
- return { data: result2.data };
248
- }
249
- const result = await get(url, { ...config, signal });
250
- return { data: result.data };
251
- }
252
- } catch (err) {
253
- if (axios.isAxiosError(err)) {
254
- if (typeof err.response?.data === "object" && err.response?.data !== null && "error" in err.response?.data) {
255
- return { data: void 0, error: err.response?.data.error };
256
- } else {
257
- return {
258
- data: void 0,
259
- error: {
260
- name: "UnknownError",
261
- message: "There was an unknown error response from the API",
262
- details: err.response?.data,
263
- status: err.response?.status
264
- }
265
- };
266
- }
267
- }
268
- const error = err;
269
- return {
270
- data: void 0,
271
- error: {
272
- name: error.name,
273
- message: error.message,
274
- stack: error.stack
275
- }
276
- };
277
- }
278
- };
279
- const isBaseQueryError = (error) => {
280
- return error.name !== void 0;
281
- };
282
- const contentManagerApi = react.createApi({
283
- reducerPath: "contentManagerApi",
284
- baseQuery: axiosBaseQuery(),
285
- tagTypes: [
184
+ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
185
+ addTagTypes: [
286
186
  "ComponentConfiguration",
287
187
  "ContentTypesConfiguration",
288
188
  "ContentTypeSettings",
289
189
  "Document",
290
190
  "InitialData",
291
191
  "HistoryVersion",
292
- "Relations"
293
- ],
294
- endpoints: () => ({})
192
+ "Relations",
193
+ "UidAvailability"
194
+ ]
295
195
  });
296
196
  const documentApi = contentManagerApi.injectEndpoints({
197
+ overrideExisting: true,
297
198
  endpoints: (builder) => ({
298
199
  autoCloneDocument: builder.mutation({
299
200
  query: ({ model, sourceId, query }) => ({
@@ -303,7 +204,12 @@ const documentApi = contentManagerApi.injectEndpoints({
303
204
  params: query
304
205
  }
305
206
  }),
306
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
207
+ invalidatesTags: (_result, error, { model }) => {
208
+ if (error) {
209
+ return [];
210
+ }
211
+ return [{ type: "Document", id: `${model}_LIST` }];
212
+ }
307
213
  }),
308
214
  cloneDocument: builder.mutation({
309
215
  query: ({ model, sourceId, data, params }) => ({
@@ -314,7 +220,10 @@ const documentApi = contentManagerApi.injectEndpoints({
314
220
  params
315
221
  }
316
222
  }),
317
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
223
+ invalidatesTags: (_result, _error, { model }) => [
224
+ { type: "Document", id: `${model}_LIST` },
225
+ { type: "UidAvailability", id: model }
226
+ ]
318
227
  }),
319
228
  /**
320
229
  * Creates a new collection-type document. This should ONLY be used for collection-types.
@@ -331,7 +240,8 @@ const documentApi = contentManagerApi.injectEndpoints({
331
240
  }),
332
241
  invalidatesTags: (result, _error, { model }) => [
333
242
  { type: "Document", id: `${model}_LIST` },
334
- "Relations"
243
+ "Relations",
244
+ { type: "UidAvailability", id: model }
335
245
  ]
336
246
  }),
337
247
  deleteDocument: builder.mutation({
@@ -347,12 +257,15 @@ const documentApi = contentManagerApi.injectEndpoints({
347
257
  ]
348
258
  }),
349
259
  deleteManyDocuments: builder.mutation({
350
- query: ({ model, ...body }) => ({
260
+ query: ({ model, params, ...body }) => ({
351
261
  url: `/content-manager/collection-types/${model}/actions/bulkDelete`,
352
262
  method: "POST",
353
- data: body
263
+ data: body,
264
+ config: {
265
+ params
266
+ }
354
267
  }),
355
- invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
268
+ invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
356
269
  }),
357
270
  discardDocument: builder.mutation({
358
271
  query: ({ collectionType, model, documentId, params }) => ({
@@ -369,7 +282,8 @@ const documentApi = contentManagerApi.injectEndpoints({
369
282
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
370
283
  },
371
284
  { type: "Document", id: `${model}_LIST` },
372
- "Relations"
285
+ "Relations",
286
+ { type: "UidAvailability", id: model }
373
287
  ];
374
288
  }
375
289
  }),
@@ -382,11 +296,12 @@ const documentApi = contentManagerApi.injectEndpoints({
382
296
  url: `/content-manager/collection-types/${model}`,
383
297
  method: "GET",
384
298
  config: {
385
- params
299
+ params: qs.stringify(params, { encode: true })
386
300
  }
387
301
  }),
388
302
  providesTags: (result, _error, arg) => {
389
303
  return [
304
+ { type: "Document", id: `ALL_LIST` },
390
305
  { type: "Document", id: `${arg.model}_LIST` },
391
306
  ...result?.results.map(({ documentId }) => ({
392
307
  type: "Document",
@@ -425,6 +340,11 @@ const documentApi = contentManagerApi.injectEndpoints({
425
340
  {
426
341
  type: "Document",
427
342
  id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
343
+ },
344
+ // Make it easy to invalidate all individual documents queries for a model
345
+ {
346
+ type: "Document",
347
+ id: `${model}_ALL_ITEMS`
428
348
  }
429
349
  ];
430
350
  }
@@ -463,10 +383,13 @@ const documentApi = contentManagerApi.injectEndpoints({
463
383
  }
464
384
  }),
465
385
  publishManyDocuments: builder.mutation({
466
- query: ({ model, ...body }) => ({
386
+ query: ({ model, params, ...body }) => ({
467
387
  url: `/content-manager/collection-types/${model}/actions/bulkPublish`,
468
388
  method: "POST",
469
- data: body
389
+ data: body,
390
+ config: {
391
+ params
392
+ }
470
393
  }),
471
394
  invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
472
395
  }),
@@ -485,8 +408,21 @@ const documentApi = contentManagerApi.injectEndpoints({
485
408
  type: "Document",
486
409
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
487
410
  },
488
- "Relations"
411
+ "Relations",
412
+ { type: "UidAvailability", id: model }
489
413
  ];
414
+ },
415
+ async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
416
+ const patchResult = dispatch(
417
+ documentApi.util.updateQueryData("getDocument", patch, (draft) => {
418
+ Object.assign(draft.data, data);
419
+ })
420
+ );
421
+ try {
422
+ await queryFulfilled;
423
+ } catch {
424
+ patchResult.undo();
425
+ }
490
426
  }
491
427
  }),
492
428
  unpublishDocument: builder.mutation({
@@ -508,10 +444,13 @@ const documentApi = contentManagerApi.injectEndpoints({
508
444
  }
509
445
  }),
510
446
  unpublishManyDocuments: builder.mutation({
511
- query: ({ model, ...body }) => ({
447
+ query: ({ model, params, ...body }) => ({
512
448
  url: `/content-manager/collection-types/${model}/actions/bulkUnpublish`,
513
449
  method: "POST",
514
- data: body
450
+ data: body,
451
+ config: {
452
+ params
453
+ }
515
454
  }),
516
455
  invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
517
456
  })
@@ -535,20 +474,54 @@ const {
535
474
  useUnpublishDocumentMutation,
536
475
  useUnpublishManyDocumentsMutation
537
476
  } = documentApi;
538
- const createYupSchema = (attributes = {}, components = {}) => {
477
+ const buildValidParams = (query) => {
478
+ if (!query)
479
+ return query;
480
+ const { plugins: _, ...validQueryParams } = {
481
+ ...query,
482
+ ...Object.values(query?.plugins ?? {}).reduce(
483
+ (acc, current) => Object.assign(acc, current),
484
+ {}
485
+ )
486
+ };
487
+ return validQueryParams;
488
+ };
489
+ const isBaseQueryError = (error) => {
490
+ return error.name !== void 0;
491
+ };
492
+ const arrayValidator = (attribute, options) => ({
493
+ message: strapiAdmin.translatedErrors.required,
494
+ test(value) {
495
+ if (options.status === "draft") {
496
+ return true;
497
+ }
498
+ if (!attribute.required) {
499
+ return true;
500
+ }
501
+ if (!value) {
502
+ return false;
503
+ }
504
+ if (Array.isArray(value) && value.length === 0) {
505
+ return false;
506
+ }
507
+ return true;
508
+ }
509
+ });
510
+ const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
539
511
  const createModelSchema = (attributes2) => yup__namespace.object().shape(
540
512
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
541
513
  if (DOCUMENT_META_FIELDS.includes(name)) {
542
514
  return acc;
543
515
  }
544
516
  const validations = [
517
+ addNullableValidation,
545
518
  addRequiredValidation,
546
519
  addMinLengthValidation,
547
520
  addMaxLengthValidation,
548
521
  addMinValidation,
549
522
  addMaxValidation,
550
523
  addRegexValidation
551
- ].map((fn) => fn(attribute));
524
+ ].map((fn) => fn(attribute, options));
552
525
  const transformSchema = pipe__default.default(...validations);
553
526
  switch (attribute.type) {
554
527
  case "component": {
@@ -558,12 +531,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
558
531
  ...acc,
559
532
  [name]: transformSchema(
560
533
  yup__namespace.array().of(createModelSchema(attributes3).nullable(false))
561
- )
534
+ ).test(arrayValidator(attribute, options))
562
535
  };
563
536
  } else {
564
537
  return {
565
538
  ...acc,
566
- [name]: transformSchema(createModelSchema(attributes3))
539
+ [name]: transformSchema(createModelSchema(attributes3).nullable())
567
540
  };
568
541
  }
569
542
  }
@@ -574,24 +547,42 @@ const createYupSchema = (attributes = {}, components = {}) => {
574
547
  yup__namespace.array().of(
575
548
  yup__namespace.lazy(
576
549
  (data) => {
577
- const { attributes: attributes3 } = components[data.__component];
578
- return yup__namespace.object().shape({
550
+ const attributes3 = components?.[data?.__component]?.attributes;
551
+ const validation = yup__namespace.object().shape({
579
552
  __component: yup__namespace.string().required().oneOf(Object.keys(components))
580
- }).nullable(false).concat(createModelSchema(attributes3));
553
+ }).nullable(false);
554
+ if (!attributes3) {
555
+ return validation;
556
+ }
557
+ return validation.concat(createModelSchema(attributes3));
581
558
  }
582
559
  )
583
560
  )
584
- )
561
+ ).test(arrayValidator(attribute, options))
585
562
  };
586
563
  case "relation":
587
564
  return {
588
565
  ...acc,
589
566
  [name]: transformSchema(
590
- yup__namespace.array().of(
591
- yup__namespace.object().shape({
592
- id: yup__namespace.string().required()
593
- })
594
- )
567
+ yup__namespace.lazy((value) => {
568
+ if (!value) {
569
+ return yup__namespace.mixed().nullable(true);
570
+ } else if (Array.isArray(value)) {
571
+ return yup__namespace.array().of(
572
+ yup__namespace.object().shape({
573
+ id: yup__namespace.number().required()
574
+ })
575
+ );
576
+ } else if (typeof value === "object") {
577
+ return yup__namespace.object();
578
+ } else {
579
+ return yup__namespace.mixed().test(
580
+ "type-error",
581
+ "Relation values must be either null, an array of objects with {id} or an object.",
582
+ () => false
583
+ );
584
+ }
585
+ })
595
586
  )
596
587
  };
597
588
  default:
@@ -631,6 +622,14 @@ const createAttributeSchema = (attribute) => {
631
622
  if (!value || typeof value === "string" && value.length === 0) {
632
623
  return true;
633
624
  }
625
+ if (typeof value === "object") {
626
+ try {
627
+ JSON.stringify(value);
628
+ return true;
629
+ } catch (err) {
630
+ return false;
631
+ }
632
+ }
634
633
  try {
635
634
  JSON.parse(value);
636
635
  return true;
@@ -649,16 +648,30 @@ const createAttributeSchema = (attribute) => {
649
648
  return yup__namespace.mixed();
650
649
  }
651
650
  };
652
- const addRequiredValidation = (attribute) => (schema) => {
653
- if (attribute.required) {
654
- return schema.required({
655
- id: strapiAdmin.translatedErrors.required.id,
656
- defaultMessage: "This field is required."
657
- });
651
+ const nullableSchema = (schema) => {
652
+ return schema?.nullable ? schema.nullable() : (
653
+ // In some cases '.nullable' will not be available on the schema.
654
+ // e.g. when the schema has been built using yup.lazy (e.g. for relations).
655
+ // In these cases we should just return the schema as it is.
656
+ schema
657
+ );
658
+ };
659
+ const addNullableValidation = () => (schema) => {
660
+ return nullableSchema(schema);
661
+ };
662
+ const addRequiredValidation = (attribute, options) => (schema) => {
663
+ if (options.status === "draft" || !attribute.required) {
664
+ return schema;
665
+ }
666
+ if (attribute.required && "required" in schema) {
667
+ return schema.required(strapiAdmin.translatedErrors.required);
658
668
  }
659
- return schema.nullable();
669
+ return schema;
660
670
  };
661
- const addMinLengthValidation = (attribute) => (schema) => {
671
+ const addMinLengthValidation = (attribute, options) => (schema) => {
672
+ if (options.status === "draft") {
673
+ return schema;
674
+ }
662
675
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
663
676
  return schema.min(attribute.minLength, {
664
677
  ...strapiAdmin.translatedErrors.minLength,
@@ -680,10 +693,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
680
693
  }
681
694
  return schema;
682
695
  };
683
- const addMinValidation = (attribute) => (schema) => {
684
- if ("min" in attribute) {
696
+ const addMinValidation = (attribute, options) => (schema) => {
697
+ if (options.status === "draft") {
698
+ return schema;
699
+ }
700
+ if ("min" in attribute && "min" in schema) {
685
701
  const min = toInteger(attribute.min);
686
- if ("min" in schema && min) {
702
+ if (min) {
687
703
  return schema.min(min, {
688
704
  ...strapiAdmin.translatedErrors.min,
689
705
  values: {
@@ -728,24 +744,6 @@ const addRegexValidation = (attribute) => (schema) => {
728
744
  }
729
745
  return schema;
730
746
  };
731
- const extractValuesFromYupError = (errorType, errorParams) => {
732
- if (!errorType || !errorParams) {
733
- return {};
734
- }
735
- return {
736
- [errorType]: errorParams[errorType]
737
- };
738
- };
739
- const getInnerErrors = (error) => (error?.inner || []).reduce((acc, currentError) => {
740
- if (currentError.path) {
741
- acc[currentError.path.split("[").join(".").split("]").join("")] = {
742
- id: currentError.message,
743
- defaultMessage: currentError.message,
744
- values: extractValuesFromYupError(currentError?.type, currentError?.params)
745
- };
746
- }
747
- return acc;
748
- }, {});
749
747
  const initApi = contentManagerApi.injectEndpoints({
750
748
  endpoints: (builder) => ({
751
749
  getInitialData: builder.query({
@@ -759,27 +757,20 @@ const { useGetInitialDataQuery } = initApi;
759
757
  const useContentTypeSchema = (model) => {
760
758
  const { toggleNotification } = strapiAdmin.useNotification();
761
759
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
762
- const { components, contentType, contentTypes, error, isLoading, isFetching } = useGetInitialDataQuery(void 0, {
763
- selectFromResult: (res) => {
764
- const contentType2 = res.data?.contentTypes.find((ct) => ct.uid === model);
765
- const componentsByKey = res.data?.components.reduce(
766
- (acc, component) => {
767
- acc[component.uid] = component;
768
- return acc;
769
- },
770
- {}
771
- );
772
- const components2 = extractContentTypeComponents(contentType2?.attributes, componentsByKey);
773
- return {
774
- isLoading: res.isLoading,
775
- isFetching: res.isFetching,
776
- error: res.error,
777
- components: Object.keys(components2).length === 0 ? void 0 : components2,
778
- contentType: contentType2,
779
- contentTypes: res.data?.contentTypes ?? []
780
- };
781
- }
782
- });
760
+ const { data, error, isLoading, isFetching } = useGetInitialDataQuery(void 0);
761
+ const { components, contentType, contentTypes } = React__namespace.useMemo(() => {
762
+ const contentType2 = data?.contentTypes.find((ct) => ct.uid === model);
763
+ const componentsByKey = data?.components.reduce((acc, component) => {
764
+ acc[component.uid] = component;
765
+ return acc;
766
+ }, {});
767
+ const components2 = extractContentTypeComponents(contentType2?.attributes, componentsByKey);
768
+ return {
769
+ components: Object.keys(components2).length === 0 ? void 0 : components2,
770
+ contentType: contentType2,
771
+ contentTypes: data?.contentTypes ?? []
772
+ };
773
+ }, [model, data]);
783
774
  React__namespace.useEffect(() => {
784
775
  if (error) {
785
776
  toggleNotification({
@@ -826,16 +817,328 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
826
817
  }, {});
827
818
  return componentsByKey;
828
819
  };
829
- const useDocument = (args, opts) => {
820
+ const HOOKS = {
821
+ /**
822
+ * Hook that allows to mutate the displayed headers of the list view table
823
+ * @constant
824
+ * @type {string}
825
+ */
826
+ INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
827
+ /**
828
+ * Hook that allows to mutate the CM's collection types links pre-set filters
829
+ * @constant
830
+ * @type {string}
831
+ */
832
+ MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
833
+ /**
834
+ * Hook that allows to mutate the CM's edit view layout
835
+ * @constant
836
+ * @type {string}
837
+ */
838
+ MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
839
+ /**
840
+ * Hook that allows to mutate the CM's single types links pre-set filters
841
+ * @constant
842
+ * @type {string}
843
+ */
844
+ MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
845
+ };
846
+ const contentTypesApi = contentManagerApi.injectEndpoints({
847
+ endpoints: (builder) => ({
848
+ getContentTypeConfiguration: builder.query({
849
+ query: (uid) => ({
850
+ url: `/content-manager/content-types/${uid}/configuration`,
851
+ method: "GET"
852
+ }),
853
+ transformResponse: (response) => response.data,
854
+ providesTags: (_result, _error, uid) => [
855
+ { type: "ContentTypesConfiguration", id: uid },
856
+ { type: "ContentTypeSettings", id: "LIST" }
857
+ ]
858
+ }),
859
+ getAllContentTypeSettings: builder.query({
860
+ query: () => "/content-manager/content-types-settings",
861
+ transformResponse: (response) => response.data,
862
+ providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
863
+ }),
864
+ updateContentTypeConfiguration: builder.mutation({
865
+ query: ({ uid, ...body }) => ({
866
+ url: `/content-manager/content-types/${uid}/configuration`,
867
+ method: "PUT",
868
+ data: body
869
+ }),
870
+ transformResponse: (response) => response.data,
871
+ invalidatesTags: (_result, _error, { uid }) => [
872
+ { type: "ContentTypesConfiguration", id: uid },
873
+ { type: "ContentTypeSettings", id: "LIST" },
874
+ // Is this necessary?
875
+ { type: "InitialData" }
876
+ ]
877
+ })
878
+ })
879
+ });
880
+ const {
881
+ useGetContentTypeConfigurationQuery,
882
+ useGetAllContentTypeSettingsQuery,
883
+ useUpdateContentTypeConfigurationMutation
884
+ } = contentTypesApi;
885
+ const checkIfAttributeIsDisplayable = (attribute) => {
886
+ const { type } = attribute;
887
+ if (type === "relation") {
888
+ return !attribute.relation.toLowerCase().includes("morph");
889
+ }
890
+ return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
891
+ };
892
+ const getMainField = (attribute, mainFieldName, { schemas, components }) => {
893
+ if (!mainFieldName) {
894
+ return void 0;
895
+ }
896
+ const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
897
+ // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
898
+ schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
899
+ );
900
+ return {
901
+ name: mainFieldName,
902
+ type: mainFieldType ?? "string"
903
+ };
904
+ };
905
+ const DEFAULT_SETTINGS = {
906
+ bulkable: false,
907
+ filterable: false,
908
+ searchable: false,
909
+ pagination: false,
910
+ defaultSortBy: "",
911
+ defaultSortOrder: "asc",
912
+ mainField: "id",
913
+ pageSize: 10
914
+ };
915
+ const useDocumentLayout = (model) => {
916
+ const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
917
+ const [{ query }] = strapiAdmin.useQueryParams();
918
+ const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
830
919
  const { toggleNotification } = strapiAdmin.useNotification();
831
920
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
921
+ const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
832
922
  const {
833
- currentData: data,
834
- isLoading: isLoadingDocument,
923
+ data,
924
+ isLoading: isLoadingConfigs,
925
+ error,
926
+ isFetching: isFetchingConfigs
927
+ } = useGetContentTypeConfigurationQuery(model);
928
+ const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
929
+ React__namespace.useEffect(() => {
930
+ if (error) {
931
+ toggleNotification({
932
+ type: "danger",
933
+ message: formatAPIError(error)
934
+ });
935
+ }
936
+ }, [error, formatAPIError, toggleNotification]);
937
+ const editLayout = React__namespace.useMemo(
938
+ () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
939
+ layout: [],
940
+ components: {},
941
+ metadatas: {},
942
+ options: {},
943
+ settings: DEFAULT_SETTINGS
944
+ },
945
+ [data, isLoading, schemas, schema, components]
946
+ );
947
+ const listLayout = React__namespace.useMemo(() => {
948
+ return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
949
+ layout: [],
950
+ metadatas: {},
951
+ options: {},
952
+ settings: DEFAULT_SETTINGS
953
+ };
954
+ }, [data, isLoading, schemas, schema, components]);
955
+ const { layout: edit } = React__namespace.useMemo(
956
+ () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
957
+ layout: editLayout,
958
+ query
959
+ }),
960
+ [editLayout, query, runHookWaterfall]
961
+ );
962
+ return {
963
+ error,
964
+ isLoading,
965
+ edit,
966
+ list: listLayout
967
+ };
968
+ };
969
+ const useDocLayout = () => {
970
+ const { model } = useDoc();
971
+ return useDocumentLayout(model);
972
+ };
973
+ const formatEditLayout = (data, {
974
+ schemas,
975
+ schema,
976
+ components
977
+ }) => {
978
+ let currentPanelIndex = 0;
979
+ const panelledEditAttributes = convertEditLayoutToFieldLayouts(
980
+ data.contentType.layouts.edit,
981
+ schema?.attributes,
982
+ data.contentType.metadatas,
983
+ { configurations: data.components, schemas: components },
984
+ schemas
985
+ ).reduce((panels, row) => {
986
+ if (row.some((field) => field.type === "dynamiczone")) {
987
+ panels.push([row]);
988
+ currentPanelIndex += 2;
989
+ } else {
990
+ if (!panels[currentPanelIndex]) {
991
+ panels.push([row]);
992
+ } else {
993
+ panels[currentPanelIndex].push(row);
994
+ }
995
+ }
996
+ return panels;
997
+ }, []);
998
+ const componentEditAttributes = Object.entries(data.components).reduce(
999
+ (acc, [uid, configuration]) => {
1000
+ acc[uid] = {
1001
+ layout: convertEditLayoutToFieldLayouts(
1002
+ configuration.layouts.edit,
1003
+ components[uid].attributes,
1004
+ configuration.metadatas,
1005
+ { configurations: data.components, schemas: components }
1006
+ ),
1007
+ settings: {
1008
+ ...configuration.settings,
1009
+ icon: components[uid].info.icon,
1010
+ displayName: components[uid].info.displayName
1011
+ }
1012
+ };
1013
+ return acc;
1014
+ },
1015
+ {}
1016
+ );
1017
+ const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
1018
+ (acc, [attribute, metadata]) => {
1019
+ return {
1020
+ ...acc,
1021
+ [attribute]: metadata.edit
1022
+ };
1023
+ },
1024
+ {}
1025
+ );
1026
+ return {
1027
+ layout: panelledEditAttributes,
1028
+ components: componentEditAttributes,
1029
+ metadatas: editMetadatas,
1030
+ settings: {
1031
+ ...data.contentType.settings,
1032
+ displayName: schema?.info.displayName
1033
+ },
1034
+ options: {
1035
+ ...schema?.options,
1036
+ ...schema?.pluginOptions,
1037
+ ...data.contentType.options
1038
+ }
1039
+ };
1040
+ };
1041
+ const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
1042
+ return rows.map(
1043
+ (row) => row.map((field) => {
1044
+ const attribute = attributes[field.name];
1045
+ if (!attribute) {
1046
+ return null;
1047
+ }
1048
+ const { edit: metadata } = metadatas[field.name];
1049
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1050
+ return {
1051
+ attribute,
1052
+ disabled: !metadata.editable,
1053
+ hint: metadata.description,
1054
+ label: metadata.label ?? "",
1055
+ name: field.name,
1056
+ // @ts-expect-error – mainField does exist on the metadata for a relation.
1057
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1058
+ schemas,
1059
+ components: components?.schemas ?? {}
1060
+ }),
1061
+ placeholder: metadata.placeholder ?? "",
1062
+ required: attribute.required ?? false,
1063
+ size: field.size,
1064
+ unique: "unique" in attribute ? attribute.unique : false,
1065
+ visible: metadata.visible ?? true,
1066
+ type: attribute.type
1067
+ };
1068
+ }).filter((field) => field !== null)
1069
+ );
1070
+ };
1071
+ const formatListLayout = (data, {
1072
+ schemas,
1073
+ schema,
1074
+ components
1075
+ }) => {
1076
+ const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
1077
+ (acc, [attribute, metadata]) => {
1078
+ return {
1079
+ ...acc,
1080
+ [attribute]: metadata.list
1081
+ };
1082
+ },
1083
+ {}
1084
+ );
1085
+ const listAttributes = convertListLayoutToFieldLayouts(
1086
+ data.contentType.layouts.list,
1087
+ schema?.attributes,
1088
+ listMetadatas,
1089
+ { configurations: data.components, schemas: components },
1090
+ schemas
1091
+ );
1092
+ return {
1093
+ layout: listAttributes,
1094
+ settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
1095
+ metadatas: listMetadatas,
1096
+ options: {
1097
+ ...schema?.options,
1098
+ ...schema?.pluginOptions,
1099
+ ...data.contentType.options
1100
+ }
1101
+ };
1102
+ };
1103
+ const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
1104
+ return columns.map((name) => {
1105
+ const attribute = attributes[name];
1106
+ if (!attribute) {
1107
+ return null;
1108
+ }
1109
+ const metadata = metadatas[name];
1110
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1111
+ return {
1112
+ attribute,
1113
+ label: metadata.label ?? "",
1114
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1115
+ schemas,
1116
+ components: components?.schemas ?? {}
1117
+ }),
1118
+ name,
1119
+ searchable: metadata.searchable ?? true,
1120
+ sortable: metadata.sortable ?? true
1121
+ };
1122
+ }).filter((field) => field !== null);
1123
+ };
1124
+ const useDocument = (args, opts) => {
1125
+ const { toggleNotification } = strapiAdmin.useNotification();
1126
+ const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
1127
+ const {
1128
+ currentData: data,
1129
+ isLoading: isLoadingDocument,
835
1130
  isFetching: isFetchingDocument,
836
1131
  error
837
- } = useGetDocumentQuery(args, opts);
838
- const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
1132
+ } = useGetDocumentQuery(args, {
1133
+ ...opts,
1134
+ skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
1135
+ });
1136
+ const {
1137
+ components,
1138
+ schema,
1139
+ schemas,
1140
+ isLoading: isLoadingSchema
1141
+ } = useContentTypeSchema(args.model);
839
1142
  React__namespace.useEffect(() => {
840
1143
  if (error) {
841
1144
  toggleNotification({
@@ -862,7 +1165,7 @@ const useDocument = (args, opts) => {
862
1165
  return null;
863
1166
  } catch (error2) {
864
1167
  if (error2 instanceof yup.ValidationError) {
865
- return getInnerErrors(error2);
1168
+ return strapiAdmin.getYupValidationErrors(error2);
866
1169
  }
867
1170
  throw error2;
868
1171
  }
@@ -870,12 +1173,15 @@ const useDocument = (args, opts) => {
870
1173
  [validationSchema]
871
1174
  );
872
1175
  const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
1176
+ const hasError = !!error;
873
1177
  return {
874
1178
  components,
875
1179
  document: data?.data,
876
1180
  meta: data?.meta,
877
1181
  isLoading,
1182
+ hasError,
878
1183
  schema,
1184
+ schemas,
879
1185
  validate
880
1186
  };
881
1187
  };
@@ -889,22 +1195,60 @@ const useDoc = () => {
889
1195
  if (!slug) {
890
1196
  throw new Error("Could not find model in url params");
891
1197
  }
1198
+ const document = useDocument(
1199
+ { documentId: origin || id, model: slug, collectionType, params },
1200
+ {
1201
+ skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
1202
+ }
1203
+ );
1204
+ const returnId = origin || id === "create" ? void 0 : id;
892
1205
  return {
893
1206
  collectionType,
894
1207
  model: slug,
895
- id: origin || id === "create" ? void 0 : id,
896
- ...useDocument(
897
- { documentId: origin || id, model: slug, collectionType, params },
898
- {
899
- skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
900
- }
901
- )
1208
+ id: returnId,
1209
+ ...document
1210
+ };
1211
+ };
1212
+ const useContentManagerContext = () => {
1213
+ const {
1214
+ collectionType,
1215
+ model,
1216
+ id,
1217
+ components,
1218
+ isLoading: isLoadingDoc,
1219
+ schema,
1220
+ schemas
1221
+ } = useDoc();
1222
+ const layout = useDocumentLayout(model);
1223
+ const form = strapiAdmin.useForm("useContentManagerContext", (state) => state);
1224
+ const isSingleType = collectionType === SINGLE_TYPES;
1225
+ const slug = model;
1226
+ const isCreatingEntry = id === "create";
1227
+ useContentTypeSchema();
1228
+ const isLoading = isLoadingDoc || layout.isLoading;
1229
+ const error = layout.error;
1230
+ return {
1231
+ error,
1232
+ isLoading,
1233
+ // Base metadata
1234
+ model,
1235
+ collectionType,
1236
+ id,
1237
+ slug,
1238
+ isCreatingEntry,
1239
+ isSingleType,
1240
+ hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
1241
+ // All schema infos
1242
+ components,
1243
+ contentType: schema,
1244
+ contentTypes: schemas,
1245
+ // Form state
1246
+ form,
1247
+ // layout infos
1248
+ layout
902
1249
  };
903
1250
  };
904
1251
  const prefixPluginTranslations = (trad, pluginId) => {
905
- if (!pluginId) {
906
- throw new TypeError("pluginId can't be empty");
907
- }
908
1252
  return Object.keys(trad).reduce((acc, current) => {
909
1253
  acc[`${pluginId}.${current}`] = trad[current];
910
1254
  return acc;
@@ -920,6 +1264,8 @@ const useDocumentActions = () => {
920
1264
  const { formatMessage } = reactIntl.useIntl();
921
1265
  const { trackUsage } = strapiAdmin.useTracking();
922
1266
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
1267
+ const navigate = reactRouterDom.useNavigate();
1268
+ const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
923
1269
  const [deleteDocument] = useDeleteDocumentMutation();
924
1270
  const _delete = React__namespace.useCallback(
925
1271
  async ({ collectionType, model, documentId, params }, trackerProperty) => {
@@ -958,14 +1304,53 @@ const useDocumentActions = () => {
958
1304
  },
959
1305
  [trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
960
1306
  );
1307
+ const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
1308
+ const deleteMany = React__namespace.useCallback(
1309
+ async ({ model, documentIds, params }) => {
1310
+ try {
1311
+ trackUsage("willBulkDeleteEntries");
1312
+ const res = await deleteManyDocuments({
1313
+ model,
1314
+ documentIds,
1315
+ params
1316
+ });
1317
+ if ("error" in res) {
1318
+ toggleNotification({
1319
+ type: "danger",
1320
+ message: formatAPIError(res.error)
1321
+ });
1322
+ return { error: res.error };
1323
+ }
1324
+ toggleNotification({
1325
+ type: "success",
1326
+ title: formatMessage({
1327
+ id: getTranslation("success.records.delete"),
1328
+ defaultMessage: "Successfully deleted."
1329
+ }),
1330
+ message: ""
1331
+ });
1332
+ trackUsage("didBulkDeleteEntries");
1333
+ return res.data;
1334
+ } catch (err) {
1335
+ toggleNotification({
1336
+ type: "danger",
1337
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1338
+ });
1339
+ trackUsage("didNotBulkDeleteEntries");
1340
+ throw err;
1341
+ }
1342
+ },
1343
+ [trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
1344
+ );
961
1345
  const [discardDocument] = useDiscardDocumentMutation();
962
1346
  const discard = React__namespace.useCallback(
963
- async ({ collectionType, model, documentId }) => {
1347
+ async ({ collectionType, model, documentId, params }) => {
964
1348
  try {
965
1349
  const res = await discardDocument({
966
1350
  collectionType,
967
1351
  model,
968
- documentId
1352
+ documentId,
1353
+ params
969
1354
  });
970
1355
  if ("error" in res) {
971
1356
  toggleNotification({
@@ -1027,6 +1412,43 @@ const useDocumentActions = () => {
1027
1412
  },
1028
1413
  [trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
1029
1414
  );
1415
+ const [publishManyDocuments] = usePublishManyDocumentsMutation();
1416
+ const publishMany = React__namespace.useCallback(
1417
+ async ({ model, documentIds, params }) => {
1418
+ try {
1419
+ const res = await publishManyDocuments({
1420
+ model,
1421
+ documentIds,
1422
+ params
1423
+ });
1424
+ if ("error" in res) {
1425
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1426
+ return { error: res.error };
1427
+ }
1428
+ toggleNotification({
1429
+ type: "success",
1430
+ message: formatMessage({
1431
+ id: getTranslation("success.record.publish"),
1432
+ defaultMessage: "Published document"
1433
+ })
1434
+ });
1435
+ return res.data;
1436
+ } catch (err) {
1437
+ toggleNotification({
1438
+ type: "danger",
1439
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1440
+ });
1441
+ throw err;
1442
+ }
1443
+ },
1444
+ [
1445
+ // trackUsage,
1446
+ publishManyDocuments,
1447
+ toggleNotification,
1448
+ formatMessage,
1449
+ formatAPIError
1450
+ ]
1451
+ );
1030
1452
  const [updateDocument] = useUpdateDocumentMutation();
1031
1453
  const update = React__namespace.useCallback(
1032
1454
  async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
@@ -1101,6 +1523,41 @@ const useDocumentActions = () => {
1101
1523
  },
1102
1524
  [trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
1103
1525
  );
1526
+ const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
1527
+ const unpublishMany = React__namespace.useCallback(
1528
+ async ({ model, documentIds, params }) => {
1529
+ try {
1530
+ trackUsage("willBulkUnpublishEntries");
1531
+ const res = await unpublishManyDocuments({
1532
+ model,
1533
+ documentIds,
1534
+ params
1535
+ });
1536
+ if ("error" in res) {
1537
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1538
+ return { error: res.error };
1539
+ }
1540
+ trackUsage("didBulkUnpublishEntries");
1541
+ toggleNotification({
1542
+ type: "success",
1543
+ title: formatMessage({
1544
+ id: getTranslation("success.records.unpublish"),
1545
+ defaultMessage: "Successfully unpublished."
1546
+ }),
1547
+ message: ""
1548
+ });
1549
+ return res.data;
1550
+ } catch (err) {
1551
+ toggleNotification({
1552
+ type: "danger",
1553
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1554
+ });
1555
+ trackUsage("didNotBulkUnpublishEntries");
1556
+ throw err;
1557
+ }
1558
+ },
1559
+ [trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
1560
+ );
1104
1561
  const [createDocument] = useCreateDocumentMutation();
1105
1562
  const create = React__namespace.useCallback(
1106
1563
  async ({ model, params }, data, trackerProperty) => {
@@ -1123,6 +1580,7 @@ const useDocumentActions = () => {
1123
1580
  defaultMessage: "Saved document"
1124
1581
  })
1125
1582
  });
1583
+ setCurrentStep("contentManager.success");
1126
1584
  return res.data;
1127
1585
  } catch (err) {
1128
1586
  toggleNotification({
@@ -1144,7 +1602,6 @@ const useDocumentActions = () => {
1144
1602
  sourceId
1145
1603
  });
1146
1604
  if ("error" in res) {
1147
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1148
1605
  return { error: res.error };
1149
1606
  }
1150
1607
  toggleNotification({
@@ -1163,7 +1620,7 @@ const useDocumentActions = () => {
1163
1620
  throw err;
1164
1621
  }
1165
1622
  },
1166
- [autoCloneDocument, formatAPIError, formatMessage, toggleNotification]
1623
+ [autoCloneDocument, formatMessage, toggleNotification]
1167
1624
  );
1168
1625
  const [cloneDocument] = useCloneDocumentMutation();
1169
1626
  const clone = React__namespace.useCallback(
@@ -1189,6 +1646,7 @@ const useDocumentActions = () => {
1189
1646
  defaultMessage: "Cloned document"
1190
1647
  })
1191
1648
  });
1649
+ navigate(`../../${res.data.data.documentId}`, { relative: "path" });
1192
1650
  return res.data;
1193
1651
  } catch (err) {
1194
1652
  toggleNotification({
@@ -1199,7 +1657,7 @@ const useDocumentActions = () => {
1199
1657
  throw err;
1200
1658
  }
1201
1659
  },
1202
- [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
1660
+ [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
1203
1661
  );
1204
1662
  const [getDoc] = useLazyGetDocumentQuery();
1205
1663
  const getDocument = React__namespace.useCallback(
@@ -1214,17 +1672,20 @@ const useDocumentActions = () => {
1214
1672
  clone,
1215
1673
  create,
1216
1674
  delete: _delete,
1675
+ deleteMany,
1217
1676
  discard,
1218
1677
  getDocument,
1219
1678
  publish,
1679
+ publishMany,
1220
1680
  unpublish,
1681
+ unpublishMany,
1221
1682
  update
1222
1683
  };
1223
1684
  };
1224
- const ProtectedHistoryPage = React.lazy(
1225
- () => Promise.resolve().then(() => require("./History-C17LiyRg.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1685
+ const ProtectedHistoryPage = React__namespace.lazy(
1686
+ () => Promise.resolve().then(() => require("./History-BsPXl1XH.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1226
1687
  );
1227
- const routes$1 = [
1688
+ const routes$2 = [
1228
1689
  {
1229
1690
  path: ":collectionType/:slug/:id/history",
1230
1691
  Component: ProtectedHistoryPage
@@ -1234,32 +1695,45 @@ const routes$1 = [
1234
1695
  Component: ProtectedHistoryPage
1235
1696
  }
1236
1697
  ];
1698
+ const ProtectedPreviewPage = React__namespace.lazy(
1699
+ () => Promise.resolve().then(() => require("./Preview-BKuVG1dV.js")).then((mod) => ({ default: mod.ProtectedPreviewPage }))
1700
+ );
1701
+ const routes$1 = [
1702
+ {
1703
+ path: ":collectionType/:slug/:id/preview",
1704
+ Component: ProtectedPreviewPage
1705
+ },
1706
+ {
1707
+ path: ":collectionType/:slug/preview",
1708
+ Component: ProtectedPreviewPage
1709
+ }
1710
+ ];
1237
1711
  const ProtectedEditViewPage = React.lazy(
1238
- () => Promise.resolve().then(() => require("./EditViewPage-CzOT5Kpj.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1712
+ () => Promise.resolve().then(() => require("./EditViewPage-BRA-JSnw.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1239
1713
  );
1240
1714
  const ProtectedListViewPage = React.lazy(
1241
- () => Promise.resolve().then(() => require("./ListViewPage-BwrZrPsh.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1715
+ () => Promise.resolve().then(() => require("./ListViewPage-BUKFOJuS.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1242
1716
  );
1243
1717
  const ProtectedListConfiguration = React.lazy(
1244
- () => Promise.resolve().then(() => require("./ListConfigurationPage-Dks5SX6f.js")).then((mod) => ({
1718
+ () => Promise.resolve().then(() => require("./ListConfigurationPage-CN1-7Pgi.js")).then((mod) => ({
1245
1719
  default: mod.ProtectedListConfiguration
1246
1720
  }))
1247
1721
  );
1248
1722
  const ProtectedEditConfigurationPage = React.lazy(
1249
- () => Promise.resolve().then(() => require("./EditConfigurationPage-BfFzJ4Br.js")).then((mod) => ({
1723
+ () => Promise.resolve().then(() => require("./EditConfigurationPage-sdGi-bna.js")).then((mod) => ({
1250
1724
  default: mod.ProtectedEditConfigurationPage
1251
1725
  }))
1252
1726
  );
1253
1727
  const ProtectedComponentConfigurationPage = React.lazy(
1254
- () => Promise.resolve().then(() => require("./ComponentConfigurationPage-43KmCNQE.js")).then((mod) => ({
1728
+ () => Promise.resolve().then(() => require("./ComponentConfigurationPage-BebDdCkl.js")).then((mod) => ({
1255
1729
  default: mod.ProtectedComponentConfigurationPage
1256
1730
  }))
1257
1731
  );
1258
1732
  const NoPermissions = React.lazy(
1259
- () => Promise.resolve().then(() => require("./NoPermissionsPage-C-j6TEUF.js")).then((mod) => ({ default: mod.NoPermissions }))
1733
+ () => Promise.resolve().then(() => require("./NoPermissionsPage-DRPnEq9t.js")).then((mod) => ({ default: mod.NoPermissions }))
1260
1734
  );
1261
1735
  const NoContentType = React.lazy(
1262
- () => Promise.resolve().then(() => require("./NoContentTypePage-Cu5r1-JT.js")).then((mod) => ({ default: mod.NoContentType }))
1736
+ () => Promise.resolve().then(() => require("./NoContentTypePage-Cs7Kk9EW.js")).then((mod) => ({ default: mod.NoContentType }))
1263
1737
  );
1264
1738
  const CollectionTypePages = () => {
1265
1739
  const { collectionType } = reactRouterDom.useParams();
@@ -1271,7 +1745,7 @@ const CollectionTypePages = () => {
1271
1745
  const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
1272
1746
  const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
1273
1747
  const LIST_RELATIVE_PATH = ":collectionType/:slug";
1274
- const LIST_PATH = `/content-manager/${LIST_RELATIVE_PATH}`;
1748
+ const LIST_PATH = `/content-manager/collection-types/:slug`;
1275
1749
  const routes = [
1276
1750
  {
1277
1751
  path: LIST_RELATIVE_PATH,
@@ -1305,6 +1779,7 @@ const routes = [
1305
1779
  path: "no-content-types",
1306
1780
  Component: NoContentType
1307
1781
  },
1782
+ ...routes$2,
1308
1783
  ...routes$1
1309
1784
  ];
1310
1785
  const DocumentActions = ({ actions: actions2 }) => {
@@ -1373,12 +1848,14 @@ const DocumentActionButton = (action) => {
1373
1848
  /* @__PURE__ */ jsxRuntime.jsx(
1374
1849
  designSystem.Button,
1375
1850
  {
1376
- flex: 1,
1851
+ flex: "auto",
1377
1852
  startIcon: action.icon,
1378
1853
  disabled: action.disabled,
1379
1854
  onClick: handleClick(action),
1380
1855
  justifyContent: "center",
1381
1856
  variant: action.variant || "default",
1857
+ paddingTop: "7px",
1858
+ paddingBottom: "7px",
1382
1859
  children: action.label
1383
1860
  }
1384
1861
  ),
@@ -1386,7 +1863,7 @@ const DocumentActionButton = (action) => {
1386
1863
  DocumentActionConfirmDialog,
1387
1864
  {
1388
1865
  ...action.dialog,
1389
- variant: action.variant,
1866
+ variant: action.dialog?.variant ?? action.variant,
1390
1867
  isOpen: dialogId === action.id,
1391
1868
  onClose: handleClose
1392
1869
  }
@@ -1401,6 +1878,11 @@ const DocumentActionButton = (action) => {
1401
1878
  ) : null
1402
1879
  ] });
1403
1880
  };
1881
+ const MenuItem = styledComponents.styled(designSystem.Menu.Item)`
1882
+ &:hover {
1883
+ background: ${({ theme, isVariantDanger, isDisabled }) => isVariantDanger && !isDisabled ? theme.colors.danger100 : "neutral"};
1884
+ }
1885
+ `;
1404
1886
  const DocumentActionsMenu = ({
1405
1887
  actions: actions2,
1406
1888
  children,
@@ -1443,49 +1925,48 @@ const DocumentActionsMenu = ({
1443
1925
  disabled: isDisabled,
1444
1926
  size: "S",
1445
1927
  endIcon: null,
1446
- paddingTop: "7px",
1447
- paddingLeft: "9px",
1448
- paddingRight: "9px",
1928
+ paddingTop: "4px",
1929
+ paddingLeft: "7px",
1930
+ paddingRight: "7px",
1449
1931
  variant,
1450
1932
  children: [
1451
1933
  /* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
1452
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { as: "span", children: label || formatMessage({
1934
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { tag: "span", children: label || formatMessage({
1453
1935
  id: "content-manager.containers.edit.panels.default.more-actions",
1454
1936
  defaultMessage: "More document actions"
1455
1937
  }) })
1456
1938
  ]
1457
1939
  }
1458
1940
  ),
1459
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { top: "4px", maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1941
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1460
1942
  actions2.map((action) => {
1461
1943
  return /* @__PURE__ */ jsxRuntime.jsx(
1462
- designSystem.Menu.Item,
1944
+ MenuItem,
1463
1945
  {
1464
1946
  disabled: action.disabled,
1465
1947
  onSelect: handleClick(action),
1466
1948
  display: "block",
1467
- children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
1468
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { color: convertActionVariantToColor(action.variant), gap: 2, as: "span", children: [
1469
- action.icon,
1470
- action.label
1471
- ] }),
1472
- action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
1473
- designSystem.Flex,
1474
- {
1475
- alignItems: "center",
1476
- background: "alternative100",
1477
- borderStyle: "solid",
1478
- borderColor: "alternative200",
1479
- borderWidth: "1px",
1480
- height: 5,
1481
- paddingLeft: 2,
1482
- paddingRight: 2,
1483
- hasRadius: true,
1484
- color: "alternative600",
1485
- children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
1486
- }
1487
- )
1488
- ] })
1949
+ isVariantDanger: action.variant === "danger",
1950
+ isDisabled: action.disabled,
1951
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(
1952
+ designSystem.Flex,
1953
+ {
1954
+ color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
1955
+ gap: 2,
1956
+ tag: "span",
1957
+ children: [
1958
+ /* @__PURE__ */ jsxRuntime.jsx(
1959
+ designSystem.Flex,
1960
+ {
1961
+ tag: "span",
1962
+ color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
1963
+ children: action.icon
1964
+ }
1965
+ ),
1966
+ action.label
1967
+ ]
1968
+ }
1969
+ ) })
1489
1970
  },
1490
1971
  action.id
1491
1972
  );
@@ -1527,6 +2008,18 @@ const convertActionVariantToColor = (variant = "secondary") => {
1527
2008
  return "primary600";
1528
2009
  }
1529
2010
  };
2011
+ const convertActionVariantToIconColor = (variant = "secondary") => {
2012
+ switch (variant) {
2013
+ case "danger":
2014
+ return "danger600";
2015
+ case "secondary":
2016
+ return "neutral500";
2017
+ case "success":
2018
+ return "success600";
2019
+ default:
2020
+ return "primary600";
2021
+ }
2022
+ };
1530
2023
  const DocumentActionConfirmDialog = ({
1531
2024
  onClose,
1532
2025
  onCancel,
@@ -1549,61 +2042,54 @@ const DocumentActionConfirmDialog = ({
1549
2042
  }
1550
2043
  onClose();
1551
2044
  };
1552
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog, { isOpen, title, onClose: handleClose, children: [
1553
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.DialogBody, { children: content }),
1554
- /* @__PURE__ */ jsxRuntime.jsx(
1555
- designSystem.DialogFooter,
1556
- {
1557
- startAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleClose, variant: "tertiary", children: formatMessage({
1558
- id: "app.components.Button.cancel",
1559
- defaultMessage: "Cancel"
1560
- }) }),
1561
- endAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
1562
- id: "app.components.Button.confirm",
1563
- defaultMessage: "Confirm"
1564
- }) })
1565
- }
1566
- )
1567
- ] });
2045
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2046
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
2047
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
2048
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
2049
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
2050
+ id: "app.components.Button.cancel",
2051
+ defaultMessage: "Cancel"
2052
+ }) }) }),
2053
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
2054
+ id: "app.components.Button.confirm",
2055
+ defaultMessage: "Confirm"
2056
+ }) })
2057
+ ] })
2058
+ ] }) });
1568
2059
  };
1569
2060
  const DocumentActionModal = ({
1570
2061
  isOpen,
1571
2062
  title,
1572
2063
  onClose,
1573
2064
  footer: Footer,
1574
- content,
2065
+ content: Content,
1575
2066
  onModalClose
1576
2067
  }) => {
1577
- const id = React__namespace.useId();
1578
- if (!isOpen) {
1579
- return null;
1580
- }
1581
2068
  const handleClose = () => {
1582
2069
  if (onClose) {
1583
2070
  onClose();
1584
2071
  }
1585
2072
  onModalClose();
1586
2073
  };
1587
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.ModalLayout, { borderRadius: "4px", overflow: "hidden", onClose: handleClose, labelledBy: id, children: [
1588
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", textColor: "neutral800", as: "h2", id, children: title }) }),
1589
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalBody, { children: content }),
1590
- /* @__PURE__ */ jsxRuntime.jsx(
1591
- designSystem.Box,
1592
- {
1593
- paddingTop: 4,
1594
- paddingBottom: 4,
1595
- paddingLeft: 5,
1596
- paddingRight: 5,
1597
- borderWidth: "1px 0 0 0",
1598
- borderStyle: "solid",
1599
- borderColor: "neutral150",
1600
- background: "neutral100",
1601
- children: typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
1602
- }
1603
- )
1604
- ] });
2074
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
2075
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: title }) }),
2076
+ typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: Content }),
2077
+ typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
2078
+ ] }) });
2079
+ };
2080
+ const transformData = (data) => {
2081
+ if (Array.isArray(data)) {
2082
+ return data.map(transformData);
2083
+ }
2084
+ if (typeof data === "object" && data !== null) {
2085
+ if ("apiData" in data) {
2086
+ return data.apiData;
2087
+ }
2088
+ return mapValues__default.default(transformData)(data);
2089
+ }
2090
+ return data;
1605
2091
  };
1606
- const PublishAction = ({
2092
+ const PublishAction$1 = ({
1607
2093
  activeTab,
1608
2094
  documentId,
1609
2095
  model,
@@ -1615,13 +2101,17 @@ const PublishAction = ({
1615
2101
  const navigate = reactRouterDom.useNavigate();
1616
2102
  const { toggleNotification } = strapiAdmin.useNotification();
1617
2103
  const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
2104
+ const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
1618
2105
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
1619
2106
  const { formatMessage } = reactIntl.useIntl();
1620
- const { canPublish, canCreate, canUpdate } = useDocumentRBAC(
1621
- "PublishAction",
1622
- ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
1623
- );
2107
+ const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
1624
2108
  const { publish } = useDocumentActions();
2109
+ const [
2110
+ countDraftRelations,
2111
+ { isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
2112
+ ] = useLazyGetDraftRelationCountQuery();
2113
+ const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
2114
+ const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
1625
2115
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1626
2116
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
1627
2117
  const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
@@ -1630,10 +2120,105 @@ const PublishAction = ({
1630
2120
  const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
1631
2121
  const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
1632
2122
  const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
2123
+ React__namespace.useEffect(() => {
2124
+ if (isErrorDraftRelations) {
2125
+ toggleNotification({
2126
+ type: "danger",
2127
+ message: formatMessage({
2128
+ id: getTranslation("error.records.fetch-draft-relatons"),
2129
+ defaultMessage: "An error occurred while fetching draft relations on this document."
2130
+ })
2131
+ });
2132
+ }
2133
+ }, [isErrorDraftRelations, toggleNotification, formatMessage]);
2134
+ React__namespace.useEffect(() => {
2135
+ const localDraftRelations = /* @__PURE__ */ new Set();
2136
+ const extractDraftRelations = (data) => {
2137
+ const relations = data.connect || [];
2138
+ relations.forEach((relation) => {
2139
+ if (relation.status === "draft") {
2140
+ localDraftRelations.add(relation.id);
2141
+ }
2142
+ });
2143
+ };
2144
+ const traverseAndExtract = (data) => {
2145
+ Object.entries(data).forEach(([key, value]) => {
2146
+ if (key === "connect" && Array.isArray(value)) {
2147
+ extractDraftRelations({ connect: value });
2148
+ } else if (typeof value === "object" && value !== null) {
2149
+ traverseAndExtract(value);
2150
+ }
2151
+ });
2152
+ };
2153
+ if (!documentId || modified) {
2154
+ traverseAndExtract(formValues);
2155
+ setLocalCountOfDraftRelations(localDraftRelations.size);
2156
+ }
2157
+ }, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
2158
+ React__namespace.useEffect(() => {
2159
+ if (!document || !document.documentId || isListView) {
2160
+ return;
2161
+ }
2162
+ const fetchDraftRelationsCount = async () => {
2163
+ const { data, error } = await countDraftRelations({
2164
+ collectionType,
2165
+ model,
2166
+ documentId,
2167
+ params
2168
+ });
2169
+ if (error) {
2170
+ throw error;
2171
+ }
2172
+ if (data) {
2173
+ setServerCountOfDraftRelations(data.data);
2174
+ }
2175
+ };
2176
+ fetchDraftRelationsCount();
2177
+ }, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
1633
2178
  const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1634
2179
  if (!schema?.options?.draftAndPublish) {
1635
2180
  return null;
1636
2181
  }
2182
+ const performPublish = async () => {
2183
+ setSubmitting(true);
2184
+ try {
2185
+ const { errors } = await validate(true, {
2186
+ status: "published"
2187
+ });
2188
+ if (errors) {
2189
+ toggleNotification({
2190
+ type: "danger",
2191
+ message: formatMessage({
2192
+ id: "content-manager.validation.error",
2193
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
2194
+ })
2195
+ });
2196
+ return;
2197
+ }
2198
+ const res = await publish(
2199
+ {
2200
+ collectionType,
2201
+ model,
2202
+ documentId,
2203
+ params
2204
+ },
2205
+ transformData(formValues)
2206
+ );
2207
+ if ("data" in res && collectionType !== SINGLE_TYPES) {
2208
+ navigate({
2209
+ pathname: `../${collectionType}/${model}/${res.data.documentId}`,
2210
+ search: rawQuery
2211
+ });
2212
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2213
+ setErrors(formatValidationErrors(res.error));
2214
+ }
2215
+ } finally {
2216
+ setSubmitting(false);
2217
+ }
2218
+ };
2219
+ const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
2220
+ const enableDraftRelationsCount = false;
2221
+ const hasDraftRelations = enableDraftRelationsCount;
1637
2222
  return {
1638
2223
  /**
1639
2224
  * Disabled when:
@@ -1643,52 +2228,39 @@ const PublishAction = ({
1643
2228
  * - the document is already published & not modified
1644
2229
  * - the document is being created & not modified
1645
2230
  * - the user doesn't have the permission to publish
1646
- * - the user doesn't have the permission to create a new document
1647
- * - the user doesn't have the permission to update the document
1648
2231
  */
1649
- disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
2232
+ disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
1650
2233
  label: formatMessage({
1651
2234
  id: "app.utils.publish",
1652
2235
  defaultMessage: "Publish"
1653
2236
  }),
1654
2237
  onClick: async () => {
1655
- setSubmitting(true);
1656
- try {
1657
- const { errors } = await validate();
1658
- if (errors) {
1659
- toggleNotification({
1660
- type: "danger",
1661
- message: formatMessage({
1662
- id: "content-manager.validation.error",
1663
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1664
- })
1665
- });
1666
- return;
1667
- }
1668
- const res = await publish(
1669
- {
1670
- collectionType,
1671
- model,
1672
- documentId,
1673
- params
1674
- },
1675
- formValues
1676
- );
1677
- if ("data" in res && collectionType !== SINGLE_TYPES) {
1678
- navigate({
1679
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1680
- search: rawQuery
1681
- });
1682
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1683
- setErrors(formatValidationErrors(res.error));
2238
+ await performPublish();
2239
+ },
2240
+ dialog: hasDraftRelations ? {
2241
+ type: "dialog",
2242
+ variant: "danger",
2243
+ footer: null,
2244
+ title: formatMessage({
2245
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
2246
+ defaultMessage: "Confirmation"
2247
+ }),
2248
+ content: formatMessage(
2249
+ {
2250
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
2251
+ defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
2252
+ },
2253
+ {
2254
+ count: totalDraftRelations
1684
2255
  }
1685
- } finally {
1686
- setSubmitting(false);
2256
+ ),
2257
+ onConfirm: async () => {
2258
+ await performPublish();
1687
2259
  }
1688
- }
2260
+ } : void 0
1689
2261
  };
1690
2262
  };
1691
- PublishAction.type = "publish";
2263
+ PublishAction$1.type = "publish";
1692
2264
  const UpdateAction = ({
1693
2265
  activeTab,
1694
2266
  documentId,
@@ -1701,10 +2273,6 @@ const UpdateAction = ({
1701
2273
  const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
1702
2274
  const isCloning = cloneMatch !== null;
1703
2275
  const { formatMessage } = reactIntl.useIntl();
1704
- const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
1705
- canCreate: canCreate2,
1706
- canUpdate: canUpdate2
1707
- }));
1708
2276
  const { create, update, clone } = useDocumentActions();
1709
2277
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1710
2278
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
@@ -1721,18 +2289,18 @@ const UpdateAction = ({
1721
2289
  * - the form is submitting
1722
2290
  * - the document is not modified & we're not cloning (you can save a clone entity straight away)
1723
2291
  * - the active tab is the published tab
1724
- * - the user doesn't have the permission to create a new document
1725
- * - the user doesn't have the permission to update the document
1726
2292
  */
1727
- disabled: isSubmitting || !modified && !isCloning || activeTab === "published" || Boolean(!documentId && !canCreate || documentId && !canUpdate),
2293
+ disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
1728
2294
  label: formatMessage({
1729
- id: "content-manager.containers.Edit.save",
2295
+ id: "global.save",
1730
2296
  defaultMessage: "Save"
1731
2297
  }),
1732
2298
  onClick: async () => {
1733
2299
  setSubmitting(true);
1734
2300
  try {
1735
- const { errors } = await validate();
2301
+ const { errors } = await validate(true, {
2302
+ status: "draft"
2303
+ });
1736
2304
  if (errors) {
1737
2305
  toggleNotification({
1738
2306
  type: "danger",
@@ -1750,13 +2318,16 @@ const UpdateAction = ({
1750
2318
  documentId: cloneMatch.params.origin,
1751
2319
  params
1752
2320
  },
1753
- document
2321
+ transformData(document)
1754
2322
  );
1755
2323
  if ("data" in res) {
1756
- navigate({
1757
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1758
- search: rawQuery
1759
- });
2324
+ navigate(
2325
+ {
2326
+ pathname: `../${res.data.documentId}`,
2327
+ search: rawQuery
2328
+ },
2329
+ { relative: "path" }
2330
+ );
1760
2331
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1761
2332
  setErrors(formatValidationErrors(res.error));
1762
2333
  }
@@ -1768,7 +2339,7 @@ const UpdateAction = ({
1768
2339
  documentId,
1769
2340
  params
1770
2341
  },
1771
- document
2342
+ transformData(document)
1772
2343
  );
1773
2344
  if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1774
2345
  setErrors(formatValidationErrors(res.error));
@@ -1781,13 +2352,16 @@ const UpdateAction = ({
1781
2352
  model,
1782
2353
  params
1783
2354
  },
1784
- document
2355
+ transformData(document)
1785
2356
  );
1786
2357
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1787
- navigate({
1788
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1789
- search: rawQuery
1790
- });
2358
+ navigate(
2359
+ {
2360
+ pathname: `../${res.data.documentId}`,
2361
+ search: rawQuery
2362
+ },
2363
+ { replace: true, relative: "path" }
2364
+ );
1791
2365
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1792
2366
  setErrors(formatValidationErrors(res.error));
1793
2367
  }
@@ -1803,7 +2377,7 @@ const UNPUBLISH_DRAFT_OPTIONS = {
1803
2377
  KEEP: "keep",
1804
2378
  DISCARD: "discard"
1805
2379
  };
1806
- const UnpublishAction = ({
2380
+ const UnpublishAction$1 = ({
1807
2381
  activeTab,
1808
2382
  documentId,
1809
2383
  model,
@@ -1819,10 +2393,8 @@ const UnpublishAction = ({
1819
2393
  const { toggleNotification } = strapiAdmin.useNotification();
1820
2394
  const [shouldKeepDraft, setShouldKeepDraft] = React__namespace.useState(true);
1821
2395
  const isDocumentModified = document?.status === "modified";
1822
- const handleChange = (e) => {
1823
- if ("value" in e.target) {
1824
- setShouldKeepDraft(e.target.value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
1825
- }
2396
+ const handleChange = (value) => {
2397
+ setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
1826
2398
  };
1827
2399
  if (!schema?.options?.draftAndPublish) {
1828
2400
  return null;
@@ -1833,7 +2405,7 @@ const UnpublishAction = ({
1833
2405
  id: "app.utils.unpublish",
1834
2406
  defaultMessage: "Unpublish"
1835
2407
  }),
1836
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
2408
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
1837
2409
  onClick: async () => {
1838
2410
  if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
1839
2411
  if (!documentId) {
@@ -1866,45 +2438,30 @@ const UnpublishAction = ({
1866
2438
  content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "flex-start", direction: "column", gap: 6, children: [
1867
2439
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", direction: "column", gap: 2, children: [
1868
2440
  /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
1869
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "p", variant: "omega", textAlign: "center", children: formatMessage({
2441
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
1870
2442
  id: "content-manager.actions.unpublish.dialog.body",
1871
2443
  defaultMessage: "Are you sure?"
1872
2444
  }) })
1873
2445
  ] }),
1874
2446
  /* @__PURE__ */ jsxRuntime.jsxs(
1875
- designSystem.Flex,
2447
+ designSystem.Radio.Group,
1876
2448
  {
1877
- onChange: handleChange,
1878
- direction: "column",
1879
- alignItems: "flex-start",
1880
- as: "fieldset",
1881
- gap: 3,
2449
+ defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
2450
+ name: "discard-options",
2451
+ "aria-label": formatMessage({
2452
+ id: "content-manager.actions.unpublish.dialog.radio-label",
2453
+ defaultMessage: "Choose an option to unpublish the document."
2454
+ }),
2455
+ onValueChange: handleChange,
1882
2456
  children: [
1883
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { as: "legend" }),
1884
- /* @__PURE__ */ jsxRuntime.jsx(
1885
- designSystem.Radio,
1886
- {
1887
- checked: shouldKeepDraft,
1888
- value: UNPUBLISH_DRAFT_OPTIONS.KEEP,
1889
- name: "discard-options",
1890
- children: formatMessage({
1891
- id: "content-manager.actions.unpublish.dialog.option.keep-draft",
1892
- defaultMessage: "Keep draft"
1893
- })
1894
- }
1895
- ),
1896
- /* @__PURE__ */ jsxRuntime.jsx(
1897
- designSystem.Radio,
1898
- {
1899
- checked: !shouldKeepDraft,
1900
- value: UNPUBLISH_DRAFT_OPTIONS.DISCARD,
1901
- name: "discard-options",
1902
- children: formatMessage({
1903
- id: "content-manager.actions.unpublish.dialog.option.replace-draft",
1904
- defaultMessage: "Replace draft"
1905
- })
1906
- }
1907
- )
2457
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
2458
+ id: "content-manager.actions.unpublish.dialog.option.keep-draft",
2459
+ defaultMessage: "Keep draft"
2460
+ }) }),
2461
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
2462
+ id: "content-manager.actions.unpublish.dialog.option.replace-draft",
2463
+ defaultMessage: "Replace draft"
2464
+ }) })
1908
2465
  ]
1909
2466
  }
1910
2467
  )
@@ -1937,7 +2494,7 @@ const UnpublishAction = ({
1937
2494
  position: ["panel", "table-row"]
1938
2495
  };
1939
2496
  };
1940
- UnpublishAction.type = "unpublish";
2497
+ UnpublishAction$1.type = "unpublish";
1941
2498
  const DiscardAction = ({
1942
2499
  activeTab,
1943
2500
  documentId,
@@ -1960,7 +2517,7 @@ const DiscardAction = ({
1960
2517
  id: "content-manager.actions.discard.label",
1961
2518
  defaultMessage: "Discard changes"
1962
2519
  }),
1963
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
2520
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
1964
2521
  position: ["panel", "table-row"],
1965
2522
  variant: "danger",
1966
2523
  dialog: {
@@ -1971,7 +2528,7 @@ const DiscardAction = ({
1971
2528
  }),
1972
2529
  content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
1973
2530
  /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
1974
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "p", variant: "omega", textAlign: "center", children: formatMessage({
2531
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
1975
2532
  id: "content-manager.actions.discard.dialog.body",
1976
2533
  defaultMessage: "Are you sure?"
1977
2534
  }) })
@@ -1988,12 +2545,7 @@ const DiscardAction = ({
1988
2545
  };
1989
2546
  };
1990
2547
  DiscardAction.type = "discard";
1991
- const StyledCrossCircle = styled__default.default(Icons.CrossCircle)`
1992
- path {
1993
- fill: currentColor;
1994
- }
1995
- `;
1996
- const DEFAULT_ACTIONS = [PublishAction, UpdateAction, UnpublishAction, DiscardAction];
2548
+ const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
1997
2549
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
1998
2550
  const RelativeTime = React__namespace.forwardRef(
1999
2551
  ({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
@@ -2005,7 +2557,7 @@ const RelativeTime = React__namespace.forwardRef(
2005
2557
  });
2006
2558
  const unit = intervals.find((intervalUnit) => {
2007
2559
  return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
2008
- });
2560
+ }) ?? "seconds";
2009
2561
  const relativeTime = dateFns.isPast(timestamp) ? -interval[unit] : interval[unit];
2010
2562
  const customInterval = customIntervals.find(
2011
2563
  (custom) => interval[custom.unit] < custom.threshold
@@ -2039,34 +2591,34 @@ const getDisplayName = ({
2039
2591
  return email ?? "";
2040
2592
  };
2041
2593
  const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
2042
- const DocumentStatus = ({ status = "draft", ...restProps }) => {
2043
- const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
2044
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "span", variant: "omega", fontWeight: "bold", children: capitalise(status) }) });
2594
+ const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
2595
+ const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
2596
+ const { formatMessage } = reactIntl.useIntl();
2597
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
2598
+ id: `content-manager.containers.List.${status}`,
2599
+ defaultMessage: capitalise(status)
2600
+ }) }) });
2045
2601
  };
2046
2602
  const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2047
2603
  const { formatMessage } = reactIntl.useIntl();
2048
2604
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2605
+ const params = reactRouterDom.useParams();
2049
2606
  const title = isCreating ? formatMessage({
2050
2607
  id: "content-manager.containers.edit.title.new",
2051
2608
  defaultMessage: "Create an entry"
2052
2609
  }) : documentTitle;
2053
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 8, paddingBottom: 4, gap: 3, children: [
2054
- /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
2055
- /* @__PURE__ */ jsxRuntime.jsxs(
2056
- designSystem.Flex,
2610
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
2611
+ /* @__PURE__ */ jsxRuntime.jsx(
2612
+ strapiAdmin.BackButton,
2057
2613
  {
2058
- width: "100%",
2059
- justifyContent: "space-between",
2060
- paddingTop: 1,
2061
- gap: "80px",
2062
- alignItems: "flex-start",
2063
- children: [
2064
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", as: "h1", children: title }),
2065
- /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2066
- ]
2614
+ fallback: params.collectionType === SINGLE_TYPES ? void 0 : `../${COLLECTION_TYPES}/${params.slug}`
2067
2615
  }
2068
2616
  ),
2069
- status ? /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
2617
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
2618
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2619
+ /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2620
+ ] }),
2621
+ status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
2070
2622
  ] });
2071
2623
  };
2072
2624
  const HeaderToolbar = () => {
@@ -2149,12 +2701,12 @@ const Information = ({ activeTab }) => {
2149
2701
  isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
2150
2702
  label: formatMessage({
2151
2703
  id: "content-manager.containers.edit.information.last-published.label",
2152
- defaultMessage: "Last published"
2704
+ defaultMessage: "Published"
2153
2705
  }),
2154
2706
  value: formatMessage(
2155
2707
  {
2156
2708
  id: "content-manager.containers.edit.information.last-published.value",
2157
- defaultMessage: `Published {time}{isAnonymous, select, true {} other { by {author}}}`
2709
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2158
2710
  },
2159
2711
  {
2160
2712
  time: /* @__PURE__ */ jsxRuntime.jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
@@ -2167,12 +2719,12 @@ const Information = ({ activeTab }) => {
2167
2719
  isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
2168
2720
  label: formatMessage({
2169
2721
  id: "content-manager.containers.edit.information.last-draft.label",
2170
- defaultMessage: "Last draft"
2722
+ defaultMessage: "Updated"
2171
2723
  }),
2172
2724
  value: formatMessage(
2173
2725
  {
2174
2726
  id: "content-manager.containers.edit.information.last-draft.value",
2175
- defaultMessage: `Modified {time}{isAnonymous, select, true {} other { by {author}}}`
2727
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2176
2728
  },
2177
2729
  {
2178
2730
  time: /* @__PURE__ */ jsxRuntime.jsx(
@@ -2190,12 +2742,12 @@ const Information = ({ activeTab }) => {
2190
2742
  isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
2191
2743
  label: formatMessage({
2192
2744
  id: "content-manager.containers.edit.information.document.label",
2193
- defaultMessage: "Document"
2745
+ defaultMessage: "Created"
2194
2746
  }),
2195
2747
  value: formatMessage(
2196
2748
  {
2197
2749
  id: "content-manager.containers.edit.information.document.value",
2198
- defaultMessage: `Created {time}{isAnonymous, select, true {} other { by {author}}}`
2750
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2199
2751
  },
2200
2752
  {
2201
2753
  time: /* @__PURE__ */ jsxRuntime.jsx(
@@ -2218,7 +2770,7 @@ const Information = ({ activeTab }) => {
2218
2770
  borderColor: "neutral150",
2219
2771
  direction: "column",
2220
2772
  marginTop: 2,
2221
- as: "dl",
2773
+ tag: "dl",
2222
2774
  padding: 5,
2223
2775
  gap: 3,
2224
2776
  alignItems: "flex-start",
@@ -2226,32 +2778,84 @@ const Information = ({ activeTab }) => {
2226
2778
  marginRight: "-0.4rem",
2227
2779
  width: "calc(100% + 8px)",
2228
2780
  children: information.map((info) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 1, direction: "column", alignItems: "flex-start", children: [
2229
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
2230
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "dd", variant: "pi", textColor: "neutral600", children: info.value })
2781
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
2782
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
2231
2783
  ] }, info.label))
2232
2784
  }
2233
2785
  );
2234
2786
  };
2235
2787
  const HeaderActions = ({ actions: actions2 }) => {
2236
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: actions2.map((action) => {
2237
- if ("options" in action) {
2788
+ const [dialogId, setDialogId] = React__namespace.useState(null);
2789
+ const handleClick = (action) => async (e) => {
2790
+ if (!("options" in action)) {
2791
+ const { onClick = () => false, dialog, id } = action;
2792
+ const muteDialog = await onClick(e);
2793
+ if (dialog && !muteDialog) {
2794
+ e.preventDefault();
2795
+ setDialogId(id);
2796
+ }
2797
+ }
2798
+ };
2799
+ const handleClose = () => {
2800
+ setDialogId(null);
2801
+ };
2802
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, children: actions2.map((action) => {
2803
+ if (action.options) {
2238
2804
  return /* @__PURE__ */ jsxRuntime.jsx(
2239
2805
  designSystem.SingleSelect,
2240
2806
  {
2241
2807
  size: "S",
2242
- disabled: action.disabled,
2243
- "aria-label": action.label,
2244
2808
  onChange: action.onSelect,
2245
- value: action.value,
2809
+ "aria-label": action.label,
2810
+ ...action,
2246
2811
  children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
2247
2812
  },
2248
2813
  action.id
2249
2814
  );
2250
2815
  } else {
2251
- return null;
2816
+ if (action.type === "icon") {
2817
+ return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
2818
+ /* @__PURE__ */ jsxRuntime.jsx(
2819
+ designSystem.IconButton,
2820
+ {
2821
+ disabled: action.disabled,
2822
+ label: action.label,
2823
+ size: "S",
2824
+ onClick: handleClick(action),
2825
+ children: action.icon
2826
+ }
2827
+ ),
2828
+ action.dialog ? /* @__PURE__ */ jsxRuntime.jsx(
2829
+ HeaderActionDialog,
2830
+ {
2831
+ ...action.dialog,
2832
+ isOpen: dialogId === action.id,
2833
+ onClose: handleClose
2834
+ }
2835
+ ) : null
2836
+ ] }, action.id);
2837
+ }
2252
2838
  }
2253
2839
  }) });
2254
2840
  };
2841
+ const HeaderActionDialog = ({
2842
+ onClose,
2843
+ onCancel,
2844
+ title,
2845
+ content: Content,
2846
+ isOpen
2847
+ }) => {
2848
+ const handleClose = async () => {
2849
+ if (onCancel) {
2850
+ await onCancel();
2851
+ }
2852
+ onClose();
2853
+ };
2854
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2855
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
2856
+ typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content
2857
+ ] }) });
2858
+ };
2255
2859
  const ConfigureTheViewAction = ({ collectionType, model }) => {
2256
2860
  const navigate = reactRouterDom.useNavigate();
2257
2861
  const { formatMessage } = reactIntl.useIntl();
@@ -2260,7 +2864,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2260
2864
  id: "app.links.configure-view",
2261
2865
  defaultMessage: "Configure the view"
2262
2866
  }),
2263
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCog, {}),
2867
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ListPlus, {}),
2264
2868
  onClick: () => {
2265
2869
  navigate(`../${collectionType}/${model}/configurations/edit`);
2266
2870
  },
@@ -2268,11 +2872,6 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2268
2872
  };
2269
2873
  };
2270
2874
  ConfigureTheViewAction.type = "configure-the-view";
2271
- const StyledCog = styled__default.default(Icons.Cog)`
2272
- path {
2273
- fill: currentColor;
2274
- }
2275
- `;
2276
2875
  const EditTheModelAction = ({ model }) => {
2277
2876
  const navigate = reactRouterDom.useNavigate();
2278
2877
  const { formatMessage } = reactIntl.useIntl();
@@ -2281,7 +2880,7 @@ const EditTheModelAction = ({ model }) => {
2281
2880
  id: "content-manager.link-to-ctb",
2282
2881
  defaultMessage: "Edit the model"
2283
2882
  }),
2284
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledPencil$1, {}),
2883
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {}),
2285
2884
  onClick: () => {
2286
2885
  navigate(`/plugins/content-type-builder/content-types/${model}`);
2287
2886
  },
@@ -2289,12 +2888,7 @@ const EditTheModelAction = ({ model }) => {
2289
2888
  };
2290
2889
  };
2291
2890
  EditTheModelAction.type = "edit-the-model";
2292
- const StyledPencil$1 = styled__default.default(Icons.Pencil)`
2293
- path {
2294
- fill: currentColor;
2295
- }
2296
- `;
2297
- const DeleteAction = ({ documentId, model, collectionType, document }) => {
2891
+ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2298
2892
  const navigate = reactRouterDom.useNavigate();
2299
2893
  const { formatMessage } = reactIntl.useIntl();
2300
2894
  const listViewPathMatch = reactRouterDom.useMatch(LIST_PATH);
@@ -2302,13 +2896,17 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2302
2896
  const { delete: deleteAction } = useDocumentActions();
2303
2897
  const { toggleNotification } = strapiAdmin.useNotification();
2304
2898
  const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
2899
+ const isLocalized = document?.locale != null;
2305
2900
  return {
2306
2901
  disabled: !canDelete || !document,
2307
- label: formatMessage({
2308
- id: "content-manager.actions.delete.label",
2309
- defaultMessage: "Delete document"
2310
- }),
2311
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledTrash, {}),
2902
+ label: formatMessage(
2903
+ {
2904
+ id: "content-manager.actions.delete.label",
2905
+ defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
2906
+ },
2907
+ { isLocalized }
2908
+ ),
2909
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
2312
2910
  dialog: {
2313
2911
  type: "dialog",
2314
2912
  title: formatMessage({
@@ -2317,7 +2915,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2317
2915
  }),
2318
2916
  content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
2319
2917
  /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
2320
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "p", variant: "omega", textAlign: "center", children: formatMessage({
2918
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
2321
2919
  id: "content-manager.actions.delete.dialog.body",
2322
2920
  defaultMessage: "Are you sure?"
2323
2921
  }) })
@@ -2362,13 +2960,8 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2362
2960
  position: ["header", "table-row"]
2363
2961
  };
2364
2962
  };
2365
- DeleteAction.type = "delete";
2366
- const StyledTrash = styled__default.default(Icons.Trash)`
2367
- path {
2368
- fill: currentColor;
2369
- }
2370
- `;
2371
- const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction];
2963
+ DeleteAction$1.type = "delete";
2964
+ const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2372
2965
  const Panels = () => {
2373
2966
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2374
2967
  const [
@@ -2402,7 +2995,7 @@ const ActionsPanel = () => {
2402
2995
  return {
2403
2996
  title: formatMessage({
2404
2997
  id: "content-manager.containers.edit.panels.default.title",
2405
- defaultMessage: "Document"
2998
+ defaultMessage: "Entry"
2406
2999
  }),
2407
3000
  content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
2408
3001
  };
@@ -2442,7 +3035,7 @@ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
2442
3035
  designSystem.Flex,
2443
3036
  {
2444
3037
  ref,
2445
- as: "aside",
3038
+ tag: "aside",
2446
3039
  "aria-labelledby": "additional-information",
2447
3040
  background: "neutral0",
2448
3041
  borderColor: "neutral150",
@@ -2457,24 +3050,601 @@ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
2457
3050
  justifyContent: "stretch",
2458
3051
  alignItems: "flex-start",
2459
3052
  children: [
2460
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
3053
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
2461
3054
  children
2462
3055
  ]
2463
3056
  }
2464
3057
  );
2465
3058
  });
2466
- const DEFAULT_BULK_ACTIONS = [];
2467
- const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
3059
+ const ConfirmBulkActionDialog = ({
3060
+ onToggleDialog,
3061
+ isOpen = false,
3062
+ dialogBody,
3063
+ endAction
3064
+ }) => {
2468
3065
  const { formatMessage } = reactIntl.useIntl();
2469
- const getDefaultErrorMessage = (reason) => {
2470
- switch (reason) {
2471
- case "relation":
2472
- return "Duplicating the relation could remove it from the original entry.";
2473
- case "unique":
2474
- return "Identical values in a unique field are not allowed";
2475
- default:
2476
- return reason;
2477
- }
3066
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
3067
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
3068
+ id: "app.components.ConfirmDialog.title",
3069
+ defaultMessage: "Confirmation"
3070
+ }) }),
3071
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3072
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3073
+ dialogBody
3074
+ ] }) }),
3075
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
3076
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { fullWidth: true, onClick: onToggleDialog, variant: "tertiary", children: formatMessage({
3077
+ id: "app.components.Button.cancel",
3078
+ defaultMessage: "Cancel"
3079
+ }) }) }),
3080
+ endAction
3081
+ ] })
3082
+ ] }) });
3083
+ };
3084
+ const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
3085
+ const ConfirmDialogPublishAll = ({
3086
+ isOpen,
3087
+ onToggleDialog,
3088
+ isConfirmButtonLoading = false,
3089
+ onConfirm
3090
+ }) => {
3091
+ const { formatMessage } = reactIntl.useIntl();
3092
+ const selectedEntries = strapiAdmin.useTable("ConfirmDialogPublishAll", (state) => state.selectedRows);
3093
+ const { toggleNotification } = strapiAdmin.useNotification();
3094
+ const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
3095
+ const { model, schema } = useDoc();
3096
+ const [{ query }] = strapiAdmin.useQueryParams();
3097
+ const enableDraftRelationsCount = false;
3098
+ const {
3099
+ data: countDraftRelations = 0,
3100
+ isLoading,
3101
+ error
3102
+ } = useGetManyDraftRelationCountQuery(
3103
+ {
3104
+ model,
3105
+ documentIds: selectedEntries.map((entry) => entry.documentId),
3106
+ locale: query?.plugins?.i18n?.locale
3107
+ },
3108
+ {
3109
+ skip: !enableDraftRelationsCount
3110
+ }
3111
+ );
3112
+ React__namespace.useEffect(() => {
3113
+ if (error) {
3114
+ toggleNotification({ type: "danger", message: formatAPIError(error) });
3115
+ }
3116
+ }, [error, formatAPIError, toggleNotification]);
3117
+ if (error) {
3118
+ return null;
3119
+ }
3120
+ return /* @__PURE__ */ jsxRuntime.jsx(
3121
+ ConfirmBulkActionDialog,
3122
+ {
3123
+ isOpen: isOpen && !isLoading,
3124
+ onToggleDialog,
3125
+ dialogBody: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3126
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: [
3127
+ countDraftRelations > 0 && formatMessage(
3128
+ {
3129
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
3130
+ defaultMessage: "<b>{count} {count, plural, one { relation } other { relations } } out of {entities} { entities, plural, one { entry } other { entries } } {count, plural, one { is } other { are } }</b> not published yet and might lead to unexpected behavior. "
3131
+ },
3132
+ {
3133
+ b: BoldChunk$1,
3134
+ count: countDraftRelations,
3135
+ entities: selectedEntries.length
3136
+ }
3137
+ ),
3138
+ formatMessage({
3139
+ id: getTranslation("popUpWarning.bodyMessage.contentType.publish.all"),
3140
+ defaultMessage: "Are you sure you want to publish these entries?"
3141
+ })
3142
+ ] }),
3143
+ schema?.pluginOptions && "i18n" in schema.pluginOptions && schema?.pluginOptions.i18n && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", textAlign: "center", children: formatMessage(
3144
+ {
3145
+ id: getTranslation("Settings.list.actions.publishAdditionalInfos"),
3146
+ defaultMessage: "This will publish the active locale versions <em>(from Internationalization)</em>"
3147
+ },
3148
+ {
3149
+ em: Emphasis
3150
+ }
3151
+ ) })
3152
+ ] }),
3153
+ endAction: /* @__PURE__ */ jsxRuntime.jsx(
3154
+ designSystem.Button,
3155
+ {
3156
+ onClick: onConfirm,
3157
+ variant: "secondary",
3158
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Check, {}),
3159
+ loading: isConfirmButtonLoading,
3160
+ children: formatMessage({
3161
+ id: "app.utils.publish",
3162
+ defaultMessage: "Publish"
3163
+ })
3164
+ }
3165
+ )
3166
+ }
3167
+ );
3168
+ };
3169
+ const TypographyMaxWidth = styledComponents.styled(designSystem.Typography)`
3170
+ max-width: 300px;
3171
+ `;
3172
+ const formatErrorMessages = (errors, parentKey, formatMessage) => {
3173
+ const messages = [];
3174
+ Object.entries(errors).forEach(([key, value]) => {
3175
+ const currentKey = parentKey ? `${parentKey}.${key}` : key;
3176
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
3177
+ if ("id" in value && "defaultMessage" in value) {
3178
+ messages.push(
3179
+ formatMessage(
3180
+ {
3181
+ id: `${value.id}.withField`,
3182
+ defaultMessage: value.defaultMessage
3183
+ },
3184
+ { field: currentKey }
3185
+ )
3186
+ );
3187
+ } else {
3188
+ messages.push(
3189
+ ...formatErrorMessages(
3190
+ // @ts-expect-error TODO: check why value is not compatible with FormErrors
3191
+ value,
3192
+ currentKey,
3193
+ formatMessage
3194
+ )
3195
+ );
3196
+ }
3197
+ } else {
3198
+ messages.push(
3199
+ formatMessage(
3200
+ {
3201
+ id: `${value}.withField`,
3202
+ defaultMessage: value
3203
+ },
3204
+ { field: currentKey }
3205
+ )
3206
+ );
3207
+ }
3208
+ });
3209
+ return messages;
3210
+ };
3211
+ const EntryValidationText = ({ validationErrors, status }) => {
3212
+ const { formatMessage } = reactIntl.useIntl();
3213
+ if (validationErrors) {
3214
+ const validationErrorsMessages = formatErrorMessages(validationErrors, "", formatMessage).join(
3215
+ " "
3216
+ );
3217
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3218
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.CrossCircle, { fill: "danger600" }),
3219
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsxRuntime.jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
3220
+ ] });
3221
+ }
3222
+ if (status === "published") {
3223
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3224
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
3225
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
3226
+ id: "content-manager.bulk-publish.already-published",
3227
+ defaultMessage: "Already Published"
3228
+ }) })
3229
+ ] });
3230
+ }
3231
+ if (status === "modified") {
3232
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3233
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.ArrowsCounterClockwise, { fill: "alternative600" }),
3234
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
3235
+ id: "content-manager.bulk-publish.modified",
3236
+ defaultMessage: "Ready to publish changes"
3237
+ }) })
3238
+ ] });
3239
+ }
3240
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3241
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
3242
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
3243
+ id: "app.utils.ready-to-publish",
3244
+ defaultMessage: "Ready to publish"
3245
+ }) })
3246
+ ] });
3247
+ };
3248
+ const TABLE_HEADERS = [
3249
+ { name: "id", label: "id" },
3250
+ { name: "name", label: "name" },
3251
+ { name: "status", label: "status" },
3252
+ { name: "publicationStatus", label: "Publication status" }
3253
+ ];
3254
+ const SelectedEntriesTableContent = ({
3255
+ isPublishing,
3256
+ rowsToDisplay = [],
3257
+ entriesToPublish = [],
3258
+ validationErrors = {}
3259
+ }) => {
3260
+ const { pathname } = reactRouterDom.useLocation();
3261
+ const { formatMessage } = reactIntl.useIntl();
3262
+ const {
3263
+ list: {
3264
+ settings: { mainField }
3265
+ }
3266
+ } = useDocLayout();
3267
+ const shouldDisplayMainField = mainField != null && mainField !== "id";
3268
+ return /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Content, { children: [
3269
+ /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Head, { children: [
3270
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.HeaderCheckboxCell, {}),
3271
+ TABLE_HEADERS.filter((head) => head.name !== "name" || shouldDisplayMainField).map(
3272
+ (head) => /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.HeaderCell, { ...head }, head.name)
3273
+ )
3274
+ ] }),
3275
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Loading, {}),
3276
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Body, { children: rowsToDisplay.map((row, index2) => /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Row, { children: [
3277
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.CheckboxCell, { id: row.id }),
3278
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row.id }) }),
3279
+ shouldDisplayMainField && /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row[mainField] }) }),
3280
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: row.status, maxWidth: "min-content" }) }),
3281
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: isPublishing && entriesToPublish.includes(row.documentId) ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3282
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
3283
+ id: "content-manager.success.record.publishing",
3284
+ defaultMessage: "Publishing..."
3285
+ }) }),
3286
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Loader, { small: true })
3287
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
3288
+ EntryValidationText,
3289
+ {
3290
+ validationErrors: validationErrors[row.documentId],
3291
+ status: row.status
3292
+ }
3293
+ ) }),
3294
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
3295
+ designSystem.IconButton,
3296
+ {
3297
+ tag: reactRouterDom.Link,
3298
+ to: {
3299
+ pathname: `${pathname}/${row.documentId}`,
3300
+ search: row.locale && `?plugins[i18n][locale]=${row.locale}`
3301
+ },
3302
+ state: { from: pathname },
3303
+ label: formatMessage({
3304
+ id: "content-manager.bulk-publish.edit",
3305
+ defaultMessage: "Edit"
3306
+ }),
3307
+ target: "_blank",
3308
+ marginLeft: "auto",
3309
+ variant: "ghost",
3310
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
3311
+ }
3312
+ ) }) })
3313
+ ] }, row.id)) })
3314
+ ] });
3315
+ };
3316
+ const BoldChunk = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
3317
+ const SelectedEntriesModalContent = ({
3318
+ listViewSelectedEntries,
3319
+ toggleModal,
3320
+ setListViewSelectedDocuments,
3321
+ model
3322
+ }) => {
3323
+ const { formatMessage } = reactIntl.useIntl();
3324
+ const { schema, components } = useContentTypeSchema(model);
3325
+ const documentIds = listViewSelectedEntries.map(({ documentId }) => documentId);
3326
+ const [{ query }] = strapiAdmin.useQueryParams();
3327
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
3328
+ const { data, isLoading, isFetching, refetch } = useGetAllDocumentsQuery(
3329
+ {
3330
+ model,
3331
+ params: {
3332
+ page: "1",
3333
+ pageSize: documentIds.length.toString(),
3334
+ sort: query.sort,
3335
+ filters: {
3336
+ documentId: {
3337
+ $in: documentIds
3338
+ }
3339
+ },
3340
+ locale: query.plugins?.i18n?.locale
3341
+ }
3342
+ },
3343
+ {
3344
+ selectFromResult: ({ data: data2, ...restRes }) => ({ data: data2?.results ?? [], ...restRes })
3345
+ }
3346
+ );
3347
+ const { rows, validationErrors } = React__namespace.useMemo(() => {
3348
+ if (data.length > 0 && schema) {
3349
+ const validate = createYupSchema(
3350
+ schema.attributes,
3351
+ components,
3352
+ // Since this is the "Publish" action, the validation
3353
+ // schema must enforce the rules for published entities
3354
+ { status: "published" }
3355
+ );
3356
+ const validationErrors2 = {};
3357
+ const rows2 = data.map((entry) => {
3358
+ try {
3359
+ validate.validateSync(entry, { abortEarly: false });
3360
+ return entry;
3361
+ } catch (e) {
3362
+ if (e instanceof yup.ValidationError) {
3363
+ validationErrors2[entry.documentId] = strapiAdmin.getYupValidationErrors(e);
3364
+ }
3365
+ return entry;
3366
+ }
3367
+ });
3368
+ return { rows: rows2, validationErrors: validationErrors2 };
3369
+ }
3370
+ return {
3371
+ rows: [],
3372
+ validationErrors: {}
3373
+ };
3374
+ }, [components, data, schema]);
3375
+ const [publishedCount, setPublishedCount] = React__namespace.useState(0);
3376
+ const [isDialogOpen, setIsDialogOpen] = React__namespace.useState(false);
3377
+ const { publishMany: bulkPublishAction } = useDocumentActions();
3378
+ const [, { isLoading: isSubmittingForm }] = usePublishManyDocumentsMutation();
3379
+ const selectedRows = strapiAdmin.useTable("publishAction", (state) => state.selectedRows);
3380
+ const selectedEntries = rows.filter(
3381
+ (entry) => selectedRows.some((selectedEntry) => selectedEntry.documentId === entry.documentId)
3382
+ );
3383
+ const entriesToPublish = selectedEntries.filter((entry) => !validationErrors[entry.documentId]).map((entry) => entry.documentId);
3384
+ const selectedEntriesWithErrorsCount = selectedEntries.filter(
3385
+ ({ documentId }) => validationErrors[documentId]
3386
+ ).length;
3387
+ const selectedEntriesPublished = selectedEntries.filter(
3388
+ ({ status }) => status === "published"
3389
+ ).length;
3390
+ const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublished;
3391
+ const toggleDialog = () => setIsDialogOpen((prev) => !prev);
3392
+ const handleConfirmBulkPublish = async () => {
3393
+ toggleDialog();
3394
+ const res = await bulkPublishAction({ model, documentIds: entriesToPublish, params });
3395
+ if (!("error" in res)) {
3396
+ setPublishedCount(res.count);
3397
+ const unpublishedEntries = rows.filter((row) => {
3398
+ return !entriesToPublish.includes(row.documentId);
3399
+ });
3400
+ setListViewSelectedDocuments(unpublishedEntries);
3401
+ }
3402
+ };
3403
+ const getFormattedCountMessage = () => {
3404
+ if (publishedCount) {
3405
+ return formatMessage(
3406
+ {
3407
+ id: getTranslation("containers.list.selectedEntriesModal.publishedCount"),
3408
+ defaultMessage: "<b>{publishedCount}</b> {publishedCount, plural, =0 {entries} one {entry} other {entries}} published. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action."
3409
+ },
3410
+ {
3411
+ publishedCount,
3412
+ withErrorsCount: selectedEntriesWithErrorsCount,
3413
+ b: BoldChunk
3414
+ }
3415
+ );
3416
+ }
3417
+ return formatMessage(
3418
+ {
3419
+ id: getTranslation("containers.list.selectedEntriesModal.selectedCount"),
3420
+ defaultMessage: "<b>{alreadyPublishedCount}</b> {alreadyPublishedCount, plural, =0 {entries} one {entry} other {entries}} already published. <b>{readyToPublishCount}</b> {readyToPublishCount, plural, =0 {entries} one {entry} other {entries}} ready to publish. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action."
3421
+ },
3422
+ {
3423
+ readyToPublishCount: selectedEntriesWithNoErrorsCount,
3424
+ withErrorsCount: selectedEntriesWithErrorsCount,
3425
+ alreadyPublishedCount: selectedEntriesPublished,
3426
+ b: BoldChunk
3427
+ }
3428
+ );
3429
+ };
3430
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3431
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Body, { children: [
3432
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: getFormattedCountMessage() }),
3433
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 5, children: /* @__PURE__ */ jsxRuntime.jsx(
3434
+ SelectedEntriesTableContent,
3435
+ {
3436
+ isPublishing: isSubmittingForm,
3437
+ rowsToDisplay: rows,
3438
+ entriesToPublish,
3439
+ validationErrors
3440
+ }
3441
+ ) })
3442
+ ] }),
3443
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
3444
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: toggleModal, variant: "tertiary", children: formatMessage({
3445
+ id: "app.components.Button.cancel",
3446
+ defaultMessage: "Cancel"
3447
+ }) }),
3448
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3449
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: refetch, variant: "tertiary", loading: isFetching, children: formatMessage({ id: "app.utils.refresh", defaultMessage: "Refresh" }) }),
3450
+ /* @__PURE__ */ jsxRuntime.jsx(
3451
+ designSystem.Button,
3452
+ {
3453
+ onClick: toggleDialog,
3454
+ disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
3455
+ loading: isSubmittingForm,
3456
+ children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
3457
+ }
3458
+ )
3459
+ ] })
3460
+ ] }),
3461
+ /* @__PURE__ */ jsxRuntime.jsx(
3462
+ ConfirmDialogPublishAll,
3463
+ {
3464
+ isOpen: isDialogOpen,
3465
+ onToggleDialog: toggleDialog,
3466
+ isConfirmButtonLoading: isSubmittingForm,
3467
+ onConfirm: handleConfirmBulkPublish
3468
+ }
3469
+ )
3470
+ ] });
3471
+ };
3472
+ const PublishAction = ({ documents, model }) => {
3473
+ const { formatMessage } = reactIntl.useIntl();
3474
+ const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
3475
+ const showPublishButton = hasPublishPermission && documents.some(({ status }) => status !== "published");
3476
+ const setListViewSelectedDocuments = strapiAdmin.useTable("publishAction", (state) => state.selectRow);
3477
+ const refetchList = () => {
3478
+ contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
3479
+ };
3480
+ if (!showPublishButton)
3481
+ return null;
3482
+ return {
3483
+ actionType: "publish",
3484
+ variant: "tertiary",
3485
+ label: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" }),
3486
+ dialog: {
3487
+ type: "modal",
3488
+ title: formatMessage({
3489
+ id: getTranslation("containers.ListPage.selectedEntriesModal.title"),
3490
+ defaultMessage: "Publish entries"
3491
+ }),
3492
+ content: ({ onClose }) => {
3493
+ return /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Root, { rows: documents, defaultSelectedRows: documents, headers: TABLE_HEADERS, children: /* @__PURE__ */ jsxRuntime.jsx(
3494
+ SelectedEntriesModalContent,
3495
+ {
3496
+ listViewSelectedEntries: documents,
3497
+ toggleModal: () => {
3498
+ onClose();
3499
+ refetchList();
3500
+ },
3501
+ setListViewSelectedDocuments,
3502
+ model
3503
+ }
3504
+ ) });
3505
+ },
3506
+ onClose: () => {
3507
+ refetchList();
3508
+ }
3509
+ }
3510
+ };
3511
+ };
3512
+ const BulkActionsRenderer = () => {
3513
+ const plugins = strapiAdmin.useStrapiApp("BulkActionsRenderer", (state) => state.plugins);
3514
+ const { model, collectionType } = useDoc();
3515
+ const { selectedRows } = strapiAdmin.useTable("BulkActionsRenderer", (state) => state);
3516
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
3517
+ strapiAdmin.DescriptionComponentRenderer,
3518
+ {
3519
+ props: {
3520
+ model,
3521
+ collectionType,
3522
+ documents: selectedRows
3523
+ },
3524
+ descriptions: plugins["content-manager"].apis.getBulkActions(),
3525
+ children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActionButton, { ...action }, action.id))
3526
+ }
3527
+ ) });
3528
+ };
3529
+ const DeleteAction = ({ documents, model }) => {
3530
+ const { formatMessage } = reactIntl.useIntl();
3531
+ const { schema: contentType } = useDoc();
3532
+ const selectRow = strapiAdmin.useTable("DeleteAction", (state) => state.selectRow);
3533
+ const hasI18nEnabled = Boolean(contentType?.pluginOptions?.i18n);
3534
+ const [{ query }] = strapiAdmin.useQueryParams();
3535
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
3536
+ const hasDeletePermission = useDocumentRBAC("deleteAction", (state) => state.canDelete);
3537
+ const { deleteMany: bulkDeleteAction } = useDocumentActions();
3538
+ const documentIds = documents.map(({ documentId }) => documentId);
3539
+ const handleConfirmBulkDelete = async () => {
3540
+ const res = await bulkDeleteAction({
3541
+ documentIds,
3542
+ model,
3543
+ params
3544
+ });
3545
+ if (!("error" in res)) {
3546
+ selectRow([]);
3547
+ }
3548
+ };
3549
+ if (!hasDeletePermission)
3550
+ return null;
3551
+ return {
3552
+ variant: "danger-light",
3553
+ label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
3554
+ dialog: {
3555
+ type: "dialog",
3556
+ title: formatMessage({
3557
+ id: "app.components.ConfirmDialog.title",
3558
+ defaultMessage: "Confirmation"
3559
+ }),
3560
+ content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3561
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3562
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3563
+ id: "popUpWarning.bodyMessage.contentType.delete.all",
3564
+ defaultMessage: "Are you sure you want to delete these entries?"
3565
+ }) }),
3566
+ hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
3567
+ {
3568
+ id: getTranslation("Settings.list.actions.deleteAdditionalInfos"),
3569
+ defaultMessage: "This will delete the active locale versions <em>(from Internationalization)</em>"
3570
+ },
3571
+ {
3572
+ em: Emphasis
3573
+ }
3574
+ ) }) })
3575
+ ] }),
3576
+ onConfirm: handleConfirmBulkDelete
3577
+ }
3578
+ };
3579
+ };
3580
+ DeleteAction.type = "delete";
3581
+ const UnpublishAction = ({ documents, model }) => {
3582
+ const { formatMessage } = reactIntl.useIntl();
3583
+ const { schema } = useDoc();
3584
+ const selectRow = strapiAdmin.useTable("UnpublishAction", (state) => state.selectRow);
3585
+ const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
3586
+ const hasI18nEnabled = Boolean(schema?.pluginOptions?.i18n);
3587
+ const hasDraftAndPublishEnabled = Boolean(schema?.options?.draftAndPublish);
3588
+ const { unpublishMany: bulkUnpublishAction } = useDocumentActions();
3589
+ const documentIds = documents.map(({ documentId }) => documentId);
3590
+ const [{ query }] = strapiAdmin.useQueryParams();
3591
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
3592
+ const handleConfirmBulkUnpublish = async () => {
3593
+ const data = await bulkUnpublishAction({ documentIds, model, params });
3594
+ if (!("error" in data)) {
3595
+ selectRow([]);
3596
+ }
3597
+ };
3598
+ const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
3599
+ if (!showUnpublishButton)
3600
+ return null;
3601
+ return {
3602
+ variant: "tertiary",
3603
+ label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
3604
+ dialog: {
3605
+ type: "dialog",
3606
+ title: formatMessage({
3607
+ id: "app.components.ConfirmDialog.title",
3608
+ defaultMessage: "Confirmation"
3609
+ }),
3610
+ content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3611
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3612
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3613
+ id: "popUpWarning.bodyMessage.contentType.unpublish.all",
3614
+ defaultMessage: "Are you sure you want to unpublish these entries?"
3615
+ }) }),
3616
+ hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
3617
+ {
3618
+ id: getTranslation("Settings.list.actions.unpublishAdditionalInfos"),
3619
+ defaultMessage: "This will unpublish the active locale versions <em>(from Internationalization)</em>"
3620
+ },
3621
+ {
3622
+ em: Emphasis
3623
+ }
3624
+ ) }) })
3625
+ ] }),
3626
+ confirmButton: formatMessage({
3627
+ id: "app.utils.unpublish",
3628
+ defaultMessage: "Unpublish"
3629
+ }),
3630
+ onConfirm: handleConfirmBulkUnpublish
3631
+ }
3632
+ };
3633
+ };
3634
+ UnpublishAction.type = "unpublish";
3635
+ const Emphasis = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "semiBold", textColor: "danger500", children: chunks });
3636
+ const DEFAULT_BULK_ACTIONS = [PublishAction, UnpublishAction, DeleteAction];
3637
+ const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
3638
+ const { formatMessage } = reactIntl.useIntl();
3639
+ const getDefaultErrorMessage = (reason) => {
3640
+ switch (reason) {
3641
+ case "relation":
3642
+ return "Duplicating the relation could remove it from the original entry.";
3643
+ case "unique":
3644
+ return "Identical values in a unique field are not allowed";
3645
+ default:
3646
+ return reason;
3647
+ }
2478
3648
  };
2479
3649
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2480
3650
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", children: formatMessage({
@@ -2495,7 +3665,7 @@ const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
2495
3665
  hasRadius: true,
2496
3666
  padding: 6,
2497
3667
  children: [
2498
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "row", as: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { fontWeight: "semiBold", as: "li", children: [
3668
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "row", tag: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { fontWeight: "semiBold", tag: "li", children: [
2499
3669
  pathSegment,
2500
3670
  index2 !== fieldPath.length - 1 && /* @__PURE__ */ jsxRuntime.jsx(
2501
3671
  Icons.ChevronRight,
@@ -2507,7 +3677,7 @@ const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
2507
3677
  }
2508
3678
  )
2509
3679
  ] }, index2)) }),
2510
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "p", textColor: "neutral600", children: formatMessage({
3680
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", textColor: "neutral600", children: formatMessage({
2511
3681
  id: getTranslation(`containers.list.autoCloneModal.error.${reason}`),
2512
3682
  defaultMessage: getDefaultErrorMessage(reason)
2513
3683
  }) })
@@ -2532,7 +3702,7 @@ const TableActions = ({ document }) => {
2532
3702
  strapiAdmin.DescriptionComponentRenderer,
2533
3703
  {
2534
3704
  props,
2535
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
3705
+ descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
2536
3706
  children: (actions2) => {
2537
3707
  const tableRowActions = actions2.filter((action) => {
2538
3708
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -2591,7 +3761,7 @@ const EditAction = ({ documentId }) => {
2591
3761
  };
2592
3762
  };
2593
3763
  EditAction.type = "edit";
2594
- const StyledPencil = styled__default.default(Icons.Pencil)`
3764
+ const StyledPencil = styledComponents.styled(Icons.Pencil)`
2595
3765
  path {
2596
3766
  fill: currentColor;
2597
3767
  }
@@ -2643,7 +3813,7 @@ const CloneAction = ({ model, documentId }) => {
2643
3813
  }),
2644
3814
  content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
2645
3815
  footer: ({ onClose }) => {
2646
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", children: [
3816
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
2647
3817
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
2648
3818
  id: "cancel",
2649
3819
  defaultMessage: "Cancel"
@@ -2651,7 +3821,7 @@ const CloneAction = ({ model, documentId }) => {
2651
3821
  /* @__PURE__ */ jsxRuntime.jsx(
2652
3822
  designSystem.LinkButton,
2653
3823
  {
2654
- as: reactRouterDom.NavLink,
3824
+ tag: reactRouterDom.NavLink,
2655
3825
  to: {
2656
3826
  pathname: `clone/${documentId}`
2657
3827
  },
@@ -2667,7 +3837,7 @@ const CloneAction = ({ model, documentId }) => {
2667
3837
  };
2668
3838
  };
2669
3839
  CloneAction.type = "clone";
2670
- const StyledDuplicate = styled__default.default(Icons.Duplicate)`
3840
+ const StyledDuplicate = styledComponents.styled(Icons.Duplicate)`
2671
3841
  path {
2672
3842
  fill: currentColor;
2673
3843
  }
@@ -2684,8 +3854,7 @@ class ContentManagerPlugin {
2684
3854
  documentActions = [
2685
3855
  ...DEFAULT_ACTIONS,
2686
3856
  ...DEFAULT_TABLE_ROW_ACTIONS,
2687
- ...DEFAULT_HEADER_ACTIONS,
2688
- HistoryAction
3857
+ ...DEFAULT_HEADER_ACTIONS
2689
3858
  ];
2690
3859
  editViewSidePanels = [ActionsPanel];
2691
3860
  headerActions = [];
@@ -2774,352 +3943,170 @@ const getPrintableType = (value) => {
2774
3943
  }
2775
3944
  return nativeType;
2776
3945
  };
2777
- const initialState = {
2778
- collectionTypeLinks: [],
2779
- components: [],
2780
- fieldSizes: {},
2781
- models: [],
2782
- singleTypeLinks: [],
2783
- isLoading: true
2784
- };
2785
- const appSlice = toolkit.createSlice({
2786
- name: "app",
2787
- initialState,
2788
- reducers: {
2789
- setInitialData(state, action) {
2790
- const {
2791
- authorizedCollectionTypeLinks,
2792
- authorizedSingleTypeLinks,
2793
- components,
2794
- contentTypeSchemas,
2795
- fieldSizes
2796
- } = action.payload;
2797
- state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
2798
- ({ isDisplayed }) => isDisplayed
2799
- );
2800
- state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
2801
- state.components = components;
2802
- state.models = contentTypeSchemas;
2803
- state.fieldSizes = fieldSizes;
2804
- state.isLoading = false;
2805
- }
2806
- }
2807
- });
2808
- const { actions, reducer: reducer$1 } = appSlice;
2809
- const { setInitialData } = actions;
2810
- const reducer = toolkit.combineReducers({
2811
- app: reducer$1
2812
- });
2813
- const HOOKS = {
2814
- /**
2815
- * Hook that allows to mutate the displayed headers of the list view table
2816
- * @constant
2817
- * @type {string}
2818
- */
2819
- INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
2820
- /**
2821
- * Hook that allows to mutate the CM's collection types links pre-set filters
2822
- * @constant
2823
- * @type {string}
2824
- */
2825
- MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
2826
- /**
2827
- * Hook that allows to mutate the CM's edit view layout
2828
- * @constant
2829
- * @type {string}
2830
- */
2831
- MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
2832
- /**
2833
- * Hook that allows to mutate the CM's single types links pre-set filters
2834
- * @constant
2835
- * @type {string}
2836
- */
2837
- MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
2838
- };
2839
- const contentTypesApi = contentManagerApi.injectEndpoints({
2840
- endpoints: (builder) => ({
2841
- getContentTypeConfiguration: builder.query({
2842
- query: (uid) => ({
2843
- url: `/content-manager/content-types/${uid}/configuration`,
2844
- method: "GET"
2845
- }),
2846
- transformResponse: (response) => response.data,
2847
- providesTags: (_result, _error, uid) => [
2848
- { type: "ContentTypesConfiguration", id: uid },
2849
- { type: "ContentTypeSettings", id: "LIST" }
2850
- ]
2851
- }),
2852
- getAllContentTypeSettings: builder.query({
2853
- query: () => "/content-manager/content-types-settings",
2854
- transformResponse: (response) => response.data,
2855
- providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
2856
- }),
2857
- updateContentTypeConfiguration: builder.mutation({
2858
- query: ({ uid, ...body }) => ({
2859
- url: `/content-manager/content-types/${uid}/configuration`,
2860
- method: "PUT",
2861
- data: body
2862
- }),
2863
- transformResponse: (response) => response.data,
2864
- invalidatesTags: (_result, _error, { uid }) => [
2865
- { type: "ContentTypesConfiguration", id: uid },
2866
- { type: "ContentTypeSettings", id: "LIST" },
2867
- // Is this necessary?
2868
- { type: "InitialData" }
2869
- ]
2870
- })
2871
- })
2872
- });
2873
- const {
2874
- useGetContentTypeConfigurationQuery,
2875
- useGetAllContentTypeSettingsQuery,
2876
- useUpdateContentTypeConfigurationMutation
2877
- } = contentTypesApi;
2878
- const checkIfAttributeIsDisplayable = (attribute) => {
2879
- const { type } = attribute;
2880
- if (type === "relation") {
2881
- return !attribute.relation.toLowerCase().includes("morph");
2882
- }
2883
- return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
2884
- };
2885
- const getMainField = (attribute, mainFieldName, { schemas, components }) => {
2886
- if (!mainFieldName) {
2887
- return void 0;
3946
+ const HistoryAction = ({ model, document }) => {
3947
+ const { formatMessage } = reactIntl.useIntl();
3948
+ const [{ query }] = strapiAdmin.useQueryParams();
3949
+ const navigate = reactRouterDom.useNavigate();
3950
+ const { trackUsage } = strapiAdmin.useTracking();
3951
+ const { pathname } = reactRouterDom.useLocation();
3952
+ const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
3953
+ if (!window.strapi.features.isEnabled("cms-content-history")) {
3954
+ return null;
2888
3955
  }
2889
- const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
2890
- // @ts-expect-error `targetModel` does exist on the attribute for a relation.
2891
- schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
2892
- );
2893
- return {
2894
- name: mainFieldName,
2895
- type: mainFieldType ?? "string"
3956
+ const handleOnClick = () => {
3957
+ const destination = { pathname: "history", search: pluginsQueryParams };
3958
+ trackUsage("willNavigate", {
3959
+ from: pathname,
3960
+ to: `${pathname}/${destination.pathname}`
3961
+ });
3962
+ navigate(destination);
2896
3963
  };
2897
- };
2898
- const DEFAULT_SETTINGS = {
2899
- bulkable: false,
2900
- filterable: false,
2901
- searchable: false,
2902
- pagination: false,
2903
- defaultSortBy: "",
2904
- defaultSortOrder: "asc",
2905
- mainField: "id",
2906
- pageSize: 10
2907
- };
2908
- const useDocumentLayout = (model) => {
2909
- const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
2910
- const [{ query }] = strapiAdmin.useQueryParams();
2911
- const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
2912
- const { toggleNotification } = strapiAdmin.useNotification();
2913
- const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
2914
- const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
2915
- const {
2916
- data,
2917
- isLoading: isLoadingConfigs,
2918
- error,
2919
- isFetching: isFetchingConfigs
2920
- } = useGetContentTypeConfigurationQuery(model);
2921
- const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
2922
- React__namespace.useEffect(() => {
2923
- if (error) {
2924
- toggleNotification({
2925
- type: "danger",
2926
- message: formatAPIError(error)
2927
- });
2928
- }
2929
- }, [error, formatAPIError, toggleNotification]);
2930
- const editLayout = React__namespace.useMemo(
2931
- () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
2932
- layout: [],
2933
- components: {},
2934
- metadatas: {},
2935
- options: {},
2936
- settings: DEFAULT_SETTINGS
2937
- },
2938
- [data, isLoading, schemas, schema, components]
2939
- );
2940
- const listLayout = React__namespace.useMemo(() => {
2941
- return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
2942
- layout: [],
2943
- metadatas: {},
2944
- options: {},
2945
- settings: DEFAULT_SETTINGS
2946
- };
2947
- }, [data, isLoading, schemas, schema, components]);
2948
- const { layout: edit } = React__namespace.useMemo(
2949
- () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
2950
- layout: editLayout,
2951
- query
2952
- }),
2953
- [editLayout, query, runHookWaterfall]
2954
- );
2955
3964
  return {
2956
- error,
2957
- isLoading,
2958
- edit,
2959
- list: listLayout
3965
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
3966
+ label: formatMessage({
3967
+ id: "content-manager.history.document-action",
3968
+ defaultMessage: "Content History"
3969
+ }),
3970
+ onClick: handleOnClick,
3971
+ disabled: (
3972
+ /**
3973
+ * The user is creating a new document.
3974
+ * It hasn't been saved yet, so there's no history to go to
3975
+ */
3976
+ !document || /**
3977
+ * The document has been created but the current dimension has never been saved.
3978
+ * For example, the user is creating a new locale in an existing document,
3979
+ * so there's no history for the document in that locale
3980
+ */
3981
+ !document.id || /**
3982
+ * History is only available for content types created by the user.
3983
+ * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
3984
+ * which start with `admin::` or `plugin::`
3985
+ */
3986
+ !model.startsWith("api::")
3987
+ ),
3988
+ position: "header"
2960
3989
  };
2961
3990
  };
2962
- const useDocLayout = () => {
2963
- const { model } = useDoc();
2964
- return useDocumentLayout(model);
3991
+ HistoryAction.type = "history";
3992
+ const historyAdmin = {
3993
+ bootstrap(app) {
3994
+ const { addDocumentAction } = app.getPlugin("content-manager").apis;
3995
+ addDocumentAction((actions2) => {
3996
+ const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
3997
+ actions2.splice(indexOfDeleteAction, 0, HistoryAction);
3998
+ return actions2;
3999
+ });
4000
+ }
2965
4001
  };
2966
- const formatEditLayout = (data, {
2967
- schemas,
2968
- schema,
2969
- components
2970
- }) => {
2971
- let currentPanelIndex = 0;
2972
- const panelledEditAttributes = convertEditLayoutToFieldLayouts(
2973
- data.contentType.layouts.edit,
2974
- schema?.attributes,
2975
- data.contentType.metadatas,
2976
- { configurations: data.components, schemas: components },
2977
- schemas
2978
- ).reduce((panels, row) => {
2979
- if (row.some((field) => field.type === "dynamiczone")) {
2980
- panels.push([row]);
2981
- currentPanelIndex += 2;
2982
- } else {
2983
- if (!panels[currentPanelIndex]) {
2984
- panels.push([]);
2985
- }
2986
- panels[currentPanelIndex].push(row);
4002
+ const initialState = {
4003
+ collectionTypeLinks: [],
4004
+ components: [],
4005
+ fieldSizes: {},
4006
+ models: [],
4007
+ singleTypeLinks: [],
4008
+ isLoading: true
4009
+ };
4010
+ const appSlice = toolkit.createSlice({
4011
+ name: "app",
4012
+ initialState,
4013
+ reducers: {
4014
+ setInitialData(state, action) {
4015
+ const {
4016
+ authorizedCollectionTypeLinks,
4017
+ authorizedSingleTypeLinks,
4018
+ components,
4019
+ contentTypeSchemas,
4020
+ fieldSizes
4021
+ } = action.payload;
4022
+ state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
4023
+ ({ isDisplayed }) => isDisplayed
4024
+ );
4025
+ state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
4026
+ state.components = components;
4027
+ state.models = contentTypeSchemas;
4028
+ state.fieldSizes = fieldSizes;
4029
+ state.isLoading = false;
2987
4030
  }
2988
- return panels;
2989
- }, []);
2990
- const componentEditAttributes = Object.entries(data.components).reduce(
2991
- (acc, [uid, configuration]) => {
2992
- acc[uid] = {
2993
- layout: convertEditLayoutToFieldLayouts(
2994
- configuration.layouts.edit,
2995
- components[uid].attributes,
2996
- configuration.metadatas
2997
- ),
2998
- settings: {
2999
- ...configuration.settings,
3000
- icon: components[uid].info.icon,
3001
- displayName: components[uid].info.displayName
3002
- }
3003
- };
3004
- return acc;
3005
- },
3006
- {}
3007
- );
3008
- const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
3009
- (acc, [attribute, metadata]) => {
3010
- return {
3011
- ...acc,
3012
- [attribute]: metadata.edit
3013
- };
3014
- },
3015
- {}
3016
- );
3017
- return {
3018
- layout: panelledEditAttributes,
3019
- components: componentEditAttributes,
3020
- metadatas: editMetadatas,
3021
- settings: {
3022
- ...data.contentType.settings,
3023
- displayName: schema?.info.displayName
4031
+ }
4032
+ });
4033
+ const { actions, reducer: reducer$1 } = appSlice;
4034
+ const { setInitialData } = actions;
4035
+ const reducer = toolkit.combineReducers({
4036
+ app: reducer$1
4037
+ });
4038
+ const previewApi = contentManagerApi.injectEndpoints({
4039
+ endpoints: (builder) => ({
4040
+ getPreviewUrl: builder.query({
4041
+ query({ query, params }) {
4042
+ return {
4043
+ url: `/content-manager/preview/url/${params.contentType}`,
4044
+ method: "GET",
4045
+ config: {
4046
+ params: query
4047
+ }
4048
+ };
4049
+ }
4050
+ })
4051
+ })
4052
+ });
4053
+ const { useGetPreviewUrlQuery } = previewApi;
4054
+ const PreviewSidePanel = ({ model, documentId, document }) => {
4055
+ const { formatMessage } = reactIntl.useIntl();
4056
+ const { trackUsage } = strapiAdmin.useTracking();
4057
+ const { pathname } = reactRouterDom.useLocation();
4058
+ const [{ query }] = strapiAdmin.useQueryParams();
4059
+ const { data, error } = useGetPreviewUrlQuery({
4060
+ params: {
4061
+ contentType: model
3024
4062
  },
3025
- options: {
3026
- ...schema?.options,
3027
- ...schema?.pluginOptions,
3028
- ...data.contentType.options
4063
+ query: {
4064
+ documentId,
4065
+ locale: document?.locale,
4066
+ status: document?.status
3029
4067
  }
4068
+ });
4069
+ if (!data?.data?.url || error) {
4070
+ return null;
4071
+ }
4072
+ const trackNavigation = () => {
4073
+ const destinationPathname = pathname.replace(/\/$/, "") + "/preview";
4074
+ trackUsage("willNavigate", { from: pathname, to: destinationPathname });
3030
4075
  };
3031
- };
3032
- const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
3033
- return rows.map(
3034
- (row) => row.map((field) => {
3035
- const attribute = attributes[field.name];
3036
- if (!attribute) {
3037
- return null;
3038
- }
3039
- const { edit: metadata } = metadatas[field.name];
3040
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
3041
- return {
3042
- attribute,
3043
- disabled: !metadata.editable,
3044
- hint: metadata.description,
3045
- label: metadata.label ?? "",
3046
- name: field.name,
3047
- // @ts-expect-error – mainField does exist on the metadata for a relation.
3048
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
3049
- schemas,
3050
- components: components?.schemas ?? {}
3051
- }),
3052
- placeholder: metadata.placeholder ?? "",
3053
- required: attribute.required ?? false,
3054
- size: field.size,
3055
- unique: "unique" in attribute ? attribute.unique : false,
3056
- visible: metadata.visible ?? true,
3057
- type: attribute.type
3058
- };
3059
- }).filter((field) => field !== null)
3060
- );
3061
- };
3062
- const formatListLayout = (data, {
3063
- schemas,
3064
- schema,
3065
- components
3066
- }) => {
3067
- const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
3068
- (acc, [attribute, metadata]) => {
3069
- return {
3070
- ...acc,
3071
- [attribute]: metadata.list
3072
- };
3073
- },
3074
- {}
3075
- );
3076
- const listAttributes = convertListLayoutToFieldLayouts(
3077
- data.contentType.layouts.list,
3078
- schema?.attributes,
3079
- listMetadatas,
3080
- { configurations: data.components, schemas: components },
3081
- schemas
3082
- );
3083
4076
  return {
3084
- layout: listAttributes,
3085
- settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
3086
- metadatas: listMetadatas,
3087
- options: {
3088
- ...schema?.options,
3089
- ...schema?.pluginOptions,
3090
- ...data.contentType.options
3091
- }
4077
+ title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
4078
+ content: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, width: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(
4079
+ designSystem.Button,
4080
+ {
4081
+ variant: "tertiary",
4082
+ tag: reactRouterDom.Link,
4083
+ to: { pathname: "preview", search: qs.stringify(query, { encode: false }) },
4084
+ onClick: trackNavigation,
4085
+ flex: "auto",
4086
+ children: formatMessage({
4087
+ id: "content-manager.preview.panel.button",
4088
+ defaultMessage: "Open preview"
4089
+ })
4090
+ }
4091
+ ) })
3092
4092
  };
3093
4093
  };
3094
- const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
3095
- return columns.map((name) => {
3096
- const attribute = attributes[name];
3097
- if (!attribute) {
3098
- return null;
4094
+ const FEATURE_ID = "preview";
4095
+ const previewAdmin = {
4096
+ bootstrap(app) {
4097
+ if (!window.strapi.future.isEnabled(FEATURE_ID)) {
4098
+ return;
3099
4099
  }
3100
- const metadata = metadatas[name];
3101
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
3102
- return {
3103
- attribute,
3104
- label: metadata.label ?? "",
3105
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
3106
- schemas,
3107
- components: components?.schemas ?? {}
3108
- }),
3109
- name,
3110
- searchable: metadata.searchable ?? true,
3111
- sortable: metadata.sortable ?? true
3112
- };
3113
- }).filter((field) => field !== null);
4100
+ const contentManagerPluginApis = app.getPlugin("content-manager").apis;
4101
+ contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
4102
+ }
3114
4103
  };
3115
4104
  const index = {
3116
4105
  register(app) {
3117
4106
  const cm = new ContentManagerPlugin();
3118
4107
  app.addReducers({
3119
- [contentManagerApi.reducerPath]: contentManagerApi.reducer,
3120
4108
  [PLUGIN_ID]: reducer
3121
4109
  });
3122
- app.addMiddlewares([() => contentManagerApi.middleware]);
3123
4110
  app.addMenuLink({
3124
4111
  to: PLUGIN_ID,
3125
4112
  icon: Icons.Feather,
@@ -3128,14 +4115,32 @@ const index = {
3128
4115
  defaultMessage: "Content Manager"
3129
4116
  },
3130
4117
  permissions: [],
3131
- Component: () => Promise.resolve().then(() => require("./layout-dBc7wN7L.js")).then((mod) => ({ default: mod.Layout }))
4118
+ position: 1
4119
+ });
4120
+ app.router.addRoute({
4121
+ path: "content-manager/*",
4122
+ lazy: async () => {
4123
+ const { Layout } = await Promise.resolve().then(() => require("./layout-Cx9LHtH5.js"));
4124
+ return {
4125
+ Component: Layout
4126
+ };
4127
+ },
4128
+ children: routes
3132
4129
  });
3133
4130
  app.registerPlugin(cm.config);
3134
4131
  },
4132
+ bootstrap(app) {
4133
+ if (typeof historyAdmin.bootstrap === "function") {
4134
+ historyAdmin.bootstrap(app);
4135
+ }
4136
+ if (typeof previewAdmin.bootstrap === "function") {
4137
+ previewAdmin.bootstrap(app);
4138
+ }
4139
+ },
3135
4140
  async registerTrads({ locales }) {
3136
4141
  const importedTrads = await Promise.all(
3137
4142
  locales.map((locale) => {
3138
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-C-V1_90f.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-EUonQTon.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B7kGGg3E.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-CcFe8diO.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
4143
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-DTWPCdTS.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-9K52xZIr.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B2Kyv8Z9.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-7sfIbjxE.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
3139
4144
  return {
3140
4145
  data: prefixPluginTranslations(data, PLUGIN_ID),
3141
4146
  locale
@@ -3152,6 +4157,8 @@ const index = {
3152
4157
  }
3153
4158
  };
3154
4159
  exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
4160
+ exports.BulkActionsRenderer = BulkActionsRenderer;
4161
+ exports.CLONE_PATH = CLONE_PATH;
3155
4162
  exports.COLLECTION_TYPES = COLLECTION_TYPES;
3156
4163
  exports.CREATOR_FIELDS = CREATOR_FIELDS;
3157
4164
  exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
@@ -3178,8 +4185,8 @@ exports.getDisplayName = getDisplayName;
3178
4185
  exports.getMainField = getMainField;
3179
4186
  exports.getTranslation = getTranslation;
3180
4187
  exports.index = index;
3181
- exports.routes = routes;
3182
4188
  exports.setInitialData = setInitialData;
4189
+ exports.useContentManagerContext = useContentManagerContext;
3183
4190
  exports.useContentTypeSchema = useContentTypeSchema;
3184
4191
  exports.useDoc = useDoc;
3185
4192
  exports.useDocLayout = useDocLayout;
@@ -3191,5 +4198,6 @@ exports.useGetAllContentTypeSettingsQuery = useGetAllContentTypeSettingsQuery;
3191
4198
  exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
3192
4199
  exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
3193
4200
  exports.useGetInitialDataQuery = useGetInitialDataQuery;
4201
+ exports.useGetPreviewUrlQuery = useGetPreviewUrlQuery;
3194
4202
  exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
3195
- //# sourceMappingURL=index-X_2tafck.js.map
4203
+ //# sourceMappingURL=index-DjV7tyGu.js.map