feat: simplifies collapsible label API, adds e2e tests

This commit is contained in:
Jarrod Flesch
2022-11-16 12:57:54 -05:00
parent 999c8fc08b
commit d9df98ff22
11 changed files with 105 additions and 110 deletions

View File

@@ -4,24 +4,27 @@ import { useWatchForm } from '../Form/context';
const baseClass = 'row-label';
export const RowLabel: React.FC<Props> = (props) => {
export const RowLabel: React.FC<Props> = ({ className, ...rest }) => {
return (
<span style={{
pointerEvents: 'none',
}}
<span
style={{
pointerEvents: 'none',
}}
className={[
baseClass,
className,
].filter(Boolean).join(' ')}
>
<RowLabelContent {...props} />
<RowLabelContent {...rest} />
</span>
);
};
const RowLabelContent: React.FC<Props> = (props) => {
const RowLabelContent: React.FC<Omit<Props, 'className'>> = (props) => {
const {
path,
fallback,
label,
rowNumber,
className,
} = props;
const { getDataByPath, getSiblingData } = useWatchForm();
@@ -35,37 +38,18 @@ const RowLabelContent: React.FC<Props> = (props) => {
<Label
data={data}
path={path}
fallback={fallback}
index={rowNumber}
/>
);
}
if (label) {
return (
<span
className={[
baseClass,
className,
].filter(Boolean).join(' ')}
>
{typeof label === 'function' ? label({
data,
path,
fallback,
index: rowNumber,
}) : label}
</span>
);
}
if (fallback) {
return (
<React.Fragment>
{fallback}
</React.Fragment>
);
}
return null;
return (
<React.Fragment>
{typeof label === 'function' ? label({
data,
path,
index: rowNumber,
}) : label}
</React.Fragment>
);
};

View File

@@ -2,7 +2,6 @@ import React from 'react';
import { Data } from '../Form/types';
export type Props = {
fallback: string;
path: string;
label?: RowLabel;
rowNumber?: number;
@@ -12,8 +11,7 @@ export type Props = {
export type RowLabelArgs = {
data: Data,
path: string,
index: number,
fallback: string
index?: number,
}
export type RowLabelFunction = (args: RowLabelArgs) => string

View File

@@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useReducer, useState } from 'react';
import React, { useCallback, useEffect, useReducer } from 'react';
import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd';
import { useAuth } from '../../../utilities/Auth';
import withCondition from '../../withCondition';
@@ -50,8 +50,6 @@ const ArrayFieldType: React.FC<Props> = (props) => {
},
} = props;
const RowLabelFromProps = components?.RowLabel || undefined;
const path = pathFromProps || name;
// Handle labeling for Arrays, Global Arrays, and Blocks
@@ -65,6 +63,8 @@ const ArrayFieldType: React.FC<Props> = (props) => {
// eslint-disable-next-line react/destructuring-assignment
const label = props?.label ?? props?.labels?.singular;
const CustomRowLabel = components?.RowLabel || undefined;
const { preferencesKey } = useDocumentInfo();
const { getPreference } = usePreferences();
const { setPreference } = usePreferences();
@@ -255,6 +255,7 @@ const ArrayFieldType: React.FC<Props> = (props) => {
>
{rows.length > 0 && rows.map((row, i) => {
const rowNumber = i + 1;
const fallbackLabel = `${labels.singular} ${String(rowNumber).padStart(2, '0')}`;
return (
<Draggable
@@ -278,8 +279,7 @@ const ArrayFieldType: React.FC<Props> = (props) => {
header={(
<RowLabel
path={`${path}.${i}`}
label={RowLabelFromProps}
fallback={`${labels.singular} ${String(rowNumber).padStart(2, '0')}`}
label={CustomRowLabel || fallbackLabel}
rowNumber={rowNumber}
/>
)}

View File

@@ -1,6 +1,8 @@
@import '../../../../scss/styles.scss';
.collapsible-field {
margin: 0 0 base(2);
&__label {
pointer-events: none;
}

View File

@@ -3,7 +3,6 @@ import RenderFields from '../../RenderFields';
import withCondition from '../../withCondition';
import { Props } from './types';
import { Collapsible } from '../../../elements/Collapsible';
import toKebabCase from '../../../../../utilities/toKebabCase';
import { usePreferences } from '../../../utilities/Preferences';
import { DocumentPreferences } from '../../../../../preferences/types';
import { useDocumentInfo } from '../../../utilities/DocumentInfo';
@@ -28,45 +27,57 @@ const CollapsibleField: React.FC<Props> = (props) => {
className,
initCollapsed,
description,
components,
},
} = props;
const CollapsibleLabelFromProps = components?.CollapsibleLabel || undefined;
const { getPreference, setPreference } = usePreferences();
const { preferencesKey } = useDocumentInfo();
const [collapsedOnMount, setCollapsedOnMount] = useState<boolean>();
const [fieldPreferencesKey] = useState(() => `collapsible-${toKebabCase(label)}`);
const fieldPreferencesKey = `collapsible-${indexPath.replace(/\./gi, '__')}`;
const onToggle = useCallback(async (newCollapsedState: boolean) => {
const existingPreferences: DocumentPreferences = await getPreference(preferencesKey);
setPreference(preferencesKey, {
...existingPreferences,
fields: {
...existingPreferences?.fields || {},
[fieldPreferencesKey]: {
...existingPreferences?.fields?.[fieldPreferencesKey],
collapsed: newCollapsedState,
...path ? {
fields: {
...existingPreferences?.fields || {},
[path]: {
...existingPreferences?.fields?.[path],
collapsed: newCollapsedState,
},
},
} : {
fields: {
...existingPreferences?.fields || {},
[fieldPreferencesKey]: {
...existingPreferences?.fields?.[fieldPreferencesKey],
collapsed: newCollapsedState,
},
},
},
});
}, [preferencesKey, fieldPreferencesKey, getPreference, setPreference]);
}, [preferencesKey, fieldPreferencesKey, getPreference, setPreference, path]);
useEffect(() => {
const fetchInitialState = async () => {
const preferences = await getPreference(preferencesKey);
setCollapsedOnMount(Boolean(preferences?.fields?.[fieldPreferencesKey]?.collapsed ?? initCollapsed));
if (preferences) {
const initCollapsedFromPref = path ? preferences?.fields?.[path]?.collapsed : preferences?.fields?.[fieldPreferencesKey]?.collapsed;
setCollapsedOnMount(Boolean(initCollapsedFromPref));
} else {
setCollapsedOnMount(typeof initCollapsed === 'boolean' ? initCollapsed : false);
}
};
fetchInitialState();
}, [getPreference, preferencesKey, fieldPreferencesKey, initCollapsed]);
}, [getPreference, preferencesKey, fieldPreferencesKey, initCollapsed, path]);
if (typeof collapsedOnMount !== 'boolean') return null;
return (
<div id={fieldPreferencesKey}>
<div id={`field-${fieldPreferencesKey}${path ? `-${path.replace(/\./gi, '__')}` : ''}`}>
<Collapsible
initCollapsed={collapsedOnMount}
className={[
@@ -77,8 +88,7 @@ const CollapsibleField: React.FC<Props> = (props) => {
header={(
<RowLabel
path={path}
fallback={label}
label={CollapsibleLabelFromProps}
label={label}
/>
)}
onToggle={onToggle}