feat!: store array values as actual array value (#3442)
This commit is contained in:
@@ -66,7 +66,7 @@ export const ArrayAction: React.FC<Props> = ({
|
|||||||
<PopupList.Button
|
<PopupList.Button
|
||||||
className={`${baseClass}__action ${baseClass}__add`}
|
className={`${baseClass}__action ${baseClass}__add`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
addRow(index + 1)
|
addRow(index)
|
||||||
close()
|
close()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -140,8 +140,8 @@ export const addFieldStatePromise = async ({
|
|||||||
fieldState.value = null
|
fieldState.value = null
|
||||||
fieldState.initialValue = null
|
fieldState.initialValue = null
|
||||||
} else {
|
} else {
|
||||||
fieldState.value = arrayValue.length
|
fieldState.value = arrayValue
|
||||||
fieldState.initialValue = arrayValue.length
|
fieldState.initialValue = arrayValue
|
||||||
|
|
||||||
if (arrayValue.length > 0) {
|
if (arrayValue.length > 0) {
|
||||||
fieldState.disableFormData = true
|
fieldState.disableFormData = true
|
||||||
@@ -230,8 +230,8 @@ export const addFieldStatePromise = async ({
|
|||||||
fieldState.value = null
|
fieldState.value = null
|
||||||
fieldState.initialValue = null
|
fieldState.initialValue = null
|
||||||
} else {
|
} else {
|
||||||
fieldState.value = blocksValue.length
|
fieldState.value = blocksValue
|
||||||
fieldState.initialValue = blocksValue.length
|
fieldState.initialValue = blocksValue
|
||||||
|
|
||||||
if (blocksValue.length > 0) {
|
if (blocksValue.length > 0) {
|
||||||
fieldState.disableFormData = true
|
fieldState.disableFormData = true
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ export function fieldReducer(state: Fields, action: FieldAction): Fields {
|
|||||||
...state[path],
|
...state[path],
|
||||||
disableFormData: rows.length > 0,
|
disableFormData: rows.length > 0,
|
||||||
rows: rowsMetadata,
|
rows: rowsMetadata,
|
||||||
value: rows.length,
|
value: rows,
|
||||||
},
|
},
|
||||||
...flattenRows(path, rows),
|
...flattenRows(path, rows),
|
||||||
}
|
}
|
||||||
@@ -136,7 +136,7 @@ export function fieldReducer(state: Fields, action: FieldAction): Fields {
|
|||||||
|
|
||||||
const rowsMetadata = [...(state[path]?.rows || [])]
|
const rowsMetadata = [...(state[path]?.rows || [])]
|
||||||
rowsMetadata.splice(
|
rowsMetadata.splice(
|
||||||
rowIndex + 1,
|
rowIndex,
|
||||||
0,
|
0,
|
||||||
// new row
|
// new row
|
||||||
{
|
{
|
||||||
@@ -158,7 +158,7 @@ export function fieldReducer(state: Fields, action: FieldAction): Fields {
|
|||||||
const { remainingFields, rows } = separateRows(path, state)
|
const { remainingFields, rows } = separateRows(path, state)
|
||||||
|
|
||||||
// actual form state (value saved in db)
|
// actual form state (value saved in db)
|
||||||
rows.splice(rowIndex + 1, 0, subFieldState)
|
rows.splice(rowIndex, 0, subFieldState)
|
||||||
|
|
||||||
const newState: Fields = {
|
const newState: Fields = {
|
||||||
...remainingFields,
|
...remainingFields,
|
||||||
@@ -167,7 +167,7 @@ export function fieldReducer(state: Fields, action: FieldAction): Fields {
|
|||||||
...state[path],
|
...state[path],
|
||||||
disableFormData: true,
|
disableFormData: true,
|
||||||
rows: rowsMetadata,
|
rows: rowsMetadata,
|
||||||
value: rows.length,
|
value: rows,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,7 +205,7 @@ export function fieldReducer(state: Fields, action: FieldAction): Fields {
|
|||||||
...state[path],
|
...state[path],
|
||||||
disableFormData: true,
|
disableFormData: true,
|
||||||
rows: rowsMetadata,
|
rows: rowsMetadata,
|
||||||
value: rows.length,
|
value: rows,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,7 +236,7 @@ export function fieldReducer(state: Fields, action: FieldAction): Fields {
|
|||||||
...state[path],
|
...state[path],
|
||||||
disableFormData: true,
|
disableFormData: true,
|
||||||
rows: rowsMetadata,
|
rows: rowsMetadata,
|
||||||
value: rows.length,
|
value: rows,
|
||||||
},
|
},
|
||||||
...flattenRows(path, rows),
|
...flattenRows(path, rows),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -463,7 +463,7 @@ const Form: React.FC<Props> = (props) => {
|
|||||||
dispatchFields({
|
dispatchFields({
|
||||||
blockType: data?.blockType,
|
blockType: data?.blockType,
|
||||||
path,
|
path,
|
||||||
rowIndex: rowIndex - 1,
|
rowIndex,
|
||||||
subFieldState,
|
subFieldState,
|
||||||
type: 'ADD_ROW',
|
type: 'ADD_ROW',
|
||||||
})
|
})
|
||||||
@@ -501,7 +501,7 @@ const Form: React.FC<Props> = (props) => {
|
|||||||
dispatchFields({
|
dispatchFields({
|
||||||
blockType: data?.blockType,
|
blockType: data?.blockType,
|
||||||
path,
|
path,
|
||||||
rowIndex: rowIndex - 1,
|
rowIndex,
|
||||||
subFieldState,
|
subFieldState,
|
||||||
type: 'REPLACE_ROW',
|
type: 'REPLACE_ROW',
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ import { useForm, useFormSubmitted } from '../../Form/context'
|
|||||||
import { NullifyLocaleField } from '../../NullifyField'
|
import { NullifyLocaleField } from '../../NullifyField'
|
||||||
import useField from '../../useField'
|
import useField from '../../useField'
|
||||||
import withCondition from '../../withCondition'
|
import withCondition from '../../withCondition'
|
||||||
|
import { fieldBaseClass } from '../shared'
|
||||||
import { ArrayRow } from './ArrayRow'
|
import { ArrayRow } from './ArrayRow'
|
||||||
import './index.scss'
|
import './index.scss'
|
||||||
import { fieldBaseClass } from '../shared'
|
|
||||||
|
|
||||||
const baseClass = 'array-field'
|
const baseClass = 'array-field'
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ const ArrayFieldType: React.FC<Props> = (props) => {
|
|||||||
showError,
|
showError,
|
||||||
valid,
|
valid,
|
||||||
value,
|
value,
|
||||||
} = useField<number>({
|
} = useField<[]>({
|
||||||
condition,
|
condition,
|
||||||
hasRows: true,
|
hasRows: true,
|
||||||
path,
|
path,
|
||||||
@@ -111,20 +111,20 @@ const ArrayFieldType: React.FC<Props> = (props) => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const duplicateRow = useCallback(
|
const duplicateRow = useCallback(
|
||||||
async (rowIndex: number) => {
|
(rowIndex: number) => {
|
||||||
dispatchFields({ path, rowIndex, type: 'DUPLICATE_ROW' })
|
dispatchFields({ path, rowIndex, type: 'DUPLICATE_ROW' })
|
||||||
setModified(true)
|
setModified(true)
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
scrollToID(`${path}-row-${rowIndex + 1}`)
|
scrollToID(`${path}-row-${rowIndex}`)
|
||||||
}, 0)
|
}, 0)
|
||||||
},
|
},
|
||||||
[dispatchFields, path, setModified],
|
[dispatchFields, path, setModified],
|
||||||
)
|
)
|
||||||
|
|
||||||
const removeRow = useCallback(
|
const removeRow = useCallback(
|
||||||
(rowIndex: number) => {
|
async (rowIndex: number) => {
|
||||||
removeFieldRow({ path, rowIndex })
|
await removeFieldRow({ path, rowIndex })
|
||||||
setModified(true)
|
setModified(true)
|
||||||
},
|
},
|
||||||
[removeFieldRow, path, setModified],
|
[removeFieldRow, path, setModified],
|
||||||
@@ -139,14 +139,14 @@ const ArrayFieldType: React.FC<Props> = (props) => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const toggleCollapseAll = useCallback(
|
const toggleCollapseAll = useCallback(
|
||||||
async (collapsed: boolean) => {
|
(collapsed: boolean) => {
|
||||||
dispatchFields({ collapsed, path, setDocFieldPreferences, type: 'SET_ALL_ROWS_COLLAPSED' })
|
dispatchFields({ collapsed, path, setDocFieldPreferences, type: 'SET_ALL_ROWS_COLLAPSED' })
|
||||||
},
|
},
|
||||||
[dispatchFields, path, setDocFieldPreferences],
|
[dispatchFields, path, setDocFieldPreferences],
|
||||||
)
|
)
|
||||||
|
|
||||||
const setCollapse = useCallback(
|
const setCollapse = useCallback(
|
||||||
async (rowID: string, collapsed: boolean) => {
|
(rowID: string, collapsed: boolean) => {
|
||||||
dispatchFields({ collapsed, path, rowID, setDocFieldPreferences, type: 'SET_ROW_COLLAPSED' })
|
dispatchFields({ collapsed, path, rowID, setDocFieldPreferences, type: 'SET_ROW_COLLAPSED' })
|
||||||
},
|
},
|
||||||
[dispatchFields, path, setDocFieldPreferences],
|
[dispatchFields, path, setDocFieldPreferences],
|
||||||
@@ -274,11 +274,11 @@ const ArrayFieldType: React.FC<Props> = (props) => {
|
|||||||
{!readOnly && !hasMaxRows && (
|
{!readOnly && !hasMaxRows && (
|
||||||
<Button
|
<Button
|
||||||
buttonStyle="icon-label"
|
buttonStyle="icon-label"
|
||||||
|
className={`${baseClass}__add-row`}
|
||||||
icon="plus"
|
icon="plus"
|
||||||
iconPosition="left"
|
iconPosition="left"
|
||||||
iconStyle="with-border"
|
iconStyle="with-border"
|
||||||
onClick={() => addRow(value)}
|
onClick={() => addRow(value?.length || 0)}
|
||||||
className={`${baseClass}__add-row`}
|
|
||||||
>
|
>
|
||||||
{t('addLabel', { label: getTranslation(labels.singular, i18n) })}
|
{t('addLabel', { label: getTranslation(labels.singular, i18n) })}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ const BlocksField: React.FC<Props> = (props) => {
|
|||||||
showError,
|
showError,
|
||||||
valid,
|
valid,
|
||||||
value,
|
value,
|
||||||
} = useField<number>({
|
} = useField<[]>({
|
||||||
condition,
|
condition,
|
||||||
hasRows: true,
|
hasRows: true,
|
||||||
path,
|
path,
|
||||||
@@ -99,7 +99,7 @@ const BlocksField: React.FC<Props> = (props) => {
|
|||||||
|
|
||||||
const addRow = useCallback(
|
const addRow = useCallback(
|
||||||
async (rowIndex: number, blockType: string) => {
|
async (rowIndex: number, blockType: string) => {
|
||||||
addFieldRow({
|
await addFieldRow({
|
||||||
data: {
|
data: {
|
||||||
blockType,
|
blockType,
|
||||||
},
|
},
|
||||||
@@ -116,7 +116,7 @@ const BlocksField: React.FC<Props> = (props) => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const duplicateRow = useCallback(
|
const duplicateRow = useCallback(
|
||||||
async (rowIndex: number) => {
|
(rowIndex: number) => {
|
||||||
dispatchFields({ path, rowIndex, type: 'DUPLICATE_ROW' })
|
dispatchFields({ path, rowIndex, type: 'DUPLICATE_ROW' })
|
||||||
setModified(true)
|
setModified(true)
|
||||||
|
|
||||||
@@ -128,8 +128,8 @@ const BlocksField: React.FC<Props> = (props) => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const removeRow = useCallback(
|
const removeRow = useCallback(
|
||||||
(rowIndex: number) => {
|
async (rowIndex: number) => {
|
||||||
removeFieldRow({ path, rowIndex })
|
await removeFieldRow({ path, rowIndex })
|
||||||
setModified(true)
|
setModified(true)
|
||||||
},
|
},
|
||||||
[path, removeFieldRow, setModified],
|
[path, removeFieldRow, setModified],
|
||||||
@@ -144,14 +144,14 @@ const BlocksField: React.FC<Props> = (props) => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const toggleCollapseAll = useCallback(
|
const toggleCollapseAll = useCallback(
|
||||||
async (collapsed: boolean) => {
|
(collapsed: boolean) => {
|
||||||
dispatchFields({ collapsed, path, setDocFieldPreferences, type: 'SET_ALL_ROWS_COLLAPSED' })
|
dispatchFields({ collapsed, path, setDocFieldPreferences, type: 'SET_ALL_ROWS_COLLAPSED' })
|
||||||
},
|
},
|
||||||
[dispatchFields, path, setDocFieldPreferences],
|
[dispatchFields, path, setDocFieldPreferences],
|
||||||
)
|
)
|
||||||
|
|
||||||
const setCollapse = useCallback(
|
const setCollapse = useCallback(
|
||||||
async (rowID: string, collapsed: boolean) => {
|
(rowID: string, collapsed: boolean) => {
|
||||||
dispatchFields({ collapsed, path, rowID, setDocFieldPreferences, type: 'SET_ROW_COLLAPSED' })
|
dispatchFields({ collapsed, path, rowID, setDocFieldPreferences, type: 'SET_ROW_COLLAPSED' })
|
||||||
},
|
},
|
||||||
[dispatchFields, path, setDocFieldPreferences],
|
[dispatchFields, path, setDocFieldPreferences],
|
||||||
@@ -297,7 +297,7 @@ const BlocksField: React.FC<Props> = (props) => {
|
|||||||
</DrawerToggler>
|
</DrawerToggler>
|
||||||
<BlocksDrawer
|
<BlocksDrawer
|
||||||
addRow={addRow}
|
addRow={addRow}
|
||||||
addRowIndex={value}
|
addRowIndex={value?.length || 0}
|
||||||
blocks={blocks}
|
blocks={blocks}
|
||||||
drawerSlug={drawerSlug}
|
drawerSlug={drawerSlug}
|
||||||
labels={labels}
|
labels={labels}
|
||||||
|
|||||||
@@ -92,14 +92,9 @@ export const promise = async ({
|
|||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!skipValidationFromHere && field.validate) {
|
if (!skipValidationFromHere && field.validate) {
|
||||||
let valueToValidate = siblingData[field.name]
|
const valueToValidate = siblingData[field.name]
|
||||||
let jsonError
|
let jsonError
|
||||||
|
|
||||||
if (['array', 'blocks'].includes(field.type)) {
|
|
||||||
const rows = siblingData[field.name]
|
|
||||||
valueToValidate = Array.isArray(rows) ? rows.length : 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if (field.type === 'json' && typeof siblingData[field.name] === 'string') {
|
if (field.type === 'json' && typeof siblingData[field.name] === 'string') {
|
||||||
try {
|
try {
|
||||||
JSON.parse(siblingData[field.name] as string)
|
JSON.parse(siblingData[field.name] as string)
|
||||||
|
|||||||
@@ -389,15 +389,17 @@ export const array: Validate<unknown, unknown, ArrayField> = (
|
|||||||
value,
|
value,
|
||||||
{ maxRows, minRows, required, t },
|
{ maxRows, minRows, required, t },
|
||||||
) => {
|
) => {
|
||||||
if (minRows && value < minRows) {
|
const arrayLength = Array.isArray(value) ? value.length : 0
|
||||||
|
|
||||||
|
if (minRows && arrayLength < minRows) {
|
||||||
return t('validation:requiresAtLeast', { count: minRows, label: t('rows') })
|
return t('validation:requiresAtLeast', { count: minRows, label: t('rows') })
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxRows && value > maxRows) {
|
if (maxRows && arrayLength > maxRows) {
|
||||||
return t('validation:requiresNoMoreThan', { count: maxRows, label: t('rows') })
|
return t('validation:requiresNoMoreThan', { count: maxRows, label: t('rows') })
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!value && required) {
|
if (!arrayLength && required) {
|
||||||
return t('validation:requiresAtLeast', { count: 1, label: t('row') })
|
return t('validation:requiresAtLeast', { count: 1, label: t('row') })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,15 +458,17 @@ export const blocks: Validate<unknown, unknown, BlockField> = (
|
|||||||
value,
|
value,
|
||||||
{ maxRows, minRows, required, t },
|
{ maxRows, minRows, required, t },
|
||||||
) => {
|
) => {
|
||||||
if (minRows && value < minRows) {
|
const arrayLength = Array.isArray(value) ? value.length : 0
|
||||||
|
|
||||||
|
if (minRows && arrayLength < minRows) {
|
||||||
return t('validation:requiresAtLeast', { count: minRows, label: t('rows') })
|
return t('validation:requiresAtLeast', { count: minRows, label: t('rows') })
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxRows && value > maxRows) {
|
if (maxRows && arrayLength > maxRows) {
|
||||||
return t('validation:requiresNoMoreThan', { count: maxRows, label: t('rows') })
|
return t('validation:requiresNoMoreThan', { count: maxRows, label: t('rows') })
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!value && required) {
|
if (!arrayLength && required) {
|
||||||
return t('validation:requiresAtLeast', { count: 1, label: t('row') })
|
return t('validation:requiresAtLeast', { count: 1, label: t('row') })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export const AddCustomBlocks: React.FC = () => {
|
|||||||
const { addFieldRow, replaceFieldRow } = useForm()
|
const { addFieldRow, replaceFieldRow } = useForm()
|
||||||
const { value } = useField({ path: 'customBlocks' })
|
const { value } = useField({ path: 'customBlocks' })
|
||||||
|
|
||||||
const nextIndex = typeof value === 'number' ? value + 1 : 0
|
const nextIndex = Array.isArray(value) ? value.length : 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={baseClass}>
|
<div className={baseClass}>
|
||||||
@@ -56,7 +56,7 @@ export const AddCustomBlocks: React.FC = () => {
|
|||||||
}
|
}
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
Replace Block {nextIndex - 1}
|
Replace Block {nextIndex}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user