Skip to content

Commit

Permalink
refactor: move context files
Browse files Browse the repository at this point in the history
  • Loading branch information
rpenido committed Nov 29, 2024
1 parent 2c18cb8 commit 3662b82
Show file tree
Hide file tree
Showing 52 changed files with 235 additions and 218 deletions.
2 changes: 1 addition & 1 deletion src/library-authoring/EmptyStates.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
import { Add } from '@openedx/paragon/icons';
import { ClearFiltersButton } from '../search-manager';
import messages from './messages';
import { useLibraryContext } from './common/context';
import { useLibraryContext } from './common/context/LibraryContext';

export const NoComponents = ({
infoText = messages.noComponents,
Expand Down
3 changes: 2 additions & 1 deletion src/library-authoring/LibraryAuthoringPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ import {
} from '../search-manager';
import LibraryContent, { ContentType } from './LibraryContent';
import { LibrarySidebar } from './library-sidebar';
import { SidebarBodyComponentId, useLibraryContext, useComponentPickerContext } from './common/context';
import { SidebarBodyComponentId, useLibraryContext } from './common/context/LibraryContext';
import { useComponentPickerContext } from './common/context/ComponentPickerContext';
import messages from './messages';

const HeaderActions = () => {
Expand Down
2 changes: 1 addition & 1 deletion src/library-authoring/LibraryContent.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import { getContentSearchConfigUrl } from '../search-manager/data/api';
import { mockContentLibrary } from './data/api.mocks';
import mockEmptyResult from '../search-modal/__mocks__/empty-search-result.json';
import { LibraryProvider } from './common/context';
import { LibraryProvider } from './common/context/LibraryContext';
import LibraryContent from './LibraryContent';
import { libraryComponentsMock } from './__mocks__';

Expand Down
2 changes: 1 addition & 1 deletion src/library-authoring/LibraryContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useEffect } from 'react';
import { LoadingSpinner } from '../generic/Loading';
import { useSearchContext } from '../search-manager';
import { NoComponents, NoSearchResults } from './EmptyStates';
import { useLibraryContext } from './common/context';
import { useLibraryContext } from './common/context/LibraryContext';
import CollectionCard from './components/CollectionCard';
import ComponentCard from './components/ComponentCard';
import { useLoadOnScroll } from '../hooks';
Expand Down
2 changes: 1 addition & 1 deletion src/library-authoring/LibraryLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
} from 'react-router-dom';

import LibraryAuthoringPage from './LibraryAuthoringPage';
import { LibraryProvider } from './common/context';
import { LibraryProvider } from './common/context/LibraryContext';
import { CreateCollectionModal } from './create-collection';
import { LibraryTeamModal } from './library-team';
import LibraryCollectionPage from './collections/LibraryCollectionPage';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
getContentLibraryApiUrl, getCreateLibraryBlockUrl, getLibraryCollectionComponentApiUrl, getLibraryPasteClipboardUrl,
} from '../data/api';
import { mockBroadcastChannel, mockClipboardEmpty, mockClipboardHtml } from '../../generic/data/api.mock';
import { LibraryProvider } from '../common/context';
import { LibraryProvider } from '../common/context/LibraryContext';
import AddContentContainer from './AddContentContainer';
import { ComponentEditorModal } from '../components/ComponentEditorModal';
import editorCmsApi from '../../editors/data/services/cms/api';
Expand Down
2 changes: 1 addition & 1 deletion src/library-authoring/add-content/AddContentContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { ToastContext } from '../../generic/toast-context';
import { useCopyToClipboard } from '../../generic/clipboard';
import { getCanEdit } from '../../course-unit/data/selectors';
import { useCreateLibraryBlock, useLibraryPasteClipboard, useAddComponentsToCollection } from '../data/apiHooks';
import { useLibraryContext } from '../common/context';
import { useLibraryContext } from '../common/context/LibraryContext';
import { canEditComponent } from '../components/ComponentEditorModal';
import { PickLibraryContentModal } from './PickLibraryContentModal';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import { studioHomeMock } from '../../studio-home/__mocks__';
import { getStudioHomeApiUrl } from '../../studio-home/data/api';
import mockResult from '../__mocks__/library-search.json';
import { LibraryProvider } from '../common/context';
import { LibraryProvider } from '../common/context/LibraryContext';
import { ComponentPicker } from '../component-picker';
import * as api from '../data/api';
import {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import { ActionRow, Button, StandardModal } from '@openedx/paragon';

import { ToastContext } from '../../generic/toast-context';
import { type SelectedComponent, useLibraryContext } from '../common/context';
import { useLibraryContext } from '../common/context/LibraryContext';
import type { SelectedComponent } from '../common/context/ComponentPickerContext';
import { useAddComponentsToCollection } from '../data/apiHooks';
import messages from './messages';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
waitFor,
within,
} from '../../testUtils';
import { LibraryProvider, SidebarBodyComponentId } from '../common/context';
import { LibraryProvider, SidebarBodyComponentId } from '../common/context/LibraryContext';
import * as api from '../data/api';
import { mockContentLibrary, mockGetCollectionMetadata } from '../data/api.mocks';
import CollectionDetails from './CollectionDetails';
Expand Down
2 changes: 1 addition & 1 deletion src/library-authoring/collections/CollectionDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import classNames from 'classnames';
import { getItemIcon } from '../../generic/block-type-utils';
import { ToastContext } from '../../generic/toast-context';
import { BlockTypeLabel, useGetBlockTypes } from '../../search-manager';
import { useLibraryContext } from '../common/context';
import { useLibraryContext } from '../common/context/LibraryContext';
import { useCollection, useUpdateCollection } from '../data/apiHooks';
import HistoryWidget from '../generic/history-widget';
import messages from './messages';
Expand Down
5 changes: 2 additions & 3 deletions src/library-authoring/collections/CollectionInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ import {
} from '@openedx/paragon';
import { useCallback } from 'react';
import { useNavigate, useMatch } from 'react-router-dom';

import { useComponentPickerContext } from '../common/context/ComponentPickerContext';
import {
useComponentPickerContext,
useLibraryContext,
type CollectionInfoTab,
COLLECTION_INFO_TABS,
isCollectionInfoTab,
COMPONENT_INFO_TABS,
} from '../common/context';
} from '../common/context/LibraryContext';
import CollectionDetails from './CollectionDetails';
import messages from './messages';
import { ContentTagsDrawer } from '../../content-tags-drawer';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
screen,
waitFor,
} from '../../testUtils';
import { LibraryProvider, SidebarBodyComponentId } from '../common/context';
import { LibraryProvider, SidebarBodyComponentId } from '../common/context/LibraryContext';
import { mockContentLibrary, mockGetCollectionMetadata } from '../data/api.mocks';
import * as api from '../data/api';
import CollectionInfoHeader from './CollectionInfoHeader';
Expand Down
2 changes: 1 addition & 1 deletion src/library-authoring/collections/CollectionInfoHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import { Edit } from '@openedx/paragon/icons';

import { ToastContext } from '../../generic/toast-context';
import { useLibraryContext } from '../common/context';
import { useLibraryContext } from '../common/context/LibraryContext';
import { useCollection, useUpdateCollection } from '../data/apiHooks';
import messages from './messages';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Stack } from '@openedx/paragon';
import { NoComponents, NoSearchResults } from '../EmptyStates';
import { useSearchContext } from '../../search-manager';
import messages from './messages';
import { useLibraryContext } from '../common/context';
import { useLibraryContext } from '../common/context/LibraryContext';
import LibraryContent, { ContentType } from '../LibraryContent';

const LibraryCollectionComponents = () => {
Expand Down
3 changes: 2 additions & 1 deletion src/library-authoring/collections/LibraryCollectionPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ import {
SearchSortWidget,
} from '../../search-manager';
import { useCollection, useContentLibrary } from '../data/apiHooks';
import { useComponentPickerContext, useLibraryContext } from '../common/context';
import { useComponentPickerContext } from '../common/context/ComponentPickerContext';
import { useLibraryContext } from '../common/context/LibraryContext';
import messages from './messages';
import { LibrarySidebar } from '../library-sidebar';
import LibraryCollectionComponents from './LibraryCollectionComponents';
Expand Down
163 changes: 163 additions & 0 deletions src/library-authoring/common/context/ComponentPickerContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import {
createContext,
useCallback,
useContext,
useMemo,
useState,
} from 'react';

export interface SelectedComponent {
usageKey: string;
blockType: string;
}

export type ComponentSelectedEvent = (selectedComponent: SelectedComponent) => void;
export type ComponentSelectionChangedEvent = (selectedComponents: SelectedComponent[]) => void;

type NoComponentPickerType = {
componentPickerMode: false;
/** We add the `never` type to ensure that the other properties are not used,
* but allow it to be desconstructed from the return value of `useComponentPickerContext()`
*/
onComponentSelected?: never;
selectedComponents?: never;
addComponentToSelectedComponents?: never;
removeComponentFromSelectedComponents?: never;
restrictToLibrary?: never;
};

type ComponentPickerSingleType = {
componentPickerMode: 'single';
onComponentSelected: ComponentSelectedEvent;
selectedComponents?: never;
addComponentToSelectedComponents?: never;
removeComponentFromSelectedComponents?: never;
restrictToLibrary: boolean;
};

type ComponentPickerMultipleType = {
componentPickerMode: 'multiple';
onComponentSelected?: never;
selectedComponents: SelectedComponent[];
addComponentToSelectedComponents: ComponentSelectedEvent;
removeComponentFromSelectedComponents: ComponentSelectedEvent;
restrictToLibrary: boolean;
};

type ComponentPickerContextData = ComponentPickerSingleType | ComponentPickerMultipleType;

/**
* Component Picker Context.
* This context is used to provide the component picker mode and the selected components.
*
* Get this using `useComponentPickerContext()`
*/
const ComponentPickerContext = createContext<ComponentPickerContextData | undefined>(undefined);

export type ComponentPickerSingleProps = {
componentPickerMode: 'single';
onComponentSelected: ComponentSelectedEvent;
onChangeComponentSelection?: never;
restrictToLibrary?: boolean;
};

export type ComponentPickerMultipleProps = {
componentPickerMode: 'multiple';
onComponentSelected?: never;
onChangeComponentSelection?: ComponentSelectionChangedEvent;
restrictToLibrary?: boolean;
};

type ComponentPickerProps = ComponentPickerSingleProps | ComponentPickerMultipleProps;

type ComponentPickerProviderProps = {
children?: React.ReactNode;
} & ComponentPickerProps;

/**
* React component to provide `ComponentPickerContext`
*/
export const ComponentPickerProvider = ({
children,
componentPickerMode,
restrictToLibrary = false,
onComponentSelected,
onChangeComponentSelection,
}: ComponentPickerProviderProps) => {
const [selectedComponents, setSelectedComponents] = useState<SelectedComponent[]>([]);

const addComponentToSelectedComponents = useCallback<ComponentSelectedEvent>((
selectedComponent: SelectedComponent,
) => {
setSelectedComponents((prevSelectedComponents) => {
// istanbul ignore if: this should never happen
if (prevSelectedComponents.some((component) => component.usageKey === selectedComponent.usageKey)) {
return prevSelectedComponents;
}
const newSelectedComponents = [...prevSelectedComponents, selectedComponent];
onChangeComponentSelection?.(newSelectedComponents);
return newSelectedComponents;
});
}, []);

const removeComponentFromSelectedComponents = useCallback<ComponentSelectedEvent>((
selectedComponent: SelectedComponent,
) => {
setSelectedComponents((prevSelectedComponents) => {
// istanbul ignore if: this should never happen
if (!prevSelectedComponents.some((component) => component.usageKey === selectedComponent.usageKey)) {
return prevSelectedComponents;
}
const newSelectedComponents = prevSelectedComponents.filter(
(component) => component.usageKey !== selectedComponent.usageKey,
);
onChangeComponentSelection?.(newSelectedComponents);
return newSelectedComponents;
});
}, []);

const context = useMemo<ComponentPickerContextData>(() => {
switch (componentPickerMode) {
case 'single':
return {
componentPickerMode,
restrictToLibrary,
onComponentSelected,
};
case 'multiple':
return {
componentPickerMode,
restrictToLibrary,
selectedComponents,
addComponentToSelectedComponents,
removeComponentFromSelectedComponents,
};
default:
throw new Error('Invalid component picker mode');

Check warning on line 136 in src/library-authoring/common/context/ComponentPickerContext.tsx

View check run for this annotation

Codecov / codecov/patch

src/library-authoring/common/context/ComponentPickerContext.tsx#L135-L136

Added lines #L135 - L136 were not covered by tests
}
}, [
componentPickerMode,
restrictToLibrary,
onComponentSelected,
addComponentToSelectedComponents,
removeComponentFromSelectedComponents,
selectedComponents,
onChangeComponentSelection,
]);

return (
<ComponentPickerContext.Provider value={context}>
{children}
</ComponentPickerContext.Provider>
);
};

export function useComponentPickerContext(): ComponentPickerContextData | NoComponentPickerType {
const ctx = useContext(ComponentPickerContext);
if (ctx === undefined) {
return {
componentPickerMode: false,
};
}
return ctx;
}
Loading

0 comments on commit 3662b82

Please sign in to comment.