Skip to content

Commit

Permalink
Add rename narrative function.
Browse files Browse the repository at this point in the history
  • Loading branch information
dakotablair committed Sep 14, 2023
1 parent c6d3fab commit 1c579bf
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 19 deletions.
17 changes: 15 additions & 2 deletions src/common/api/narrativeService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,28 @@ const narrativeService = dynamicService({

export interface NarrativeServiceParams {
getStatus: void;
renameNarrative: { nameNew: string; narrativeRef: string };
restoreNarrative: { objId: number; version: number; wsId: number };
}

interface NarrativeServiceResults {
getStatus: unknown;
getStatus: { state: string }[];
renameNarrative: unknown;
restoreNarrative: unknown;
}

export const narrativeServiceApi = baseApi.injectEndpoints({
endpoints: (builder) => ({
renameNarrative: builder.mutation<
NarrativeServiceResults['renameNarrative'],
NarrativeServiceParams['renameNarrative']
>({
query: ({ narrativeRef, nameNew }) =>
narrativeService({
method: 'NarrativeService.rename_narrative',
params: [{ narrative_ref: narrativeRef, new_name: nameNew }],
}),
}),
restoreNarrative: builder.mutation<
NarrativeServiceResults['restoreNarrative'],
NarrativeServiceParams['restoreNarrative']
Expand All @@ -42,4 +54,5 @@ export const narrativeServiceApi = baseApi.injectEndpoints({
}),
});

export const { getStatus, restoreNarrative } = narrativeServiceApi.endpoints;
export const { getStatus, renameNarrative, restoreNarrative } =
narrativeServiceApi.endpoints;
10 changes: 6 additions & 4 deletions src/common/components/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ import { v4 as uuidv4 } from 'uuid';
import classes from './Input.module.scss';

interface InputInterface extends ComponentProps<'input'> {
label?: ReactElement;
errors?: boolean;
label?: ReactElement;
maxLength?: number;
validated?: boolean;
}

export const Input = forwardRef<HTMLInputElement, InputInterface>(
(props, ref) => {
const { className, errors, validated, label, ...rest } = props;
const { className, errors, label, maxLength, validated, ...rest } = props;
const { name } = rest; // react-hook-form internals
const idForLabel = useMemo(() => `input-${uuidv4()}`, []);
const statusClass = errors ? classes.error : classes.success;
Expand Down Expand Up @@ -60,9 +61,10 @@ export const Input = forwardRef<HTMLInputElement, InputInterface>(
{...rest}
className={classes.input}
id={idForLabel}
type={'text'}
onFocus={handleFocus}
maxLength={maxLength}
onBlur={handleBlur}
onFocus={handleFocus}
type={'text'}
/>
</span>
);
Expand Down
56 changes: 50 additions & 6 deletions src/features/navigator/NarrativeControl/Rename.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
/* NarrativeControl/Rename */
import { FC } from 'react';
import { useForm } from 'react-hook-form';
import toast from 'react-hot-toast';
import { isKBaseBaseQueryError } from '../../../common/api/utils/common';
import { parseError } from '../../../common/api/utils/parseError';
import { renameNarrative } from '../../../common/api/narrativeService';
import { Button } from '../../../common/components';
import {
inputRegisterFactory,
Expand All @@ -9,8 +13,8 @@ import {
import { Input } from '../../../common/components/Input';
import { useAppDispatch } from '../../../common/hooks';
import { NarrativeDoc } from '../../../common/types/NarrativeDoc';
import { TODOAddLoadingState } from '../common';
import { renameNarrative } from '../navigatorSlice';
import { renameNarrative as renameAction, setLoading } from '../navigatorSlice';
import { ErrorMessage } from './common';

interface RenameValues {
narrativeRenameName: string;
Expand All @@ -20,39 +24,79 @@ export const Rename: FC<{
narrativeDoc: NarrativeDoc;
modalClose: () => void;
}> = ({ narrativeDoc, modalClose }) => {
/* hooks */
const dispatch = useAppDispatch();
const { formState, getValues, register } = useForm<RenameValues>({
defaultValues: {
narrativeRenameName: narrativeDoc.narrative_title,
},
mode: 'all',
});
const [renameTrigger] = renameNarrative.useMutation();
/* derived values */
const { access_group: wsId, obj_id: objId } = narrativeDoc;
const inputRegister = inputRegisterFactory<RenameValues>({
formState,
register,
});
const errors = formState.errors;
const errorEntries = Object.entries(errors);
const formInvalid = errorEntries.length > 0;
/* rename narrative callback */
const renameNarrativeHandler = async () => {
const { narrativeRenameName: name } = getValues();
await TODOAddLoadingState();
dispatch(renameNarrative({ wsId: narrativeDoc.access_group, name }));
const message = `Rename ${wsId} to ${name}.`;
modalClose();
dispatch(renameAction({ wsId: narrativeDoc.access_group, name }));
try {
await renameTrigger({
narrativeRef: `${wsId}/${objId}`,
nameNew: name,
}).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);
};
return (
<>
<p>Rename Narrative</p>
<p>Enter a new name for the Narrative:</p>

<div>
{formInvalid ? (
<>
Errors:
<ul>
{Object.entries(errors).map(([name, err]) => (
<li key={name}>{err.message}</li>
))}
</ul>
</>
) : (
<></>
)}
<Input
label={<>New Narrative Title</>}
maxLength={MAX_WS_METADATA_VALUE_SIZE}
{...inputRegister('narrativeRenameName', {
maxLength: {
value: MAX_WS_METADATA_VALUE_SIZE,
message: 'too long',
message: 'The selected name is too long.',
},
})}
/>
<Button onClick={renameNarrativeHandler}>OK</Button>
<Button disabled={formInvalid} onClick={renameNarrativeHandler}>
OK
</Button>
<Button onClick={modalClose}>Cancel</Button>
</div>
</>
Expand Down
2 changes: 1 addition & 1 deletion src/features/navigator/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ export const useNarrativeServiceStatus = () => {
useEffect(() => {
if (nsQuery.isSuccess && nsQuery.data) {
const data = nsQuery.data;
console.log({ data }); // eslint-disable-line no-console
console.log(`NarrativeService status: ${data[0].state}`); // eslint-disable-line no-console
}
}, [nsQuery.data, nsQuery.isSuccess]);
};
Expand Down
10 changes: 4 additions & 6 deletions src/features/navigator/navigatorSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,17 +117,15 @@ export const navigatorSlice = createSlice({
state,
action: PayloadAction<{ name: string; wsId: number }>
) => {
const { name, wsId } = action.payload;
const message = `Rename ${wsId} to ${name}.`;
console.log(message); // eslint-disable-line no-console
// For now, wait until the page refreshes to reflect the changes.
state.synchronizedLast = Date.now();
state.synchronized = false;
},
restoreNarrative: (
state,
action: PayloadAction<{ objId: number; version: number; wsId: number }>
) => {
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
// For now, wait until the page refreshes to reflect the changes.
state.synchronizedLast = Date.now();
state.synchronized = false;
},
Expand Down

0 comments on commit 1c579bf

Please sign in to comment.