@strapi/admin 4.12.0-beta.0 → 4.12.0-beta.3

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 (226) hide show
  1. package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +1 -3
  2. package/admin/src/content-manager/components/RelationInput/components/Option.js +6 -5
  3. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +7 -7
  4. package/admin/src/content-manager/pages/EditSettingsView/components/DisplayedFields.js +23 -21
  5. package/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js +21 -23
  6. package/admin/src/content-manager/pages/EditView/Information/index.js +1 -1
  7. package/admin/src/content-manager/pages/EditView/InformationBox/InformationBoxCE.js +1 -2
  8. package/admin/src/content-manager/pages/EditView/InformationBox/index.js +1 -3
  9. package/admin/src/content-manager/pages/EditView/index.js +14 -2
  10. package/admin/src/content-manager/pages/ListSettingsView/components/SortDisplayedFields.js +24 -22
  11. package/admin/src/content-manager/pages/ListView/components/Body/index.js +191 -0
  12. package/admin/src/content-manager/pages/ListView/components/BulkActionButtons/ConfirmBulkActionDialog/index.js +164 -0
  13. package/admin/src/content-manager/pages/ListView/components/BulkActionButtons/SelectedEntriesModal/index.js +468 -0
  14. package/admin/src/content-manager/{components/DynamicTable/BulkActionsBar → pages/ListView/components/BulkActionButtons}/index.js +56 -132
  15. package/admin/src/content-manager/pages/ListView/components/CellContent/RelationMultiple/index.js +63 -69
  16. package/admin/src/content-manager/pages/ListView/components/CellContent/RepeatableComponent/index.js +28 -21
  17. package/admin/src/content-manager/pages/ListView/index.js +191 -132
  18. package/admin/src/hooks/useSettingsMenu/index.js +35 -21
  19. package/admin/src/layouts/UnauthenticatedLayout/LocaleToggle/index.js +7 -7
  20. package/admin/src/pages/AuthPage/components/Login/index.js +3 -5
  21. package/admin/src/pages/AuthPage/constants.js +3 -2
  22. package/admin/src/pages/AuthPage/index.js +18 -1
  23. package/admin/src/pages/HomePage/index.js +19 -7
  24. package/admin/src/pages/ProfilePage/index.js +6 -11
  25. package/admin/src/pages/SettingsPage/components/SettingsNav/index.js +13 -11
  26. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js +17 -1
  27. package/admin/src/pages/SettingsPage/pages/Users/EditPage/index.js +15 -2
  28. package/admin/src/pages/SettingsPage/pages/Users/ListPage/CreateAction/index.js +2 -4
  29. package/admin/src/pages/SettingsPage/pages/Users/ListPage/ModalForm/index.js +15 -1
  30. package/admin/src/pages/SettingsPage/pages/Users/ListPage/index.js +36 -5
  31. package/admin/src/pages/SettingsPage/pages/Users/components/MagicLink/index.js +3 -5
  32. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/EventTable/index.js +1 -3
  33. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/WebhookForm/index.js +16 -1
  34. package/admin/src/translations/ca.json +4 -4
  35. package/admin/src/translations/de.json +4 -4
  36. package/admin/src/translations/dk.json +2 -2
  37. package/admin/src/translations/en.json +23 -4
  38. package/admin/src/translations/es.json +4 -4
  39. package/admin/src/translations/eu.json +4 -4
  40. package/admin/src/translations/fr.json +2 -2
  41. package/admin/src/translations/gu.json +4 -4
  42. package/admin/src/translations/hi.json +4 -4
  43. package/admin/src/translations/hu.json +4 -4
  44. package/admin/src/translations/ja.json +2 -2
  45. package/admin/src/translations/ko.json +2 -2
  46. package/admin/src/translations/ml.json +4 -4
  47. package/admin/src/translations/nl.json +4 -4
  48. package/admin/src/translations/pl.json +4 -4
  49. package/admin/src/translations/pt-BR.json +4 -4
  50. package/admin/src/translations/ru.json +4 -4
  51. package/admin/src/translations/sa.json +4 -4
  52. package/admin/src/translations/sk.json +4 -4
  53. package/admin/src/translations/sv.json +4 -4
  54. package/admin/src/translations/tr.json +4 -4
  55. package/admin/src/translations/zh-Hans.json +4 -4
  56. package/admin/src/translations/zh.json +4 -4
  57. package/build/1049.758a01f5.chunk.js +1 -0
  58. package/build/{3528.4845cf92.chunk.js → 1386.762d6eb8.chunk.js} +1 -1
  59. package/build/1727.b49f0713.chunk.js +1 -0
  60. package/build/{5563.a146acac.chunk.js → 2225.15d1df72.chunk.js} +2 -2
  61. package/build/2379.d33a2e16.chunk.js +1 -0
  62. package/build/2395.b0419a54.chunk.js +26 -0
  63. package/build/2801.18f38baf.chunk.js +1 -0
  64. package/build/{7394.423886bd.chunk.js → 3100.21c343fa.chunk.js} +1 -1
  65. package/build/311.cb0884bb.chunk.js +1 -0
  66. package/build/3483.ddd2d6df.chunk.js +1 -0
  67. package/build/{970.89601f27.chunk.js → 3739.63e352f1.chunk.js} +52 -20
  68. package/build/3984.ea7b8036.chunk.js +1 -0
  69. package/build/4546.ff9fdf30.chunk.js +1 -0
  70. package/build/502.ccb38223.chunk.js +1 -0
  71. package/build/5483.ed2c7efa.chunk.js +6 -0
  72. package/build/{5542.c62d0daf.chunk.js → 5542.2415a393.chunk.js} +6 -6
  73. package/build/6158.c974fd83.chunk.js +1 -0
  74. package/build/6691.f880a0b6.chunk.js +105 -0
  75. package/build/7030.b98dcedf.chunk.js +1 -0
  76. package/build/7464.c6d0565c.chunk.js +1 -0
  77. package/build/8276.23e0763b.chunk.js +26 -0
  78. package/build/8298.fd253c9f.chunk.js +117 -0
  79. package/build/918.54414509.chunk.js +1 -0
  80. package/build/{9932.7e2b71de.chunk.js → 9806.91360bb6.chunk.js} +79 -79
  81. package/build/{9944.29289a16.chunk.js → 9944.7af075a5.chunk.js} +1 -1
  82. package/build/{Admin-authenticatedApp.9d3afb79.chunk.js → Admin-authenticatedApp.36b3826c.chunk.js} +5 -5
  83. package/build/Admin_InternalErrorPage.f45f2462.chunk.js +1 -0
  84. package/build/{Admin_homePage.be30ef4e.chunk.js → Admin_homePage.ac9dfb86.chunk.js} +23 -15
  85. package/build/{Admin_marketplace.74a58e20.chunk.js → Admin_marketplace.f0b87fce.chunk.js} +1 -1
  86. package/build/{Admin_pluginsPage.ce464189.chunk.js → Admin_pluginsPage.8728ff6e.chunk.js} +1 -1
  87. package/build/{Admin_profilePage.2131eb68.chunk.js → Admin_profilePage.a968035f.chunk.js} +2 -2
  88. package/build/Admin_settingsPage.8c600d1a.chunk.js +111 -0
  89. package/build/Upload_ConfigureTheView.345ac1e0.chunk.js +1 -0
  90. package/build/admin-app.1c3f7fd6.chunk.js +36 -0
  91. package/build/{admin-edit-roles-page.3fdd6b9d.chunk.js → admin-edit-roles-page.a49b9f4f.chunk.js} +4 -4
  92. package/build/admin-edit-users.67704088.chunk.js +10 -0
  93. package/build/{admin-roles-list.e17b00d7.chunk.js → admin-roles-list.0c129e98.chunk.js} +1 -1
  94. package/build/admin-users.3279ffb0.chunk.js +11 -0
  95. package/build/api-tokens-create-page.46c2ea84.chunk.js +1 -0
  96. package/build/{api-tokens-edit-page.9a1dd2fa.chunk.js → api-tokens-edit-page.58139df9.chunk.js} +1 -1
  97. package/build/{api-tokens-list-page.a103f526.chunk.js → api-tokens-list-page.505bf7e0.chunk.js} +2 -2
  98. package/build/audit-logs-settings-page.4b422831.chunk.js +1 -0
  99. package/build/{ca-json.1fed5d8b.chunk.js → ca-json.a53c10b6.chunk.js} +1 -1
  100. package/build/content-manager.b8d593d4.chunk.js +1103 -0
  101. package/build/{content-type-builder-list-view.a200a358.chunk.js → content-type-builder-list-view.bf9be456.chunk.js} +9 -9
  102. package/build/{content-type-builder-translation-ar-json.56d8fcf4.chunk.js → content-type-builder-translation-ar-json.3e808e2f.chunk.js} +1 -1
  103. package/build/{content-type-builder-translation-cs-json.a5b299ca.chunk.js → content-type-builder-translation-cs-json.1ef9e106.chunk.js} +1 -1
  104. package/build/{content-type-builder-translation-de-json.393a76c0.chunk.js → content-type-builder-translation-de-json.63fcff7b.chunk.js} +1 -1
  105. package/build/{content-type-builder-translation-dk-json.fbd39bb7.chunk.js → content-type-builder-translation-dk-json.fd626b67.chunk.js} +1 -1
  106. package/build/{content-type-builder-translation-en-json.38e20391.chunk.js → content-type-builder-translation-en-json.ed29ff4d.chunk.js} +1 -1
  107. package/build/{content-type-builder-translation-es-json.9288474b.chunk.js → content-type-builder-translation-es-json.a4a361a9.chunk.js} +1 -1
  108. package/build/{content-type-builder-translation-fr-json.d35e269c.chunk.js → content-type-builder-translation-fr-json.499c3a46.chunk.js} +1 -1
  109. package/build/{content-type-builder-translation-id-json.f0513929.chunk.js → content-type-builder-translation-id-json.65255f93.chunk.js} +1 -1
  110. package/build/{content-type-builder-translation-it-json.aaf16753.chunk.js → content-type-builder-translation-it-json.e268ab74.chunk.js} +1 -1
  111. package/build/{content-type-builder-translation-ko-json.8fe21a7f.chunk.js → content-type-builder-translation-ko-json.04cb309d.chunk.js} +1 -1
  112. package/build/{content-type-builder-translation-ms-json.3b5d2d3e.chunk.js → content-type-builder-translation-ms-json.f6b743b9.chunk.js} +1 -1
  113. package/build/{content-type-builder-translation-nl-json.225ef5d3.chunk.js → content-type-builder-translation-nl-json.997fe8cc.chunk.js} +1 -1
  114. package/build/{content-type-builder-translation-pl-json.92f36be2.chunk.js → content-type-builder-translation-pl-json.634f638b.chunk.js} +1 -1
  115. package/build/{content-type-builder-translation-pt-BR-json.3bd10f89.chunk.js → content-type-builder-translation-pt-BR-json.6a95dc71.chunk.js} +1 -1
  116. package/build/{content-type-builder-translation-ru-json.9bfe47ce.chunk.js → content-type-builder-translation-ru-json.3af65503.chunk.js} +1 -1
  117. package/build/{content-type-builder-translation-sk-json.d03cc18a.chunk.js → content-type-builder-translation-sk-json.c6078082.chunk.js} +1 -1
  118. package/build/{content-type-builder-translation-sv-json.d23dcd32.chunk.js → content-type-builder-translation-sv-json.a6df2462.chunk.js} +1 -1
  119. package/build/{content-type-builder-translation-th-json.7ad256e2.chunk.js → content-type-builder-translation-th-json.122277cc.chunk.js} +1 -1
  120. package/build/{content-type-builder-translation-tr-json.926f6191.chunk.js → content-type-builder-translation-tr-json.41f44f77.chunk.js} +1 -1
  121. package/build/{content-type-builder-translation-uk-json.7bf19546.chunk.js → content-type-builder-translation-uk-json.e1315acd.chunk.js} +1 -1
  122. package/build/{content-type-builder-translation-zh-Hans-json.415577fb.chunk.js → content-type-builder-translation-zh-Hans-json.6ff57db6.chunk.js} +1 -1
  123. package/build/{content-type-builder-translation-zh-json.ad24dbeb.chunk.js → content-type-builder-translation-zh-json.3532b962.chunk.js} +1 -1
  124. package/build/content-type-builder.40534de5.chunk.js +170 -0
  125. package/build/{de-json.fcac7381.chunk.js → de-json.b3be02c7.chunk.js} +1 -1
  126. package/build/{dk-json.e34cad0d.chunk.js → dk-json.842aa391.chunk.js} +1 -1
  127. package/build/{email-settings-page.45695daa.chunk.js → email-settings-page.d494d1eb.chunk.js} +2 -2
  128. package/build/{en-json.fb9f6ddd.chunk.js → en-json.4c733bd1.chunk.js} +1 -1
  129. package/build/{es-json.42096084.chunk.js → es-json.f57b5335.chunk.js} +1 -1
  130. package/build/{eu-json.fb17c8f9.chunk.js → eu-json.633025f0.chunk.js} +1 -1
  131. package/build/{fr-json.69789980.chunk.js → fr-json.aa8839d2.chunk.js} +1 -1
  132. package/build/{gu-json.4d667d0c.chunk.js → gu-json.5bd62812.chunk.js} +1 -1
  133. package/build/{hi-json.323be97d.chunk.js → hi-json.9104eb78.chunk.js} +1 -1
  134. package/build/{hu-json.fe71e6c8.chunk.js → hu-json.9f4aae42.chunk.js} +1 -1
  135. package/build/{i18n-settings-page.29308d0b.chunk.js → i18n-settings-page.47f78016.chunk.js} +1 -1
  136. package/build/index.html +1 -1
  137. package/build/{ja-json.81b6d1e3.chunk.js → ja-json.91286391.chunk.js} +1 -1
  138. package/build/{ko-json.4539f4ba.chunk.js → ko-json.fcf3ec4b.chunk.js} +1 -1
  139. package/build/main.a12c4c0f.js +2856 -0
  140. package/build/{ml-json.8988e374.chunk.js → ml-json.557aa14c.chunk.js} +1 -1
  141. package/build/{nl-json.98345913.chunk.js → nl-json.b2b16eea.chunk.js} +1 -1
  142. package/build/{pl-json.59a5dab3.chunk.js → pl-json.f094a417.chunk.js} +1 -1
  143. package/build/{pt-BR-json.9410688b.chunk.js → pt-BR-json.dec7fb01.chunk.js} +1 -1
  144. package/build/review-workflows-settings-create-view.dfd87e1f.chunk.js +1 -0
  145. package/build/review-workflows-settings-edit-view.53c00afe.chunk.js +1 -0
  146. package/build/review-workflows-settings-list-view.a34be805.chunk.js +56 -0
  147. package/build/{ru-json.678cd48b.chunk.js → ru-json.8193d8c4.chunk.js} +1 -1
  148. package/build/{runtime~main.5e9bf4b3.js → runtime~main.d197f488.js} +2 -2
  149. package/build/{sa-json.6359a11c.chunk.js → sa-json.a56836f1.chunk.js} +1 -1
  150. package/build/{sk-json.2374f129.chunk.js → sk-json.bf2f057a.chunk.js} +1 -1
  151. package/build/sso-settings-page.ed6f3f15.chunk.js +1 -0
  152. package/build/{sv-json.ae6e71ea.chunk.js → sv-json.fd0e86c6.chunk.js} +1 -1
  153. package/build/{tr-json.bac5dbd3.chunk.js → tr-json.56c32cf6.chunk.js} +1 -1
  154. package/build/transfer-tokens-create-page.1597e6ab.chunk.js +1 -0
  155. package/build/transfer-tokens-edit-page.8741529f.chunk.js +1 -0
  156. package/build/{transfer-tokens-list-page.7237443d.chunk.js → transfer-tokens-list-page.22147d2c.chunk.js} +2 -2
  157. package/build/upload-settings.cac210a0.chunk.js +14 -0
  158. package/build/upload.cbfeefa5.chunk.js +58 -0
  159. package/build/{users-advanced-settings-page.750b1f76.chunk.js → users-advanced-settings-page.18379a56.chunk.js} +1 -1
  160. package/build/users-email-settings-page.a87978e5.chunk.js +9 -0
  161. package/build/users-providers-settings-page.8876c1ee.chunk.js +14 -0
  162. package/build/{users-roles-settings-page.d286426a.chunk.js → users-roles-settings-page.0431f48c.chunk.js} +2 -2
  163. package/build/webhook-edit-page.a91f27a1.chunk.js +33 -0
  164. package/build/{webhook-list-page.940a40f1.chunk.js → webhook-list-page.65e1b5bb.chunk.js} +1 -1
  165. package/build/{zh-Hans-json.fada6f40.chunk.js → zh-Hans-json.36d81cdc.chunk.js} +1 -1
  166. package/build/{zh-json.3529f1e5.chunk.js → zh-json.1cc86ff0.chunk.js} +1 -1
  167. package/ee/admin/content-manager/pages/EditView/InformationBox/InformationBoxEE.js +6 -3
  168. package/ee/admin/content-manager/pages/EditView/InformationBox/index.js +1 -3
  169. package/ee/admin/content-manager/pages/ListView/ReviewWorkflowsColumn/constants.js +2 -2
  170. package/ee/admin/pages/AuthPage/components/Login/index.js +3 -5
  171. package/ee/admin/pages/HomePage/index.js +11 -0
  172. package/ee/admin/pages/SettingsPage/pages/ApplicationInfosPage/components/AdminSeatInfo/index.js +1 -3
  173. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/ProtectedPage/ProtectedPage.js +1 -1
  174. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/Stage.js +1 -1
  175. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/CreateView/CreateView.js +38 -10
  176. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/EditView/EditView.js +57 -8
  177. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/ListView/ListView.js +3 -3
  178. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/utils/{getWorkflowValidationSchema.js → validateWorkflow.js} +33 -2
  179. package/ee/admin/pages/SettingsPage/pages/Users/ListPage/CreateAction/index.js +2 -4
  180. package/ee/admin/pages/SettingsPage/pages/Users/ListPage/index.js +13 -0
  181. package/ee/admin/pages/SettingsPage/pages/Users/components/MagicLink/index.js +3 -5
  182. package/ee/admin/pages/SettingsPage/pages/Webhooks/EditView/components/EventTable/index.js +1 -3
  183. package/ee/server/constants/default-stages.json +1 -1
  184. package/ee/server/constants/workflows.js +1 -0
  185. package/ee/server/services/review-workflows/validation.js +6 -0
  186. package/ee/server/validation/review-workflows.js +6 -2
  187. package/index.js +0 -14
  188. package/package.json +12 -20
  189. package/webpack.alias.js +0 -3
  190. package/webpack.config.js +1 -75
  191. package/admin/src/content-manager/pages/ListView/components/TableRows/index.js +0 -300
  192. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/AdminSeatInfo/index.js +0 -5
  193. package/build/1386.3b2aa6a7.chunk.js +0 -3
  194. package/build/1970.39a2d75e.chunk.js +0 -1
  195. package/build/2799.cf9b491f.chunk.js +0 -1
  196. package/build/3269.1ea0f5a6.chunk.js +0 -1
  197. package/build/4485.d3c6dd1d.chunk.js +0 -6
  198. package/build/539.865446c0.chunk.js +0 -1
  199. package/build/6691.e6d5ac38.chunk.js +0 -105
  200. package/build/7018.f3dad3c1.chunk.js +0 -1
  201. package/build/7259.0e25ab5d.chunk.js +0 -1
  202. package/build/9465.d8fc1377.chunk.js +0 -112
  203. package/build/Admin_InternalErrorPage.8911cb49.chunk.js +0 -1
  204. package/build/Admin_settingsPage.074655f6.chunk.js +0 -79
  205. package/build/Upload_ConfigureTheView.7a1cb9c9.chunk.js +0 -1
  206. package/build/admin-app.3ede71ad.chunk.js +0 -61
  207. package/build/admin-edit-users.78552758.chunk.js +0 -10
  208. package/build/admin-users.c23322fc.chunk.js +0 -11
  209. package/build/api-tokens-create-page.3dd4e921.chunk.js +0 -1
  210. package/build/audit-logs-settings-page.37fe915c.chunk.js +0 -1
  211. package/build/content-manager.08541eeb.chunk.js +0 -1094
  212. package/build/content-type-builder.de22f7c9.chunk.js +0 -166
  213. package/build/main.a8ede50d.js +0 -2927
  214. package/build/review-workflows-settings-create-view.56f61e18.chunk.js +0 -1
  215. package/build/review-workflows-settings-edit-view.912bc9c0.chunk.js +0 -1
  216. package/build/review-workflows-settings-list-view.cf6a08d3.chunk.js +0 -56
  217. package/build/sso-settings-page.0cdb96a6.chunk.js +0 -1
  218. package/build/transfer-tokens-create-page.de14cad4.chunk.js +0 -1
  219. package/build/transfer-tokens-edit-page.4f5e39af.chunk.js +0 -1
  220. package/build/upload-settings.cb6c14c3.chunk.js +0 -14
  221. package/build/upload.7e629643.chunk.js +0 -26
  222. package/build/users-email-settings-page.e9bcd865.chunk.js +0 -9
  223. package/build/users-providers-settings-page.a94253e9.chunk.js +0 -14
  224. package/build/webhook-edit-page.77ef4f1a.chunk.js +0 -33
  225. /package/admin/src/content-manager/components/{DynamicTable → ListViewTable}/CellContent/PublicationState/PublicationState.js +0 -0
  226. /package/admin/src/content-manager/components/{DynamicTable → ListViewTable}/CellContent/PublicationState/index.js +0 -0
@@ -0,0 +1,164 @@
1
+ import * as React from 'react';
2
+
3
+ import { Button, Flex, Dialog, DialogBody, DialogFooter, Typography } from '@strapi/design-system';
4
+ import {
5
+ useTableContext,
6
+ useFetchClient,
7
+ useNotification,
8
+ useAPIErrorHandler,
9
+ } from '@strapi/helper-plugin';
10
+ import { Check, ExclamationMarkCircle } from '@strapi/icons';
11
+ import PropTypes from 'prop-types';
12
+ import { useIntl } from 'react-intl';
13
+ import { useQuery } from 'react-query';
14
+ import { useSelector } from 'react-redux';
15
+
16
+ import InjectionZoneList from '../../../../../components/InjectionZoneList';
17
+ import { getTrad } from '../../../../../utils';
18
+ import { listViewDomain } from '../../../selectors';
19
+
20
+ const ConfirmBulkActionDialog = ({ onToggleDialog, isOpen, dialogBody, endAction }) => {
21
+ const { formatMessage } = useIntl();
22
+
23
+ return (
24
+ <Dialog
25
+ onClose={onToggleDialog}
26
+ title={formatMessage({
27
+ id: 'app.components.ConfirmDialog.title',
28
+ defaultMessage: 'Confirmation',
29
+ })}
30
+ isOpen={isOpen}
31
+ >
32
+ <DialogBody icon={<ExclamationMarkCircle />}>
33
+ <Flex direction="column" alignItems="stretch" gap={2}>
34
+ {dialogBody}
35
+ </Flex>
36
+ </DialogBody>
37
+ <DialogFooter
38
+ startAction={
39
+ <Button onClick={onToggleDialog} variant="tertiary">
40
+ {formatMessage({
41
+ id: 'app.components.Button.cancel',
42
+ defaultMessage: 'Cancel',
43
+ })}
44
+ </Button>
45
+ }
46
+ endAction={endAction}
47
+ />
48
+ </Dialog>
49
+ );
50
+ };
51
+
52
+ ConfirmBulkActionDialog.propTypes = {
53
+ isOpen: PropTypes.bool.isRequired,
54
+ onToggleDialog: PropTypes.func.isRequired,
55
+ dialogBody: PropTypes.node.isRequired,
56
+ endAction: PropTypes.node.isRequired,
57
+ };
58
+
59
+ export const confirmDialogsPropTypes = {
60
+ isConfirmButtonLoading: PropTypes.bool.isRequired,
61
+ isOpen: PropTypes.bool.isRequired,
62
+ onConfirm: PropTypes.func.isRequired,
63
+ onToggleDialog: PropTypes.func.isRequired,
64
+ };
65
+
66
+ /* -------------------------------------------------------------------------------------------------
67
+ * BoldChunk
68
+ * -----------------------------------------------------------------------------------------------*/
69
+
70
+ const BoldChunk = (chunks) => <Typography fontWeight="bold">{chunks}</Typography>;
71
+
72
+ /* -------------------------------------------------------------------------------------------------
73
+ * ConfirmDialogPublishAll
74
+ * -----------------------------------------------------------------------------------------------*/
75
+
76
+ const ConfirmDialogPublishAll = ({ isOpen, onToggleDialog, isConfirmButtonLoading, onConfirm }) => {
77
+ const { formatMessage } = useIntl();
78
+ const { get } = useFetchClient();
79
+ const { selectedEntries } = useTableContext();
80
+ const toggleNotification = useNotification();
81
+ const { formatAPIError } = useAPIErrorHandler(getTrad);
82
+ const {
83
+ contentType: { uid: slug },
84
+ } = useSelector(listViewDomain());
85
+
86
+ const {
87
+ data: countDraftRelations,
88
+ isLoading,
89
+ isError,
90
+ } = useQuery(
91
+ ['content-manager', 'draft-relations', slug, selectedEntries],
92
+ async () => {
93
+ const {
94
+ data: { data },
95
+ } = await get(
96
+ `/content-manager/collection-types/${slug}/actions/countManyEntriesDraftRelations`,
97
+ {
98
+ params: {
99
+ ids: selectedEntries,
100
+ },
101
+ }
102
+ );
103
+
104
+ return data;
105
+ },
106
+ {
107
+ onError(error) {
108
+ toggleNotification({ type: 'warning', message: formatAPIError(error) });
109
+ },
110
+ }
111
+ );
112
+
113
+ if (isError) {
114
+ return null;
115
+ }
116
+
117
+ return (
118
+ <ConfirmBulkActionDialog
119
+ isOpen={isOpen && !isLoading}
120
+ onToggleDialog={onToggleDialog}
121
+ dialogBody={
122
+ <>
123
+ <Typography id="confirm-description" textAlign="center">
124
+ {countDraftRelations > 0 &&
125
+ formatMessage(
126
+ {
127
+ id: getTrad(`popUpwarning.warning.bulk-has-draft-relations.message`),
128
+ defaultMessage:
129
+ '<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. ',
130
+ },
131
+ {
132
+ b: BoldChunk,
133
+ count: countDraftRelations,
134
+ entities: selectedEntries.length,
135
+ }
136
+ )}
137
+ {formatMessage({
138
+ id: getTrad('popUpWarning.bodyMessage.contentType.publish.all'),
139
+ defaultMessage: 'Are you sure you want to publish these entries?',
140
+ })}
141
+ </Typography>
142
+ <InjectionZoneList area="contentManager.listView.publishModalAdditionalInfos" />
143
+ </>
144
+ }
145
+ endAction={
146
+ <Button
147
+ onClick={onConfirm}
148
+ variant="secondary"
149
+ startIcon={<Check />}
150
+ loading={isConfirmButtonLoading}
151
+ >
152
+ {formatMessage({
153
+ id: 'app.utils.publish',
154
+ defaultMessage: 'Publish',
155
+ })}
156
+ </Button>
157
+ }
158
+ />
159
+ );
160
+ };
161
+
162
+ ConfirmDialogPublishAll.propTypes = confirmDialogsPropTypes;
163
+
164
+ export { ConfirmDialogPublishAll, ConfirmBulkActionDialog };
@@ -0,0 +1,468 @@
1
+ import React from 'react';
2
+
3
+ import {
4
+ Box,
5
+ Button,
6
+ Typography,
7
+ ModalLayout,
8
+ ModalHeader,
9
+ ModalBody,
10
+ ModalFooter,
11
+ Tr,
12
+ Td,
13
+ IconButton,
14
+ Flex,
15
+ Icon,
16
+ Tooltip,
17
+ Loader,
18
+ } from '@strapi/design-system';
19
+ import {
20
+ useTableContext,
21
+ Table,
22
+ getYupInnerErrors,
23
+ useFetchClient,
24
+ useQueryParams,
25
+ useNotification,
26
+ } from '@strapi/helper-plugin';
27
+ import { Pencil, CrossCircle, CheckCircle } from '@strapi/icons';
28
+ import PropTypes from 'prop-types';
29
+ import { useIntl } from 'react-intl';
30
+ import { useMutation, useQuery } from 'react-query';
31
+ import { useSelector } from 'react-redux';
32
+ import { Link, useHistory } from 'react-router-dom';
33
+ import styled from 'styled-components';
34
+
35
+ import formatAPIError from '../../../../../../utils/formatAPIErrors';
36
+ import { getTrad, createYupSchema } from '../../../../../utils';
37
+ import { listViewDomain } from '../../../selectors';
38
+ import { Body } from '../../Body';
39
+ import { ConfirmDialogPublishAll } from '../ConfirmBulkActionDialog';
40
+
41
+ const TypographyMaxWidth = styled(Typography)`
42
+ max-width: 300px;
43
+ `;
44
+
45
+ /* -------------------------------------------------------------------------------------------------
46
+ * EntryValidationText
47
+ * -----------------------------------------------------------------------------------------------*/
48
+
49
+ const EntryValidationText = ({ errors, isPublished }) => {
50
+ const { formatMessage } = useIntl();
51
+
52
+ if (errors) {
53
+ const errorMessages = Object.entries(errors)
54
+ .map(([key, value]) =>
55
+ formatMessage(
56
+ { id: `${value.id}.withField`, defaultMessage: value.defaultMessage },
57
+ { field: key }
58
+ )
59
+ )
60
+ .join(' ');
61
+
62
+ return (
63
+ <Flex gap={2}>
64
+ <Icon color="danger600" as={CrossCircle} />
65
+ <Tooltip description={errorMessages}>
66
+ <TypographyMaxWidth textColor="danger600" variant="omega" fontWeight="semiBold" ellipsis>
67
+ {errorMessages}
68
+ </TypographyMaxWidth>
69
+ </Tooltip>
70
+ </Flex>
71
+ );
72
+ }
73
+
74
+ if (isPublished) {
75
+ return (
76
+ <Flex gap={2}>
77
+ <Icon color="success600" as={CheckCircle} />
78
+ <Typography textColor="success600" fontWeight="bold">
79
+ {formatMessage({
80
+ id: 'app.utils.published',
81
+ defaultMessage: 'Published',
82
+ })}
83
+ </Typography>
84
+ </Flex>
85
+ );
86
+ }
87
+
88
+ return (
89
+ <Flex gap={2}>
90
+ <Icon color="success600" as={CheckCircle} />
91
+ <Typography>
92
+ {formatMessage({
93
+ id: 'app.utils.ready-to-publish',
94
+ defaultMessage: 'Ready to publish',
95
+ })}
96
+ </Typography>
97
+ </Flex>
98
+ );
99
+ };
100
+
101
+ EntryValidationText.defaultProps = {
102
+ errors: null,
103
+ isPublished: false,
104
+ };
105
+
106
+ EntryValidationText.propTypes = {
107
+ errors: PropTypes.shape({
108
+ [PropTypes.string]: PropTypes.shape({
109
+ id: PropTypes.string,
110
+ defaultMessage: PropTypes.string,
111
+ }),
112
+ }),
113
+ isPublished: PropTypes.bool,
114
+ };
115
+
116
+ /* -------------------------------------------------------------------------------------------------
117
+ * SelectedEntriesTableContent
118
+ * -----------------------------------------------------------------------------------------------*/
119
+
120
+ const SelectedEntriesTableContent = ({ isPublishing, rowsToDisplay, entriesToPublish }) => {
121
+ const {
122
+ location: { pathname },
123
+ } = useHistory();
124
+ const { formatMessage } = useIntl();
125
+
126
+ // Get main field from list view layout
127
+ const listViewStore = useSelector(listViewDomain());
128
+ const { mainField } = listViewStore.contentType.settings;
129
+ const shouldDisplayMainField = mainField != null && mainField !== 'id';
130
+
131
+ const getItemLineText = (count) =>
132
+ formatMessage(
133
+ {
134
+ id: 'content-manager.components.ListViewTable.row-line',
135
+ defaultMessage: 'item line {number}',
136
+ },
137
+ { number: count + 1 }
138
+ );
139
+
140
+ return (
141
+ <Table.Content>
142
+ <Table.Head>
143
+ <Table.HeaderCheckboxCell />
144
+ <Table.HeaderCell fieldSchemaType="number" label="id" name="id" />
145
+ {shouldDisplayMainField && (
146
+ <Table.HeaderCell fieldSchemaType="string" label="name" name="name" />
147
+ )}
148
+ <Table.HeaderCell fieldSchemaType="string" label="status" name="status" />
149
+ </Table.Head>
150
+ <Table.LoadingBody />
151
+ <Table.Body>
152
+ {rowsToDisplay.map(({ entity, errors }, index) => (
153
+ <Tr key={entity.id}>
154
+ <Body.CheckboxDataCell rowId={entity.id} index={index} />
155
+ <Td>
156
+ <Typography>{entity.id}</Typography>
157
+ </Td>
158
+ {shouldDisplayMainField && (
159
+ <Td>
160
+ <Typography>{entity[mainField]}</Typography>
161
+ </Td>
162
+ )}
163
+ <Td>
164
+ {isPublishing && entriesToPublish.includes(entity.id) ? (
165
+ <Flex gap={2}>
166
+ <Typography>
167
+ {formatMessage({
168
+ id: 'content-manager.success.record.publishing',
169
+ defaultMessage: 'Publishing...',
170
+ })}
171
+ </Typography>
172
+ <Loader small />
173
+ </Flex>
174
+ ) : (
175
+ <EntryValidationText errors={errors} isPublished={entity.publishedAt !== null} />
176
+ )}
177
+ </Td>
178
+ <Td>
179
+ <IconButton
180
+ forwardedAs={Link}
181
+ to={{
182
+ pathname: `${pathname}/${entity.id}`,
183
+ state: { from: pathname },
184
+ }}
185
+ label={formatMessage(
186
+ { id: 'app.component.table.edit', defaultMessage: 'Edit {target}' },
187
+ { target: getItemLineText(index) }
188
+ )}
189
+ noBorder
190
+ target="_blank"
191
+ >
192
+ <Pencil />
193
+ </IconButton>
194
+ </Td>
195
+ </Tr>
196
+ ))}
197
+ </Table.Body>
198
+ </Table.Content>
199
+ );
200
+ };
201
+
202
+ SelectedEntriesTableContent.defaultProps = {
203
+ isPublishing: false,
204
+ rowsToDisplay: [],
205
+ entriesToPublish: [],
206
+ };
207
+
208
+ SelectedEntriesTableContent.propTypes = {
209
+ isPublishing: PropTypes.bool,
210
+ rowsToDisplay: PropTypes.arrayOf(PropTypes.object),
211
+ entriesToPublish: PropTypes.arrayOf(PropTypes.number),
212
+ };
213
+
214
+ /* -------------------------------------------------------------------------------------------------
215
+ * BoldChunk
216
+ * -----------------------------------------------------------------------------------------------*/
217
+
218
+ const BoldChunk = (chunks) => <Typography fontWeight="bold">{chunks}</Typography>;
219
+
220
+ /* -------------------------------------------------------------------------------------------------
221
+ * SelectedEntriesModalContent
222
+ * -----------------------------------------------------------------------------------------------*/
223
+
224
+ const SelectedEntriesModalContent = ({ toggleModal, refetchModalData, setEntriesToFetch }) => {
225
+ const { formatMessage } = useIntl();
226
+ const { selectedEntries, rows, onSelectRow, isLoading, isFetching } = useTableContext();
227
+ const [isDialogOpen, setIsDialogOpen] = React.useState(false);
228
+ const [rowsToDisplay, setRowsToDisplay] = React.useState([]);
229
+ const [publishedCount, setPublishedCount] = React.useState(0);
230
+
231
+ const entriesToPublish = rows
232
+ .filter(({ entity, errors }) => selectedEntries.includes(entity.id) && !errors)
233
+ .map(({ entity }) => entity.id);
234
+
235
+ const { post } = useFetchClient();
236
+ const toggleNotification = useNotification();
237
+ const { contentType } = useSelector(listViewDomain());
238
+
239
+ const selectedEntriesWithErrorsCount = rowsToDisplay.filter(
240
+ ({ entity, errors }) => selectedEntries.includes(entity.id) && errors
241
+ ).length;
242
+ const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount;
243
+
244
+ const bulkPublishMutation = useMutation(
245
+ (data) =>
246
+ post(`/content-manager/collection-types/${contentType.uid}/actions/bulkPublish`, data),
247
+ {
248
+ onSuccess() {
249
+ const update = rowsToDisplay.filter((row) => {
250
+ if (entriesToPublish.includes(row.entity.id)) {
251
+ // Deselect the entries that have been published from the modal table
252
+ onSelectRow({ name: row.entity.id, value: false });
253
+ }
254
+
255
+ // Remove the entries that have been published from the table
256
+ return !entriesToPublish.includes(row.entity.id);
257
+ });
258
+
259
+ setRowsToDisplay(update);
260
+ // Set the parent's entries to fetch when clicking refresh
261
+ setEntriesToFetch(update.map(({ entity }) => entity.id));
262
+
263
+ if (update.length === 0) {
264
+ toggleModal();
265
+ }
266
+
267
+ toggleNotification({
268
+ type: 'success',
269
+ message: { id: 'content-manager.success.record.publish', defaultMessage: 'Published' },
270
+ });
271
+ },
272
+ onError(error) {
273
+ toggleNotification({
274
+ type: 'warning',
275
+ message: formatAPIError(error),
276
+ });
277
+ },
278
+ }
279
+ );
280
+
281
+ const toggleDialog = () => setIsDialogOpen((prev) => !prev);
282
+
283
+ const handleConfirmBulkPublish = async () => {
284
+ toggleDialog();
285
+ const { data } = await bulkPublishMutation.mutateAsync({ ids: entriesToPublish });
286
+ setPublishedCount(data.count);
287
+ };
288
+
289
+ const getFormattedCountMessage = () => {
290
+ if (publishedCount) {
291
+ return formatMessage(
292
+ {
293
+ id: getTrad('containers.ListPage.selectedEntriesModal.publishedCount'),
294
+ defaultMessage:
295
+ '<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.',
296
+ },
297
+ {
298
+ publishedCount,
299
+ withErrorsCount: selectedEntriesWithErrorsCount,
300
+ b: BoldChunk,
301
+ }
302
+ );
303
+ }
304
+
305
+ return formatMessage(
306
+ {
307
+ id: getTrad('containers.ListPage.selectedEntriesModal.selectedCount'),
308
+ defaultMessage:
309
+ '<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.',
310
+ },
311
+ {
312
+ readyToPublishCount: selectedEntriesWithNoErrorsCount,
313
+ withErrorsCount: selectedEntriesWithErrorsCount,
314
+ b: BoldChunk,
315
+ }
316
+ );
317
+ };
318
+
319
+ React.useEffect(() => {
320
+ // When the api responds with data
321
+ if (rows.length > 0) {
322
+ // Update the rows to display
323
+ setRowsToDisplay(rows);
324
+ }
325
+ }, [rows]);
326
+
327
+ return (
328
+ <ModalLayout onClose={toggleModal} labelledBy="title">
329
+ <ModalHeader>
330
+ <Typography fontWeight="bold" textColor="neutral800" as="h2" id="title">
331
+ {formatMessage({
332
+ id: getTrad('containers.ListPage.selectedEntriesModal.title'),
333
+ defaultMessage: 'Publish entries',
334
+ })}
335
+ </Typography>
336
+ </ModalHeader>
337
+ <ModalBody>
338
+ <Typography>{getFormattedCountMessage()}</Typography>
339
+ <Box marginTop={5}>
340
+ <SelectedEntriesTableContent
341
+ isPublishing={bulkPublishMutation.isLoading}
342
+ rowsToDisplay={rowsToDisplay}
343
+ entriesToPublish={entriesToPublish}
344
+ />
345
+ </Box>
346
+ </ModalBody>
347
+ <ModalFooter
348
+ startActions={
349
+ <Button onClick={toggleModal} variant="tertiary">
350
+ {formatMessage({
351
+ id: 'app.components.Button.cancel',
352
+ defaultMessage: 'Cancel',
353
+ })}
354
+ </Button>
355
+ }
356
+ endActions={
357
+ <Flex gap={2}>
358
+ <Button onClick={refetchModalData} variant="tertiary" loading={isFetching}>
359
+ {formatMessage({ id: 'app.utils.refresh', defaultMessage: 'Refresh' })}
360
+ </Button>
361
+ <Button
362
+ onClick={toggleDialog}
363
+ disabled={
364
+ selectedEntries.length === 0 ||
365
+ selectedEntries.length === selectedEntriesWithErrorsCount ||
366
+ isLoading
367
+ }
368
+ loading={bulkPublishMutation.isLoading}
369
+ >
370
+ {formatMessage({ id: 'app.utils.publish', defaultMessage: 'Publish' })}
371
+ </Button>
372
+ </Flex>
373
+ }
374
+ />
375
+ <ConfirmDialogPublishAll
376
+ isOpen={isDialogOpen}
377
+ onToggleDialog={toggleDialog}
378
+ isConfirmButtonLoading={bulkPublishMutation.isLoading}
379
+ onConfirm={handleConfirmBulkPublish}
380
+ />
381
+ </ModalLayout>
382
+ );
383
+ };
384
+
385
+ SelectedEntriesModalContent.propTypes = {
386
+ toggleModal: PropTypes.func.isRequired,
387
+ refetchModalData: PropTypes.func.isRequired,
388
+ setEntriesToFetch: PropTypes.func.isRequired,
389
+ };
390
+
391
+ /* -------------------------------------------------------------------------------------------------
392
+ * SelectedEntriesModal
393
+ * -----------------------------------------------------------------------------------------------*/
394
+
395
+ const SelectedEntriesModal = ({ onToggle }) => {
396
+ const { selectedEntries: selectedListViewEntries } = useTableContext();
397
+ const { contentType, components } = useSelector(listViewDomain());
398
+ // The child table will update this value based on the entries that were published
399
+ const [entriesToFetch, setEntriesToFetch] = React.useState(selectedListViewEntries);
400
+
401
+ // We want to keep the selected entries order same as the list view
402
+ const [
403
+ {
404
+ query: { sort },
405
+ },
406
+ ] = useQueryParams();
407
+ const queryParams = {
408
+ sort,
409
+ filters: {
410
+ id: {
411
+ $in: entriesToFetch,
412
+ },
413
+ },
414
+ };
415
+
416
+ const { get } = useFetchClient();
417
+
418
+ const { data, isLoading, isFetching, refetch } = useQuery(
419
+ ['entries', contentType.uid, queryParams],
420
+ async () => {
421
+ const { data } = await get(`content-manager/collection-types/${contentType.uid}`, {
422
+ params: queryParams,
423
+ });
424
+
425
+ if (data.results) {
426
+ const schema = createYupSchema(contentType, { components }, { isDraft: false });
427
+ const rows = data.results.map((entry) => {
428
+ try {
429
+ schema.validateSync(entry, { abortEarly: false });
430
+
431
+ return { entity: entry };
432
+ } catch (e) {
433
+ return {
434
+ entity: entry,
435
+ errors: getYupInnerErrors(e),
436
+ };
437
+ }
438
+ });
439
+
440
+ return rows;
441
+ }
442
+
443
+ return [];
444
+ }
445
+ );
446
+
447
+ return (
448
+ <Table.Root
449
+ rows={data}
450
+ defaultSelectedEntries={selectedListViewEntries}
451
+ colCount={4}
452
+ isLoading={isLoading}
453
+ isFetching={isFetching}
454
+ >
455
+ <SelectedEntriesModalContent
456
+ setEntriesToFetch={setEntriesToFetch}
457
+ toggleModal={onToggle}
458
+ refetchModalData={refetch}
459
+ />
460
+ </Table.Root>
461
+ );
462
+ };
463
+
464
+ SelectedEntriesModal.propTypes = {
465
+ onToggle: PropTypes.func.isRequired,
466
+ };
467
+
468
+ export default SelectedEntriesModal;