@strapi/content-manager 0.0.0-experimental.b05633daea1bf090c66312b8ab30ec13bdb52f57 → 0.0.0-experimental.b127d7466fc2858c91fd06647dbaa742efa95505

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 (446) hide show
  1. package/dist/admin/chunks/CardDragPreview-DwuraT0K.mjs +80 -0
  2. package/dist/admin/chunks/CardDragPreview-DwuraT0K.mjs.map +1 -0
  3. package/dist/admin/chunks/CardDragPreview-_dubYgXO.js +82 -0
  4. package/dist/admin/chunks/CardDragPreview-_dubYgXO.js.map +1 -0
  5. package/dist/admin/chunks/ComponentConfigurationPage-BkcZ_iBg.mjs +276 -0
  6. package/dist/admin/chunks/ComponentConfigurationPage-BkcZ_iBg.mjs.map +1 -0
  7. package/dist/admin/chunks/ComponentConfigurationPage-Dj1bNvEF.js +298 -0
  8. package/dist/admin/chunks/ComponentConfigurationPage-Dj1bNvEF.js.map +1 -0
  9. package/dist/admin/chunks/ComponentIcon-BZcTc4rj.mjs +153 -0
  10. package/dist/admin/chunks/ComponentIcon-BZcTc4rj.mjs.map +1 -0
  11. package/dist/admin/chunks/ComponentIcon-C-EjOUPA.js +176 -0
  12. package/dist/admin/chunks/ComponentIcon-C-EjOUPA.js.map +1 -0
  13. package/dist/admin/chunks/EditConfigurationPage-B_ovdxDI.mjs +158 -0
  14. package/dist/admin/chunks/EditConfigurationPage-B_ovdxDI.mjs.map +1 -0
  15. package/dist/admin/chunks/EditConfigurationPage-Dm5woBp9.js +180 -0
  16. package/dist/admin/chunks/EditConfigurationPage-Dm5woBp9.js.map +1 -0
  17. package/dist/admin/chunks/EditViewPage-BO41xaWz.mjs +314 -0
  18. package/dist/admin/chunks/EditViewPage-BO41xaWz.mjs.map +1 -0
  19. package/dist/admin/chunks/EditViewPage-DsBKmSPb.js +337 -0
  20. package/dist/admin/chunks/EditViewPage-DsBKmSPb.js.map +1 -0
  21. package/dist/admin/chunks/FieldTypeIcon-BY6MrVF4.mjs +56 -0
  22. package/dist/admin/chunks/FieldTypeIcon-BY6MrVF4.mjs.map +1 -0
  23. package/dist/admin/chunks/FieldTypeIcon-Bxh-7Jin.js +58 -0
  24. package/dist/admin/chunks/FieldTypeIcon-Bxh-7Jin.js.map +1 -0
  25. package/dist/admin/chunks/Form-BPIhJKyf.js +978 -0
  26. package/dist/admin/chunks/Form-BPIhJKyf.js.map +1 -0
  27. package/dist/admin/chunks/Form-BW-0CCs_.mjs +955 -0
  28. package/dist/admin/chunks/Form-BW-0CCs_.mjs.map +1 -0
  29. package/dist/admin/chunks/History-D4A-n2Zm.mjs +1357 -0
  30. package/dist/admin/chunks/History-D4A-n2Zm.mjs.map +1 -0
  31. package/dist/admin/chunks/History-DBQ96jv2.js +1380 -0
  32. package/dist/admin/chunks/History-DBQ96jv2.js.map +1 -0
  33. package/dist/admin/chunks/Input-DGmRWUxk.mjs +6755 -0
  34. package/dist/admin/chunks/Input-DGmRWUxk.mjs.map +1 -0
  35. package/dist/admin/chunks/Input-Dh1MtWno.js +6786 -0
  36. package/dist/admin/chunks/Input-Dh1MtWno.js.map +1 -0
  37. package/dist/admin/chunks/ListConfigurationPage-8d3BsQIr.js +818 -0
  38. package/dist/admin/chunks/ListConfigurationPage-8d3BsQIr.js.map +1 -0
  39. package/dist/admin/chunks/ListConfigurationPage-D6omrM0-.mjs +795 -0
  40. package/dist/admin/chunks/ListConfigurationPage-D6omrM0-.mjs.map +1 -0
  41. package/dist/admin/chunks/ListViewPage-CS1ED-vI.js +1154 -0
  42. package/dist/admin/chunks/ListViewPage-CS1ED-vI.js.map +1 -0
  43. package/dist/admin/chunks/ListViewPage-Eo1uerx4.mjs +1132 -0
  44. package/dist/admin/chunks/ListViewPage-Eo1uerx4.mjs.map +1 -0
  45. package/dist/admin/chunks/NoContentTypePage-C5Qxz3I4.js +59 -0
  46. package/dist/admin/chunks/NoContentTypePage-C5Qxz3I4.js.map +1 -0
  47. package/dist/admin/chunks/NoContentTypePage-I7AD-OVm.mjs +57 -0
  48. package/dist/admin/chunks/NoContentTypePage-I7AD-OVm.mjs.map +1 -0
  49. package/dist/admin/chunks/NoPermissionsPage-BhdJx_e-.mjs +36 -0
  50. package/dist/admin/chunks/NoPermissionsPage-BhdJx_e-.mjs.map +1 -0
  51. package/dist/admin/chunks/NoPermissionsPage-C5dC0MtL.js +38 -0
  52. package/dist/admin/chunks/NoPermissionsPage-C5dC0MtL.js.map +1 -0
  53. package/dist/admin/chunks/Preview-DBvmhR7Q.js +553 -0
  54. package/dist/admin/chunks/Preview-DBvmhR7Q.js.map +1 -0
  55. package/dist/admin/chunks/Preview-Pk4Xzv7l.mjs +531 -0
  56. package/dist/admin/chunks/Preview-Pk4Xzv7l.mjs.map +1 -0
  57. package/dist/admin/chunks/Relations-DjQ-a16E.mjs +827 -0
  58. package/dist/admin/chunks/Relations-DjQ-a16E.mjs.map +1 -0
  59. package/dist/admin/chunks/Relations-XHxDKEvT.js +853 -0
  60. package/dist/admin/chunks/Relations-XHxDKEvT.js.map +1 -0
  61. package/dist/admin/chunks/ar-DckYq_WK.mjs +222 -0
  62. package/dist/{_chunks/ar-CCEVvqGG.mjs.map → admin/chunks/ar-DckYq_WK.mjs.map} +1 -1
  63. package/dist/admin/chunks/ar-DeQBSsfl.js +227 -0
  64. package/dist/{_chunks/ru-BT3ybNny.js.map → admin/chunks/ar-DeQBSsfl.js.map} +1 -1
  65. package/dist/admin/chunks/ca-ClDTvatJ.js +202 -0
  66. package/dist/admin/chunks/ca-ClDTvatJ.js.map +1 -0
  67. package/dist/admin/chunks/ca-DviY7mRj.mjs +197 -0
  68. package/dist/admin/chunks/ca-DviY7mRj.mjs.map +1 -0
  69. package/dist/admin/chunks/cs-BJFxwIWj.js +126 -0
  70. package/dist/{_chunks/cs-CkJy6B2v.js.map → admin/chunks/cs-BJFxwIWj.js.map} +1 -1
  71. package/dist/admin/chunks/cs-C7OSYFQ7.mjs +122 -0
  72. package/dist/{_chunks/cs-CM2aBUar.mjs.map → admin/chunks/cs-C7OSYFQ7.mjs.map} +1 -1
  73. package/dist/admin/chunks/de-5QRlDHyR.mjs +195 -0
  74. package/dist/{_chunks/eu-CdALomew.mjs.map → admin/chunks/de-5QRlDHyR.mjs.map} +1 -1
  75. package/dist/admin/chunks/de-CbImAUA5.js +200 -0
  76. package/dist/{_chunks/gu-BRmF601H.js.map → admin/chunks/de-CbImAUA5.js.map} +1 -1
  77. package/dist/admin/chunks/en-C1CjdAtC.js +313 -0
  78. package/dist/{_chunks/en-BzQmavmK.js.map → admin/chunks/en-C1CjdAtC.js.map} +1 -1
  79. package/dist/admin/chunks/en-LfhocNG2.mjs +308 -0
  80. package/dist/{_chunks/en-CSxLmrh1.mjs.map → admin/chunks/en-LfhocNG2.mjs.map} +1 -1
  81. package/dist/admin/chunks/es-C8vLuvZL.js +197 -0
  82. package/dist/{_chunks/es-9K52xZIr.js.map → admin/chunks/es-C8vLuvZL.js.map} +1 -1
  83. package/dist/admin/chunks/es-DkoWSExG.mjs +192 -0
  84. package/dist/{_chunks/ja-BHqhDq4V.mjs.map → admin/chunks/es-DkoWSExG.mjs.map} +1 -1
  85. package/dist/admin/chunks/eu-BG1xX7HK.mjs +198 -0
  86. package/dist/admin/chunks/eu-BG1xX7HK.mjs.map +1 -0
  87. package/dist/admin/chunks/eu-BJW3AvXu.js +203 -0
  88. package/dist/admin/chunks/eu-BJW3AvXu.js.map +1 -0
  89. package/dist/admin/chunks/fr-CFdRaRVj.mjs +215 -0
  90. package/dist/admin/chunks/fr-CFdRaRVj.mjs.map +1 -0
  91. package/dist/admin/chunks/fr-gQSilC7w.js +220 -0
  92. package/dist/admin/chunks/fr-gQSilC7w.js.map +1 -0
  93. package/dist/admin/chunks/gu-D5MMMXRs.mjs +196 -0
  94. package/dist/admin/chunks/gu-D5MMMXRs.mjs.map +1 -0
  95. package/dist/admin/chunks/gu-DPU4wyx7.js +201 -0
  96. package/dist/{_chunks/eu-VDH-3ovk.js.map → admin/chunks/gu-DPU4wyx7.js.map} +1 -1
  97. package/dist/admin/chunks/hi-Dp4omeBb.js +201 -0
  98. package/dist/admin/chunks/hi-Dp4omeBb.js.map +1 -0
  99. package/dist/admin/chunks/hi-lp17SCjr.mjs +196 -0
  100. package/dist/admin/chunks/hi-lp17SCjr.mjs.map +1 -0
  101. package/dist/{_chunks/hooks-BAaaKPS_.js → admin/chunks/hooks-D-sOYd1s.js} +6 -3
  102. package/dist/admin/chunks/hooks-D-sOYd1s.js.map +1 -0
  103. package/dist/admin/chunks/hooks-DMvik5y_.mjs +7 -0
  104. package/dist/admin/chunks/hooks-DMvik5y_.mjs.map +1 -0
  105. package/dist/admin/chunks/hu-CLka1U2C.mjs +198 -0
  106. package/dist/admin/chunks/hu-CLka1U2C.mjs.map +1 -0
  107. package/dist/admin/chunks/hu-CtFJuhTd.js +203 -0
  108. package/dist/admin/chunks/hu-CtFJuhTd.js.map +1 -0
  109. package/dist/admin/chunks/id-D7V5S1rB.js +161 -0
  110. package/dist/{_chunks/it-DkBIs7vD.js.map → admin/chunks/id-D7V5S1rB.js.map} +1 -1
  111. package/dist/admin/chunks/id-USfY9m1g.mjs +156 -0
  112. package/dist/{_chunks/id-BtwA9WJT.mjs.map → admin/chunks/id-USfY9m1g.mjs.map} +1 -1
  113. package/dist/admin/chunks/index-BczuAULz.js +5416 -0
  114. package/dist/admin/chunks/index-BczuAULz.js.map +1 -0
  115. package/dist/admin/chunks/index-DjT63ZVp.mjs +5350 -0
  116. package/dist/admin/chunks/index-DjT63ZVp.mjs.map +1 -0
  117. package/dist/admin/chunks/it-BAHrwmYS.mjs +158 -0
  118. package/dist/{_chunks/it-BrVPqaf1.mjs.map → admin/chunks/it-BAHrwmYS.mjs.map} +1 -1
  119. package/dist/admin/chunks/it-CQFpa_Dc.js +163 -0
  120. package/dist/{_chunks/ko-woFZPmLk.js.map → admin/chunks/it-CQFpa_Dc.js.map} +1 -1
  121. package/dist/admin/chunks/ja-BWKmBJFT.mjs +192 -0
  122. package/dist/{_chunks/ko-HVQRlfUI.mjs.map → admin/chunks/ja-BWKmBJFT.mjs.map} +1 -1
  123. package/dist/admin/chunks/ja-jdQM-B79.js +197 -0
  124. package/dist/{_chunks/de-CCEmbAah.js.map → admin/chunks/ja-jdQM-B79.js.map} +1 -1
  125. package/dist/admin/chunks/ko-CgADGBNt.mjs +191 -0
  126. package/dist/{_chunks/es-D34tqjMw.mjs.map → admin/chunks/ko-CgADGBNt.mjs.map} +1 -1
  127. package/dist/admin/chunks/ko-k46sEyzt.js +196 -0
  128. package/dist/{_chunks/ja-7sfIbjxE.js.map → admin/chunks/ko-k46sEyzt.js.map} +1 -1
  129. package/dist/admin/chunks/layout-C1ypP2pr.mjs +598 -0
  130. package/dist/admin/chunks/layout-C1ypP2pr.mjs.map +1 -0
  131. package/dist/admin/chunks/layout-DcDoRT8g.js +618 -0
  132. package/dist/admin/chunks/layout-DcDoRT8g.js.map +1 -0
  133. package/dist/admin/chunks/ml-CnhCfOn_.mjs +196 -0
  134. package/dist/admin/chunks/ml-CnhCfOn_.mjs.map +1 -0
  135. package/dist/admin/chunks/ml-DqxPwODx.js +201 -0
  136. package/dist/admin/chunks/ml-DqxPwODx.js.map +1 -0
  137. package/dist/admin/chunks/ms-Bh09NFff.mjs +140 -0
  138. package/dist/{_chunks/ms-m_WjyWx7.mjs.map → admin/chunks/ms-Bh09NFff.mjs.map} +1 -1
  139. package/dist/admin/chunks/ms-CvSC0OdG.js +145 -0
  140. package/dist/{_chunks/ms-BuFotyP_.js.map → admin/chunks/ms-CvSC0OdG.js.map} +1 -1
  141. package/dist/admin/chunks/nl-BEubhS8C.js +203 -0
  142. package/dist/admin/chunks/nl-BEubhS8C.js.map +1 -0
  143. package/dist/admin/chunks/nl-C8HYflTc.mjs +198 -0
  144. package/dist/admin/chunks/nl-C8HYflTc.mjs.map +1 -0
  145. package/dist/admin/chunks/objects-C3EebVVe.js +76 -0
  146. package/dist/admin/chunks/objects-C3EebVVe.js.map +1 -0
  147. package/dist/admin/chunks/objects-wl73iEma.mjs +73 -0
  148. package/dist/admin/chunks/objects-wl73iEma.mjs.map +1 -0
  149. package/dist/admin/chunks/pl-DWhGDzmM.js +200 -0
  150. package/dist/{_chunks/ca-Cmk45QO6.js.map → admin/chunks/pl-DWhGDzmM.js.map} +1 -1
  151. package/dist/admin/chunks/pl-MFCZJZuZ.mjs +195 -0
  152. package/dist/{_chunks/ca-5U32ON2v.mjs.map → admin/chunks/pl-MFCZJZuZ.mjs.map} +1 -1
  153. package/dist/admin/chunks/pt-BR-CPtAXD-4.js +202 -0
  154. package/dist/{_chunks/pt-BR-BiOz37D9.js.map → admin/chunks/pt-BR-CPtAXD-4.js.map} +1 -1
  155. package/dist/admin/chunks/pt-BR-CcotyBGJ.mjs +197 -0
  156. package/dist/{_chunks/pt-BR-C71iDxnh.mjs.map → admin/chunks/pt-BR-CcotyBGJ.mjs.map} +1 -1
  157. package/dist/admin/chunks/pt-BoPxN80n.js +96 -0
  158. package/dist/admin/chunks/pt-BoPxN80n.js.map +1 -0
  159. package/dist/admin/chunks/pt-HbmgeiYO.mjs +93 -0
  160. package/dist/admin/chunks/pt-HbmgeiYO.mjs.map +1 -0
  161. package/dist/admin/chunks/relations-CYyb3QEr.mjs +173 -0
  162. package/dist/admin/chunks/relations-CYyb3QEr.mjs.map +1 -0
  163. package/dist/admin/chunks/relations-CgaydhiM.js +178 -0
  164. package/dist/admin/chunks/relations-CgaydhiM.js.map +1 -0
  165. package/dist/admin/chunks/ru-C0op0ALG.js +232 -0
  166. package/dist/admin/chunks/ru-C0op0ALG.js.map +1 -0
  167. package/dist/admin/chunks/ru-CB4BUyQp.mjs +230 -0
  168. package/dist/{_chunks/ru-BE6A4Exp.mjs.map → admin/chunks/ru-CB4BUyQp.mjs.map} +1 -1
  169. package/dist/admin/chunks/sa-B_FuPyMw.js +201 -0
  170. package/dist/admin/chunks/sa-B_FuPyMw.js.map +1 -0
  171. package/dist/admin/chunks/sa-n_aPA-pU.mjs +196 -0
  172. package/dist/admin/chunks/sa-n_aPA-pU.mjs.map +1 -0
  173. package/dist/admin/chunks/sk-D_iXML2C.js +203 -0
  174. package/dist/admin/chunks/sk-D_iXML2C.js.map +1 -0
  175. package/dist/admin/chunks/sk-tn_BDjE2.mjs +198 -0
  176. package/dist/admin/chunks/sk-tn_BDjE2.mjs.map +1 -0
  177. package/dist/admin/chunks/sv-BstBC1Yp.js +203 -0
  178. package/dist/admin/chunks/sv-BstBC1Yp.js.map +1 -0
  179. package/dist/admin/chunks/sv-cq4ZrQRd.mjs +198 -0
  180. package/dist/admin/chunks/sv-cq4ZrQRd.mjs.map +1 -0
  181. package/dist/admin/chunks/th-lXoOCqPC.js +149 -0
  182. package/dist/{_chunks/th-D9_GfAjc.js.map → admin/chunks/th-lXoOCqPC.js.map} +1 -1
  183. package/dist/admin/chunks/th-mUH7hEtc.mjs +144 -0
  184. package/dist/{_chunks/th-BqbI8lIT.mjs.map → admin/chunks/th-mUH7hEtc.mjs.map} +1 -1
  185. package/dist/admin/chunks/tr-CkS6sLIE.js +200 -0
  186. package/dist/admin/chunks/tr-CkS6sLIE.js.map +1 -0
  187. package/dist/admin/chunks/tr-Yt38daxh.mjs +195 -0
  188. package/dist/{_chunks/de-C72KDNOl.mjs.map → admin/chunks/tr-Yt38daxh.mjs.map} +1 -1
  189. package/dist/admin/chunks/uk-B24MoTVg.js +145 -0
  190. package/dist/{_chunks/uk-C8EiqJY7.js.map → admin/chunks/uk-B24MoTVg.js.map} +1 -1
  191. package/dist/admin/chunks/uk-Cpgmm7gE.mjs +140 -0
  192. package/dist/{_chunks/uk-CR-zDhAY.mjs.map → admin/chunks/uk-Cpgmm7gE.mjs.map} +1 -1
  193. package/dist/admin/chunks/useDragAndDrop-HYwNDExe.mjs +247 -0
  194. package/dist/admin/chunks/useDragAndDrop-HYwNDExe.mjs.map +1 -0
  195. package/dist/admin/chunks/useDragAndDrop-gcqEJMnO.js +271 -0
  196. package/dist/admin/chunks/useDragAndDrop-gcqEJMnO.js.map +1 -0
  197. package/dist/admin/chunks/usePrev-Bjw2dhmq.mjs +18 -0
  198. package/dist/admin/chunks/usePrev-Bjw2dhmq.mjs.map +1 -0
  199. package/dist/admin/chunks/usePrev-DIYl-IAL.js +21 -0
  200. package/dist/admin/chunks/usePrev-DIYl-IAL.js.map +1 -0
  201. package/dist/admin/chunks/vi-BGr1X_HZ.js +112 -0
  202. package/dist/{_chunks/vi-CJlYDheJ.js.map → admin/chunks/vi-BGr1X_HZ.js.map} +1 -1
  203. package/dist/admin/chunks/vi-CvBGlTjr.mjs +108 -0
  204. package/dist/{_chunks/vi-DUXIk_fw.mjs.map → admin/chunks/vi-CvBGlTjr.mjs.map} +1 -1
  205. package/dist/admin/chunks/zh-BmF-sHaT.mjs +205 -0
  206. package/dist/admin/chunks/zh-BmF-sHaT.mjs.map +1 -0
  207. package/dist/admin/chunks/zh-DwFu_Kfj.js +210 -0
  208. package/dist/admin/chunks/zh-DwFu_Kfj.js.map +1 -0
  209. package/dist/admin/chunks/zh-Hans-CI0HKio3.mjs +934 -0
  210. package/dist/{_chunks/zh-Hans-BPQcRIyH.mjs.map → admin/chunks/zh-Hans-CI0HKio3.mjs.map} +1 -1
  211. package/dist/admin/chunks/zh-Hans-JVK9x7xr.js +953 -0
  212. package/dist/{_chunks/zh-Hans-9kOncHGw.js.map → admin/chunks/zh-Hans-JVK9x7xr.js.map} +1 -1
  213. package/dist/admin/index.js +23 -4
  214. package/dist/admin/index.js.map +1 -1
  215. package/dist/admin/index.mjs +16 -13
  216. package/dist/admin/index.mjs.map +1 -1
  217. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  218. package/dist/admin/src/hooks/useDocument.d.ts +21 -4
  219. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.d.ts +50 -1
  220. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.d.ts +4 -1
  221. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +4 -1
  222. package/dist/admin/src/pages/EditView/components/FormLayout.d.ts +27 -0
  223. package/dist/admin/src/pages/EditView/utils/data.d.ts +1 -0
  224. package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -1
  225. package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -1
  226. package/dist/admin/src/preview/index.d.ts +2 -3
  227. package/dist/admin/src/preview/pages/Preview.d.ts +1 -1
  228. package/dist/server/index.js +5451 -4361
  229. package/dist/server/index.js.map +1 -1
  230. package/dist/server/index.mjs +5437 -4345
  231. package/dist/server/index.mjs.map +1 -1
  232. package/dist/server/src/controllers/utils/metadata.d.ts +2 -1
  233. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
  234. package/dist/server/src/history/controllers/history-version.d.ts +1 -1
  235. package/dist/server/src/history/controllers/history-version.d.ts.map +1 -1
  236. package/dist/server/src/history/services/history.d.ts +3 -3
  237. package/dist/server/src/history/services/history.d.ts.map +1 -1
  238. package/dist/server/src/history/services/utils.d.ts +6 -10
  239. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  240. package/dist/server/src/index.d.ts +3 -2
  241. package/dist/server/src/index.d.ts.map +1 -1
  242. package/dist/server/src/services/document-metadata.d.ts +4 -2
  243. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  244. package/dist/server/src/services/index.d.ts +3 -2
  245. package/dist/server/src/services/index.d.ts.map +1 -1
  246. package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
  247. package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
  248. package/dist/server/src/services/utils/count.d.ts +1 -1
  249. package/dist/server/src/services/utils/count.d.ts.map +1 -1
  250. package/dist/server/src/services/utils/populate.d.ts +3 -3
  251. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  252. package/dist/shared/contracts/collection-types.d.ts +0 -1
  253. package/dist/shared/contracts/components.d.ts +0 -1
  254. package/dist/shared/contracts/content-types.d.ts +0 -1
  255. package/dist/shared/contracts/history-versions.d.ts +0 -1
  256. package/dist/shared/contracts/index.d.ts +0 -1
  257. package/dist/shared/contracts/init.d.ts +0 -1
  258. package/dist/shared/contracts/preview.d.ts +0 -1
  259. package/dist/shared/contracts/relations.d.ts +1 -2
  260. package/dist/shared/contracts/relations.d.ts.map +1 -1
  261. package/dist/shared/contracts/review-workflows.d.ts +0 -1
  262. package/dist/shared/contracts/single-types.d.ts +0 -1
  263. package/dist/shared/contracts/uid.d.ts +0 -1
  264. package/dist/shared/index.d.ts +0 -1
  265. package/dist/shared/index.js +35 -24
  266. package/dist/shared/index.js.map +1 -1
  267. package/dist/shared/index.mjs +34 -25
  268. package/dist/shared/index.mjs.map +1 -1
  269. package/package.json +14 -12
  270. package/dist/_chunks/CardDragPreview-C0QyJgRA.js +0 -69
  271. package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +0 -1
  272. package/dist/_chunks/CardDragPreview-DOxamsuj.mjs +0 -70
  273. package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +0 -1
  274. package/dist/_chunks/ComponentConfigurationPage-A5f-t42A.mjs +0 -236
  275. package/dist/_chunks/ComponentConfigurationPage-A5f-t42A.mjs.map +0 -1
  276. package/dist/_chunks/ComponentConfigurationPage-BtmEfYUS.js +0 -254
  277. package/dist/_chunks/ComponentConfigurationPage-BtmEfYUS.js.map +0 -1
  278. package/dist/_chunks/ComponentIcon-CRbtQEUV.js +0 -175
  279. package/dist/_chunks/ComponentIcon-CRbtQEUV.js.map +0 -1
  280. package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs +0 -157
  281. package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +0 -1
  282. package/dist/_chunks/EditConfigurationPage-CXLQhPpj.js +0 -150
  283. package/dist/_chunks/EditConfigurationPage-CXLQhPpj.js.map +0 -1
  284. package/dist/_chunks/EditConfigurationPage-DN6yaDFZ.mjs +0 -132
  285. package/dist/_chunks/EditConfigurationPage-DN6yaDFZ.mjs.map +0 -1
  286. package/dist/_chunks/EditViewPage-BW-BJJVg.js +0 -272
  287. package/dist/_chunks/EditViewPage-BW-BJJVg.js.map +0 -1
  288. package/dist/_chunks/EditViewPage-ONky_-8U.mjs +0 -254
  289. package/dist/_chunks/EditViewPage-ONky_-8U.mjs.map +0 -1
  290. package/dist/_chunks/Field-B4gAYDmQ.mjs +0 -5642
  291. package/dist/_chunks/Field-B4gAYDmQ.mjs.map +0 -1
  292. package/dist/_chunks/Field-BMlzghtV.js +0 -5674
  293. package/dist/_chunks/Field-BMlzghtV.js.map +0 -1
  294. package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs +0 -50
  295. package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +0 -1
  296. package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js +0 -49
  297. package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +0 -1
  298. package/dist/_chunks/Form-DQPyv3UY.js +0 -778
  299. package/dist/_chunks/Form-DQPyv3UY.js.map +0 -1
  300. package/dist/_chunks/Form-e4RpNQY0.mjs +0 -758
  301. package/dist/_chunks/Form-e4RpNQY0.mjs.map +0 -1
  302. package/dist/_chunks/History-Bk2VCzmJ.mjs +0 -975
  303. package/dist/_chunks/History-Bk2VCzmJ.mjs.map +0 -1
  304. package/dist/_chunks/History-CzkXjAR0.js +0 -995
  305. package/dist/_chunks/History-CzkXjAR0.js.map +0 -1
  306. package/dist/_chunks/ListConfigurationPage-B9TbaEqp.js +0 -652
  307. package/dist/_chunks/ListConfigurationPage-B9TbaEqp.js.map +0 -1
  308. package/dist/_chunks/ListConfigurationPage-BhNCzkQd.mjs +0 -633
  309. package/dist/_chunks/ListConfigurationPage-BhNCzkQd.mjs.map +0 -1
  310. package/dist/_chunks/ListViewPage-CIHO4H2J.js +0 -874
  311. package/dist/_chunks/ListViewPage-CIHO4H2J.js.map +0 -1
  312. package/dist/_chunks/ListViewPage-mK-sFVGU.mjs +0 -851
  313. package/dist/_chunks/ListViewPage-mK-sFVGU.mjs.map +0 -1
  314. package/dist/_chunks/NoContentTypePage-BSVg7nZI.mjs +0 -51
  315. package/dist/_chunks/NoContentTypePage-BSVg7nZI.mjs.map +0 -1
  316. package/dist/_chunks/NoContentTypePage-Dbfi49ek.js +0 -51
  317. package/dist/_chunks/NoContentTypePage-Dbfi49ek.js.map +0 -1
  318. package/dist/_chunks/NoPermissionsPage-CDvWOtEy.js +0 -23
  319. package/dist/_chunks/NoPermissionsPage-CDvWOtEy.js.map +0 -1
  320. package/dist/_chunks/NoPermissionsPage-zpYME1_X.mjs +0 -23
  321. package/dist/_chunks/NoPermissionsPage-zpYME1_X.mjs.map +0 -1
  322. package/dist/_chunks/Preview-8U27vy1U.js +0 -311
  323. package/dist/_chunks/Preview-8U27vy1U.js.map +0 -1
  324. package/dist/_chunks/Preview-Dd3kQluA.mjs +0 -293
  325. package/dist/_chunks/Preview-Dd3kQluA.mjs.map +0 -1
  326. package/dist/_chunks/Relations-BvdARGTL.mjs +0 -728
  327. package/dist/_chunks/Relations-BvdARGTL.mjs.map +0 -1
  328. package/dist/_chunks/Relations-CFMS6Dm8.js +0 -747
  329. package/dist/_chunks/Relations-CFMS6Dm8.js.map +0 -1
  330. package/dist/_chunks/ar-BUUWXIYu.js +0 -226
  331. package/dist/_chunks/ar-BUUWXIYu.js.map +0 -1
  332. package/dist/_chunks/ar-CCEVvqGG.mjs +0 -226
  333. package/dist/_chunks/ca-5U32ON2v.mjs +0 -201
  334. package/dist/_chunks/ca-Cmk45QO6.js +0 -201
  335. package/dist/_chunks/cs-CM2aBUar.mjs +0 -125
  336. package/dist/_chunks/cs-CkJy6B2v.js +0 -125
  337. package/dist/_chunks/de-C72KDNOl.mjs +0 -199
  338. package/dist/_chunks/de-CCEmbAah.js +0 -199
  339. package/dist/_chunks/en-BzQmavmK.js +0 -310
  340. package/dist/_chunks/en-CSxLmrh1.mjs +0 -310
  341. package/dist/_chunks/es-9K52xZIr.js +0 -196
  342. package/dist/_chunks/es-D34tqjMw.mjs +0 -196
  343. package/dist/_chunks/eu-CdALomew.mjs +0 -202
  344. package/dist/_chunks/eu-VDH-3ovk.js +0 -202
  345. package/dist/_chunks/fr--pg5jUbt.mjs +0 -216
  346. package/dist/_chunks/fr--pg5jUbt.mjs.map +0 -1
  347. package/dist/_chunks/fr-B2Kyv8Z9.js +0 -216
  348. package/dist/_chunks/fr-B2Kyv8Z9.js.map +0 -1
  349. package/dist/_chunks/gu-BRmF601H.js +0 -200
  350. package/dist/_chunks/gu-CNpaMDpH.mjs +0 -200
  351. package/dist/_chunks/gu-CNpaMDpH.mjs.map +0 -1
  352. package/dist/_chunks/hi-CCJBptSq.js +0 -200
  353. package/dist/_chunks/hi-CCJBptSq.js.map +0 -1
  354. package/dist/_chunks/hi-Dwvd04m3.mjs +0 -200
  355. package/dist/_chunks/hi-Dwvd04m3.mjs.map +0 -1
  356. package/dist/_chunks/hooks-BAaaKPS_.js.map +0 -1
  357. package/dist/_chunks/hooks-E5u1mcgM.mjs +0 -8
  358. package/dist/_chunks/hooks-E5u1mcgM.mjs.map +0 -1
  359. package/dist/_chunks/hu-CeYvaaO0.mjs +0 -202
  360. package/dist/_chunks/hu-CeYvaaO0.mjs.map +0 -1
  361. package/dist/_chunks/hu-sNV_yLYy.js +0 -202
  362. package/dist/_chunks/hu-sNV_yLYy.js.map +0 -1
  363. package/dist/_chunks/id-B5Ser98A.js +0 -160
  364. package/dist/_chunks/id-B5Ser98A.js.map +0 -1
  365. package/dist/_chunks/id-BtwA9WJT.mjs +0 -160
  366. package/dist/_chunks/index-B3tHjkLZ.mjs +0 -4272
  367. package/dist/_chunks/index-B3tHjkLZ.mjs.map +0 -1
  368. package/dist/_chunks/index-TSBwtMDV.js +0 -4291
  369. package/dist/_chunks/index-TSBwtMDV.js.map +0 -1
  370. package/dist/_chunks/it-BrVPqaf1.mjs +0 -162
  371. package/dist/_chunks/it-DkBIs7vD.js +0 -162
  372. package/dist/_chunks/ja-7sfIbjxE.js +0 -196
  373. package/dist/_chunks/ja-BHqhDq4V.mjs +0 -196
  374. package/dist/_chunks/ko-HVQRlfUI.mjs +0 -195
  375. package/dist/_chunks/ko-woFZPmLk.js +0 -195
  376. package/dist/_chunks/layout-C71zeI19.mjs +0 -471
  377. package/dist/_chunks/layout-C71zeI19.mjs.map +0 -1
  378. package/dist/_chunks/layout-CB2vrWLp.js +0 -488
  379. package/dist/_chunks/layout-CB2vrWLp.js.map +0 -1
  380. package/dist/_chunks/ml-BihZwQit.mjs +0 -200
  381. package/dist/_chunks/ml-BihZwQit.mjs.map +0 -1
  382. package/dist/_chunks/ml-C2W8N8k1.js +0 -200
  383. package/dist/_chunks/ml-C2W8N8k1.js.map +0 -1
  384. package/dist/_chunks/ms-BuFotyP_.js +0 -144
  385. package/dist/_chunks/ms-m_WjyWx7.mjs +0 -144
  386. package/dist/_chunks/nl-D4R9gHx5.mjs +0 -202
  387. package/dist/_chunks/nl-D4R9gHx5.mjs.map +0 -1
  388. package/dist/_chunks/nl-bbEOHChV.js +0 -202
  389. package/dist/_chunks/nl-bbEOHChV.js.map +0 -1
  390. package/dist/_chunks/objects-BcXOv6_9.js +0 -47
  391. package/dist/_chunks/objects-BcXOv6_9.js.map +0 -1
  392. package/dist/_chunks/objects-D6yBsdmx.mjs +0 -45
  393. package/dist/_chunks/objects-D6yBsdmx.mjs.map +0 -1
  394. package/dist/_chunks/pl-sbx9mSt_.mjs +0 -199
  395. package/dist/_chunks/pl-sbx9mSt_.mjs.map +0 -1
  396. package/dist/_chunks/pl-uzwG-hk7.js +0 -199
  397. package/dist/_chunks/pl-uzwG-hk7.js.map +0 -1
  398. package/dist/_chunks/pt-BR-BiOz37D9.js +0 -201
  399. package/dist/_chunks/pt-BR-C71iDxnh.mjs +0 -201
  400. package/dist/_chunks/pt-BsaFvS8-.mjs +0 -95
  401. package/dist/_chunks/pt-BsaFvS8-.mjs.map +0 -1
  402. package/dist/_chunks/pt-CeXQuq50.js +0 -95
  403. package/dist/_chunks/pt-CeXQuq50.js.map +0 -1
  404. package/dist/_chunks/relations-8mON7ZVQ.js +0 -133
  405. package/dist/_chunks/relations-8mON7ZVQ.js.map +0 -1
  406. package/dist/_chunks/relations-DcEHhh0U.mjs +0 -134
  407. package/dist/_chunks/relations-DcEHhh0U.mjs.map +0 -1
  408. package/dist/_chunks/ru-BE6A4Exp.mjs +0 -231
  409. package/dist/_chunks/ru-BT3ybNny.js +0 -231
  410. package/dist/_chunks/sa-CcvkYInH.js +0 -200
  411. package/dist/_chunks/sa-CcvkYInH.js.map +0 -1
  412. package/dist/_chunks/sa-Dag0k-Z8.mjs +0 -200
  413. package/dist/_chunks/sa-Dag0k-Z8.mjs.map +0 -1
  414. package/dist/_chunks/sk-BFg-R8qJ.mjs +0 -202
  415. package/dist/_chunks/sk-BFg-R8qJ.mjs.map +0 -1
  416. package/dist/_chunks/sk-CvY09Xjv.js +0 -202
  417. package/dist/_chunks/sk-CvY09Xjv.js.map +0 -1
  418. package/dist/_chunks/sv-CUnfWGsh.mjs +0 -202
  419. package/dist/_chunks/sv-CUnfWGsh.mjs.map +0 -1
  420. package/dist/_chunks/sv-MYDuzgvT.js +0 -202
  421. package/dist/_chunks/sv-MYDuzgvT.js.map +0 -1
  422. package/dist/_chunks/th-BqbI8lIT.mjs +0 -148
  423. package/dist/_chunks/th-D9_GfAjc.js +0 -148
  424. package/dist/_chunks/tr-CgeK3wJM.mjs +0 -199
  425. package/dist/_chunks/tr-CgeK3wJM.mjs.map +0 -1
  426. package/dist/_chunks/tr-D9UH-O_R.js +0 -199
  427. package/dist/_chunks/tr-D9UH-O_R.js.map +0 -1
  428. package/dist/_chunks/uk-C8EiqJY7.js +0 -144
  429. package/dist/_chunks/uk-CR-zDhAY.mjs +0 -144
  430. package/dist/_chunks/useDebounce-CtcjDB3L.js +0 -28
  431. package/dist/_chunks/useDebounce-CtcjDB3L.js.map +0 -1
  432. package/dist/_chunks/useDebounce-DmuSJIF3.mjs +0 -29
  433. package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +0 -1
  434. package/dist/_chunks/useDragAndDrop-BMtgCYzL.js +0 -245
  435. package/dist/_chunks/useDragAndDrop-BMtgCYzL.js.map +0 -1
  436. package/dist/_chunks/useDragAndDrop-DJ6jqvZN.mjs +0 -228
  437. package/dist/_chunks/useDragAndDrop-DJ6jqvZN.mjs.map +0 -1
  438. package/dist/_chunks/vi-CJlYDheJ.js +0 -111
  439. package/dist/_chunks/vi-DUXIk_fw.mjs +0 -111
  440. package/dist/_chunks/zh-BWZspA60.mjs +0 -209
  441. package/dist/_chunks/zh-BWZspA60.mjs.map +0 -1
  442. package/dist/_chunks/zh-CQQfszqR.js +0 -209
  443. package/dist/_chunks/zh-CQQfszqR.js.map +0 -1
  444. package/dist/_chunks/zh-Hans-9kOncHGw.js +0 -952
  445. package/dist/_chunks/zh-Hans-BPQcRIyH.mjs +0 -952
  446. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/utils/prismLanguages.d.ts +0 -49
@@ -1,4272 +0,0 @@
1
- import { More, Cross, WarningCircle, ListPlus, Pencil, Trash, Check, CrossCircle, CheckCircle, ArrowsCounterClockwise, ChevronRight, Duplicate, ClockCounterClockwise, Feather } from "@strapi/icons";
2
- import { jsx, Fragment, jsxs } from "react/jsx-runtime";
3
- import { useStrapiApp, createContext, useQueryParams, useAuth, useRBAC, Page, adminApi, translatedErrors, useNotification, useAPIErrorHandler, getYupValidationErrors, useForm, useTracking, useGuidedTour, BackButton, DescriptionComponentRenderer, useTable, Table } from "@strapi/admin/strapi-admin";
4
- import * as React from "react";
5
- import { lazy } from "react";
6
- import { Menu, Button, VisuallyHidden, Flex, Dialog, Modal, Typography, Radio, Status, Box, SingleSelect, SingleSelectOption, IconButton, Loader, Tooltip, LinkButton } from "@strapi/design-system";
7
- import mapValues from "lodash/fp/mapValues";
8
- import { useIntl } from "react-intl";
9
- import { useParams, useNavigate, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
10
- import { styled } from "styled-components";
11
- import * as yup from "yup";
12
- import { ValidationError } from "yup";
13
- import { stringify } from "qs";
14
- import pipe from "lodash/fp/pipe";
15
- import { intervalToDuration, isPast } from "date-fns";
16
- import { createSlice, combineReducers } from "@reduxjs/toolkit";
17
- const __variableDynamicImportRuntimeHelper = (glob, path, segs) => {
18
- const v = glob[path];
19
- if (v) {
20
- return typeof v === "function" ? v() : Promise.resolve(v);
21
- }
22
- return new Promise((_, reject) => {
23
- (typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(
24
- reject.bind(
25
- null,
26
- new Error(
27
- "Unknown variable dynamic import: " + path + (path.split("/").length !== segs ? ". Note that variables only represent file names one level deep." : "")
28
- )
29
- )
30
- );
31
- });
32
- };
33
- const PLUGIN_ID = "content-manager";
34
- const PERMISSIONS = [
35
- "plugin::content-manager.explorer.create",
36
- "plugin::content-manager.explorer.read",
37
- "plugin::content-manager.explorer.update",
38
- "plugin::content-manager.explorer.delete",
39
- "plugin::content-manager.explorer.publish"
40
- ];
41
- const INJECTION_ZONES = {
42
- editView: { informations: [], "right-links": [] },
43
- listView: {
44
- actions: [],
45
- deleteModalAdditionalInfos: [],
46
- publishModalAdditionalInfos: [],
47
- unpublishModalAdditionalInfos: []
48
- }
49
- };
50
- const InjectionZone = ({ area, ...props }) => {
51
- const components = useInjectionZone(area);
52
- return /* @__PURE__ */ jsx(Fragment, { children: components.map((component) => /* @__PURE__ */ jsx(component.Component, { ...props }, component.name)) });
53
- };
54
- const useInjectionZone = (area) => {
55
- const getPlugin = useStrapiApp("useInjectionZone", (state) => state.getPlugin);
56
- const contentManagerPlugin = getPlugin(PLUGIN_ID);
57
- const [page, position] = area.split(".");
58
- return contentManagerPlugin.getInjectedComponents(page, position);
59
- };
60
- const ID = "id";
61
- const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
62
- const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
63
- const CREATOR_FIELDS = [CREATED_BY_ATTRIBUTE_NAME, UPDATED_BY_ATTRIBUTE_NAME];
64
- const PUBLISHED_BY_ATTRIBUTE_NAME = "publishedBy";
65
- const CREATED_AT_ATTRIBUTE_NAME = "createdAt";
66
- const UPDATED_AT_ATTRIBUTE_NAME = "updatedAt";
67
- const PUBLISHED_AT_ATTRIBUTE_NAME = "publishedAt";
68
- const DOCUMENT_META_FIELDS = [
69
- ID,
70
- ...CREATOR_FIELDS,
71
- PUBLISHED_BY_ATTRIBUTE_NAME,
72
- CREATED_AT_ATTRIBUTE_NAME,
73
- UPDATED_AT_ATTRIBUTE_NAME,
74
- PUBLISHED_AT_ATTRIBUTE_NAME
75
- ];
76
- const ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = [
77
- "dynamiczone",
78
- "json",
79
- "text",
80
- "relation",
81
- "component",
82
- "boolean",
83
- "media",
84
- "password",
85
- "richtext",
86
- "timestamp",
87
- "blocks"
88
- ];
89
- const SINGLE_TYPES = "single-types";
90
- const COLLECTION_TYPES = "collection-types";
91
- const [DocumentRBACProvider, useDocumentRBAC] = createContext(
92
- "DocumentRBAC",
93
- {
94
- canCreate: false,
95
- canCreateFields: [],
96
- canDelete: false,
97
- canPublish: false,
98
- canRead: false,
99
- canReadFields: [],
100
- canUpdate: false,
101
- canUpdateFields: [],
102
- canUserAction: () => false,
103
- isLoading: false
104
- }
105
- );
106
- const DocumentRBAC = ({ children, permissions }) => {
107
- const { slug } = useParams();
108
- if (!slug) {
109
- throw new Error("Cannot find the slug param in the URL");
110
- }
111
- const [{ rawQuery }] = useQueryParams();
112
- const userPermissions = useAuth("DocumentRBAC", (state) => state.permissions);
113
- const contentTypePermissions = React.useMemo(() => {
114
- const contentTypePermissions2 = userPermissions.filter(
115
- (permission) => permission.subject === slug
116
- );
117
- return contentTypePermissions2.reduce((acc, permission) => {
118
- const [action] = permission.action.split(".").slice(-1);
119
- return { ...acc, [action]: [permission] };
120
- }, {});
121
- }, [slug, userPermissions]);
122
- const { isLoading, allowedActions } = useRBAC(
123
- contentTypePermissions,
124
- permissions ?? void 0,
125
- // TODO: useRBAC context should be typed and built differently
126
- // We are passing raw query as context to the hook so that it can
127
- // rely on the locale provided from DocumentRBAC for its permission calculations.
128
- rawQuery
129
- );
130
- const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
131
- const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
132
- const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
133
- const canUserAction = React.useCallback(
134
- (fieldName, fieldsUserCanAction, fieldType) => {
135
- const name = removeNumericalStrings(fieldName.split("."));
136
- const componentFieldNames = fieldsUserCanAction.filter((field) => field.split(".").length > 1);
137
- if (fieldType === "component") {
138
- return componentFieldNames.some((field) => {
139
- return field.includes(name.join("."));
140
- });
141
- }
142
- if (name.length > 1) {
143
- return componentFieldNames.includes(name.join("."));
144
- }
145
- return fieldsUserCanAction.includes(fieldName);
146
- },
147
- []
148
- );
149
- if (isLoading) {
150
- return /* @__PURE__ */ jsx(Page.Loading, {});
151
- }
152
- return /* @__PURE__ */ jsx(
153
- DocumentRBACProvider,
154
- {
155
- isLoading,
156
- canCreateFields,
157
- canReadFields,
158
- canUpdateFields,
159
- canUserAction,
160
- ...allowedActions,
161
- children
162
- }
163
- );
164
- };
165
- const extractAndDedupeFields = (permissions = []) => permissions.flatMap((permission) => permission.properties?.fields).filter(
166
- (field, index2, arr) => arr.indexOf(field) === index2 && typeof field === "string"
167
- );
168
- const removeNumericalStrings = (arr) => arr.filter((item) => isNaN(Number(item)));
169
- const contentManagerApi = adminApi.enhanceEndpoints({
170
- addTagTypes: [
171
- "ComponentConfiguration",
172
- "ContentTypesConfiguration",
173
- "ContentTypeSettings",
174
- "Document",
175
- "InitialData",
176
- "HistoryVersion",
177
- "Relations",
178
- "UidAvailability",
179
- "RecentDocumentList"
180
- ]
181
- });
182
- const documentApi = contentManagerApi.injectEndpoints({
183
- overrideExisting: true,
184
- endpoints: (builder) => ({
185
- autoCloneDocument: builder.mutation({
186
- query: ({ model, sourceId, query }) => ({
187
- url: `/content-manager/collection-types/${model}/auto-clone/${sourceId}`,
188
- method: "POST",
189
- config: {
190
- params: query
191
- }
192
- }),
193
- invalidatesTags: (_result, error, { model }) => {
194
- if (error) {
195
- return [];
196
- }
197
- return [{ type: "Document", id: `${model}_LIST` }, "RecentDocumentList"];
198
- }
199
- }),
200
- cloneDocument: builder.mutation({
201
- query: ({ model, sourceId, data, params }) => ({
202
- url: `/content-manager/collection-types/${model}/clone/${sourceId}`,
203
- method: "POST",
204
- data,
205
- config: {
206
- params
207
- }
208
- }),
209
- invalidatesTags: (_result, _error, { model }) => [
210
- { type: "Document", id: `${model}_LIST` },
211
- { type: "UidAvailability", id: model },
212
- "RecentDocumentList"
213
- ]
214
- }),
215
- /**
216
- * Creates a new collection-type document. This should ONLY be used for collection-types.
217
- * single-types should always be using `updateDocument` since they always exist.
218
- */
219
- createDocument: builder.mutation({
220
- query: ({ model, data, params }) => ({
221
- url: `/content-manager/collection-types/${model}`,
222
- method: "POST",
223
- data,
224
- config: {
225
- params
226
- }
227
- }),
228
- invalidatesTags: (result, _error, { model }) => [
229
- { type: "Document", id: `${model}_LIST` },
230
- "Relations",
231
- { type: "UidAvailability", id: model },
232
- "RecentDocumentList"
233
- ]
234
- }),
235
- deleteDocument: builder.mutation({
236
- query: ({ collectionType, model, documentId, params }) => ({
237
- url: `/content-manager/${collectionType}/${model}${collectionType !== SINGLE_TYPES && documentId ? `/${documentId}` : ""}`,
238
- method: "DELETE",
239
- config: {
240
- params
241
- }
242
- }),
243
- invalidatesTags: (_result, _error, { collectionType, model }) => [
244
- { type: "Document", id: collectionType !== SINGLE_TYPES ? `${model}_LIST` : model },
245
- "RecentDocumentList"
246
- ]
247
- }),
248
- deleteManyDocuments: builder.mutation({
249
- query: ({ model, params, ...body }) => ({
250
- url: `/content-manager/collection-types/${model}/actions/bulkDelete`,
251
- method: "POST",
252
- data: body,
253
- config: {
254
- params
255
- }
256
- }),
257
- invalidatesTags: (_res, _error, { model }) => [
258
- { type: "Document", id: `${model}_LIST` },
259
- "RecentDocumentList"
260
- ]
261
- }),
262
- discardDocument: builder.mutation({
263
- query: ({ collectionType, model, documentId, params }) => ({
264
- url: documentId ? `/content-manager/${collectionType}/${model}/${documentId}/actions/discard` : `/content-manager/${collectionType}/${model}/actions/discard`,
265
- method: "POST",
266
- config: {
267
- params
268
- }
269
- }),
270
- invalidatesTags: (_result, _error, { collectionType, model, documentId }) => {
271
- return [
272
- {
273
- type: "Document",
274
- id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
275
- },
276
- { type: "Document", id: `${model}_LIST` },
277
- "Relations",
278
- { type: "UidAvailability", id: model },
279
- "RecentDocumentList"
280
- ];
281
- }
282
- }),
283
- /**
284
- * Gets all documents of a collection type or single type.
285
- * By passing different params you can get different results e.g. only published documents or 'es' documents.
286
- */
287
- getAllDocuments: builder.query({
288
- query: ({ model, params }) => ({
289
- url: `/content-manager/collection-types/${model}`,
290
- method: "GET",
291
- config: {
292
- params: stringify(params, { encode: true })
293
- }
294
- }),
295
- providesTags: (result, _error, arg) => {
296
- return [
297
- { type: "Document", id: `ALL_LIST` },
298
- { type: "Document", id: `${arg.model}_LIST` },
299
- ...result?.results.map(({ documentId }) => ({
300
- type: "Document",
301
- id: `${arg.model}_${documentId}`
302
- })) ?? []
303
- ];
304
- }
305
- }),
306
- getDraftRelationCount: builder.query({
307
- query: ({ collectionType, model, documentId, params }) => ({
308
- url: documentId ? `/content-manager/${collectionType}/${model}/${documentId}/actions/countDraftRelations` : `/content-manager/${collectionType}/${model}/actions/countDraftRelations`,
309
- method: "GET",
310
- config: {
311
- params
312
- }
313
- })
314
- }),
315
- getDocument: builder.query({
316
- // @ts-expect-error – TODO: fix ts error where data unknown doesn't work with response via an assertion?
317
- queryFn: async ({ collectionType, model, documentId, params }, _api, _extraOpts, baseQuery) => {
318
- const res = await baseQuery({
319
- url: `/content-manager/${collectionType}/${model}${documentId ? `/${documentId}` : ""}`,
320
- method: "GET",
321
- config: {
322
- params
323
- }
324
- });
325
- if (res.error && res.error.name === "NotFoundError" && collectionType === SINGLE_TYPES) {
326
- return { data: { document: void 0 }, error: void 0 };
327
- }
328
- return res;
329
- },
330
- providesTags: (result, _error, { collectionType, model, documentId }) => {
331
- return [
332
- // we prefer the result's id because we don't fetch single-types with an ID.
333
- {
334
- type: "Document",
335
- id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
336
- },
337
- // Make it easy to invalidate all individual documents queries for a model
338
- {
339
- type: "Document",
340
- id: `${model}_ALL_ITEMS`
341
- }
342
- ];
343
- }
344
- }),
345
- getManyDraftRelationCount: builder.query({
346
- query: ({ model, ...params }) => ({
347
- url: `/content-manager/collection-types/${model}/actions/countManyEntriesDraftRelations`,
348
- method: "GET",
349
- config: {
350
- params
351
- }
352
- }),
353
- transformResponse: (response) => response.data
354
- }),
355
- /**
356
- * This endpoint will either create or update documents at the same time as publishing.
357
- */
358
- publishDocument: builder.mutation({
359
- query: ({ collectionType, model, documentId, params, data }) => ({
360
- url: documentId ? `/content-manager/${collectionType}/${model}/${documentId}/actions/publish` : `/content-manager/${collectionType}/${model}/actions/publish`,
361
- method: "POST",
362
- data,
363
- config: {
364
- params
365
- }
366
- }),
367
- invalidatesTags: (_result, _error, { collectionType, model, documentId }) => {
368
- return [
369
- {
370
- type: "Document",
371
- id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
372
- },
373
- { type: "Document", id: `${model}_LIST` },
374
- "Relations",
375
- "RecentDocumentList"
376
- ];
377
- }
378
- }),
379
- publishManyDocuments: builder.mutation({
380
- query: ({ model, params, ...body }) => ({
381
- url: `/content-manager/collection-types/${model}/actions/bulkPublish`,
382
- method: "POST",
383
- data: body,
384
- config: {
385
- params
386
- }
387
- }),
388
- invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
389
- }),
390
- updateDocument: builder.mutation({
391
- query: ({ collectionType, model, documentId, data, params }) => ({
392
- url: `/content-manager/${collectionType}/${model}${documentId ? `/${documentId}` : ""}`,
393
- method: "PUT",
394
- data,
395
- config: {
396
- params
397
- }
398
- }),
399
- invalidatesTags: (_result, _error, { collectionType, model, documentId }) => {
400
- return [
401
- {
402
- type: "Document",
403
- id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
404
- },
405
- "Relations",
406
- { type: "UidAvailability", id: model },
407
- "RecentDocumentList",
408
- "RecentDocumentList"
409
- ];
410
- },
411
- async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
412
- const patchResult = dispatch(
413
- documentApi.util.updateQueryData("getDocument", patch, (draft) => {
414
- Object.assign(draft.data, data);
415
- })
416
- );
417
- try {
418
- await queryFulfilled;
419
- } catch {
420
- patchResult.undo();
421
- }
422
- }
423
- }),
424
- unpublishDocument: builder.mutation({
425
- query: ({ collectionType, model, documentId, params, data }) => ({
426
- url: documentId ? `/content-manager/${collectionType}/${model}/${documentId}/actions/unpublish` : `/content-manager/${collectionType}/${model}/actions/unpublish`,
427
- method: "POST",
428
- data,
429
- config: {
430
- params
431
- }
432
- }),
433
- invalidatesTags: (_result, _error, { collectionType, model, documentId }) => {
434
- return [
435
- {
436
- type: "Document",
437
- id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
438
- },
439
- "RecentDocumentList"
440
- ];
441
- }
442
- }),
443
- unpublishManyDocuments: builder.mutation({
444
- query: ({ model, params, ...body }) => ({
445
- url: `/content-manager/collection-types/${model}/actions/bulkUnpublish`,
446
- method: "POST",
447
- data: body,
448
- config: {
449
- params
450
- }
451
- }),
452
- invalidatesTags: (_res, _error, { model, documentIds }) => [
453
- ...documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` })),
454
- "RecentDocumentList"
455
- ]
456
- })
457
- })
458
- });
459
- const {
460
- useAutoCloneDocumentMutation,
461
- useCloneDocumentMutation,
462
- useCreateDocumentMutation,
463
- useDeleteDocumentMutation,
464
- useDeleteManyDocumentsMutation,
465
- useDiscardDocumentMutation,
466
- useGetAllDocumentsQuery,
467
- useLazyGetDocumentQuery,
468
- useGetDocumentQuery,
469
- useLazyGetDraftRelationCountQuery,
470
- useGetManyDraftRelationCountQuery,
471
- usePublishDocumentMutation,
472
- usePublishManyDocumentsMutation,
473
- useUpdateDocumentMutation,
474
- useUnpublishDocumentMutation,
475
- useUnpublishManyDocumentsMutation
476
- } = documentApi;
477
- const buildValidParams = (query) => {
478
- if (!query) return query;
479
- const { plugins: _, ...validQueryParams } = {
480
- ...query,
481
- ...Object.values(query?.plugins ?? {}).reduce(
482
- (acc, current) => Object.assign(acc, current),
483
- {}
484
- )
485
- };
486
- return validQueryParams;
487
- };
488
- const isBaseQueryError = (error) => {
489
- return error.name !== void 0;
490
- };
491
- const arrayValidator = (attribute, options) => ({
492
- message: translatedErrors.required,
493
- test(value) {
494
- if (options.status === "draft") {
495
- return true;
496
- }
497
- if (!attribute.required) {
498
- return true;
499
- }
500
- if (!value) {
501
- return false;
502
- }
503
- if (Array.isArray(value) && value.length === 0) {
504
- return false;
505
- }
506
- return true;
507
- }
508
- });
509
- const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
510
- const createModelSchema = (attributes2) => yup.object().shape(
511
- Object.entries(attributes2).reduce((acc, [name, attribute]) => {
512
- if (DOCUMENT_META_FIELDS.includes(name)) {
513
- return acc;
514
- }
515
- const validations = [
516
- addNullableValidation,
517
- addRequiredValidation,
518
- addMinLengthValidation,
519
- addMaxLengthValidation,
520
- addMinValidation,
521
- addMaxValidation,
522
- addRegexValidation
523
- ].map((fn) => fn(attribute, options));
524
- const transformSchema = pipe(...validations);
525
- switch (attribute.type) {
526
- case "component": {
527
- const { attributes: attributes3 } = components[attribute.component];
528
- if (attribute.repeatable) {
529
- return {
530
- ...acc,
531
- [name]: transformSchema(
532
- yup.array().of(createModelSchema(attributes3).nullable(false))
533
- ).test(arrayValidator(attribute, options))
534
- };
535
- } else {
536
- return {
537
- ...acc,
538
- [name]: transformSchema(createModelSchema(attributes3).nullable())
539
- };
540
- }
541
- }
542
- case "dynamiczone":
543
- return {
544
- ...acc,
545
- [name]: transformSchema(
546
- yup.array().of(
547
- yup.lazy(
548
- (data) => {
549
- const attributes3 = components?.[data?.__component]?.attributes;
550
- const validation = yup.object().shape({
551
- __component: yup.string().required().oneOf(Object.keys(components))
552
- }).nullable(false);
553
- if (!attributes3) {
554
- return validation;
555
- }
556
- return validation.concat(createModelSchema(attributes3));
557
- }
558
- )
559
- )
560
- ).test(arrayValidator(attribute, options))
561
- };
562
- case "relation":
563
- return {
564
- ...acc,
565
- [name]: transformSchema(
566
- yup.lazy((value) => {
567
- if (!value) {
568
- return yup.mixed().nullable(true);
569
- } else if (Array.isArray(value)) {
570
- return yup.array().of(
571
- yup.object().shape({
572
- id: yup.number().required()
573
- })
574
- );
575
- } else if (typeof value === "object") {
576
- return yup.object();
577
- } else {
578
- return yup.mixed().test(
579
- "type-error",
580
- "Relation values must be either null, an array of objects with {id} or an object.",
581
- () => false
582
- );
583
- }
584
- })
585
- )
586
- };
587
- default:
588
- return {
589
- ...acc,
590
- [name]: transformSchema(createAttributeSchema(attribute))
591
- };
592
- }
593
- }, {})
594
- ).default(null);
595
- return createModelSchema(attributes);
596
- };
597
- const createAttributeSchema = (attribute) => {
598
- switch (attribute.type) {
599
- case "biginteger":
600
- return yup.string().matches(/^-?\d*$/);
601
- case "boolean":
602
- return yup.boolean();
603
- case "blocks":
604
- return yup.mixed().test("isBlocks", translatedErrors.json, (value) => {
605
- if (!value || Array.isArray(value)) {
606
- return true;
607
- } else {
608
- return false;
609
- }
610
- });
611
- case "decimal":
612
- case "float":
613
- case "integer":
614
- return yup.number();
615
- case "email":
616
- return yup.string().email(translatedErrors.email);
617
- case "enumeration":
618
- return yup.string().oneOf([...attribute.enum, null]);
619
- case "json":
620
- return yup.mixed().test("isJSON", translatedErrors.json, (value) => {
621
- if (!value || typeof value === "string" && value.length === 0) {
622
- return true;
623
- }
624
- if (typeof value === "object") {
625
- try {
626
- JSON.stringify(value);
627
- return true;
628
- } catch (err) {
629
- return false;
630
- }
631
- }
632
- try {
633
- JSON.parse(value);
634
- return true;
635
- } catch (err) {
636
- return false;
637
- }
638
- });
639
- case "password":
640
- case "richtext":
641
- case "string":
642
- case "text":
643
- return yup.string();
644
- case "uid":
645
- return yup.string().matches(/^[A-Za-z0-9-_.~]*$/);
646
- default:
647
- return yup.mixed();
648
- }
649
- };
650
- const nullableSchema = (schema) => {
651
- return schema?.nullable ? schema.nullable() : (
652
- // In some cases '.nullable' will not be available on the schema.
653
- // e.g. when the schema has been built using yup.lazy (e.g. for relations).
654
- // In these cases we should just return the schema as it is.
655
- schema
656
- );
657
- };
658
- const addNullableValidation = () => (schema) => {
659
- return nullableSchema(schema);
660
- };
661
- const addRequiredValidation = (attribute, options) => (schema) => {
662
- if (options.status === "draft" || !attribute.required) {
663
- return schema;
664
- }
665
- if (attribute.required && "required" in schema) {
666
- return schema.required(translatedErrors.required);
667
- }
668
- return schema;
669
- };
670
- const addMinLengthValidation = (attribute, options) => (schema) => {
671
- if (options.status === "draft") {
672
- return schema;
673
- }
674
- if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
675
- return schema.min(attribute.minLength, {
676
- ...translatedErrors.minLength,
677
- values: {
678
- min: attribute.minLength
679
- }
680
- });
681
- }
682
- return schema;
683
- };
684
- const addMaxLengthValidation = (attribute) => (schema) => {
685
- if ("maxLength" in attribute && attribute.maxLength && Number.isInteger(attribute.maxLength) && "max" in schema) {
686
- return schema.max(attribute.maxLength, {
687
- ...translatedErrors.maxLength,
688
- values: {
689
- max: attribute.maxLength
690
- }
691
- });
692
- }
693
- return schema;
694
- };
695
- const addMinValidation = (attribute, options) => (schema) => {
696
- if (options.status === "draft") {
697
- return schema;
698
- }
699
- if ("min" in attribute && "min" in schema) {
700
- const min = toInteger(attribute.min);
701
- if (min) {
702
- return schema.min(min, {
703
- ...translatedErrors.min,
704
- values: {
705
- min
706
- }
707
- });
708
- }
709
- }
710
- return schema;
711
- };
712
- const addMaxValidation = (attribute) => (schema) => {
713
- if ("max" in attribute) {
714
- const max = toInteger(attribute.max);
715
- if ("max" in schema && max) {
716
- return schema.max(max, {
717
- ...translatedErrors.max,
718
- values: {
719
- max
720
- }
721
- });
722
- }
723
- }
724
- return schema;
725
- };
726
- const toInteger = (val) => {
727
- if (typeof val === "number" || val === void 0) {
728
- return val;
729
- } else {
730
- const num = Number(val);
731
- return isNaN(num) ? void 0 : num;
732
- }
733
- };
734
- const addRegexValidation = (attribute) => (schema) => {
735
- if ("regex" in attribute && attribute.regex && "matches" in schema) {
736
- return schema.matches(new RegExp(attribute.regex), {
737
- message: {
738
- id: translatedErrors.regex.id,
739
- defaultMessage: "The value does not match the defined pattern."
740
- },
741
- excludeEmptyString: !attribute.required
742
- });
743
- }
744
- return schema;
745
- };
746
- const initApi = contentManagerApi.injectEndpoints({
747
- endpoints: (builder) => ({
748
- getInitialData: builder.query({
749
- query: () => "/content-manager/init",
750
- transformResponse: (response) => response.data,
751
- providesTags: ["InitialData"]
752
- })
753
- })
754
- });
755
- const { useGetInitialDataQuery } = initApi;
756
- const useContentTypeSchema = (model) => {
757
- const { toggleNotification } = useNotification();
758
- const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
759
- const { data, error, isLoading, isFetching } = useGetInitialDataQuery(void 0);
760
- const { components, contentType, contentTypes } = React.useMemo(() => {
761
- const contentType2 = data?.contentTypes.find((ct) => ct.uid === model);
762
- const componentsByKey = data?.components.reduce((acc, component) => {
763
- acc[component.uid] = component;
764
- return acc;
765
- }, {});
766
- const components2 = extractContentTypeComponents(contentType2?.attributes, componentsByKey);
767
- return {
768
- components: Object.keys(components2).length === 0 ? void 0 : components2,
769
- contentType: contentType2,
770
- contentTypes: data?.contentTypes ?? []
771
- };
772
- }, [model, data]);
773
- React.useEffect(() => {
774
- if (error) {
775
- toggleNotification({
776
- type: "danger",
777
- message: formatAPIError(error)
778
- });
779
- }
780
- }, [toggleNotification, error, formatAPIError]);
781
- return {
782
- // This must be memoized to avoid inifiinite re-renders where the empty object is different everytime.
783
- components: React.useMemo(() => components ?? {}, [components]),
784
- schema: contentType,
785
- schemas: contentTypes,
786
- isLoading: isLoading || isFetching
787
- };
788
- };
789
- const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
790
- const getComponents = (attributes2) => {
791
- return attributes2.reduce((acc, attribute) => {
792
- if (attribute.type === "component") {
793
- const componentAttributes = Object.values(
794
- allComponents[attribute.component]?.attributes ?? {}
795
- );
796
- acc.push(attribute.component, ...getComponents(componentAttributes));
797
- } else if (attribute.type === "dynamiczone") {
798
- acc.push(
799
- ...attribute.components,
800
- ...attribute.components.flatMap((componentUid) => {
801
- const componentAttributes = Object.values(
802
- allComponents[componentUid]?.attributes ?? {}
803
- );
804
- return getComponents(componentAttributes);
805
- })
806
- );
807
- }
808
- return acc;
809
- }, []);
810
- };
811
- const componentUids = getComponents(Object.values(attributes));
812
- const uniqueComponentUids = [...new Set(componentUids)];
813
- const componentsByKey = uniqueComponentUids.reduce((acc, uid) => {
814
- acc[uid] = allComponents[uid];
815
- return acc;
816
- }, {});
817
- return componentsByKey;
818
- };
819
- const HOOKS = {
820
- /**
821
- * Hook that allows to mutate the displayed headers of the list view table
822
- * @constant
823
- * @type {string}
824
- */
825
- INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
826
- /**
827
- * Hook that allows to mutate the CM's collection types links pre-set filters
828
- * @constant
829
- * @type {string}
830
- */
831
- MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
832
- /**
833
- * Hook that allows to mutate the CM's edit view layout
834
- * @constant
835
- * @type {string}
836
- */
837
- MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
838
- /**
839
- * Hook that allows to mutate the CM's single types links pre-set filters
840
- * @constant
841
- * @type {string}
842
- */
843
- MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
844
- };
845
- const contentTypesApi = contentManagerApi.injectEndpoints({
846
- endpoints: (builder) => ({
847
- getContentTypeConfiguration: builder.query({
848
- query: (uid) => ({
849
- url: `/content-manager/content-types/${uid}/configuration`,
850
- method: "GET"
851
- }),
852
- transformResponse: (response) => response.data,
853
- providesTags: (_result, _error, uid) => [
854
- { type: "ContentTypesConfiguration", id: uid },
855
- { type: "ContentTypeSettings", id: "LIST" }
856
- ]
857
- }),
858
- getAllContentTypeSettings: builder.query({
859
- query: () => "/content-manager/content-types-settings",
860
- transformResponse: (response) => response.data,
861
- providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
862
- }),
863
- updateContentTypeConfiguration: builder.mutation({
864
- query: ({ uid, ...body }) => ({
865
- url: `/content-manager/content-types/${uid}/configuration`,
866
- method: "PUT",
867
- data: body
868
- }),
869
- transformResponse: (response) => response.data,
870
- invalidatesTags: (_result, _error, { uid }) => [
871
- { type: "ContentTypesConfiguration", id: uid },
872
- { type: "ContentTypeSettings", id: "LIST" },
873
- // Is this necessary?
874
- { type: "InitialData" }
875
- ]
876
- })
877
- })
878
- });
879
- const {
880
- useGetContentTypeConfigurationQuery,
881
- useGetAllContentTypeSettingsQuery,
882
- useUpdateContentTypeConfigurationMutation
883
- } = contentTypesApi;
884
- const checkIfAttributeIsDisplayable = (attribute) => {
885
- const { type } = attribute;
886
- if (type === "relation") {
887
- return !attribute.relation.toLowerCase().includes("morph");
888
- }
889
- return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
890
- };
891
- const getMainField = (attribute, mainFieldName, { schemas, components }) => {
892
- if (!mainFieldName) {
893
- return void 0;
894
- }
895
- const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
896
- // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
897
- schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
898
- );
899
- return {
900
- name: mainFieldName,
901
- type: mainFieldType ?? "string"
902
- };
903
- };
904
- const DEFAULT_SETTINGS = {
905
- bulkable: false,
906
- filterable: false,
907
- searchable: false,
908
- pagination: false,
909
- defaultSortBy: "",
910
- defaultSortOrder: "asc",
911
- mainField: "id",
912
- pageSize: 10
913
- };
914
- const useDocumentLayout = (model) => {
915
- const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
916
- const [{ query }] = useQueryParams();
917
- const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
918
- const { toggleNotification } = useNotification();
919
- const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
920
- const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
921
- const {
922
- data,
923
- isLoading: isLoadingConfigs,
924
- error,
925
- isFetching: isFetchingConfigs
926
- } = useGetContentTypeConfigurationQuery(model);
927
- const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
928
- React.useEffect(() => {
929
- if (error) {
930
- toggleNotification({
931
- type: "danger",
932
- message: formatAPIError(error)
933
- });
934
- }
935
- }, [error, formatAPIError, toggleNotification]);
936
- const editLayout = React.useMemo(
937
- () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
938
- layout: [],
939
- components: {},
940
- metadatas: {},
941
- options: {},
942
- settings: DEFAULT_SETTINGS
943
- },
944
- [data, isLoading, schemas, schema, components]
945
- );
946
- const listLayout = React.useMemo(() => {
947
- return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
948
- layout: [],
949
- metadatas: {},
950
- options: {},
951
- settings: DEFAULT_SETTINGS
952
- };
953
- }, [data, isLoading, schemas, schema, components]);
954
- const { layout: edit } = React.useMemo(
955
- () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
956
- layout: editLayout,
957
- query
958
- }),
959
- [editLayout, query, runHookWaterfall]
960
- );
961
- return {
962
- error,
963
- isLoading,
964
- edit,
965
- list: listLayout
966
- };
967
- };
968
- const useDocLayout = () => {
969
- const { model } = useDoc();
970
- return useDocumentLayout(model);
971
- };
972
- const formatEditLayout = (data, {
973
- schemas,
974
- schema,
975
- components
976
- }) => {
977
- let currentPanelIndex = 0;
978
- const panelledEditAttributes = convertEditLayoutToFieldLayouts(
979
- data.contentType.layouts.edit,
980
- schema?.attributes,
981
- data.contentType.metadatas,
982
- { configurations: data.components, schemas: components },
983
- schemas
984
- ).reduce((panels, row) => {
985
- if (row.some((field) => field.type === "dynamiczone")) {
986
- panels.push([row]);
987
- currentPanelIndex += 2;
988
- } else {
989
- if (!panels[currentPanelIndex]) {
990
- panels.push([row]);
991
- } else {
992
- panels[currentPanelIndex].push(row);
993
- }
994
- }
995
- return panels;
996
- }, []);
997
- const componentEditAttributes = Object.entries(data.components).reduce(
998
- (acc, [uid, configuration]) => {
999
- acc[uid] = {
1000
- layout: convertEditLayoutToFieldLayouts(
1001
- configuration.layouts.edit,
1002
- components[uid].attributes,
1003
- configuration.metadatas,
1004
- { configurations: data.components, schemas: components }
1005
- ),
1006
- settings: {
1007
- ...configuration.settings,
1008
- icon: components[uid].info.icon,
1009
- displayName: components[uid].info.displayName
1010
- }
1011
- };
1012
- return acc;
1013
- },
1014
- {}
1015
- );
1016
- const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
1017
- (acc, [attribute, metadata]) => {
1018
- return {
1019
- ...acc,
1020
- [attribute]: metadata.edit
1021
- };
1022
- },
1023
- {}
1024
- );
1025
- return {
1026
- layout: panelledEditAttributes,
1027
- components: componentEditAttributes,
1028
- metadatas: editMetadatas,
1029
- settings: {
1030
- ...data.contentType.settings,
1031
- displayName: schema?.info.displayName
1032
- },
1033
- options: {
1034
- ...schema?.options,
1035
- ...schema?.pluginOptions,
1036
- ...data.contentType.options
1037
- }
1038
- };
1039
- };
1040
- const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
1041
- return rows.map(
1042
- (row) => row.map((field) => {
1043
- const attribute = attributes[field.name];
1044
- if (!attribute) {
1045
- return null;
1046
- }
1047
- const { edit: metadata } = metadatas[field.name];
1048
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1049
- return {
1050
- attribute,
1051
- disabled: !metadata.editable,
1052
- hint: metadata.description,
1053
- label: metadata.label ?? "",
1054
- name: field.name,
1055
- // @ts-expect-error – mainField does exist on the metadata for a relation.
1056
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1057
- schemas,
1058
- components: components?.schemas ?? {}
1059
- }),
1060
- placeholder: metadata.placeholder ?? "",
1061
- required: attribute.required ?? false,
1062
- size: field.size,
1063
- unique: "unique" in attribute ? attribute.unique : false,
1064
- visible: metadata.visible ?? true,
1065
- type: attribute.type
1066
- };
1067
- }).filter((field) => field !== null)
1068
- );
1069
- };
1070
- const formatListLayout = (data, {
1071
- schemas,
1072
- schema,
1073
- components
1074
- }) => {
1075
- const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
1076
- (acc, [attribute, metadata]) => {
1077
- return {
1078
- ...acc,
1079
- [attribute]: metadata.list
1080
- };
1081
- },
1082
- {}
1083
- );
1084
- const listAttributes = convertListLayoutToFieldLayouts(
1085
- data.contentType.layouts.list,
1086
- schema?.attributes,
1087
- listMetadatas,
1088
- { configurations: data.components, schemas: components },
1089
- schemas
1090
- );
1091
- return {
1092
- layout: listAttributes,
1093
- settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
1094
- metadatas: listMetadatas,
1095
- options: {
1096
- ...schema?.options,
1097
- ...schema?.pluginOptions,
1098
- ...data.contentType.options
1099
- }
1100
- };
1101
- };
1102
- const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
1103
- return columns.map((name) => {
1104
- const attribute = attributes[name];
1105
- if (!attribute) {
1106
- return null;
1107
- }
1108
- const metadata = metadatas[name];
1109
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1110
- return {
1111
- attribute,
1112
- label: metadata.label ?? "",
1113
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1114
- schemas,
1115
- components: components?.schemas ?? {}
1116
- }),
1117
- name,
1118
- searchable: metadata.searchable ?? true,
1119
- sortable: metadata.sortable ?? true
1120
- };
1121
- }).filter((field) => field !== null);
1122
- };
1123
- const useDocument = (args, opts) => {
1124
- const { toggleNotification } = useNotification();
1125
- const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
1126
- const {
1127
- currentData: data,
1128
- isLoading: isLoadingDocument,
1129
- isFetching: isFetchingDocument,
1130
- error
1131
- } = useGetDocumentQuery(args, {
1132
- ...opts,
1133
- skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
1134
- });
1135
- const {
1136
- components,
1137
- schema,
1138
- schemas,
1139
- isLoading: isLoadingSchema
1140
- } = useContentTypeSchema(args.model);
1141
- React.useEffect(() => {
1142
- if (error) {
1143
- toggleNotification({
1144
- type: "danger",
1145
- message: formatAPIError(error)
1146
- });
1147
- }
1148
- }, [toggleNotification, error, formatAPIError, args.collectionType]);
1149
- const validationSchema = React.useMemo(() => {
1150
- if (!schema) {
1151
- return null;
1152
- }
1153
- return createYupSchema(schema.attributes, components);
1154
- }, [schema, components]);
1155
- const validate = React.useCallback(
1156
- (document) => {
1157
- if (!validationSchema) {
1158
- throw new Error(
1159
- "There is no validation schema generated, this is likely due to the schema not being loaded yet."
1160
- );
1161
- }
1162
- try {
1163
- validationSchema.validateSync(document, { abortEarly: false, strict: true });
1164
- return null;
1165
- } catch (error2) {
1166
- if (error2 instanceof ValidationError) {
1167
- return getYupValidationErrors(error2);
1168
- }
1169
- throw error2;
1170
- }
1171
- },
1172
- [validationSchema]
1173
- );
1174
- const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
1175
- const hasError = !!error;
1176
- return {
1177
- components,
1178
- document: data?.data,
1179
- meta: data?.meta,
1180
- isLoading,
1181
- hasError,
1182
- schema,
1183
- schemas,
1184
- validate
1185
- };
1186
- };
1187
- const useDoc = () => {
1188
- const { id, slug, collectionType, origin } = useParams();
1189
- const [{ query }] = useQueryParams();
1190
- const params = React.useMemo(() => buildValidParams(query), [query]);
1191
- if (!collectionType) {
1192
- throw new Error("Could not find collectionType in url params");
1193
- }
1194
- if (!slug) {
1195
- throw new Error("Could not find model in url params");
1196
- }
1197
- const document = useDocument(
1198
- { documentId: origin || id, model: slug, collectionType, params },
1199
- {
1200
- skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
1201
- }
1202
- );
1203
- const returnId = origin || id === "create" ? void 0 : id;
1204
- return {
1205
- collectionType,
1206
- model: slug,
1207
- id: returnId,
1208
- ...document
1209
- };
1210
- };
1211
- const useContentManagerContext = () => {
1212
- const {
1213
- collectionType,
1214
- model,
1215
- id,
1216
- components,
1217
- isLoading: isLoadingDoc,
1218
- schema,
1219
- schemas
1220
- } = useDoc();
1221
- const layout = useDocumentLayout(model);
1222
- const form = useForm("useContentManagerContext", (state) => state);
1223
- const isSingleType = collectionType === SINGLE_TYPES;
1224
- const slug = model;
1225
- const isCreatingEntry = id === "create";
1226
- useContentTypeSchema();
1227
- const isLoading = isLoadingDoc || layout.isLoading;
1228
- const error = layout.error;
1229
- return {
1230
- error,
1231
- isLoading,
1232
- // Base metadata
1233
- model,
1234
- collectionType,
1235
- id,
1236
- slug,
1237
- isCreatingEntry,
1238
- isSingleType,
1239
- hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
1240
- // All schema infos
1241
- components,
1242
- contentType: schema,
1243
- contentTypes: schemas,
1244
- // Form state
1245
- form,
1246
- // layout infos
1247
- layout
1248
- };
1249
- };
1250
- const prefixPluginTranslations = (trad, pluginId) => {
1251
- return Object.keys(trad).reduce((acc, current) => {
1252
- acc[`${pluginId}.${current}`] = trad[current];
1253
- return acc;
1254
- }, {});
1255
- };
1256
- const getTranslation = (id) => `content-manager.${id}`;
1257
- const DEFAULT_UNEXPECTED_ERROR_MSG = {
1258
- id: "notification.error",
1259
- defaultMessage: "An error occurred, please try again"
1260
- };
1261
- const useDocumentActions = () => {
1262
- const { toggleNotification } = useNotification();
1263
- const { formatMessage } = useIntl();
1264
- const { trackUsage } = useTracking();
1265
- const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
1266
- const navigate = useNavigate();
1267
- const setCurrentStep = useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
1268
- const [deleteDocument] = useDeleteDocumentMutation();
1269
- const _delete = React.useCallback(
1270
- async ({ collectionType, model, documentId, params }, trackerProperty) => {
1271
- try {
1272
- trackUsage("willDeleteEntry", trackerProperty);
1273
- const res = await deleteDocument({
1274
- collectionType,
1275
- model,
1276
- documentId,
1277
- params
1278
- });
1279
- if ("error" in res) {
1280
- toggleNotification({
1281
- type: "danger",
1282
- message: formatAPIError(res.error)
1283
- });
1284
- return { error: res.error };
1285
- }
1286
- toggleNotification({
1287
- type: "success",
1288
- message: formatMessage({
1289
- id: getTranslation("success.record.delete"),
1290
- defaultMessage: "Deleted document"
1291
- })
1292
- });
1293
- trackUsage("didDeleteEntry", trackerProperty);
1294
- return res.data;
1295
- } catch (err) {
1296
- toggleNotification({
1297
- type: "danger",
1298
- message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1299
- });
1300
- trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
1301
- throw err;
1302
- }
1303
- },
1304
- [trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
1305
- );
1306
- const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
1307
- const deleteMany = React.useCallback(
1308
- async ({ model, documentIds, params }) => {
1309
- try {
1310
- trackUsage("willBulkDeleteEntries");
1311
- const res = await deleteManyDocuments({
1312
- model,
1313
- documentIds,
1314
- params
1315
- });
1316
- if ("error" in res) {
1317
- toggleNotification({
1318
- type: "danger",
1319
- message: formatAPIError(res.error)
1320
- });
1321
- return { error: res.error };
1322
- }
1323
- toggleNotification({
1324
- type: "success",
1325
- title: formatMessage({
1326
- id: getTranslation("success.records.delete"),
1327
- defaultMessage: "Successfully deleted."
1328
- }),
1329
- message: ""
1330
- });
1331
- trackUsage("didBulkDeleteEntries");
1332
- return res.data;
1333
- } catch (err) {
1334
- toggleNotification({
1335
- type: "danger",
1336
- message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1337
- });
1338
- trackUsage("didNotBulkDeleteEntries");
1339
- throw err;
1340
- }
1341
- },
1342
- [trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
1343
- );
1344
- const [discardDocument] = useDiscardDocumentMutation();
1345
- const discard = React.useCallback(
1346
- async ({ collectionType, model, documentId, params }) => {
1347
- try {
1348
- const res = await discardDocument({
1349
- collectionType,
1350
- model,
1351
- documentId,
1352
- params
1353
- });
1354
- if ("error" in res) {
1355
- toggleNotification({
1356
- type: "danger",
1357
- message: formatAPIError(res.error)
1358
- });
1359
- return { error: res.error };
1360
- }
1361
- toggleNotification({
1362
- type: "success",
1363
- message: formatMessage({
1364
- id: "content-manager.success.record.discard",
1365
- defaultMessage: "Changes discarded"
1366
- })
1367
- });
1368
- return res.data;
1369
- } catch (err) {
1370
- toggleNotification({
1371
- type: "danger",
1372
- message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1373
- });
1374
- throw err;
1375
- }
1376
- },
1377
- [discardDocument, formatAPIError, formatMessage, toggleNotification]
1378
- );
1379
- const [publishDocument] = usePublishDocumentMutation();
1380
- const publish = React.useCallback(
1381
- async ({ collectionType, model, documentId, params }, data) => {
1382
- try {
1383
- trackUsage("willPublishEntry");
1384
- const res = await publishDocument({
1385
- collectionType,
1386
- model,
1387
- documentId,
1388
- data,
1389
- params
1390
- });
1391
- if ("error" in res) {
1392
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1393
- return { error: res.error };
1394
- }
1395
- trackUsage("didPublishEntry");
1396
- toggleNotification({
1397
- type: "success",
1398
- message: formatMessage({
1399
- id: getTranslation("success.record.publish"),
1400
- defaultMessage: "Published document"
1401
- })
1402
- });
1403
- return res.data;
1404
- } catch (err) {
1405
- toggleNotification({
1406
- type: "danger",
1407
- message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1408
- });
1409
- throw err;
1410
- }
1411
- },
1412
- [trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
1413
- );
1414
- const [publishManyDocuments] = usePublishManyDocumentsMutation();
1415
- const publishMany = React.useCallback(
1416
- async ({ model, documentIds, params }) => {
1417
- try {
1418
- const res = await publishManyDocuments({
1419
- model,
1420
- documentIds,
1421
- params
1422
- });
1423
- if ("error" in res) {
1424
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1425
- return { error: res.error };
1426
- }
1427
- toggleNotification({
1428
- type: "success",
1429
- message: formatMessage({
1430
- id: getTranslation("success.record.publish"),
1431
- defaultMessage: "Published document"
1432
- })
1433
- });
1434
- return res.data;
1435
- } catch (err) {
1436
- toggleNotification({
1437
- type: "danger",
1438
- message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1439
- });
1440
- throw err;
1441
- }
1442
- },
1443
- [
1444
- // trackUsage,
1445
- publishManyDocuments,
1446
- toggleNotification,
1447
- formatMessage,
1448
- formatAPIError
1449
- ]
1450
- );
1451
- const [updateDocument] = useUpdateDocumentMutation();
1452
- const update = React.useCallback(
1453
- async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
1454
- try {
1455
- trackUsage("willEditEntry", trackerProperty);
1456
- const res = await updateDocument({
1457
- collectionType,
1458
- model,
1459
- documentId,
1460
- data,
1461
- params
1462
- });
1463
- if ("error" in res) {
1464
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1465
- trackUsage("didNotEditEntry", { error: res.error, ...trackerProperty });
1466
- return { error: res.error };
1467
- }
1468
- trackUsage("didEditEntry", trackerProperty);
1469
- toggleNotification({
1470
- type: "success",
1471
- message: formatMessage({
1472
- id: getTranslation("success.record.save"),
1473
- defaultMessage: "Saved document"
1474
- })
1475
- });
1476
- return res.data;
1477
- } catch (err) {
1478
- trackUsage("didNotEditEntry", { error: err, ...trackerProperty });
1479
- toggleNotification({
1480
- type: "danger",
1481
- message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1482
- });
1483
- throw err;
1484
- }
1485
- },
1486
- [trackUsage, updateDocument, toggleNotification, formatMessage, formatAPIError]
1487
- );
1488
- const [unpublishDocument] = useUnpublishDocumentMutation();
1489
- const unpublish = React.useCallback(
1490
- async ({ collectionType, model, documentId, params }, discardDraft = false) => {
1491
- try {
1492
- trackUsage("willUnpublishEntry");
1493
- const res = await unpublishDocument({
1494
- collectionType,
1495
- model,
1496
- documentId,
1497
- params,
1498
- data: {
1499
- discardDraft
1500
- }
1501
- });
1502
- if ("error" in res) {
1503
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1504
- return { error: res.error };
1505
- }
1506
- trackUsage("didUnpublishEntry");
1507
- toggleNotification({
1508
- type: "success",
1509
- message: formatMessage({
1510
- id: getTranslation("success.record.unpublish"),
1511
- defaultMessage: "Unpublished document"
1512
- })
1513
- });
1514
- return res.data;
1515
- } catch (err) {
1516
- toggleNotification({
1517
- type: "danger",
1518
- message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1519
- });
1520
- throw err;
1521
- }
1522
- },
1523
- [trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
1524
- );
1525
- const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
1526
- const unpublishMany = React.useCallback(
1527
- async ({ model, documentIds, params }) => {
1528
- try {
1529
- trackUsage("willBulkUnpublishEntries");
1530
- const res = await unpublishManyDocuments({
1531
- model,
1532
- documentIds,
1533
- params
1534
- });
1535
- if ("error" in res) {
1536
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1537
- return { error: res.error };
1538
- }
1539
- trackUsage("didBulkUnpublishEntries");
1540
- toggleNotification({
1541
- type: "success",
1542
- title: formatMessage({
1543
- id: getTranslation("success.records.unpublish"),
1544
- defaultMessage: "Successfully unpublished."
1545
- }),
1546
- message: ""
1547
- });
1548
- return res.data;
1549
- } catch (err) {
1550
- toggleNotification({
1551
- type: "danger",
1552
- message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1553
- });
1554
- trackUsage("didNotBulkUnpublishEntries");
1555
- throw err;
1556
- }
1557
- },
1558
- [trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
1559
- );
1560
- const [createDocument] = useCreateDocumentMutation();
1561
- const create = React.useCallback(
1562
- async ({ model, params }, data, trackerProperty) => {
1563
- try {
1564
- const res = await createDocument({
1565
- model,
1566
- data,
1567
- params
1568
- });
1569
- if ("error" in res) {
1570
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1571
- trackUsage("didNotCreateEntry", { error: res.error, ...trackerProperty });
1572
- return { error: res.error };
1573
- }
1574
- trackUsage("didCreateEntry", trackerProperty);
1575
- toggleNotification({
1576
- type: "success",
1577
- message: formatMessage({
1578
- id: getTranslation("success.record.save"),
1579
- defaultMessage: "Saved document"
1580
- })
1581
- });
1582
- setCurrentStep("contentManager.success");
1583
- return res.data;
1584
- } catch (err) {
1585
- toggleNotification({
1586
- type: "danger",
1587
- message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1588
- });
1589
- trackUsage("didNotCreateEntry", { error: err, ...trackerProperty });
1590
- throw err;
1591
- }
1592
- },
1593
- [createDocument, formatAPIError, formatMessage, toggleNotification, trackUsage]
1594
- );
1595
- const [autoCloneDocument] = useAutoCloneDocumentMutation();
1596
- const autoClone = React.useCallback(
1597
- async ({ model, sourceId }) => {
1598
- try {
1599
- const res = await autoCloneDocument({
1600
- model,
1601
- sourceId
1602
- });
1603
- if ("error" in res) {
1604
- return { error: res.error };
1605
- }
1606
- toggleNotification({
1607
- type: "success",
1608
- message: formatMessage({
1609
- id: getTranslation("success.record.clone"),
1610
- defaultMessage: "Cloned document"
1611
- })
1612
- });
1613
- return res.data;
1614
- } catch (err) {
1615
- toggleNotification({
1616
- type: "danger",
1617
- message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1618
- });
1619
- throw err;
1620
- }
1621
- },
1622
- [autoCloneDocument, formatMessage, toggleNotification]
1623
- );
1624
- const [cloneDocument] = useCloneDocumentMutation();
1625
- const clone = React.useCallback(
1626
- async ({ model, documentId, params }, body, trackerProperty) => {
1627
- try {
1628
- const { id: _id, ...restBody } = body;
1629
- const res = await cloneDocument({
1630
- model,
1631
- sourceId: documentId,
1632
- data: restBody,
1633
- params
1634
- });
1635
- if ("error" in res) {
1636
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1637
- trackUsage("didNotCreateEntry", { error: res.error, ...trackerProperty });
1638
- return { error: res.error };
1639
- }
1640
- trackUsage("didCreateEntry", trackerProperty);
1641
- toggleNotification({
1642
- type: "success",
1643
- message: formatMessage({
1644
- id: getTranslation("success.record.clone"),
1645
- defaultMessage: "Cloned document"
1646
- })
1647
- });
1648
- navigate(`../../${res.data.data.documentId}`, { relative: "path" });
1649
- return res.data;
1650
- } catch (err) {
1651
- toggleNotification({
1652
- type: "danger",
1653
- message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1654
- });
1655
- trackUsage("didNotCreateEntry", { error: err, ...trackerProperty });
1656
- throw err;
1657
- }
1658
- },
1659
- [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
1660
- );
1661
- const [getDoc] = useLazyGetDocumentQuery();
1662
- const getDocument = React.useCallback(
1663
- async (args) => {
1664
- const { data } = await getDoc(args);
1665
- return data;
1666
- },
1667
- [getDoc]
1668
- );
1669
- return {
1670
- autoClone,
1671
- clone,
1672
- create,
1673
- delete: _delete,
1674
- deleteMany,
1675
- discard,
1676
- getDocument,
1677
- publish,
1678
- publishMany,
1679
- unpublish,
1680
- unpublishMany,
1681
- update
1682
- };
1683
- };
1684
- const ProtectedHistoryPage = React.lazy(
1685
- () => import("./History-Bk2VCzmJ.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
1686
- );
1687
- const routes$2 = [
1688
- {
1689
- path: ":collectionType/:slug/:id/history",
1690
- Component: ProtectedHistoryPage
1691
- },
1692
- {
1693
- path: ":collectionType/:slug/history",
1694
- Component: ProtectedHistoryPage
1695
- }
1696
- ];
1697
- const ProtectedPreviewPage = React.lazy(
1698
- () => import("./Preview-Dd3kQluA.mjs").then((mod) => ({ default: mod.ProtectedPreviewPage }))
1699
- );
1700
- const routes$1 = [
1701
- {
1702
- path: ":collectionType/:slug/:id/preview",
1703
- Component: ProtectedPreviewPage
1704
- },
1705
- {
1706
- path: ":collectionType/:slug/preview",
1707
- Component: ProtectedPreviewPage
1708
- }
1709
- ];
1710
- const ProtectedEditViewPage = lazy(
1711
- () => import("./EditViewPage-ONky_-8U.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
1712
- );
1713
- const ProtectedListViewPage = lazy(
1714
- () => import("./ListViewPage-mK-sFVGU.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
1715
- );
1716
- const ProtectedListConfiguration = lazy(
1717
- () => import("./ListConfigurationPage-BhNCzkQd.mjs").then((mod) => ({
1718
- default: mod.ProtectedListConfiguration
1719
- }))
1720
- );
1721
- const ProtectedEditConfigurationPage = lazy(
1722
- () => import("./EditConfigurationPage-DN6yaDFZ.mjs").then((mod) => ({
1723
- default: mod.ProtectedEditConfigurationPage
1724
- }))
1725
- );
1726
- const ProtectedComponentConfigurationPage = lazy(
1727
- () => import("./ComponentConfigurationPage-A5f-t42A.mjs").then((mod) => ({
1728
- default: mod.ProtectedComponentConfigurationPage
1729
- }))
1730
- );
1731
- const NoPermissions = lazy(
1732
- () => import("./NoPermissionsPage-zpYME1_X.mjs").then((mod) => ({ default: mod.NoPermissions }))
1733
- );
1734
- const NoContentType = lazy(
1735
- () => import("./NoContentTypePage-BSVg7nZI.mjs").then((mod) => ({ default: mod.NoContentType }))
1736
- );
1737
- const CollectionTypePages = () => {
1738
- const { collectionType } = useParams();
1739
- if (collectionType !== COLLECTION_TYPES && collectionType !== SINGLE_TYPES) {
1740
- return /* @__PURE__ */ jsx(Navigate, { to: "/404" });
1741
- }
1742
- return collectionType === COLLECTION_TYPES ? /* @__PURE__ */ jsx(ProtectedListViewPage, {}) : /* @__PURE__ */ jsx(ProtectedEditViewPage, {});
1743
- };
1744
- const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
1745
- const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
1746
- const LIST_RELATIVE_PATH = ":collectionType/:slug";
1747
- const LIST_PATH = `/content-manager/collection-types/:slug`;
1748
- const routes = [
1749
- {
1750
- path: LIST_RELATIVE_PATH,
1751
- element: /* @__PURE__ */ jsx(CollectionTypePages, {})
1752
- },
1753
- {
1754
- path: ":collectionType/:slug/:id",
1755
- Component: ProtectedEditViewPage
1756
- },
1757
- {
1758
- path: CLONE_RELATIVE_PATH,
1759
- Component: ProtectedEditViewPage
1760
- },
1761
- {
1762
- path: ":collectionType/:slug/configurations/list",
1763
- Component: ProtectedListConfiguration
1764
- },
1765
- {
1766
- path: "components/:slug/configurations/edit",
1767
- Component: ProtectedComponentConfigurationPage
1768
- },
1769
- {
1770
- path: ":collectionType/:slug/configurations/edit",
1771
- Component: ProtectedEditConfigurationPage
1772
- },
1773
- {
1774
- path: "403",
1775
- Component: NoPermissions
1776
- },
1777
- {
1778
- path: "no-content-types",
1779
- Component: NoContentType
1780
- },
1781
- ...routes$2,
1782
- ...routes$1
1783
- ];
1784
- const DocumentActions = ({ actions: actions2 }) => {
1785
- const { formatMessage } = useIntl();
1786
- const [primaryAction, secondaryAction, ...restActions] = actions2.filter((action) => {
1787
- if (action.position === void 0) {
1788
- return true;
1789
- }
1790
- const positions = Array.isArray(action.position) ? action.position : [action.position];
1791
- return positions.includes("panel");
1792
- });
1793
- if (!primaryAction) {
1794
- return null;
1795
- }
1796
- return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, alignItems: "stretch", width: "100%", children: [
1797
- /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
1798
- /* @__PURE__ */ jsx(DocumentActionButton, { ...primaryAction, variant: primaryAction.variant || "default" }),
1799
- restActions.length > 0 ? /* @__PURE__ */ jsx(
1800
- DocumentActionsMenu,
1801
- {
1802
- actions: restActions,
1803
- label: formatMessage({
1804
- id: "content-manager.containers.edit.panels.default.more-actions",
1805
- defaultMessage: "More document actions"
1806
- })
1807
- }
1808
- ) : null
1809
- ] }),
1810
- secondaryAction ? /* @__PURE__ */ jsx(
1811
- DocumentActionButton,
1812
- {
1813
- ...secondaryAction,
1814
- variant: secondaryAction.variant || "secondary"
1815
- }
1816
- ) : null
1817
- ] });
1818
- };
1819
- const DocumentActionButton = (action) => {
1820
- const [dialogId, setDialogId] = React.useState(null);
1821
- const { toggleNotification } = useNotification();
1822
- const handleClick = (action2) => async (e) => {
1823
- const { onClick = () => false, dialog, id } = action2;
1824
- const muteDialog = await onClick(e);
1825
- if (dialog && !muteDialog) {
1826
- switch (dialog.type) {
1827
- case "notification":
1828
- toggleNotification({
1829
- title: dialog.title,
1830
- message: dialog.content,
1831
- type: dialog.status,
1832
- timeout: dialog.timeout,
1833
- onClose: dialog.onClose
1834
- });
1835
- break;
1836
- case "dialog":
1837
- case "modal":
1838
- e.preventDefault();
1839
- setDialogId(id);
1840
- }
1841
- }
1842
- };
1843
- const handleClose = () => {
1844
- setDialogId(null);
1845
- };
1846
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1847
- /* @__PURE__ */ jsx(
1848
- Button,
1849
- {
1850
- flex: "auto",
1851
- startIcon: action.icon,
1852
- disabled: action.disabled,
1853
- onClick: handleClick(action),
1854
- justifyContent: "center",
1855
- variant: action.variant || "default",
1856
- paddingTop: "7px",
1857
- paddingBottom: "7px",
1858
- children: action.label
1859
- }
1860
- ),
1861
- action.dialog?.type === "dialog" ? /* @__PURE__ */ jsx(
1862
- DocumentActionConfirmDialog,
1863
- {
1864
- ...action.dialog,
1865
- variant: action.dialog?.variant ?? action.variant,
1866
- isOpen: dialogId === action.id,
1867
- onClose: handleClose
1868
- }
1869
- ) : null,
1870
- action.dialog?.type === "modal" ? /* @__PURE__ */ jsx(
1871
- DocumentActionModal,
1872
- {
1873
- ...action.dialog,
1874
- onModalClose: handleClose,
1875
- isOpen: dialogId === action.id
1876
- }
1877
- ) : null
1878
- ] });
1879
- };
1880
- const MenuItem = styled(Menu.Item)`
1881
- &:hover {
1882
- background: ${({ theme, isVariantDanger, isDisabled }) => isVariantDanger && !isDisabled ? theme.colors.danger100 : "neutral"};
1883
- }
1884
- `;
1885
- const DocumentActionsMenu = ({
1886
- actions: actions2,
1887
- children,
1888
- label,
1889
- variant = "tertiary"
1890
- }) => {
1891
- const [isOpen, setIsOpen] = React.useState(false);
1892
- const [dialogId, setDialogId] = React.useState(null);
1893
- const { formatMessage } = useIntl();
1894
- const { toggleNotification } = useNotification();
1895
- const isDisabled = actions2.every((action) => action.disabled) || actions2.length === 0;
1896
- const handleClick = (action) => async (e) => {
1897
- const { onClick = () => false, dialog, id } = action;
1898
- const muteDialog = await onClick(e);
1899
- if (dialog && !muteDialog) {
1900
- switch (dialog.type) {
1901
- case "notification":
1902
- toggleNotification({
1903
- title: dialog.title,
1904
- message: dialog.content,
1905
- type: dialog.status,
1906
- timeout: dialog.timeout,
1907
- onClose: dialog.onClose
1908
- });
1909
- break;
1910
- case "dialog":
1911
- case "modal":
1912
- setDialogId(id);
1913
- }
1914
- }
1915
- };
1916
- const handleClose = () => {
1917
- setDialogId(null);
1918
- setIsOpen(false);
1919
- };
1920
- return /* @__PURE__ */ jsxs(Menu.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
1921
- /* @__PURE__ */ jsxs(
1922
- Menu.Trigger,
1923
- {
1924
- disabled: isDisabled,
1925
- size: "S",
1926
- endIcon: null,
1927
- paddingTop: "4px",
1928
- paddingLeft: "7px",
1929
- paddingRight: "7px",
1930
- variant,
1931
- children: [
1932
- /* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
1933
- /* @__PURE__ */ jsx(VisuallyHidden, { tag: "span", children: label || formatMessage({
1934
- id: "content-manager.containers.edit.panels.default.more-actions",
1935
- defaultMessage: "More document actions"
1936
- }) })
1937
- ]
1938
- }
1939
- ),
1940
- /* @__PURE__ */ jsxs(Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1941
- actions2.map((action) => {
1942
- return /* @__PURE__ */ jsx(
1943
- MenuItem,
1944
- {
1945
- disabled: action.disabled,
1946
- onSelect: handleClick(action),
1947
- display: "block",
1948
- isVariantDanger: action.variant === "danger",
1949
- isDisabled: action.disabled,
1950
- children: /* @__PURE__ */ jsx(Flex, { justifyContent: "space-between", gap: 4, children: /* @__PURE__ */ jsxs(
1951
- Flex,
1952
- {
1953
- color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
1954
- gap: 2,
1955
- tag: "span",
1956
- children: [
1957
- /* @__PURE__ */ jsx(
1958
- Flex,
1959
- {
1960
- tag: "span",
1961
- color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
1962
- children: action.icon
1963
- }
1964
- ),
1965
- action.label
1966
- ]
1967
- }
1968
- ) })
1969
- },
1970
- action.id
1971
- );
1972
- }),
1973
- children
1974
- ] }),
1975
- actions2.map((action) => {
1976
- return /* @__PURE__ */ jsxs(React.Fragment, { children: [
1977
- action.dialog?.type === "dialog" ? /* @__PURE__ */ jsx(
1978
- DocumentActionConfirmDialog,
1979
- {
1980
- ...action.dialog,
1981
- variant: action.variant,
1982
- isOpen: dialogId === action.id,
1983
- onClose: handleClose
1984
- }
1985
- ) : null,
1986
- action.dialog?.type === "modal" ? /* @__PURE__ */ jsx(
1987
- DocumentActionModal,
1988
- {
1989
- ...action.dialog,
1990
- onModalClose: handleClose,
1991
- isOpen: dialogId === action.id
1992
- }
1993
- ) : null
1994
- ] }, action.id);
1995
- })
1996
- ] });
1997
- };
1998
- const convertActionVariantToColor = (variant = "secondary") => {
1999
- switch (variant) {
2000
- case "danger":
2001
- return "danger600";
2002
- case "secondary":
2003
- return void 0;
2004
- case "success":
2005
- return "success600";
2006
- default:
2007
- return "primary600";
2008
- }
2009
- };
2010
- const convertActionVariantToIconColor = (variant = "secondary") => {
2011
- switch (variant) {
2012
- case "danger":
2013
- return "danger600";
2014
- case "secondary":
2015
- return "neutral500";
2016
- case "success":
2017
- return "success600";
2018
- default:
2019
- return "primary600";
2020
- }
2021
- };
2022
- const DocumentActionConfirmDialog = ({
2023
- onClose,
2024
- onCancel,
2025
- onConfirm,
2026
- title,
2027
- content,
2028
- isOpen,
2029
- variant = "secondary"
2030
- }) => {
2031
- const { formatMessage } = useIntl();
2032
- const handleClose = async () => {
2033
- if (onCancel) {
2034
- await onCancel();
2035
- }
2036
- onClose();
2037
- };
2038
- const handleConfirm = async () => {
2039
- if (onConfirm) {
2040
- await onConfirm();
2041
- }
2042
- onClose();
2043
- };
2044
- return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
2045
- /* @__PURE__ */ jsx(Dialog.Header, { children: title }),
2046
- /* @__PURE__ */ jsx(Dialog.Body, { children: content }),
2047
- /* @__PURE__ */ jsxs(Dialog.Footer, { children: [
2048
- /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
2049
- id: "app.components.Button.cancel",
2050
- defaultMessage: "Cancel"
2051
- }) }) }),
2052
- /* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
2053
- id: "app.components.Button.confirm",
2054
- defaultMessage: "Confirm"
2055
- }) })
2056
- ] })
2057
- ] }) });
2058
- };
2059
- const DocumentActionModal = ({
2060
- isOpen,
2061
- title,
2062
- onClose,
2063
- footer: Footer,
2064
- content: Content,
2065
- onModalClose
2066
- }) => {
2067
- const handleClose = () => {
2068
- if (onClose) {
2069
- onClose();
2070
- }
2071
- onModalClose();
2072
- };
2073
- return /* @__PURE__ */ jsx(Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
2074
- /* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: title }) }),
2075
- typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsx(Modal.Body, { children: Content }),
2076
- typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
2077
- ] }) });
2078
- };
2079
- const transformData = (data) => {
2080
- if (Array.isArray(data)) {
2081
- return data.map(transformData);
2082
- }
2083
- if (typeof data === "object" && data !== null) {
2084
- if ("apiData" in data) {
2085
- return data.apiData;
2086
- }
2087
- return mapValues(transformData)(data);
2088
- }
2089
- return data;
2090
- };
2091
- const PublishAction$1 = ({
2092
- activeTab,
2093
- documentId,
2094
- model,
2095
- collectionType,
2096
- meta,
2097
- document
2098
- }) => {
2099
- const { schema } = useDoc();
2100
- const navigate = useNavigate();
2101
- const { toggleNotification } = useNotification();
2102
- const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
2103
- const isListView = useMatch(LIST_PATH) !== null;
2104
- const isCloning = useMatch(CLONE_PATH) !== null;
2105
- const { id } = useParams();
2106
- const { formatMessage } = useIntl();
2107
- const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
2108
- const { publish } = useDocumentActions();
2109
- const [
2110
- countDraftRelations,
2111
- { isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
2112
- ] = useLazyGetDraftRelationCountQuery();
2113
- const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React.useState(0);
2114
- const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React.useState(0);
2115
- const [{ query, rawQuery }] = useQueryParams();
2116
- const params = React.useMemo(() => buildValidParams(query), [query]);
2117
- const modified = useForm("PublishAction", ({ modified: modified2 }) => modified2);
2118
- const setSubmitting = useForm("PublishAction", ({ setSubmitting: setSubmitting2 }) => setSubmitting2);
2119
- const isSubmitting = useForm("PublishAction", ({ isSubmitting: isSubmitting2 }) => isSubmitting2);
2120
- const validate = useForm("PublishAction", (state) => state.validate);
2121
- const setErrors = useForm("PublishAction", (state) => state.setErrors);
2122
- const formValues = useForm("PublishAction", ({ values }) => values);
2123
- React.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.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.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]);
2178
- const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
2179
- if (!schema?.options?.draftAndPublish) {
2180
- return null;
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
- if (id === "create") {
2209
- navigate({
2210
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
2211
- search: rawQuery
2212
- });
2213
- }
2214
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2215
- setErrors(formatValidationErrors(res.error));
2216
- }
2217
- } finally {
2218
- setSubmitting(false);
2219
- }
2220
- };
2221
- const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
2222
- const enableDraftRelationsCount = false;
2223
- const hasDraftRelations = enableDraftRelationsCount;
2224
- return {
2225
- /**
2226
- * Disabled when:
2227
- * - currently if you're cloning a document we don't support publish & clone at the same time.
2228
- * - the form is submitting
2229
- * - the active tab is the published tab
2230
- * - the document is already published & not modified
2231
- * - the document is being created & not modified
2232
- * - the user doesn't have the permission to publish
2233
- */
2234
- disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
2235
- label: formatMessage({
2236
- id: "app.utils.publish",
2237
- defaultMessage: "Publish"
2238
- }),
2239
- onClick: async () => {
2240
- await performPublish();
2241
- },
2242
- dialog: hasDraftRelations ? {
2243
- type: "dialog",
2244
- variant: "danger",
2245
- footer: null,
2246
- title: formatMessage({
2247
- id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
2248
- defaultMessage: "Confirmation"
2249
- }),
2250
- content: formatMessage(
2251
- {
2252
- id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
2253
- defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
2254
- },
2255
- {
2256
- count: totalDraftRelations
2257
- }
2258
- ),
2259
- onConfirm: async () => {
2260
- await performPublish();
2261
- }
2262
- } : void 0
2263
- };
2264
- };
2265
- PublishAction$1.type = "publish";
2266
- PublishAction$1.position = "panel";
2267
- const UpdateAction = ({
2268
- activeTab,
2269
- documentId,
2270
- model,
2271
- collectionType
2272
- }) => {
2273
- const navigate = useNavigate();
2274
- const { toggleNotification } = useNotification();
2275
- const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
2276
- const cloneMatch = useMatch(CLONE_PATH);
2277
- const isCloning = cloneMatch !== null;
2278
- const { formatMessage } = useIntl();
2279
- const { create, update, clone } = useDocumentActions();
2280
- const [{ query, rawQuery }] = useQueryParams();
2281
- const params = React.useMemo(() => buildValidParams(query), [query]);
2282
- const isSubmitting = useForm("UpdateAction", ({ isSubmitting: isSubmitting2 }) => isSubmitting2);
2283
- const modified = useForm("UpdateAction", ({ modified: modified2 }) => modified2);
2284
- const setSubmitting = useForm("UpdateAction", ({ setSubmitting: setSubmitting2 }) => setSubmitting2);
2285
- const document = useForm("UpdateAction", ({ values }) => values);
2286
- const validate = useForm("UpdateAction", (state) => state.validate);
2287
- const setErrors = useForm("UpdateAction", (state) => state.setErrors);
2288
- const resetForm = useForm("PublishAction", ({ resetForm: resetForm2 }) => resetForm2);
2289
- const handleUpdate = React.useCallback(async () => {
2290
- setSubmitting(true);
2291
- try {
2292
- if (!modified) {
2293
- return;
2294
- }
2295
- const { errors } = await validate(true, {
2296
- status: "draft"
2297
- });
2298
- if (errors) {
2299
- toggleNotification({
2300
- type: "danger",
2301
- message: formatMessage({
2302
- id: "content-manager.validation.error",
2303
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
2304
- })
2305
- });
2306
- return;
2307
- }
2308
- if (isCloning) {
2309
- const res = await clone(
2310
- {
2311
- model,
2312
- documentId: cloneMatch.params.origin,
2313
- params
2314
- },
2315
- transformData(document)
2316
- );
2317
- if ("data" in res) {
2318
- navigate(
2319
- {
2320
- pathname: `../${res.data.documentId}`,
2321
- search: rawQuery
2322
- },
2323
- { relative: "path" }
2324
- );
2325
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2326
- setErrors(formatValidationErrors(res.error));
2327
- }
2328
- } else if (documentId || collectionType === SINGLE_TYPES) {
2329
- const res = await update(
2330
- {
2331
- collectionType,
2332
- model,
2333
- documentId,
2334
- params
2335
- },
2336
- transformData(document)
2337
- );
2338
- if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2339
- setErrors(formatValidationErrors(res.error));
2340
- } else {
2341
- resetForm();
2342
- }
2343
- } else {
2344
- const res = await create(
2345
- {
2346
- model,
2347
- params
2348
- },
2349
- transformData(document)
2350
- );
2351
- if ("data" in res && collectionType !== SINGLE_TYPES) {
2352
- navigate(
2353
- {
2354
- pathname: `../${res.data.documentId}`,
2355
- search: rawQuery
2356
- },
2357
- { replace: true, relative: "path" }
2358
- );
2359
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2360
- setErrors(formatValidationErrors(res.error));
2361
- }
2362
- }
2363
- } finally {
2364
- setSubmitting(false);
2365
- }
2366
- }, [
2367
- clone,
2368
- cloneMatch?.params.origin,
2369
- collectionType,
2370
- create,
2371
- document,
2372
- documentId,
2373
- formatMessage,
2374
- formatValidationErrors,
2375
- isCloning,
2376
- model,
2377
- modified,
2378
- navigate,
2379
- params,
2380
- rawQuery,
2381
- resetForm,
2382
- setErrors,
2383
- setSubmitting,
2384
- toggleNotification,
2385
- update,
2386
- validate
2387
- ]);
2388
- React.useEffect(() => {
2389
- const handleKeyDown = (e) => {
2390
- if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
2391
- e.preventDefault();
2392
- handleUpdate();
2393
- }
2394
- };
2395
- window.addEventListener("keydown", handleKeyDown);
2396
- return () => {
2397
- window.removeEventListener("keydown", handleKeyDown);
2398
- };
2399
- }, [handleUpdate]);
2400
- return {
2401
- /**
2402
- * Disabled when:
2403
- * - the form is submitting
2404
- * - the document is not modified & we're not cloning (you can save a clone entity straight away)
2405
- * - the active tab is the published tab
2406
- */
2407
- disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
2408
- label: formatMessage({
2409
- id: "global.save",
2410
- defaultMessage: "Save"
2411
- }),
2412
- onClick: handleUpdate
2413
- };
2414
- };
2415
- UpdateAction.type = "update";
2416
- UpdateAction.position = "panel";
2417
- const UNPUBLISH_DRAFT_OPTIONS = {
2418
- KEEP: "keep",
2419
- DISCARD: "discard"
2420
- };
2421
- const UnpublishAction$1 = ({
2422
- activeTab,
2423
- documentId,
2424
- model,
2425
- collectionType,
2426
- document
2427
- }) => {
2428
- const { formatMessage } = useIntl();
2429
- const { schema } = useDoc();
2430
- const canPublish = useDocumentRBAC("UnpublishAction", ({ canPublish: canPublish2 }) => canPublish2);
2431
- const { unpublish } = useDocumentActions();
2432
- const [{ query }] = useQueryParams();
2433
- const params = React.useMemo(() => buildValidParams(query), [query]);
2434
- const { toggleNotification } = useNotification();
2435
- const [shouldKeepDraft, setShouldKeepDraft] = React.useState(true);
2436
- const isDocumentModified = document?.status === "modified";
2437
- const handleChange = (value) => {
2438
- setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
2439
- };
2440
- if (!schema?.options?.draftAndPublish) {
2441
- return null;
2442
- }
2443
- return {
2444
- disabled: !canPublish || activeTab === "published" || document?.status !== "published" && document?.status !== "modified",
2445
- label: formatMessage({
2446
- id: "app.utils.unpublish",
2447
- defaultMessage: "Unpublish"
2448
- }),
2449
- icon: /* @__PURE__ */ jsx(Cross, {}),
2450
- onClick: async () => {
2451
- if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
2452
- if (!documentId) {
2453
- console.error(
2454
- "You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
2455
- );
2456
- toggleNotification({
2457
- message: formatMessage({
2458
- id: "content-manager.actions.unpublish.error",
2459
- defaultMessage: "An error occurred while trying to unpublish the document."
2460
- }),
2461
- type: "danger"
2462
- });
2463
- }
2464
- return;
2465
- }
2466
- await unpublish({
2467
- collectionType,
2468
- model,
2469
- documentId,
2470
- params
2471
- });
2472
- },
2473
- dialog: isDocumentModified ? {
2474
- type: "dialog",
2475
- title: formatMessage({
2476
- id: "app.components.ConfirmDialog.title",
2477
- defaultMessage: "Confirmation"
2478
- }),
2479
- content: /* @__PURE__ */ jsxs(Flex, { alignItems: "flex-start", direction: "column", gap: 6, children: [
2480
- /* @__PURE__ */ jsxs(Flex, { width: "100%", direction: "column", gap: 2, children: [
2481
- /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
2482
- /* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
2483
- id: "content-manager.actions.unpublish.dialog.body",
2484
- defaultMessage: "Are you sure?"
2485
- }) })
2486
- ] }),
2487
- /* @__PURE__ */ jsxs(
2488
- Radio.Group,
2489
- {
2490
- defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
2491
- name: "discard-options",
2492
- "aria-label": formatMessage({
2493
- id: "content-manager.actions.unpublish.dialog.radio-label",
2494
- defaultMessage: "Choose an option to unpublish the document."
2495
- }),
2496
- onValueChange: handleChange,
2497
- children: [
2498
- /* @__PURE__ */ jsx(Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
2499
- id: "content-manager.actions.unpublish.dialog.option.keep-draft",
2500
- defaultMessage: "Keep draft"
2501
- }) }),
2502
- /* @__PURE__ */ jsx(Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
2503
- id: "content-manager.actions.unpublish.dialog.option.replace-draft",
2504
- defaultMessage: "Replace draft"
2505
- }) })
2506
- ]
2507
- }
2508
- )
2509
- ] }),
2510
- onConfirm: async () => {
2511
- if (!documentId && collectionType !== SINGLE_TYPES) {
2512
- console.error(
2513
- "You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
2514
- );
2515
- toggleNotification({
2516
- message: formatMessage({
2517
- id: "content-manager.actions.unpublish.error",
2518
- defaultMessage: "An error occurred while trying to unpublish the document."
2519
- }),
2520
- type: "danger"
2521
- });
2522
- }
2523
- await unpublish(
2524
- {
2525
- collectionType,
2526
- model,
2527
- documentId,
2528
- params
2529
- },
2530
- !shouldKeepDraft
2531
- );
2532
- }
2533
- } : void 0,
2534
- variant: "danger",
2535
- position: ["panel", "table-row"]
2536
- };
2537
- };
2538
- UnpublishAction$1.type = "unpublish";
2539
- UnpublishAction$1.position = "panel";
2540
- const DiscardAction = ({
2541
- activeTab,
2542
- documentId,
2543
- model,
2544
- collectionType,
2545
- document
2546
- }) => {
2547
- const { formatMessage } = useIntl();
2548
- const { schema } = useDoc();
2549
- const canUpdate = useDocumentRBAC("DiscardAction", ({ canUpdate: canUpdate2 }) => canUpdate2);
2550
- const { discard } = useDocumentActions();
2551
- const [{ query }] = useQueryParams();
2552
- const params = React.useMemo(() => buildValidParams(query), [query]);
2553
- if (!schema?.options?.draftAndPublish) {
2554
- return null;
2555
- }
2556
- return {
2557
- disabled: !canUpdate || activeTab === "published" || document?.status !== "modified",
2558
- label: formatMessage({
2559
- id: "content-manager.actions.discard.label",
2560
- defaultMessage: "Discard changes"
2561
- }),
2562
- icon: /* @__PURE__ */ jsx(Cross, {}),
2563
- position: ["panel", "table-row"],
2564
- variant: "danger",
2565
- dialog: {
2566
- type: "dialog",
2567
- title: formatMessage({
2568
- id: "app.components.ConfirmDialog.title",
2569
- defaultMessage: "Confirmation"
2570
- }),
2571
- content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
2572
- /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
2573
- /* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
2574
- id: "content-manager.actions.discard.dialog.body",
2575
- defaultMessage: "Are you sure?"
2576
- }) })
2577
- ] }),
2578
- onConfirm: async () => {
2579
- await discard({
2580
- collectionType,
2581
- model,
2582
- documentId,
2583
- params
2584
- });
2585
- }
2586
- }
2587
- };
2588
- };
2589
- DiscardAction.type = "discard";
2590
- DiscardAction.position = "panel";
2591
- const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
2592
- const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
2593
- const RelativeTime = React.forwardRef(
2594
- ({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
2595
- const { formatRelativeTime, formatDate, formatTime } = useIntl();
2596
- const interval = intervalToDuration({
2597
- start: timestamp,
2598
- end: Date.now()
2599
- // see https://github.com/date-fns/date-fns/issues/2891 – No idea why it's all partial it returns it every time.
2600
- });
2601
- const unit = intervals.find((intervalUnit) => {
2602
- return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
2603
- }) ?? "seconds";
2604
- const relativeTime = isPast(timestamp) ? -interval[unit] : interval[unit];
2605
- const customInterval = customIntervals.find(
2606
- (custom) => interval[custom.unit] < custom.threshold
2607
- );
2608
- const displayText = customInterval ? customInterval.text : formatRelativeTime(relativeTime, unit, { numeric: "auto" });
2609
- return /* @__PURE__ */ jsx(
2610
- "time",
2611
- {
2612
- ref: forwardedRef,
2613
- dateTime: timestamp.toISOString(),
2614
- role: "time",
2615
- title: `${formatDate(timestamp)} ${formatTime(timestamp)}`,
2616
- ...restProps,
2617
- children: displayText
2618
- }
2619
- );
2620
- }
2621
- );
2622
- const getDisplayName = ({
2623
- firstname,
2624
- lastname,
2625
- username,
2626
- email
2627
- } = {}) => {
2628
- if (username) {
2629
- return username;
2630
- }
2631
- if (firstname) {
2632
- return `${firstname} ${lastname ?? ""}`.trim();
2633
- }
2634
- return email ?? "";
2635
- };
2636
- const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
2637
- const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
2638
- const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
2639
- const { formatMessage } = useIntl();
2640
- return /* @__PURE__ */ jsx(Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
2641
- id: `content-manager.containers.List.${status}`,
2642
- defaultMessage: capitalise(status)
2643
- }) }) });
2644
- };
2645
- const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2646
- const { formatMessage } = useIntl();
2647
- const isCloning = useMatch(CLONE_PATH) !== null;
2648
- const params = useParams();
2649
- const title = isCreating ? formatMessage({
2650
- id: "content-manager.containers.edit.title.new",
2651
- defaultMessage: "Create an entry"
2652
- }) : documentTitle;
2653
- return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
2654
- /* @__PURE__ */ jsx(
2655
- BackButton,
2656
- {
2657
- fallback: params.collectionType === SINGLE_TYPES ? void 0 : `../${COLLECTION_TYPES}/${params.slug}`
2658
- }
2659
- ),
2660
- /* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
2661
- /* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
2662
- /* @__PURE__ */ jsx(HeaderToolbar, {})
2663
- ] }),
2664
- status ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
2665
- ] });
2666
- };
2667
- const HeaderToolbar = () => {
2668
- const { formatMessage } = useIntl();
2669
- const isCloning = useMatch(CLONE_PATH) !== null;
2670
- const [
2671
- {
2672
- query: { status = "draft" }
2673
- }
2674
- ] = useQueryParams();
2675
- const { model, id, document, meta, collectionType } = useDoc();
2676
- const plugins = useStrapiApp("HeaderToolbar", (state) => state.plugins);
2677
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
2678
- /* @__PURE__ */ jsx(
2679
- DescriptionComponentRenderer,
2680
- {
2681
- props: {
2682
- activeTab: status,
2683
- model,
2684
- documentId: id,
2685
- document: isCloning ? void 0 : document,
2686
- meta: isCloning ? void 0 : meta,
2687
- collectionType
2688
- },
2689
- descriptions: plugins["content-manager"].apis.getHeaderActions(),
2690
- children: (actions2) => {
2691
- if (actions2.length > 0) {
2692
- return /* @__PURE__ */ jsx(HeaderActions, { actions: actions2 });
2693
- } else {
2694
- return null;
2695
- }
2696
- }
2697
- }
2698
- ),
2699
- /* @__PURE__ */ jsx(
2700
- DescriptionComponentRenderer,
2701
- {
2702
- props: {
2703
- activeTab: status,
2704
- model,
2705
- documentId: id,
2706
- document: isCloning ? void 0 : document,
2707
- meta: isCloning ? void 0 : meta,
2708
- collectionType
2709
- },
2710
- descriptions: plugins["content-manager"].apis.getDocumentActions("header"),
2711
- children: (actions2) => {
2712
- const headerActions = actions2.filter((action) => {
2713
- const positions = Array.isArray(action.position) ? action.position : [action.position];
2714
- return positions.includes("header");
2715
- });
2716
- return /* @__PURE__ */ jsx(
2717
- DocumentActionsMenu,
2718
- {
2719
- actions: headerActions,
2720
- label: formatMessage({
2721
- id: "content-manager.containers.edit.header.more-actions",
2722
- defaultMessage: "More actions"
2723
- }),
2724
- children: /* @__PURE__ */ jsx(Information, { activeTab: status })
2725
- }
2726
- );
2727
- }
2728
- }
2729
- )
2730
- ] });
2731
- };
2732
- const Information = ({ activeTab }) => {
2733
- const { formatMessage } = useIntl();
2734
- const { document, meta } = useDoc();
2735
- if (!document || !document.id) {
2736
- return null;
2737
- }
2738
- const createAndUpdateDocument = activeTab === "draft" ? document : meta?.availableStatus.find((status) => status.publishedAt === null);
2739
- const publishDocument = activeTab === "published" ? document : meta?.availableStatus.find((status) => status.publishedAt !== null);
2740
- const creator = createAndUpdateDocument?.[CREATED_BY_ATTRIBUTE_NAME] ? getDisplayName(createAndUpdateDocument[CREATED_BY_ATTRIBUTE_NAME]) : null;
2741
- const updator = createAndUpdateDocument?.[UPDATED_BY_ATTRIBUTE_NAME] ? getDisplayName(createAndUpdateDocument[UPDATED_BY_ATTRIBUTE_NAME]) : null;
2742
- const information = [
2743
- {
2744
- isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
2745
- label: formatMessage({
2746
- id: "content-manager.containers.edit.information.last-published.label",
2747
- defaultMessage: "Published"
2748
- }),
2749
- value: formatMessage(
2750
- {
2751
- id: "content-manager.containers.edit.information.last-published.value",
2752
- defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2753
- },
2754
- {
2755
- time: /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
2756
- isAnonymous: !publishDocument?.[PUBLISHED_BY_ATTRIBUTE_NAME],
2757
- author: publishDocument?.[PUBLISHED_BY_ATTRIBUTE_NAME] ? getDisplayName(publishDocument?.[PUBLISHED_BY_ATTRIBUTE_NAME]) : null
2758
- }
2759
- )
2760
- },
2761
- {
2762
- isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
2763
- label: formatMessage({
2764
- id: "content-manager.containers.edit.information.last-draft.label",
2765
- defaultMessage: "Updated"
2766
- }),
2767
- value: formatMessage(
2768
- {
2769
- id: "content-manager.containers.edit.information.last-draft.value",
2770
- defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2771
- },
2772
- {
2773
- time: /* @__PURE__ */ jsx(
2774
- RelativeTime,
2775
- {
2776
- timestamp: new Date(createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME])
2777
- }
2778
- ),
2779
- isAnonymous: !updator,
2780
- author: updator
2781
- }
2782
- )
2783
- },
2784
- {
2785
- isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
2786
- label: formatMessage({
2787
- id: "content-manager.containers.edit.information.document.label",
2788
- defaultMessage: "Created"
2789
- }),
2790
- value: formatMessage(
2791
- {
2792
- id: "content-manager.containers.edit.information.document.value",
2793
- defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2794
- },
2795
- {
2796
- time: /* @__PURE__ */ jsx(
2797
- RelativeTime,
2798
- {
2799
- timestamp: new Date(createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME])
2800
- }
2801
- ),
2802
- isAnonymous: !creator,
2803
- author: creator
2804
- }
2805
- )
2806
- }
2807
- ].filter((info) => info.isDisplayed);
2808
- return /* @__PURE__ */ jsx(
2809
- Flex,
2810
- {
2811
- borderWidth: "1px 0 0 0",
2812
- borderStyle: "solid",
2813
- borderColor: "neutral150",
2814
- direction: "column",
2815
- marginTop: 2,
2816
- tag: "dl",
2817
- padding: 5,
2818
- gap: 3,
2819
- alignItems: "flex-start",
2820
- marginLeft: "-0.4rem",
2821
- marginRight: "-0.4rem",
2822
- width: "calc(100% + 8px)",
2823
- children: information.map((info) => /* @__PURE__ */ jsxs(Flex, { gap: 1, direction: "column", alignItems: "flex-start", children: [
2824
- /* @__PURE__ */ jsx(Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
2825
- /* @__PURE__ */ jsx(Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
2826
- ] }, info.label))
2827
- }
2828
- );
2829
- };
2830
- const HeaderActions = ({ actions: actions2 }) => {
2831
- const [dialogId, setDialogId] = React.useState(null);
2832
- const handleClick = (action) => async (e) => {
2833
- if (!("options" in action)) {
2834
- const { onClick = () => false, dialog, id } = action;
2835
- const muteDialog = await onClick(e);
2836
- if (dialog && !muteDialog) {
2837
- e.preventDefault();
2838
- setDialogId(id);
2839
- }
2840
- }
2841
- };
2842
- const handleClose = () => {
2843
- setDialogId(null);
2844
- };
2845
- return /* @__PURE__ */ jsx(Flex, { gap: 1, children: actions2.map((action) => {
2846
- if (action.options) {
2847
- return /* @__PURE__ */ jsx(
2848
- SingleSelect,
2849
- {
2850
- size: "S",
2851
- onChange: action.onSelect,
2852
- "aria-label": action.label,
2853
- ...action,
2854
- children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsx(SingleSelectOption, { ...option, children: label }, option.value))
2855
- },
2856
- action.id
2857
- );
2858
- } else {
2859
- if (action.type === "icon") {
2860
- return /* @__PURE__ */ jsxs(React.Fragment, { children: [
2861
- /* @__PURE__ */ jsx(
2862
- IconButton,
2863
- {
2864
- disabled: action.disabled,
2865
- label: action.label,
2866
- size: "S",
2867
- onClick: handleClick(action),
2868
- children: action.icon
2869
- }
2870
- ),
2871
- action.dialog ? /* @__PURE__ */ jsx(
2872
- HeaderActionDialog,
2873
- {
2874
- ...action.dialog,
2875
- isOpen: dialogId === action.id,
2876
- onClose: handleClose
2877
- }
2878
- ) : null
2879
- ] }, action.id);
2880
- }
2881
- }
2882
- }) });
2883
- };
2884
- const HeaderActionDialog = ({
2885
- onClose,
2886
- onCancel,
2887
- title,
2888
- content: Content,
2889
- isOpen
2890
- }) => {
2891
- const handleClose = async () => {
2892
- if (onCancel) {
2893
- await onCancel();
2894
- }
2895
- onClose();
2896
- };
2897
- return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
2898
- /* @__PURE__ */ jsx(Dialog.Header, { children: title }),
2899
- typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content
2900
- ] }) });
2901
- };
2902
- const ConfigureTheViewAction = ({ collectionType, model }) => {
2903
- const navigate = useNavigate();
2904
- const { formatMessage } = useIntl();
2905
- return {
2906
- label: formatMessage({
2907
- id: "app.links.configure-view",
2908
- defaultMessage: "Configure the view"
2909
- }),
2910
- icon: /* @__PURE__ */ jsx(ListPlus, {}),
2911
- onClick: () => {
2912
- navigate(`../${collectionType}/${model}/configurations/edit`);
2913
- },
2914
- position: "header"
2915
- };
2916
- };
2917
- ConfigureTheViewAction.type = "configure-the-view";
2918
- ConfigureTheViewAction.position = "header";
2919
- const EditTheModelAction = ({ model }) => {
2920
- const navigate = useNavigate();
2921
- const { formatMessage } = useIntl();
2922
- return {
2923
- label: formatMessage({
2924
- id: "content-manager.link-to-ctb",
2925
- defaultMessage: "Edit the model"
2926
- }),
2927
- icon: /* @__PURE__ */ jsx(Pencil, {}),
2928
- onClick: () => {
2929
- navigate(`/plugins/content-type-builder/content-types/${model}`);
2930
- },
2931
- position: "header"
2932
- };
2933
- };
2934
- EditTheModelAction.type = "edit-the-model";
2935
- EditTheModelAction.position = "header";
2936
- const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2937
- const navigate = useNavigate();
2938
- const { formatMessage } = useIntl();
2939
- const listViewPathMatch = useMatch(LIST_PATH);
2940
- const canDelete = useDocumentRBAC("DeleteAction", (state) => state.canDelete);
2941
- const { delete: deleteAction } = useDocumentActions();
2942
- const { toggleNotification } = useNotification();
2943
- const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
2944
- const isLocalized = document?.locale != null;
2945
- return {
2946
- disabled: !canDelete || !document,
2947
- label: formatMessage(
2948
- {
2949
- id: "content-manager.actions.delete.label",
2950
- defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
2951
- },
2952
- { isLocalized }
2953
- ),
2954
- icon: /* @__PURE__ */ jsx(Trash, {}),
2955
- dialog: {
2956
- type: "dialog",
2957
- title: formatMessage({
2958
- id: "app.components.ConfirmDialog.title",
2959
- defaultMessage: "Confirmation"
2960
- }),
2961
- content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
2962
- /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
2963
- /* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
2964
- id: "content-manager.actions.delete.dialog.body",
2965
- defaultMessage: "Are you sure?"
2966
- }) })
2967
- ] }),
2968
- onConfirm: async () => {
2969
- if (!listViewPathMatch) {
2970
- setSubmitting(true);
2971
- }
2972
- try {
2973
- if (!documentId && collectionType !== SINGLE_TYPES) {
2974
- console.error(
2975
- "You're trying to delete a document without an id, this is likely a bug with Strapi. Please open an issue."
2976
- );
2977
- toggleNotification({
2978
- message: formatMessage({
2979
- id: "content-manager.actions.delete.error",
2980
- defaultMessage: "An error occurred while trying to delete the document."
2981
- }),
2982
- type: "danger"
2983
- });
2984
- return;
2985
- }
2986
- const res = await deleteAction({
2987
- documentId,
2988
- model,
2989
- collectionType,
2990
- params: {
2991
- locale: "*"
2992
- }
2993
- });
2994
- if (!("error" in res)) {
2995
- navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
2996
- }
2997
- } finally {
2998
- if (!listViewPathMatch) {
2999
- setSubmitting(false);
3000
- }
3001
- }
3002
- }
3003
- },
3004
- variant: "danger",
3005
- position: ["header", "table-row"]
3006
- };
3007
- };
3008
- DeleteAction$1.type = "delete";
3009
- DeleteAction$1.position = ["header", "table-row"];
3010
- const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
3011
- const Panels = () => {
3012
- const isCloning = useMatch(CLONE_PATH) !== null;
3013
- const [
3014
- {
3015
- query: { status }
3016
- }
3017
- ] = useQueryParams({
3018
- status: "draft"
3019
- });
3020
- const { model, id, document, meta, collectionType } = useDoc();
3021
- const plugins = useStrapiApp("Panels", (state) => state.plugins);
3022
- const props = {
3023
- activeTab: status,
3024
- model,
3025
- documentId: id,
3026
- document: isCloning ? void 0 : document,
3027
- meta: isCloning ? void 0 : meta,
3028
- collectionType
3029
- };
3030
- return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
3031
- DescriptionComponentRenderer,
3032
- {
3033
- props,
3034
- descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
3035
- children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
3036
- }
3037
- ) });
3038
- };
3039
- const ActionsPanel = () => {
3040
- const { formatMessage } = useIntl();
3041
- return {
3042
- title: formatMessage({
3043
- id: "content-manager.containers.edit.panels.default.title",
3044
- defaultMessage: "Entry"
3045
- }),
3046
- content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
3047
- };
3048
- };
3049
- ActionsPanel.type = "actions";
3050
- const ActionsPanelContent = () => {
3051
- const isCloning = useMatch(CLONE_PATH) !== null;
3052
- const [
3053
- {
3054
- query: { status = "draft" }
3055
- }
3056
- ] = useQueryParams();
3057
- const { model, id, document, meta, collectionType } = useDoc();
3058
- const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
3059
- const props = {
3060
- activeTab: status,
3061
- model,
3062
- documentId: id,
3063
- document: isCloning ? void 0 : document,
3064
- meta: isCloning ? void 0 : meta,
3065
- collectionType
3066
- };
3067
- return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
3068
- /* @__PURE__ */ jsx(
3069
- DescriptionComponentRenderer,
3070
- {
3071
- props,
3072
- descriptions: plugins["content-manager"].apis.getDocumentActions("panel"),
3073
- children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
3074
- }
3075
- ),
3076
- /* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
3077
- ] });
3078
- };
3079
- const Panel = React.forwardRef(({ children, title }, ref) => {
3080
- return /* @__PURE__ */ jsxs(
3081
- Flex,
3082
- {
3083
- ref,
3084
- tag: "aside",
3085
- "aria-labelledby": "additional-information",
3086
- background: "neutral0",
3087
- borderColor: "neutral150",
3088
- hasRadius: true,
3089
- paddingBottom: 4,
3090
- paddingLeft: 4,
3091
- paddingRight: 4,
3092
- paddingTop: 4,
3093
- shadow: "tableShadow",
3094
- gap: 3,
3095
- direction: "column",
3096
- justifyContent: "stretch",
3097
- alignItems: "flex-start",
3098
- children: [
3099
- /* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
3100
- children
3101
- ]
3102
- }
3103
- );
3104
- });
3105
- const ConfirmBulkActionDialog = ({
3106
- onToggleDialog,
3107
- isOpen = false,
3108
- dialogBody,
3109
- endAction
3110
- }) => {
3111
- const { formatMessage } = useIntl();
3112
- return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
3113
- /* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage({
3114
- id: "app.components.ConfirmDialog.title",
3115
- defaultMessage: "Confirmation"
3116
- }) }),
3117
- /* @__PURE__ */ jsx(Dialog.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3118
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3119
- dialogBody
3120
- ] }) }),
3121
- /* @__PURE__ */ jsxs(Dialog.Footer, { children: [
3122
- /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { fullWidth: true, onClick: onToggleDialog, variant: "tertiary", children: formatMessage({
3123
- id: "app.components.Button.cancel",
3124
- defaultMessage: "Cancel"
3125
- }) }) }),
3126
- endAction
3127
- ] })
3128
- ] }) });
3129
- };
3130
- const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
3131
- const ConfirmDialogPublishAll = ({
3132
- isOpen,
3133
- onToggleDialog,
3134
- isConfirmButtonLoading = false,
3135
- onConfirm
3136
- }) => {
3137
- const { formatMessage } = useIntl();
3138
- const selectedEntries = useTable("ConfirmDialogPublishAll", (state) => state.selectedRows);
3139
- const { toggleNotification } = useNotification();
3140
- const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
3141
- const { model, schema } = useDoc();
3142
- const [{ query }] = useQueryParams();
3143
- const enableDraftRelationsCount = false;
3144
- const {
3145
- data: countDraftRelations = 0,
3146
- isLoading,
3147
- error
3148
- } = useGetManyDraftRelationCountQuery(
3149
- {
3150
- model,
3151
- documentIds: selectedEntries.map((entry) => entry.documentId),
3152
- locale: query?.plugins?.i18n?.locale
3153
- },
3154
- {
3155
- skip: !enableDraftRelationsCount
3156
- }
3157
- );
3158
- React.useEffect(() => {
3159
- if (error) {
3160
- toggleNotification({ type: "danger", message: formatAPIError(error) });
3161
- }
3162
- }, [error, formatAPIError, toggleNotification]);
3163
- if (error) {
3164
- return null;
3165
- }
3166
- return /* @__PURE__ */ jsx(
3167
- ConfirmBulkActionDialog,
3168
- {
3169
- isOpen: isOpen && !isLoading,
3170
- onToggleDialog,
3171
- dialogBody: /* @__PURE__ */ jsxs(Fragment, { children: [
3172
- /* @__PURE__ */ jsxs(Typography, { id: "confirm-description", textAlign: "center", children: [
3173
- countDraftRelations > 0 && formatMessage(
3174
- {
3175
- id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
3176
- 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. "
3177
- },
3178
- {
3179
- b: BoldChunk$1,
3180
- count: countDraftRelations,
3181
- entities: selectedEntries.length
3182
- }
3183
- ),
3184
- formatMessage({
3185
- id: getTranslation("popUpWarning.bodyMessage.contentType.publish.all"),
3186
- defaultMessage: "Are you sure you want to publish these entries?"
3187
- })
3188
- ] }),
3189
- schema?.pluginOptions && "i18n" in schema.pluginOptions && schema?.pluginOptions.i18n && /* @__PURE__ */ jsx(Typography, { textColor: "danger500", textAlign: "center", children: formatMessage(
3190
- {
3191
- id: getTranslation("Settings.list.actions.publishAdditionalInfos"),
3192
- defaultMessage: "This will publish the active locale versions <em>(from Internationalization)</em>"
3193
- },
3194
- {
3195
- em: Emphasis
3196
- }
3197
- ) })
3198
- ] }),
3199
- endAction: /* @__PURE__ */ jsx(
3200
- Button,
3201
- {
3202
- onClick: onConfirm,
3203
- variant: "secondary",
3204
- startIcon: /* @__PURE__ */ jsx(Check, {}),
3205
- loading: isConfirmButtonLoading,
3206
- children: formatMessage({
3207
- id: "app.utils.publish",
3208
- defaultMessage: "Publish"
3209
- })
3210
- }
3211
- )
3212
- }
3213
- );
3214
- };
3215
- const TypographyMaxWidth = styled(Typography)`
3216
- max-width: 300px;
3217
- `;
3218
- const formatErrorMessages = (errors, parentKey, formatMessage) => {
3219
- const messages = [];
3220
- Object.entries(errors).forEach(([key, value]) => {
3221
- const currentKey = parentKey ? `${parentKey}.${key}` : key;
3222
- if (typeof value === "object" && value !== null && !Array.isArray(value)) {
3223
- if ("id" in value && "defaultMessage" in value) {
3224
- messages.push(
3225
- formatMessage(
3226
- {
3227
- id: `${value.id}.withField`,
3228
- defaultMessage: value.defaultMessage
3229
- },
3230
- { field: currentKey }
3231
- )
3232
- );
3233
- } else {
3234
- messages.push(
3235
- ...formatErrorMessages(
3236
- // @ts-expect-error TODO: check why value is not compatible with FormErrors
3237
- value,
3238
- currentKey,
3239
- formatMessage
3240
- )
3241
- );
3242
- }
3243
- } else {
3244
- messages.push(
3245
- formatMessage(
3246
- {
3247
- id: `${value}.withField`,
3248
- defaultMessage: value
3249
- },
3250
- { field: currentKey }
3251
- )
3252
- );
3253
- }
3254
- });
3255
- return messages;
3256
- };
3257
- const EntryValidationText = ({ validationErrors, status }) => {
3258
- const { formatMessage } = useIntl();
3259
- if (validationErrors) {
3260
- const validationErrorsMessages = formatErrorMessages(validationErrors, "", formatMessage).join(
3261
- " "
3262
- );
3263
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
3264
- /* @__PURE__ */ jsx(CrossCircle, { fill: "danger600" }),
3265
- /* @__PURE__ */ jsx(Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
3266
- ] });
3267
- }
3268
- if (status === "published") {
3269
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
3270
- /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
3271
- /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
3272
- id: "content-manager.bulk-publish.already-published",
3273
- defaultMessage: "Already Published"
3274
- }) })
3275
- ] });
3276
- }
3277
- if (status === "modified") {
3278
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
3279
- /* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
3280
- /* @__PURE__ */ jsx(Typography, { children: formatMessage({
3281
- id: "content-manager.bulk-publish.modified",
3282
- defaultMessage: "Ready to publish changes"
3283
- }) })
3284
- ] });
3285
- }
3286
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
3287
- /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
3288
- /* @__PURE__ */ jsx(Typography, { children: formatMessage({
3289
- id: "app.utils.ready-to-publish",
3290
- defaultMessage: "Ready to publish"
3291
- }) })
3292
- ] });
3293
- };
3294
- const TABLE_HEADERS = [
3295
- { name: "id", label: "id" },
3296
- { name: "name", label: "name" },
3297
- { name: "status", label: "status" },
3298
- { name: "publicationStatus", label: "Publication status" }
3299
- ];
3300
- const SelectedEntriesTableContent = ({
3301
- isPublishing,
3302
- rowsToDisplay = [],
3303
- entriesToPublish = [],
3304
- validationErrors = {}
3305
- }) => {
3306
- const { pathname } = useLocation();
3307
- const { formatMessage } = useIntl();
3308
- const {
3309
- list: {
3310
- settings: { mainField }
3311
- }
3312
- } = useDocLayout();
3313
- const shouldDisplayMainField = mainField != null && mainField !== "id";
3314
- return /* @__PURE__ */ jsxs(Table.Content, { children: [
3315
- /* @__PURE__ */ jsxs(Table.Head, { children: [
3316
- /* @__PURE__ */ jsx(Table.HeaderCheckboxCell, {}),
3317
- TABLE_HEADERS.filter((head) => head.name !== "name" || shouldDisplayMainField).map(
3318
- (head) => /* @__PURE__ */ jsx(Table.HeaderCell, { ...head }, head.name)
3319
- )
3320
- ] }),
3321
- /* @__PURE__ */ jsx(Table.Loading, {}),
3322
- /* @__PURE__ */ jsx(Table.Body, { children: rowsToDisplay.map((row, index2) => /* @__PURE__ */ jsxs(Table.Row, { children: [
3323
- /* @__PURE__ */ jsx(Table.CheckboxCell, { id: row.id }),
3324
- /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Typography, { children: row.id }) }),
3325
- shouldDisplayMainField && /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Typography, { children: row[mainField] }) }),
3326
- /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(DocumentStatus, { status: row.status, maxWidth: "min-content" }) }),
3327
- /* @__PURE__ */ jsx(Table.Cell, { children: isPublishing && entriesToPublish.includes(row.documentId) ? /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
3328
- /* @__PURE__ */ jsx(Typography, { children: formatMessage({
3329
- id: "content-manager.success.record.publishing",
3330
- defaultMessage: "Publishing..."
3331
- }) }),
3332
- /* @__PURE__ */ jsx(Loader, { small: true })
3333
- ] }) : /* @__PURE__ */ jsx(
3334
- EntryValidationText,
3335
- {
3336
- validationErrors: validationErrors[row.documentId],
3337
- status: row.status
3338
- }
3339
- ) }),
3340
- /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
3341
- IconButton,
3342
- {
3343
- tag: Link,
3344
- to: {
3345
- pathname: `${pathname}/${row.documentId}`,
3346
- search: row.locale && `?plugins[i18n][locale]=${row.locale}`
3347
- },
3348
- state: { from: pathname },
3349
- label: formatMessage({
3350
- id: "content-manager.bulk-publish.edit",
3351
- defaultMessage: "Edit"
3352
- }),
3353
- target: "_blank",
3354
- marginLeft: "auto",
3355
- variant: "ghost",
3356
- children: /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" })
3357
- }
3358
- ) }) })
3359
- ] }, row.id)) })
3360
- ] });
3361
- };
3362
- const BoldChunk = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
3363
- const SelectedEntriesModalContent = ({
3364
- listViewSelectedEntries,
3365
- toggleModal,
3366
- setListViewSelectedDocuments,
3367
- model
3368
- }) => {
3369
- const { formatMessage } = useIntl();
3370
- const { schema, components } = useContentTypeSchema(model);
3371
- const documentIds = listViewSelectedEntries.map(({ documentId }) => documentId);
3372
- const [{ query }] = useQueryParams();
3373
- const params = React.useMemo(() => buildValidParams(query), [query]);
3374
- const { data, isLoading, isFetching, refetch } = useGetAllDocumentsQuery(
3375
- {
3376
- model,
3377
- params: {
3378
- page: "1",
3379
- pageSize: documentIds.length.toString(),
3380
- sort: query.sort,
3381
- filters: {
3382
- documentId: {
3383
- $in: documentIds
3384
- }
3385
- },
3386
- locale: query.plugins?.i18n?.locale
3387
- }
3388
- },
3389
- {
3390
- selectFromResult: ({ data: data2, ...restRes }) => ({ data: data2?.results ?? [], ...restRes })
3391
- }
3392
- );
3393
- const { rows, validationErrors } = React.useMemo(() => {
3394
- if (data.length > 0 && schema) {
3395
- const validate = createYupSchema(
3396
- schema.attributes,
3397
- components,
3398
- // Since this is the "Publish" action, the validation
3399
- // schema must enforce the rules for published entities
3400
- { status: "published" }
3401
- );
3402
- const validationErrors2 = {};
3403
- const rows2 = data.map((entry) => {
3404
- try {
3405
- validate.validateSync(entry, { abortEarly: false });
3406
- return entry;
3407
- } catch (e) {
3408
- if (e instanceof ValidationError) {
3409
- validationErrors2[entry.documentId] = getYupValidationErrors(e);
3410
- }
3411
- return entry;
3412
- }
3413
- });
3414
- return { rows: rows2, validationErrors: validationErrors2 };
3415
- }
3416
- return {
3417
- rows: [],
3418
- validationErrors: {}
3419
- };
3420
- }, [components, data, schema]);
3421
- const [publishedCount, setPublishedCount] = React.useState(0);
3422
- const [isDialogOpen, setIsDialogOpen] = React.useState(false);
3423
- const { publishMany: bulkPublishAction } = useDocumentActions();
3424
- const [, { isLoading: isSubmittingForm }] = usePublishManyDocumentsMutation();
3425
- const selectedRows = useTable("publishAction", (state) => state.selectedRows);
3426
- const selectedEntries = rows.filter(
3427
- (entry) => selectedRows.some((selectedEntry) => selectedEntry.documentId === entry.documentId)
3428
- );
3429
- const entriesToPublish = selectedEntries.filter((entry) => !validationErrors[entry.documentId]).map((entry) => entry.documentId);
3430
- const selectedEntriesWithErrorsCount = selectedEntries.filter(
3431
- ({ documentId }) => validationErrors[documentId]
3432
- ).length;
3433
- const selectedEntriesPublished = selectedEntries.filter(
3434
- ({ status }) => status === "published"
3435
- ).length;
3436
- const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublished;
3437
- const toggleDialog = () => setIsDialogOpen((prev) => !prev);
3438
- const handleConfirmBulkPublish = async () => {
3439
- toggleDialog();
3440
- const res = await bulkPublishAction({ model, documentIds: entriesToPublish, params });
3441
- if (!("error" in res)) {
3442
- setPublishedCount(res.count);
3443
- const unpublishedEntries = rows.filter((row) => {
3444
- return !entriesToPublish.includes(row.documentId);
3445
- });
3446
- setListViewSelectedDocuments(unpublishedEntries);
3447
- }
3448
- };
3449
- const getFormattedCountMessage = () => {
3450
- if (publishedCount) {
3451
- return formatMessage(
3452
- {
3453
- id: getTranslation("containers.list.selectedEntriesModal.publishedCount"),
3454
- 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."
3455
- },
3456
- {
3457
- publishedCount,
3458
- withErrorsCount: selectedEntriesWithErrorsCount,
3459
- b: BoldChunk
3460
- }
3461
- );
3462
- }
3463
- return formatMessage(
3464
- {
3465
- id: getTranslation("containers.list.selectedEntriesModal.selectedCount"),
3466
- 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."
3467
- },
3468
- {
3469
- readyToPublishCount: selectedEntriesWithNoErrorsCount,
3470
- withErrorsCount: selectedEntriesWithErrorsCount,
3471
- alreadyPublishedCount: selectedEntriesPublished,
3472
- b: BoldChunk
3473
- }
3474
- );
3475
- };
3476
- return /* @__PURE__ */ jsxs(Fragment, { children: [
3477
- /* @__PURE__ */ jsxs(Modal.Body, { children: [
3478
- /* @__PURE__ */ jsx(Typography, { children: getFormattedCountMessage() }),
3479
- /* @__PURE__ */ jsx(Box, { marginTop: 5, children: /* @__PURE__ */ jsx(
3480
- SelectedEntriesTableContent,
3481
- {
3482
- isPublishing: isSubmittingForm,
3483
- rowsToDisplay: rows,
3484
- entriesToPublish,
3485
- validationErrors
3486
- }
3487
- ) })
3488
- ] }),
3489
- /* @__PURE__ */ jsxs(Modal.Footer, { children: [
3490
- /* @__PURE__ */ jsx(Button, { onClick: toggleModal, variant: "tertiary", children: formatMessage({
3491
- id: "app.components.Button.cancel",
3492
- defaultMessage: "Cancel"
3493
- }) }),
3494
- /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
3495
- /* @__PURE__ */ jsx(Button, { onClick: refetch, variant: "tertiary", loading: isFetching, children: formatMessage({ id: "app.utils.refresh", defaultMessage: "Refresh" }) }),
3496
- /* @__PURE__ */ jsx(
3497
- Button,
3498
- {
3499
- onClick: toggleDialog,
3500
- disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
3501
- loading: isSubmittingForm,
3502
- children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
3503
- }
3504
- )
3505
- ] })
3506
- ] }),
3507
- /* @__PURE__ */ jsx(
3508
- ConfirmDialogPublishAll,
3509
- {
3510
- isOpen: isDialogOpen,
3511
- onToggleDialog: toggleDialog,
3512
- isConfirmButtonLoading: isSubmittingForm,
3513
- onConfirm: handleConfirmBulkPublish
3514
- }
3515
- )
3516
- ] });
3517
- };
3518
- const PublishAction = ({ documents, model }) => {
3519
- const { formatMessage } = useIntl();
3520
- const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
3521
- const showPublishButton = hasPublishPermission && documents.some(({ status }) => status !== "published");
3522
- const setListViewSelectedDocuments = useTable("publishAction", (state) => state.selectRow);
3523
- const refetchList = () => {
3524
- contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
3525
- };
3526
- if (!showPublishButton) return null;
3527
- return {
3528
- actionType: "publish",
3529
- variant: "tertiary",
3530
- label: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" }),
3531
- dialog: {
3532
- type: "modal",
3533
- title: formatMessage({
3534
- id: getTranslation("containers.ListPage.selectedEntriesModal.title"),
3535
- defaultMessage: "Publish entries"
3536
- }),
3537
- content: ({ onClose }) => {
3538
- return /* @__PURE__ */ jsx(Table.Root, { rows: documents, defaultSelectedRows: documents, headers: TABLE_HEADERS, children: /* @__PURE__ */ jsx(
3539
- SelectedEntriesModalContent,
3540
- {
3541
- listViewSelectedEntries: documents,
3542
- toggleModal: () => {
3543
- onClose();
3544
- refetchList();
3545
- },
3546
- setListViewSelectedDocuments,
3547
- model
3548
- }
3549
- ) });
3550
- },
3551
- onClose: () => {
3552
- refetchList();
3553
- }
3554
- }
3555
- };
3556
- };
3557
- const BulkActionsRenderer = () => {
3558
- const plugins = useStrapiApp("BulkActionsRenderer", (state) => state.plugins);
3559
- const { model, collectionType } = useDoc();
3560
- const { selectedRows } = useTable("BulkActionsRenderer", (state) => state);
3561
- return /* @__PURE__ */ jsx(Flex, { gap: 2, children: /* @__PURE__ */ jsx(
3562
- DescriptionComponentRenderer,
3563
- {
3564
- props: {
3565
- model,
3566
- collectionType,
3567
- documents: selectedRows
3568
- },
3569
- descriptions: plugins["content-manager"].apis.getBulkActions(),
3570
- children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsx(DocumentActionButton, { ...action }, action.id))
3571
- }
3572
- ) });
3573
- };
3574
- const DeleteAction = ({ documents, model }) => {
3575
- const { formatMessage } = useIntl();
3576
- const { schema: contentType } = useDoc();
3577
- const selectRow = useTable("DeleteAction", (state) => state.selectRow);
3578
- const hasI18nEnabled = Boolean(contentType?.pluginOptions?.i18n);
3579
- const [{ query }] = useQueryParams();
3580
- const params = React.useMemo(() => buildValidParams(query), [query]);
3581
- const hasDeletePermission = useDocumentRBAC("deleteAction", (state) => state.canDelete);
3582
- const { deleteMany: bulkDeleteAction } = useDocumentActions();
3583
- const documentIds = documents.map(({ documentId }) => documentId);
3584
- const handleConfirmBulkDelete = async () => {
3585
- const res = await bulkDeleteAction({
3586
- documentIds,
3587
- model,
3588
- params
3589
- });
3590
- if (!("error" in res)) {
3591
- selectRow([]);
3592
- }
3593
- };
3594
- if (!hasDeletePermission) return null;
3595
- return {
3596
- variant: "danger-light",
3597
- label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
3598
- dialog: {
3599
- type: "dialog",
3600
- title: formatMessage({
3601
- id: "app.components.ConfirmDialog.title",
3602
- defaultMessage: "Confirmation"
3603
- }),
3604
- content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3605
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3606
- /* @__PURE__ */ jsx(Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3607
- id: "popUpWarning.bodyMessage.contentType.delete.all",
3608
- defaultMessage: "Are you sure you want to delete these entries?"
3609
- }) }),
3610
- hasI18nEnabled && /* @__PURE__ */ jsx(Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsx(Typography, { textColor: "danger500", children: formatMessage(
3611
- {
3612
- id: getTranslation("Settings.list.actions.deleteAdditionalInfos"),
3613
- defaultMessage: "This will delete the active locale versions <em>(from Internationalization)</em>"
3614
- },
3615
- {
3616
- em: Emphasis
3617
- }
3618
- ) }) })
3619
- ] }),
3620
- onConfirm: handleConfirmBulkDelete
3621
- }
3622
- };
3623
- };
3624
- DeleteAction.type = "delete";
3625
- const UnpublishAction = ({ documents, model }) => {
3626
- const { formatMessage } = useIntl();
3627
- const { schema } = useDoc();
3628
- const selectRow = useTable("UnpublishAction", (state) => state.selectRow);
3629
- const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
3630
- const hasI18nEnabled = Boolean(schema?.pluginOptions?.i18n);
3631
- const hasDraftAndPublishEnabled = Boolean(schema?.options?.draftAndPublish);
3632
- const { unpublishMany: bulkUnpublishAction } = useDocumentActions();
3633
- const documentIds = documents.map(({ documentId }) => documentId);
3634
- const [{ query }] = useQueryParams();
3635
- const params = React.useMemo(() => buildValidParams(query), [query]);
3636
- const handleConfirmBulkUnpublish = async () => {
3637
- const data = await bulkUnpublishAction({ documentIds, model, params });
3638
- if (!("error" in data)) {
3639
- selectRow([]);
3640
- }
3641
- };
3642
- const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
3643
- if (!showUnpublishButton) return null;
3644
- return {
3645
- variant: "tertiary",
3646
- label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
3647
- dialog: {
3648
- type: "dialog",
3649
- title: formatMessage({
3650
- id: "app.components.ConfirmDialog.title",
3651
- defaultMessage: "Confirmation"
3652
- }),
3653
- content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3654
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3655
- /* @__PURE__ */ jsx(Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3656
- id: "popUpWarning.bodyMessage.contentType.unpublish.all",
3657
- defaultMessage: "Are you sure you want to unpublish these entries?"
3658
- }) }),
3659
- hasI18nEnabled && /* @__PURE__ */ jsx(Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsx(Typography, { textColor: "danger500", children: formatMessage(
3660
- {
3661
- id: getTranslation("Settings.list.actions.unpublishAdditionalInfos"),
3662
- defaultMessage: "This will unpublish the active locale versions <em>(from Internationalization)</em>"
3663
- },
3664
- {
3665
- em: Emphasis
3666
- }
3667
- ) }) })
3668
- ] }),
3669
- confirmButton: formatMessage({
3670
- id: "app.utils.unpublish",
3671
- defaultMessage: "Unpublish"
3672
- }),
3673
- onConfirm: handleConfirmBulkUnpublish
3674
- }
3675
- };
3676
- };
3677
- UnpublishAction.type = "unpublish";
3678
- const Emphasis = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", textColor: "danger500", children: chunks });
3679
- const DEFAULT_BULK_ACTIONS = [PublishAction, UnpublishAction, DeleteAction];
3680
- const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
3681
- const { formatMessage } = useIntl();
3682
- const getDefaultErrorMessage = (reason) => {
3683
- switch (reason) {
3684
- case "relation":
3685
- return "Duplicating the relation could remove it from the original entry.";
3686
- case "unique":
3687
- return "Identical values in a unique field are not allowed";
3688
- default:
3689
- return reason;
3690
- }
3691
- };
3692
- return /* @__PURE__ */ jsxs(Fragment, { children: [
3693
- /* @__PURE__ */ jsx(Typography, { variant: "beta", children: formatMessage({
3694
- id: getTranslation("containers.list.autoCloneModal.title"),
3695
- defaultMessage: "This entry can't be duplicated directly."
3696
- }) }),
3697
- /* @__PURE__ */ jsx(Box, { marginTop: 2, children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: formatMessage({
3698
- id: getTranslation("containers.list.autoCloneModal.description"),
3699
- defaultMessage: "A new entry will be created with the same content, but you'll have to change the following fields to save it."
3700
- }) }) }),
3701
- /* @__PURE__ */ jsx(Flex, { marginTop: 6, gap: 2, direction: "column", alignItems: "stretch", children: prohibitedFields.map(([fieldPath, reason]) => /* @__PURE__ */ jsxs(
3702
- Flex,
3703
- {
3704
- direction: "column",
3705
- gap: 2,
3706
- alignItems: "flex-start",
3707
- borderColor: "neutral200",
3708
- hasRadius: true,
3709
- padding: 6,
3710
- children: [
3711
- /* @__PURE__ */ jsx(Flex, { direction: "row", tag: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxs(Typography, { fontWeight: "semiBold", tag: "li", children: [
3712
- pathSegment,
3713
- index2 !== fieldPath.length - 1 && /* @__PURE__ */ jsx(
3714
- ChevronRight,
3715
- {
3716
- fill: "neutral500",
3717
- height: "0.8rem",
3718
- width: "0.8rem",
3719
- style: { margin: "0 0.8rem" }
3720
- }
3721
- )
3722
- ] }, index2)) }),
3723
- /* @__PURE__ */ jsx(Typography, { tag: "p", textColor: "neutral600", children: formatMessage({
3724
- id: getTranslation(`containers.list.autoCloneModal.error.${reason}`),
3725
- defaultMessage: getDefaultErrorMessage(reason)
3726
- }) })
3727
- ]
3728
- },
3729
- fieldPath.join()
3730
- )) })
3731
- ] });
3732
- };
3733
- const TableActions = ({ document }) => {
3734
- const { formatMessage } = useIntl();
3735
- const { model, collectionType } = useDoc();
3736
- const plugins = useStrapiApp("TableActions", (state) => state.plugins);
3737
- const props = {
3738
- activeTab: null,
3739
- model,
3740
- documentId: document.documentId,
3741
- collectionType,
3742
- document
3743
- };
3744
- return /* @__PURE__ */ jsx(
3745
- DescriptionComponentRenderer,
3746
- {
3747
- props,
3748
- descriptions: plugins["content-manager"].apis.getDocumentActions("table-row").filter((action) => action.name !== "PublishAction"),
3749
- children: (actions2) => {
3750
- const tableRowActions = actions2.filter((action) => {
3751
- const positions = Array.isArray(action.position) ? action.position : [action.position];
3752
- return positions.includes("table-row");
3753
- });
3754
- return /* @__PURE__ */ jsx(
3755
- DocumentActionsMenu,
3756
- {
3757
- actions: tableRowActions,
3758
- label: formatMessage({
3759
- id: "content-manager.containers.list.table.row-actions",
3760
- defaultMessage: "Row action"
3761
- }),
3762
- variant: "ghost"
3763
- }
3764
- );
3765
- }
3766
- }
3767
- );
3768
- };
3769
- const EditAction = ({ documentId }) => {
3770
- const navigate = useNavigate();
3771
- const { formatMessage } = useIntl();
3772
- const { canRead } = useDocumentRBAC("EditAction", ({ canRead: canRead2 }) => ({ canRead: canRead2 }));
3773
- const { toggleNotification } = useNotification();
3774
- const [{ query }] = useQueryParams();
3775
- return {
3776
- disabled: !canRead,
3777
- icon: /* @__PURE__ */ jsx(StyledPencil, {}),
3778
- label: formatMessage({
3779
- id: "content-manager.actions.edit.label",
3780
- defaultMessage: "Edit"
3781
- }),
3782
- position: "table-row",
3783
- onClick: async () => {
3784
- if (!documentId) {
3785
- console.error(
3786
- "You're trying to edit a document without an id, this is likely a bug with Strapi. Please open an issue."
3787
- );
3788
- toggleNotification({
3789
- message: formatMessage({
3790
- id: "content-manager.actions.edit.error",
3791
- defaultMessage: "An error occurred while trying to edit the document."
3792
- }),
3793
- type: "danger"
3794
- });
3795
- return;
3796
- }
3797
- navigate({
3798
- pathname: documentId,
3799
- search: stringify({
3800
- plugins: query.plugins
3801
- })
3802
- });
3803
- }
3804
- };
3805
- };
3806
- EditAction.type = "edit";
3807
- EditAction.position = "table-row";
3808
- const StyledPencil = styled(Pencil)`
3809
- path {
3810
- fill: currentColor;
3811
- }
3812
- `;
3813
- const CloneAction = ({ model, documentId }) => {
3814
- const navigate = useNavigate();
3815
- const { formatMessage } = useIntl();
3816
- const { canCreate } = useDocumentRBAC("CloneAction", ({ canCreate: canCreate2 }) => ({ canCreate: canCreate2 }));
3817
- const { toggleNotification } = useNotification();
3818
- const { autoClone } = useDocumentActions();
3819
- const [prohibitedFields, setProhibitedFields] = React.useState([]);
3820
- return {
3821
- disabled: !canCreate,
3822
- icon: /* @__PURE__ */ jsx(StyledDuplicate, {}),
3823
- label: formatMessage({
3824
- id: "content-manager.actions.clone.label",
3825
- defaultMessage: "Duplicate"
3826
- }),
3827
- position: "table-row",
3828
- onClick: async () => {
3829
- if (!documentId) {
3830
- console.error(
3831
- "You're trying to clone a document in the table without an id, this is likely a bug with Strapi. Please open an issue."
3832
- );
3833
- toggleNotification({
3834
- message: formatMessage({
3835
- id: "content-manager.actions.clone.error",
3836
- defaultMessage: "An error occurred while trying to clone the document."
3837
- }),
3838
- type: "danger"
3839
- });
3840
- return;
3841
- }
3842
- const res = await autoClone({ model, sourceId: documentId });
3843
- if ("data" in res) {
3844
- navigate(res.data.documentId);
3845
- return true;
3846
- }
3847
- if (isBaseQueryError(res.error) && res.error.details && typeof res.error.details === "object" && "prohibitedFields" in res.error.details && Array.isArray(res.error.details.prohibitedFields)) {
3848
- const prohibitedFields2 = res.error.details.prohibitedFields;
3849
- setProhibitedFields(prohibitedFields2);
3850
- }
3851
- },
3852
- dialog: {
3853
- type: "modal",
3854
- title: formatMessage({
3855
- id: "content-manager.containers.list.autoCloneModal.header",
3856
- defaultMessage: "Duplicate"
3857
- }),
3858
- content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
3859
- footer: ({ onClose }) => {
3860
- return /* @__PURE__ */ jsxs(Modal.Footer, { children: [
3861
- /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
3862
- id: "cancel",
3863
- defaultMessage: "Cancel"
3864
- }) }),
3865
- /* @__PURE__ */ jsx(
3866
- LinkButton,
3867
- {
3868
- tag: NavLink,
3869
- to: {
3870
- pathname: `clone/${documentId}`
3871
- },
3872
- children: formatMessage({
3873
- id: "content-manager.containers.list.autoCloneModal.create",
3874
- defaultMessage: "Create"
3875
- })
3876
- }
3877
- )
3878
- ] });
3879
- }
3880
- }
3881
- };
3882
- };
3883
- CloneAction.type = "clone";
3884
- CloneAction.position = "table-row";
3885
- const StyledDuplicate = styled(Duplicate)`
3886
- path {
3887
- fill: currentColor;
3888
- }
3889
- `;
3890
- const DEFAULT_TABLE_ROW_ACTIONS = [EditAction, CloneAction];
3891
- class ContentManagerPlugin {
3892
- /**
3893
- * The following properties are the stored ones provided by any plugins registering with
3894
- * the content-manager. The function calls however, need to be called at runtime in the
3895
- * application, so instead we collate them and run them later with the complete list incl.
3896
- * ones already registered & the context of the view.
3897
- */
3898
- bulkActions = [...DEFAULT_BULK_ACTIONS];
3899
- documentActions = [
3900
- ...DEFAULT_ACTIONS,
3901
- ...DEFAULT_TABLE_ROW_ACTIONS,
3902
- ...DEFAULT_HEADER_ACTIONS
3903
- ];
3904
- editViewSidePanels = [ActionsPanel];
3905
- headerActions = [];
3906
- constructor() {
3907
- }
3908
- addEditViewSidePanel(panels) {
3909
- if (Array.isArray(panels)) {
3910
- this.editViewSidePanels = [...this.editViewSidePanels, ...panels];
3911
- } else if (typeof panels === "function") {
3912
- this.editViewSidePanels = panels(this.editViewSidePanels);
3913
- } else {
3914
- throw new Error(
3915
- `Expected the \`panels\` passed to \`addEditViewSidePanel\` to be an array or a function, but received ${getPrintableType(
3916
- panels
3917
- )}`
3918
- );
3919
- }
3920
- }
3921
- addDocumentAction(actions2) {
3922
- if (Array.isArray(actions2)) {
3923
- this.documentActions = [...this.documentActions, ...actions2];
3924
- } else if (typeof actions2 === "function") {
3925
- this.documentActions = actions2(this.documentActions);
3926
- } else {
3927
- throw new Error(
3928
- `Expected the \`actions\` passed to \`addDocumentAction\` to be an array or a function, but received ${getPrintableType(
3929
- actions2
3930
- )}`
3931
- );
3932
- }
3933
- }
3934
- addDocumentHeaderAction(actions2) {
3935
- if (Array.isArray(actions2)) {
3936
- this.headerActions = [...this.headerActions, ...actions2];
3937
- } else if (typeof actions2 === "function") {
3938
- this.headerActions = actions2(this.headerActions);
3939
- } else {
3940
- throw new Error(
3941
- `Expected the \`actions\` passed to \`addDocumentHeaderAction\` to be an array or a function, but received ${getPrintableType(
3942
- actions2
3943
- )}`
3944
- );
3945
- }
3946
- }
3947
- addBulkAction(actions2) {
3948
- if (Array.isArray(actions2)) {
3949
- this.bulkActions = [...this.bulkActions, ...actions2];
3950
- } else if (typeof actions2 === "function") {
3951
- this.bulkActions = actions2(this.bulkActions);
3952
- } else {
3953
- throw new Error(
3954
- `Expected the \`actions\` passed to \`addBulkAction\` to be an array or a function, but received ${getPrintableType(
3955
- actions2
3956
- )}`
3957
- );
3958
- }
3959
- }
3960
- get config() {
3961
- return {
3962
- id: PLUGIN_ID,
3963
- name: "Content Manager",
3964
- injectionZones: INJECTION_ZONES,
3965
- apis: {
3966
- addBulkAction: this.addBulkAction.bind(this),
3967
- addDocumentAction: this.addDocumentAction.bind(this),
3968
- addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
3969
- addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
3970
- getBulkActions: () => this.bulkActions,
3971
- getDocumentActions: (position) => {
3972
- if (position) {
3973
- return this.documentActions.filter(
3974
- (action) => action.position == void 0 || [action.position].flat().includes(position)
3975
- );
3976
- }
3977
- return this.documentActions;
3978
- },
3979
- getEditViewSidePanels: () => this.editViewSidePanels,
3980
- getHeaderActions: () => this.headerActions
3981
- }
3982
- };
3983
- }
3984
- }
3985
- const getPrintableType = (value) => {
3986
- const nativeType = typeof value;
3987
- if (nativeType === "object") {
3988
- if (value === null) return "null";
3989
- if (Array.isArray(value)) return "array";
3990
- if (value instanceof Object && value.constructor.name !== "Object") {
3991
- return value.constructor.name;
3992
- }
3993
- }
3994
- return nativeType;
3995
- };
3996
- const HistoryAction = ({ model, document }) => {
3997
- const { formatMessage } = useIntl();
3998
- const [{ query }] = useQueryParams();
3999
- const navigate = useNavigate();
4000
- const { trackUsage } = useTracking();
4001
- const { pathname } = useLocation();
4002
- const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
4003
- if (!window.strapi.features.isEnabled("cms-content-history")) {
4004
- return null;
4005
- }
4006
- const handleOnClick = () => {
4007
- const destination = { pathname: "history", search: pluginsQueryParams };
4008
- trackUsage("willNavigate", {
4009
- from: pathname,
4010
- to: `${pathname}/${destination.pathname}`
4011
- });
4012
- navigate(destination);
4013
- };
4014
- return {
4015
- icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
4016
- label: formatMessage({
4017
- id: "content-manager.history.document-action",
4018
- defaultMessage: "Content History"
4019
- }),
4020
- onClick: handleOnClick,
4021
- disabled: (
4022
- /**
4023
- * The user is creating a new document.
4024
- * It hasn't been saved yet, so there's no history to go to
4025
- */
4026
- !document || /**
4027
- * The document has been created but the current dimension has never been saved.
4028
- * For example, the user is creating a new locale in an existing document,
4029
- * so there's no history for the document in that locale
4030
- */
4031
- !document.id || /**
4032
- * History is only available for content types created by the user.
4033
- * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
4034
- * which start with `admin::` or `plugin::`
4035
- */
4036
- !model.startsWith("api::")
4037
- ),
4038
- position: "header"
4039
- };
4040
- };
4041
- HistoryAction.type = "history";
4042
- HistoryAction.position = "header";
4043
- const historyAdmin = {
4044
- bootstrap(app) {
4045
- const { addDocumentAction } = app.getPlugin("content-manager").apis;
4046
- addDocumentAction((actions2) => {
4047
- const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
4048
- actions2.splice(indexOfDeleteAction, 0, HistoryAction);
4049
- return actions2;
4050
- });
4051
- }
4052
- };
4053
- const initialState = {
4054
- collectionTypeLinks: [],
4055
- components: [],
4056
- fieldSizes: {},
4057
- models: [],
4058
- singleTypeLinks: [],
4059
- isLoading: true
4060
- };
4061
- const appSlice = createSlice({
4062
- name: "app",
4063
- initialState,
4064
- reducers: {
4065
- setInitialData(state, action) {
4066
- const {
4067
- authorizedCollectionTypeLinks,
4068
- authorizedSingleTypeLinks,
4069
- components,
4070
- contentTypeSchemas,
4071
- fieldSizes
4072
- } = action.payload;
4073
- state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
4074
- ({ isDisplayed }) => isDisplayed
4075
- );
4076
- state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
4077
- state.components = components;
4078
- state.models = contentTypeSchemas;
4079
- state.fieldSizes = fieldSizes;
4080
- state.isLoading = false;
4081
- }
4082
- }
4083
- });
4084
- const { actions, reducer: reducer$1 } = appSlice;
4085
- const { setInitialData } = actions;
4086
- const reducer = combineReducers({
4087
- app: reducer$1
4088
- });
4089
- const previewApi = contentManagerApi.injectEndpoints({
4090
- endpoints: (builder) => ({
4091
- getPreviewUrl: builder.query({
4092
- query({ query, params }) {
4093
- return {
4094
- url: `/content-manager/preview/url/${params.contentType}`,
4095
- method: "GET",
4096
- config: {
4097
- params: query
4098
- }
4099
- };
4100
- }
4101
- })
4102
- })
4103
- });
4104
- const { useGetPreviewUrlQuery } = previewApi;
4105
- const ConditionalTooltip = ({ isShown, label, children }) => {
4106
- if (isShown) {
4107
- return /* @__PURE__ */ jsx(Tooltip, { label, children });
4108
- }
4109
- return children;
4110
- };
4111
- const PreviewSidePanel = ({ model, documentId, document }) => {
4112
- const { formatMessage } = useIntl();
4113
- const { trackUsage } = useTracking();
4114
- const { pathname } = useLocation();
4115
- const [{ query }] = useQueryParams();
4116
- const isModified = useForm("PreviewSidePanel", (state) => state.modified);
4117
- const { data, error } = useGetPreviewUrlQuery({
4118
- params: {
4119
- contentType: model
4120
- },
4121
- query: {
4122
- documentId,
4123
- locale: document?.locale,
4124
- status: document?.status
4125
- }
4126
- });
4127
- if (!data?.data?.url || error) {
4128
- return null;
4129
- }
4130
- const trackNavigation = () => {
4131
- const destinationPathname = pathname.replace(/\/$/, "") + "/preview";
4132
- trackUsage("willNavigate", { from: pathname, to: destinationPathname });
4133
- };
4134
- return {
4135
- title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
4136
- content: /* @__PURE__ */ jsx(
4137
- ConditionalTooltip,
4138
- {
4139
- label: formatMessage({
4140
- id: "content-manager.preview.panel.button-disabled-tooltip",
4141
- defaultMessage: "Please save to open the preview"
4142
- }),
4143
- isShown: isModified,
4144
- children: /* @__PURE__ */ jsx(Box, { cursor: "not-allowed", width: "100%", children: /* @__PURE__ */ jsx(
4145
- Button,
4146
- {
4147
- variant: "tertiary",
4148
- tag: Link,
4149
- to: { pathname: "preview", search: stringify(query, { encode: false }) },
4150
- onClick: trackNavigation,
4151
- width: "100%",
4152
- disabled: isModified,
4153
- pointerEvents: isModified ? "none" : void 0,
4154
- tabIndex: isModified ? -1 : void 0,
4155
- children: formatMessage({
4156
- id: "content-manager.preview.panel.button",
4157
- defaultMessage: "Open preview"
4158
- })
4159
- }
4160
- ) })
4161
- }
4162
- )
4163
- };
4164
- };
4165
- const previewAdmin = {
4166
- bootstrap(app) {
4167
- const contentManagerPluginApis = app.getPlugin("content-manager").apis;
4168
- contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
4169
- }
4170
- };
4171
- const index = {
4172
- register(app) {
4173
- const cm = new ContentManagerPlugin();
4174
- app.addReducers({
4175
- [PLUGIN_ID]: reducer
4176
- });
4177
- app.addMenuLink({
4178
- to: PLUGIN_ID,
4179
- icon: Feather,
4180
- intlLabel: {
4181
- id: `content-manager.plugin.name`,
4182
- defaultMessage: "Content Manager"
4183
- },
4184
- permissions: [],
4185
- position: 1
4186
- });
4187
- app.router.addRoute({
4188
- path: "content-manager/*",
4189
- lazy: async () => {
4190
- const { Layout } = await import("./layout-C71zeI19.mjs");
4191
- return {
4192
- Component: Layout
4193
- };
4194
- },
4195
- children: routes
4196
- });
4197
- app.registerPlugin(cm.config);
4198
- },
4199
- bootstrap(app) {
4200
- if (typeof historyAdmin.bootstrap === "function") {
4201
- historyAdmin.bootstrap(app);
4202
- }
4203
- if (typeof previewAdmin.bootstrap === "function") {
4204
- previewAdmin.bootstrap(app);
4205
- }
4206
- },
4207
- async registerTrads({ locales }) {
4208
- const importedTrads = await Promise.all(
4209
- locales.map((locale) => {
4210
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => import("./ar-CCEVvqGG.mjs"), "./translations/ca.json": () => import("./ca-5U32ON2v.mjs"), "./translations/cs.json": () => import("./cs-CM2aBUar.mjs"), "./translations/de.json": () => import("./de-C72KDNOl.mjs"), "./translations/en.json": () => import("./en-CSxLmrh1.mjs"), "./translations/es.json": () => import("./es-D34tqjMw.mjs"), "./translations/eu.json": () => import("./eu-CdALomew.mjs"), "./translations/fr.json": () => import("./fr--pg5jUbt.mjs"), "./translations/gu.json": () => import("./gu-CNpaMDpH.mjs"), "./translations/hi.json": () => import("./hi-Dwvd04m3.mjs"), "./translations/hu.json": () => import("./hu-CeYvaaO0.mjs"), "./translations/id.json": () => import("./id-BtwA9WJT.mjs"), "./translations/it.json": () => import("./it-BrVPqaf1.mjs"), "./translations/ja.json": () => import("./ja-BHqhDq4V.mjs"), "./translations/ko.json": () => import("./ko-HVQRlfUI.mjs"), "./translations/ml.json": () => import("./ml-BihZwQit.mjs"), "./translations/ms.json": () => import("./ms-m_WjyWx7.mjs"), "./translations/nl.json": () => import("./nl-D4R9gHx5.mjs"), "./translations/pl.json": () => import("./pl-sbx9mSt_.mjs"), "./translations/pt-BR.json": () => import("./pt-BR-C71iDxnh.mjs"), "./translations/pt.json": () => import("./pt-BsaFvS8-.mjs"), "./translations/ru.json": () => import("./ru-BE6A4Exp.mjs"), "./translations/sa.json": () => import("./sa-Dag0k-Z8.mjs"), "./translations/sk.json": () => import("./sk-BFg-R8qJ.mjs"), "./translations/sv.json": () => import("./sv-CUnfWGsh.mjs"), "./translations/th.json": () => import("./th-BqbI8lIT.mjs"), "./translations/tr.json": () => import("./tr-CgeK3wJM.mjs"), "./translations/uk.json": () => import("./uk-CR-zDhAY.mjs"), "./translations/vi.json": () => import("./vi-DUXIk_fw.mjs"), "./translations/zh-Hans.json": () => import("./zh-Hans-BPQcRIyH.mjs"), "./translations/zh.json": () => import("./zh-BWZspA60.mjs") }), `./translations/${locale}.json`, 3).then(({ default: data }) => {
4211
- return {
4212
- data: prefixPluginTranslations(data, PLUGIN_ID),
4213
- locale
4214
- };
4215
- }).catch(() => {
4216
- return {
4217
- data: {},
4218
- locale
4219
- };
4220
- });
4221
- })
4222
- );
4223
- return Promise.resolve(importedTrads);
4224
- }
4225
- };
4226
- export {
4227
- ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD as A,
4228
- BulkActionsRenderer as B,
4229
- COLLECTION_TYPES as C,
4230
- DocumentStatus as D,
4231
- extractContentTypeComponents as E,
4232
- DEFAULT_SETTINGS as F,
4233
- convertEditLayoutToFieldLayouts as G,
4234
- HOOKS as H,
4235
- InjectionZone as I,
4236
- useDocument as J,
4237
- useGetPreviewUrlQuery as K,
4238
- index as L,
4239
- useContentManagerContext as M,
4240
- useDocumentActions as N,
4241
- Panels as P,
4242
- RelativeTime as R,
4243
- SINGLE_TYPES as S,
4244
- TableActions as T,
4245
- useGetInitialDataQuery as a,
4246
- useGetAllContentTypeSettingsQuery as b,
4247
- useDoc as c,
4248
- buildValidParams as d,
4249
- contentManagerApi as e,
4250
- useDocumentRBAC as f,
4251
- getTranslation as g,
4252
- useDocumentLayout as h,
4253
- createYupSchema as i,
4254
- Header as j,
4255
- PERMISSIONS as k,
4256
- DocumentRBAC as l,
4257
- DOCUMENT_META_FIELDS as m,
4258
- CLONE_PATH as n,
4259
- useDocLayout as o,
4260
- useGetContentTypeConfigurationQuery as p,
4261
- CREATOR_FIELDS as q,
4262
- getMainField as r,
4263
- setInitialData as s,
4264
- getDisplayName as t,
4265
- useContentTypeSchema as u,
4266
- checkIfAttributeIsDisplayable as v,
4267
- useGetAllDocumentsQuery as w,
4268
- convertListLayoutToFieldLayouts as x,
4269
- capitalise as y,
4270
- useUpdateContentTypeConfigurationMutation as z
4271
- };
4272
- //# sourceMappingURL=index-B3tHjkLZ.mjs.map