@akemona-org/strapi-plugin-documentation 3.7.0
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.
- package/LICENSE +22 -0
- package/README.md +170 -0
- package/admin/src/assets/images/logo.svg +1 -0
- package/admin/src/components/Block/components.js +26 -0
- package/admin/src/components/Block/index.js +39 -0
- package/admin/src/components/Row/ButtonContainer.js +53 -0
- package/admin/src/components/Row/components.js +83 -0
- package/admin/src/components/Row/index.js +57 -0
- package/admin/src/containers/App/index.js +30 -0
- package/admin/src/containers/HomePage/actions.js +72 -0
- package/admin/src/containers/HomePage/components.js +59 -0
- package/admin/src/containers/HomePage/constants.js +14 -0
- package/admin/src/containers/HomePage/index.js +283 -0
- package/admin/src/containers/HomePage/reducer.js +49 -0
- package/admin/src/containers/HomePage/saga.js +126 -0
- package/admin/src/containers/HomePage/selectors.js +34 -0
- package/admin/src/containers/Initializer/index.js +28 -0
- package/admin/src/containers/Initializer/tests/index.test.js +21 -0
- package/admin/src/index.js +57 -0
- package/admin/src/lifecycles.js +13 -0
- package/admin/src/permissions.js +19 -0
- package/admin/src/pluginId.js +5 -0
- package/admin/src/reducers.js +8 -0
- package/admin/src/translations/ar.json +23 -0
- package/admin/src/translations/cs.json +24 -0
- package/admin/src/translations/de.json +30 -0
- package/admin/src/translations/en.json +31 -0
- package/admin/src/translations/es.json +27 -0
- package/admin/src/translations/fr.json +29 -0
- package/admin/src/translations/id.json +28 -0
- package/admin/src/translations/index.js +49 -0
- package/admin/src/translations/it.json +29 -0
- package/admin/src/translations/ko.json +24 -0
- package/admin/src/translations/ms.json +26 -0
- package/admin/src/translations/nl.json +24 -0
- package/admin/src/translations/pl.json +27 -0
- package/admin/src/translations/pt-BR.json +24 -0
- package/admin/src/translations/pt.json +24 -0
- package/admin/src/translations/ru.json +31 -0
- package/admin/src/translations/sk.json +27 -0
- package/admin/src/translations/th.json +27 -0
- package/admin/src/translations/tr.json +23 -0
- package/admin/src/translations/uk.json +26 -0
- package/admin/src/translations/vi.json +27 -0
- package/admin/src/translations/zh-Hans.json +31 -0
- package/admin/src/translations/zh.json +27 -0
- package/admin/src/utils/getTrad.js +5 -0
- package/admin/src/utils/openWithNewTab.js +20 -0
- package/config/functions/bootstrap.js +138 -0
- package/config/policies/index.js +35 -0
- package/config/routes.json +74 -0
- package/config/settings.json +46 -0
- package/controllers/Documentation.js +303 -0
- package/middlewares/documentation/defaults.json +5 -0
- package/middlewares/documentation/index.js +59 -0
- package/package.json +89 -0
- package/public/index.html +57 -0
- package/public/login.html +135 -0
- package/services/Documentation.js +1861 -0
- package/services/Token.js +31 -0
- package/services/utils/components.json +25 -0
- package/services/utils/forms.json +29 -0
- package/services/utils/parametersOptions.json +134 -0
- package/services/utils/unknownComponent.json +11 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2015-present Strapi Solutions SAS
|
|
2
|
+
|
|
3
|
+
Portions of the Strapi software are licensed as follows:
|
|
4
|
+
|
|
5
|
+
* All software that resides under an "ee/" directory (the “EE Software”), if that directory exists, is licensed under the license defined in "ee/LICENSE".
|
|
6
|
+
|
|
7
|
+
* All software outside of the above-mentioned directories or restrictions above is available under the "MIT Expat" license as set forth below.
|
|
8
|
+
|
|
9
|
+
MIT Expat License
|
|
10
|
+
|
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
in the Software without restriction, including without limitation the rights
|
|
14
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# Plugin documentation
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Deprecation Warning :warning:
|
|
6
|
+
|
|
7
|
+
Hello! We have some news to share,
|
|
8
|
+
|
|
9
|
+
We’ve decided it’ll soon be time to end the support for `strapi-plugin-documentation`.
|
|
10
|
+
|
|
11
|
+
After years of iterations, Strapi is going to V4 and we won’t maintain V3 packages when it’ll reach its end-of-support milestone (~end of Q3 2022).
|
|
12
|
+
|
|
13
|
+
If you’ve been using `strapi-plugin-documentation` and have migrated to V4 (or if you want to), you can find the equivalent and updated version of this package at this [URL](https://github.com/strapi/strapi/tree/master/packages/plugins/documentation) and with the following name on NPM: `@strapi/plugin-documentation`.
|
|
14
|
+
|
|
15
|
+
If you’ve contributed to the development of this package, thank you again for that! We hope to see you on the V4 soon.
|
|
16
|
+
|
|
17
|
+
The Akemona team
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
This plugin automates your API documentation creation. It basically generates a swagger file. It follows the [Open API specification version 3.0.1](https://swagger.io/specification/).
|
|
22
|
+
The documentation plugin is not release on npm yet, Here's how to install it.
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
- Config
|
|
27
|
+
- Creating a new documentation version
|
|
28
|
+
- Generated files
|
|
29
|
+
- full_documentation.json structure
|
|
30
|
+
- Overriding the suggested documentation
|
|
31
|
+
- FAQ
|
|
32
|
+
- How does it generate the others plugins documentation ?
|
|
33
|
+
- I have created a route into a common API (like product) that query another model. How to automate this?
|
|
34
|
+
- TODO
|
|
35
|
+
|
|
36
|
+
### Config
|
|
37
|
+
|
|
38
|
+
The plugin comes with a `settings.json` file located in `./my-project/plugins/documentation/config` folder where you can specify all your environment variables, licenses, external documentation and so one...
|
|
39
|
+
You can add all the entries listed in the [specification](https://swagger.io/specification/).
|
|
40
|
+
|
|
41
|
+
_NOTE_ if you need to add a custom key you can do it by prefixing your key by `x-{something}`
|
|
42
|
+
|
|
43
|
+
### Creating a new documentation version
|
|
44
|
+
|
|
45
|
+
In order to create a new version you need to change the `info.version` key in the `settings.json` file.
|
|
46
|
+
|
|
47
|
+
This will automatically create a new version.
|
|
48
|
+
|
|
49
|
+
### Generated files
|
|
50
|
+
|
|
51
|
+
When you start your server with this plugin installed it will automatically create the following files in your APIs (we will see how it works for the plugins).
|
|
52
|
+
|
|
53
|
+
- api
|
|
54
|
+
- my-api
|
|
55
|
+
- documentation
|
|
56
|
+
- documentationVersion // 1.0.0
|
|
57
|
+
- my-api.json // File containing all the identified path
|
|
58
|
+
- unclassified.json // File containing the manually added paths
|
|
59
|
+
- overrides // Folder to override the generated documentation
|
|
60
|
+
- plugins
|
|
61
|
+
- ...
|
|
62
|
+
- documentation
|
|
63
|
+
- documentation
|
|
64
|
+
- 1.0.0
|
|
65
|
+
- full_documentation.json
|
|
66
|
+
|
|
67
|
+
#### full_documentation.json
|
|
68
|
+
|
|
69
|
+
The combined documentation is merged into the `full_documentation.json` file and it's located in `./plugins/documentation/{version}/full_documentation.json`
|
|
70
|
+
|
|
71
|
+
It has the following structure
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
{
|
|
75
|
+
"openapi": "3.0.0" // do not change this version
|
|
76
|
+
"info": {
|
|
77
|
+
"version": "1.0.0" // change this line to create a new version
|
|
78
|
+
...
|
|
79
|
+
}
|
|
80
|
+
"x-strapi-config": {
|
|
81
|
+
"path": "/documentation", // Change this line to change to url of the doc
|
|
82
|
+
"showGeneratedFiles": true // Do not change this line at the moment...
|
|
83
|
+
},
|
|
84
|
+
"servers" {} // Your servers config (it will be automated),
|
|
85
|
+
"externalDocs": {},
|
|
86
|
+
"paths": {} // All your Api routes,
|
|
87
|
+
"tags": [] // Group of route
|
|
88
|
+
"components": {} // Default generated components and custom ones
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Overriding the suggested documentation
|
|
93
|
+
|
|
94
|
+
Currently the plugin writes a json file for each API.
|
|
95
|
+
|
|
96
|
+
In order to customize the responses or to add information to a path you need to create a file in the associated `overrides/<file-name>.json` (the name of the file matters so make sure they are similar). Then you just need to identify the path you want to modify.
|
|
97
|
+
You can modify the default generated tags by adding a new one at the end of the file. Same for the components.
|
|
98
|
+
|
|
99
|
+
**_NOTE 1_**
|
|
100
|
+
|
|
101
|
+
Overriding the `full_documentation.json` is a bad idea since it will be regenerated each time you change a model.
|
|
102
|
+
|
|
103
|
+
**_NOTE 2_**
|
|
104
|
+
|
|
105
|
+
You can easily modify the description, summary, parameters of a path however, for a response like the `200` you will need to write the full object. Take a look at the `./plugins/users-permissions/documentation/overrides/1.0.0/users-permissions-User.json` for a complete example.
|
|
106
|
+
|
|
107
|
+
### FAQ
|
|
108
|
+
|
|
109
|
+
#### How does it generate the others plugins documentation ?
|
|
110
|
+
|
|
111
|
+
In other to reference a plugin's route into the documentation you need to add a `description` key in the `config` object.
|
|
112
|
+
|
|
113
|
+
For example this is the plugin email routes.json file
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
{
|
|
117
|
+
"routes": [
|
|
118
|
+
{
|
|
119
|
+
"method": "POST",
|
|
120
|
+
"path": "/",
|
|
121
|
+
"handler": "Email.send",
|
|
122
|
+
"config": {
|
|
123
|
+
"policies": [],
|
|
124
|
+
"description": "Send an email",
|
|
125
|
+
"tag": {
|
|
126
|
+
"plugin": "email",
|
|
127
|
+
"name": "Email"
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"method": "GET",
|
|
133
|
+
"path": "/environments",
|
|
134
|
+
"handler": "Email.getEnvironments",
|
|
135
|
+
"config": {
|
|
136
|
+
"policies": []
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"method": "GET",
|
|
141
|
+
"path": "/settings/:environment",
|
|
142
|
+
"handler": "Email.getSettings",
|
|
143
|
+
"config": {
|
|
144
|
+
"policies": []
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"method": "PUT",
|
|
149
|
+
"path": "/settings/:environment",
|
|
150
|
+
"handler": "Email.updateSettings",
|
|
151
|
+
"config": {
|
|
152
|
+
"policies": []
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
]
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
In this file we have only one route that we want to reference in our documentation (`/`). Usually, the tag object is used for the SWAGGER UI, it will group this route under the `Email - Email` dropdown in the documentation. Furthermore, the algorithm will try to find the model to generate the best response possible. If the model is unknown it generates a response like the following `{ foo: "string" }` that you can easily override later.
|
|
160
|
+
|
|
161
|
+
There's another property to guide the algorithm to create the best response possible, the `actionType` key.
|
|
162
|
+
When we can't know by the controller name the type of the returned response (like `find` and `findOne`) you can specify it with this key. There's an example in `./plugins/users-permissions/config/routes.json`.
|
|
163
|
+
|
|
164
|
+
#### I have created a route in a common API (like product) that query another model. How to automate this ?
|
|
165
|
+
|
|
166
|
+
You can use the `tag` key in your route. If you provide a `tag` which is a string like `"tag": "Product"` the algorithm will know that the end-point retrieves data from the **`Product`** table. Creating a tag object `{ "tag": { "name": "User", "plugin": "User-Permissions } }` will result in generating a response with the **`User`** model from the plugin users-permissions.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
Each entry of the object is easily customisable take look at the users-permissions ones they are a good example on how to do it.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg width="24" height="22" xmlns="http://www.w3.org/2000/svg"><text transform="translate(-23 -7)" fill="#4B515A" fill-rule="evenodd" font-family="AppleColorEmoji, Apple Color Emoji" font-size="24"><tspan x="23" y="28">🗂</tspan></text></svg>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
|
|
3
|
+
const Wrapper = styled.div`
|
|
4
|
+
margin-bottom: 28px;
|
|
5
|
+
background: #ffffff;
|
|
6
|
+
padding: 22px 28px 18px;
|
|
7
|
+
border-radius: 2px;
|
|
8
|
+
box-shadow: 0 2px 4px #e3e9f3;
|
|
9
|
+
-webkit-font-smoothing: antialiased;
|
|
10
|
+
`;
|
|
11
|
+
|
|
12
|
+
const Title = styled.div`
|
|
13
|
+
padding-top: 0px;
|
|
14
|
+
line-height: 18px;
|
|
15
|
+
> span {
|
|
16
|
+
font-weight: 600;
|
|
17
|
+
color: #333740;
|
|
18
|
+
font-size: 18px;
|
|
19
|
+
}
|
|
20
|
+
> p {
|
|
21
|
+
color: #787e8f;
|
|
22
|
+
font-size: 13px;
|
|
23
|
+
}
|
|
24
|
+
`;
|
|
25
|
+
|
|
26
|
+
export { Wrapper, Title };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Block
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import PropTypes from 'prop-types';
|
|
8
|
+
import { FormattedMessage } from 'react-intl';
|
|
9
|
+
import { Wrapper, Title } from './components';
|
|
10
|
+
|
|
11
|
+
const renderMsg = msg => <p>{msg}</p>;
|
|
12
|
+
|
|
13
|
+
const Block = ({ children, description, style, title }) => (
|
|
14
|
+
<div className="col-md-12">
|
|
15
|
+
<Wrapper style={style}>
|
|
16
|
+
<Title>
|
|
17
|
+
<FormattedMessage id={title} />
|
|
18
|
+
<FormattedMessage id={description}>{renderMsg}</FormattedMessage>
|
|
19
|
+
</Title>
|
|
20
|
+
{children}
|
|
21
|
+
</Wrapper>
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
Block.defaultProps = {
|
|
26
|
+
children: null,
|
|
27
|
+
description: 'app.utils.defaultMessage',
|
|
28
|
+
style: {},
|
|
29
|
+
title: 'app.utils.defaultMessage',
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
Block.propTypes = {
|
|
33
|
+
children: PropTypes.any,
|
|
34
|
+
description: PropTypes.string,
|
|
35
|
+
style: PropTypes.object,
|
|
36
|
+
title: PropTypes.string,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export default Block;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { FormattedMessage } from 'react-intl';
|
|
4
|
+
import { CheckPermissions } from 'strapi-helper-plugin';
|
|
5
|
+
import pluginPermissions from '../../permissions';
|
|
6
|
+
import openWithNewTab from '../../utils/openWithNewTab';
|
|
7
|
+
import { StyledButton } from './components';
|
|
8
|
+
|
|
9
|
+
const ButtonContainer = ({ currentDocVersion, isHeader, onClick, onClickDelete, version }) => {
|
|
10
|
+
if (isHeader) {
|
|
11
|
+
return <div />;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<div>
|
|
16
|
+
<StyledButton
|
|
17
|
+
type="openDocumentation"
|
|
18
|
+
onClick={() => openWithNewTab(`/documentation/v${version}`)}
|
|
19
|
+
>
|
|
20
|
+
<FormattedMessage id="documentation.components.Row.open" />
|
|
21
|
+
</StyledButton>
|
|
22
|
+
<CheckPermissions permissions={pluginPermissions.regenerate}>
|
|
23
|
+
<StyledButton type="generateDocumentation" onClick={() => onClick(version)}>
|
|
24
|
+
<FormattedMessage id="documentation.components.Row.regenerate" />
|
|
25
|
+
</StyledButton>
|
|
26
|
+
</CheckPermissions>
|
|
27
|
+
<CheckPermissions permissions={pluginPermissions.update}>
|
|
28
|
+
<StyledButton
|
|
29
|
+
type={version === currentDocVersion ? '' : 'trash'}
|
|
30
|
+
onClick={() => onClickDelete(version)}
|
|
31
|
+
/>
|
|
32
|
+
</CheckPermissions>
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
ButtonContainer.defaultProps = {
|
|
38
|
+
currentDocVersion: '1.0.0',
|
|
39
|
+
isHeader: false,
|
|
40
|
+
onClick: () => {},
|
|
41
|
+
onClickDelete: () => {},
|
|
42
|
+
version: '',
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
ButtonContainer.propTypes = {
|
|
46
|
+
currentDocVersion: PropTypes.string,
|
|
47
|
+
isHeader: PropTypes.bool,
|
|
48
|
+
onClick: PropTypes.func,
|
|
49
|
+
onClickDelete: PropTypes.func,
|
|
50
|
+
version: PropTypes.string,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default ButtonContainer;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import styled, { css } from 'styled-components';
|
|
2
|
+
import { Button } from 'strapi-helper-plugin';
|
|
3
|
+
|
|
4
|
+
const Wrapper = styled.div`
|
|
5
|
+
height: 54px;
|
|
6
|
+
display: flex;
|
|
7
|
+
line-height: 53px;
|
|
8
|
+
margin: 0 28px 0 36px;
|
|
9
|
+
justify-content: space-between;
|
|
10
|
+
border-bottom: 1px solid rgba(14, 22, 34, 0.04);
|
|
11
|
+
font-size: 13px;
|
|
12
|
+
color: #333740;
|
|
13
|
+
> div:first-child {
|
|
14
|
+
flex: 0 0 70px;
|
|
15
|
+
font-weight: 500;
|
|
16
|
+
}
|
|
17
|
+
> div:nth-child(2) {
|
|
18
|
+
flex: 0 0 160px;
|
|
19
|
+
text-align: left;
|
|
20
|
+
font-weight: 500 !important;
|
|
21
|
+
}
|
|
22
|
+
> div:last-child {
|
|
23
|
+
flex: 0 0 400px;
|
|
24
|
+
align-self: center;
|
|
25
|
+
text-align: right;
|
|
26
|
+
}
|
|
27
|
+
-webkit-font-smoothing: antialiased;
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
const StyledButton = styled(Button)`
|
|
31
|
+
height: 26px;
|
|
32
|
+
margin: 0;
|
|
33
|
+
padding: 0 15px;
|
|
34
|
+
line-height: initial;
|
|
35
|
+
font-size: 13px;
|
|
36
|
+
font-weight: 500;
|
|
37
|
+
${({ type }) => {
|
|
38
|
+
if (type === 'openDocumentation') {
|
|
39
|
+
return css`
|
|
40
|
+
margin-right: 10px;
|
|
41
|
+
border: 1px solid #dfe0e1;
|
|
42
|
+
&:before {
|
|
43
|
+
margin-right: 10px;
|
|
44
|
+
content: '\f08e';
|
|
45
|
+
font-family: 'FontAwesome';
|
|
46
|
+
font-size: 10px;
|
|
47
|
+
}
|
|
48
|
+
`;
|
|
49
|
+
}
|
|
50
|
+
if (type === 'generateDocumentation') {
|
|
51
|
+
return css`
|
|
52
|
+
background: #e6f0fb;
|
|
53
|
+
border: 1px solid #aed4fb;
|
|
54
|
+
color: #007eff;
|
|
55
|
+
&:before {
|
|
56
|
+
margin-right: 10px;
|
|
57
|
+
content: '\f021';
|
|
58
|
+
font-family: 'FontAwesome';
|
|
59
|
+
font-size: 10px;
|
|
60
|
+
}
|
|
61
|
+
`;
|
|
62
|
+
}
|
|
63
|
+
if (type === 'trash') {
|
|
64
|
+
return css`
|
|
65
|
+
margin-left: 25px;
|
|
66
|
+
font-weight: 400;
|
|
67
|
+
&:before {
|
|
68
|
+
margin-right: 10px;
|
|
69
|
+
content: '\f2ed';
|
|
70
|
+
font-family: 'FontAwesome';
|
|
71
|
+
font-size: 12 px;
|
|
72
|
+
}
|
|
73
|
+
`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return css`
|
|
77
|
+
margin-left: 45px;
|
|
78
|
+
font-weight: 400;
|
|
79
|
+
`;
|
|
80
|
+
}}
|
|
81
|
+
`;
|
|
82
|
+
|
|
83
|
+
export { Wrapper, StyledButton };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Row
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { FormattedMessage } from 'react-intl';
|
|
7
|
+
import PropTypes from 'prop-types';
|
|
8
|
+
import ButtonContainer from './ButtonContainer';
|
|
9
|
+
import { Wrapper } from './components';
|
|
10
|
+
|
|
11
|
+
function Row({
|
|
12
|
+
currentDocVersion,
|
|
13
|
+
data,
|
|
14
|
+
isHeader,
|
|
15
|
+
onClickDelete,
|
|
16
|
+
onUpdateDoc,
|
|
17
|
+
}) {
|
|
18
|
+
const { version, generatedDate } = data;
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Wrapper>
|
|
22
|
+
<div>{version}</div>
|
|
23
|
+
<div>
|
|
24
|
+
{isHeader ? (
|
|
25
|
+
<FormattedMessage id="documentation.components.Row.generatedDate" />
|
|
26
|
+
) : (
|
|
27
|
+
<span>{generatedDate}</span>
|
|
28
|
+
)}
|
|
29
|
+
</div>
|
|
30
|
+
<ButtonContainer
|
|
31
|
+
currentDocVersion={currentDocVersion}
|
|
32
|
+
isHeader={isHeader}
|
|
33
|
+
version={version}
|
|
34
|
+
onClickDelete={onClickDelete}
|
|
35
|
+
onClick={onUpdateDoc}
|
|
36
|
+
/>
|
|
37
|
+
</Wrapper>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
Row.defaultProps = {
|
|
42
|
+
currentDocVersion: '1.0.0',
|
|
43
|
+
data: {},
|
|
44
|
+
isHeader: false,
|
|
45
|
+
onClickDelete: () => {},
|
|
46
|
+
onUpdateDoc: () => {},
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
Row.propTypes = {
|
|
50
|
+
currentDocVersion: PropTypes.string,
|
|
51
|
+
data: PropTypes.object,
|
|
52
|
+
isHeader: PropTypes.bool,
|
|
53
|
+
onClickDelete: PropTypes.func,
|
|
54
|
+
onUpdateDoc: PropTypes.func,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export default Row;
|
|
@@ -0,0 +1,30 @@
|
|
|
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 from 'react';
|
|
9
|
+
import { Switch, Route } from 'react-router-dom';
|
|
10
|
+
import { NotFound, CheckPagePermissions } from 'strapi-helper-plugin';
|
|
11
|
+
// Utils
|
|
12
|
+
import pluginPermissions from '../../permissions';
|
|
13
|
+
import pluginId from '../../pluginId';
|
|
14
|
+
// Containers
|
|
15
|
+
import HomePage from '../HomePage';
|
|
16
|
+
|
|
17
|
+
function App() {
|
|
18
|
+
return (
|
|
19
|
+
<CheckPagePermissions permissions={pluginPermissions.main}>
|
|
20
|
+
<div className={pluginId}>
|
|
21
|
+
<Switch>
|
|
22
|
+
<Route path={`/plugins/${pluginId}`} component={HomePage} exact />
|
|
23
|
+
<Route component={NotFound} />
|
|
24
|
+
</Switch>
|
|
25
|
+
</div>
|
|
26
|
+
</CheckPagePermissions>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default App;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*
|
|
3
|
+
* HomePage actions
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
GET_DOC_INFOS,
|
|
9
|
+
GET_DOC_INFOS_SUCCEEDED,
|
|
10
|
+
ON_CHANGE,
|
|
11
|
+
ON_CLICK_DELETE_DOC,
|
|
12
|
+
ON_CONFIRM_DELETE_DOC,
|
|
13
|
+
ON_SUBMIT,
|
|
14
|
+
ON_UPDATE_DOC,
|
|
15
|
+
SET_FORM_ERRORS,
|
|
16
|
+
} from './constants';
|
|
17
|
+
|
|
18
|
+
export function getDocInfos() {
|
|
19
|
+
return {
|
|
20
|
+
type: GET_DOC_INFOS,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function getDocInfosSucceeded(data) {
|
|
25
|
+
return {
|
|
26
|
+
type: GET_DOC_INFOS_SUCCEEDED,
|
|
27
|
+
data,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function onChange({ target }) {
|
|
32
|
+
return {
|
|
33
|
+
type: ON_CHANGE,
|
|
34
|
+
keys: target.name.split('.'),
|
|
35
|
+
value: target.value,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function onClickDeleteDoc(version) {
|
|
40
|
+
return {
|
|
41
|
+
type: ON_CLICK_DELETE_DOC,
|
|
42
|
+
version,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function onConfirmDeleteDoc() {
|
|
47
|
+
return {
|
|
48
|
+
type: ON_CONFIRM_DELETE_DOC,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function onSubmit(e) {
|
|
53
|
+
e.preventDefault();
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
type: ON_SUBMIT,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function onUpdateDoc(version) {
|
|
61
|
+
return {
|
|
62
|
+
type: ON_UPDATE_DOC,
|
|
63
|
+
version,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function setFormErrors(errors) {
|
|
68
|
+
return {
|
|
69
|
+
type: SET_FORM_ERRORS,
|
|
70
|
+
errors,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
|
|
3
|
+
const ContainerFluid = styled.div`
|
|
4
|
+
padding: 18px 30px;
|
|
5
|
+
> div:first-child {
|
|
6
|
+
max-height: 33px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.buttonOutline {
|
|
10
|
+
height: 30px;
|
|
11
|
+
padding: 0 15px;
|
|
12
|
+
border: 1px solid #dfe0e1;
|
|
13
|
+
font-weight: 500;
|
|
14
|
+
font-size: 13px;
|
|
15
|
+
&:before {
|
|
16
|
+
margin-right: 10px;
|
|
17
|
+
content: '\f08e';
|
|
18
|
+
font-family: 'FontAwesome';
|
|
19
|
+
font-size: 10px;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
`;
|
|
23
|
+
|
|
24
|
+
const StyledRow = styled.div`
|
|
25
|
+
padding-top: 11px;
|
|
26
|
+
> div:last-child {
|
|
27
|
+
> div {
|
|
28
|
+
padding-bottom: 0 !important;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
> div:first-child {
|
|
32
|
+
> div {
|
|
33
|
+
margin-bottom: 22px !important;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
`;
|
|
37
|
+
|
|
38
|
+
const VersionWrapper = styled.div`
|
|
39
|
+
margin-top: -9px;
|
|
40
|
+
margin-left: -28px;
|
|
41
|
+
margin-right: -28px;
|
|
42
|
+
> div:first-child {
|
|
43
|
+
height: 18px;
|
|
44
|
+
line-height: 16px;
|
|
45
|
+
border-bottom: 0;
|
|
46
|
+
|
|
47
|
+
> div:nth-child(2) {
|
|
48
|
+
font-weight: 600;
|
|
49
|
+
color: #9ea7b8;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
> div:last-child {
|
|
53
|
+
> div {
|
|
54
|
+
border-bottom: none;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
`;
|
|
58
|
+
|
|
59
|
+
export { ContainerFluid, StyledRow, VersionWrapper };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*
|
|
3
|
+
* HomePage constants
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const GET_DOC_INFOS = 'documentation/HomePage/GET_DOC_INFOS';
|
|
8
|
+
export const GET_DOC_INFOS_SUCCEEDED = 'documentation/HomePage/GET_DOC_INFOS_SUCCEEDED';
|
|
9
|
+
export const ON_CHANGE = 'documentation/HomePage/ON_CHANGE';
|
|
10
|
+
export const ON_CLICK_DELETE_DOC = 'documentation/HomePage/ON_CLICK_DELETE_DOC';
|
|
11
|
+
export const ON_CONFIRM_DELETE_DOC = 'documentation/HomePage/ON_CONFIRM_DELETE_DOC';
|
|
12
|
+
export const ON_SUBMIT = 'documentation/HomePage/ON_SUBMIT';
|
|
13
|
+
export const ON_UPDATE_DOC = 'documentation/HomePage/ON_UPDATE_DOC';
|
|
14
|
+
export const SET_FORM_ERRORS = 'documentation/HomePage/SET_FORM_ERRORS';
|