feat!: store array values as actual array value (#3442)

This commit is contained in:
Jarrod Flesch
2023-10-05 13:16:30 -04:00
committed by GitHub
parent 618ee991dc
commit 9880880384
9 changed files with 44 additions and 45 deletions

View File

@@ -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()
}} }}
> >

View File

@@ -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

View File

@@ -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),
} }

View File

@@ -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',
}) })

View File

@@ -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>

View File

@@ -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}

View File

@@ -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)

View File

@@ -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') })
} }

View File

@@ -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>