mirror of
https://github.com/strapi/strapi.git
synced 2025-09-03 13:50:38 +00:00
Add dynamic to edit a field
This commit is contained in:
parent
c29212aa2c
commit
d9ca6451d7
@ -3,7 +3,7 @@ import React, { useState, useEffect, useRef, memo } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { Link, useLocation } from 'react-router-dom';
|
import { Link, useLocation } from 'react-router-dom';
|
||||||
import { get, isArray, isEmpty } from 'lodash';
|
import { get, cloneDeep, isArray, isEmpty } from 'lodash';
|
||||||
import { request } from 'strapi-helper-plugin';
|
import { request } from 'strapi-helper-plugin';
|
||||||
import pluginId from '../../pluginId';
|
import pluginId from '../../pluginId';
|
||||||
import useDataManager from '../../hooks/useDataManager';
|
import useDataManager from '../../hooks/useDataManager';
|
||||||
|
@ -138,7 +138,7 @@ const DataManagerProvider = ({ children }) => {
|
|||||||
return <Redirect to={`/plugins/${pluginId}/content-types/${firstCTUid}`} />;
|
return <Redirect to={`/plugins/${pluginId}/content-types/${firstCTUid}`} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log({ modifiedData });
|
console.log({ modifiedData, contentTypes });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DataManagerContext.Provider
|
<DataManagerContext.Provider
|
||||||
|
@ -28,11 +28,17 @@ const reducer = (state, action) => {
|
|||||||
return fromJS(rest);
|
return fromJS(rest);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.updateIn(['modifiedData', 'schema', 'attributes'], obj => {
|
.updateIn(
|
||||||
const type = get(rest, 'type');
|
['modifiedData', ...pathToDataToEdit, 'schema', 'attributes'],
|
||||||
|
obj => {
|
||||||
|
const type = get(rest, 'type', 'relation');
|
||||||
const target = get(rest, 'target', null);
|
const target = get(rest, 'target', null);
|
||||||
const nature = get(rest, 'nature', null);
|
const nature = get(rest, 'nature', null);
|
||||||
const currentUid = state.getIn(['modifiedData', 'uid']);
|
const currentUid = state.getIn([
|
||||||
|
'modifiedData',
|
||||||
|
...pathToDataToEdit,
|
||||||
|
'uid',
|
||||||
|
]);
|
||||||
|
|
||||||
// When the user in creating a relation with the same content type we need to create another attribute
|
// When the user in creating a relation with the same content type we need to create another attribute
|
||||||
// that is the opposite of the created one
|
// that is the opposite of the created one
|
||||||
@ -58,7 +64,8 @@ const reducer = (state, action) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
case 'GET_DATA_SUCCEEDED':
|
case 'GET_DATA_SUCCEEDED':
|
||||||
return state
|
return state
|
||||||
|
@ -14,7 +14,7 @@ import {
|
|||||||
import { Inputs } from '@buffetjs/custom';
|
import { Inputs } from '@buffetjs/custom';
|
||||||
import { useHistory, useLocation } from 'react-router-dom';
|
import { useHistory, useLocation } from 'react-router-dom';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { get, isEmpty, toString, upperFirst } from 'lodash';
|
import { get, has, isEmpty, set, toString, upperFirst } from 'lodash';
|
||||||
import pluginId from '../../pluginId';
|
import pluginId from '../../pluginId';
|
||||||
import useQuery from '../../hooks/useQuery';
|
import useQuery from '../../hooks/useQuery';
|
||||||
import useDataManager from '../../hooks/useDataManager';
|
import useDataManager from '../../hooks/useDataManager';
|
||||||
@ -44,6 +44,7 @@ const FormModal = () => {
|
|||||||
targetUid: null,
|
targetUid: null,
|
||||||
attributeType: null,
|
attributeType: null,
|
||||||
headerDisplayName: null,
|
headerDisplayName: null,
|
||||||
|
pathToSchema: [],
|
||||||
};
|
};
|
||||||
const [state, setState] = useState(initialStateData);
|
const [state, setState] = useState(initialStateData);
|
||||||
const [reducerState, dispatch] = useReducer(reducer, initialState, init);
|
const [reducerState, dispatch] = useReducer(reducer, initialState, init);
|
||||||
@ -59,34 +60,60 @@ const FormModal = () => {
|
|||||||
modifiedData: allDataSchema,
|
modifiedData: allDataSchema,
|
||||||
sortedContentTypesList,
|
sortedContentTypesList,
|
||||||
} = useDataManager();
|
} = useDataManager();
|
||||||
const { formErrors, modifiedData } = reducerState.toJS();
|
const { formErrors, initialData, modifiedData } = reducerState.toJS();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isEmpty(search)) {
|
if (!isEmpty(search)) {
|
||||||
// Return 'null' if there isn't any attributeType search params
|
// Return 'null' if there isn't any attributeType search params
|
||||||
//TODO need targetUID
|
|
||||||
// TODO change target by targetUID & add displayName instead of target
|
|
||||||
const attributeType = query.get('attributeType');
|
const attributeType = query.get('attributeType');
|
||||||
const modalType = query.get('modalType');
|
const modalType = query.get('modalType');
|
||||||
const actionType = query.get('actionType');
|
const actionType = query.get('actionType');
|
||||||
|
const attributeName = query.get('attributeName');
|
||||||
|
const settingType = query.get('settingType');
|
||||||
|
const forTarget = query.get('forTarget');
|
||||||
|
const targetUid = query.get('targetUid');
|
||||||
|
const headerDisplayName = query.get('headerDisplayName');
|
||||||
|
const pathToSchema =
|
||||||
|
forTarget === 'contentType' || forTarget === 'component'
|
||||||
|
? [forTarget]
|
||||||
|
: [forTarget, targetUid];
|
||||||
|
|
||||||
setState({
|
setState({
|
||||||
attributeName: query.get('attributeName'),
|
attributeName,
|
||||||
actionType,
|
actionType,
|
||||||
modalType,
|
modalType,
|
||||||
settingType: query.get('settingType'),
|
settingType,
|
||||||
forTarget: query.get('forTarget'),
|
forTarget,
|
||||||
targetUid: query.get('targetUid'),
|
targetUid,
|
||||||
headerDisplayName: query.get('headerDisplayName'),
|
headerDisplayName,
|
||||||
attributeType,
|
attributeType,
|
||||||
|
pathToSchema,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set the predefined data structure to create an attribute
|
// Set the predefined data structure to create an attribute
|
||||||
if (
|
if (
|
||||||
attributeType &&
|
attributeType &&
|
||||||
attributeType !== 'null' &&
|
attributeType !== 'null' &&
|
||||||
|
// This condition is added to prevent the reducer state to be cleared when navigating from the base tab to tha advanced one
|
||||||
state.modalType !== 'attribute'
|
state.modalType !== 'attribute'
|
||||||
) {
|
) {
|
||||||
|
const attributeToEditNotFormatted = get(
|
||||||
|
allDataSchema,
|
||||||
|
[...pathToSchema, 'schema', 'attributes', attributeName],
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
const attributeToEdit = {
|
||||||
|
...attributeToEditNotFormatted,
|
||||||
|
name: attributeName,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (
|
||||||
|
attributeType === 'relation' &&
|
||||||
|
!has(attributeToEdit, ['targetAttribute'])
|
||||||
|
) {
|
||||||
|
set(attributeToEdit, ['targetAttribute'], '-');
|
||||||
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'SET_ATTRIBUTE_DATA_SCHEMA',
|
type: 'SET_ATTRIBUTE_DATA_SCHEMA',
|
||||||
attributeType,
|
attributeType,
|
||||||
@ -96,6 +123,8 @@ const FormModal = () => {
|
|||||||
'error'
|
'error'
|
||||||
),
|
),
|
||||||
targetUid: get(sortedContentTypesList, ['0', 'uid'], 'error'),
|
targetUid: get(sortedContentTypesList, ['0', 'uid'], 'error'),
|
||||||
|
isEditing: actionType === 'edit',
|
||||||
|
modifiedDataToSetForEditing: attributeToEdit,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,8 +151,6 @@ const FormModal = () => {
|
|||||||
headerId = null;
|
headerId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log({ allDataSchema });
|
|
||||||
|
|
||||||
const checkFormValidity = async () => {
|
const checkFormValidity = async () => {
|
||||||
let schema;
|
let schema;
|
||||||
|
|
||||||
@ -134,15 +161,16 @@ const FormModal = () => {
|
|||||||
// && state.forTarget !== 'components' &&
|
// && state.forTarget !== 'components' &&
|
||||||
// state.forTarget !== 'component'
|
// state.forTarget !== 'component'
|
||||||
) {
|
) {
|
||||||
const pathToSchemaAttributes =
|
const type =
|
||||||
state.forTarget === 'contentType' || state.forTarget === 'component'
|
state.attributeType === 'relation' ? 'relation' : modifiedData.type;
|
||||||
? [state.forTarget]
|
|
||||||
: [state.forTarget, state.targetUid];
|
|
||||||
|
|
||||||
schema = forms[state.modalType].schema(
|
schema = forms[state.modalType].schema(
|
||||||
get(allDataSchema, pathToSchemaAttributes, {}),
|
get(allDataSchema, state.pathToSchema, {}),
|
||||||
modifiedData.type,
|
type,
|
||||||
modifiedData
|
modifiedData,
|
||||||
|
state.actionType === 'edit',
|
||||||
|
state.attributeName,
|
||||||
|
initialData
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// TODO validate component schema
|
// TODO validate component schema
|
||||||
|
@ -4,6 +4,7 @@ import pluralize from 'pluralize';
|
|||||||
const initialState = fromJS({
|
const initialState = fromJS({
|
||||||
formErrors: {},
|
formErrors: {},
|
||||||
modifiedData: {},
|
modifiedData: {},
|
||||||
|
initialData: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const shouldPluralizeTargetAttribute = nature =>
|
export const shouldPluralizeTargetAttribute = nature =>
|
||||||
@ -75,7 +76,20 @@ const reducer = (state, action) => {
|
|||||||
case 'RESET_PROPS':
|
case 'RESET_PROPS':
|
||||||
return initialState;
|
return initialState;
|
||||||
case 'SET_ATTRIBUTE_DATA_SCHEMA': {
|
case 'SET_ATTRIBUTE_DATA_SCHEMA': {
|
||||||
const { attributeType, nameToSetForRelation, targetUid } = action;
|
const {
|
||||||
|
attributeType,
|
||||||
|
isEditing,
|
||||||
|
modifiedDataToSetForEditing,
|
||||||
|
nameToSetForRelation,
|
||||||
|
targetUid,
|
||||||
|
} = action;
|
||||||
|
|
||||||
|
if (isEditing) {
|
||||||
|
return state
|
||||||
|
.update('modifiedData', () => fromJS(modifiedDataToSetForEditing))
|
||||||
|
.update('initialData', () => fromJS(modifiedDataToSetForEditing));
|
||||||
|
}
|
||||||
|
|
||||||
let dataToSet;
|
let dataToSet;
|
||||||
|
|
||||||
if (attributeType === 'text') {
|
if (attributeType === 'text') {
|
||||||
|
@ -17,7 +17,7 @@ yup.addMethod(yup.mixed, 'defined', function() {
|
|||||||
|
|
||||||
yup.addMethod(yup.string, 'unique', function(
|
yup.addMethod(yup.string, 'unique', function(
|
||||||
message,
|
message,
|
||||||
allReadyTakenValues,
|
alreadyTakenAttributes,
|
||||||
validator
|
validator
|
||||||
) {
|
) {
|
||||||
return this.test('unique', message, function(string) {
|
return this.test('unique', message, function(string) {
|
||||||
@ -25,7 +25,7 @@ yup.addMethod(yup.string, 'unique', function(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !allReadyTakenValues.includes(
|
return !alreadyTakenAttributes.includes(
|
||||||
typeof validator === 'function' ? validator(string) : string
|
typeof validator === 'function' ? validator(string) : string
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -46,18 +46,42 @@ const ATTRIBUTES_THAT_DONT_HAVE_MIN_MAX_SETTINGS = [
|
|||||||
|
|
||||||
const forms = {
|
const forms = {
|
||||||
attribute: {
|
attribute: {
|
||||||
schema(currentSchema, attributeType, dataToValidate) {
|
schema(
|
||||||
const allreadyTakenAttributes = Object.keys(
|
currentSchema,
|
||||||
|
attributeType,
|
||||||
|
dataToValidate,
|
||||||
|
isEditing,
|
||||||
|
attributeToEditName,
|
||||||
|
initialData
|
||||||
|
) {
|
||||||
|
const alreadyTakenAttributes = Object.keys(
|
||||||
get(currentSchema, ['schema', 'attributes'], {})
|
get(currentSchema, ['schema', 'attributes'], {})
|
||||||
|
).filter(attribute => {
|
||||||
|
if (isEditing) {
|
||||||
|
return attribute !== attributeToEditName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
let targetAttributeAlreadyTakenValue = dataToValidate.name
|
||||||
|
? [...alreadyTakenAttributes, dataToValidate.name]
|
||||||
|
: alreadyTakenAttributes;
|
||||||
|
|
||||||
|
if (
|
||||||
|
isEditing &&
|
||||||
|
attributeType === 'relation' &&
|
||||||
|
dataToValidate.target === currentSchema.uid
|
||||||
|
) {
|
||||||
|
targetAttributeAlreadyTakenValue = targetAttributeAlreadyTakenValue.filter(
|
||||||
|
attribute => attribute !== initialData.targetAttribute
|
||||||
);
|
);
|
||||||
const targetAttributeAllreadyTakenValue = dataToValidate.name
|
}
|
||||||
? [...allreadyTakenAttributes, dataToValidate.name]
|
|
||||||
: allreadyTakenAttributes;
|
|
||||||
|
|
||||||
const commonShape = {
|
const commonShape = {
|
||||||
name: yup
|
name: yup
|
||||||
.string()
|
.string()
|
||||||
.unique(errorsTrads.unique, allreadyTakenAttributes)
|
.unique(errorsTrads.unique, alreadyTakenAttributes)
|
||||||
.required(errorsTrads.required),
|
.required(errorsTrads.required),
|
||||||
type: yup.string().required(errorsTrads.required),
|
type: yup.string().required(errorsTrads.required),
|
||||||
default: yup.string().nullable(),
|
default: yup.string().nullable(),
|
||||||
@ -144,13 +168,12 @@ const forms = {
|
|||||||
return yup.object().shape({
|
return yup.object().shape({
|
||||||
name: yup
|
name: yup
|
||||||
.string()
|
.string()
|
||||||
.unique(errorsTrads.unique, allreadyTakenAttributes)
|
.unique(errorsTrads.unique, alreadyTakenAttributes)
|
||||||
.required(errorsTrads.required),
|
.required(errorsTrads.required),
|
||||||
targetAttribute: yup
|
targetAttribute: yup
|
||||||
.string()
|
.string()
|
||||||
.unique(errorsTrads.unique, targetAttributeAllreadyTakenValue)
|
.unique(errorsTrads.unique, targetAttributeAlreadyTakenValue)
|
||||||
.required(errorsTrads.required),
|
.required(errorsTrads.required),
|
||||||
type: yup.string().required(errorsTrads.required),
|
|
||||||
target: yup.string().required(errorsTrads.required),
|
target: yup.string().required(errorsTrads.required),
|
||||||
nature: yup.string().required(),
|
nature: yup.string().required(),
|
||||||
dominant: yup.boolean().nullable(),
|
dominant: yup.boolean().nullable(),
|
||||||
@ -586,11 +609,11 @@ const forms = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
contentType: {
|
contentType: {
|
||||||
schema(allReadyTakenValues) {
|
schema(alreadyTakenAttributes) {
|
||||||
return yup.object().shape({
|
return yup.object().shape({
|
||||||
name: yup
|
name: yup
|
||||||
.string()
|
.string()
|
||||||
.unique(errorsTrads.unique, allReadyTakenValues, createUid)
|
.unique(errorsTrads.unique, alreadyTakenAttributes, createUid)
|
||||||
.required(errorsTrads.required),
|
.required(errorsTrads.required),
|
||||||
collectionName: yup.string(),
|
collectionName: yup.string(),
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user