Skip to content

Commit

Permalink
EditSection refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
SKarolFolio committed Nov 22, 2024
1 parent 65d0731 commit 6df161b
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 144 deletions.
4 changes: 2 additions & 2 deletions src/common/hooks/useSearchNavigationState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import state from '@state';
export const useSearchNavigationState = () => {
const [searchParams] = useSearchParams();
const querySearchParam = searchParams.get(SearchQueryParams.Query);
const searchBySearchParam = searchParams.get(SearchQueryParams.SearchBy);
const searchBySearchParam = searchParams.get(SearchQueryParams.SearchBy) as SearchIdentifiers;
const offsetSearchParam = searchParams.get(SearchQueryParams.Offset);

const setNavigationState = useSetRecoilState(state.search.navigationState);

useEffect(() => {
const generatedState = generateSearchParamsState(
querySearchParam,
searchBySearchParam as SearchIdentifiers,
searchBySearchParam,
offsetSearchParam as unknown as number,
);

Expand Down
158 changes: 17 additions & 141 deletions src/components/EditSection/EditSection.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,19 @@
import { useEffect, memo, useCallback } from 'react';
import { useEffect, memo } from 'react';
import { useRecoilValue, useRecoilState } from 'recoil';
import { FormattedMessage } from 'react-intl';
import classNames from 'classnames';
import state from '@state';
import { applyUserValues } from '@common/helpers/profile.helper';
import { saveRecordLocally } from '@common/helpers/record.helper';
import { GROUP_COMPLEX_CUTOFF_LEVEL, PROFILE_BFIDS } from '@common/constants/bibframe.constants';
import { PROFILE_BFIDS } from '@common/constants/bibframe.constants';
import { AUTOSAVE_INTERVAL } from '@common/constants/storage.constants';
import { AdvancedFieldType } from '@common/constants/uiControls.constants';
import { EDIT_ALT_DISPLAY_LABELS, EDIT_SECTION_CONTAINER_ID } from '@common/constants/uiElements.constants';
import { EDIT_SECTION_CONTAINER_ID } from '@common/constants/uiElements.constants';
import { Fields } from '@components/Fields';
import { LiteralField } from '@components/LiteralField';
import { DropdownField } from '@components/DropdownField';
import { SimpleLookupField } from '@components/SimpleLookupField';
import { ComplexLookupField } from '@components/ComplexLookupField';
import { Prompt } from '@components/Prompt';
import { findParentEntryByProperty } from '@common/helpers/schema.helper';
import { FieldWithMetadataAndControls } from '@components/FieldWithMetadataAndControls';
import { useContainerEvents } from '@common/hooks/useContainerEvents';
import { useServicesContext } from '@common/hooks/useServicesContext';
import { Button, ButtonType } from '@components/Button';
import { drawComponentHOC } from './drawComponentHOC';
import './EditSection.scss';

export type IDrawComponent = {
schema: Map<string, SchemaEntry>;
entry: SchemaEntry;
disabledFields?: Schema;
level?: number;
isCompact?: boolean;
};

export const EditSection = memo(() => {
const { selectedEntriesService } = useServicesContext() as Required<ServicesParams>;
const resourceTemplates = useRecoilValue(state.config.selectedProfile)?.json.Profile.resourceTemplates;
Expand Down Expand Up @@ -78,131 +62,23 @@ export const EditSection = memo(() => {
}));
};

const handleGroupsCollapseExpand = () => setCollapsedEntries(collapsedEntries.size ? new Set([]) : collapsibleEntries);

const drawComponent = useCallback(
({ schema, entry, disabledFields, level = 0, isCompact = false }: IDrawComponent) => {
const { uuid, displayName = '', type, children, constraints } = entry;
const isDisabled = !!disabledFields?.get(uuid);
const displayNameWithAltValue = EDIT_ALT_DISPLAY_LABELS[displayName] || displayName;
const selectedUserValue = userValues[uuid];

if (type === AdvancedFieldType.block) {
return (
<FieldWithMetadataAndControls
entry={entry}
level={level}
isCompact={isCompact}
showLabel={false}
className="entity-heading"
>
<strong className="heading">{displayNameWithAltValue}</strong>
{!!collapsibleEntries.size && (
<Button className="toggle-expansion-button" type={ButtonType.Link} onClick={handleGroupsCollapseExpand}>
<FormattedMessage id={collapsedEntries.size ? 'ld.expandAll' : 'ld.collapseAll'} />
</Button>
)}
</FieldWithMetadataAndControls>
);
}

if (
(type === AdvancedFieldType.group || type === AdvancedFieldType.groupComplex) &&
level < GROUP_COMPLEX_CUTOFF_LEVEL
) {
const isComplexGroup = type === AdvancedFieldType.groupComplex;

return (
<FieldWithMetadataAndControls entry={entry} level={level} isCompact={isCompact} showLabel={isComplexGroup}>
{!isComplexGroup && <span className="group-label">{displayNameWithAltValue}</span>}
</FieldWithMetadataAndControls>
);
}

if (type === AdvancedFieldType.literal) {
return (
<FieldWithMetadataAndControls entry={entry} level={level} isCompact={isCompact}>
<LiteralField
uuid={uuid}
value={selectedUserValue?.contents[0].label}
onChange={onChange}
isDisabled={isDisabled}
/>
</FieldWithMetadataAndControls>
);
}

if (type === AdvancedFieldType.dropdown && children) {
const options = children
.map(id => schema.get(id))
.map(entry => ({
label: entry?.displayName ?? '',
value: entry?.uri ?? '', // TBD
uri: entry?.uri ?? '',
id: entry?.uuid,
}));

const selectedOption = options?.find(({ id }) => id && selectedEntries.includes(id));

const handleChange = (option: any) => {
selectedEntriesService.addNew(selectedOption?.id, option.id);

setSelectedEntries(selectedEntriesService.get());
};

return (
<FieldWithMetadataAndControls entry={entry} level={level} isCompact={isCompact}>
<DropdownField
options={options}
uuid={uuid}
onChange={handleChange}
value={selectedOption}
isDisabled={isDisabled || entry?.layout?.readOnly}
/>
</FieldWithMetadataAndControls>
);
}

if (type === AdvancedFieldType.simple) {
const blockEntry = findParentEntryByProperty({
schema,
path: entry.path,
key: 'type',
value: AdvancedFieldType.block,
});

return (
<FieldWithMetadataAndControls entry={entry} level={level} isCompact={isCompact}>
<SimpleLookupField
uri={constraints?.useValuesFrom[0] ?? ''}
uuid={uuid}
onChange={onChange}
parentUri={constraints?.valueDataType?.dataTypeURI}
value={selectedUserValue?.contents}
isDisabled={isDisabled}
propertyUri={entry.uri}
parentBlockUri={blockEntry?.uriBFLite}
/>
</FieldWithMetadataAndControls>
);
}

if (type === AdvancedFieldType.complex) {
return (
<FieldWithMetadataAndControls entry={entry} level={level} isCompact={isCompact}>
<ComplexLookupField entry={entry} onChange={onChange} value={selectedUserValue?.contents} />
</FieldWithMetadataAndControls>
);
}

return null;
},
[selectedEntries, collapsedEntries, schema],
);
const handleGroupsCollapseExpand = () =>
setCollapsedEntries(collapsedEntries.size ? new Set([]) : collapsibleEntries);

// Uncomment if it is needed to render certain groups of fields disabled, then use it as a prop in Fields component
// const disabledFields = useMemo(() => getAllDisabledFields(schema), [schema]);

const drawComponent = drawComponentHOC({
selectedEntriesService,
selectedEntries,
setSelectedEntries,
userValues,
collapsedEntries,
collapsibleEntries,
onChange,
handleGroupsCollapseExpand,
});

return resourceTemplates ? (
<div
id={EDIT_SECTION_CONTAINER_ID}
Expand Down
159 changes: 159 additions & 0 deletions src/components/EditSection/drawComponentHOC.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import { SetterOrUpdater } from 'recoil';
import { FormattedMessage } from 'react-intl';
import { GROUP_COMPLEX_CUTOFF_LEVEL } from '@common/constants/bibframe.constants';
import { AdvancedFieldType } from '@common/constants/uiControls.constants';
import { EDIT_ALT_DISPLAY_LABELS } from '@common/constants/uiElements.constants';
import { findParentEntryByProperty } from '@common/helpers/schema.helper';
import { Button, ButtonType } from '@components/Button';
import { ComplexLookupField } from '@components/ComplexLookupField';
import { DropdownField } from '@components/DropdownField';
import { FieldWithMetadataAndControls } from '@components/FieldWithMetadataAndControls';
import { LiteralField } from '@components/LiteralField';
import { SimpleLookupField } from '@components/SimpleLookupField';

export type IDrawComponent = {
schema: Map<string, SchemaEntry>;
entry: SchemaEntry;
disabledFields?: Schema;
level?: number;
isCompact?: boolean;
};

type DrawComponentProps = {
selectedEntriesService: ISelectedEntriesService;
selectedEntries: string[];
setSelectedEntries: SetterOrUpdater<string[]>;
userValues: UserValues;
collapsedEntries: Set<string>;
collapsibleEntries: Set<string>;
onChange: (uuid: string, contents: UserValueContents[]) => void;
handleGroupsCollapseExpand: VoidFunction;
}

export const drawComponentHOC =
({
selectedEntriesService,
selectedEntries,
setSelectedEntries,
userValues,
collapsedEntries,
collapsibleEntries,
onChange,
handleGroupsCollapseExpand,
}: DrawComponentProps) =>
({ schema, entry, disabledFields, level = 0, isCompact = false }: IDrawComponent) => {
const { uuid, displayName = '', type, children, constraints } = entry;
const isDisabled = !!disabledFields?.get(uuid);
const displayNameWithAltValue = EDIT_ALT_DISPLAY_LABELS[displayName] || displayName;
const selectedUserValue = userValues[uuid];

if (type === AdvancedFieldType.block) {
return (
<FieldWithMetadataAndControls
entry={entry}
level={level}
isCompact={isCompact}
showLabel={false}
className="entity-heading"
>
<strong className="heading">{displayNameWithAltValue}</strong>
{!!collapsibleEntries.size && (
<Button className="toggle-expansion-button" type={ButtonType.Link} onClick={handleGroupsCollapseExpand}>
<FormattedMessage id={collapsedEntries.size ? 'ld.expandAll' : 'ld.collapseAll'} />
</Button>
)}
</FieldWithMetadataAndControls>
);
}

if (
(type === AdvancedFieldType.group || type === AdvancedFieldType.groupComplex) &&
level < GROUP_COMPLEX_CUTOFF_LEVEL
) {
const isComplexGroup = type === AdvancedFieldType.groupComplex;

return (
<FieldWithMetadataAndControls entry={entry} level={level} isCompact={isCompact} showLabel={isComplexGroup}>
{!isComplexGroup && <span className="group-label">{displayNameWithAltValue}</span>}
</FieldWithMetadataAndControls>
);
}

if (type === AdvancedFieldType.literal) {
return (
<FieldWithMetadataAndControls entry={entry} level={level} isCompact={isCompact}>
<LiteralField
uuid={uuid}
value={selectedUserValue?.contents[0].label}
onChange={onChange}
isDisabled={isDisabled}
/>
</FieldWithMetadataAndControls>
);
}

if (type === AdvancedFieldType.dropdown && children) {
const options = children
.map(id => schema.get(id))
.map(entry => ({
label: entry?.displayName ?? '',
value: entry?.uri ?? '', // TBD
uri: entry?.uri ?? '',
id: entry?.uuid,
}));

const selectedOption = options?.find(({ id }) => id && selectedEntries.includes(id));

const handleChange = (option: any) => {
selectedEntriesService.addNew(selectedOption?.id, option.id);

setSelectedEntries(selectedEntriesService.get());
};

return (
<FieldWithMetadataAndControls entry={entry} level={level} isCompact={isCompact}>
<DropdownField
options={options}
uuid={uuid}
onChange={handleChange}
value={selectedOption}
isDisabled={isDisabled || entry?.layout?.readOnly}
/>
</FieldWithMetadataAndControls>
);
}

if (type === AdvancedFieldType.simple) {
const blockEntry = findParentEntryByProperty({
schema,
path: entry.path,
key: 'type',
value: AdvancedFieldType.block,
});

return (
<FieldWithMetadataAndControls entry={entry} level={level} isCompact={isCompact}>
<SimpleLookupField
uri={constraints?.useValuesFrom[0] ?? ''}
uuid={uuid}
onChange={onChange}
parentUri={constraints?.valueDataType?.dataTypeURI}
value={selectedUserValue?.contents}
isDisabled={isDisabled}
propertyUri={entry.uri}
parentBlockUri={blockEntry?.uriBFLite}
/>
</FieldWithMetadataAndControls>
);
}

if (type === AdvancedFieldType.complex) {
return (
<FieldWithMetadataAndControls entry={entry} level={level} isCompact={isCompact}>
<ComplexLookupField entry={entry} onChange={onChange} value={selectedUserValue?.contents} />
</FieldWithMetadataAndControls>
);
}

return null;
};
2 changes: 1 addition & 1 deletion src/components/EditSection/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { EditSection } from './EditSection';

export type { IDrawComponent } from './EditSection';
export type { IDrawComponent } from './drawComponentHOC';

0 comments on commit 6df161b

Please sign in to comment.