Skip to content

Commit

Permalink
Add restore narrative function.
Browse files Browse the repository at this point in the history
  • Loading branch information
dakotablair committed Sep 13, 2023
1 parent 3866202 commit c6d3fab
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 30 deletions.
14 changes: 13 additions & 1 deletion src/common/api/narrativeService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,26 @@ const narrativeService = dynamicService({

export interface NarrativeServiceParams {
getStatus: void;
restoreNarrative: { objId: number; version: number; wsId: number };
}

interface NarrativeServiceResults {
getStatus: unknown;
restoreNarrative: unknown;
}

export const narrativeServiceApi = baseApi.injectEndpoints({
endpoints: (builder) => ({
restoreNarrative: builder.mutation<
NarrativeServiceResults['restoreNarrative'],
NarrativeServiceParams['restoreNarrative']
>({
query: ({ objId, version, wsId }) =>
narrativeService({
method: 'NarrativeService.revert_narrative_object',
params: [{ ver: version, objid: objId, wsid: wsId }],
}),
}),
getStatus: builder.query<
NarrativeServiceResults['getStatus'],
NarrativeServiceParams['getStatus']
Expand All @@ -30,4 +42,4 @@ export const narrativeServiceApi = baseApi.injectEndpoints({
}),
});

export const { getStatus } = narrativeServiceApi.endpoints;
export const { getStatus, restoreNarrative } = narrativeServiceApi.endpoints;
4 changes: 2 additions & 2 deletions src/common/api/workspaceApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type TimeParams = (
);

interface wsParams {
deleteWorkspace: { reqId?: number | string; wsId: number };
deleteWorkspace: { wsId: number };
getwsNarrative: { upa: string };
getwsObjectByName: { upa: string };
getwsPermissions: { wsId: number };
Expand Down Expand Up @@ -103,7 +103,7 @@ const wsApi = baseApi.injectEndpoints({
wsResults['deleteWorkspace'],
wsParams['deleteWorkspace']
>({
query: ({ wsId, reqId }) =>
query: ({ wsId }) =>
ws({
method: 'Workspace.delete_workspace',
params: [{ id: wsId }],
Expand Down
9 changes: 1 addition & 8 deletions src/features/navigator/NarrativeControl/Delete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,7 @@ import {
getParams,
} from '../../../features/params/paramsSlice';
import { deleteNarrative, loading, setLoading } from '../navigatorSlice';
import { ControlProps } from './common';

const ErrorMessage: FC<{ err: unknown }> = ({ err }) => (
<>
<span>There was an error! Guru meditation:</span>
<span>{JSON.stringify(err)}</span>
</>
);
import { ControlProps, ErrorMessage } from './common';

export const Delete: FC<ControlProps> = ({ narrativeDoc, modalClose }) => {
const dispatch = useAppDispatch();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Tests for <NarrativeControl />

import { render, screen } from '@testing-library/react';
import { MemoryRouter as Router } from 'react-router-dom';
import { noOp } from '../../common';
import { testNarrativeDoc } from '../fixtures';
import {
Expand Down Expand Up @@ -62,11 +63,13 @@ describe('The <Rename /> component...', () => {
describe('The <Restore /> component...', () => {
test('renders.', () => {
const { container } = render(
<RestoreTemplate
modalClose={noOp}
narrativeDoc={testNarrativeDoc}
version={1}
/>
<Router>
<RestoreTemplate
modalClose={noOp}
narrativeDoc={testNarrativeDoc}
version={1}
/>
</Router>
);
expect(container).toBeTruthy();
expect(screen.getByText('Reverting', { exact: false })).toBeInTheDocument();
Expand Down
58 changes: 50 additions & 8 deletions src/features/navigator/NarrativeControl/Restore.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,71 @@
/* NarrativeControl/Restore */
import { FC } from 'react';
import toast from 'react-hot-toast';
import { useNavigate } from 'react-router-dom';
import { restoreNarrative } from '../../../common/api/narrativeService';
import { isKBaseBaseQueryError } from '../../../common/api/utils/common';
import { parseError } from '../../../common/api/utils/parseError';
import { Button } from '../../../common/components';
import { useAppDispatch } from '../../../common/hooks';
import { useAppDispatch, useAppSelector } from '../../../common/hooks';
import { NarrativeDoc } from '../../../common/types/NarrativeDoc';
import { TODOAddLoadingState } from '../common';
import { restoreNarrative } from '../navigatorSlice';
import { getParams } from '../../../features/params/paramsSlice';
import { generateNavigatorPath } from '../common';
import { categorySelected } from '../navigatorSlice';
import { ErrorMessage } from './common';
import {
restoreNarrative as restoreAction,
setLoading,
} from '../navigatorSlice';

export const Restore: FC<{
modalClose: () => void;
narrativeDoc: NarrativeDoc;
version: number;
}> = ({ modalClose, narrativeDoc, version }) => {
/* hooks */
const dispatch = useAppDispatch();
const wsId = narrativeDoc.access_group;
const navigate = useNavigate();
const categorySet = useAppSelector(categorySelected);
const params = useAppSelector(getParams);
const [restoreTrigger] = restoreNarrative.useMutation();
/* derived values */
const categoryPath = categorySet !== 'own' ? categorySet : '';
const { access_group: wsId, obj_id: objId } = narrativeDoc;
const message = `Restored version ${version} of object ${objId} in ${wsId}.`;
/* restore narrative callback */
const restoreHandler = async () => {
await TODOAddLoadingState();
dispatch(restoreNarrative({ version, wsId }));
modalClose();
dispatch(restoreAction({ objId, version, wsId }));
try {
await restoreTrigger({ objId, version, wsId }).unwrap();
dispatch(setLoading(false));
} catch (err) {
if (!isKBaseBaseQueryError(err)) {
console.error({ err }); // eslint-disable-line no-console
toast(ErrorMessage({ err }));
return;
}
toast(ErrorMessage({ err: parseError(err) }));
dispatch(setLoading(false));
return;
}
toast(message);
navigate(
generateNavigatorPath({
id: wsId.toString(),
obj: objId.toString(),
ver: version.toString(),
categoryPath,
...params,
})
);
};

/* Restore component */
return (
<>
<p>
Reverting a narrative will create a new version identical to
{`v${narrativeDoc.version}`}.
{` v${version}`}.
</p>

<p>
Expand Down
8 changes: 8 additions & 0 deletions src/features/navigator/NarrativeControl/common.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { FC } from 'react';
import { NarrativeDoc } from '../../../common/types/NarrativeDoc';

export interface ControlProps {
narrativeDoc: NarrativeDoc;
modalClose: () => void;
}

export const ErrorMessage: FC<{ err: unknown }> = ({ err }) => (
<>
<span>There was an error! Guru meditation:</span>
<span>{JSON.stringify(err)}</span>
</>
);
7 changes: 4 additions & 3 deletions src/features/navigator/RefreshButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,25 @@ import {
setSynchronized,
} from './navigatorSlice';

const delaySeconds = AUTOMATIC_REFRESH_DELAY / 1000;
const RefreshButton: FC = () => {
const [count, setCount] = useState(5);
const [count, setCount] = useState(delaySeconds);
const dispatch = useAppDispatch();
const syncd = useAppSelector(synchronized);
const syncdLast = useAppSelector(synchronizedLast);

const refreshHandler = useCallback(() => {
dispatch(clearCacheAction);
dispatch(setSynchronized(true));
setCount(5);
setCount(delaySeconds);
}, [dispatch]);

useEffect(() => {
const now = Date.now();
const age = now - syncdLast;
if (!syncd && age > AUTOMATIC_REFRESH_DELAY) {
if (count > 0) {
setCount(count - 1);
setCount(Math.max(count - 1, 0));
return;
}
refreshHandler();
Expand Down
2 changes: 1 addition & 1 deletion src/features/navigator/common.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Cell } from '../../common/types/NarrativeDoc';
import { generatePathWithSearchParams } from '../../features/params/paramsSlice';

export const AUTOMATIC_REFRESH_DELAY = 5000;
export const AUTOMATIC_REFRESH_DELAY = 15000;

// Narrative and Navigator paths
export const narrativeURL = (wsId: number | string) =>
Expand Down
7 changes: 5 additions & 2 deletions src/features/navigator/navigatorSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,13 @@ export const navigatorSlice = createSlice({
},
restoreNarrative: (
state,
action: PayloadAction<{ version: number; wsId: number }>
action: PayloadAction<{ objId: number; version: number; wsId: number }>
) => {
const message = `Restore version ${action.payload.version} of ${action.payload.wsId}.`;
const { objId, version, wsId } = action.payload;
const message = `Restore version ${version} of narrative object ${objId} in ${wsId}.`;
console.log(message); // eslint-disable-line no-console
state.synchronizedLast = Date.now();
state.synchronized = false;
},
select: (state, action: PayloadAction<NavigatorState['selected']>) => {
state.selected = action.payload;
Expand Down

0 comments on commit c6d3fab

Please sign in to comment.