Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/library-authoring/common/context/SidebarContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import { useStateWithUrlSearchParam } from '../../../hooks';
import { useComponentPickerContext } from './ComponentPickerContext';
import { useLibraryContext } from './LibraryContext';
import { useRunOnNextRender } from '@src/utils';

Check failure on line 13 in src/library-authoring/common/context/SidebarContext.tsx

View workflow job for this annotation

GitHub Actions / tests

`@src/utils` import should occur before import of `../../../hooks`

export enum SidebarBodyItemId {
AddContent = 'add-content',
Expand Down Expand Up @@ -124,19 +125,22 @@
const [defaultTab, setDefaultTab] = useState<DefaultTabs>(DEFAULT_TAB);
const [hiddenTabs, setHiddenTabs] = useState<Array<SidebarInfoTab>>([]);

const [sidebarTab, setSidebarTab] = useStateWithUrlSearchParam<SidebarInfoTab>(
const [sidebarTab, setSidebarTabInternal] = useStateWithUrlSearchParam<SidebarInfoTab>(
defaultTab.component,
'st',
(value: string) => toSidebarInfoTab(value),
(value: SidebarInfoTab) => value.toString(),
);
const setSidebarTab = useRunOnNextRender((tab: SidebarInfoTab) => setSidebarTabInternal(tab));

const [sidebarAction, setSidebarAction] = useStateWithUrlSearchParam<SidebarActions>(
const [sidebarAction, setSidebarActionInternal] = useStateWithUrlSearchParam<SidebarActions>(
SidebarActions.None,
'sa',
(value: string) => Object.values(SidebarActions).find((enumValue) => value === enumValue),
(value: SidebarActions) => value.toString(),
);
const setSidebarAction = useRunOnNextRender((action: SidebarActions) => setSidebarActionInternal(action));

const resetSidebarAction = useCallback(() => {
setSidebarAction(SidebarActions.None);
}, [setSidebarAction]);
Expand Down
17 changes: 2 additions & 15 deletions src/library-authoring/components/ComponentMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import ComponentDeleter from './ComponentDeleter';
import messages from './messages';
import { useLibraryRoutes } from '../routes';
import { useRunOnNextRender } from '../../utils';

export const ComponentMenu = ({ usageKey }: { usageKey: string }) => {
const intl = useIntl();
Expand All @@ -34,7 +33,7 @@

const {
sidebarItemInfo,
openComponentInfoSidebar,

Check failure on line 36 in src/library-authoring/components/ComponentMenu.tsx

View workflow job for this annotation

GitHub Actions / tests

'openComponentInfoSidebar' is assigned a value but never used
closeLibrarySidebar,
setSidebarAction,
} = useSidebarContext();
Expand Down Expand Up @@ -95,21 +94,9 @@
openComponentEditor(usageKey);
}, [usageKey, navigateTo]);

const scheduleJumpToCollection = useRunOnNextRender(() => {
// TODO: Ugly hack to make sure sidebar shows add to collection section
// This needs to run after all changes to url takes place to avoid conflicts.
setTimeout(() => setSidebarAction(SidebarActions.JumpToManageCollections), 250);
});

const showManageCollections = useCallback(() => {
navigateTo({ selectedItemId: usageKey });
scheduleJumpToCollection();
}, [
scheduleJumpToCollection,
openComponentInfoSidebar,
usageKey,
navigateTo,
]);
navigateTo({ selectedItemId: usageKey }, () => setSidebarAction(SidebarActions.JumpToManageCollections));
}, [usageKey, setSidebarAction, navigateTo]);

return (
<Dropdown id="component-card-dropdown">
Expand Down
12 changes: 2 additions & 10 deletions src/library-authoring/components/ContainerCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import AddComponentWidget from './AddComponentWidget';
import BaseCard from './BaseCard';
import messages from './messages';
import ContainerDeleter from './ContainerDeleter';
import { useRunOnNextRender } from '../../utils';

type ContainerMenuProps = {
containerKey: string;
Expand Down Expand Up @@ -56,16 +55,9 @@ export const ContainerMenu = ({ containerKey, displayName } : ContainerMenuProps
});
};

const scheduleJumpToCollection = useRunOnNextRender(() => {
// TODO: Ugly hack to make sure sidebar shows add to collection section
// This needs to run after all changes to url takes place to avoid conflicts.
setTimeout(() => setSidebarAction(SidebarActions.JumpToManageCollections));
});

const showManageCollections = useCallback(() => {
navigateTo({ selectedItemId: containerKey });
scheduleJumpToCollection();
}, [scheduleJumpToCollection, navigateTo, containerKey]);
navigateTo({ selectedItemId: containerKey }, () => setSidebarAction(SidebarActions.JumpToManageCollections));
}, [navigateTo, containerKey]);

const openContainer = useCallback(() => {
navigateTo({ containerId: containerKey });
Expand Down
26 changes: 23 additions & 3 deletions src/library-authoring/routes.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
/**
* Constants and utility hook for the Library Authoring routes.
*/
import { useCallback, useMemo } from 'react';
import {
useCallback,
useMemo,
useState,
useRef,
useEffect,
} from 'react';
import {
generatePath,
matchPath,
useParams,
useLocation,
useNavigate,
useSearchParams,
useNavigation,
type PathMatch,
} from 'react-router-dom';
import { ContainerType, getBlockType } from '../generic/key-utils';
Expand Down Expand Up @@ -76,14 +83,17 @@ export type LibraryRoutesData = {
* This function can be mutated if there are changes in the current route, so always include
* it in the dependencies array if used on a `useCallback`.
*/
navigateTo: (dict?: NavigateToData) => void;
navigateTo: (dict?: NavigateToData, callback?: () => void) => void;
};

export const useLibraryRoutes = (): LibraryRoutesData => {
const { pathname } = useLocation();
const params = useParams();
const [searchParams] = useSearchParams();
const navigate = useNavigate();
const navigation = useNavigation();
const [hasNavigated, setHasNavigated] = useState(false);
const navigationCallbackRef = useRef<() => void>();

const insideCollection = matchPath(BASE_ROUTE + ROUTES.COLLECTION, pathname);
const insideCollections = matchPath(BASE_ROUTE + ROUTES.COLLECTIONS, pathname);
Expand Down Expand Up @@ -119,7 +129,7 @@ export const useLibraryRoutes = (): LibraryRoutesData => {
collectionId,
containerId,
contentType,
}: NavigateToData = {}) => {
}: NavigateToData = {}, callback?: () => void) => {
const routeParams = {
...params,
// Overwrite the params with the provided values.
Expand Down Expand Up @@ -237,6 +247,8 @@ export const useLibraryRoutes = (): LibraryRoutesData => {
pathname: newPath,
search: searchParams.toString(),
});
navigationCallbackRef.current = callback;
setHasNavigated(true);
}
}, [
navigate,
Expand All @@ -245,6 +257,14 @@ export const useLibraryRoutes = (): LibraryRoutesData => {
pathname,
]);

useEffect(() => {
if (hasNavigated && navigation.state === 'idle') {
navigationCallbackRef.current?.();
navigationCallbackRef.current = undefined;
setHasNavigated(false);
}
}, [navigation.state, hasNavigated]);

return useMemo(() => ({
navigateTo,
insideCollection,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import { ContainerMenu } from '../components/ContainerCard';
import { useLibraryRoutes } from '../routes';
import { SidebarActions, useSidebarContext } from '../common/context/SidebarContext';
import { useRunOnNextRender } from '../../utils';

interface LibraryContainerChildrenProps {
containerKey: string;
Expand Down Expand Up @@ -60,17 +59,9 @@
}
};

/* istanbul ignore next */
const scheduleJumpToTags = useRunOnNextRender(() => {
// TODO: Ugly hack to make sure sidebar shows manage tags section
// This needs to run after all changes to url takes place to avoid conflicts.
setTimeout(() => setSidebarAction(SidebarActions.JumpToManageTags), 250);
});

const jumpToManageTags = () => {
navigateTo({ selectedItemId: container.originalId });
scheduleJumpToTags();
};
const jumpToManageTags = useCallback(() => {
navigateTo({ selectedItemId: container.originalId }, () => setSidebarAction(SidebarActions.JumpToManageTags))

Check failure on line 63 in src/library-authoring/section-subsections/LibraryContainerChildren.tsx

View workflow job for this annotation

GitHub Actions / tests

Missing semicolon
}, [navigateTo, container.originalId, setSidebarAction]);

return (
<>
Expand Down
11 changes: 1 addition & 10 deletions src/library-authoring/units/LibraryUnitBlocks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import messages from './messages';
import { SidebarActions, useSidebarContext } from '../common/context/SidebarContext';
import { ToastContext } from '../../generic/toast-context';
import { canEditComponent } from '../components/ComponentEditorModal';
import { useRunOnNextRender } from '../../utils';

/** Components that need large min height in preview */
const LARGE_COMPONENTS = [
Expand Down Expand Up @@ -75,17 +74,9 @@ const BlockHeader = ({ block, readOnly }: ComponentBlockProps) => {
}
};

/* istanbul ignore next */
const scheduleJumpToTags = useRunOnNextRender(() => {
// TODO: Ugly hack to make sure sidebar shows manage tags section
// This needs to run after all changes to url takes place to avoid conflicts.
setTimeout(() => setSidebarAction(SidebarActions.JumpToManageTags), 250);
});

/* istanbul ignore next */
const jumpToManageTags = () => {
navigateTo({ selectedItemId: block.originalId });
scheduleJumpToTags();
navigateTo({ selectedItemId: block.originalId }, () => setSidebarAction(SidebarActions.JumpToManageTags));
};

return (
Expand Down
18 changes: 15 additions & 3 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { useState, useContext, useEffect } from 'react';
import {
useState,
useContext,
useEffect,
useRef,
useCallback,
} from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useMediaQuery } from 'react-responsive';
import * as Yup from 'yup';
Expand Down Expand Up @@ -308,15 +314,21 @@ export const getFileSizeToClosestByte = (fileSize) => {
*/
export const useRunOnNextRender = (callback) => {
const [scheduled, setScheduled] = useState(false);
const argsRef = useRef();

useEffect(() => {
if (!scheduled) {
return;
}

setScheduled(false);
callback();
callback(argsRef.current);
}, [scheduled]);

return () => setScheduled(true);
const trigger = useCallback((...args) => {
argsRef.current = args;
setScheduled(true);
}, []);

return trigger;
};
Loading