Skip to content

Commit

Permalink
feat: UILD-421: STORY: Multiple instances per Work (#48)
Browse files Browse the repository at this point in the history
* feat: UILD-421: STORY: Multiple instances per Work

* unit tests, unused code cleanup

* style and general fixes

* fix tests
  • Loading branch information
s3fs authored Dec 5, 2024
1 parent 6797821 commit e797005
Show file tree
Hide file tree
Showing 30 changed files with 682 additions and 159 deletions.
8 changes: 8 additions & 0 deletions src/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ body > #editor-root,
// font-size: 16px;
}

h2,
h3,
h4,
h5,
h6 {
margin: 0;
}

#app-root {
display: flex;
flex-direction: column;
Expand Down
20 changes: 16 additions & 4 deletions src/common/constants/bibframeMapping.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const BFLITE_URIS = {
CLASSIFICATION: 'http://bibfra.me/vocab/lite/classification',
PROVISION_ACTIVITY: 'https://bibfra.me/vocab/marc/provisionActivity',
TITLE: 'http://bibfra.me/vocab/marc/title',
TITLE_CONTAINER: 'http://bibfra.me/vocab/marc/Title',
MAIN_TITLE: 'http://bibfra.me/vocab/marc/mainTitle',
PRODUCTION: 'http://bibfra.me/vocab/marc/production',
PUBLICATION: 'http://bibfra.me/vocab/marc/publication',
Expand Down Expand Up @@ -215,29 +216,37 @@ export const BF_URIS = {
LABEL: 'http://www.w3.org/2000/01/rdf-schema#label',
};

export const INSTANCE_REF_KEY = "_instanceReference"
export const WORK_REF_KEY = "_workReference"

export const BLOCKS_BFLITE = {
INSTANCE: {
uri: BFLITE_URIS.INSTANCE,
referenceKey: '_instanceReference',
referenceKey: INSTANCE_REF_KEY,
resourceType: ResourceType.instance,
reference: {
key: '_workReference',
key: WORK_REF_KEY,
uri: BFLITE_URIS.WORK,
name: ResourceType.work,
},
},
WORK: {
uri: BFLITE_URIS.WORK,
referenceKey: '_workReference',
referenceKey: WORK_REF_KEY,
resourceType: ResourceType.work,
reference: {
key: '_instanceReference',
key: INSTANCE_REF_KEY,
uri: BFLITE_URIS.INSTANCE,
name: ResourceType.instance,
},
},
};

export const REF_TO_NAME = {
[INSTANCE_REF_KEY]: ResourceType.instance,
[WORK_REF_KEY]: ResourceType.work,
}

export const BFLITE_BFID_TO_BLOCK = {
'lc:RT:bf2:Monograph:Instance': BLOCKS_BFLITE.INSTANCE,
'lc:RT:bf2:Monograph:Work': BLOCKS_BFLITE.WORK,
Expand Down Expand Up @@ -609,6 +618,9 @@ export const TYPE_MAP = {

export const NEW_BF2_TO_BFLITE_MAPPING = {
[BFLITE_URIS.INSTANCE]: {
[BFLITE_URIS.INSTANCE]: {
container: { bf2Uri: 'http://id.loc.gov/ontologies/bibframe/Instance' }
},
'http://bibfra.me/vocab/marc/title': {
container: { bf2Uri: 'http://id.loc.gov/ontologies/bibframe/title' },
options: {
Expand Down
30 changes: 24 additions & 6 deletions src/common/helpers/record.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ import {
TYPE_URIS,
} from '@common/constants/bibframe.constants';
import { formatRecord } from './recordFormatting.helper';
import { BFLITE_URI_TO_BLOCK, BFLITE_URIS, BLOCKS_BFLITE } from '@common/constants/bibframeMapping.constants';
import {
BFLITE_URI_TO_BLOCK,
BFLITE_URIS,
BLOCKS_BFLITE,
REF_TO_NAME,
} from '@common/constants/bibframeMapping.constants';
import { ResourceType } from '@common/constants/record.constants';
import { QueryParams } from '@common/constants/routes.constants';
import { cloneDeep } from 'lodash';
Expand Down Expand Up @@ -216,7 +221,7 @@ export const getPreviewFieldsConditions = ({
schema,
isOnBranchWithUserValue,
altDisplayNames,
hideActions,
hideEntities,
isEntity,
forceRenderAllTopLevelEntities,
}: {
Expand All @@ -227,7 +232,7 @@ export const getPreviewFieldsConditions = ({
schema: Schema;
isOnBranchWithUserValue: boolean;
altDisplayNames?: Record<string, string>;
hideActions?: boolean;
hideEntities?: boolean;
isEntity: boolean;
forceRenderAllTopLevelEntities?: boolean;
}) => {
Expand All @@ -241,7 +246,7 @@ export const getPreviewFieldsConditions = ({
const isBranchEndWithoutValues = !selectedUserValues && isBranchEnd;
const isBranchEndWithValues = !!selectedUserValues;
const shouldRenderLabelOrPlaceholders =
(isPreviewable && isGroupable) ||
(!(isEntity && hideEntities) && isPreviewable && isGroupable) ||
type === AdvancedFieldType.dropdown ||
(isBranchEndWithValues && type !== AdvancedFieldType.complex) ||
isBranchEndWithoutValues;
Expand All @@ -257,7 +262,6 @@ export const getPreviewFieldsConditions = ({
const isBlock = level === GROUP_BY_LEVEL && shouldRenderLabelOrPlaceholders;
const isBlockContents = level === GROUP_CONTENTS_LEVEL;
const isInstance = bfid === PROFILE_BFIDS.INSTANCE;
const showEntityActions = !hideActions && isEntity;
const wrapEntities = forceRenderAllTopLevelEntities && isEntity;

return {
Expand All @@ -270,7 +274,21 @@ export const getPreviewFieldsConditions = ({
isBlock,
isBlockContents,
isInstance,
showEntityActions,
wrapEntities,
};
};

export const getRecordDependencies = (record?: RecordEntry | null) => {
if (!record) return;

const contents = unwrapRecordValuesFromCommonContainer(record);
const { block, reference } = getEditingRecordBlocks(contents);

if (block && reference) {
return {
keys: reference,
type: REF_TO_NAME[reference.key as keyof typeof REF_TO_NAME],
entries: contents[block][reference.key] as unknown as RecursiveRecordSchema[],
};
}
};
34 changes: 34 additions & 0 deletions src/common/helpers/recordFormatting.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
NON_BF_RECORD_ELEMENTS,
} from '@common/constants/bibframeMapping.constants';
import { getRecordPropertyData } from './record.helper';
import { Row } from '@components/Table';

export const formatRecord = ({
parsedRecord,
Expand Down Expand Up @@ -232,3 +233,36 @@ export const applyIntlToTemplates = ({
...rest,
template: Object.fromEntries(Object.entries(template).map(([k, v]) => [k, format({ id: v })])),
}));

export const formatDependeciesTable = (deps: Record<string, unknown>[]): Row[] => {
return deps.map(({ id, ...rest }) => {
const selectedPublication = (rest?.[BFLITE_URIS.PUBLICATION] as Record<string, unknown>)?.[0] as Record<
string,
unknown[]
>;
const selectedTitle = (rest?.[BFLITE_URIS.TITLE] as Record<string, unknown>)?.[0] as Record<
string,
Record<string, unknown[]>
>;

return {
__meta: {
id,
key: id,
...rest,
},
title: {
label: selectedTitle?.[BFLITE_URIS.TITLE_CONTAINER]?.[BFLITE_URIS.MAIN_TITLE]?.[0],
className: 'title',
},
publisher: {
label: selectedPublication?.[BFLITE_URIS.NAME]?.[0],
className: 'publisher',
},
pubDate: {
label: selectedPublication?.[BFLITE_URIS.DATE]?.[0],
className: 'publication-date',
},
};
}) as Row[];
};
47 changes: 29 additions & 18 deletions src/common/hooks/useConfig.hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,25 @@ import { useProcessedRecordAndSchema } from './useProcessedRecordAndSchema.hook'
import { useServicesContext } from './useServicesContext';

export type PreviewParams = {
noStateUpdate?: boolean;
singular?: boolean;
};

type GetProfiles = {
type IGetProfiles = {
record?: RecordEntry;
recordId?: string;
previewParams?: PreviewParams;
asClone?: boolean;
};

type IBuildSchema = {
profile: ProfileEntry;
templates: ResourceTemplates;
record: Record<string, unknown> | Array<unknown>;
asClone?: boolean;
noStateUpdate?: boolean;
};

export const useConfig = () => {
const { schemaCreatorService, userValuesService, selectedEntriesService } =
useServicesContext() as Required<ServicesParams>;
Expand Down Expand Up @@ -56,12 +65,7 @@ export const useConfig = () => {
return preparedFields;
};

const buildSchema = async (
profile: ProfileEntry,
templates: ResourceTemplates,
record: Record<string, unknown> | Array<unknown>,
asClone = false,
) => {
const buildSchema = async ({ profile, templates, record, asClone = false, noStateUpdate = false }: IBuildSchema) => {
const initKey = uuidv4();
const userValues: UserValues = {};

Expand All @@ -75,18 +79,21 @@ export const useConfig = () => {
record,
userValues,
asClone,
noStateUpdate,
});

setUserValues(updatedUserValues || userValues);
setInitialSchemaKey(initKey);
setSelectedEntries(selectedEntriesService.get());
setSchema(updatedSchema);
setSelectedRecordBlocks(selectedRecordBlocks);
if (!noStateUpdate) {
setUserValues(updatedUserValues || userValues);
setInitialSchemaKey(initKey);
setSelectedEntries(selectedEntriesService.get());
setSchema(updatedSchema);
setSelectedRecordBlocks(selectedRecordBlocks);
}

return { updatedSchema, initKey };
};

const getProfiles = async ({ record, recordId, previewParams, asClone }: GetProfiles): Promise<unknown> => {
const getProfiles = async ({ record, recordId, previewParams, asClone }: IGetProfiles): Promise<unknown> => {
if (isProcessingProfiles.current && (record || recordId)) return;

try {
Expand All @@ -102,16 +109,20 @@ export const useConfig = () => {
setProfiles(response);
}

setUserValues({});

const recordData = record?.resource || {};
const recordTitle = getRecordTitle(recordData as RecordEntry);
const entities = getPrimaryEntitiesFromRecord(record as RecordEntry);

if (selectedProfile) {
setSelectedProfile(selectedProfile);

const { updatedSchema, initKey } = await buildSchema(selectedProfile, templates, recordData, asClone);
!previewParams?.noStateUpdate && setSelectedProfile(selectedProfile);

const { updatedSchema, initKey } = await buildSchema({
profile: selectedProfile,
templates,
record: recordData,
asClone,
noStateUpdate: previewParams?.noStateUpdate,
});

if (previewParams && recordId) {
setPreviewContent(prev => [
Expand Down
5 changes: 3 additions & 2 deletions src/common/hooks/useProcessedRecordAndSchema.hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type IGetProcessedRecordAndSchema = {
record: Record<string, unknown> | Array<unknown>;
userValues: UserValues;
asClone?: boolean;
noStateUpdate?: boolean;
};

export const useProcessedRecordAndSchema = () => {
Expand All @@ -28,7 +29,7 @@ export const useProcessedRecordAndSchema = () => {
useServicesContext() as Required<ServicesParams>;

const getProcessedRecordAndSchema = useCallback(
async ({ baseSchema, record, userValues, asClone = false }: IGetProcessedRecordAndSchema) => {
async ({ baseSchema, record, userValues, asClone = false, noStateUpdate }: IGetProcessedRecordAndSchema) => {
let updatedSchema = baseSchema;
let updatedUserValues = userValues;
let selectedRecordBlocks = undefined;
Expand All @@ -52,7 +53,7 @@ export const useProcessedRecordAndSchema = () => {
})
: undefined;

setRecord(wrapRecordValuesWithCommonContainer(adjustedRecord));
!noStateUpdate && setRecord(wrapRecordValuesWithCommonContainer(adjustedRecord));
selectedRecordBlocks = { block, reference };
schemaWithDuplicatesService.set(baseSchema);
recordNormalizingService.init(adjustedRecord, block, reference);
Expand Down
5 changes: 4 additions & 1 deletion src/common/hooks/useRecordControls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type IBaseFetchRecord = {
cachedRecord?: RecordEntry;
idType?: ExternalResourceIdType;
errorMessage?: string;
previewParams?: PreviewParams;
};

export const useRecordControls = () => {
Expand Down Expand Up @@ -270,7 +271,7 @@ export const useRecordControls = () => {
}
};

const getRecordAndInitializeParsing = async ({ recordId, cachedRecord, idType, errorMessage }: IBaseFetchRecord) => {
const getRecordAndInitializeParsing = async ({ recordId, cachedRecord, idType, previewParams, errorMessage }: IBaseFetchRecord) => {
if (!recordId && !cachedRecord) return;

try {
Expand All @@ -279,6 +280,7 @@ export const useRecordControls = () => {
await getProfiles({
record: recordData,
recordId,
previewParams,
});

return recordData;
Expand Down Expand Up @@ -333,5 +335,6 @@ export const useRecordControls = () => {
fetchRecordAndSelectEntityValues,
fetchExternalRecordForPreview,
tryFetchExternalRecordForEdit,
getRecordAndInitializeParsing,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,8 @@ export class RecordToSchemaMappingService implements IRecordToSchemaMapping {

private readonly getSchemaEntries = (containerBf2Uri?: string, containerDataTypeUri?: string) => {
return this.schemaArray.filter((entry: SchemaEntry) => {
const hasTheSameUri = entry.uri === containerBf2Uri;
const hasTheSameDataTypeUri = containerDataTypeUri
const isOfSameUri = entry.uri === containerBf2Uri;
const isOfSameDataTypeUri = containerDataTypeUri
? entry.constraints?.valueDataType?.dataTypeURI === containerDataTypeUri
: true;
let hasBlockParent = false;
Expand All @@ -195,8 +195,7 @@ export class RecordToSchemaMappingService implements IRecordToSchemaMapping {
if (this.updatedSchema?.get(getParentEntryUuid(entry.path))?.type === AdvancedFieldTypeEnum.block) {
hasBlockParent = true;
}

return hasTheSameUri && hasTheSameDataTypeUri && hasProperBlock && hasBlockParent;
return isOfSameUri && isOfSameDataTypeUri && hasProperBlock && hasBlockParent;
});
};

Expand Down
Loading

0 comments on commit e797005

Please sign in to comment.