Merge branch 'master' into fix/readCallbackProvider

This commit is contained in:
Fredrik Söderquist 2020-01-15 11:25:12 +01:00 committed by GitHub
commit 21bbbbcfe8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 590 additions and 118 deletions

View File

@ -7,7 +7,7 @@ module.exports = {
'prettier',
],
plugins: ['react', 'redux-saga', 'react-hooks'],
plugins: ['react', 'redux-saga', 'react-hooks', 'import'],
env: {
browser: true,
commonjs: true,
@ -51,4 +51,13 @@ module.exports = {
version: '16.5.2',
},
},
overrides: [
{
files: ['packages/**/admin/src/**/**/*.js'],
rules: {
'no-nested-ternary': ['error'],
'import/order': 2,
},
},
],
};

View File

@ -15,7 +15,7 @@ You can also use **yarn** if you want [here](https://yarnpkg.com/en/docs/getting
Strapi is supporting multiple databases. If you are using the `--quickstart` or if you manually chose the `SQLite` database, you will not need to install any database on you local computer.
If you want to use a custom database, here is versions you will have to respect:
If you want to use a custom database, here are the versions you will have to respect:
- **MongoDB** >= 3.6
- **MySQL** >= 5.6

View File

@ -62,8 +62,10 @@ NODE_ENV=production npm run build
```bash
npm install cross-env
```
Then in your `package.json` scripts section:
```bash
```bash
"production": "cross-env NODE_ENV=production npm run build"
```
@ -96,7 +98,9 @@ NODE_ENV=production npm start
```bash
npm install cross-env
```
Then in your `package.json` scripts section:
```bash
"production": "cross-env NODE_ENV=production npm start"
```
@ -1340,10 +1344,30 @@ If you plan to use **MongoDB** with your project, [refer to the create a Strapi
`Path: ./`
:::: tabs
::: tab yarn
Use **yarn** to install the Strapi project (**recommended**). [Install yarn with these docs](https://yarnpkg.com/lang/en/docs/install/)
```bash
strapi new my-project --quickstart
yarn create strapi-app my-project --quickstart
```
:::
::: tab npx
Use **npm/npx** to install the Strapi project
```bash
npx create-strapi-app my-project --quickstart
```
:::
::::
::: tip
When you use `--quickstart` to create a Strapi project locally, a **SQLite database** is used which is not compatible with Heroku. Therefore, another database option [must be chosen](#_6-heroku-database-set-up).
:::

View File

@ -496,7 +496,7 @@ RENAME TABLE groups_old_table_name TO components_new_table_name;
**2. Change the `collectionName` of the component**
**Before**
`./components/component.json`
`./components/yourcategoryname/yourcomponentname.json`
```json
{
@ -506,7 +506,7 @@ RENAME TABLE groups_old_table_name TO components_new_table_name;
```
**After**
`./components/component.json`
`./components/yourcategoryname/yourcomponentname.json`
```json
{
@ -565,7 +565,7 @@ db.collection.renameCollection('groups_my_group', 'components_my_component');
**3. Change the `collectionName` of the component**
**Before**
`./components/component.json`
`./components/yourcategoryname/yourcomponentname.json`
```json
{
@ -575,7 +575,7 @@ db.collection.renameCollection('groups_my_group', 'components_my_component');
```
**After**
`./components/component.json`
`./components/yourcategoryname/yourcomponentname.json`
```json
{

View File

@ -134,19 +134,317 @@ axios
#### Providers
Thanks to [Grant](https://github.com/simov/grant) and [Purest](https://github.com/simov/purest), you can easily use OAuth and OAuth2
providers to enable authentication in your application. By default,
Strapi comes with the following providers:
Thanks to [Grant](https://github.com/simov/grant) and [Purest](https://github.com/simov/purest), you can easily use OAuth and OAuth2 providers to enable authentication in your application.
- [Discord](https://github.com/strapi/strapi-examples/blob/master/login-react/doc/discord_setup.md)
- [Facebook](https://github.com/strapi/strapi-examples/blob/master/login-react/doc/fb_setup.md)
- [Google](https://github.com/strapi/strapi-examples/blob/master/login-react/doc/google_setup.md)
- [Github](https://github.com/strapi/strapi-examples/blob/master/login-react/doc/github_setup.md)
- [Twitter](https://github.com/strapi/strapi-examples/blob/master/login-react/doc/twitter_setup.md)
Before setting up a provider, you'll need to install the `ngrok` package globally to work with providers that don't allow `localhost` redirect URIs.
[👀 See our complete example with detailed tutorials for each provider (with React)](https://github.com/strapi/strapi-examples/tree/master/login-react)
In the following examples, the client app will be the [react login examples app](https://github.com/strapi/strapi-examples/tree/master/login-react). It will be running on `http://localhost:3000`.
---
:::: tabs
::: tab GitHub
### Setup the server
Use `ngrok` to serve the frontend app.
```
ngrok http 3000
```
### Github configuration
- Visit the OAuth Apps list page <br> [https://github.com/settings/developers](https://github.com/settings/developers)
- Click on **New OAuth App** button
Then fill the informations:
- **Application name**: Strapi GitHub auth
- **Homepage URL**: `https://65e60559.ngrok.io`
- **Application description**: Strapi provider auth description
- **Authorization callback URL**: `https://65e60559.ngrok.io/connect/github`
### Strapi configuration
- Visit the User Permissions provider settings page <br> [http://localhost:1337/admin/plugins/users-permissions/providers](http://localhost:1337/admin/plugins/users-permissions/providers)
- Click on the **GitHub** provider
Then fill the informations:
- **Enable**: `ON`
- **Client ID**: 53de5258f8472c140917
- **Client ID**: fb9d0fe1d345d9ac7f83d7a1e646b37c554dae8b
- **The redirect URL to your front-end app**: `https://65e60559.ngrok.io/connect/github`
:::
::: tab Facebook
### Setup the server
Use `ngrok` to serve the server app.
```
ngrok http 1337
```
### Facebook configuration
- Visit the Developer Apps list page <br> [https://developers.facebook.com/apps/](https://developers.facebook.com/apps/)
- Click on **Add a New App** button
- Fill the **Display Name** in the modal and create the app
- Setup a **Facebook Login** product
- Click on the **PRODUCTS > Facebook login > Settings** link in the left menu
Then fill the informations:
- **Valid OAuth Redirect URIs**: `https://559394cd.ngrok.io/connect/facebook/callback`
To access the Application ID and secret:
- Click on **Settings** in the left menu
- Then on **Basic** link
### Strapi configuration
- Visit the User Permissions provider settings page <br> [http://localhost:1337/admin/plugins/users-permissions/providers](http://localhost:1337/admin/plugins/users-permissions/providers)
- Click on the **Facebook** provider
Then fill the informations:
- **Enable**: `ON`
- **Client ID**: 2408954435875229
- **Client ID**: 4fe04b740b69f31ea410b9391ff3b5b0
- **The redirect URL to your front-end app**: `http://localhost:3000/connect/facebook`
:::
::: tab Google
### Facebook configuration
- Visit the Google Developer Console <br> [https://console.developers.google.com/](https://console.developers.google.com/)
- Click on the **Select a project** dropdown in the top menu
- Then click **NEW PROJECT** button
- Fill the **Project name** input and create
Wait a few seconds while the application is created.
- On the project dropdown, select your new project
- Click on **Go to APIs overview** Under the **APIs** card
- Then click on the **Credentials** link in the left menu
- Click on **OAuth consent screen** button
- Chose **External** and click on **create**
- Fill the **Application name** and save
- Then click on **Create credentials** button
- Chose **OAuth client ID** option
Then fill the informations:
- **Name**: `Strapi Auth`
- **Authorized redirect URIs**: `http://localhost:1337/connect/google/callback`
To access the Client ID and secret:
- Click on **OAuth 2.0 Client IDs** name of the client you just created
### Strapi configuration
- Visit the User Permissions provider settings page <br> [http://localhost:1337/admin/plugins/users-permissions/providers](http://localhost:1337/admin/plugins/users-permissions/providers)
- Click on the **Google** provider
Then fill the informations:
- **Enable**: `ON`
- **Client ID**: 226437944084-o2mojv5i4lfnng9q8kq3jkf5v03avemk.apps.googleusercontent.com
- **Client ID**: aiTbMoiuJQflSBy6uQrfgsni
- **The redirect URL to your front-end app**: `http://localhost:3000/connect/google`
:::
::: tab Twitter
### Setup the server
Use `ngrok` to serve the frontend app.
```
ngrok http 3000
```
### Twitter configuration
- Visit the Apps list page <br> [https://developer.twitter.com/en/apps](https://developer.twitter.com/en/apps)
- Click on **Create an app** button
Then fill the informations:
- **App name**: Strapi Twitter auth
- **Application description**: This is an demo app for Strapi auth
- **Website URL**: `https://65e60559.ngrok.io`
- **Callback URLs**: `https://65e60559.ngrok.io/connect/twitter`
- **Tell us how this app will be used**: - here write a message enough long -
To access the Consumer API keys:
- Click on **Keys and tokens** tab
### Strapi configuration
- Visit the User Permissions provider settings page <br> [http://localhost:1337/admin/plugins/users-permissions/providers](http://localhost:1337/admin/plugins/users-permissions/providers)
- Click on the **Twitter** provider
Then fill the informations:
- **Enable**: `ON`
- **Client ID**: yfN4ycGGmKXiS1njtIYxuN5IH
- **Client ID**: Nag1en8S4VwqurBvlW5OaFyKlzqrXFeyWhph6CZlpGA2V3VR3T
- **The redirect URL to your front-end app**: `https://65e60559.ngrok.io/connect/twitter`
:::
::: tab Discord
### Discord configuration
- Visit the Apps list page on the developer portal <br> [https://discordapp.com/developers/applications/](https://discordapp.com/developers/applications/)
- Click on **New application** button
- Fill the **name** and create
- Click on **OAuth2** in the left menu
- And click on **Add redirect** button
- Fill the **Redirect** input with `http://localhost:1337/connect/discord/callback` URL and save
To access the Consumer API keys:
- Click on **General information** in the left menu
### Strapi configuration
- Visit the User Permissions provider settings page <br> [http://localhost:1337/admin/plugins/users-permissions/providers](http://localhost:1337/admin/plugins/users-permissions/providers)
- Click on the **Discord** provider
Then fill the informations:
- **Enable**: `ON`
- **Client ID**: 665118465148846081
- **Client ID**: iJbr7mkyqyut-J2hGvvSDch_5Dw5U77J
- **The redirect URL to your front-end app**: `http://localhost:3000/connect/discord`
:::
::: tab Twitch
### Twitch configuration
- Visit the Apps list page on the developer console <br> [https://dev.twitch.tv/console/apps](https://dev.twitch.tv/console/apps)
- Click on **Register Your Application** button
Then fill the informations:
- **Name**: Strapi auth
- **OAuth Redirect URLs**: `http://localhost:1337/connect/twitch/callback`
- **Category**: Chose a category
To access the Consumer API keys:
- Click on **Manage** button of your new app
- Then generate a new **Client Secret** with the **New Secret** button
### Strapi configuration
- Visit the User Permissions provider settings page <br> [http://localhost:1337/admin/plugins/users-permissions/providers](http://localhost:1337/admin/plugins/users-permissions/providers)
- Click on the **Twitch** provider
Then fill the informations:
- **Enable**: `ON`
- **Client ID**: amuy279g8wt68qlht3u4gek4oykh5j
- **Client ID**: dapssh10uo97gg2l25qufr8wen3yr6
- **The redirect URL to your front-end app**: `http://localhost:3000/connect/twitch`
:::
::: tab Instagram
### Setup the server
Use `ngrok` to serve the server app.
```
ngrok http 1337
```
### Facebook configuration
- Visit the Developer Apps list page <br> [https://developers.facebook.com/apps/](https://developers.facebook.com/apps/)
- Click on **Add a New App** button
- Fill the **Display Name** in the modal and create the app
- Setup a **Instagram** product
- Click on the **PRODUCTS > Instagram > Basic Display** link in the left menu
- Then click on the **Create new application** button (and valid the modal)
Then fill the informations:
- **Valid OAuth Redirect URIs**: `https://c6a8cc7c.ngrok.io/connect/instagram/callback`
- **Deauthorize**: `https://c6a8cc7c.ngrok.io`
- **Data Deletion Requests**: `https://c6a8cc7c.ngrok.io`
On the **App Review for Instagram Basic Display** click on **Add to submition** for **instagram_graph_user_profile**.
Make sure your Application information are well completed.
### Strapi configuration
- Visit the User Permissions provider settings page <br> [http://localhost:1337/admin/plugins/users-permissions/providers](http://localhost:1337/admin/plugins/users-permissions/providers)
- Click on the **Instagram** provider
Then fill the informations:
- **Enable**: `ON`
- **Client ID**: 563883201184965
- **Client ID**: f5ba10a7dd78c2410ab6b8a35ab28226
- **The redirect URL to your front-end app**: `http://localhost:3000/connect/instagram`
:::
::: tab VK
### VK configuration
- Visit the Apps list page <br> [https://vk.com/apps?act=manage](https://vk.com/apps?act=manage)
- Click on **Create app** button
Then fill the informations:
- **Title**: Strapi auth
- **Platform**: Chose **Website** option
- **Website address**: `http://localhost:1337`
- **Base domain**: `localhost`
Then setup OAuth seetings:
- Click on **Settings** link in the left menu
- Click on **Open API** link to enable this option
Then fill the informations:
- **Authorized redirect UR**: `http://localhost:1337/connect/vk/callback`
### Strapi configuration
- Visit the User Permissions provider settings page <br> [http://localhost:1337/admin/plugins/users-permissions/providers](http://localhost:1337/admin/plugins/users-permissions/providers)
- Click on the **VK** provider
Then fill the informations:
- **Enable**: `ON`
- **Client ID**: 7276416
- **Client ID**: cFBUSghLXGuxqnCyw1N3
- **The redirect URL to your front-end app**: `http://localhost:3000/connect/vk`
:::
::::
Set your providers credentials in the admin interface (Plugin Users & Permissions > Providers).
Then update and enable the provider you want use.
@ -261,11 +559,11 @@ The `user` object is available to successfully authenticated requests.
```js
create: async ctx => {
const { _id } = ctx.state.user;
const { id } = ctx.state.user;
const depositObj = {
...ctx.request.body,
depositor: _id,
depositor: id,
};
const data = await strapi.services.deposit.add(depositObj);
@ -437,7 +735,9 @@ You can update these template in the **Email Templates** tab in the admin panel.
- `URL` is the Strapi backend URL that confirm the code (by default `/auth/email-confirmation`).
## Security configuration
JWT tokens can be verified and trusted because the information is digitally signed. To sign a token a *secret* is required. By default Strapi generates one that is stored in `./your-app/extensions/users-permissions/config/jwt.json`. This is useful during development but for security reasons it is **recommended** to set a custom token via an environment variable `JWT_SECRET` when deploying to production. It is also possible to modify `jwt.json` file to accept `JWT_TOKEN` automatically by doing following ([docs](https://strapi.io/documentation/3.0.0-beta.x/concepts/configurations.html#dynamic-configurations)).
JWT tokens can be verified and trusted because the information is digitally signed. To sign a token a _secret_ is required. By default Strapi generates one that is stored in `./your-app/extensions/users-permissions/config/jwt.json`. This is useful during development but for security reasons it is **recommended** to set a custom token via an environment variable `JWT_SECRET` when deploying to production. It is also possible to modify `jwt.json` file to accept `JWT_TOKEN` automatically by doing following ([docs](https://strapi.io/documentation/3.0.0-beta.x/concepts/configurations.html#dynamic-configurations)).
```
"jwtSecret": "${process.env.JWT_SECRET}"
```

View File

@ -12,6 +12,7 @@
"enzyme-adapter-react-16": "^1.12.1",
"eslint": "^6.3.0",
"eslint-config-prettier": "^6.2.0",
"eslint-plugin-import": "^2.19.1",
"eslint-plugin-react": "^7.14.0",
"eslint-plugin-react-hooks": "^2.0.0",
"eslint-plugin-redux-saga": "^1.1.0",

View File

@ -6,9 +6,8 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
import { Content, Wrapper } from './components';
import Icon from '../../assets/icons/icon_success.svg';
import { Content, Wrapper } from './components';
function DownloadInfo() {
return (

View File

@ -1,14 +1,13 @@
import React from 'react';
import { shallow } from 'enzyme';
import { OverlayBlocker } from 'strapi-helper-plugin';
import {
disableGlobalOverlayBlocker,
enableGlobalOverlayBlocker,
updatePlugin,
} from '../../App/actions';
import { OverlayBlocker } from 'strapi-helper-plugin';
import { Admin, mapDispatchToProps } from '../index';
import { setAppError } from '../actions';

View File

@ -19,6 +19,7 @@ import { connect } from 'react-redux';
import { bindActionCreators, compose } from 'redux';
import { LoadingIndicatorPage, request } from 'strapi-helper-plugin';
import GlobalStyle from '../../components/GlobalStyle';
import Admin from '../Admin';
import AuthPage from '../AuthPage';
import NotFoundPage from '../NotFoundPage';
@ -28,8 +29,6 @@ import Theme from '../Theme';
import { Content, Wrapper } from './components';
import GlobalStyle from '../../components/GlobalStyle';
import { getDataSucceeded } from './actions';
function App(props) {

View File

@ -327,7 +327,7 @@ module.exports = {
email: 'no-reply@strapi.io',
},
response_email: '',
object: '­Reset password',
object: 'Reset password',
message: `<p>We heard that you lost your password. Sorry about that!</p>
<p>But dont worry! You can use the following link to reset your password:</p>

View File

@ -0,0 +1,8 @@
const DATE_FORMATS = {
date: 'dddd, MMMM Do YYYY',
datetime: 'dddd, MMMM Do YYYY HH:mm',
time: 'HH:mm A',
timestamp: 'dddd, MMMM Do YYYY',
};
export default DATE_FORMATS;

View File

@ -5,11 +5,12 @@ import { get, isEmpty, isNull, isObject, toLower, toString } from 'lodash';
import moment from 'moment';
import { IcoContainer, useGlobalContext } from 'strapi-helper-plugin';
import useListView from '../../hooks/useListView';
import CustomInputCheckbox from '../CustomInputCheckbox';
import MediaPreviewList from '../MediaPreviewList';
import { ActionContainer, Truncate, Truncated } from './styledComponents';
import DATE_FORMATS from './DATE_FORMATS';
const dateToUtcTime = date => moment.parseZone(date).utc();
const getDisplayedValue = (type, value, name) => {
switch (toLower(type)) {
@ -28,7 +29,6 @@ const getDisplayedValue = (type, value, name) => {
case 'boolean':
return value !== null ? toString(value) : '-';
case 'date':
case 'time':
case 'datetime':
case 'timestamp': {
if (value == null) {
@ -40,10 +40,7 @@ const getDisplayedValue = (type, value, name) => {
? JSON.stringify(value)
: value;
return moment
.parseZone(date)
.utc()
.format('dddd, MMMM Do YYYY');
return dateToUtcTime(date).format(DATE_FORMATS[type]);
}
case 'password':
return '••••••••';
@ -51,6 +48,16 @@ const getDisplayedValue = (type, value, name) => {
case 'file':
case 'files':
return value;
case 'time': {
const [hour, minute, second] = value.split(':');
const timeObj = {
hour,
minute,
second,
};
const date = moment().set(timeObj);
return date.format(DATE_FORMATS.time);
}
default:
return '-';
}

View File

@ -1,10 +1,10 @@
import React, { forwardRef, useState } from 'react';
import { get } from 'lodash';
import PropTypes from 'prop-types';
import Carret from './Carret';
import DraggedField from '../DraggedField';
import DynamicZoneWrapper from './DynamicZoneWrapper';
import PreviewCarret from '../PreviewCarret';
import Carret from './Carret';
import DynamicZoneWrapper from './DynamicZoneWrapper';
import Wrapper from './Wrapper';
import DynamicComponent from './DynamicComponent';

View File

@ -11,8 +11,8 @@ import useListView from '../../hooks/useListView';
import Container from '../Container';
import getFilterType from '../FilterPickerOption/utils';
import { Flex, Span, Wrapper } from './components';
import FilterPickerOption from '../FilterPickerOption';
import { Flex, Span, Wrapper } from './components';
import init from './init';
import reducer, { initialState } from './reducer';

View File

@ -18,7 +18,7 @@ function reducer(state, action) {
return state
.updateIn(['modifiedData', ...action.keys], () => {
if (action.value._isAMomentObject === true) {
if (action.value && action.value._isAMomentObject === true) {
return moment(action.value, 'YYYY-MM-DD HH:mm:ss').format();
}
return action.value;

View File

@ -6,29 +6,33 @@
import React, { memo } from 'react';
import PropTypes from 'prop-types';
import { InputWrapperDate } from './components';
import { DateTime } from '@buffetjs/custom';
import {
InputDate,
InputNumber,
InputSelect,
DatePicker,
InputText,
} from 'strapi-helper-plugin';
InputNumber,
Select,
TimePicker,
} from '@buffetjs/core';
import { InputWrapperDate } from './components';
const getInputType = attrType => {
switch (attrType) {
case 'boolean':
return InputSelect;
return Select;
case 'date':
case 'datetime':
case 'timestamp':
case 'timestampUpdate':
return InputDate;
return DatePicker;
case 'datetime':
return DateTime;
case 'integer':
case 'biginteger':
case 'decimal':
case 'float':
return InputNumber;
case 'time':
return TimePicker;
default:
return InputText;
}
@ -36,10 +40,18 @@ const getInputType = attrType => {
function Input({ type, ...rest }) {
const Component = getInputType(type);
const style = { width: '210px', paddingTop: '4px' };
let style = type !== 'time' ? { width: '210px', paddingTop: '4px' } : {};
if (['integer', 'biginteger', 'float', 'decimal'].includes(type)) {
style = { marginRight: '20px' };
}
const styles =
type === 'boolean' ? { minWidth: '100px', maxWidth: '200px' } : style;
const wrapperStyle = type == 'boolean' ? { marginRight: '20px' } : {};
const wrapperStyle =
type == 'boolean' ||
['date', 'timestamp', 'time', 'datetime'].includes(type)
? { marginRight: '20px' }
: { marginRight: '10px' };
return (
<InputWrapperDate type={type || 'text'} style={wrapperStyle}>

View File

@ -0,0 +1,18 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
import PropTypes from 'prop-types';
const Option = ({ id, value }) => {
return (
<FormattedMessage id={id}>
{msg => <option value={value}>{msg}</option>}
</FormattedMessage>
);
};
Option.propTypes = {
id: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
};
export default Option;

View File

@ -53,39 +53,27 @@ const Button = styled.button`
const InputWrapperDate = styled.div`
margin-right: 10px;
span {
left: 5px;
}
.rc-input-number-handler-wrap {
right: -5px !important;
}
.rc-input-number-input-wrap {
max-width: 210px;
overflow: visible;
}
> div {
width: 210px;
}
${({ type }) => {
if (
type.includes('date') ||
type === 'timestampUpdate' ||
type === 'timestamp'
) {
return css`
position: relative;
&:before {
content: '\f073';
position: absolute;
left: 6px;
top: 1px;
width: 32px;
height: 32px;
border-radius: 3px 0px 0px 3px;
background: #fafafb;
color: #b3b5b9;
text-align: center;
font-family: 'FontAwesome';
font-size: 1.4rem;
line-height: 32px;
z-index: 999;
-webkit-font-smoothing: none;
}
input {
width: 100%;
padding-left: 42px;
box-shadow: 0px 1px 1px rgba(104, 118, 142, 0.05);
&:focus {
outline: none;
}
}
if (type === 'datetime') {
return `
> div {
width: 300px;
}
`;
}
}}
@ -103,5 +91,4 @@ const Input = styled.input`
font-family: 'Lato' !important;
box-shadow: 0px 1px 1px rgba(104, 118, 142, 0.05);
`;
export { Button, InputWrapper, Wrapper, InputWrapperDate, Input };

View File

@ -1,10 +1,10 @@
import React, { memo } from 'react';
import { get, isEmpty } from 'lodash';
import PropTypes from 'prop-types';
import { InputSelect } from 'strapi-helper-plugin';
import { Select } from '@buffetjs/core';
import { Button, InputWrapper, Wrapper } from './components';
import Input from './Input';
import Option from './Option';
import getFilters from './utils';
const styles = {
@ -46,7 +46,7 @@ function FilterPickerOption({
isRemoveButton
onClick={() => onRemoveFilter(index)}
/>
<InputSelect
<Select
onChange={e => {
// Change the attribute
onChange(e);
@ -55,13 +55,15 @@ function FilterPickerOption({
}}
name={`${index}.name`}
value={get(modifiedData, [index, 'name'], '')}
selectOptions={allowedAttributes.map(attr => attr.name)}
options={allowedAttributes.map(attr => attr.name)}
style={styles.select}
/>
<InputSelect
<Select
onChange={onChange}
name={`${index}.filter`}
selectOptions={filtersOptions}
options={filtersOptions.map(option => (
<Option {...option} key={option.value} />
))}
style={styles.selectMiddle}
value={get(modifiedData, [index, 'filter'], '')}
/>
@ -69,7 +71,7 @@ function FilterPickerOption({
type={type}
name={`${index}.value`}
value={get(modifiedData, [index, 'value'], '')}
selectOptions={['true', 'false']}
options={['true', 'false']}
onChange={onChange}
/>
{showAddButton && <Button type="button" onClick={onClickAddFilter} />}

View File

@ -4,8 +4,8 @@ import PropTypes from 'prop-types';
import { Grab } from '@buffetjs/icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import pluginId from '../../pluginId';
import BannerWrapper from './BannerWrapper';
import PreviewCarret from '../PreviewCarret';
import BannerWrapper from './BannerWrapper';
import CarretTop from './CarretTop';
const Banner = forwardRef(

View File

@ -27,9 +27,9 @@ import PopupForm from '../../components/PopupForm';
import SettingsViewWrapper from '../../components/SettingsViewWrapper';
import SortableList from '../../components/SortableList';
import { unformatLayout } from '../../utils/layout';
import getInjectedComponents from '../../utils/getComponents';
import LayoutDndProvider from '../LayoutDndProvider';
import getInputProps from './utils/getInputProps';
import getInjectedComponents from '../../utils/getComponents';
import reducer, { initialState } from './reducer';

View File

@ -17,12 +17,12 @@ import FormWrapper from '../../components/FormWrapper';
import FieldComponent from '../../components/FieldComponent';
import Inputs from '../../components/Inputs';
import SelectWrapper from '../../components/SelectWrapper';
import getInjectedComponents from '../../utils/getComponents';
import EditViewDataManagerProvider from '../EditViewDataManagerProvider';
import EditViewProvider from '../EditViewProvider';
import Header from './Header';
import createAttributesLayout from './utils/createAttributesLayout';
import { LinkWrapper, SubWrapper } from './components';
import getInjectedComponents from '../../utils/getComponents';
import init from './init';
import reducer, { initialState } from './reducer';

View File

@ -74,4 +74,4 @@ EditViewButton.propTypes = {
push: PropTypes.func.isRequired,
};
export default EditViewButton;
export default EditViewButton;

View File

@ -38,4 +38,4 @@ EditViewLink.propTypes = {
getModelName: PropTypes.func.isRequired,
};
export default EditViewLink;
export default EditViewLink;

View File

@ -12,9 +12,9 @@ import { Plus } from '@buffetjs/icons';
import useDataManager from '../../hooks/useDataManager';
import getTrad from '../../utils/getTrad';
import ComponentList from '../ComponentList';
import ComponentButton from './ComponentButton';
import ComponentCard from '../ComponentCard';
import Td from '../Td';
import ComponentButton from './ComponentButton';
function DynamicZoneList({
customRowComponent,

View File

@ -4,11 +4,11 @@ import { HeaderModalTitle } from 'strapi-helper-plugin';
import { get } from 'lodash';
import { FormattedMessage } from 'react-intl';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import UpperFirst from '../UpperFirst';
import ComponentIcon from './ComponentIcon';
import ComponentInfos from './ComponentInfos';
import Icon from './Icon';
import IconWrapper from './IconWrapper';
import UpperFirst from '../UpperFirst';
import DropdownInfos from './DropdownInfos';
const ModalHeader = ({ headerId, headers }) => {

View File

@ -4,6 +4,7 @@ import { SelectWrapper, SelectNav } from 'strapi-helper-plugin';
import { ErrorMessage } from '@buffetjs/styles';
import CreatableSelect from '../CreatableSelect';
import ComponentSelect from '../ComponentSelect';
/* eslint-disable no-nested-ternary */
const WrapperSelect = ({ error, label, name, type, ...rest }) => {
const styles = {

View File

@ -9,13 +9,12 @@ import { Switch, Route } from 'react-router-dom';
import { LoadingIndicatorPage } from 'strapi-helper-plugin';
import pluginId from '../../pluginId';
import DataManagerProvider from '../DataManagerProvider';
import RecursivePath from '../RecursivePath';
import icons from './utils/icons.json';
import Wrapper from './Wrapper';
const ListView = lazy(() => import('../ListView'));
import RecursivePath from '../RecursivePath';
const App = () => {
return (
<Wrapper>

View File

@ -14,6 +14,8 @@ import {
Redirect,
} from 'react-router-dom';
import DataManagerContext from '../../contexts/DataManagerContext';
import getTrad from '../../utils/getTrad';
import makeUnique from '../../utils/makeUnique';
import pluginId from '../../pluginId';
import FormModal from '../FormModal';
import init from './init';
@ -26,13 +28,11 @@ import retrieveSpecificInfoFromComponents from './utils/retrieveSpecificInfoFrom
import retrieveComponentsFromSchema from './utils/retrieveComponentsFromSchema';
import retrieveNestedComponents from './utils/retrieveNestedComponents';
import { retrieveComponentsThatHaveComponents } from './utils/retrieveComponentsThatHaveComponents';
import makeUnique from '../../utils/makeUnique';
import {
getComponentsToPost,
formatMainDataType,
getCreatedAndModifiedComponents,
} from './utils/cleanData';
import getTrad from '../../utils/getTrad';
const DataManagerProvider = ({ allIcons, children }) => {
const [reducerState, dispatch] = useReducer(reducer, initialState, init);

View File

@ -1,7 +1,7 @@
import { fromJS, OrderedMap } from 'immutable';
import { get, has } from 'lodash';
import retrieveComponentsFromSchema from './utils/retrieveComponentsFromSchema';
import makeUnique from '../../utils/makeUnique';
import retrieveComponentsFromSchema from './utils/retrieveComponentsFromSchema';
const initialState = fromJS({
components: {},

View File

@ -18,4 +18,4 @@ const RESERVED_NAMES = [
...JS_BUILT_IN_OBJECTS,
];
export default RESERVED_NAMES;
export default RESERVED_NAMES;

View File

@ -7,11 +7,11 @@
import React from 'react';
import { Switch, Route } from 'react-router-dom';
import { NotFound } from 'strapi-helper-plugin';
// Utils
import pluginId from '../../pluginId';
// Containers
import HomePage from '../HomePage';
import { NotFound } from 'strapi-helper-plugin';
function App() {
return (

View File

@ -1931,7 +1931,7 @@ module.exports = {
const overrideDocumentationPath = isPlugin
? path.resolve(
strapi.config.appPath,
'plugins',
'extensions',
current,
'documentation',
version,

View File

@ -7,13 +7,11 @@
import React from 'react';
import { Switch, Route } from 'react-router-dom';
import { NotFound } from 'strapi-helper-plugin';
import pluginId from '../../pluginId';
// Containers
import ConfigPage from '../ConfigPage';
import HomePage from '../HomePage';
import { NotFound } from 'strapi-helper-plugin';
function App() {
return (

View File

@ -8,11 +8,9 @@ import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { map, omitBy, size } from 'lodash';
import { Button, LoadingBar, LoadingIndicator } from 'strapi-helper-plugin';
import { Flex, ListWrapper, Title, Wrapper } from './Components';
import ListRow from '../ListRow';
import { Flex, ListWrapper, Title, Wrapper } from './Components';
const generateListTitle = (data, settingType) => {
switch (settingType) {

View File

@ -10,11 +10,10 @@ import { FormattedMessage } from 'react-intl';
import { capitalize, get, includes } from 'lodash';
import { IcoContainer, PopUpWarning } from 'strapi-helper-plugin';
import en from '../../translations/en.json';
import { HomePageContext } from '../../contexts/HomePage';
import { Container, Flex, Row, Wrapper } from './Components';
import en from '../../translations/en.json';
class ListRow extends React.Component {
// eslint-disable-line react/prefer-stateless-function
state = { showModalDelete: false };

View File

@ -1,10 +1,10 @@
import React from 'react';
import pluginPkg from '../../package.json';
import layout from '../../config/layout';
import pluginId from './pluginId';
import App from './containers/App';
import Initializer from './containers/Initializer';
import lifecycles from './lifecycles';
import layout from '../../config/layout';
import trads from './translations';
const pluginDescription = pluginPkg.strapi.description || pluginPkg.description;

View File

@ -126,7 +126,7 @@ module.exports = async () => {
email: 'no-reply@strapi.io',
},
response_email: '',
object: '­Reset password',
object: 'Reset password',
message: `<p>We heard that you lost your password. Sorry about that!</p>
<p>But dont worry! You can use the following link to reset your password:</p>

View File

@ -112,7 +112,7 @@ module.exports = {
formatError({
id: 'Auth.form.error.password.local',
message:
'This user never set a local password, please login thanks to the provider used during account creation.',
'This user never set a local password, please login with the provider used during account creation.',
})
);
}
@ -150,7 +150,7 @@ module.exports = {
);
}
// Connect the user thanks to the third-party provider.
// Connect the user with the third-party provider.
let user, error;
try {
[user, error] = await strapi.plugins[
@ -296,7 +296,7 @@ module.exports = {
name: 'users-permissions',
});
// Find the user user thanks to his email.
// Find the user by email.
const user = await strapi
.query('user', 'users-permissions')
.findOne({ email });

24
scripts/publish.sh Executable file
View File

@ -0,0 +1,24 @@
# Force start from root folder
cd "$(dirname "$0")/.."
set -e
version=""
echo "Please enter the version you want to publish"
read version
# publish packages
./node_modules/.bin/lerna publish --no-push --dist-tag beta --exact "$version"
# push master branch
git push origin master
# push tag
git push origin v"$version"
# set latest dist-tag on npm
lerna exec --stream --no-bail --no-private -- npm dist-tag add '${LERNA_PACKAGE_NAME}'@"$version" latest
# run changelog cli
npx @sclt/program-changelog

View File

@ -5094,6 +5094,11 @@ constants-browserify@^1.0.0:
resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=
contains-path@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a"
integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=
content-disposition@0.5.3, content-disposition@~0.5.2:
version "0.5.3"
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
@ -6169,6 +6174,14 @@ dockerfile-ast@0.0.16:
dependencies:
vscode-languageserver-types "^3.5.0"
doctrine@1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=
dependencies:
esutils "^2.0.2"
isarray "^1.0.0"
doctrine@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
@ -6679,6 +6692,40 @@ eslint-config-prettier@^6.2.0:
dependencies:
get-stdin "^6.0.0"
eslint-import-resolver-node@^0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a"
integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==
dependencies:
debug "^2.6.9"
resolve "^1.5.0"
eslint-module-utils@^2.4.1:
version "2.5.0"
resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.5.0.tgz#cdf0b40d623032274ccd2abd7e64c4e524d6e19c"
integrity sha512-kCo8pZaNz2dsAW7nCUjuVoI11EBXXpIzfNxmaoLhXoRDOnqXLC4iSGVRdZPhOitfbdEfMEfKOiENaK6wDPZEGw==
dependencies:
debug "^2.6.9"
pkg-dir "^2.0.0"
eslint-plugin-import@^2.19.1:
version "2.19.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.19.1.tgz#5654e10b7839d064dd0d46cd1b88ec2133a11448"
integrity sha512-x68131aKoCZlCae7rDXKSAQmbT5DQuManyXo2sK6fJJ0aK5CWAkv6A6HJZGgqC8IhjQxYPgo6/IY4Oz8AFsbBw==
dependencies:
array-includes "^3.0.3"
array.prototype.flat "^1.2.1"
contains-path "^0.1.0"
debug "^2.6.9"
doctrine "1.5.0"
eslint-import-resolver-node "^0.3.2"
eslint-module-utils "^2.4.1"
has "^1.0.3"
minimatch "^3.0.4"
object.values "^1.1.0"
read-pkg-up "^2.0.0"
resolve "^1.12.0"
eslint-plugin-react-hooks@^2.0.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-2.1.2.tgz#1358d2acb2c5e02b7e90c37e611ac258a488e3a7"
@ -10742,6 +10789,16 @@ load-json-file@^1.0.0:
pinkie-promise "^2.0.0"
strip-bom "^2.0.0"
load-json-file@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8"
integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=
dependencies:
graceful-fs "^4.1.2"
parse-json "^2.2.0"
pify "^2.0.0"
strip-bom "^3.0.0"
load-json-file@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
@ -12921,6 +12978,13 @@ path-type@^1.0.0:
pify "^2.0.0"
pinkie-promise "^2.0.0"
path-type@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73"
integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=
dependencies:
pify "^2.0.0"
path-type@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
@ -13068,6 +13132,13 @@ pirates@^4.0.1:
dependencies:
node-modules-regexp "^1.0.0"
pkg-dir@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=
dependencies:
find-up "^2.1.0"
pkg-dir@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3"
@ -14382,6 +14453,14 @@ read-pkg-up@^1.0.1:
find-up "^1.0.0"
read-pkg "^1.0.0"
read-pkg-up@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be"
integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=
dependencies:
find-up "^2.0.0"
read-pkg "^2.0.0"
read-pkg-up@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07"
@ -14407,6 +14486,15 @@ read-pkg@^1.0.0:
normalize-package-data "^2.3.2"
path-type "^1.0.0"
read-pkg@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8"
integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=
dependencies:
load-json-file "^2.0.0"
normalize-package-data "^2.3.2"
path-type "^2.0.0"
read-pkg@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"