Skip to content

Commit

Permalink
UILD-462: Remove autosave feature (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
SKarolFolio authored Dec 24, 2024
1 parent cc8184b commit 61f2c27
Show file tree
Hide file tree
Showing 13 changed files with 314 additions and 337 deletions.
3 changes: 0 additions & 3 deletions src/common/constants/storage.constants.ts

This file was deleted.

8 changes: 0 additions & 8 deletions src/common/helpers/progressBackup.helper.ts

This file was deleted.

74 changes: 0 additions & 74 deletions src/common/helpers/record.helper.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import { AUTOCLEAR_TIMEOUT } from '@common/constants/storage.constants';
import { localStorageService } from '@common/services/storage';
import { generateRecordBackupKey } from './progressBackup.helper';
import {
GROUP_BY_LEVEL,
GROUP_CONTENTS_LEVEL,
Expand All @@ -9,7 +6,6 @@ import {
TITLE_CONTAINER_URIS,
TYPE_URIS,
} from '@common/constants/bibframe.constants';
import { formatRecord } from './recordFormatting.helper';
import {
BFLITE_URI_TO_BLOCK,
BFLITE_URIS,
Expand All @@ -35,76 +31,6 @@ export const getRecordId = (record: RecordEntry | null, selectedBlock?: string,
return previewBlock ? (record?.resource?.[block]?.[previewBlock] as any[])?.[0]?.id : record?.resource?.[block]?.id;
};

export const getRecordWithUpdatedID = (record: RecordEntry, id: RecordID) => ({
resource: {
...record.resource,
[TYPE_URIS.INSTANCE]: { ...record.resource[TYPE_URIS.INSTANCE], id },
},
});

export const deleteRecordLocally = (profile: string, recordId?: RecordID) => {
const storageKey = generateRecordBackupKey(profile, recordId);

localStorageService.delete(storageKey);
};

export const generateRecordData = (record: ParsedRecord) => {
return {
createdAt: new Date().getTime(),
data: record,
};
};

export const generateAndSaveRecord = (storageKey: string, record: ParsedRecord) => {
const newRecord = generateRecordData(record);

localStorageService.serialize(storageKey, newRecord);

return newRecord;
};

export const saveRecordLocally = ({
profile,
parsedRecord,
record,
selectedRecordBlocks,
}: {
profile: string;
parsedRecord: ParsedRecord;
record: RecordEntry | null;
selectedRecordBlocks?: SelectedRecordBlocks;
}) => {
if (!record) return;

const recordId = getRecordId(record) as string;
const storageKey = generateRecordBackupKey(profile, recordId);
const formattedRecord = formatRecord({ parsedRecord, record, selectedRecordBlocks });
const updatedRecord = getRecordWithUpdatedID(formattedRecord as RecordEntry, recordId);

return generateAndSaveRecord(storageKey, updatedRecord as ParsedRecord);
};

export const getSavedRecord = (profile: string, recordId?: RecordID): LocallySavedRecord | null => {
const storageKey = generateRecordBackupKey(profile, recordId);
const savedRecordData = localStorageService.deserialize(storageKey);

if (savedRecordData && !savedRecordData?.data) {
return generateAndSaveRecord(storageKey, savedRecordData);
}

return savedRecordData ? autoClearSavedData(savedRecordData, profile, recordId) : null;
};

export const autoClearSavedData = (savedRecordData: LocallySavedRecord, profile: string, recordId?: RecordID) => {
const shouldBeCleared = savedRecordData.createdAt + AUTOCLEAR_TIMEOUT <= new Date().getTime();

if (!shouldBeCleared) return savedRecordData;

deleteRecordLocally(profile, recordId);

return null;
};

export const checkIdentifierAsValue = (record: Record<string, string[]>, uri: string) => {
const identifierAsValueSelection = IDENTIFIER_AS_VALUE[uri];

Expand Down
57 changes: 23 additions & 34 deletions src/common/hooks/useRecordControls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,9 @@ import {
getGraphIdByExternalId,
getRecord,
} from '@common/api/records.api';
import { BibframeEntities, PROFILE_BFIDS } from '@common/constants/bibframe.constants';
import { BibframeEntities } from '@common/constants/bibframe.constants';
import { StatusType } from '@common/constants/status.constants';
import { DEFAULT_RECORD_ID } from '@common/constants/storage.constants';
import {
deleteRecordLocally,
getPrimaryEntitiesFromRecord,
getRecordId,
getSelectedRecordBlocks,
saveRecordLocally,
getSavedRecord,
} from '@common/helpers/record.helper';
import { getPrimaryEntitiesFromRecord, getRecordId, getSelectedRecordBlocks } from '@common/helpers/record.helper';
import { UserNotificationFactory } from '@common/services/userNotification';
import { PreviewParams, useConfig } from '@common/hooks/useConfig.hook';
import { formatRecord } from '@common/helpers/recordFormatting.helper';
Expand Down Expand Up @@ -53,8 +45,12 @@ export const useRecordControls = () => {
const { setSelectedProfile } = useProfileState();
const { setIsDuplicateImportedResourceModalOpen, setCurrentlyEditedEntityBfid, setCurrentlyPreviewedEntityBfid } =
useUIState();
const { setRecordStatus, setLastSavedRecordId, setIsRecordEdited: setIsEdited, addStatusMessagesItem } = useStatusState();
const profile = PROFILE_BFIDS.MONOGRAPH;
const {
setRecordStatus,
setLastSavedRecordId,
setIsRecordEdited: setIsEdited,
addStatusMessagesItem,
} = useStatusState();
const currentRecordId = getRecordId(record);
const { getProfiles } = useConfig();
const navigate = useNavigate();
Expand All @@ -66,12 +62,7 @@ export const useRecordControls = () => {
const { generateRecord } = useRecordGeneration();

const fetchRecord = async (recordId: string, previewParams?: PreviewParams) => {
const profile = PROFILE_BFIDS.MONOGRAPH;
const locallySavedData = getSavedRecord(profile, recordId);
const cachedRecord: RecordEntry | undefined =
locallySavedData && !previewParams ? (locallySavedData.data as RecordEntry) : undefined;

const recordData = await getRecordAndInitializeParsing({ recordId, cachedRecord });
const recordData = await getRecordAndInitializeParsing({ recordId });

if (!recordData) return;

Expand All @@ -98,7 +89,6 @@ export const useRecordControls = () => {
shouldSetSearchParams = true,
}: SaveRecordProps = {}) => {
const parsed = generateRecord();
const currentRecordId = record?.id;

if (!parsed) return;

Expand All @@ -113,14 +103,13 @@ export const useRecordControls = () => {
}) as RecordEntry;

const recordId = getRecordId(record, selectedRecordBlocks?.block);
const shouldPostRecord = !recordId || getRecordId(record) === DEFAULT_RECORD_ID || isClone;
const shouldPostRecord = !recordId || isClone;

const response = shouldPostRecord
? await postRecord(formattedRecord)
: await putRecord(recordId as string, formattedRecord);
const parsedResponse = await response.json();

deleteRecordLocally(profile, currentRecordId as RecordID);
dispatchUnblockEvent();
!asRefToNewRecord && setRecord(parsedResponse);

Expand Down Expand Up @@ -177,14 +166,6 @@ export const useRecordControls = () => {
}
};

const saveLocalRecord = () => {
const parsed = generateRecord();

if (!parsed) return;

return saveRecordLocally({ profile, parsedRecord: parsed, record, selectedRecordBlocks });
};

const clearRecordState = () => {
resetUserValues();
setRecord(null);
Expand All @@ -205,7 +186,6 @@ export const useRecordControls = () => {
if (!currentRecordId) return;

await deleteRecordRequest(currentRecordId as unknown as string);
deleteRecordLocally(profile, currentRecordId as unknown as string);
discardRecord();
addStatusMessagesItem?.(UserNotificationFactory.createMessage(StatusType.success, 'ld.rdDeleted'));

Expand All @@ -224,7 +204,9 @@ export const useRecordControls = () => {
const contents = record?.resource?.[uriSelector];

if (!contents) {
addStatusMessagesItem?.(UserNotificationFactory.createMessage(StatusType.error, 'ld.cantSelectReferenceContents'));
addStatusMessagesItem?.(
UserNotificationFactory.createMessage(StatusType.error, 'ld.cantSelectReferenceContents'),
);

return navigate(ROUTES.RESOURCE_CREATE.uri);
}
Expand All @@ -248,7 +230,13 @@ export const useRecordControls = () => {
}
};

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

try {
Expand All @@ -262,7 +250,9 @@ export const useRecordControls = () => {

return recordData;
} catch (_err) {
addStatusMessagesItem?.(UserNotificationFactory.createMessage(StatusType.error, errorMessage ?? 'ld.errorFetching'));
addStatusMessagesItem?.(
UserNotificationFactory.createMessage(StatusType.error, errorMessage ?? 'ld.errorFetching'),
);
}
};

Expand Down Expand Up @@ -301,7 +291,6 @@ export const useRecordControls = () => {
return {
fetchRecord,
saveRecord,
saveLocalRecord,
deleteRecord,
discardRecord,
clearRecordState,
Expand Down
4 changes: 1 addition & 3 deletions src/components/DeleteRecord/DeleteRecord.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { FC, memo } from 'react';
import { FormattedMessage } from 'react-intl';
import { DEFAULT_RECORD_ID } from '@common/constants/storage.constants';
import { useRecordControls } from '@common/hooks/useRecordControls';
import { ModalDeleteRecord } from '@components/ModalDeleteRecord';
import { useModalControls } from '@common/hooks/useModalControls';
import { getRecordId } from '@common/helpers/record.helper';
import { useRoutePathPattern } from '@common/hooks/useRoutePathPattern';
import { RESOURCE_URLS } from '@common/constants/routes.constants';
import { checkButtonDisabledState } from '@common/helpers/recordControls.helper';
Expand All @@ -21,7 +19,7 @@ const DeleteRecord: FC = () => {
const { hasBeenSaved } = useRecordStatus();
const isDisabledForEditPage =
checkButtonDisabledState({ resourceRoutePattern, isInitiallyLoaded: !hasBeenSaved, isEdited }) || false;
const isDisabled = !record || getRecordId(record) === DEFAULT_RECORD_ID || isDisabledForEditPage;
const isDisabled = !record || isDisabledForEditPage;

return (
<>
Expand Down
29 changes: 2 additions & 27 deletions src/components/EditSection/EditSection.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import { useEffect, memo, useRef } from 'react';
import { memo, useRef } from 'react';
import { debounce } from 'lodash';
import classNames from 'classnames';
import { saveRecordLocally } from '@common/helpers/record.helper';
import { PROFILE_BFIDS } from '@common/constants/bibframe.constants';
import { AUTOSAVE_INTERVAL } from '@common/constants/storage.constants';
import { EDIT_SECTION_CONTAINER_ID } from '@common/constants/uiElements.constants';
import { Fields } from '@components/Fields';
import { Prompt } from '@components/Prompt';
import { useContainerEvents } from '@common/hooks/useContainerEvents';
import { useServicesContext } from '@common/hooks/useServicesContext';
import { useRecordGeneration } from '@common/hooks/useRecordGeneration';
import { useInputsState, useProfileState, useStatusState, useUIState } from '@src/store';
import { renderDrawComponent } from './renderDrawComponent';
import './EditSection.scss';
Expand All @@ -20,34 +17,12 @@ export const EditSection = memo(() => {
const { selectedEntriesService } = useServicesContext() as Required<ServicesParams>;
const { selectedProfile, initialSchemaKey } = useProfileState();
const resourceTemplates = selectedProfile?.json.Profile.resourceTemplates;
const { userValues, addUserValuesItem, selectedRecordBlocks, record, selectedEntries, setSelectedEntries } =
useInputsState();
const { userValues, addUserValuesItem, selectedEntries, setSelectedEntries } = useInputsState();
const { isRecordEdited: isEdited, setIsRecordEdited: setIsEdited } = useStatusState();
const { collapsedEntries, setCollapsedEntries, collapsibleEntries, currentlyEditedEntityBfid } = useUIState();
const { generateRecord } = useRecordGeneration();

useContainerEvents({ watchEditedState: true });

useEffect(() => {
if (!isEdited) return;

const autoSaveRecord = setInterval(() => {
try {
const parsed = generateRecord();

if (!parsed) return;

const profile = PROFILE_BFIDS.MONOGRAPH;

saveRecordLocally({ profile, parsedRecord: parsed, record, selectedRecordBlocks });
} catch (error) {
console.error('Unable to automatically save changes:', error);
}
}, AUTOSAVE_INTERVAL);

return () => clearInterval(autoSaveRecord);
}, [isEdited, userValues]);

const debouncedAddUserValues = useRef(
debounce((value: UserValues) => {
addUserValuesItem?.(value);
Expand Down
2 changes: 0 additions & 2 deletions src/test/__mocks__/common/hooks/useRecordControls.mock.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export const saveRecord = jest.fn();
export const saveRecordLocally = jest.fn();
export const discardRecord = jest.fn();
export const fetchRecord = jest.fn();
export const clearRecordState = jest.fn();
Expand All @@ -13,7 +12,6 @@ jest.mock('@common/hooks/useRecordControls', () => ({
discardRecord,
fetchRecord,
clearRecordState,
saveRecordLocally,
fetchRecordAndSelectEntityValues,
fetchExternalRecordForPreview,
getRecordAndInitializeParsing,
Expand Down
31 changes: 0 additions & 31 deletions src/test/__tests__/common/helpers/progressBackup.helper.test.ts

This file was deleted.

Loading

0 comments on commit 61f2c27

Please sign in to comment.