@strapi/plugin-documentation 4.0.0-next.7 → 4.0.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 (72) hide show
  1. package/admin/src/components/FieldActionWrapper/index.js +14 -0
  2. package/admin/src/components/PluginIcon/index.js +12 -0
  3. package/admin/src/index.js +27 -12
  4. package/admin/src/pages/PluginPage/index.js +199 -0
  5. package/admin/src/pages/PluginPage/tests/index.test.js +873 -0
  6. package/admin/src/pages/PluginPage/tests/server.js +23 -0
  7. package/admin/src/pages/SettingsPage/index.js +181 -0
  8. package/admin/src/pages/SettingsPage/tests/index.test.js +612 -0
  9. package/admin/src/pages/SettingsPage/tests/server.js +18 -0
  10. package/admin/src/pages/{HomePage/utils → utils}/api.js +5 -4
  11. package/admin/src/pages/{HomePage/utils → utils}/schema.js +0 -0
  12. package/admin/src/pages/utils/useReactQuery.js +46 -0
  13. package/admin/src/translations/ar.json +0 -3
  14. package/admin/src/translations/cs.json +0 -3
  15. package/admin/src/translations/de.json +0 -3
  16. package/admin/src/translations/en.json +14 -3
  17. package/admin/src/translations/es.json +0 -3
  18. package/admin/src/translations/fr.json +0 -3
  19. package/admin/src/translations/id.json +0 -3
  20. package/admin/src/translations/it.json +0 -3
  21. package/admin/src/translations/ko.json +41 -22
  22. package/admin/src/translations/ms.json +0 -3
  23. package/admin/src/translations/nl.json +0 -3
  24. package/admin/src/translations/pl.json +0 -3
  25. package/admin/src/translations/pt-BR.json +0 -3
  26. package/admin/src/translations/pt.json +0 -3
  27. package/admin/src/translations/ru.json +0 -3
  28. package/admin/src/translations/sk.json +0 -3
  29. package/admin/src/translations/th.json +0 -3
  30. package/admin/src/translations/tr.json +0 -3
  31. package/admin/src/translations/uk.json +0 -3
  32. package/admin/src/translations/vi.json +0 -3
  33. package/admin/src/translations/zh-Hans.json +3 -6
  34. package/admin/src/translations/zh.json +0 -3
  35. package/package.json +32 -47
  36. package/server/bootstrap.js +19 -105
  37. package/server/config/default-config.js +12 -15
  38. package/server/config/index.js +10 -2
  39. package/server/controllers/documentation.js +61 -127
  40. package/server/index.js +17 -0
  41. package/server/middlewares/documentation.js +18 -41
  42. package/server/{policies/index-policy.js → middlewares/restrict-access.js} +5 -16
  43. package/{public → server/public}/index.html +0 -0
  44. package/{public → server/public}/login.html +0 -0
  45. package/server/register.js +11 -0
  46. package/server/routes/index.js +81 -3
  47. package/server/services/documentation.js +125 -1835
  48. package/server/utils/builders/build-api-endpoint-path.js +174 -0
  49. package/server/utils/builders/build-api-requests.js +41 -0
  50. package/server/utils/builders/build-api-responses.js +108 -0
  51. package/server/utils/builders/index.js +11 -0
  52. package/server/utils/clean-schema-attributes.js +205 -0
  53. package/server/utils/error-response.js +22 -0
  54. package/server/utils/get-schema-data.js +32 -0
  55. package/server/utils/query-params.js +84 -0
  56. package/strapi-admin.js +3 -0
  57. package/strapi-server.js +1 -19
  58. package/admin/src/assets/images/logo.svg +0 -1
  59. package/admin/src/components/Block/components.js +0 -26
  60. package/admin/src/components/Block/index.js +0 -39
  61. package/admin/src/components/Copy/index.js +0 -36
  62. package/admin/src/components/Header/index.js +0 -72
  63. package/admin/src/components/Row/ButtonContainer.js +0 -67
  64. package/admin/src/components/Row/components.js +0 -83
  65. package/admin/src/components/Row/index.js +0 -51
  66. package/admin/src/pages/App/index.js +0 -21
  67. package/admin/src/pages/HomePage/components.js +0 -59
  68. package/admin/src/pages/HomePage/index.js +0 -168
  69. package/admin/src/pages/HomePage/useHomePage.js +0 -56
  70. package/server/policies/index.js +0 -7
  71. package/server/routes/routes.json +0 -74
  72. package/server/services/utils/forms.json +0 -29
@@ -0,0 +1,14 @@
1
+ import styled from 'styled-components';
2
+ import { FieldAction } from '@strapi/design-system/Field';
3
+
4
+ const FieldActionWrapper = styled(FieldAction)`
5
+ svg {
6
+ height: 1rem;
7
+ width: 1rem;
8
+ path {
9
+ fill: ${({ theme }) => theme.colors.neutral600};
10
+ }
11
+ }
12
+ `;
13
+
14
+ export default FieldActionWrapper;
@@ -0,0 +1,12 @@
1
+ /**
2
+ *
3
+ * PluginIcon
4
+ *
5
+ */
6
+
7
+ import React from 'react';
8
+ import Information from '@strapi/icons/Information';
9
+
10
+ const PluginIcon = () => <Information />;
11
+
12
+ export default PluginIcon;
@@ -6,39 +6,54 @@
6
6
  // IF THE DOC IS NOT UPDATED THE PULL REQUEST WILL NOT BE MERGED
7
7
  import { prefixPluginTranslations } from '@strapi/helper-plugin';
8
8
  import pluginPkg from '../../package.json';
9
+ import PluginIcon from './components/PluginIcon';
9
10
  import pluginPermissions from './permissions';
10
11
  import pluginId from './pluginId';
11
- import pluginLogo from './assets/images/logo.svg';
12
- import App from './pages/App';
13
12
 
14
- const pluginDescription = pluginPkg.strapi.description || pluginPkg.description;
15
- const icon = pluginPkg.strapi.icon;
16
13
  const name = pluginPkg.strapi.name;
17
14
 
18
15
  export default {
19
16
  register(app) {
20
17
  app.addMenuLink({
21
18
  to: `/plugins/${pluginId}`,
22
- icon,
19
+ icon: PluginIcon,
23
20
  intlLabel: {
24
21
  id: `${pluginId}.plugin.name`,
25
22
  defaultMessage: 'Documentation',
26
23
  },
27
24
  permissions: pluginPermissions.main,
28
- Component: App,
25
+ Component: async () => {
26
+ const component = await import(
27
+ /* webpackChunkName: "documentation-page" */ './pages/PluginPage'
28
+ );
29
+
30
+ return component;
31
+ },
29
32
  });
30
33
 
31
34
  app.registerPlugin({
32
- description: pluginDescription,
33
- icon,
34
35
  id: pluginId,
35
- isReady: true,
36
- isRequired: pluginPkg.strapi.required || false,
37
36
  name,
38
- pluginLogo,
39
37
  });
40
38
  },
41
- bootstrap() {},
39
+ bootstrap(app) {
40
+ app.addSettingsLink('global', {
41
+ intlLabel: {
42
+ id: `${pluginId}.plugin.name`,
43
+ defaultMessage: 'Documentation',
44
+ },
45
+ id: 'documentation',
46
+ to: `/settings/${pluginId}`,
47
+ Component: async () => {
48
+ const component = await import(
49
+ /* webpackChunkName: "documentation-settings" */ './pages/SettingsPage'
50
+ );
51
+
52
+ return component;
53
+ },
54
+ permissions: pluginPermissions.main,
55
+ });
56
+ },
42
57
  async registerTrads({ locales }) {
43
58
  const importedTrads = await Promise.all(
44
59
  locales.map(locale => {
@@ -0,0 +1,199 @@
1
+ /**
2
+ *
3
+ * This component is the skeleton around the actual pages, and should only
4
+ * contain code that should be seen on all pages. (e.g. navigation bar)
5
+ *
6
+ */
7
+
8
+ import React, { useState } from 'react';
9
+ import { useIntl } from 'react-intl';
10
+ import {
11
+ CheckPermissions,
12
+ ConfirmDialog,
13
+ LoadingIndicatorPage,
14
+ stopPropagation,
15
+ EmptyStateLayout,
16
+ useFocusWhenNavigate,
17
+ } from '@strapi/helper-plugin';
18
+ import { Helmet } from 'react-helmet';
19
+ import { Button } from '@strapi/design-system/Button';
20
+ import { Layout, HeaderLayout, ContentLayout } from '@strapi/design-system/Layout';
21
+ import { Main } from '@strapi/design-system/Main';
22
+ import { IconButton } from '@strapi/design-system/IconButton';
23
+ import { Typography } from '@strapi/design-system/Typography';
24
+ import { Flex } from '@strapi/design-system/Flex';
25
+ import { Table, Tr, Thead, Th, Tbody, Td } from '@strapi/design-system/Table';
26
+
27
+ import Trash from '@strapi/icons/Trash';
28
+ import Show from '@strapi/icons/Eye';
29
+ import Reload from '@strapi/icons/Refresh';
30
+
31
+ import permissions from '../../permissions';
32
+ import { getTrad } from '../../utils';
33
+ import openWithNewTab from '../../utils/openWithNewTab';
34
+ import useReactQuery from '../utils/useReactQuery';
35
+
36
+ const PluginPage = () => {
37
+ useFocusWhenNavigate();
38
+ const { formatMessage } = useIntl();
39
+ const { data, isLoading, deleteMutation, regenerateDocMutation } = useReactQuery();
40
+ const [showConfirmDelete, setShowConfirmDelete] = useState(false);
41
+ const [isConfirmButtonLoading, setIsConfirmButtonLoading] = useState(false);
42
+ const [versionToDelete, setVersionToDelete] = useState();
43
+
44
+ const colCount = 4;
45
+ const rowCount = (data?.docVersions?.length || 0) + 1;
46
+
47
+ const openDocVersion = () => {
48
+ const slash = data?.prefix.startsWith('/') ? '' : '/';
49
+ openWithNewTab(`${slash}${data?.prefix}/v${data?.currentVersion}`);
50
+ };
51
+
52
+ const handleRegenerateDoc = version => {
53
+ regenerateDocMutation.mutate({ version, prefix: data?.prefix });
54
+ };
55
+
56
+ const handleShowConfirmDelete = () => {
57
+ setShowConfirmDelete(!showConfirmDelete);
58
+ };
59
+
60
+ const handleConfirmDelete = async () => {
61
+ setIsConfirmButtonLoading(true);
62
+ await deleteMutation.mutateAsync({ prefix: data?.prefix, version: versionToDelete });
63
+ setShowConfirmDelete(!showConfirmDelete);
64
+ setIsConfirmButtonLoading(false);
65
+ };
66
+
67
+ const handleClickDelete = version => {
68
+ setVersionToDelete(version);
69
+ setShowConfirmDelete(!showConfirmDelete);
70
+ };
71
+
72
+ const title = formatMessage({
73
+ id: getTrad('plugin.name'),
74
+ defaultMessage: 'Documentation',
75
+ });
76
+
77
+ return (
78
+ <Layout>
79
+ <Helmet title={title} />
80
+ <Main aria-busy={isLoading}>
81
+ <HeaderLayout
82
+ title={title}
83
+ subtitle={formatMessage({
84
+ id: getTrad('pages.PluginPage.header.description'),
85
+ defaultMessage: 'Configure the documentation plugin',
86
+ })}
87
+ primaryAction={
88
+ // eslint-disable-next-line
89
+ <CheckPermissions permissions={permissions.open}>
90
+ <Button onClick={openDocVersion} startIcon={<Show />}>
91
+ {formatMessage({
92
+ id: getTrad('pages.PluginPage.Button.open'),
93
+ defaultMessage: 'Open Documentation',
94
+ })}
95
+ </Button>
96
+ </CheckPermissions>
97
+ }
98
+ />
99
+ <ContentLayout>
100
+ {isLoading && <LoadingIndicatorPage>Plugin is loading</LoadingIndicatorPage>}
101
+ {data?.docVersions.length ? (
102
+ <Table colCount={colCount} rowCount={rowCount}>
103
+ <Thead>
104
+ <Tr>
105
+ <Th>
106
+ <Typography variant="sigma" textColor="neutral600">
107
+ {formatMessage({
108
+ id: getTrad('pages.PluginPage.table.version'),
109
+ defaultMessage: 'Version',
110
+ })}
111
+ </Typography>
112
+ </Th>
113
+ <Th>
114
+ <Typography variant="sigma" textColor="neutral600">
115
+ {formatMessage({
116
+ id: getTrad('pages.PluginPage.table.generated'),
117
+ defaultMessage: 'Last Generated',
118
+ })}
119
+ </Typography>
120
+ </Th>
121
+ </Tr>
122
+ </Thead>
123
+ <Tbody>
124
+ {data.docVersions
125
+ .sort((a, b) => (a.generatedDate < b.generatedDate ? 1 : -1))
126
+ .map(doc => (
127
+ <Tr key={doc.version}>
128
+ <Td width="50%">
129
+ <Typography>{doc.version}</Typography>
130
+ </Td>
131
+ <Td width="50%">
132
+ <Typography>{doc.generatedDate}</Typography>
133
+ </Td>
134
+ <Td>
135
+ <Flex justifyContent="end" {...stopPropagation}>
136
+ <IconButton
137
+ onClick={openDocVersion}
138
+ noBorder
139
+ icon={<Show />}
140
+ label={formatMessage(
141
+ {
142
+ id: getTrad('pages.PluginPage.table.icon.show'),
143
+ defaultMessage: 'Open {target}',
144
+ },
145
+ { target: `${doc.version}` }
146
+ )}
147
+ />
148
+ <CheckPermissions permissions={permissions.regenerate}>
149
+ <IconButton
150
+ onClick={() => handleRegenerateDoc(doc.version)}
151
+ noBorder
152
+ icon={<Reload />}
153
+ label={formatMessage(
154
+ {
155
+ id: getTrad('pages.PluginPage.table.icon.regenerate'),
156
+ defaultMessage: 'Regenerate {target}',
157
+ },
158
+ { target: `${doc.version}` }
159
+ )}
160
+ />
161
+ </CheckPermissions>
162
+ <CheckPermissions permissions={permissions.update}>
163
+ {doc.version !== data.currentVersion && (
164
+ <IconButton
165
+ onClick={() => handleClickDelete(doc.version)}
166
+ noBorder
167
+ icon={<Trash />}
168
+ label={formatMessage(
169
+ {
170
+ id: getTrad('pages.PluginPage.table.icon.delete'),
171
+ defaultMessage: 'Delete {target}',
172
+ },
173
+ { target: `${doc.version}` }
174
+ )}
175
+ />
176
+ )}
177
+ </CheckPermissions>
178
+ </Flex>
179
+ </Td>
180
+ </Tr>
181
+ ))}
182
+ </Tbody>
183
+ </Table>
184
+ ) : (
185
+ <EmptyStateLayout />
186
+ )}
187
+ </ContentLayout>
188
+ <ConfirmDialog
189
+ isConfirmButtonLoading={isConfirmButtonLoading}
190
+ onConfirm={handleConfirmDelete}
191
+ onToggleDialog={handleShowConfirmDelete}
192
+ isOpen={showConfirmDelete}
193
+ />
194
+ </Main>
195
+ </Layout>
196
+ );
197
+ };
198
+
199
+ export default PluginPage;