feat/add support for setting collapsable fields (array, block, collapsable… (#1057)
Co-authored-by: liorix <liorix@gmail.com> Co-authored-by: Elliot DeNolf <denolfe@gmail.com>
This commit is contained in:
@@ -42,6 +42,7 @@ const ArrayFieldType: React.FC<Props> = (props) => {
|
||||
readOnly,
|
||||
description,
|
||||
condition,
|
||||
initCollapsed,
|
||||
className,
|
||||
},
|
||||
} = props;
|
||||
@@ -128,33 +129,40 @@ const ArrayFieldType: React.FC<Props> = (props) => {
|
||||
moveRow(sourceIndex, destinationIndex);
|
||||
}, [moveRow]);
|
||||
|
||||
const setCollapse = useCallback(async (rowID: string, collapsed: boolean) => {
|
||||
dispatchRows({ type: 'SET_COLLAPSE', id: rowID, collapsed });
|
||||
const setCollapse = useCallback(
|
||||
async (rowID: string, collapsed: boolean) => {
|
||||
dispatchRows({ type: 'SET_COLLAPSE', id: rowID, collapsed });
|
||||
|
||||
if (preferencesKey) {
|
||||
const preferencesToSet = await getPreference(preferencesKey) || { fields: {} };
|
||||
let newCollapsedState = preferencesToSet?.fields?.[path]?.collapsed
|
||||
.filter((filterID) => (rows.find((row) => row.id === filterID)))
|
||||
|| [];
|
||||
if (preferencesKey) {
|
||||
const preferencesToSet = (await getPreference(preferencesKey)) || { fields: {} };
|
||||
let newCollapsedState: string[] = preferencesToSet?.fields?.[path]?.collapsed;
|
||||
|
||||
if (!collapsed) {
|
||||
newCollapsedState = newCollapsedState.filter((existingID) => existingID !== rowID);
|
||||
} else {
|
||||
newCollapsedState.push(rowID);
|
||||
}
|
||||
if (initCollapsed && typeof newCollapsedState === 'undefined') {
|
||||
newCollapsedState = rows.map((row) => row.id);
|
||||
} else if (typeof newCollapsedState === 'undefined') {
|
||||
newCollapsedState = [];
|
||||
}
|
||||
|
||||
setPreference(preferencesKey, {
|
||||
...preferencesToSet,
|
||||
fields: {
|
||||
...preferencesToSet?.fields || {},
|
||||
[path]: {
|
||||
...preferencesToSet?.fields?.[path],
|
||||
collapsed: newCollapsedState,
|
||||
if (!collapsed) {
|
||||
newCollapsedState = newCollapsedState.filter((existingID) => existingID !== rowID);
|
||||
} else {
|
||||
newCollapsedState.push(rowID);
|
||||
}
|
||||
|
||||
setPreference(preferencesKey, {
|
||||
...preferencesToSet,
|
||||
fields: {
|
||||
...(preferencesToSet?.fields || {}),
|
||||
[path]: {
|
||||
...preferencesToSet?.fields?.[path],
|
||||
collapsed: newCollapsedState,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}, [preferencesKey, path, setPreference, rows, getPreference]);
|
||||
});
|
||||
}
|
||||
},
|
||||
[preferencesKey, getPreference, path, setPreference, initCollapsed, rows],
|
||||
);
|
||||
|
||||
const toggleCollapseAll = useCallback(async (collapse: boolean) => {
|
||||
dispatchRows({ type: 'SET_ALL_COLLAPSED', collapse });
|
||||
@@ -178,12 +186,12 @@ const ArrayFieldType: React.FC<Props> = (props) => {
|
||||
useEffect(() => {
|
||||
const initializeRowState = async () => {
|
||||
const data = formContext.getDataByPath<Row[]>(path);
|
||||
const preferences = await getPreference(preferencesKey) || { fields: {} };
|
||||
dispatchRows({ type: 'SET_ALL', data: data || [], collapsedState: preferences?.fields?.[path]?.collapsed });
|
||||
const preferences = (await getPreference(preferencesKey)) || { fields: {} };
|
||||
dispatchRows({ type: 'SET_ALL', data: data || [], collapsedState: preferences?.fields?.[path]?.collapsed, initCollapsed });
|
||||
};
|
||||
|
||||
initializeRowState();
|
||||
}, [formContext, path, getPreference, preferencesKey]);
|
||||
}, [formContext, path, getPreference, preferencesKey, initCollapsed]);
|
||||
|
||||
useEffect(() => {
|
||||
setValue(rows?.length || 0, true);
|
||||
|
||||
@@ -54,6 +54,7 @@ const Index: React.FC<Props> = (props) => {
|
||||
readOnly,
|
||||
description,
|
||||
condition,
|
||||
initCollapsed,
|
||||
className,
|
||||
},
|
||||
} = props;
|
||||
@@ -141,9 +142,13 @@ const Index: React.FC<Props> = (props) => {
|
||||
|
||||
if (preferencesKey) {
|
||||
const preferencesToSet = await getPreference(preferencesKey) || { fields: {} };
|
||||
let newCollapsedState = preferencesToSet?.fields?.[path]?.collapsed
|
||||
.filter((filterID) => (rows.find((row) => row.id === filterID)))
|
||||
|| [];
|
||||
let newCollapsedState: string[] = preferencesToSet?.fields?.[path]?.collapsed;
|
||||
|
||||
if (initCollapsed && typeof newCollapsedState === 'undefined') {
|
||||
newCollapsedState = rows.map((row) => row.id);
|
||||
} else if (typeof newCollapsedState === 'undefined') {
|
||||
newCollapsedState = [];
|
||||
}
|
||||
|
||||
if (!collapsed) {
|
||||
newCollapsedState = newCollapsedState.filter((existingID) => existingID !== rowID);
|
||||
@@ -162,7 +167,7 @@ const Index: React.FC<Props> = (props) => {
|
||||
},
|
||||
});
|
||||
}
|
||||
}, [preferencesKey, getPreference, path, setPreference, rows]);
|
||||
}, [preferencesKey, getPreference, path, setPreference, initCollapsed, rows]);
|
||||
|
||||
const toggleCollapseAll = useCallback(async (collapse: boolean) => {
|
||||
dispatchRows({ type: 'SET_ALL_COLLAPSED', collapse });
|
||||
@@ -187,12 +192,12 @@ const Index: React.FC<Props> = (props) => {
|
||||
useEffect(() => {
|
||||
const initializeRowState = async () => {
|
||||
const data = formContext.getDataByPath<Row[]>(path);
|
||||
const preferences = await getPreference(preferencesKey) || { fields: {} };
|
||||
dispatchRows({ type: 'SET_ALL', data: data || [], collapsedState: preferences?.fields?.[path]?.collapsed });
|
||||
const preferences = (await getPreference(preferencesKey)) || { fields: {} };
|
||||
dispatchRows({ type: 'SET_ALL', data: data || [], collapsedState: preferences?.fields?.[path]?.collapsed, initCollapsed });
|
||||
};
|
||||
|
||||
initializeRowState();
|
||||
}, [formContext, path, getPreference, preferencesKey]);
|
||||
}, [formContext, path, getPreference, preferencesKey, initCollapsed]);
|
||||
|
||||
useEffect(() => {
|
||||
setValue(rows?.length || 0, true);
|
||||
|
||||
@@ -24,13 +24,14 @@ const CollapsibleField: React.FC<Props> = (props) => {
|
||||
admin: {
|
||||
readOnly,
|
||||
className,
|
||||
initCollapsed,
|
||||
description,
|
||||
},
|
||||
} = props;
|
||||
|
||||
const { getPreference, setPreference } = usePreferences();
|
||||
const { preferencesKey } = useDocumentInfo();
|
||||
const [initCollapsed, setInitCollapsed] = useState<boolean>();
|
||||
const [collapsedOnMount, setCollapsedOnMount] = useState<boolean>();
|
||||
const [fieldPreferencesKey] = useState(() => `collapsible-${toKebabCase(label)}`);
|
||||
|
||||
const onToggle = useCallback(async (newCollapsedState: boolean) => {
|
||||
@@ -51,18 +52,18 @@ const CollapsibleField: React.FC<Props> = (props) => {
|
||||
useEffect(() => {
|
||||
const fetchInitialState = async () => {
|
||||
const preferences = await getPreference(preferencesKey);
|
||||
setInitCollapsed(Boolean(preferences?.fields?.[fieldPreferencesKey]?.collapsed));
|
||||
setCollapsedOnMount(Boolean(preferences?.fields?.[fieldPreferencesKey]?.collapsed ?? initCollapsed));
|
||||
};
|
||||
|
||||
fetchInitialState();
|
||||
}, [getPreference, preferencesKey, fieldPreferencesKey]);
|
||||
}, [getPreference, preferencesKey, fieldPreferencesKey, initCollapsed]);
|
||||
|
||||
if (typeof initCollapsed !== 'boolean') return null;
|
||||
if (typeof collapsedOnMount !== 'boolean') return null;
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Collapsible
|
||||
initCollapsed={initCollapsed}
|
||||
initCollapsed={collapsedOnMount}
|
||||
className={[
|
||||
'field-type',
|
||||
baseClass,
|
||||
|
||||
@@ -11,6 +11,7 @@ type SET_ALL = {
|
||||
data: { id?: string, blockType?: string }[]
|
||||
collapsedState?: string[]
|
||||
blockType?: string
|
||||
initCollapsed?: boolean
|
||||
}
|
||||
|
||||
type SET_COLLAPSE = {
|
||||
@@ -48,13 +49,13 @@ const reducer = (currentState: Row[], action: Action): Row[] => {
|
||||
|
||||
switch (action.type) {
|
||||
case 'SET_ALL': {
|
||||
const { data, collapsedState } = action;
|
||||
const { data, collapsedState, initCollapsed } = action;
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
return data.map((dataRow, i) => {
|
||||
const row = {
|
||||
id: dataRow?.id || new ObjectID().toHexString(),
|
||||
collapsed: (collapsedState || []).includes(dataRow?.id),
|
||||
collapsed: Array.isArray(collapsedState) ? collapsedState.includes(dataRow?.id) : initCollapsed,
|
||||
blockType: dataRow?.blockType,
|
||||
};
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ export const baseAdminFields = joi.object().keys({
|
||||
style: joi.object().unknown(),
|
||||
className: joi.string(),
|
||||
readOnly: joi.boolean().default(false),
|
||||
initCollapsed: joi.boolean().default(false),
|
||||
hidden: joi.boolean().default(false),
|
||||
disabled: joi.boolean().default(false),
|
||||
condition: joi.func(),
|
||||
|
||||
@@ -184,6 +184,9 @@ export type CollapsibleField = Omit<FieldBase, 'name'> & {
|
||||
type: 'collapsible';
|
||||
label: string
|
||||
fields: Field[];
|
||||
admin?: Admin & {
|
||||
initCollapsed?: boolean | false;
|
||||
}
|
||||
}
|
||||
|
||||
export type TabsAdmin = Omit<Admin, 'description'>;
|
||||
@@ -327,6 +330,9 @@ export type ArrayField = FieldBase & {
|
||||
maxRows?: number;
|
||||
labels?: Labels;
|
||||
fields: Field[];
|
||||
admin?: Admin & {
|
||||
initCollapsed?: boolean | false;
|
||||
}
|
||||
}
|
||||
|
||||
export type RadioField = FieldBase & {
|
||||
@@ -352,6 +358,10 @@ export type BlockField = FieldBase & {
|
||||
blocks: Block[];
|
||||
defaultValue?: unknown
|
||||
labels?: Labels
|
||||
admin?: Admin & {
|
||||
initCollapsed?: boolean | false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export type PointField = FieldBase & {
|
||||
|
||||
Reference in New Issue
Block a user