Created React select one

This commit is contained in:
soupette 2019-07-16 18:53:41 +02:00
parent cf6e3e0536
commit 1157f6ae75
23 changed files with 884 additions and 519 deletions

View File

@ -47,7 +47,7 @@
},
"tags": {
"collection": "tag",
"via": "articles"
"via": "article"
},
"json": {
"type": "json"

View File

@ -0,0 +1,52 @@
{
"routes": [
{
"method": "GET",
"path": "/rocketships",
"handler": "Rocketship.find",
"config": {
"policies": []
}
},
{
"method": "GET",
"path": "/rocketships/count",
"handler": "Rocketship.count",
"config": {
"policies": []
}
},
{
"method": "GET",
"path": "/rocketships/:id",
"handler": "Rocketship.findOne",
"config": {
"policies": []
}
},
{
"method": "POST",
"path": "/rocketships",
"handler": "Rocketship.create",
"config": {
"policies": []
}
},
{
"method": "PUT",
"path": "/rocketships/:id",
"handler": "Rocketship.update",
"config": {
"policies": []
}
},
{
"method": "DELETE",
"path": "/rocketships/:id",
"handler": "Rocketship.delete",
"config": {
"policies": []
}
}
]
}

View File

@ -0,0 +1,8 @@
'use strict';
/**
* Read the documentation (https://strapi.io/documentation/3.0.0-beta.x/guides/controllers.html#core-controllers)
* to customize this controller
*/
module.exports = {};

View File

@ -0,0 +1,55 @@
'use strict';
/**
* Lifecycle callbacks for the `Rocketship` model.
*/
module.exports = {
// Before saving a value.
// Fired before an `insert` or `update` query.
// beforeSave: async (model, attrs, options) => {},
// After saving a value.
// Fired after an `insert` or `update` query.
// afterSave: async (model, response, options) => {},
// Before fetching a value.
// Fired before a `fetch` operation.
// beforeFetch: async (model, columns, options) => {},
// After fetching a value.
// Fired after a `fetch` operation.
// afterFetch: async (model, response, options) => {},
// Before fetching all values.
// Fired before a `fetchAll` operation.
// beforeFetchAll: async (model, columns, options) => {},
// After fetching all values.
// Fired after a `fetchAll` operation.
// afterFetchAll: async (model, response, options) => {},
// Before creating a value.
// Fired before an `insert` query.
// beforeCreate: async (model, attrs, options) => {},
// After creating a value.
// Fired after an `insert` query.
// afterCreate: async (model, attrs, options) => {},
// Before updating a value.
// Fired before an `update` query.
// beforeUpdate: async (model, attrs, options) => {},
// After updating a value.
// Fired after an `update` query.
// afterUpdate: async (model, attrs, options) => {},
// Before destroying a value.
// Fired before a `delete` query.
// beforeDestroy: async (model, attrs, options) => {},
// After destroying a value.
// Fired after a `delete` query.
// afterDestroy: async (model, attrs, options) => {}
};

View File

@ -0,0 +1,22 @@
{
"connection": "default",
"collectionName": "rocketships",
"info": {
"name": "rocketship",
"description": ""
},
"options": {
"increments": true,
"timestamps": true,
"comment": ""
},
"attributes": {
"name": {
"type": "string"
},
"rocketshipmaker": {
"model": "rocketshipmaker",
"via": "rocketships"
}
}
}

View File

@ -0,0 +1,8 @@
'use strict';
/**
* Read the documentation (https://strapi.io/documentation/3.0.0-beta.x/guides/services.html#core-services)
* to customize this service
*/
module.exports = {};

View File

@ -0,0 +1,52 @@
{
"routes": [
{
"method": "GET",
"path": "/rocketshipmakers",
"handler": "Rocketshipmaker.find",
"config": {
"policies": []
}
},
{
"method": "GET",
"path": "/rocketshipmakers/count",
"handler": "Rocketshipmaker.count",
"config": {
"policies": []
}
},
{
"method": "GET",
"path": "/rocketshipmakers/:id",
"handler": "Rocketshipmaker.findOne",
"config": {
"policies": []
}
},
{
"method": "POST",
"path": "/rocketshipmakers",
"handler": "Rocketshipmaker.create",
"config": {
"policies": []
}
},
{
"method": "PUT",
"path": "/rocketshipmakers/:id",
"handler": "Rocketshipmaker.update",
"config": {
"policies": []
}
},
{
"method": "DELETE",
"path": "/rocketshipmakers/:id",
"handler": "Rocketshipmaker.delete",
"config": {
"policies": []
}
}
]
}

View File

@ -0,0 +1,8 @@
'use strict';
/**
* Read the documentation (https://strapi.io/documentation/3.0.0-beta.x/guides/controllers.html#core-controllers)
* to customize this controller
*/
module.exports = {};

View File

@ -0,0 +1,55 @@
'use strict';
/**
* Lifecycle callbacks for the `Rocketshipmaker` model.
*/
module.exports = {
// Before saving a value.
// Fired before an `insert` or `update` query.
// beforeSave: async (model, attrs, options) => {},
// After saving a value.
// Fired after an `insert` or `update` query.
// afterSave: async (model, response, options) => {},
// Before fetching a value.
// Fired before a `fetch` operation.
// beforeFetch: async (model, columns, options) => {},
// After fetching a value.
// Fired after a `fetch` operation.
// afterFetch: async (model, response, options) => {},
// Before fetching all values.
// Fired before a `fetchAll` operation.
// beforeFetchAll: async (model, columns, options) => {},
// After fetching all values.
// Fired after a `fetchAll` operation.
// afterFetchAll: async (model, response, options) => {},
// Before creating a value.
// Fired before an `insert` query.
// beforeCreate: async (model, attrs, options) => {},
// After creating a value.
// Fired after an `insert` query.
// afterCreate: async (model, attrs, options) => {},
// Before updating a value.
// Fired before an `update` query.
// beforeUpdate: async (model, attrs, options) => {},
// After updating a value.
// Fired after an `update` query.
// afterUpdate: async (model, attrs, options) => {},
// Before destroying a value.
// Fired before a `delete` query.
// beforeDestroy: async (model, attrs, options) => {},
// After destroying a value.
// Fired after a `delete` query.
// afterDestroy: async (model, attrs, options) => {}
};

View File

@ -0,0 +1,22 @@
{
"connection": "default",
"collectionName": "rocketshipmakers",
"info": {
"name": "rocketshipmaker",
"description": ""
},
"options": {
"increments": true,
"timestamps": true,
"comment": ""
},
"attributes": {
"name": {
"type": "string"
},
"rocketships": {
"collection": "rocketship",
"via": "rocketshipmaker"
}
}
}

View File

@ -0,0 +1,8 @@
'use strict';
/**
* Read the documentation (https://strapi.io/documentation/3.0.0-beta.x/guides/services.html#core-services)
* to customize this service
*/
module.exports = {};

View File

@ -14,9 +14,8 @@
"name": {
"type": "string"
},
"articles": {
"collection": "article",
"dominant": true,
"article": {
"model": "article",
"via": "tags"
}
}

View File

@ -43,6 +43,22 @@ type createRecipePayload {
recipe: Recipe
}
input createRocketshipInput {
data: RocketshipInput
}
input createRocketshipmakerInput {
data: RocketshipmakerInput
}
type createRocketshipmakerPayload {
rocketshipmaker: Rocketshipmaker
}
type createRocketshipPayload {
rocketship: Rocketship
}
input createRoleInput {
data: RoleInput
}
@ -88,6 +104,22 @@ type deleteRecipePayload {
recipe: Recipe
}
input deleteRocketshipInput {
where: InputID
}
input deleteRocketshipmakerInput {
where: InputID
}
type deleteRocketshipmakerPayload {
rocketshipmaker: Rocketshipmaker
}
type deleteRocketshipPayload {
rocketship: Rocketship
}
input deleteRoleInput {
where: InputID
}
@ -142,6 +174,16 @@ input editRecipeInput {
title: String
}
input editRocketshipInput {
name: String
rocketshipmaker: ID
}
input editRocketshipmakerInput {
name: String
rocketships: [ID]
}
input editRoleInput {
name: String
description: String
@ -152,7 +194,7 @@ input editRoleInput {
input editTagInput {
name: String
articles: [ID]
article: ID
}
input editTestInput {
@ -197,7 +239,7 @@ scalar JSON
"""The `Long` scalar type represents 52-bit integers"""
scalar Long
union Morph = UsersPermissionsMe | UsersPermissionsMeRole | Article | createArticlePayload | updateArticlePayload | deleteArticlePayload | Recipe | createRecipePayload | updateRecipePayload | deleteRecipePayload | Tag | createTagPayload | updateTagPayload | deleteTagPayload | UploadFile | UsersPermissionsPermission | UsersPermissionsRole | createRolePayload | updateRolePayload | deleteRolePayload | UsersPermissionsUser | createUserPayload | updateUserPayload | deleteUserPayload | MypluginTest
union Morph = UsersPermissionsMe | UsersPermissionsMeRole | Article | createArticlePayload | updateArticlePayload | deleteArticlePayload | Recipe | createRecipePayload | updateRecipePayload | deleteRecipePayload | Rocketship | createRocketshipPayload | updateRocketshipPayload | deleteRocketshipPayload | Rocketshipmaker | createRocketshipmakerPayload | updateRocketshipmakerPayload | deleteRocketshipmakerPayload | Tag | createTagPayload | updateTagPayload | deleteTagPayload | UploadFile | UsersPermissionsPermission | UsersPermissionsRole | createRolePayload | updateRolePayload | deleteRolePayload | UsersPermissionsUser | createUserPayload | updateUserPayload | deleteUserPayload | MypluginTest
type Mutation {
createArticle(input: createArticleInput): createArticlePayload
@ -206,6 +248,12 @@ type Mutation {
createRecipe(input: createRecipeInput): createRecipePayload
updateRecipe(input: updateRecipeInput): updateRecipePayload
deleteRecipe(input: deleteRecipeInput): deleteRecipePayload
createRocketship(input: createRocketshipInput): createRocketshipPayload
updateRocketship(input: updateRocketshipInput): updateRocketshipPayload
deleteRocketship(input: deleteRocketshipInput): deleteRocketshipPayload
createRocketshipmaker(input: createRocketshipmakerInput): createRocketshipmakerPayload
updateRocketshipmaker(input: updateRocketshipmakerInput): updateRocketshipmakerPayload
deleteRocketshipmaker(input: deleteRocketshipmakerInput): deleteRocketshipmakerPayload
createTag(input: createTagInput): createTagPayload
updateTag(input: updateTagInput): updateTagPayload
deleteTag(input: deleteTagInput): deleteTagPayload
@ -240,6 +288,10 @@ type Query {
articles(sort: String, limit: Int, start: Int, where: JSON): [Article]
recipe(id: ID!): Recipe
recipes(sort: String, limit: Int, start: Int, where: JSON): [Recipe]
rocketship(id: ID!): Rocketship
rocketships(sort: String, limit: Int, start: Int, where: JSON): [Rocketship]
rocketshipmaker(id: ID!): Rocketshipmaker
rocketshipmakers(sort: String, limit: Int, start: Int, where: JSON): [Rocketshipmaker]
tag(id: ID!): Tag
tags(sort: String, limit: Int, start: Int, where: JSON): [Tag]
files(sort: String, limit: Int, start: Int, where: JSON): [UploadFile]
@ -268,6 +320,32 @@ input RecipeInput {
title: String
}
type Rocketship {
id: ID!
created_at: DateTime!
updated_at: DateTime!
name: String
rocketshipmaker: Rocketshipmaker
}
input RocketshipInput {
name: String
rocketshipmaker: ID
}
type Rocketshipmaker {
id: ID!
created_at: DateTime!
updated_at: DateTime!
name: String
rocketships(sort: String, limit: Int, start: Int, where: JSON): [Rocketship]
}
input RocketshipmakerInput {
name: String
rocketships: [ID]
}
input RoleInput {
name: String!
description: String
@ -281,12 +359,12 @@ type Tag {
created_at: DateTime!
updated_at: DateTime!
name: String
articles(sort: String, limit: Int, start: Int, where: JSON): [Article]
article: Article
}
input TagInput {
name: String
articles: [ID]
article: ID
}
input TestInput {
@ -311,6 +389,24 @@ type updateRecipePayload {
recipe: Recipe
}
input updateRocketshipInput {
where: InputID
data: editRocketshipInput
}
input updateRocketshipmakerInput {
where: InputID
data: editRocketshipmakerInput
}
type updateRocketshipmakerPayload {
rocketshipmaker: Rocketshipmaker
}
type updateRocketshipPayload {
rocketship: Rocketship
}
input updateRoleInput {
where: InputID
data: editRoleInput

View File

@ -11,7 +11,7 @@ import 'sanitize.css/sanitize.css';
// Third party css library needed
// Currently unable to bundle them
import 'react-select/dist/react-select.css';
// import 'react-select/dist/react-select.css';
import 'react-datetime/css/react-datetime.css';
import './styles/main.scss';
@ -90,7 +90,7 @@ Object.keys(plugins).forEach(plugin => {
// TODO
const remoteURL = (() => {
// Relative URL (ex: /dashboard)
// Relative URL (ex: /dashboard)
if (REMOTE_URL[0] === '/') {
return (window.location.origin + REMOTE_URL).replace(/\/$/, '');
}

View File

@ -63,7 +63,6 @@
"react-redux": "7.0.2",
"react-router": "^5.0.0",
"react-router-dom": "^5.0.0",
"react-select": "^3.0.4",
"react-transition-group": "^2.9.0",
"reactstrap": "^5.0.0",
"redux": "^4.0.1",

View File

@ -0,0 +1,51 @@
import styled from 'styled-components';
const Wrapper = styled.div`
position: relative;
label {
font-size: 1.3rem;
font-weight: 500;
margin-top: 3px;
}
nav + div {
height: 34px;
margin: 3px 0 26px;
> div {
box-shadow: none !important;
border-color: #e3e9f3 !important;
> span:first-of-type {
> div:first-of-type {
color: #9ea7b8;
}
}
> span:last-of-type {
span {
border-color: #b3b5b9 transparent transparent;
}
}
}
}
`;
const Nav = styled.nav`
display: flex;
justify-content: space-between;
a {
color: #007eff !important;
font-size: 1.3rem;
padding-top: 3px;
&:hover {
text-decoration: underline !important;
cursor: pointer;
}
}
`;
export { Nav, Wrapper };

View File

@ -1,228 +1,136 @@
/**
*
* SelectOne
*
*/
import React from 'react';
import Select from 'react-select';
import { FormattedMessage } from 'react-intl';
import React, { useState, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router-dom';
import { get, isEmpty, isNull } from 'lodash';
import { request } from 'strapi-helper-plugin';
import Select from 'react-select';
import {
cloneDeep,
map,
includes,
isArray,
isNull,
isUndefined,
isFunction,
get,
findIndex,
} from 'lodash';
import pluginId from '../../pluginId';
import { request, templateObject } from 'strapi-helper-plugin';
import { Nav, Wrapper } from './components';
import styles from './styles.scss';
function SelectOne({
description,
label,
mainField,
name,
onChange,
pathname,
search,
targetModel,
plugin,
value,
}) {
const [state, setState] = useState({
_q: '',
_limit: 8,
_start: 0,
source: isEmpty(plugin) ? 'content-manager' : plugin,
});
const [options, setOptions] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const ref = useRef();
class SelectOne extends React.Component {
// eslint-disable-line react/prefer-stateless-function
constructor(props) {
super(props);
ref.current = async (uid, params = state) => {
try {
const requestUrl = `/${pluginId}/explorer/${uid}`;
this.state = {
isLoading: true,
options: [],
toSkip: 0,
};
}
if (isEmpty(params._q)) {
delete params._q;
}
componentDidMount() {
this.getOptions('');
}
componentDidUpdate(prevProps, prevState) {
if (prevState.toSkip !== this.state.toSkip) {
this.getOptions('');
}
}
getOptions = query => {
const params = {
_limit: 20,
_start: this.state.toSkip,
source: this.props.relation.plugin || 'content-manager',
};
// Set `query` parameter if necessary
if (query) {
delete params._limit;
delete params._start;
params[`${this.props.relation.displayedAttribute}_contains`] = query;
}
// Request URL
const requestUrlSuffix =
query && get(this.props.record, [this.props.relation.alias])
? get(this.props.record, [this.props.relation.alias])
: '';
const requestUrl = `/content-manager/explorer/${this.props.relation.model ||
this.props.relation.collection}/${requestUrlSuffix}`;
// Call our request helper (see 'utils/request')
return request(requestUrl, {
method: 'GET',
params,
})
.then(response => {
const options = isArray(response)
? map(response, item => ({
value: item,
label: templateObject(
{ mainField: this.props.relation.displayedAttribute },
item,
).mainField,
}))
: [
{
value: response,
label: templateObject(
{ mainField: this.props.relation.displayedAttribute },
response,
).mainField,
},
];
const newOptions = cloneDeep(this.state.options);
options.map(option => {
// Don't add the values when searching
if (
findIndex(newOptions, o => o.value.id === option.value.id) === -1
) {
return newOptions.push(option);
}
});
return this.setState({
options: newOptions,
isLoading: false,
});
})
.catch(() => {
strapi.notification.error(
'content-manager.notification.error.relationship.fetch',
);
const data = await request(requestUrl, {
method: 'GET',
params: params,
});
};
handleChange = value => {
const target = {
name: `record.${this.props.relation.alias}`,
value,
type: 'select',
};
setOptions(
data.map(obj => {
return { value: obj, label: obj[mainField] };
})
);
setIsLoading(false);
} catch (err) {
console.log({ err });
this.props.setRecordAttribute({ target });
};
handleBottomScroll = () => {
this.setState(prevState => {
return {
toSkip: prevState.toSkip + 1,
};
});
};
// Redirect to the edit page
handleClick = (item = {}) => {
this.props.onRedirect({
model: this.props.relation.collection || this.props.relation.model,
id: item.value.id || item.value._id,
source: this.props.relation.plugin,
});
};
handleInputChange = value => {
const clonedOptions = this.state.options;
const filteredValues = clonedOptions.filter(data =>
includes(data.label, value),
);
if (filteredValues.length === 0) {
return this.getOptions(value);
strapi.notification.error('notification.error');
}
};
render() {
const description = this.props.relation.description ? (
<p>{this.props.relation.description}</p>
) : (
''
useEffect(() => {
ref.current(targetModel);
}, [ref, targetModel, state._start]);
const nextSearch = `${pathname}${search}`;
const to = `/plugins/${pluginId}/${targetModel}/${
value ? value.id : null
}?redirectUrl=${nextSearch}`;
const link =
value === null ||
value === undefined ||
['role', 'permission'].includes(targetModel) ? null : (
<Link to={to}>
<FormattedMessage id="content-manager.containers.Edit.seeDetails" />
</Link>
);
const value = get(this.props.record, this.props.relation.alias);
const excludeModel = ['role', 'permission', 'file'].includes(
this.props.relation.model || this.props.relation.collection,
); // Temporary.
const entryLink =
isNull(value) || isUndefined(value) || excludeModel ? (
''
) : (
<FormattedMessage id="content-manager.containers.Edit.clickToJump">
{title => (
<a onClick={() => this.handleClick({ value })} title={title}>
<FormattedMessage id="content-manager.containers.Edit.seeDetails" />
</a>
)}
</FormattedMessage>
);
const onInputChange = inputValue => {
setState(prevState => ({ ...prevState, _q: inputValue }));
/* eslint-disable jsx-a11y/label-has-for */
return (
<div className={`form-group ${styles.selectOne}`}>
<nav className={styles.headline}>
<label htmlFor={this.props.relation.alias}>
{this.props.relation.alias}
</label>
{entryLink}
</nav>
{description}
<Select
onChange={this.handleChange}
options={this.state.options}
id={this.props.relation.alias}
isLoading={this.state.isLoading}
onMenuScrollToBottom={this.handleBottomScroll}
onInputChange={this.handleInputChange}
onSelectResetsInput={false}
simpleValue
value={
isNull(value) || isUndefined(value)
? null
: {
value: isFunction(value.toJS) ? value.toJS() : value,
label:
templateObject(
{ mainField: this.props.relation.displayedAttribute },
isFunction(value.toJS) ? value.toJS() : value,
).mainField ||
(isFunction(value.toJS)
? get(value.toJS(), 'id')
: get(value, 'id')),
}
}
/>
</div>
);
/* eslint-disable jsx-a11y/label-has-for */
}
return inputValue;
};
const onMenuScrollToBottom = () => {
setState(prevState => ({ ...prevState, _start: prevState._start + 1 }));
};
return (
<Wrapper className="form-group">
<Nav>
<label htmlFor={name}>{label}</label>
{link}
</Nav>
{!isEmpty(description) && <p>{description}</p>}
<Select
id={name}
isLoading={isLoading}
isClearable
options={options}
onChange={value => {
onChange({ target: { name, value: value ? value.value : value } });
}}
onInputChange={onInputChange}
onMenuClose={() => {
setState(prevState => ({ ...prevState, _start: 0 }));
}}
onMenuScrollToBottom={onMenuScrollToBottom}
value={
isNull(value) ? null : { label: get(value, [mainField], ''), value }
}
/>
</Wrapper>
);
}
SelectOne.defaultProps = {
description: '',
label: '',
plugin: '',
value: null,
};
SelectOne.propTypes = {
onRedirect: PropTypes.func.isRequired,
record: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]).isRequired,
relation: PropTypes.object.isRequired,
setRecordAttribute: PropTypes.func.isRequired,
description: PropTypes.string,
label: PropTypes.string,
mainField: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
pathname: PropTypes.string.isRequired,
plugin: PropTypes.string,
search: PropTypes.string.isRequired,
targetModel: PropTypes.string.isRequired,
value: PropTypes.object,
};
export default SelectOne;

View File

@ -0,0 +1,228 @@
/**
*
* SelectOne
*
*/
import React from 'react';
import Select from 'react-select';
import { FormattedMessage } from 'react-intl';
import PropTypes from 'prop-types';
import {
cloneDeep,
map,
includes,
isArray,
isNull,
isUndefined,
isFunction,
get,
findIndex,
} from 'lodash';
import { request, templateObject } from 'strapi-helper-plugin';
import styles from './styles.scss';
class SelectOne extends React.Component {
// eslint-disable-line react/prefer-stateless-function
constructor(props) {
super(props);
this.state = {
isLoading: true,
options: [],
toSkip: 0,
};
}
componentDidMount() {
this.getOptions('');
}
componentDidUpdate(prevProps, prevState) {
if (prevState.toSkip !== this.state.toSkip) {
this.getOptions('');
}
}
getOptions = query => {
const params = {
_limit: 20,
_start: this.state.toSkip,
source: this.props.relation.plugin || 'content-manager',
};
// Set `query` parameter if necessary
if (query) {
delete params._limit;
delete params._start;
params[`${this.props.relation.displayedAttribute}_contains`] = query;
}
// Request URL
const requestUrlSuffix =
query && get(this.props.record, [this.props.relation.alias])
? get(this.props.record, [this.props.relation.alias])
: '';
const requestUrl = `/content-manager/explorer/${this.props.relation.model ||
this.props.relation.collection}/${requestUrlSuffix}`;
// Call our request helper (see 'utils/request')
return request(requestUrl, {
method: 'GET',
params,
})
.then(response => {
const options = isArray(response)
? map(response, item => ({
value: item,
label: templateObject(
{ mainField: this.props.relation.displayedAttribute },
item,
).mainField,
}))
: [
{
value: response,
label: templateObject(
{ mainField: this.props.relation.displayedAttribute },
response,
).mainField,
},
];
const newOptions = cloneDeep(this.state.options);
options.map(option => {
// Don't add the values when searching
if (
findIndex(newOptions, o => o.value.id === option.value.id) === -1
) {
return newOptions.push(option);
}
});
return this.setState({
options: newOptions,
isLoading: false,
});
})
.catch(() => {
strapi.notification.error(
'content-manager.notification.error.relationship.fetch',
);
});
};
handleChange = value => {
const target = {
name: `record.${this.props.relation.alias}`,
value,
type: 'select',
};
this.props.setRecordAttribute({ target });
};
handleBottomScroll = () => {
this.setState(prevState => {
return {
toSkip: prevState.toSkip + 1,
};
});
};
// Redirect to the edit page
handleClick = (item = {}) => {
this.props.onRedirect({
model: this.props.relation.collection || this.props.relation.model,
id: item.value.id || item.value._id,
source: this.props.relation.plugin,
});
};
handleInputChange = value => {
const clonedOptions = this.state.options;
const filteredValues = clonedOptions.filter(data =>
includes(data.label, value),
);
if (filteredValues.length === 0) {
return this.getOptions(value);
}
};
render() {
const description = this.props.relation.description ? (
<p>{this.props.relation.description}</p>
) : (
''
);
const value = get(this.props.record, this.props.relation.alias);
const excludeModel = ['role', 'permission', 'file'].includes(
this.props.relation.model || this.props.relation.collection,
); // Temporary.
const entryLink =
isNull(value) || isUndefined(value) || excludeModel ? (
''
) : (
<FormattedMessage id="content-manager.containers.Edit.clickToJump">
{title => (
<a onClick={() => this.handleClick({ value })} title={title}>
<FormattedMessage id="content-manager.containers.Edit.seeDetails" />
</a>
)}
</FormattedMessage>
);
/* eslint-disable jsx-a11y/label-has-for */
return (
<div className={`form-group ${styles.selectOne}`}>
<nav className={styles.headline}>
<label htmlFor={this.props.relation.alias}>
{this.props.relation.alias}
</label>
{entryLink}
</nav>
{description}
<Select
onChange={this.handleChange}
options={this.state.options}
id={this.props.relation.alias}
isLoading={this.state.isLoading}
onMenuScrollToBottom={this.handleBottomScroll}
onInputChange={this.handleInputChange}
onSelectResetsInput={false}
simpleValue
value={
isNull(value) || isUndefined(value)
? null
: {
value: isFunction(value.toJS) ? value.toJS() : value,
label:
templateObject(
{ mainField: this.props.relation.displayedAttribute },
isFunction(value.toJS) ? value.toJS() : value,
).mainField ||
(isFunction(value.toJS)
? get(value.toJS(), 'id')
: get(value, 'id')),
}
}
/>
</div>
);
/* eslint-disable jsx-a11y/label-has-for */
}
}
SelectOne.propTypes = {
onRedirect: PropTypes.func.isRequired,
record: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]).isRequired,
relation: PropTypes.object.isRequired,
setRecordAttribute: PropTypes.func.isRequired,
};
export default SelectOne;

View File

@ -15,6 +15,7 @@ import {
import pluginId from '../../pluginId';
import Container from '../../components/Container';
import SelectOne from '../../components/SelectOne';
import { LinkWrapper, MainWrapper, SubWrapper } from './components';
import Group from './Group';
@ -29,7 +30,7 @@ function EditView({
currentEnvironment,
emitEvent,
layouts,
location: { search },
location: { pathname, search },
history: { push },
match: {
params: { slug, id },
@ -181,7 +182,11 @@ function EditView({
const toggleWarningCancel = () => setWarningCancel(prevState => !prevState);
const toggleWarningDelete = () => setWarningDelete(prevState => !prevState);
const redirectURL = search.split('redirectUrl=')[1];
const redirectURL = search
.split('redirectUrl=')
.filter((_, index) => index !== 0)
.join('');
const redirectToPreviousPage = () => push(redirectURL);
const handleConfirmDelete = async () => {
@ -214,7 +219,8 @@ function EditView({
? { id: `${pluginId}.containers.Edit.pluginHeader.title.new` }
: templateObject({ mainField: displayedFieldNameInHeader }, initialData)
.mainField;
const hasRelations = get(layout, ['layouts', 'editRelations'], []).length > 0;
const displayedRelations = get(layout, ['layouts', 'editRelations'], []);
const hasRelations = displayedRelations.length > 0;
const fields = get(layout, ['layouts', 'edit'], []);
/**
@ -394,7 +400,49 @@ function EditView({
style={{ padding: '0 20px 1px', marginBottom: '28px' }}
>
<div style={{ paddingTop: '19px' }}>
RELATIONS COMING SOON
{displayedRelations.map(relationName => {
//
const relation = get(
layout,
['schema', 'attributes', relationName],
{}
);
const relationMetas = get(
layout,
['metadata', relationName, 'edit'],
{}
);
const value = get(modifiedData, [relationName], null);
const Component = [
'oneWay',
'oneToOne',
'manyToOne',
'oneToManyMorph',
'oneToOneMorph',
].includes(relation.relationType)
? SelectOne
: // eslint-disable-next-line react/display-name
() => <div>SelectMany</div>;
return (
<Component
key={relationName}
{...relation}
{...relationMetas}
name={relationName}
onChange={({ target: { name, value } }) => {
dispatch({
type: 'ON_CHANGE',
keys: name.split('.'),
value,
});
}}
pathname={pathname}
search={search}
value={value}
/>
);
})}
</div>
</SubWrapper>
)}

View File

@ -199,10 +199,10 @@ module.exports = {
type: 'string',
},
articles: {
article: {
type: 'relation',
targetModel: 'article',
relationType: 'manyToMany',
relationType: 'manyToOne',
},
},
},
@ -237,20 +237,20 @@ module.exports = {
sortable: true,
},
},
articles: {
article: {
edit: {
label: 'articles',
description: '....',
editable: true,
visible: true,
mainField: 'id',
mainField: 'title',
},
list: {},
},
},
layouts: {
list: ['id', 'name'],
editRelations: ['articles'],
editRelations: ['article'],
edit: [
[
{
@ -307,7 +307,7 @@ module.exports = {
tags: {
type: 'relation',
targetModel: 'tag',
relationType: 'manyToMany',
relationType: 'oneToMany',
},
pics: {
collection: 'file',
@ -584,42 +584,42 @@ module.exports = {
searchable: true,
sortable: true,
},
confirmed: {
edit: {
label: 'confirmed',
description: '....',
editable: true,
visible: true,
},
list: {
label: 'confirmed',
searchable: true,
sortable: true,
},
},
confirmed: {
edit: {
label: 'confirmed',
description: '....',
editable: true,
visible: true,
},
blocked: {
edit: {
label: 'blocked',
description: '....',
editable: true,
visible: true,
},
list: {
label: 'blocked',
searchable: true,
sortable: true,
},
list: {
label: 'confirmed',
searchable: true,
sortable: true,
},
role: {
edit: {
label: 'role',
description: '....',
editable: true,
visible: true,
mainField: 'name',
},
list: {},
},
blocked: {
edit: {
label: 'blocked',
description: '....',
editable: true,
visible: true,
},
list: {
label: 'blocked',
searchable: true,
sortable: true,
},
},
role: {
edit: {
label: 'role',
description: '....',
editable: true,
visible: true,
mainField: 'name',
},
list: {},
},
},
layouts: {

View File

@ -25,7 +25,7 @@
"react-redux": "^7.0.2",
"react-router": "^5.0.0",
"react-router-dom": "^5.0.0",
"react-select": "^1.3.0",
"react-select": "^3.0.4",
"react-transition-group": "^2.5.0",
"reactstrap": "^5.0.0",
"redux": "^4.0.1",

View File

@ -27,7 +27,6 @@
"react-redux": "^7.0.3",
"react-router": "^5.0.0",
"react-router-dom": "^5.0.0",
"react-select": "^2.4.3",
"react-transition-group": "^4.0.1",
"reactstrap": "^8.0.0",
"redux": "^4.0.1",

261
yarn.lock
View File

@ -714,13 +714,6 @@
dependencies:
regenerator-runtime "^0.13.2"
"@babel/runtime@^7.4.2":
version "7.4.4"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.4.tgz#dc2e34982eb236803aa27a07fea6857af1b9171d"
integrity sha512-w0+uT71b6Yi7i5SE0co4NioIpSYS6lLiXvCzWzGSKvpK5vdQtCbICHMj+gbAKAOtxiV6HsVh/MBdaF9EQ6faSg==
dependencies:
regenerator-runtime "^0.13.2"
"@babel/template@^7.1.0", "@babel/template@^7.4.0", "@babel/template@^7.4.4":
version "7.4.4"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237"
@ -790,59 +783,6 @@
debug "^3.1.0"
lodash.once "^4.1.1"
"@emotion/babel-utils@^0.6.4":
version "0.6.10"
resolved "https://registry.yarnpkg.com/@emotion/babel-utils/-/babel-utils-0.6.10.tgz#83dbf3dfa933fae9fc566e54fbb45f14674c6ccc"
integrity sha512-/fnkM/LTEp3jKe++T0KyTszVGWNKPNOUJfjNKLO17BzQ6QPxgbg3whayom1Qr2oLFH3V92tDymU+dT5q676uow==
dependencies:
"@emotion/hash" "^0.6.6"
"@emotion/memoize" "^0.6.6"
"@emotion/serialize" "^0.9.1"
convert-source-map "^1.5.1"
find-root "^1.1.0"
source-map "^0.7.2"
"@emotion/cache@^10.0.14", "@emotion/cache@^10.0.9":
version "10.0.14"
resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.14.tgz#56093cff025c04b0330bdd92afe8335ed326dd18"
integrity sha512-HNGEwWnPlNyy/WPXBXzbjzkzeZFV657Z99/xq2xs5yinJHbMfi3ioCvBJ6Y8Zc8DQzO9F5jDmVXJB41Ytx3QMw==
dependencies:
"@emotion/sheet" "0.9.3"
"@emotion/stylis" "0.8.4"
"@emotion/utils" "0.11.2"
"@emotion/weak-memoize" "0.2.3"
"@emotion/core@^10.0.9":
version "10.0.14"
resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.14.tgz#cac5c334b278d5b7688cfff39e460a5b50abb71c"
integrity sha512-G9FbyxLm3lSnPfLDcag8fcOQBKui/ueXmWOhV+LuEQg9HrqExuWnWaO6gm6S5rNe+AMcqLXVljf8pYgAdFLNSg==
dependencies:
"@babel/runtime" "^7.4.3"
"@emotion/cache" "^10.0.14"
"@emotion/css" "^10.0.14"
"@emotion/serialize" "^0.11.8"
"@emotion/sheet" "0.9.3"
"@emotion/utils" "0.11.2"
"@emotion/css@^10.0.14", "@emotion/css@^10.0.9":
version "10.0.14"
resolved "https://registry.yarnpkg.com/@emotion/css/-/css-10.0.14.tgz#95dacabdd0e22845d1a1b0b5968d9afa34011139"
integrity sha512-MozgPkBEWvorcdpqHZE5x1D/PLEHUitALQCQYt2wayf4UNhpgQs2tN0UwHYS4FMy5ROBH+0ALyCFVYJ/ywmwlg==
dependencies:
"@emotion/serialize" "^0.11.8"
"@emotion/utils" "0.11.2"
babel-plugin-emotion "^10.0.14"
"@emotion/hash@0.7.2":
version "0.7.2"
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.7.2.tgz#53211e564604beb9befa7a4400ebf8147473eeef"
integrity sha512-RMtr1i6E8MXaBWwhXL3yeOU8JXRnz8GNxHvaUfVvwxokvayUY0zoBeWbKw1S9XkufmGEEdQd228pSZXFkAln8Q==
"@emotion/hash@^0.6.2", "@emotion/hash@^0.6.6":
version "0.6.6"
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.6.6.tgz#62266c5f0eac6941fece302abad69f2ee7e25e44"
integrity sha512-ojhgxzUHZ7am3D2jHkMzPpsBAiB005GF5YU4ea+8DNPybMk01JJUM9V9YRlF/GE95tcOm8DxQvWA2jq19bGalQ==
"@emotion/is-prop-valid@^0.7.3":
version "0.7.3"
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.7.3.tgz#a6bf4fa5387cbba59d44e698a4680f481a8da6cc"
@ -855,82 +795,11 @@
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.1.tgz#e93c13942592cf5ef01aa8297444dc192beee52f"
integrity sha512-Qv4LTqO11jepd5Qmlp3M1YEjBumoTHcHFdgPTQ+sFlIL5myi/7xu/POwP7IRu6odBdmLXdtIs1D6TuW6kbwbbg==
"@emotion/memoize@0.7.2":
version "0.7.2"
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.2.tgz#7f4c71b7654068dfcccad29553520f984cc66b30"
integrity sha512-hnHhwQzvPCW1QjBWFyBtsETdllOM92BfrKWbUTmh9aeOlcVOiXvlPsK4104xH8NsaKfg86PTFsWkueQeUfMA/w==
"@emotion/memoize@^0.6.1", "@emotion/memoize@^0.6.6":
version "0.6.6"
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.6.6.tgz#004b98298d04c7ca3b4f50ca2035d4f60d2eed1b"
integrity sha512-h4t4jFjtm1YV7UirAFuSuFGyLa+NNxjdkq6DpFLANNQY5rHueFZHVY+8Cu1HYVP6DrheB0kv4m5xPjo7eKT7yQ==
"@emotion/serialize@^0.11.8":
version "0.11.8"
resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.8.tgz#e41dcf7029e45286a3e0cf922933e670fe05402c"
integrity sha512-Qb6Us2Yk1ZW8SOYH6s5z7qzXXb2iHwVeqc6FjXtac0vvxC416ki0eTtHNw4Q5smoyxdyZh3519NKGrQvvvrZ/Q==
dependencies:
"@emotion/hash" "0.7.2"
"@emotion/memoize" "0.7.2"
"@emotion/unitless" "0.7.4"
"@emotion/utils" "0.11.2"
csstype "^2.5.7"
"@emotion/serialize@^0.9.1":
version "0.9.1"
resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.9.1.tgz#a494982a6920730dba6303eb018220a2b629c145"
integrity sha512-zTuAFtyPvCctHBEL8KZ5lJuwBanGSutFEncqLn/m9T1a6a93smBStK+bZzcNPgj4QS8Rkw9VTwJGhRIUVO8zsQ==
dependencies:
"@emotion/hash" "^0.6.6"
"@emotion/memoize" "^0.6.6"
"@emotion/unitless" "^0.6.7"
"@emotion/utils" "^0.8.2"
"@emotion/sheet@0.9.3":
version "0.9.3"
resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.3.tgz#689f135ecf87d3c650ed0c4f5ddcbe579883564a"
integrity sha512-c3Q6V7Df7jfwSq5AzQWbXHa5soeE4F5cbqi40xn0CzXxWW9/6Mxq48WJEtqfWzbZtW9odZdnRAkwCQwN12ob4A==
"@emotion/stylis@0.8.4":
version "0.8.4"
resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.4.tgz#6c51afdf1dd0d73666ba09d2eb6c25c220d6fe4c"
integrity sha512-TLmkCVm8f8gH0oLv+HWKiu7e8xmBIaokhxcEKPh1m8pXiV/akCiq50FvYgOwY42rjejck8nsdQxZlXZ7pmyBUQ==
"@emotion/stylis@^0.7.0":
version "0.7.1"
resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.7.1.tgz#50f63225e712d99e2b2b39c19c70fff023793ca5"
integrity sha512-/SLmSIkN13M//53TtNxgxo57mcJk/UJIDFRKwOiLIBEyBHEcipgR6hNMQ/59Sl4VjCJ0Z/3zeAZyvnSLPG/1HQ==
"@emotion/unitless@0.7.4":
version "0.7.4"
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.4.tgz#a87b4b04e5ae14a88d48ebef15015f6b7d1f5677"
integrity sha512-kBa+cDHOR9jpRJ+kcGMsysrls0leukrm68DmFQoMIWQcXdr2cZvyvypWuGYT7U+9kAExUE7+T7r6G3C3A6L8MQ==
"@emotion/unitless@^0.6.2", "@emotion/unitless@^0.6.7":
version "0.6.7"
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.6.7.tgz#53e9f1892f725b194d5e6a1684a7b394df592397"
integrity sha512-Arj1hncvEVqQ2p7Ega08uHLr1JuRYBuO5cIvcA+WWEQ5+VmkOE3ZXzl04NbQxeQpWX78G7u6MqxKuNX3wvYZxg==
"@emotion/unitless@^0.7.0":
version "0.7.3"
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.3.tgz#6310a047f12d21a1036fb031317219892440416f"
integrity sha512-4zAPlpDEh2VwXswwr/t8xGNDGg8RQiPxtxZ3qQEXyQsBV39ptTdESCjuBvGze1nLMVrxmTIKmnO/nAV8Tqjjzg==
"@emotion/utils@0.11.2":
version "0.11.2"
resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.2.tgz#713056bfdffb396b0a14f1c8f18e7b4d0d200183"
integrity sha512-UHX2XklLl3sIaP6oiMmlVzT0J+2ATTVpf0dHQVyPJHTkOITvXfaSqnRk6mdDhV9pR8T/tHc3cex78IKXssmzrA==
"@emotion/utils@^0.8.2":
version "0.8.2"
resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.8.2.tgz#576ff7fb1230185b619a75d258cbc98f0867a8dc"
integrity sha512-rLu3wcBWH4P5q1CGoSSH/i9hrXs7SlbRLkoq9IGuoPYNGQvDJ3pt/wmOM+XgYjIDRMVIdkUWt0RsfzF50JfnCw==
"@emotion/weak-memoize@0.2.3":
version "0.2.3"
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.3.tgz#dfa0c92efe44a1d1a7974fb49ffeb40ef2da5a27"
integrity sha512-zVgvPwGK7c1aVdUVc9Qv7SqepOGRDrqCw7KZPSZziWGxSlbII3gmvGLPzLX4d0n0BMbamBacUrN22zOMyFFEkQ==
"@evocateur/libnpmaccess@^3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@evocateur/libnpmaccess/-/libnpmaccess-3.1.0.tgz#e546ee4e4bedca54ed9303948ec54c985cec33e4"
@ -3501,40 +3370,6 @@ babel-loader@^8.0.5:
mkdirp "^0.5.1"
pify "^4.0.1"
babel-plugin-emotion@^10.0.14:
version "10.0.14"
resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-10.0.14.tgz#c1d0e4621e303507ea7da57daa3cd771939d6df4"
integrity sha512-T7hdxJ4xXkKW3OXcizK0pnUJlBeNj/emjQZPDIZvGOuwl2adIgicQWRNkz6BuwKdDTrqaXQn1vayaL6aL8QW5A==
dependencies:
"@babel/helper-module-imports" "^7.0.0"
"@emotion/hash" "0.7.2"
"@emotion/memoize" "0.7.2"
"@emotion/serialize" "^0.11.8"
babel-plugin-macros "^2.0.0"
babel-plugin-syntax-jsx "^6.18.0"
convert-source-map "^1.5.0"
escape-string-regexp "^1.0.5"
find-root "^1.1.0"
source-map "^0.5.7"
babel-plugin-emotion@^9.2.11:
version "9.2.11"
resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-9.2.11.tgz#319c005a9ee1d15bb447f59fe504c35fd5807728"
integrity sha512-dgCImifnOPPSeXod2znAmgc64NhaaOjGEHROR/M+lmStb3841yK1sgaDYAYMnlvWNz8GnpwIPN0VmNpbWYZ+VQ==
dependencies:
"@babel/helper-module-imports" "^7.0.0"
"@emotion/babel-utils" "^0.6.4"
"@emotion/hash" "^0.6.2"
"@emotion/memoize" "^0.6.1"
"@emotion/stylis" "^0.7.0"
babel-plugin-macros "^2.0.0"
babel-plugin-syntax-jsx "^6.18.0"
convert-source-map "^1.5.0"
find-root "^1.1.0"
mkdirp "^0.5.1"
source-map "^0.5.7"
touch "^2.0.1"
babel-plugin-istanbul@^5.1.0:
version "5.1.4"
resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.4.tgz#841d16b9a58eeb407a0ddce622ba02fe87a752ba"
@ -3551,15 +3386,6 @@ babel-plugin-jest-hoist@^24.6.0:
dependencies:
"@types/babel__traverse" "^7.0.6"
babel-plugin-macros@^2.0.0:
version "2.5.1"
resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.5.1.tgz#4a119ac2c2e19b458c259b9accd7ee34fd57ec6f"
integrity sha512-xN3KhAxPzsJ6OQTktCanNpIFnnMsCV+t8OloKxIL72D6+SUZYFn9qfklPgef5HyyDtzYZqqb+fs1S12+gQY82Q==
dependencies:
"@babel/runtime" "^7.4.2"
cosmiconfig "^5.2.0"
resolve "^1.10.0"
"babel-plugin-styled-components@>= 1":
version "1.10.0"
resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.10.0.tgz#ff1f42ad2cc78c21f26b62266b8f564dbc862939"
@ -5074,7 +4900,7 @@ conventional-recommended-bump@^4.0.4:
meow "^4.0.0"
q "^1.5.1"
convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1:
convert-source-map@^1.1.0, convert-source-map@^1.4.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20"
integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==
@ -5217,19 +5043,6 @@ create-ecdh@^4.0.0:
bn.js "^4.1.0"
elliptic "^6.0.0"
create-emotion@^9.2.12:
version "9.2.12"
resolved "https://registry.yarnpkg.com/create-emotion/-/create-emotion-9.2.12.tgz#0fc8e7f92c4f8bb924b0fef6781f66b1d07cb26f"
integrity sha512-P57uOF9NL2y98Xrbl2OuiDQUZ30GVmASsv5fbsjF4Hlraip2kyAvMm+2PoYUvFFw03Fhgtxk3RqZSm2/qHL9hA==
dependencies:
"@emotion/hash" "^0.6.2"
"@emotion/memoize" "^0.6.1"
"@emotion/stylis" "^0.7.0"
"@emotion/unitless" "^0.6.2"
csstype "^2.5.2"
stylis "^3.5.0"
stylis-rule-sheet "^0.0.10"
create-error-class@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6"
@ -5618,16 +5431,6 @@ csstype@^2.2.0:
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.5.tgz#1cd1dff742ebf4d7c991470ae71e12bb6751e034"
integrity sha512-JsTaiksRsel5n7XwqPAfB0l3TFKdpjW/kgAELf9vrb5adGA7UCPLajKK5s3nFrcFm3Rkyp/Qkgl73ENc1UY3cA==
csstype@^2.5.2:
version "2.6.4"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.4.tgz#d585a6062096e324e7187f80e04f92bd0f00e37f"
integrity sha512-lAJUJP3M6HxFXbqtGRc0iZrdyeN+WzOWeY0q/VnFzI+kqVrYIzC7bWlKqCW7oCIdzoPkvfp82EVvrTlQ8zsWQg==
csstype@^2.5.7:
version "2.6.6"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.6.tgz#c34f8226a94bbb10c32cc0d714afdf942291fc41"
integrity sha512-RpFbQGUE74iyPgvr46U9t1xoQBM8T4BL8SxrN66Le2xYAPSaDJJKeztV3awugusb3g3G9iL8StmkBBXhcbbXhg==
ctype@0.5.3:
version "0.5.3"
resolved "https://registry.yarnpkg.com/ctype/-/ctype-0.5.3.tgz#82c18c2461f74114ef16c135224ad0b9144ca12f"
@ -6413,14 +6216,6 @@ emojis-list@^2.0.0:
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k=
emotion@^9.1.2:
version "9.2.12"
resolved "https://registry.yarnpkg.com/emotion/-/emotion-9.2.12.tgz#53925aaa005614e65c6e43db8243c843574d1ea9"
integrity sha512-hcx7jppaI8VoXxIWEhxpDW7I+B4kq9RNzQLmsrF6LY8BGKqe2N+gFAQr0EfuFucFlPs2A9HM4+xNj4NeqEWIOQ==
dependencies:
babel-plugin-emotion "^9.2.11"
create-emotion "^9.2.12"
encodeurl@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
@ -7316,7 +7111,7 @@ find-cache-dir@^2.0.0:
make-dir "^2.0.0"
pkg-dir "^3.0.0"
find-root@^1.0.0, find-root@^1.1.0:
find-root@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4"
integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==
@ -12446,13 +12241,6 @@ nopt@^4.0.1, nopt@~4.0.1:
abbrev "1"
osenv "^0.1.4"
nopt@~1.0.10:
version "1.0.10"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee"
integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=
dependencies:
abbrev "1"
normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5, normalize-package-data@^2.4.0, normalize-package-data@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
@ -14986,7 +14774,7 @@ react-helmet@^5.2.0:
prop-types "^15.5.4"
react-side-effect "^1.1.0"
react-input-autosize@^2.1.2, react-input-autosize@^2.2.1:
react-input-autosize@^2.1.2:
version "2.2.1"
resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.1.tgz#ec428fa15b1592994fb5f9aa15bb1eb6baf420f8"
integrity sha512-3+K4CD13iE4lQQ2WlF8PuV5htfmTRLH6MDnfndHM6LuBRszuXnuyIfE7nhSKt8AzRBZ50bu0sAhkNMeS5pxQQA==
@ -15133,35 +14921,6 @@ react-select@^1.3.0:
prop-types "^15.5.8"
react-input-autosize "^2.1.2"
react-select@^2.4.3:
version "2.4.3"
resolved "https://registry.yarnpkg.com/react-select/-/react-select-2.4.3.tgz#62efdf76d7e33e9bde22d907a0cc8abd0aeab656"
integrity sha512-cmxNaiHpviRYkojeW9rGEUJ4jpX7QTmPe2wcscwA4d1lStzw/cJtr4ft5H2O/YhfpkrcwaLghu3XmEYdXhBo8Q==
dependencies:
classnames "^2.2.5"
emotion "^9.1.2"
memoize-one "^5.0.0"
prop-types "^15.6.0"
raf "^3.4.0"
react-input-autosize "^2.2.1"
react-transition-group "^2.2.1"
react-select@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/react-select/-/react-select-3.0.4.tgz#16bde37c24fd4f6444914d4681e78f15ffbc86d3"
integrity sha512-fbVISKa/lSUlLsltuatfUiKcWCNvdLXxFFyrzVQCBUsjxJZH/m7UMPdw/ywmRixAmwXAP++MdbNNZypOsiDEfA==
dependencies:
"@babel/runtime" "^7.4.4"
"@emotion/cache" "^10.0.9"
"@emotion/core" "^10.0.9"
"@emotion/css" "^10.0.9"
classnames "^2.2.5"
memoize-one "^5.0.0"
prop-types "^15.6.0"
raf "^3.4.0"
react-input-autosize "^2.2.1"
react-transition-group "^2.2.1"
react-side-effect@^1.1.0:
version "1.1.5"
resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-1.1.5.tgz#f26059e50ed9c626d91d661b9f3c8bb38cd0ff2d"
@ -17053,7 +16812,7 @@ source-map@^0.4.2:
dependencies:
amdefine ">=0.0.4"
source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.0:
source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.0:
version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
@ -17063,11 +16822,6 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
source-map@^0.7.2:
version "0.7.3"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
source-map@~0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d"
@ -18067,13 +17821,6 @@ toposort@^2.0.2:
resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330"
integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=
touch@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/touch/-/touch-2.0.2.tgz#ca0b2a3ae3211246a61b16ba9e6cbf1596287164"
integrity sha512-qjNtvsFXTRq7IuMLweVgFxmEuQ6gLbRs2jQxL80TtZ31dEKWYIxRXquij6w6VimyDek5hD3PytljHmEtAs2u0A==
dependencies:
nopt "~1.0.10"
tough-cookie@>=0.12.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-3.0.1.tgz#9df4f57e739c26930a018184887f4adb7dca73b2"