diff --git a/docs/3.x.x/en/SUMMARY.md b/docs/3.x.x/en/SUMMARY.md index 163636c53f..1db11a45b3 100644 --- a/docs/3.x.x/en/SUMMARY.md +++ b/docs/3.x.x/en/SUMMARY.md @@ -34,7 +34,7 @@ * [Advanced usage](plugins/advanced.md) ### Guides - Advanced -* [Admin panel](guides-advanced/customize-admin.md) +* [Admin panel](advanced/customize-admin.md) * [Hooks](advanced/hooks.md) * [Logging](advanced/logging.md) * [Middlewares](advanced/middlewares.md) diff --git a/docs/3.x.x/en/guides-advanced/customize-admin.md b/docs/3.x.x/en/advanced/customize-admin.md similarity index 65% rename from docs/3.x.x/en/guides-advanced/customize-admin.md rename to docs/3.x.x/en/advanced/customize-admin.md index 8ae88f4129..61f9842538 100644 --- a/docs/3.x.x/en/guides-advanced/customize-admin.md +++ b/docs/3.x.x/en/advanced/customize-admin.md @@ -7,26 +7,29 @@ See the [Contributing Guide](https://github.com/strapi/strapi/blob/master/.githu ## Files structure The entire logic of the admin panel is located in a single folder named `./admin/`. This directory contains the following structure: - - `admin/`: - - `build/`: build of the front-end part generated by Webpack. - - `src/`: source code of the front-end part. - - `app.js`: entry point of the React application. - - `assets/`: contains necessary assets (images…). - - `components/`: contains components used by the admin panel. - - `containers/`: contains high level components. - - `favicon.ico`: favicon displayed in the web browser. - - `i18n.js`: logic for internationalization. - - `index.html`: basic html file in which are injected necessary styles and scripts. - - `reducers.js`: reducers logic. - - `store.js` store logic. - - `styles/`: contains the global styles. Specific styles are defined at the component level. - - `translations/`: text messages for each supported languages. - - `config/`: - - `routes.json`: admin panel API routes. - - `admin.json`: contains admin panel specific settings. - - `controllers/`: admin panel API controllers. - - `package.json`: contains admin panel dependencies list. - - `services/`: admin panel API services. +``` +/admin +└─── admin +| └─── build // Webpack generated build of the front-end +| └─── src // Front-end directory +| └─── app.js // Entry point of the Reacr application +| └─── assets // Assets directory containing images,... +| └─── components // Admin's React components directory +| └─── containers // Admin's high level components directory +| └─── favicon.ico // Favicon displayed in web browser +| └─── i18n.js // Internalization logic +| └─── index.html // Basic html file in which are injected necessary styles and scripts +| └─── reducers.js // Redux reducers logic +| └─── store.js // Redux store logic +| └─── styles // Directory containing the global styles. Specific styles are defined at the component level +| └─── translations // Directory containing text messages for each supported languages +└─── config +| └─── routes.json // Admin's API routes +| └─── admin.json // Admin's specific settings +└─── controllers // Admin's API controllers +└─── services // Admin's API services +└─── packages.json // Admin's npm dependencies +``` ## Customization diff --git a/docs/3.x.x/en/plugins/advanced.md b/docs/3.x.x/en/plugins/advanced.md index f30fd76ef7..bd72c85ccc 100644 --- a/docs/3.x.x/en/plugins/advanced.md +++ b/docs/3.x.x/en/plugins/advanced.md @@ -319,6 +319,8 @@ const shouldRenderCompo = (plugin) => new Promise((resolve, request) => { export default shouldRenderCompo; ``` +*** + ## Using React/Redux and sagas If your application is going to interact with some back-end application for data, we recommend using redux saga for side effect management. diff --git a/docs/3.x.x/en/tools/plugin-left-menu.md b/docs/3.x.x/en/plugins/plugin-left-menu.md similarity index 100% rename from docs/3.x.x/en/tools/plugin-left-menu.md rename to docs/3.x.x/en/plugins/plugin-left-menu.md diff --git a/docs/3.x.x/en/tools/button-library.md b/docs/3.x.x/en/tools/button-library.md deleted file mode 100644 index 21c5cc7643..0000000000 --- a/docs/3.x.x/en/tools/button-library.md +++ /dev/null @@ -1,20 +0,0 @@ -# Button library - -Button library based on bootstrap classes - -## Usage - -| Property | Type | Required | Description -:---| :---| :---| :--- -| `children`| node | no | Ex: `` | -| `className`| any | no | Sets a custom className. Ex: `` | -| `secondary`| bool | no | [Bootstrap className](https://v4-alpha.getbootstrap.com/components/buttons/) | -| `secondaryHotline` | bool | no | Sets className | -| `secondaryHotlineAdd` | bool | no | Inserts fontAwesone plus icon inside the button. Ex: `` | -| `type` | string | no | Sets the button type | diff --git a/docs/3.x.x/en/tools/i18n.md b/docs/3.x.x/en/tools/i18n.md deleted file mode 100644 index d45041314f..0000000000 --- a/docs/3.x.x/en/tools/i18n.md +++ /dev/null @@ -1,46 +0,0 @@ -# i18n - -[React Intl](https://github.com/yahoo/react-intl) provides React components and an API to format dates, numbers, and strings, including pluralization and handling translations. - -## Usage - -We recommend to set all your components text inside the translations folder. - -The example below shows how to use i18n inside your plugin. - -### Define all your ids with the associated message - -`// my-plugin/admin/src/translations/en.json` - -```json -{ - "notification.error.message": "An error occurred" -} -``` - -`// my-plugin/admin/src/translations/fr.json` - -```json -{ - "notification.error.message": "Une erreur est survenue" -} -``` - -### Usage inside a component - -Basic usage : - -```js -import { FormattedMessage } from 'react-intl'; - -const Foo = (props) => ( -
- - -
-) - -export default Foo; -``` - -[Check out the documentation](https://github.com/yahoo/react-intl/wiki/Components#formattedmessage) for more extensive usage. diff --git a/docs/3.x.x/en/tools/input-library.md b/docs/3.x.x/en/tools/input-library.md deleted file mode 100644 index 41946c0125..0000000000 --- a/docs/3.x.x/en/tools/input-library.md +++ /dev/null @@ -1,86 +0,0 @@ -# Input Library - -Strapi provides a built-in input library which includes : - - All kind of inputs - - Front-End validations - - Error highlight - - i18n - - ... - -## Usage - -```js -import React from 'react'; -// The library is available under node_modules/strapi-helper-plugin/src/components/Input -import Input from 'components/Input'; - -class Foo extends React.Component { - constructor(props) { - super(props); - - this.state { - data: { - foo: 'bar', - }, - error: false, - errors: [], - }; - } - - handleChange = ({ target }) => { - const value = target.type === 'number' ? Number(target.value) : target.value; - - const error = target.value.length === 0; - - if (error) { - this.setState({ error: !this.state.error, errors: [{ id: 'This input is required ' }] }); - } else { - this.setState({ data[target.name]: value }); - } - - } - - render() { - return ( -
- -
- ); - } -} -``` - -### Usage - -| Property | Type | Required | Description -:---| :---| :---| :--- -| `addon` | string | no | Allows to add a string addon in your input, based on [Bootstrap](https://v4-alpha.getbootstrap.com/components/input-group/#basic-example). Ex: `` | -| `addRequiredInputDesign` | bool | no | Allows to add an asterix on the input. Ex: `` | -| `customBootstrapClass` | string | no | Allows to override the input bootstrap col system. Ex: `` | -| `deactivateErrorHighlight` | bool | no | Prevents from displaying error highlight in the input: Ex: `` | -| `didCheckErrors` | bool | no | Use this props to display errors after submitting a form. Ex: `` | -| `disabled` | bool | no | Disable the input. Ex: `` | -| `errors` | array | no | Allows to display custom error messages. Ex: `` | -| `handleBlur` | func or bool | no | Overrides the default onBlur behavior. If bool passed to the component it will disabled the input validations checking. | -| `handleChange` | func | yes | Sets your reducer state. | -| `handFocus` | func | no | Adds an onFocus event to the input. | -| `inputDescription` | string | no | Allows to add an input description that is displayed like [bootstrap](https://v4-alpha.getbootstrap.com/components/forms/#defining-states). | -| `label` | string | yes | Displays the input's label with i18n | -| `linkContent` | object | no | Allows to display a link within the input's description. Ex: ``| -| `name` | string | yes | The key to update your reducer. | -| `noErrorsDescription` | bool | no | Prevents from displaying built-in errors. | -| `placeholder` | string | no | Allows to set a placeholder. | -| `pluginId` | string | no | Use to display name, placeholder... with i18n. | -| `selectOptions` | array | no | Options for the select. | -| `tabIndex` | string | no | Sets the order in which the inputs are focused on tab key press. | -| `title` | string | no | This props can only be used for checkboxes, it allows to add a title on top of the input, the label will be on the right side of the checkbox. | -| `validations` | object | yes | Allows to have the built-in input's validations. If set to {} the validations will be ignored. Ex: `` | -| `value` | string or bool or number | yes | The input's value. | diff --git a/docs/3.x.x/en/tools/prevent-plugin-rendering.md b/docs/3.x.x/en/tools/prevent-plugin-rendering.md deleted file mode 100644 index 6fc005eef3..0000000000 --- a/docs/3.x.x/en/tools/prevent-plugin-rendering.md +++ /dev/null @@ -1,127 +0,0 @@ -# Prevent a plugin from being rendered - -You can prevent your plugin from being rendered if some conditions aren't met. - -## Usage - -To disable your plugin's rendering, you can simply create `requirements.js` file at the root of your `src` plugin's folder. -This file must contain a default function that returns a `Promise`; - -Example: - -Let's say that you want to disable your plugin if the server autoReload config is disabled in development mode. - - -``` -// config/environments/development/server.json -{ - "host": "localhost", - "port": 1337, - "cron": { - "enabled": false - } -} -``` - -You'll first create a request to check if the `autoReload` config is enabled. - -```json -// plugins/my-plugin/config/routes.json -{ - "routes": [ - { - "method": "GET", - "path": "/autoReload", - "handler": "MyPlugin.autoReload", - "config": { - "policies": [] - } - } - ] -} -``` -Then the associated handler: - -```js -// plugins/my-plugin/controllers/MyPlugin.js - -const _ = require('lodash'); -const send = require('koa-send'); - -module.exports = { - autoReload: async ctx => { - ctx.send({ autoReload: _.get(strapi.config.environments, 'development.server.autoReload', false) }); - } -} -``` - -Finally, you'll create a file called `requirements.js`at the root of your plugin's src folder. - -The default function exported must return a `Promise`. -If you wan't to prevent the plugin from being rendered you'll have to set `plugin.preventComponentRendering = true;`. -In this case, you'll have to set: -```js -plugin.blockerComponentProps = { - blockerComponentTitle: 'my-plugin.blocker.title', - blockerComponentDescription: 'my-plugin.blocker.description', - blockerComponentIcon: 'fa-refresh', -}; -``` - -To follow the example above: - -```js -// plugin/my-plugin/admin/src/requirements.js - -// Use our request helper -import request from 'utils/request'; - -const shouldRenderCompo = (plugin) => new Promise((resolve, request) => { - request('/my-plugin/autoReload') - .then(response => { - // If autoReload is enabled the response is `{ autoReload: true }` - plugin.preventComponentRendering = !response.autoReload; - // Set the BlockerComponent props - plugin.blockerComponentProps = { - blockerComponentTitle: 'my-plugin.blocker.title', - blockerComponentDescription: 'my-plugin.blocker.description', - blockerComponentIcon: 'fa-refresh', - blockerComponentContent: 'renderIde', // renderIde will add an ide section that shows the development environment server.json config - }; - - return resolve(plugin); - }) - .catch(err => reject(err)); -}); - -export default shouldRenderCompo; -``` -## Customization - -You can render your own custom blocker by doing as follows: - -```js -// plugin/my-plugin/admin/src/requirements.js - -// Use our request helper -import request from 'utils/request'; - -// Your custom blockerComponentProps -import MyCustomBlockerComponent from 'components/MyCustomBlockerComponent'; - -const shouldRenderCompo = (plugin) => new Promise((resolve, request) => { - request('/my-plugin/autoReload') - .then(response => { - // If autoReload is enabled the response is `{ autoReload: true }` - plugin.preventComponentRendering = !response.autoReload; - - // Tell which component to be rendered instead - plugin.blockerComponent = MyCustomBlockerComponent; - - return resolve(plugin); - }) - .catch(err => reject(err)); -}); - -export default shouldRenderCompo; -``` diff --git a/docs/3.x.x/en/tools/router.md b/docs/3.x.x/en/tools/router.md deleted file mode 100644 index 81ed481e9e..0000000000 --- a/docs/3.x.x/en/tools/router.md +++ /dev/null @@ -1,279 +0,0 @@ -# Using the React Router V4 - -User navigation within your plugin can be managed by two different ways : - - Using the [React Router V4 API](https://reacttraining.com/react-router/web/guides/philosophy) - - Using the main router from the app - -## Routing declaration - -### Routing - -The routing is based on [React Router V4](https://reacttraining.com/react-router/web/guides/philosophy), due to it's implementation each route is declared in the containers/App/index.js file. - -Also, we chose to use the [Switch Router](https://reacttraining.com/react-router/web/api/Switch) because it renders a route exclusively. - -Route declaration : - -Let's say that you want to create a route /user with params /:id associated with the container User. - -The declaration would be as followed : - - - ```js - // File : `plugins/my-plugin/admin/src/containers/App/index.js`. - - import UserPage from 'containers/UserPage' - - // ... - - render() { - return ( -
- - - -
- ); - } - ``` - - -### Using Redux/sagas - -Due to React Router V4 your container's store is not directly injected. -To inject your container store if it's associated with a router you have to do it manually. - -As an example, you created a Foo container associated with the route `/plugins/my-plugin/bar`, and you want to use redux/action/reducer/sagas. - -Your `plugins/my-plugin/admin/src/containers/App/index.js` file will look as followed : - -```js -// plugins/my-plugin/admin/src/containers/App/index.js - -import FooPage from 'containers/FooPage' - -// ... - -render() { - return ( -
- - - -
- ); - -} -``` - -```js -// plugins/my-plugin/admin/src/containers/FooPage/index.js - -import React from 'react'; -import { connect } from 'react-redux'; -import { createStructuredSelector } from 'reselect'; -import { bindActionCreators, compose } from 'redux'; -import PropTypes from 'prop-types'; - -// Utils to create your container store -import injectReducer from 'utils/injectReducer'; -import injectSaga from 'utils/injectSaga'; - -import { - foo, - bar, -} from './actions'; - -import reducer from './reducer'; - -import saga from './sagas'; -import { makeSelectFooPage } from './selectors'; - -// Styles -import styles from './styles.scss'; - -export class FooPage extends React.Component { - render() { - return ( -
- Awesome container -
- ); - } -} - -FooPage.propTypes = { - fooPage: PropTypes.any, -} - -function mapDispatchToProps(dispatch) { - return bindActionCreators( - { - foo, - bar, - }, - dispatch - ); -} - -const mapStateToProps = createStructuredSelector({ - fooPage: makeSelectFooPage(), -}); - -const withConnect = connect(mapStateToProps, mapDispatchToProps); - -// This is where you create your container store -// the key must correspond to your container name in lowerCase -const withSagas = injectSaga({ key: 'fooPage', saga }); -const withReducer = injectReducer({ key: 'fooPage', reducer }); - -export default compose( - withReducer, - withSagas, - withConnect, -)(FooPage); -``` - - -Important : If you have a container which can be a child of several other containers (i.e. it doesn't have a route), in order to create the store -you'll have to inject it directly in the `plugins/my-plugin/admin/src/containers/App/index.js` file as follows : - -```js -// containers/App/index.js - -// ... - -import fooPageReducer from 'containers/FooPage/reducer'; -import fooPageSagas from 'container/FooPage/sagas'; - -import reducer from './reducer'; -import saga from './sagas'; - -// ... - -export class App extends React.Component { - render() { - // ... - } -} - -// ... - -function mapDispatchToProps(dispatch) { - return bindActionCreators( - {}, - dispatch - ); -} - -const mapStateToProps = createStructuredSelector({ - // ... -}); - -const withConnect = connect(mapStateToProps, mapDispatchToProps); - -// FooPage reducer -const withFooPageReducer = injectReducer({ key: 'fooPage', reducer: fooPageReducer }); -// Global reducer -const withReducer = injectReducer({ key: 'global', reducer }); -// FooPage sagas -const withFooPageSagas = injectSaga({ key: 'fooPage', saga: fooPageSagas }); -// Global saga -const withSagas = injectSaga({ key: 'global', saga }); - -export default compose( - withFooPageReducer, - withReducer, - withFooPageSagas, - withSagas, - withConnect, -)(App); -``` - -## Using React Router - - [Link](https://reacttraining.com/react-router/web/api/Link) provides declarative, accessible navigation around your application : - - ```js - - - // Same as - - - ``` - - [NavLink](https://reacttraining.com/react-router/web/api/NavLink) will add styling attributes to the rendered element when it matches the current URL. - - - ```js - FAQs - ``` -## Using the App Router - -We use the app router if we want to make a redirection after some user's action (ex: after submitting a form). - -```js -import React from 'react'; -import { bindActionCreators } from 'redux'; -import { connect, compose } from 'react-redux'; -import PropTypes from 'prop-types'; - -// App router -import { router } from 'app'; - -// Utils -import injectSaga from 'utils/injectSaga'; -import injectReducer from 'utils/injectReducer'; - -// Actions -import { foo, bar } from './actions'; -// Sagas -import saga from './sagas'; -// Selectors -import selectFoo from './Selectors'; -// Reducer -import reducer from './reducer'; - -export class Foo extends React.Component { - componentWillReceiveProps(nextProps) { - if (nextProps.foo !== this.props.foo) { - const hash = this.props.location.hash; - const pathname = this.props.match.pathname; - const search = '?foo=bar'; - router.push({ pathname, search, hash }); - } - } - - render() { - return
Hello
; - } -} -Foo.propTypes = { - foo: PropTypes.bool.isRequired, - location: PropTypes.object.isRequired, - match: PropTypes.object.isRequired, -}; - -const mapStateToProps = selectFoo(); - -function mapDispatchToProps(dispatch) { - return bindActionCreators({}, dispatch); -} - -const withConnect = connect(mapStateToProps, mapDispatchToProps); -const withReducer = injectReducer({ key: 'foo', reducer }); -const withSagas = injectSaga({ key: 'foo', saga }); - -export default compose( - withReducer, - withSagas, - withConnect, -)(Foo); -``` diff --git a/docs/3.x.x/en/tools/using-actions-reducer-sagas.md b/docs/3.x.x/en/tools/using-actions-reducer-sagas.md deleted file mode 100644 index 217ce58f59..0000000000 --- a/docs/3.x.x/en/tools/using-actions-reducer-sagas.md +++ /dev/null @@ -1,282 +0,0 @@ -# Redux saga - -If your application is going to interact with some back-end application for data, we recommend using redux saga for side effect management. - -## Example : fetching data on router change - -This example will show how to fetch data using actions/reducer/sagas. - -### Constants declaration - -```js -// containers/Foo/constants.js -export const DATA_FETCH = 'MyPlugin/Foo/DATA_FETCH'; -export const DATA_FETCH_ERROR = 'MyPlugin/Foo/DATA_FETCH_ERROR'; -export const DATA_FETCH_SUCCEEDED = 'MyPlugin/Foo/DATA_FETCH_SUCCEEDED'; -``` - -### Actions declaration - -```js -// containers/Foo/actions.js -import { - DATA_FETCH, - DATA_FETCH_ERROR, - DATA_FETCH_SUCCEEDED, -} from './constants'; - -export function dataFetch(params) { - return { - type: DATA_FETCH, - params, - }; -} - -export function dataFetchError(errorMessage) { - return { - type: DATA_FETCH_ERROR, - errorMessage, - }; -} - -export function dataFetchSucceeded(data) { - return { - type: DATA_FETCH_SUCCEEDED, - data, - }; -} -``` - -### Reducer - -We strongly recommend to use [Immutable.js](https://facebook.github.io/immutable-js/) to structure your data. - -```js -// containers/Foo/reducer.js -import { fromJS, Map } from 'immutable'; -import { - DATA_FETCH_ERROR, - DATA_FETCH_SUCCEEDED, -} from './constants'; - -const initialState = fromJS({ - data: Map({}), - error: false, - errorMessage: '', - loading: true, -}); - -function fooReducer(state = initialState, action) { - switch (action.type) { - case DATA_FETCH_ERROR: - return state - .set('error', true) - .set('errorMessage', action.errorMessage) - .set('loading', false); - case DATA_FETCH_SUCCEEDED: - return state - .set('data', Map(action.data)) - .set('error', false) - .set('errorMessage', '') - .set('loading', false); - break; - default: - return state; - } -} - -export default fooReducer; -``` -### Sagas - -```js -// container/Foo/sagas.js -import { takeLatest } from 'redux-saga'; -import { LOCATION_CHANGE } from 'react-router-redux'; -import { put, fork, call, take, cancel } from 'redux-saga/effects'; - -// Use our request helper -import { request } from 'utils/request'; - -// Actions -import { dataFetchError, dataFetchSucceeded } from './actions'; -import { DATA_FETCH } from './constants'; - -export function* fetchData(action) { - try { - const requestUrl = `/baseUrl/${action.params}`; - const opts = { - method: 'GET', - }; - - // Fetch data - const response = yield call(request, requestUrl, opts); - - // Pass the response to the reducer - yield put(dataFetchSucceeded(response)); - - } catch(error) { - yield put(dataFetchError(error)); - } -} - -// Individual export for testing -function* defaultSaga() { - // Listen to DATA_FETCH event - const fetchDataWatcher = yield fork(takeLatest, DATA_FETCH, fetchData); - - // Cancel watcher - yield take(LOCATION_CHANGE); - - yield cancel(fetchDataWatcher); -} - -export default defaultSaga; -``` - -N.B. You can use a selector in your saga : - -```js -import { put, select, fork, call, take, cancel } from 'redux-saga/effects'; -import { makeSelectUserName } from './selectors'; - -export function* foo() { - try { - const userName = yield select(makeSelectUserName()); - - // ... - } catch(error) { - // ... - } -} - -function defaultSaga() { - // ... -} - -export default defaultSaga; -``` - - -### Selectors - -[Reselect](https://github.com/reactjs/reselect) is a library used for slicing your redux state and providing only the relevant sub-tree to a react component. It has three key features: - - 1. Computational power - 2. Memoization - 3. Composability - - Creating a selector - ```js - import { createSelector } from 'reselect'; - - /** - * Direct selector to the foo state domain - */ - const selectFooDomain = () => state => state.get('foo'); - - /** - * Other specific selectors - */ - - const makeSelectLoading = () => createSelector( - selectFooDomain(), - (substate) => substate.get('loading'), - ); - - /** - * Default selector used by ModelPage - */ - - const selectFoo = () => createSelector( - selectFooDomain(), - (substate) => substate.toJS() - ); - - export default selectFoo; - export { makeSelectLoading }; - - ``` - - -### INDEX.js - -```js -// containers/Foo/index.js -import React from 'react'; -import { bindActionCreators } from 'redux'; -import { connect, compose } from 'react-redux'; -import PropTypes from 'prop-types'; - -// Main router -import { router } from 'app'; - -// Utils -import injectSaga from 'utils/injectSaga'; -import injectReducer from 'utils/injectReducer'; - -// Actions -import { dataFetch } from './actions'; -// sagas -import saga from './sagas'; -// Selectors -import selectFoo from './selectors'; -// Reducer -import reducer from './reducer'; - -export class Foo extends React.Component { - componentWillReceiveProps(nextProps) { - if (this.props.error !== nextProps.error && nextProps.error) { - window.Strapi.notification.error(this.props.errorMessage); - } - } - - componentDidUpdate(prevProps) { - if (prevProps.match.pathname !== this.props.pathname) { - this.props.dataFetch(this.props.match.params.bar); - } - } - - render() { - if (this.props.error) return
An error occurred
; - - return ( -
-

Data display

- {this.props.data.foo} - {this.props.data.bar} -
- ); - } - - Foo.propTypes = { - data: PropTypes.object.isRequired, - dataFetch: PropTypes.func.isRequired, - error: PropTypes.bool.isRequired, - errorMessage: PropTypes.string.isRequired, - match: PropTypes.object.isRequired, - }; - - const mapStateToProps = selectFoo(); - - function mapDispatchToProps(dispatch) { - return bindActionCreators( - { - dataFetch, - }, - dispatch - ); - } - - const withConnect = connect(mapStateToProps, mapDispatchToProps); - const withReducer = injectReducer({ key: 'foo', reducer }); - const withSagas = injectSaga({ key: 'foo', saga }); - - export default compose( - withReducer, - withSagas, - withConnect, - )(Foo); -} - -``` diff --git a/docs/3.x.x/en/ui-components/component-button.md b/docs/3.x.x/en/ui-components/component-button.md deleted file mode 100644 index b777578fc0..0000000000 --- a/docs/3.x.x/en/ui-components/component-button.md +++ /dev/null @@ -1,60 +0,0 @@ -# Component Button - -Button library based on bootstrap classes - -![Buttons img](../assets/buttons.png) - -## Usage - -| Property | Type | Required | Description | -| -------- | ---- | -------- | ----------- | -| `children`| node | no | Ex: `` | -| `className` | any | no | Sets a custom className. Ex: `` | -| `secondary`| bool | no | [Bootstrap className](https://v4-alpha.getbootstrap.com/components/buttons/) | -| `secondaryHotline` | bool | no | Sets className | -| `secondaryHotlineAdd` | bool | no | Inserts fontAwesone plus icon inside the button. Ex: `` | -| `type` | string | no | Sets the button type | - -## Example - - **Path —** `./plugins/my-plugin/admin/src/translations/en.json`. -```json -{ - "myPlugin.button.label": "Add a new" -} -``` - -**Path —** `./plugins/my-plugin/admin/src/components/Foo/index.js`. -```js -import Button from 'components/Button'; - -const Foo = () => { - // Define your buttons - const buttons = [ - { - label: 'myPlugin.button.label', - labelValues: { - foo: 'Bar', - }, - kind: 'primaryAddShape', - onClick: () => console.log('Click'), - }, - ]; - - return ( -
- {buttons.map((buttonProps) =>
- ); -} - -// Will display a primaryAddShape button with label: 'Add a new Bar' - -export default Button; -``` diff --git a/docs/3.x.x/en/ui-components/component-input.md b/docs/3.x.x/en/ui-components/component-input.md deleted file mode 100644 index de58657adb..0000000000 --- a/docs/3.x.x/en/ui-components/component-input.md +++ /dev/null @@ -1,85 +0,0 @@ -# Input Library - -Strapi provides a built-in input library which includes : - - All kind of inputs - - Front-End validations - - Error highlight - - i18n - -## Usage - -| Property | Type | Required | Description | -| -------- | ---- | -------- | ----------- | -| `addon` | string | no | Allows to add a string addon in your input, based on [Bootstrap](https://v4-alpha.getbootstrap.com/components/input-group/#basic-example). Ex: `` | -| `addRequiredInputDesign` | bool | no | Allows to add an asterix on the input. Ex: `` | -| `customBootstrapClass` | string | no | Allows to override the input bootstrap col system. Ex: `` | -| `deactivateErrorHighlight` | bool | no | Prevents from displaying error highlight in the input: Ex: `` | -| `didCheckErrors` | bool | no | Use this props to display errors after submitting a form. Ex: `` | -| `disabled` | bool | no | Disable the input. Ex: `` | -| `errors` | array | no | Allows to display custom error messages. Ex: `` | -| `handleBlur` | func or bool | no | Overrides the default onBlur behavior. If bool passed to the component it will disabled the input validations checking. | -| `handleChange` | func | yes | Sets your reducer state. | -| `handFocus` | func | no | Adds an onFocus event to the input. | -| `inputDescription` | string | no | Allows to add an input description that is displayed like [bootstrap](https://v4-alpha.getbootstrap.com/components/forms/#defining-states). | -| `label` | string | yes | Displays the input's label with i18n. | -| `linkContent` | object | no | Allows to display a link within the input's description. Ex: {% raw %} ``` ``` {% endraw %} | -| `name` | string | yes | The key to update your reducer. | -| `noErrorsDescription` | bool | no | Prevents from displaying built-in errors. | -| `placeholder` | string | no | Allows to set a placeholder. | -| `pluginId` | string | no | Use to display name, placeholder... with i18n. | -| `selectOptions` | array | no | Options for the select. | -| `tabIndex` | string | no | Sets the order in which the inputs are focused on tab key press. | -| `title` | string | no | This props can only be used for checkboxes, it allows to add a title on top of the input, the label will be on the right side of the checkbox. | -| `validations` | object | yes | Allows to have the built-in input's validations. If set to {} the validations will be ignored. Ex: {% raw %} ``` ``` {% endraw %} | -| `value` | string or bool or number | yes | The input's value. | - -## Example - -```js -import React from 'react'; -// The library is available under node_modules/strapi-helper-plugin/src/components/Input -import Input from 'components/Input'; - -class Foo extends React.Component { - constructor(props) { - super(props); - - this.state { - data: { - foo: 'bar', - }, - error: false, - errors: [], - }; - } - - handleChange = ({ target }) => { - const value = target.type === 'number' ? Number(target.value) : target.value; - - const error = target.value.length === 0; - - if (error) { - this.setState({ error: !this.state.error, errors: [{ id: 'This input is required ' }] }); - } else { - this.setState({ data[target.name]: value, error: false, errors: [] }); - } - - } - - render() { - return ( -
- -
- ); - } -} -``` diff --git a/docs/3.x.x/en/ui-components/component-popup-warning.md b/docs/3.x.x/en/ui-components/component-popup-warning.md deleted file mode 100644 index 35da247521..0000000000 --- a/docs/3.x.x/en/ui-components/component-popup-warning.md +++ /dev/null @@ -1,74 +0,0 @@ -# PopUp Warning - -PopUp warning library based on [reactstrap](https://reactstrap.github.io/components/modals/). - -![PopUp warning img](../assets/popup-warning.png) - -## Usage - -| Property | Type | Required | Description | -| -------- | ---- | -------- | ----------- | -| bodyMessage | string | no | Body message of the pop up (works with i18n). | -| handleConfirm | func | yes | Function executed when the user clicks on the `Confirm button`. | -| isOpen | bool | yes | Show or hide the popup. | -| popUpWarningType | string | yes | Sets the popup body icon. Available types: `danger`, `info`, `notFound`, `success`, `warning` | -| toggleModal | func | yes | Function to toggle the modal. | - - -## Example - -**Path —** `./plugins/my-plugin/admin/src/translations/en.json`. -```json -{ - "button.label": "Click me", - "popup.danger.message": "Are you sure you want to delete this item?" -} -``` - -**Path —** `./plugins/my-plugin/admin/src/translations/fr.json`. -```json -{ - "button.label": "Cliquez", - "popup.danger.message": "Êtes-vous certain de vouloir supprimer ce message?" -} -``` - -**Path —** `./plugins/my-plugin/admin/src/containers/Foo/index.js`. -```js -// ... - -import Button from 'components/Button'; -import PopUpWarning from 'components/PopUpWarning'; - -// ... - -class Foo extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false, - }; - } - - handlePopUpConfirm = () => { - // Some logic Here - this.setState({ isOpen: false }); - } - - render() { - return( -
-
- ); - } -} - -export default Foo; -``` diff --git a/docs/3.x.x/en/usage/consume-api.md b/docs/3.x.x/en/usage/consume-api.md deleted file mode 100644 index 95fb4ab229..0000000000 --- a/docs/3.x.x/en/usage/consume-api.md +++ /dev/null @@ -1,112 +0,0 @@ -# Consume your API - -Let's say you created a Product API with name, description and float fields. - -## List entries - -To retrieve the list of products, use `GET /your-content-type` route. - -Generated APIs provides a handy way to filter and order queries. That way, ordering products by price is as easy as `GET http://localhost:1337/product?_order=price:asc`. For more information, read the [filters documentation](todo.md). - -Here is an example using jQuery. - -```js -$.ajax({ - type: 'GET', - url: 'http://localhost:1337/product_order=price:asc', // Order by price. - done: function(products) { - console.log('Well done, here is the list of products: ', products); - }, - fail: function(error) { - console.log('An error occurred:', error); - } -}); -``` - -## Get a specific entry - -If you want to get a specific entry, add the `id` of the wanted product at the end of the url. - -```js -$.ajax({ - type: 'GET', - url: 'http://localhost:1337/product/123', // Where `123` is the `id` of the product. - done: function(product) { - console.log('Well done, here is the product having the `id` 123: ', product); - }, - fail: function(error) { - console.log('An error occurred:', error); - } -}); -``` - -## Create data (POST) - -Use the `POST` route to create a new entry. - -jQuery example: - -```js -$.ajax({ - type: 'POST', - url: 'http://localhost:1337/product', - data: { - name: 'Cheese cake', - description: 'Chocolate cheese cake with ice cream', - price: 5 - }, - done: function(product) { - console.log('Congrats, your product has been successfully created: ', product); // Remember the product `id` for the next steps. - }, - fail: function(error) { - console.log('An error occurred:', error); - } -}); -``` - -## Update data (PUT) - -Use the `PUT` route to update an existing entry. - -jQuery example: - -```js -$.ajax({ - type: 'PUT', - url: 'http://localhost:1337/product/123', // Where `123` is the `id` of the product. - data: { - description: 'This is the new description' - }, - done: function(product) { - console.log('Congrats, your product has been successfully updated: ', product.description); - }, - fail: function(error) { - console.log('An error occurred:', error); - } -}); -``` - -## Delete data (DELETE) - -Use the `DELETE` route to delete an existing entry. - -jQuery example: - -```js -$.ajax({ - type: 'DELETE', - url: 'http://localhost:1337/product/123', // Where `123` is the `id` of the product. - done: function(product) { - console.log('Congrats, your product has been successfully deleted: ', product); - }, - fail: function(error) { - console.log('An error occurred:', error); - } -}); -``` - -*** - -Congratulations! You successfully finished the Getting Started guide! Read the [documentation](../admin.md) to understand more advanced concepts. - -Also, feel free to join the community thanks to the different channels listed in the [community page](/community): team members, contributors and developers will be happy to help you. diff --git a/docs/3.x.x/en/usage/create-project.md b/docs/3.x.x/en/usage/create-project.md deleted file mode 100644 index a1c300fcf5..0000000000 --- a/docs/3.x.x/en/usage/create-project.md +++ /dev/null @@ -1,17 +0,0 @@ -# Create your first project - -After having [installed Strapi](installation.md), you are now ready to create your first project. - -## Command Line - -The first step is to **open your terminal** in the directory you want to create your application in. Then, type - -``` -$ strapi new my-project -``` - -![Generate a Strapi project](../assets/new-project.png) - -## Files structure - -This action creates a new folder named `my-project` with the entire [files structure](../API.md) of a Strapi application. diff --git a/docs/3.x.x/en/usage/generate-api.md b/docs/3.x.x/en/usage/generate-api.md deleted file mode 100644 index 56df9537fb..0000000000 --- a/docs/3.x.x/en/usage/generate-api.md +++ /dev/null @@ -1,45 +0,0 @@ -# Generate an API - -There is two ways to create an API: - - Using the Content Type Builder plugin. - - Using the CLI. - -## Content Type Builder - -The easiest way is to use the Content Type Builder plugin: a powerful UI to help you to create an API within a few clicks. - -To create your API using the Content Type Builder: - - Start your project and visit the admin panel at the following address: http://localhost:1337/admin/plugins/content-type-builder. - - Click on "Create Content Type", set `product` as name and submit the form. - - Then, click on "Add fields", add the following fields: - - A `string` field named `name`. - - A `text` field named `description`. - - A `float` field named `price`. - - Save. - -That's it: your API is created! - -![Strapi Content Type Builder](../assets/content-type-builder.png) - -## CLI generator - -You can also use the [CLI](CLI.md) and its powerful generators. - -Type in your terminal the following command: - -``` -$ strapi generate:api product name:string description:text price:float -``` - -Here are some explanations: - - `product` is the name of your Content Type. - - `name`, `description` and `price` are the attributes. - - `string`, `text` and `float` are the types of the attributes. - -For more information, read the [CLI documentation](CLI.md). - -![Generate an API](../assets/generate-api.png) - -### Files structure (I think we should remove this part) - -Whatever option you used to create your API, a new directory has been created in the `api` folder of your application which contains all the needed stuff for your `product` Content Type: API, routes, controller, service and model. Take a look at the [API structure documentation](API.md) for more informations. diff --git a/docs/3.x.x/en/usage/manage-data.md b/docs/3.x.x/en/usage/manage-data.md deleted file mode 100644 index 9d27a5c83e..0000000000 --- a/docs/3.x.x/en/usage/manage-data.md +++ /dev/null @@ -1,21 +0,0 @@ -# Manage data - -Let's say you created a Product API with name, description and price fields. - -In this section, we will discover the tool that Strapi provides to help you to manage your data. - -## Content Manager - -If you visit your admin panel at http://localhost:1337/admin, you can access to a plugin named Content Manager. This powerful interface is auto-generated according to your Content Types and lets you create, update and delete your data from UI. - -### Create a product - -Try to create a new product by clicking on "New entry". Give it a name, a description and a price. Submit the form. You can see the new product in the products list. - -### Edit a product - -From the list view, you can click on a product and edit its values. - -### Delete a product - -From the list view and the edit view, you can delete a product. diff --git a/docs/3.x.x/en/usage/start-server.md b/docs/3.x.x/en/usage/start-server.md deleted file mode 100644 index 4ec51b0252..0000000000 --- a/docs/3.x.x/en/usage/start-server.md +++ /dev/null @@ -1,17 +0,0 @@ -# Start your server - -To launch your app, go in its directory and run the following command: - -``` -$ strapi start -``` - -![Start Strapi](../assets/strapi-start.png) - -Visit http://localhost:1337 to see it live! - -You can also discover the admin panel at the following address: http://localhost:1337/admin. - -*** - -Your server is up and running.