@strapi/plugin-documentation 5.0.0-beta.0 → 5.0.0-beta.1

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 (184) hide show
  1. package/README.md +0 -1
  2. package/dist/_chunks/{index-7xstUX8_.mjs → App-ig-uE4do.mjs} +48 -14
  3. package/dist/_chunks/App-ig-uE4do.mjs.map +1 -0
  4. package/dist/_chunks/{index-D1KkfApT.js → App-o4uH8gaQ.js} +73 -20
  5. package/dist/_chunks/App-o4uH8gaQ.js.map +1 -0
  6. package/dist/_chunks/{index-VpLAJXMs.mjs → Settings-3hsPOP_b.mjs} +64 -33
  7. package/dist/_chunks/Settings-3hsPOP_b.mjs.map +1 -0
  8. package/dist/_chunks/{index-NbPCucJl.js → Settings-XmOzLTUn.js} +69 -37
  9. package/dist/_chunks/Settings-XmOzLTUn.js.map +1 -0
  10. package/dist/_chunks/getTrad-bnElvR8_.js +5 -0
  11. package/dist/_chunks/getTrad-bnElvR8_.js.map +1 -0
  12. package/dist/_chunks/getTrad-md7Tjpcv.mjs +6 -0
  13. package/dist/_chunks/getTrad-md7Tjpcv.mjs.map +1 -0
  14. package/{server/public/index.html → dist/_chunks/index-MKWIGajW.mjs} +9 -4
  15. package/dist/_chunks/index-MKWIGajW.mjs.map +1 -0
  16. package/dist/_chunks/index-WbbYm9_u.js +75 -0
  17. package/dist/_chunks/index-WbbYm9_u.js.map +1 -0
  18. package/dist/_chunks/{index-NvJ4m2q5.mjs → index-jpDwTC-Q.mjs} +121 -117
  19. package/dist/_chunks/index-jpDwTC-Q.mjs.map +1 -0
  20. package/dist/_chunks/{index-r7HsQTou.js → index-vNbIS1u2.js} +119 -115
  21. package/dist/_chunks/index-vNbIS1u2.js.map +1 -0
  22. package/dist/_chunks/login-HAajOKpu.js +150 -0
  23. package/dist/_chunks/login-HAajOKpu.js.map +1 -0
  24. package/{server/public/login.html → dist/_chunks/login-slUa679p.mjs} +6 -1
  25. package/dist/_chunks/login-slUa679p.mjs.map +1 -0
  26. package/dist/admin/index.js +1 -1
  27. package/dist/admin/index.mjs +2 -2
  28. package/dist/admin/src/components/SettingsForm.d.ts +8 -0
  29. package/dist/admin/src/constants.d.ts +18 -0
  30. package/dist/admin/src/index.d.ts +14 -0
  31. package/dist/admin/src/pages/App.d.ts +2 -0
  32. package/dist/admin/src/pages/Settings.d.ts +2 -0
  33. package/dist/admin/src/pluginId.d.ts +1 -0
  34. package/dist/admin/src/services/api.d.ts +25 -0
  35. package/dist/admin/src/types.d.ts +16 -0
  36. package/dist/admin/src/utils/baseQuery.d.ts +20 -0
  37. package/dist/admin/src/utils/getTrad.d.ts +1 -0
  38. package/dist/admin/src/utils/index.d.ts +2 -0
  39. package/dist/admin/src/utils/prefixPluginTranslations.d.ts +2 -0
  40. package/dist/server/index.js +1263 -0
  41. package/dist/server/index.js.map +1 -0
  42. package/dist/server/index.mjs +1238 -0
  43. package/dist/server/index.mjs.map +1 -0
  44. package/dist/server/src/bootstrap.d.ts +5 -0
  45. package/dist/server/src/bootstrap.d.ts.map +1 -0
  46. package/dist/server/src/config/default-plugin-config.d.ts +3 -0
  47. package/dist/server/src/config/default-plugin-config.d.ts.map +1 -0
  48. package/dist/server/src/config/index.d.ts +4 -0
  49. package/dist/server/src/config/index.d.ts.map +1 -0
  50. package/dist/server/src/controllers/documentation.d.ts +12 -0
  51. package/dist/server/src/controllers/documentation.d.ts.map +1 -0
  52. package/dist/server/src/controllers/index.d.ts +14 -0
  53. package/dist/server/src/controllers/index.d.ts.map +1 -0
  54. package/dist/server/src/index.d.ts +91 -0
  55. package/dist/server/src/index.d.ts.map +1 -0
  56. package/dist/server/src/middlewares/documentation.d.ts +5 -0
  57. package/dist/server/src/middlewares/documentation.d.ts.map +1 -0
  58. package/dist/server/src/middlewares/restrict-access.d.ts +4 -0
  59. package/dist/server/src/middlewares/restrict-access.d.ts.map +1 -0
  60. package/dist/server/src/register.d.ts +5 -0
  61. package/dist/server/src/register.d.ts.map +1 -0
  62. package/dist/server/src/routes/index.d.ts +36 -0
  63. package/dist/server/src/routes/index.d.ts.map +1 -0
  64. package/dist/server/src/services/__mocks__/mock-content-types.d.ts +449 -0
  65. package/dist/server/src/services/__mocks__/mock-content-types.d.ts.map +1 -0
  66. package/dist/server/src/services/__mocks__/mock-strapi-data.d.ts +592 -0
  67. package/dist/server/src/services/__mocks__/mock-strapi-data.d.ts.map +1 -0
  68. package/dist/server/src/services/documentation.d.ts +36 -0
  69. package/dist/server/src/services/documentation.d.ts.map +1 -0
  70. package/dist/server/src/services/helpers/build-api-endpoint-path.d.ts +7 -0
  71. package/dist/server/src/services/helpers/build-api-endpoint-path.d.ts.map +1 -0
  72. package/dist/server/src/services/helpers/build-component-schema.d.ts +4 -0
  73. package/dist/server/src/services/helpers/build-component-schema.d.ts.map +1 -0
  74. package/dist/server/src/services/helpers/index.d.ts +4 -0
  75. package/dist/server/src/services/helpers/index.d.ts.map +1 -0
  76. package/dist/server/src/services/helpers/utils/clean-schema-attributes.d.ts +15 -0
  77. package/dist/server/src/services/helpers/utils/clean-schema-attributes.d.ts.map +1 -0
  78. package/dist/server/src/services/helpers/utils/get-api-responses.d.ts +15 -0
  79. package/dist/server/src/services/helpers/utils/get-api-responses.d.ts.map +1 -0
  80. package/dist/server/src/services/helpers/utils/get-schema-data.d.ts +12 -0
  81. package/dist/server/src/services/helpers/utils/get-schema-data.d.ts.map +1 -0
  82. package/dist/server/src/services/helpers/utils/loop-content-type-names.d.ts +7 -0
  83. package/dist/server/src/services/helpers/utils/loop-content-type-names.d.ts.map +1 -0
  84. package/dist/server/src/services/helpers/utils/pascal-case.d.ts +3 -0
  85. package/dist/server/src/services/helpers/utils/pascal-case.d.ts.map +1 -0
  86. package/dist/server/src/services/helpers/utils/query-params.d.ts +4 -0
  87. package/dist/server/src/services/helpers/utils/query-params.d.ts.map +1 -0
  88. package/dist/server/src/services/helpers/utils/routes.d.ts +3 -0
  89. package/dist/server/src/services/helpers/utils/routes.d.ts.map +1 -0
  90. package/dist/server/src/services/index.d.ts +43 -0
  91. package/dist/server/src/services/index.d.ts.map +1 -0
  92. package/dist/server/src/services/override.d.ts +21 -0
  93. package/dist/server/src/services/override.d.ts.map +1 -0
  94. package/dist/server/src/services/utils/get-plugins-that-need-documentation.d.ts +4 -0
  95. package/dist/server/src/services/utils/get-plugins-that-need-documentation.d.ts.map +1 -0
  96. package/dist/server/src/types.d.ts +28 -0
  97. package/dist/server/src/types.d.ts.map +1 -0
  98. package/dist/server/src/utils.d.ts +12 -0
  99. package/dist/server/src/utils.d.ts.map +1 -0
  100. package/package.json +33 -15
  101. package/strapi-server.js +1 -1
  102. package/.eslintignore +0 -1
  103. package/.eslintrc +0 -17
  104. package/admin/src/constants.js +0 -17
  105. package/admin/src/hooks/useDocumentation.js +0 -81
  106. package/admin/src/index.js +0 -62
  107. package/admin/src/pages/PluginPage/index.jsx +0 -212
  108. package/admin/src/pages/PluginPage/tests/index.test.jsx +0 -160
  109. package/admin/src/pages/SettingsPage/index.jsx +0 -202
  110. package/admin/src/pages/SettingsPage/tests/index.test.jsx +0 -72
  111. package/admin/src/pluginId.js +0 -5
  112. package/admin/src/translations/ar.json +0 -20
  113. package/admin/src/translations/cs.json +0 -21
  114. package/admin/src/translations/de.json +0 -26
  115. package/admin/src/translations/dk.json +0 -39
  116. package/admin/src/translations/en.json +0 -39
  117. package/admin/src/translations/es.json +0 -39
  118. package/admin/src/translations/fr.json +0 -26
  119. package/admin/src/translations/id.json +0 -24
  120. package/admin/src/translations/it.json +0 -26
  121. package/admin/src/translations/ko.json +0 -39
  122. package/admin/src/translations/ms.json +0 -23
  123. package/admin/src/translations/nl.json +0 -21
  124. package/admin/src/translations/pl.json +0 -39
  125. package/admin/src/translations/pt-BR.json +0 -21
  126. package/admin/src/translations/pt.json +0 -21
  127. package/admin/src/translations/ru.json +0 -39
  128. package/admin/src/translations/sk.json +0 -24
  129. package/admin/src/translations/sv.json +0 -39
  130. package/admin/src/translations/th.json +0 -24
  131. package/admin/src/translations/tr.json +0 -39
  132. package/admin/src/translations/uk.json +0 -23
  133. package/admin/src/translations/vi.json +0 -24
  134. package/admin/src/translations/zh-Hans.json +0 -28
  135. package/admin/src/translations/zh.json +0 -39
  136. package/admin/src/utils/getTrad.js +0 -5
  137. package/admin/src/utils/index.js +0 -2
  138. package/admin/src/utils/prefixPluginTranslations.js +0 -13
  139. package/dist/_chunks/index-7xstUX8_.mjs.map +0 -1
  140. package/dist/_chunks/index-D1KkfApT.js.map +0 -1
  141. package/dist/_chunks/index-NbPCucJl.js.map +0 -1
  142. package/dist/_chunks/index-NvJ4m2q5.mjs.map +0 -1
  143. package/dist/_chunks/index-VpLAJXMs.mjs.map +0 -1
  144. package/dist/_chunks/index-r7HsQTou.js.map +0 -1
  145. package/dist/_chunks/useDocumentation-6Ks-_Ms6.mjs +0 -68
  146. package/dist/_chunks/useDocumentation-6Ks-_Ms6.mjs.map +0 -1
  147. package/dist/_chunks/useDocumentation-S0e4mU-U.js +0 -67
  148. package/dist/_chunks/useDocumentation-S0e4mU-U.js.map +0 -1
  149. package/jest.config.front.js +0 -7
  150. package/jest.config.js +0 -6
  151. package/packup.config.ts +0 -22
  152. package/server/bootstrap.js +0 -54
  153. package/server/config/default-plugin-config.js +0 -35
  154. package/server/config/index.js +0 -7
  155. package/server/controllers/documentation.js +0 -241
  156. package/server/controllers/index.js +0 -7
  157. package/server/index.js +0 -17
  158. package/server/middlewares/documentation.js +0 -25
  159. package/server/middlewares/index.js +0 -7
  160. package/server/middlewares/restrict-access.js +0 -24
  161. package/server/register.js +0 -11
  162. package/server/routes/index.js +0 -84
  163. package/server/services/__mocks__/mock-content-types.js +0 -264
  164. package/server/services/__mocks__/mock-strapi-data.js +0 -183
  165. package/server/services/__tests__/build-component-schema.test.js +0 -761
  166. package/server/services/__tests__/documentation.test.js +0 -481
  167. package/server/services/__tests__/override.test.js +0 -85
  168. package/server/services/documentation.js +0 -246
  169. package/server/services/helpers/build-api-endpoint-path.js +0 -186
  170. package/server/services/helpers/build-component-schema.js +0 -254
  171. package/server/services/helpers/index.js +0 -9
  172. package/server/services/helpers/utils/clean-schema-attributes.js +0 -246
  173. package/server/services/helpers/utils/get-api-responses.js +0 -105
  174. package/server/services/helpers/utils/get-schema-data.js +0 -32
  175. package/server/services/helpers/utils/loop-content-type-names.js +0 -55
  176. package/server/services/helpers/utils/pascal-case.js +0 -9
  177. package/server/services/helpers/utils/query-params.js +0 -105
  178. package/server/services/helpers/utils/routes.js +0 -10
  179. package/server/services/index.js +0 -9
  180. package/server/services/override.js +0 -52
  181. package/server/services/utils/default-openapi-components.js +0 -40
  182. package/server/services/utils/get-plugins-that-need-documentation.js +0 -24
  183. package/tests/server.js +0 -37
  184. package/tests/setup.js +0 -15
@@ -1,212 +0,0 @@
1
- import React, { useState } from 'react';
2
-
3
- import {
4
- LinkButton,
5
- ContentLayout,
6
- Flex,
7
- HeaderLayout,
8
- IconButton,
9
- Layout,
10
- Table,
11
- Tbody,
12
- Td,
13
- Th,
14
- Thead,
15
- Tr,
16
- Typography,
17
- EmptyStateLayout,
18
- } from '@strapi/design-system';
19
- import { Eye as Show, Refresh as Reload, Trash } from '@strapi/icons';
20
- import { ConfirmDialog, useRBAC, Page } from '@strapi/strapi/admin';
21
- import { Helmet } from 'react-helmet';
22
- import { useIntl } from 'react-intl';
23
- import styled from 'styled-components';
24
-
25
- import { PERMISSIONS } from '../../constants';
26
- import { useDocumentation } from '../../hooks/useDocumentation';
27
- import { getTrad } from '../../utils';
28
-
29
- const PluginPage = () => {
30
- const { formatMessage } = useIntl();
31
- const { data, isLoading, isError, remove, regenerate } = useDocumentation();
32
- const [showConfirmDelete, setShowConfirmDelete] = useState(false);
33
- const [versionToDelete, setVersionToDelete] = useState();
34
- const { allowedActions } = useRBAC(PERMISSIONS);
35
-
36
- const colCount = 4;
37
- const rowCount = (data?.docVersions?.length || 0) + 1;
38
-
39
- const handleRegenerateDoc = (version) => {
40
- regenerate.mutate({ version, prefix: data?.prefix });
41
- };
42
-
43
- const handleShowConfirmDelete = () => {
44
- setShowConfirmDelete(!showConfirmDelete);
45
- };
46
-
47
- const handleConfirmDelete = async () => {
48
- await remove.mutateAsync({ prefix: data?.prefix, version: versionToDelete });
49
- setShowConfirmDelete(!showConfirmDelete);
50
- };
51
-
52
- const handleClickDelete = (version) => {
53
- setVersionToDelete(version);
54
- setShowConfirmDelete(!showConfirmDelete);
55
- };
56
-
57
- const title = formatMessage({
58
- id: getTrad('plugin.name'),
59
- defaultMessage: 'Documentation',
60
- });
61
-
62
- if (isLoading) {
63
- return <Page.Loading />;
64
- }
65
-
66
- if (isError) {
67
- return <Page.Error />;
68
- }
69
-
70
- return (
71
- <Layout>
72
- <Helmet title={title} />
73
- <Page.Main>
74
- <HeaderLayout
75
- title={title}
76
- subtitle={formatMessage({
77
- id: getTrad('pages.PluginPage.header.description'),
78
- defaultMessage: 'Configure the documentation plugin',
79
- })}
80
- primaryAction={
81
- <OpenDocLink
82
- disabled={!allowedActions.canOpen || !data?.currentVersion || !data?.prefix}
83
- href={createDocumentationHref(`${data?.prefix}/v${data?.currentVersion}`)}
84
- startIcon={<Show />}
85
- >
86
- {formatMessage({
87
- id: getTrad('pages.PluginPage.Button.open'),
88
- defaultMessage: 'Open Documentation',
89
- })}
90
- </OpenDocLink>
91
- }
92
- />
93
- <ContentLayout>
94
- {data?.docVersions.length ? (
95
- <Table colCount={colCount} rowCount={rowCount}>
96
- <Thead>
97
- <Tr>
98
- <Th>
99
- <Typography variant="sigma" textColor="neutral600">
100
- {formatMessage({
101
- id: getTrad('pages.PluginPage.table.version'),
102
- defaultMessage: 'Version',
103
- })}
104
- </Typography>
105
- </Th>
106
- <Th>
107
- <Typography variant="sigma" textColor="neutral600">
108
- {formatMessage({
109
- id: getTrad('pages.PluginPage.table.generated'),
110
- defaultMessage: 'Last Generated',
111
- })}
112
- </Typography>
113
- </Th>
114
- </Tr>
115
- </Thead>
116
- <Tbody>
117
- {data.docVersions
118
- .sort((a, b) => (a.generatedDate < b.generatedDate ? 1 : -1))
119
- .map((doc) => (
120
- <Tr key={doc.version}>
121
- <Td width="50%">
122
- <Typography>{doc.version}</Typography>
123
- </Td>
124
- <Td width="50%">
125
- <Typography>{doc.generatedDate}</Typography>
126
- </Td>
127
- <Td>
128
- <Flex justifyContent="end" onClick={(e) => e.stopPropagation()}>
129
- <IconButton
130
- forwardedAs="a"
131
- disabled={!allowedActions.canOpen}
132
- href={createDocumentationHref(`${data.prefix}/v${doc.version}`)}
133
- noBorder
134
- icon={<Show />}
135
- target="_blank"
136
- rel="noopener noreferrer"
137
- label={formatMessage(
138
- {
139
- id: getTrad('pages.PluginPage.table.icon.show'),
140
- defaultMessage: 'Open {target}',
141
- },
142
- { target: `${doc.version}` }
143
- )}
144
- />
145
- {allowedActions.canRegenerate ? (
146
- <IconButton
147
- onClick={() => handleRegenerateDoc(doc.version)}
148
- noBorder
149
- icon={<Reload />}
150
- label={formatMessage(
151
- {
152
- id: getTrad('pages.PluginPage.table.icon.regenerate'),
153
- defaultMessage: 'Regenerate {target}',
154
- },
155
- { target: `${doc.version}` }
156
- )}
157
- />
158
- ) : null}
159
- {allowedActions.canUpdate && doc.version !== data.currentVersion ? (
160
- <IconButton
161
- onClick={() => handleClickDelete(doc.version)}
162
- noBorder
163
- icon={<Trash />}
164
- label={formatMessage(
165
- {
166
- id: 'global.delete-target',
167
- defaultMessage: 'Delete {target}',
168
- },
169
- { target: `${doc.version}` }
170
- )}
171
- />
172
- ) : null}
173
- </Flex>
174
- </Td>
175
- </Tr>
176
- ))}
177
- </Tbody>
178
- </Table>
179
- ) : (
180
- <EmptyStateLayout />
181
- )}
182
- </ContentLayout>
183
- <ConfirmDialog
184
- onConfirm={handleConfirmDelete}
185
- onClose={handleShowConfirmDelete}
186
- isOpen={showConfirmDelete}
187
- />
188
- </Page.Main>
189
- </Layout>
190
- );
191
- };
192
-
193
- /**
194
- * TODO: should this be fixed in the DS?
195
- */
196
- const OpenDocLink = styled(LinkButton)`
197
- text-decoration: none;
198
- `;
199
-
200
- const createDocumentationHref = (path) => {
201
- if (path.startsWith('http')) {
202
- return path;
203
- }
204
-
205
- if (path.startsWith('/')) {
206
- return `${window.strapi.backendURL}${path}`;
207
- }
208
-
209
- return `${window.strapi.backendURL}/${path}`;
210
- };
211
-
212
- export default PluginPage;
@@ -1,160 +0,0 @@
1
- import React from 'react';
2
-
3
- import { render, waitFor } from '@strapi/strapi/admin/test';
4
-
5
- import PluginPage from '../index';
6
-
7
- const versions = ['2.0.0', '1.2.0', '1.0.0'];
8
-
9
- describe('PluginPage', () => {
10
- it('render the plugin page correctly', async () => {
11
- const { getByRole, queryByText, getByText } = render(<PluginPage />);
12
-
13
- await waitFor(() => expect(queryByText('Loading content.')).not.toBeInTheDocument());
14
-
15
- expect(getByRole('heading', { name: 'Documentation' })).toBeInTheDocument();
16
- expect(getByText('Configure the documentation plugin')).toBeInTheDocument();
17
- expect(getByRole('link', { name: 'Open Documentation' })).toHaveAttribute(
18
- 'aria-disabled',
19
- 'false'
20
- );
21
-
22
- expect(getByRole('heading', { name: 'Documentation' })).toBeInTheDocument();
23
- expect(getByText('Configure the documentation plugin')).toBeInTheDocument();
24
- expect(getByRole('link', { name: 'Open Documentation' })).toBeInTheDocument();
25
-
26
- expect(getByRole('grid')).toBeInTheDocument();
27
- expect(getByRole('gridcell', { name: 'Version' })).toBeInTheDocument();
28
- expect(getByRole('gridcell', { name: 'Last Generated' })).toBeInTheDocument();
29
-
30
- versions.forEach((version) => {
31
- expect(getByRole('gridcell', { name: version })).toBeInTheDocument();
32
- expect(getByRole('link', { name: `Open ${version}` })).toBeInTheDocument();
33
- expect(getByRole('button', { name: `Regenerate ${version}` })).toBeInTheDocument();
34
-
35
- /**
36
- * You can't delete the original version
37
- */
38
- if (version !== '1.0.0') {
39
- expect(getByRole('button', { name: `Delete ${version}` })).toBeInTheDocument();
40
- }
41
- });
42
- });
43
-
44
- describe('actions', () => {
45
- it('should open the documentation', async () => {
46
- const { getByRole, queryByText, user } = render(<PluginPage />);
47
-
48
- await waitFor(() => expect(queryByText('Loading content.')).not.toBeInTheDocument());
49
-
50
- expect(getByRole('link', { name: 'Open Documentation' })).toHaveAttribute(
51
- 'href',
52
- 'http://localhost:1337/documentation/v1.0.0'
53
- );
54
-
55
- await user.click(getByRole('link', { name: 'Open Documentation' }));
56
-
57
- versions.forEach((version) => {
58
- expect(getByRole('link', { name: `Open ${version}` })).toHaveAttribute(
59
- 'href',
60
- `http://localhost:1337/documentation/v${version}`
61
- );
62
- });
63
- });
64
-
65
- it('should regenerate the documentation', async () => {
66
- const { getByRole, queryByText, user, getByText } = render(<PluginPage />);
67
-
68
- await waitFor(() => expect(queryByText('Loading content.')).not.toBeInTheDocument());
69
-
70
- expect(getByRole('button', { name: 'Regenerate 2.0.0' })).toBeInTheDocument();
71
-
72
- await user.click(getByRole('button', { name: 'Regenerate 2.0.0' }));
73
-
74
- expect(getByText('Successfully generated documentation')).toBeInTheDocument();
75
- });
76
-
77
- it('should delete the documentation', async () => {
78
- const { getByRole, queryByText, user, getByText } = render(<PluginPage />);
79
-
80
- await waitFor(() => expect(queryByText('Loading content.')).not.toBeInTheDocument());
81
-
82
- expect(getByRole('button', { name: 'Delete 2.0.0' })).toBeInTheDocument();
83
-
84
- await user.click(getByRole('button', { name: 'Delete 2.0.0' }));
85
-
86
- expect(getByRole('dialog', { name: 'Confirmation' })).toBeInTheDocument();
87
- expect(getByRole('button', { name: 'Confirm' })).toBeInTheDocument();
88
- expect(getByRole('button', { name: 'Cancel' })).toBeInTheDocument();
89
-
90
- await user.click(getByRole('button', { name: 'Confirm' }));
91
-
92
- expect(getByText('Successfully deleted documentation')).toBeInTheDocument();
93
- });
94
- });
95
-
96
- describe('permissions', () => {
97
- it("should always disable the 'Open Documentation' link if the user cannot open", async () => {
98
- const { getByRole, queryByText } = render(<PluginPage />, {
99
- providerOptions: { permissions: () => [] },
100
- });
101
-
102
- await waitFor(() => expect(queryByText('Loading content.')).not.toBeInTheDocument());
103
-
104
- expect(getByRole('link', { name: 'Open Documentation' })).toHaveAttribute(
105
- 'aria-disabled',
106
- 'true'
107
- );
108
-
109
- expect(getByRole('link', { name: 'Open Documentation' })).toHaveAttribute(
110
- 'aria-disabled',
111
- 'true'
112
- );
113
- });
114
-
115
- it('should disabled the open documentation version link in the table if the user cannot open', async () => {
116
- const { getByRole, queryByText } = render(<PluginPage />, {
117
- providerOptions: { permissions: () => [] },
118
- });
119
-
120
- await waitFor(() => expect(queryByText('Loading content.')).not.toBeInTheDocument());
121
-
122
- versions.forEach((version) => {
123
- expect(getByRole('gridcell', { name: version })).toBeInTheDocument();
124
-
125
- expect(getByRole('link', { name: `Open ${version}` })).toHaveAttribute(
126
- 'aria-disabled',
127
- 'true'
128
- );
129
- });
130
- });
131
-
132
- it('should not render the regenerate buttons if the user cannot regenerate', async () => {
133
- const { queryByRole, getByRole, queryByText } = render(<PluginPage />, {
134
- providerOptions: { permissions: () => [] },
135
- });
136
-
137
- await waitFor(() => expect(queryByText('Loading content.')).not.toBeInTheDocument());
138
-
139
- versions.forEach((version) => {
140
- expect(getByRole('gridcell', { name: version })).toBeInTheDocument();
141
-
142
- expect(queryByRole('button', { name: `Regenerate ${version}` })).not.toBeInTheDocument();
143
- });
144
- });
145
-
146
- it('should not render the delete buttons if the user cannot delete', async () => {
147
- const { queryByRole, getByRole, queryByText } = render(<PluginPage />, {
148
- providerOptions: { permissions: () => [] },
149
- });
150
-
151
- await waitFor(() => expect(queryByText('Loading content.')).not.toBeInTheDocument());
152
-
153
- versions.forEach((version) => {
154
- expect(getByRole('gridcell', { name: version })).toBeInTheDocument();
155
-
156
- expect(queryByRole('button', { name: `Delete ${version}` })).not.toBeInTheDocument();
157
- });
158
- });
159
- });
160
- });
@@ -1,202 +0,0 @@
1
- import React, { useState } from 'react';
2
-
3
- import {
4
- Box,
5
- Button,
6
- ContentLayout,
7
- Flex,
8
- Grid,
9
- GridItem,
10
- HeaderLayout,
11
- TextInput,
12
- ToggleInput,
13
- Typography,
14
- FieldAction,
15
- } from '@strapi/design-system';
16
- import { Check, Eye as Show, EyeStriked as Hide } from '@strapi/icons';
17
- import { translatedErrors, Page, useRBAC } from '@strapi/strapi/admin';
18
- import { Form, Formik } from 'formik';
19
- import { useIntl } from 'react-intl';
20
- import styled from 'styled-components';
21
- import * as yup from 'yup';
22
-
23
- import { PERMISSIONS } from '../../constants';
24
- import { useDocumentation } from '../../hooks/useDocumentation';
25
- import { getTrad } from '../../utils';
26
-
27
- const schema = yup.object().shape({
28
- restrictedAccess: yup.boolean(),
29
- password: yup.string().when('restrictedAccess', (value, initSchema) => {
30
- return value ? initSchema.required(translatedErrors.required.id) : initSchema;
31
- }),
32
- });
33
-
34
- const SettingsPage = () => {
35
- const { formatMessage } = useIntl();
36
- const { submit, data, isLoading } = useDocumentation();
37
- const [passwordShown, setPasswordShown] = useState(false);
38
- const { allowedActions } = useRBAC(PERMISSIONS);
39
-
40
- const handleUpdateSettingsSubmit = (body) => {
41
- submit.mutate({
42
- prefix: data?.prefix,
43
- body,
44
- });
45
- };
46
-
47
- if (isLoading) {
48
- return <Page.Loading />;
49
- }
50
-
51
- return (
52
- <Page.Main>
53
- <Formik
54
- initialValues={{
55
- restrictedAccess: data?.documentationAccess.restrictedAccess || false,
56
- password: '',
57
- }}
58
- onSubmit={handleUpdateSettingsSubmit}
59
- validationSchema={schema}
60
- >
61
- {({
62
- handleSubmit,
63
- values,
64
- handleChange,
65
- errors,
66
- setFieldTouched,
67
- setFieldValue,
68
- dirty,
69
- }) => {
70
- return (
71
- <Form noValidate onSubmit={handleSubmit}>
72
- <HeaderLayout
73
- title={formatMessage({
74
- id: getTrad('plugin.name'),
75
- defaultMessage: 'Documentation',
76
- })}
77
- subtitle={formatMessage({
78
- id: getTrad('pages.SettingsPage.header.description'),
79
- defaultMessage: 'Configure the documentation plugin',
80
- })}
81
- primaryAction={
82
- <Button
83
- type="submit"
84
- startIcon={<Check />}
85
- disabled={!dirty && allowedActions.canUpdate}
86
- >
87
- {formatMessage({
88
- id: getTrad('pages.SettingsPage.Button.save'),
89
- defaultMessage: 'Save',
90
- })}
91
- </Button>
92
- }
93
- />
94
- <ContentLayout>
95
- <Box
96
- background="neutral0"
97
- hasRadius
98
- shadow="filterShadow"
99
- paddingTop={6}
100
- paddingBottom={6}
101
- paddingLeft={7}
102
- paddingRight={7}
103
- >
104
- <Flex direction="column" alignItems="stretch" gap={4}>
105
- <Typography variant="delta" as="h2">
106
- {formatMessage({
107
- id: 'global.settings',
108
- defaultMessage: 'Settings',
109
- })}
110
- </Typography>
111
- <Grid gap={4}>
112
- <GridItem col={6} s={12}>
113
- <ToggleInput
114
- name="restrictedAccess"
115
- label={formatMessage({
116
- id: getTrad('pages.SettingsPage.toggle.label'),
117
- defaultMessage: 'Restricted Access',
118
- })}
119
- hint={formatMessage({
120
- id: getTrad('pages.SettingsPage.toggle.hint'),
121
- defaultMessage: 'Make the documentation endpoint private',
122
- })}
123
- checked={values.restrictedAccess}
124
- onChange={() => {
125
- if (values.restrictedAccess === true) {
126
- setFieldValue('password', '', false);
127
- setFieldTouched('password', false, false);
128
- }
129
-
130
- setFieldValue('restrictedAccess', !values.restrictedAccess, false);
131
- }}
132
- onLabel="On"
133
- offLabel="Off"
134
- />
135
- </GridItem>
136
- {values.restrictedAccess && (
137
- <GridItem col={6} s={12}>
138
- <TextInput
139
- label={formatMessage({
140
- id: 'global.password',
141
- defaultMessage: 'Password',
142
- })}
143
- name="password"
144
- placeholder="**********"
145
- type={passwordShown ? 'text' : 'password'}
146
- value={values.password}
147
- onChange={handleChange}
148
- error={
149
- errors.password
150
- ? formatMessage({
151
- id: errors.password,
152
- defaultMessage: 'Invalid value',
153
- })
154
- : null
155
- }
156
- endAction={
157
- <FieldActionWrapper
158
- onClick={(e) => {
159
- e.stopPropagation();
160
- setPasswordShown((prev) => !prev);
161
- }}
162
- label={formatMessage(
163
- passwordShown
164
- ? {
165
- id: 'Auth.form.password.show-password',
166
- defaultMessage: 'Show password',
167
- }
168
- : {
169
- id: 'Auth.form.password.hide-password',
170
- defaultMessage: 'Hide password',
171
- }
172
- )}
173
- >
174
- {passwordShown ? <Show /> : <Hide />}
175
- </FieldActionWrapper>
176
- }
177
- />
178
- </GridItem>
179
- )}
180
- </Grid>
181
- </Flex>
182
- </Box>
183
- </ContentLayout>
184
- </Form>
185
- );
186
- }}
187
- </Formik>
188
- </Page.Main>
189
- );
190
- };
191
-
192
- const FieldActionWrapper = styled(FieldAction)`
193
- svg {
194
- height: 1rem;
195
- width: 1rem;
196
- path {
197
- fill: ${({ theme }) => theme.colors.neutral600};
198
- }
199
- }
200
- `;
201
-
202
- export default SettingsPage;
@@ -1,72 +0,0 @@
1
- import React from 'react';
2
-
3
- import { fireEvent, render, waitFor } from '@strapi/strapi/admin/test';
4
- import { rest } from 'msw';
5
-
6
- import { server } from '../../../../../tests/server';
7
- import SettingsPage from '../index';
8
-
9
- describe('SettingsPage', () => {
10
- it('renders the setting page correctly', async () => {
11
- const { getByRole, queryByText, getByText } = render(<SettingsPage />);
12
-
13
- await waitFor(() => expect(queryByText('Loading content.')).not.toBeInTheDocument());
14
-
15
- expect(getByRole('heading', { name: 'Documentation' })).toBeInTheDocument();
16
- expect(getByText('Configure the documentation plugin')).toBeInTheDocument();
17
- expect(getByRole('heading', { name: 'Settings' })).toBeInTheDocument();
18
-
19
- expect(getByRole('button', { name: 'Save' })).toBeInTheDocument();
20
- expect(getByRole('button', { name: 'Save' })).toHaveAttribute('aria-disabled', 'true');
21
-
22
- expect(getByRole('checkbox', { name: 'Restricted Access' })).toBeInTheDocument();
23
- });
24
-
25
- it('should automatically render the password field if the server restricted access property is true', async () => {
26
- server.use(
27
- rest.get('*/getInfos', (req, res, ctx) => {
28
- return res(
29
- ctx.json({
30
- documentationAccess: { restrictedAccess: true },
31
- })
32
- );
33
- })
34
- );
35
-
36
- const { getByLabelText, queryByText } = render(<SettingsPage />);
37
-
38
- await waitFor(() => expect(queryByText('Loading content.')).not.toBeInTheDocument());
39
-
40
- expect(getByLabelText('Password')).toBeInTheDocument();
41
-
42
- server.restoreHandlers();
43
- });
44
-
45
- it('should render the password field when the Restricted Access checkbox is checked', async () => {
46
- const { getByRole, getByLabelText, queryByText } = render(<SettingsPage />);
47
-
48
- await waitFor(() => expect(queryByText('Loading content.')).not.toBeInTheDocument());
49
-
50
- fireEvent.click(getByRole('checkbox', { name: 'Restricted Access' }));
51
-
52
- expect(getByRole('button', { name: 'Save' })).toHaveAttribute('aria-disabled', 'false');
53
-
54
- expect(getByLabelText('Password')).toBeInTheDocument();
55
- });
56
-
57
- it('should allow me to type a password and save that settings change successfully', async () => {
58
- const { getByRole, getByLabelText, queryByText, user, getByText } = render(<SettingsPage />);
59
-
60
- await waitFor(() => expect(queryByText('Loading content.')).not.toBeInTheDocument());
61
-
62
- fireEvent.click(getByRole('checkbox', { name: 'Restricted Access' }));
63
-
64
- expect(getByRole('button', { name: 'Save' })).toHaveAttribute('aria-disabled', 'false');
65
-
66
- await user.type(getByLabelText('Password'), 'password');
67
-
68
- fireEvent.click(getByRole('button', { name: 'Save' }));
69
-
70
- await waitFor(() => expect(getByText('Successfully updated settings')).toBeInTheDocument());
71
- });
72
- });
@@ -1,5 +0,0 @@
1
- import pluginPkg from '../../package.json';
2
-
3
- const pluginId = pluginPkg.name.replace(/^@strapi\/plugin-/i, '');
4
-
5
- export default pluginId;
@@ -1,20 +0,0 @@
1
- {
2
- "components.Row.open": "Open",
3
- "components.Row.regenerate": "Regenerate",
4
- "containers.HomePage.Block.title": "Versions",
5
- "containers.HomePage.Button.update": "Update",
6
- "containers.HomePage.PluginHeader.title": "Documentation — Settings",
7
- "containers.HomePage.PopUpWarning.confirm": "I understand",
8
- "containers.HomePage.PopUpWarning.message": "Are you sure you want to delete this version?",
9
- "containers.HomePage.form.password": "Password",
10
- "containers.HomePage.form.password.inputDescription": "Set the password to access the documentation",
11
- "containers.HomePage.form.restrictedAccess": "Restricted access",
12
- "containers.HomePage.form.restrictedAccess.inputDescription": "Make the documentation endpoint private. By default, the access is public",
13
- "containers.HomePage.form.showGeneratedFiles": "Show generated files",
14
- "containers.HomePage.form.showGeneratedFiles.inputDescription": "Useful when you want to override the generated documentation. \nThe plugin will generate files split by model and plugin. \nBy enabling this option it will be easier to customize your documentation",
15
- "error.deleteDoc.versionMissing": "The version you are trying to delete does not exist.",
16
- "error.noVersion": "A version is required",
17
- "error.regenerateDoc": "An error occurred while regenerating the doc",
18
- "error.regenerateDoc.versionMissing": "The version you are trying to generate doesn't exist",
19
- "notification.update.success": "Settings updated successfully"
20
- }