@strapi/plugin-users-permissions 0.0.0-next.f45143c5e2a8a9d85691d0abf79a3f42024a0c71 → 0.0.0-next.f4ec69568d980c6fee91ce2ee0f41c138347aa81

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 (229) hide show
  1. package/.eslintignore +1 -2
  2. package/.eslintrc +17 -0
  3. package/LICENSE +18 -3
  4. package/admin/src/components/BoundRoute/{index.js → index.jsx} +6 -4
  5. package/admin/src/components/FormModal/Input/{index.js → index.jsx} +37 -33
  6. package/admin/src/components/FormModal/index.jsx +115 -0
  7. package/admin/src/components/Permissions/PermissionRow/{CheckboxWrapper.js → CheckboxWrapper.jsx} +4 -3
  8. package/admin/src/components/Permissions/PermissionRow/{SubCategory.js → SubCategory.jsx} +27 -15
  9. package/admin/src/components/Permissions/PermissionRow/{index.js → index.jsx} +4 -2
  10. package/admin/src/components/Permissions/index.jsx +47 -0
  11. package/admin/src/components/Permissions/reducer.js +1 -1
  12. package/admin/src/components/Policies/{index.js → index.jsx} +9 -6
  13. package/admin/src/components/UsersPermissions/{index.js → index.jsx} +22 -11
  14. package/admin/src/components/UsersPermissions/reducer.js +1 -1
  15. package/admin/src/{permissions.js → constants.js} +1 -3
  16. package/admin/src/contexts/UsersPermissionsContext/{index.js → index.jsx} +1 -0
  17. package/admin/src/index.js +25 -51
  18. package/admin/src/pages/AdvancedSettings/index.jsx +214 -0
  19. package/admin/src/pages/AdvancedSettings/utils/layout.js +20 -35
  20. package/admin/src/pages/AdvancedSettings/utils/schema.js +5 -2
  21. package/admin/src/pages/EmailTemplates/components/EmailForm.jsx +156 -0
  22. package/admin/src/pages/EmailTemplates/components/{EmailTable.js → EmailTable.jsx} +27 -22
  23. package/admin/src/pages/EmailTemplates/index.jsx +148 -0
  24. package/admin/src/pages/EmailTemplates/utils/schema.js +18 -6
  25. package/admin/src/pages/Providers/index.jsx +262 -0
  26. package/admin/src/pages/Providers/utils/forms.js +23 -11
  27. package/admin/src/pages/Roles/constants.js +7 -0
  28. package/admin/src/pages/Roles/hooks/usePlugins.js +78 -0
  29. package/admin/src/pages/Roles/index.jsx +24 -0
  30. package/admin/src/pages/Roles/pages/CreatePage.jsx +194 -0
  31. package/admin/src/pages/Roles/pages/EditPage.jsx +215 -0
  32. package/admin/src/pages/Roles/pages/ListPage/components/TableBody.jsx +119 -0
  33. package/admin/src/pages/Roles/{ListPage/index.js → pages/ListPage/index.jsx} +108 -83
  34. package/admin/src/translations/en.json +1 -1
  35. package/admin/src/translations/ru.json +50 -26
  36. package/admin/src/translations/zh-Hans.json +80 -80
  37. package/admin/src/utils/index.js +1 -2
  38. package/admin/src/utils/prefixPluginTranslations.js +13 -0
  39. package/dist/_chunks/ar-BguGUqwK.js +44 -0
  40. package/dist/_chunks/ar-BguGUqwK.js.map +1 -0
  41. package/dist/_chunks/ar-CK8BRRXB.mjs +44 -0
  42. package/dist/_chunks/ar-CK8BRRXB.mjs.map +1 -0
  43. package/dist/_chunks/cs-BVigMk0l.mjs +50 -0
  44. package/dist/_chunks/cs-BVigMk0l.mjs.map +1 -0
  45. package/dist/_chunks/cs-BW8-K_GY.js +50 -0
  46. package/dist/_chunks/cs-BW8-K_GY.js.map +1 -0
  47. package/dist/_chunks/de-BKUdRFI4.mjs +62 -0
  48. package/dist/_chunks/de-BKUdRFI4.mjs.map +1 -0
  49. package/dist/_chunks/de-owXpVluI.js +62 -0
  50. package/dist/_chunks/de-owXpVluI.js.map +1 -0
  51. package/dist/_chunks/dk-BQiTK50l.mjs +86 -0
  52. package/dist/_chunks/dk-BQiTK50l.mjs.map +1 -0
  53. package/dist/_chunks/dk-LXAnbuBk.js +86 -0
  54. package/dist/_chunks/dk-LXAnbuBk.js.map +1 -0
  55. package/dist/_chunks/en-DOHtPf-2.mjs +86 -0
  56. package/dist/_chunks/en-DOHtPf-2.mjs.map +1 -0
  57. package/dist/_chunks/en-MHo5mcsU.js +86 -0
  58. package/dist/_chunks/en-MHo5mcsU.js.map +1 -0
  59. package/dist/_chunks/es-BwLCLXAQ.js +86 -0
  60. package/dist/_chunks/es-BwLCLXAQ.js.map +1 -0
  61. package/dist/_chunks/es-DNgOVMjD.mjs +86 -0
  62. package/dist/_chunks/es-DNgOVMjD.mjs.map +1 -0
  63. package/dist/_chunks/fr-DkgRugiU.mjs +50 -0
  64. package/dist/_chunks/fr-DkgRugiU.mjs.map +1 -0
  65. package/dist/_chunks/fr-DkhpSjjm.js +50 -0
  66. package/dist/_chunks/fr-DkhpSjjm.js.map +1 -0
  67. package/dist/_chunks/id-BTemOeTZ.js +62 -0
  68. package/dist/_chunks/id-BTemOeTZ.js.map +1 -0
  69. package/dist/_chunks/id-BdEsvnaF.mjs +62 -0
  70. package/dist/_chunks/id-BdEsvnaF.mjs.map +1 -0
  71. package/dist/_chunks/index-2awRBazk.js +281 -0
  72. package/dist/_chunks/index-2awRBazk.js.map +1 -0
  73. package/dist/_chunks/index-BAHBK68t.js +1172 -0
  74. package/dist/_chunks/index-BAHBK68t.js.map +1 -0
  75. package/dist/_chunks/index-BHbzbu1p.mjs +246 -0
  76. package/dist/_chunks/index-BHbzbu1p.mjs.map +1 -0
  77. package/dist/_chunks/index-Be4qNiZI.js +640 -0
  78. package/dist/_chunks/index-Be4qNiZI.js.map +1 -0
  79. package/dist/_chunks/index-C88EQQJQ-C4oUQUND.js +12026 -0
  80. package/dist/_chunks/index-C88EQQJQ-C4oUQUND.js.map +1 -0
  81. package/dist/_chunks/index-C88EQQJQ-DAZ1lfuF.mjs +12002 -0
  82. package/dist/_chunks/index-C88EQQJQ-DAZ1lfuF.mjs.map +1 -0
  83. package/dist/_chunks/index-CbKOY95_.mjs +344 -0
  84. package/dist/_chunks/index-CbKOY95_.mjs.map +1 -0
  85. package/dist/_chunks/index-CeweK3q9.mjs +617 -0
  86. package/dist/_chunks/index-CeweK3q9.mjs.map +1 -0
  87. package/dist/_chunks/index-QcDREbPt.mjs +262 -0
  88. package/dist/_chunks/index-QcDREbPt.mjs.map +1 -0
  89. package/dist/_chunks/index-YTFP-hNZ.js +245 -0
  90. package/dist/_chunks/index-YTFP-hNZ.js.map +1 -0
  91. package/dist/_chunks/index-YZkqoYZN.js +366 -0
  92. package/dist/_chunks/index-YZkqoYZN.js.map +1 -0
  93. package/dist/_chunks/index-mKh-etKG.mjs +1142 -0
  94. package/dist/_chunks/index-mKh-etKG.mjs.map +1 -0
  95. package/dist/_chunks/it-B-rv0E24.mjs +62 -0
  96. package/dist/_chunks/it-B-rv0E24.mjs.map +1 -0
  97. package/dist/_chunks/it-D1rH6V6_.js +62 -0
  98. package/dist/_chunks/it-D1rH6V6_.js.map +1 -0
  99. package/dist/_chunks/ja-C8K-VBPD.mjs +48 -0
  100. package/dist/_chunks/ja-C8K-VBPD.mjs.map +1 -0
  101. package/dist/_chunks/ja-DqShgTMf.js +48 -0
  102. package/dist/_chunks/ja-DqShgTMf.js.map +1 -0
  103. package/dist/_chunks/ko-B9DGEPWH.js +86 -0
  104. package/dist/_chunks/ko-B9DGEPWH.js.map +1 -0
  105. package/dist/_chunks/ko-Busb0wIY.mjs +86 -0
  106. package/dist/_chunks/ko-Busb0wIY.mjs.map +1 -0
  107. package/dist/_chunks/ms-ByvsQjRt.mjs +49 -0
  108. package/dist/_chunks/ms-ByvsQjRt.mjs.map +1 -0
  109. package/dist/_chunks/ms-CPBU3LWf.js +49 -0
  110. package/dist/_chunks/ms-CPBU3LWf.js.map +1 -0
  111. package/dist/_chunks/nl-5qO8Rpcy.mjs +48 -0
  112. package/dist/_chunks/nl-5qO8Rpcy.mjs.map +1 -0
  113. package/dist/_chunks/nl-CwNB6YoO.js +48 -0
  114. package/dist/_chunks/nl-CwNB6YoO.js.map +1 -0
  115. package/dist/_chunks/pl-BdIzifBE.mjs +86 -0
  116. package/dist/_chunks/pl-BdIzifBE.mjs.map +1 -0
  117. package/dist/_chunks/pl-Do9UD69f.js +86 -0
  118. package/dist/_chunks/pl-Do9UD69f.js.map +1 -0
  119. package/dist/_chunks/pt-BIO24ioG.mjs +48 -0
  120. package/dist/_chunks/pt-BIO24ioG.mjs.map +1 -0
  121. package/dist/_chunks/pt-BR-D7dZhxuP.js +44 -0
  122. package/dist/_chunks/pt-BR-D7dZhxuP.js.map +1 -0
  123. package/dist/_chunks/pt-BR-f0p23AQZ.mjs +44 -0
  124. package/dist/_chunks/pt-BR-f0p23AQZ.mjs.map +1 -0
  125. package/dist/_chunks/pt-fdvyOnUp.js +48 -0
  126. package/dist/_chunks/pt-fdvyOnUp.js.map +1 -0
  127. package/dist/_chunks/ru-C94rjPGA.js +86 -0
  128. package/dist/_chunks/ru-C94rjPGA.js.map +1 -0
  129. package/dist/_chunks/ru-VWy-IB7K.mjs +86 -0
  130. package/dist/_chunks/ru-VWy-IB7K.mjs.map +1 -0
  131. package/dist/_chunks/sk-BABEhykl.js +50 -0
  132. package/dist/_chunks/sk-BABEhykl.js.map +1 -0
  133. package/dist/_chunks/sk-B_LIcepm.mjs +50 -0
  134. package/dist/_chunks/sk-B_LIcepm.mjs.map +1 -0
  135. package/dist/_chunks/sv-ABLKOokl.mjs +86 -0
  136. package/dist/_chunks/sv-ABLKOokl.mjs.map +1 -0
  137. package/dist/_chunks/sv-Be43LhA9.js +86 -0
  138. package/dist/_chunks/sv-Be43LhA9.js.map +1 -0
  139. package/dist/_chunks/th-DKyP7ueR.mjs +60 -0
  140. package/dist/_chunks/th-DKyP7ueR.mjs.map +1 -0
  141. package/dist/_chunks/th-DgVhVLhL.js +60 -0
  142. package/dist/_chunks/th-DgVhVLhL.js.map +1 -0
  143. package/dist/_chunks/tr-B_idhkEs.js +85 -0
  144. package/dist/_chunks/tr-B_idhkEs.js.map +1 -0
  145. package/dist/_chunks/tr-qa1Q5UjC.mjs +85 -0
  146. package/dist/_chunks/tr-qa1Q5UjC.mjs.map +1 -0
  147. package/dist/_chunks/uk-BmRqbeQc.mjs +49 -0
  148. package/dist/_chunks/uk-BmRqbeQc.mjs.map +1 -0
  149. package/dist/_chunks/uk-LHOivnhP.js +49 -0
  150. package/dist/_chunks/uk-LHOivnhP.js.map +1 -0
  151. package/dist/_chunks/vi-CdVRdKDw.js +50 -0
  152. package/dist/_chunks/vi-CdVRdKDw.js.map +1 -0
  153. package/dist/_chunks/vi-HW-EdMea.mjs +50 -0
  154. package/dist/_chunks/vi-HW-EdMea.mjs.map +1 -0
  155. package/dist/_chunks/zh-5hKkVPA4.mjs +86 -0
  156. package/dist/_chunks/zh-5hKkVPA4.mjs.map +1 -0
  157. package/dist/_chunks/zh-Cuq8gMnF.js +86 -0
  158. package/dist/_chunks/zh-Cuq8gMnF.js.map +1 -0
  159. package/dist/_chunks/zh-Hans-BHilK-yc.mjs +86 -0
  160. package/dist/_chunks/zh-Hans-BHilK-yc.mjs.map +1 -0
  161. package/dist/_chunks/zh-Hans-GQDMKtY4.js +86 -0
  162. package/dist/_chunks/zh-Hans-GQDMKtY4.js.map +1 -0
  163. package/dist/admin/index.js +4 -0
  164. package/dist/admin/index.js.map +1 -0
  165. package/dist/admin/index.mjs +5 -0
  166. package/dist/admin/index.mjs.map +1 -0
  167. package/documentation/content-api.yaml +23 -15
  168. package/jest.config.front.js +2 -0
  169. package/package.json +51 -35
  170. package/packup.config.ts +22 -0
  171. package/server/bootstrap/index.js +18 -15
  172. package/server/bootstrap/users-permissions-actions.js +6 -0
  173. package/server/config.js +29 -0
  174. package/server/content-types/user/index.js +0 -1
  175. package/server/controllers/auth.js +74 -38
  176. package/server/controllers/content-manager-user.js +28 -30
  177. package/server/controllers/role.js +17 -4
  178. package/server/controllers/user.js +18 -8
  179. package/server/controllers/validation/auth.js +81 -25
  180. package/server/middlewares/rateLimit.js +41 -21
  181. package/server/register.js +8 -2
  182. package/server/services/jwt.js +3 -3
  183. package/server/services/permission.js +3 -7
  184. package/server/services/providers-registry.js +469 -261
  185. package/server/services/providers.js +10 -5
  186. package/server/services/role.js +15 -13
  187. package/server/services/user.js +56 -19
  188. package/server/services/users-permissions.js +15 -13
  189. package/server/strategies/users-permissions.js +1 -8
  190. package/server/utils/index.d.ts +2 -1
  191. package/server/utils/sanitize/sanitizers.js +7 -3
  192. package/server/utils/sanitize/visitors/remove-user-relation-from-role-entities.js +2 -2
  193. package/.eslintrc.js +0 -14
  194. package/admin/src/components/FormModal/index.js +0 -123
  195. package/admin/src/components/Permissions/index.js +0 -54
  196. package/admin/src/hooks/index.js +0 -5
  197. package/admin/src/hooks/useFetchRole/index.js +0 -64
  198. package/admin/src/hooks/useFetchRole/reducer.js +0 -31
  199. package/admin/src/hooks/useForm/index.js +0 -70
  200. package/admin/src/hooks/useForm/reducer.js +0 -40
  201. package/admin/src/hooks/usePlugins/index.js +0 -67
  202. package/admin/src/hooks/usePlugins/init.js +0 -5
  203. package/admin/src/hooks/usePlugins/reducer.js +0 -34
  204. package/admin/src/hooks/useRolesList/index.js +0 -63
  205. package/admin/src/hooks/useRolesList/init.js +0 -5
  206. package/admin/src/hooks/useRolesList/reducer.js +0 -31
  207. package/admin/src/pages/AdvancedSettings/index.js +0 -243
  208. package/admin/src/pages/AdvancedSettings/utils/api.js +0 -17
  209. package/admin/src/pages/EmailTemplates/components/EmailForm.js +0 -175
  210. package/admin/src/pages/EmailTemplates/index.js +0 -160
  211. package/admin/src/pages/EmailTemplates/utils/api.js +0 -17
  212. package/admin/src/pages/Providers/index.js +0 -272
  213. package/admin/src/pages/Providers/reducer.js +0 -54
  214. package/admin/src/pages/Providers/utils/api.js +0 -25
  215. package/admin/src/pages/Providers/utils/createProvidersArray.js +0 -21
  216. package/admin/src/pages/Roles/CreatePage/index.js +0 -182
  217. package/admin/src/pages/Roles/CreatePage/utils/schema.js +0 -9
  218. package/admin/src/pages/Roles/EditPage/index.js +0 -194
  219. package/admin/src/pages/Roles/EditPage/utils/schema.js +0 -9
  220. package/admin/src/pages/Roles/ListPage/components/TableBody.js +0 -92
  221. package/admin/src/pages/Roles/ListPage/utils/api.js +0 -31
  222. package/admin/src/pages/Roles/ProtectedCreatePage/index.js +0 -12
  223. package/admin/src/pages/Roles/ProtectedEditPage/index.js +0 -12
  224. package/admin/src/pages/Roles/ProtectedListPage/index.js +0 -15
  225. package/admin/src/pages/Roles/index.js +0 -27
  226. package/admin/src/utils/getRequestURL.js +0 -5
  227. package/server/bootstrap/grant-config.js +0 -131
  228. package/strapi-admin.js +0 -3
  229. package/strapi-server.js +0 -3
@@ -1,175 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import { useIntl } from 'react-intl';
4
- import { Form, GenericInput } from '@strapi/helper-plugin';
5
- import { Formik } from 'formik';
6
- import {
7
- ModalLayout,
8
- ModalHeader,
9
- ModalFooter,
10
- ModalBody,
11
- Grid,
12
- GridItem,
13
- Button,
14
- Breadcrumbs,
15
- Crumb,
16
- Textarea,
17
- } from '@strapi/design-system';
18
- import { getTrad } from '../../../utils';
19
- import schema from '../utils/schema';
20
-
21
- const EmailForm = ({ template, onToggle, onSubmit }) => {
22
- const { formatMessage } = useIntl();
23
-
24
- return (
25
- <ModalLayout
26
- onClose={onToggle}
27
- labelledBy={`${formatMessage({
28
- id: getTrad('PopUpForm.header.edit.email-templates'),
29
- defaultMessage: 'Edit email template',
30
- })}, ${formatMessage({ id: getTrad(template.display), defaultMessage: template.display })}`}
31
- >
32
- <ModalHeader>
33
- <Breadcrumbs
34
- label={`${formatMessage({
35
- id: getTrad('PopUpForm.header.edit.email-templates'),
36
- defaultMessage: 'Edit email template',
37
- })}, ${formatMessage({
38
- id: getTrad(template.display),
39
- defaultMessage: template.display,
40
- })}`}
41
- >
42
- <Crumb>
43
- {formatMessage({
44
- id: getTrad('PopUpForm.header.edit.email-templates'),
45
- defaultMessage: 'Edit email template',
46
- })}
47
- </Crumb>
48
- <Crumb>
49
- {formatMessage({ id: getTrad(template.display), defaultMessage: template.display })}
50
- </Crumb>
51
- </Breadcrumbs>
52
- </ModalHeader>
53
- <Formik
54
- onSubmit={onSubmit}
55
- initialValues={template}
56
- validateOnChange={false}
57
- validationSchema={schema}
58
- enableReinitialize
59
- >
60
- {({ errors, values, handleChange, isSubmitting }) => {
61
- return (
62
- <Form>
63
- <ModalBody>
64
- <Grid gap={5}>
65
- <GridItem col={6} s={12}>
66
- <GenericInput
67
- intlLabel={{
68
- id: getTrad('PopUpForm.Email.options.from.name.label'),
69
- defaultMessage: 'Shipper name',
70
- }}
71
- name="options.from.name"
72
- onChange={handleChange}
73
- value={values.options.from.name}
74
- error={errors?.options?.from?.name}
75
- type="text"
76
- />
77
- </GridItem>
78
- <GridItem col={6} s={12}>
79
- <GenericInput
80
- intlLabel={{
81
- id: getTrad('PopUpForm.Email.options.from.email.label'),
82
- defaultMessage: 'Shipper email',
83
- }}
84
- name="options.from.email"
85
- onChange={handleChange}
86
- value={values.options.from.email}
87
- error={errors?.options?.from?.email}
88
- type="text"
89
- />
90
- </GridItem>
91
- <GridItem col={6} s={12}>
92
- <GenericInput
93
- intlLabel={{
94
- id: getTrad('PopUpForm.Email.options.response_email.label'),
95
- defaultMessage: 'Response email',
96
- }}
97
- name="options.response_email"
98
- onChange={handleChange}
99
- value={values.options.response_email}
100
- error={errors?.options?.response_email}
101
- type="text"
102
- />
103
- </GridItem>
104
- <GridItem col={6} s={12}>
105
- <GenericInput
106
- intlLabel={{
107
- id: getTrad('PopUpForm.Email.options.object.label'),
108
- defaultMessage: 'Subject',
109
- }}
110
- name="options.object"
111
- onChange={handleChange}
112
- value={values.options.object}
113
- error={errors?.options?.object}
114
- type="text"
115
- />
116
- </GridItem>
117
- <GridItem col={12} s={12}>
118
- <Textarea
119
- label={formatMessage({
120
- id: getTrad('PopUpForm.Email.options.message.label'),
121
- defaultMessage: 'Message',
122
- })}
123
- name="options.message"
124
- onChange={handleChange}
125
- value={values.options.message}
126
- error={
127
- errors?.options?.message &&
128
- formatMessage({
129
- id: errors.options.message,
130
- defaultMessage: errors.options.message,
131
- })
132
- }
133
- />
134
- </GridItem>
135
- </Grid>
136
- </ModalBody>
137
- <ModalFooter
138
- startActions={
139
- <Button onClick={onToggle} variant="tertiary">
140
- Cancel
141
- </Button>
142
- }
143
- endActions={
144
- <Button loading={isSubmitting} type="submit">
145
- Finish
146
- </Button>
147
- }
148
- />
149
- </Form>
150
- );
151
- }}
152
- </Formik>
153
- </ModalLayout>
154
- );
155
- };
156
-
157
- EmailForm.propTypes = {
158
- template: PropTypes.shape({
159
- display: PropTypes.string,
160
- icon: PropTypes.string,
161
- options: PropTypes.shape({
162
- from: PropTypes.shape({
163
- name: PropTypes.string,
164
- email: PropTypes.string,
165
- }),
166
- message: PropTypes.string,
167
- object: PropTypes.string,
168
- response_email: PropTypes.string,
169
- }),
170
- }).isRequired,
171
- onSubmit: PropTypes.func.isRequired,
172
- onToggle: PropTypes.func.isRequired,
173
- };
174
-
175
- export default EmailForm;
@@ -1,160 +0,0 @@
1
- import React, { useMemo, useRef, useState } from 'react';
2
- import { useQuery, useMutation, useQueryClient } from 'react-query';
3
- import { useIntl } from 'react-intl';
4
- import {
5
- SettingsPageTitle,
6
- useTracking,
7
- useNotification,
8
- useOverlayBlocker,
9
- CheckPagePermissions,
10
- useRBAC,
11
- useFocusWhenNavigate,
12
- LoadingIndicatorPage,
13
- } from '@strapi/helper-plugin';
14
- import { useNotifyAT, Main, ContentLayout, HeaderLayout } from '@strapi/design-system';
15
- import pluginPermissions from '../../permissions';
16
- import { getTrad } from '../../utils';
17
- import { fetchData, putEmailTemplate } from './utils/api';
18
- import EmailTable from './components/EmailTable';
19
- import EmailForm from './components/EmailForm';
20
-
21
- const ProtectedEmailTemplatesPage = () => (
22
- <CheckPagePermissions permissions={pluginPermissions.readEmailTemplates}>
23
- <EmailTemplatesPage />
24
- </CheckPagePermissions>
25
- );
26
-
27
- const EmailTemplatesPage = () => {
28
- const { formatMessage } = useIntl();
29
- const { trackUsage } = useTracking();
30
- const { notifyStatus } = useNotifyAT();
31
- const toggleNotification = useNotification();
32
- const { lockApp, unlockApp } = useOverlayBlocker();
33
- const trackUsageRef = useRef(trackUsage);
34
- const queryClient = useQueryClient();
35
- useFocusWhenNavigate();
36
-
37
- const [isModalOpen, setIsModalOpen] = useState(false);
38
- const [templateToEdit, setTemplateToEdit] = useState(null);
39
-
40
- const updatePermissions = useMemo(() => {
41
- return { update: pluginPermissions.updateEmailTemplates };
42
- }, []);
43
-
44
- const {
45
- isLoading: isLoadingForPermissions,
46
- allowedActions: { canUpdate },
47
- } = useRBAC(updatePermissions);
48
-
49
- const { status: isLoadingData, data } = useQuery('email-templates', () => fetchData(), {
50
- onSuccess() {
51
- notifyStatus(
52
- formatMessage({
53
- id: getTrad('Email.template.data.loaded'),
54
- defaultMessage: 'Email templates has been loaded',
55
- })
56
- );
57
- },
58
- onError() {
59
- toggleNotification({
60
- type: 'warning',
61
- message: { id: 'notification.error', defaultMessage: 'An error occured' },
62
- });
63
- },
64
- });
65
-
66
- const isLoading = isLoadingForPermissions || isLoadingData !== 'success';
67
-
68
- const handleToggle = () => {
69
- setIsModalOpen((prev) => !prev);
70
- };
71
-
72
- const handleEditClick = (template) => {
73
- setTemplateToEdit(template);
74
- handleToggle();
75
- };
76
-
77
- const submitMutation = useMutation((body) => putEmailTemplate({ 'email-templates': body }), {
78
- async onSuccess() {
79
- await queryClient.invalidateQueries('email-templates');
80
-
81
- toggleNotification({
82
- type: 'success',
83
- message: { id: 'notification.success.saved', defaultMessage: 'Saved' },
84
- });
85
-
86
- trackUsageRef.current('didEditEmailTemplates');
87
-
88
- unlockApp();
89
- handleToggle();
90
- },
91
- onError() {
92
- toggleNotification({
93
- type: 'warning',
94
- message: { id: 'notification.error', defaultMessage: 'An error occured' },
95
- });
96
- unlockApp();
97
- },
98
- refetchActive: true,
99
- });
100
- const { isLoading: isSubmittingForm } = submitMutation;
101
-
102
- const handleSubmit = (body) => {
103
- lockApp();
104
- trackUsageRef.current('willEditEmailTemplates');
105
-
106
- const editedTemplates = { ...data, [templateToEdit]: body };
107
- submitMutation.mutate(editedTemplates);
108
- };
109
-
110
- if (isLoading) {
111
- return (
112
- <Main aria-busy="true">
113
- <SettingsPageTitle
114
- name={formatMessage({
115
- id: getTrad('HeaderNav.link.emailTemplates'),
116
- defaultMessage: 'Email templates',
117
- })}
118
- />
119
- <HeaderLayout
120
- title={formatMessage({
121
- id: getTrad('HeaderNav.link.emailTemplates'),
122
- defaultMessage: 'Email templates',
123
- })}
124
- />
125
- <ContentLayout>
126
- <LoadingIndicatorPage />
127
- </ContentLayout>
128
- </Main>
129
- );
130
- }
131
-
132
- return (
133
- <Main aria-busy={isSubmittingForm}>
134
- <SettingsPageTitle
135
- name={formatMessage({
136
- id: getTrad('HeaderNav.link.emailTemplates'),
137
- defaultMessage: 'Email templates',
138
- })}
139
- />
140
- <HeaderLayout
141
- title={formatMessage({
142
- id: getTrad('HeaderNav.link.emailTemplates'),
143
- defaultMessage: 'Email templates',
144
- })}
145
- />
146
- <ContentLayout>
147
- <EmailTable onEditClick={handleEditClick} canUpdate={canUpdate} />
148
- {isModalOpen && (
149
- <EmailForm
150
- template={data[templateToEdit]}
151
- onToggle={handleToggle}
152
- onSubmit={handleSubmit}
153
- />
154
- )}
155
- </ContentLayout>
156
- </Main>
157
- );
158
- };
159
-
160
- export default ProtectedEmailTemplatesPage;
@@ -1,17 +0,0 @@
1
- import { getFetchClient } from '@strapi/helper-plugin';
2
- import { getRequestURL } from '../../../utils';
3
-
4
- const fetchData = async () => {
5
- const { get } = getFetchClient();
6
- const { data } = await get(getRequestURL('email-templates'));
7
-
8
- return data;
9
- };
10
-
11
- const putEmailTemplate = (body) => {
12
- const { put } = getFetchClient();
13
-
14
- return put(getRequestURL('email-templates'), body);
15
- };
16
-
17
- export { fetchData, putEmailTemplate };
@@ -1,272 +0,0 @@
1
- import React, { useMemo, useRef, useState } from 'react';
2
- import { useIntl } from 'react-intl';
3
- import {
4
- SettingsPageTitle,
5
- LoadingIndicatorPage,
6
- useTracking,
7
- useNotification,
8
- useOverlayBlocker,
9
- CheckPagePermissions,
10
- useRBAC,
11
- useFocusWhenNavigate,
12
- onRowClick,
13
- stopPropagation,
14
- } from '@strapi/helper-plugin';
15
- import has from 'lodash/has';
16
- import upperFirst from 'lodash/upperFirst';
17
- import {
18
- HeaderLayout,
19
- Layout,
20
- ContentLayout,
21
- Main,
22
- useNotifyAT,
23
- Table,
24
- Thead,
25
- Tr,
26
- Th,
27
- Tbody,
28
- Td,
29
- Typography,
30
- IconButton,
31
- VisuallyHidden,
32
- } from '@strapi/design-system';
33
- import { Pencil } from '@strapi/icons';
34
- import { useQuery, useMutation, useQueryClient } from 'react-query';
35
- import forms from './utils/forms';
36
- import { fetchData, putProvider } from './utils/api';
37
- import createProvidersArray from './utils/createProvidersArray';
38
- import { getTrad } from '../../utils';
39
- import pluginPermissions from '../../permissions';
40
- import FormModal from '../../components/FormModal';
41
-
42
- export const ProvidersPage = () => {
43
- const { formatMessage } = useIntl();
44
- useFocusWhenNavigate();
45
- const { notifyStatus } = useNotifyAT();
46
- const queryClient = useQueryClient();
47
- const { trackUsage } = useTracking();
48
- const trackUsageRef = useRef(trackUsage);
49
- const [isOpen, setIsOpen] = useState(false);
50
- const [isSubmiting, setIsSubmiting] = useState(false);
51
- const [providerToEditName, setProviderToEditName] = useState(null);
52
- const toggleNotification = useNotification();
53
- const { lockApp, unlockApp } = useOverlayBlocker();
54
-
55
- const updatePermissions = useMemo(() => {
56
- return { update: pluginPermissions.updateProviders };
57
- }, []);
58
-
59
- const {
60
- isLoading: isLoadingForPermissions,
61
- allowedActions: { canUpdate },
62
- } = useRBAC(updatePermissions);
63
-
64
- const {
65
- isLoading: isLoadingForData,
66
- data: modifiedData,
67
- isFetching,
68
- } = useQuery('get-providers', () => fetchData(toggleNotification), {
69
- onSuccess() {
70
- notifyStatus(
71
- formatMessage({
72
- id: getTrad('Providers.data.loaded'),
73
- defaultMessage: 'Providers have been loaded',
74
- })
75
- );
76
- },
77
- initialData: {},
78
- });
79
-
80
- const isLoading = isLoadingForData || isFetching;
81
-
82
- const submitMutation = useMutation(putProvider, {
83
- async onSuccess() {
84
- await queryClient.invalidateQueries('get-providers');
85
- toggleNotification({
86
- type: 'info',
87
- message: { id: getTrad('notification.success.submit') },
88
- });
89
-
90
- trackUsageRef.current('didEditAuthenticationProvider');
91
- setIsSubmiting(false);
92
- handleToggleModal();
93
- unlockApp();
94
- },
95
- onError() {
96
- toggleNotification({
97
- type: 'warning',
98
- message: { id: 'notification.error' },
99
- });
100
- unlockApp();
101
- setIsSubmiting(false);
102
- },
103
- refetchActive: false,
104
- });
105
-
106
- const providers = useMemo(() => createProvidersArray(modifiedData), [modifiedData]);
107
-
108
- const rowCount = providers.length;
109
-
110
- const isProviderWithSubdomain = useMemo(() => {
111
- if (!providerToEditName) {
112
- return false;
113
- }
114
-
115
- const providerToEdit = providers.find((obj) => obj.name === providerToEditName);
116
-
117
- return has(providerToEdit, 'subdomain');
118
- }, [providers, providerToEditName]);
119
-
120
- const pageTitle = formatMessage({
121
- id: getTrad('HeaderNav.link.providers'),
122
- defaultMessage: 'Providers',
123
- });
124
-
125
- const layoutToRender = useMemo(() => {
126
- if (providerToEditName === 'email') {
127
- return forms.email;
128
- }
129
-
130
- if (isProviderWithSubdomain) {
131
- return forms.providersWithSubdomain;
132
- }
133
-
134
- return forms.providers;
135
- }, [providerToEditName, isProviderWithSubdomain]);
136
-
137
- const handleToggleModal = () => {
138
- setIsOpen((prev) => !prev);
139
- };
140
-
141
- const handleClickEdit = (provider) => {
142
- if (canUpdate) {
143
- setProviderToEditName(provider.name);
144
- handleToggleModal();
145
- }
146
- };
147
-
148
- const handleSubmit = async (values) => {
149
- setIsSubmiting(true);
150
-
151
- lockApp();
152
-
153
- trackUsageRef.current('willEditAuthenticationProvider');
154
-
155
- const body = { ...modifiedData, [providerToEditName]: values };
156
-
157
- submitMutation.mutate({ providers: body });
158
- };
159
-
160
- return (
161
- <Layout>
162
- <SettingsPageTitle name={pageTitle} />
163
- <Main>
164
- <HeaderLayout
165
- title={formatMessage({
166
- id: getTrad('HeaderNav.link.providers'),
167
- defaultMessage: 'Providers',
168
- })}
169
- />
170
- {isLoading || isLoadingForPermissions ? (
171
- <LoadingIndicatorPage />
172
- ) : (
173
- <ContentLayout>
174
- <Table colCount={3} rowCount={rowCount + 1}>
175
- <Thead>
176
- <Tr>
177
- <Th>
178
- <Typography variant="sigma" textColor="neutral600">
179
- {formatMessage({ id: 'global.name', defaultMessage: 'Name' })}
180
- </Typography>
181
- </Th>
182
- <Th>
183
- <Typography variant="sigma" textColor="neutral600">
184
- {formatMessage({ id: getTrad('Providers.status'), defaultMessage: 'Status' })}
185
- </Typography>
186
- </Th>
187
- <Th>
188
- <Typography variant="sigma">
189
- <VisuallyHidden>
190
- {formatMessage({
191
- id: 'global.settings',
192
- defaultMessage: 'Settings',
193
- })}
194
- </VisuallyHidden>
195
- </Typography>
196
- </Th>
197
- </Tr>
198
- </Thead>
199
- <Tbody>
200
- {providers.map((provider) => (
201
- <Tr
202
- key={provider.name}
203
- {...onRowClick({
204
- fn: () => handleClickEdit(provider),
205
- condition: canUpdate,
206
- })}
207
- >
208
- <Td width="45%">
209
- <Typography fontWeight="semiBold" textColor="neutral800">
210
- {provider.name}
211
- </Typography>
212
- </Td>
213
- <Td width="65%">
214
- <Typography
215
- textColor={provider.enabled ? 'success600' : 'danger600'}
216
- data-testid={`enable-${provider.name}`}
217
- >
218
- {provider.enabled
219
- ? formatMessage({
220
- id: 'global.enabled',
221
- defaultMessage: 'Enabled',
222
- })
223
- : formatMessage({
224
- id: 'global.disabled',
225
- defaultMessage: 'Disabled',
226
- })}
227
- </Typography>
228
- </Td>
229
- <Td {...stopPropagation}>
230
- {canUpdate && (
231
- <IconButton
232
- onClick={() => handleClickEdit(provider)}
233
- noBorder
234
- icon={<Pencil />}
235
- label="Edit"
236
- />
237
- )}
238
- </Td>
239
- </Tr>
240
- ))}
241
- </Tbody>
242
- </Table>
243
- </ContentLayout>
244
- )}
245
- </Main>
246
- <FormModal
247
- initialData={modifiedData[providerToEditName]}
248
- isOpen={isOpen}
249
- isSubmiting={isSubmiting}
250
- layout={layoutToRender}
251
- headerBreadcrumbs={[
252
- formatMessage({
253
- id: getTrad('PopUpForm.header.edit.providers'),
254
- defaultMessage: 'Edit Provider',
255
- }),
256
- upperFirst(providerToEditName),
257
- ]}
258
- onToggle={handleToggleModal}
259
- onSubmit={handleSubmit}
260
- providerToEditName={providerToEditName}
261
- />
262
- </Layout>
263
- );
264
- };
265
-
266
- const ProtectedProvidersPage = () => (
267
- <CheckPagePermissions permissions={pluginPermissions.readProviders}>
268
- <ProvidersPage />
269
- </CheckPagePermissions>
270
- );
271
-
272
- export default ProtectedProvidersPage;
@@ -1,54 +0,0 @@
1
- import produce from 'immer';
2
- import set from 'lodash/set';
3
-
4
- const initialState = {
5
- formErrors: {},
6
- isLoading: true,
7
- initialData: {},
8
- modifiedData: {},
9
- };
10
-
11
- const reducer = (state, action) =>
12
- // eslint-disable-next-line consistent-return
13
- produce(state, (draftState) => {
14
- switch (action.type) {
15
- case 'GET_DATA': {
16
- draftState.isLoading = true;
17
- draftState.initialData = {};
18
- draftState.modifiedData = {};
19
-
20
- break;
21
- }
22
-
23
- case 'GET_DATA_SUCCEEDED': {
24
- draftState.isLoading = false;
25
- draftState.initialData = action.data;
26
- draftState.modifiedData = action.data;
27
-
28
- break;
29
- }
30
- case 'GET_DATA_ERROR': {
31
- draftState.isLoading = true;
32
- break;
33
- }
34
- case 'ON_CHANGE': {
35
- set(draftState, ['modifiedData', ...action.keys.split('.')], action.value);
36
- break;
37
- }
38
- case 'RESET_FORM': {
39
- draftState.modifiedData = state.initialData;
40
- draftState.formErrors = {};
41
- break;
42
- }
43
- case 'SET_ERRORS': {
44
- draftState.formErrors = action.errors;
45
- break;
46
- }
47
- default: {
48
- return draftState;
49
- }
50
- }
51
- });
52
-
53
- export default reducer;
54
- export { initialState };
@@ -1,25 +0,0 @@
1
- import { getFetchClient } from '@strapi/helper-plugin';
2
- import { getRequestURL } from '../../../utils';
3
-
4
- // eslint-disable-next-line import/prefer-default-export
5
- export const fetchData = async (toggleNotification) => {
6
- try {
7
- const { get } = getFetchClient();
8
- const { data } = await get(getRequestURL('providers'));
9
-
10
- return data;
11
- } catch (err) {
12
- toggleNotification({
13
- type: 'warning',
14
- message: { id: 'notification.error' },
15
- });
16
-
17
- throw new Error('error');
18
- }
19
- };
20
-
21
- export const putProvider = (body) => {
22
- const { put } = getFetchClient();
23
-
24
- return put(getRequestURL('providers'), body);
25
- };