mirror of
https://github.com/strapi/strapi.git
synced 2025-08-10 17:58:07 +00:00
Merge pull request #5897 from strapi/fix/single-types-issues
Fix single types navigation
This commit is contained in:
commit
81c94c9ea0
@ -14,7 +14,8 @@
|
||||
},
|
||||
"slug": {
|
||||
"type": "uid",
|
||||
"targetField": "title"
|
||||
"targetField": "title",
|
||||
"required": true
|
||||
},
|
||||
"single": {
|
||||
"model": "file",
|
||||
|
@ -32,13 +32,8 @@ const FieldComponent = ({
|
||||
const componentValue = get(modifiedData, name, null);
|
||||
const componentValueLength = size(componentValue);
|
||||
const isInitialized = componentValue !== null || isFromDynamicZone;
|
||||
const showResetComponent =
|
||||
!isRepeatable && isInitialized && !isFromDynamicZone;
|
||||
const currentComponentSchema = get(
|
||||
allLayoutData,
|
||||
['components', componentUid],
|
||||
{}
|
||||
);
|
||||
const showResetComponent = !isRepeatable && isInitialized && !isFromDynamicZone;
|
||||
const currentComponentSchema = get(allLayoutData, ['components', componentUid], {});
|
||||
|
||||
const displayedFields = get(currentComponentSchema, ['layouts', 'edit'], []);
|
||||
|
||||
|
@ -7,7 +7,7 @@ import { useDebounce, useClickAwayListener } from '@buffetjs/hooks';
|
||||
import styled from 'styled-components';
|
||||
import { request, LoadingIndicator } from 'strapi-helper-plugin';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { get } from 'lodash';
|
||||
|
||||
import pluginId from '../../pluginId';
|
||||
import getRequestUrl from '../../utils/getRequestUrl';
|
||||
@ -42,13 +42,12 @@ const InputUID = ({
|
||||
error: inputError,
|
||||
name,
|
||||
onChange,
|
||||
required,
|
||||
validations,
|
||||
value,
|
||||
editable,
|
||||
...inputProps
|
||||
}) => {
|
||||
const { modifiedData, initialData } = useDataManager();
|
||||
const { modifiedData, initialData, layout } = useDataManager();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [availability, setAvailability] = useState(null);
|
||||
const [isSuggestionOpen, setIsSuggestionOpen] = useState(true);
|
||||
@ -59,9 +58,10 @@ const InputUID = ({
|
||||
const wrapperRef = useRef(null);
|
||||
const generateUid = useRef();
|
||||
const initialValue = initialData[name];
|
||||
const isCreation = isEmpty(initialData);
|
||||
const createdAtName = get(layout, ['schema', 'options', 'timestamps', 0]);
|
||||
const isCreation = !initialData[createdAtName];
|
||||
|
||||
generateUid.current = async () => {
|
||||
generateUid.current = async (shouldSetInitialValue = false) => {
|
||||
setIsLoading(true);
|
||||
const requestURL = getRequestUrl('explorer/uid/generate');
|
||||
try {
|
||||
@ -73,7 +73,8 @@ const InputUID = ({
|
||||
data: modifiedData,
|
||||
},
|
||||
});
|
||||
onChange({ target: { name, value: data, type: 'text' } });
|
||||
|
||||
onChange({ target: { name, value: data, type: 'text' } }, shouldSetInitialValue);
|
||||
setIsLoading(false);
|
||||
} catch (err) {
|
||||
console.error({ err });
|
||||
@ -106,8 +107,8 @@ const InputUID = ({
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!value && required) {
|
||||
generateUid.current();
|
||||
if (!value && validations.required) {
|
||||
generateUid.current(true);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
@ -143,9 +144,15 @@ const InputUID = ({
|
||||
}, [availability]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isCustomized && isCreation && debouncedTargetFieldValue !== null) {
|
||||
generateUid.current();
|
||||
if (
|
||||
!isCustomized &&
|
||||
isCreation &&
|
||||
debouncedTargetFieldValue &&
|
||||
modifiedData[attribute.targetField]
|
||||
) {
|
||||
generateUid.current(true);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [debouncedTargetFieldValue, isCustomized, isCreation]);
|
||||
|
||||
useClickAwayListener(wrapperRef, () => setIsSuggestionOpen(false));
|
||||
@ -220,7 +227,7 @@ const InputUID = ({
|
||||
<RegenerateButton
|
||||
onMouseEnter={handleGenerateMouseEnter}
|
||||
onMouseLeave={handleGenerateMouseLeave}
|
||||
onClick={generateUid.current}
|
||||
onClick={() => generateUid.current()}
|
||||
>
|
||||
{isLoading ? (
|
||||
<LoadingIndicator small />
|
||||
@ -264,7 +271,6 @@ InputUID.propTypes = {
|
||||
error: PropTypes.string,
|
||||
name: PropTypes.string.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
required: PropTypes.bool,
|
||||
validations: PropTypes.object,
|
||||
value: PropTypes.string,
|
||||
};
|
||||
@ -273,7 +279,6 @@ InputUID.defaultProps = {
|
||||
description: '',
|
||||
editable: false,
|
||||
error: null,
|
||||
required: false,
|
||||
validations: {},
|
||||
value: '',
|
||||
};
|
||||
|
@ -53,13 +53,10 @@ const RepeatableComponent = ({
|
||||
});
|
||||
};
|
||||
const missingComponentsValue = min - componentValueLength;
|
||||
const errorsArray = componentErrorKeys.map(key =>
|
||||
get(formErrors, [key, 'id'], '')
|
||||
);
|
||||
const errorsArray = componentErrorKeys.map(key => get(formErrors, [key, 'id'], ''));
|
||||
|
||||
const hasMinError =
|
||||
get(errorsArray, [0], '').includes('min') &&
|
||||
!collapses.some(obj => obj.isOpen === true);
|
||||
get(errorsArray, [0], '').includes('min') && !collapses.some(obj => obj.isOpen === true);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -84,9 +81,7 @@ const RepeatableComponent = ({
|
||||
<DraggedItem
|
||||
fields={fields}
|
||||
componentFieldName={componentFieldName}
|
||||
doesPreviousFieldContainErrorsAndIsOpen={
|
||||
doesPreviousFieldContainErrorsAndIsOpen
|
||||
}
|
||||
doesPreviousFieldContainErrorsAndIsOpen={doesPreviousFieldContainErrorsAndIsOpen}
|
||||
hasErrors={hasErrors}
|
||||
hasMinError={hasMinError}
|
||||
isFirst={index === 0}
|
||||
@ -129,11 +124,7 @@ const RepeatableComponent = ({
|
||||
if (componentValueLength < max) {
|
||||
const shouldCheckErrors = hasMinError;
|
||||
|
||||
addRepeatableComponentToField(
|
||||
name,
|
||||
componentUid,
|
||||
shouldCheckErrors
|
||||
);
|
||||
addRepeatableComponentToField(name, componentUid, shouldCheckErrors);
|
||||
dispatch({
|
||||
type: 'ADD_NEW_FIELD',
|
||||
});
|
||||
|
@ -21,7 +21,7 @@ import reducer, { initialState } from './reducer';
|
||||
|
||||
/* eslint-disable react/no-array-index-key */
|
||||
|
||||
const EditView = ({ components, currentEnvironment, layouts, plugins, slug }) => {
|
||||
const EditView = ({ components, currentEnvironment, deleteLayout, layouts, plugins, slug }) => {
|
||||
const formatLayoutRef = useRef();
|
||||
formatLayoutRef.current = createAttributesLayout;
|
||||
// Retrieve push to programmatically navigate between views
|
||||
@ -95,6 +95,9 @@ const EditView = ({ components, currentEnvironment, layouts, plugins, slug }) =>
|
||||
currentContentTypeSchema.attributes
|
||||
),
|
||||
});
|
||||
|
||||
return () => deleteLayout(slug);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [currentContentTypeLayout, currentContentTypeSchema.attributes]);
|
||||
|
||||
const { formattedContentTypeLayout, isDraggingComponent } = reducerState.toJS();
|
||||
@ -265,12 +268,13 @@ EditView.defaultProps = {
|
||||
};
|
||||
|
||||
EditView.propTypes = {
|
||||
currentEnvironment: PropTypes.string,
|
||||
components: PropTypes.array.isRequired,
|
||||
currentEnvironment: PropTypes.string,
|
||||
deleteLayout: PropTypes.func.isRequired,
|
||||
emitEvent: PropTypes.func,
|
||||
layouts: PropTypes.object.isRequired,
|
||||
slug: PropTypes.string.isRequired,
|
||||
plugins: PropTypes.object,
|
||||
slug: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export { EditView };
|
||||
|
@ -77,6 +77,7 @@ const EditViewDataManagerProvider = ({ allLayoutData, children, redirectToPrevio
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const contentTypeDataStructure = createDefaultForm(
|
||||
currentContentTypeLayout.schema.attributes,
|
||||
allLayoutData.components
|
||||
@ -181,7 +182,7 @@ const EditViewDataManagerProvider = ({ allLayoutData, children, redirectToPrevio
|
||||
});
|
||||
};
|
||||
|
||||
const handleChange = ({ target: { name, value, type } }) => {
|
||||
const handleChange = ({ target: { name, value, type } }, shouldSetInitialValue = false) => {
|
||||
let inputValue = value;
|
||||
|
||||
// Empty string is not a valid date,
|
||||
@ -213,6 +214,7 @@ const EditViewDataManagerProvider = ({ allLayoutData, children, redirectToPrevio
|
||||
type: 'ON_CHANGE',
|
||||
keys: name.split('.'),
|
||||
value: inputValue,
|
||||
shouldSetInitialValue,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -135,11 +135,21 @@ const reducer = (state, action) => {
|
||||
let newState = state;
|
||||
const [nonRepeatableComponentKey] = action.keys;
|
||||
|
||||
// This is used to set the initialData for inputs
|
||||
// that needs an asynchronous initial value like the UID field
|
||||
// This is just a temporary patch.
|
||||
// TODO : Refactor the default form creation (workflow) to accept async default values.
|
||||
if (action.shouldSetInitialValue) {
|
||||
newState = state.updateIn(['initialData', ...action.keys], () => {
|
||||
return action.value;
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
action.keys.length === 2 &&
|
||||
state.getIn(['modifiedData', nonRepeatableComponentKey]) === null
|
||||
) {
|
||||
newState = state.updateIn(['modifiedData', nonRepeatableComponentKey], () => fromJS({}));
|
||||
newState = newState.updateIn(['modifiedData', nonRepeatableComponentKey], () => fromJS({}));
|
||||
}
|
||||
|
||||
return newState.updateIn(['modifiedData', ...action.keys], () => {
|
||||
|
@ -3,14 +3,7 @@ import { get } from 'lodash';
|
||||
const createDefaultForm = (attributes, allComponentsSchema) => {
|
||||
return Object.keys(attributes).reduce((acc, current) => {
|
||||
const attribute = get(attributes, [current], {});
|
||||
const {
|
||||
default: defaultValue,
|
||||
component,
|
||||
type,
|
||||
required,
|
||||
min,
|
||||
repeatable,
|
||||
} = attribute;
|
||||
const { default: defaultValue, component, type, required, min, repeatable } = attribute;
|
||||
|
||||
if (type === 'json') {
|
||||
acc[current] = null;
|
||||
|
Loading…
x
Reference in New Issue
Block a user