>;
+ restoreSectionList: () => void;
+ handleSectionDragAndDrop: (sectionListIds: string[], restoreSectionList: () => void) => void;
handleSubsectionDragAndDrop: (
sectionId: string,
prevSectionId: string,
subsectionListIds: string[],
restoreSectionList: () => void,
- ) => void,
+ ) => void;
handleUnitDragAndDrop: (
sectionId: string,
prevSectionId: string,
subsectionId: string,
unitListIds: string[],
restoreSectionList: () => void,
- ) => void,
- children: React.ReactNode,
+ ) => void;
+ children: React.ReactNode;
}
interface ItemInfoType {
@@ -363,7 +363,10 @@ const DraggableList = ({
};
const customClosestCorners: CollisionDetection = ({
- active, droppableContainers, droppableRects, ...args
+ active,
+ droppableContainers,
+ droppableRects,
+ ...args
}) => {
const activeCategory = active.data?.current?.category;
const filteredContainers = droppableContainers.filter(
@@ -385,7 +388,10 @@ const DraggableList = ({
},
);
return closestCorners({
- active, droppableContainers: filteredContainers, droppableRects, ...args,
+ active,
+ droppableContainers: filteredContainers,
+ droppableRects,
+ ...args,
});
};
diff --git a/src/course-outline/drag-helper/SortableItem.tsx b/src/course-outline/drag-helper/SortableItem.tsx
index d51f71e690..59e2b5485d 100644
--- a/src/course-outline/drag-helper/SortableItem.tsx
+++ b/src/course-outline/drag-helper/SortableItem.tsx
@@ -3,7 +3,9 @@ import { useIntl } from '@edx/frontend-platform/i18n';
import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import {
- Col, Icon, Row,
+ Col,
+ Icon,
+ Row,
} from '@openedx/paragon';
import { DragIndicator } from '@openedx/paragon/icons';
@@ -16,7 +18,7 @@ interface SortableItemProps {
childAddable?: boolean;
displayName: string;
status: string;
- }
+ };
isDroppable?: boolean;
isDraggable?: boolean;
children: React.ReactNode;
diff --git a/src/course-outline/drag-helper/utils.test.ts b/src/course-outline/drag-helper/utils.test.ts
index bb6a2242ae..b2389dfc59 100644
--- a/src/course-outline/drag-helper/utils.test.ts
+++ b/src/course-outline/drag-helper/utils.test.ts
@@ -1,6 +1,11 @@
import { XBlock } from '@src/data/types';
import {
- possibleSubsectionMoves, moveSubsection, moveSubsectionOver, possibleUnitMoves, moveUnit, moveUnitOver,
+ possibleSubsectionMoves,
+ moveSubsection,
+ moveSubsectionOver,
+ possibleUnitMoves,
+ moveUnit,
+ moveUnitOver,
} from './utils';
describe('possibleSubsectionMoves', () => {
diff --git a/src/course-outline/drag-helper/utils.ts b/src/course-outline/drag-helper/utils.ts
index 523fd0d7a1..58a71da994 100644
--- a/src/course-outline/drag-helper/utils.ts
+++ b/src/course-outline/drag-helper/utils.ts
@@ -30,17 +30,18 @@ export const dragHelpers = {
];
return block;
},
- isBelowOverItem: (active: Active, over: Over) => over
- && active.rect.current.translated
- && active.rect.current.translated.top
- > over.rect.top + over.rect.height,
+ isBelowOverItem: (active: Active, over: Over) =>
+ over
+ && active.rect.current.translated
+ && active.rect.current.translated.top
+ > over.rect.top + over.rect.height,
};
/**
- * This function moves a subsection from one section to another in the copy of blocks.
- * It updates the copy with the new positions for the sections and their subsections,
- * while keeping other sections intact.
-*/
+ * This function moves a subsection from one section to another in the copy of blocks.
+ * It updates the copy with the new positions for the sections and their subsections,
+ * while keeping other sections intact.
+ */
export const moveSubsectionOver = (
prevCopy: XBlock[],
activeSectionIdx: number,
@@ -107,8 +108,8 @@ export const moveUnitOver = (
};
/**
- * Handles dragging and dropping a subsection within the same section.
-*/
+ * Handles dragging and dropping a subsection within the same section.
+ */
export const moveSubsection = (
prevCopy: XBlock[],
sectionIdx: number,
@@ -167,16 +168,17 @@ export const canMoveSection = (sections: XBlock[]) => (id: number, step: number)
};
/**
- * Checks if a user can move a specific subsection within its parent section or other sections.
- * It ensures that the new position for the subsection is valid and that it's not
- * attempting to drag an unmovable item or beyond the bounds of existing sections.
-*/
+ * Checks if a user can move a specific subsection within its parent section or other sections.
+ * It ensures that the new position for the subsection is valid and that it's not
+ * attempting to drag an unmovable item or beyond the bounds of existing sections.
+ */
export const possibleSubsectionMoves = (
sections: XBlock[],
sectionIndex: number,
section: XBlock,
subsections: XBlock[],
-) => (index: number, step: number) => {
+) =>
+(index: number, step: number) => {
if (!subsections[index]?.actions?.draggable) {
return {};
}
@@ -192,7 +194,8 @@ export const possibleSubsectionMoves = (
],
sectionId: section.id,
};
- } if (step === -1 && index === 0 && sectionIndex > 0) {
+ }
+ if (step === -1 && index === 0 && sectionIndex > 0) {
// find a section that accepts children above/before the current section
const newSectionIndex = findLastIndex(sections, { actions: { childAddable: true } }, sectionIndex + step);
if (newSectionIndex === -1) {
@@ -210,7 +213,8 @@ export const possibleSubsectionMoves = (
],
sectionId: sections[newSectionIndex].id,
};
- } if (step === 1 && index === subsections.length - 1 && sectionIndex < sections.length + step) {
+ }
+ if (step === 1 && index === subsections.length - 1 && sectionIndex < sections.length + step) {
// find a section that accepts children below/after the current section
const newSectionIndex = findIndex(sections, { actions: { childAddable: true } }, sectionIndex + 1);
// move subsection to first position of next section
@@ -234,9 +238,9 @@ export const possibleSubsectionMoves = (
};
/**
- * Function to find the valid subsection index based on the current position and the step.
- * It uses the provided find method.
-*/
+ * Function to find the valid subsection index based on the current position and the step.
+ * It uses the provided find method.
+ */
const findValidSubsectionIndex = (
sections: XBlock[],
sectionIndex: number,
@@ -244,7 +248,7 @@ const findValidSubsectionIndex = (
findMethod: typeof findLastIndex | typeof findIndex,
): {
newSectionIndex: number;
- newSubsectionIndex: number
+ newSubsectionIndex: number;
} | null => {
if (sectionIndex + step < 0) {
return null;
@@ -273,7 +277,7 @@ const findValidSubsectionIndex = (
* Moves a unit to a previous location within the XBlock structure. This function attempts to move the unit
* to the previous subsection within the same section, and if that fails, it will attempt to move it to the
* previous section.
-*/
+ */
const moveToPreviousLocation = (
sections: XBlock[],
sectionIndex: number,
@@ -336,7 +340,7 @@ const moveToPreviousLocation = (
/**
* This function attempts to move a unit to the next childAddable subsection within the current section.
* If no such subsection exists, it will attempt to move the unit to the next section.
-*/
+ */
const moveToNextLocation = (
sections: XBlock[],
sectionIndex: number,
@@ -396,10 +400,10 @@ const moveToNextLocation = (
};
/**
- * Checks if a user can move a specific unit within all subsections
- * It ensures that the new position for the unit is valid and that it's not
- * attempting to drag an unmovable item or beyond the bounds of existing subsections and sections.
-*/
+ * Checks if a user can move a specific unit within all subsections
+ * It ensures that the new position for the unit is valid and that it's not
+ * attempting to drag an unmovable item or beyond the bounds of existing subsections and sections.
+ */
export const possibleUnitMoves = (
sections: XBlock[],
sectionIndex: number,
@@ -407,7 +411,8 @@ export const possibleUnitMoves = (
section: XBlock,
subsection: XBlock,
units: XBlock[],
-) => (index: number, step: number) => {
+) =>
+(index: number, step: number) => {
// Early return if unit is not draggable
if (!units[index]?.actions?.draggable) {
return {};
diff --git a/src/course-outline/empty-placeholder/EmptyPlaceholder.test.tsx b/src/course-outline/empty-placeholder/EmptyPlaceholder.test.tsx
index 0b458f394f..3b66ed8ec7 100644
--- a/src/course-outline/empty-placeholder/EmptyPlaceholder.test.tsx
+++ b/src/course-outline/empty-placeholder/EmptyPlaceholder.test.tsx
@@ -1,6 +1,9 @@
import { Button } from '@openedx/paragon';
import {
- fireEvent, initializeMocks, render, screen,
+ fireEvent,
+ initializeMocks,
+ render,
+ screen,
} from '@src/testUtils';
import EmptyPlaceholder from './EmptyPlaceholder';
@@ -8,11 +11,12 @@ import messages from './messages';
const onCreateNewSectionMock = jest.fn();
-const renderComponent = () => render(
-
- Create New Section
- ,
-);
+const renderComponent = () =>
+ render(
+
+ Create New Section
+ ,
+ );
describe(' ', () => {
it('renders EmptyPlaceholder component correctly', async () => {
diff --git a/src/course-outline/enable-highlights-modal/EnableHighlightsModal.jsx b/src/course-outline/enable-highlights-modal/EnableHighlightsModal.jsx
index 67cb818d1d..f1c70e049d 100644
--- a/src/course-outline/enable-highlights-modal/EnableHighlightsModal.jsx
+++ b/src/course-outline/enable-highlights-modal/EnableHighlightsModal.jsx
@@ -2,7 +2,10 @@ import React from 'react';
import PropTypes from 'prop-types';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
- ActionRow, AlertModal, Button, Hyperlink,
+ ActionRow,
+ AlertModal,
+ Button,
+ Hyperlink,
} from '@openedx/paragon';
import messages from './messages';
@@ -26,7 +29,7 @@ const EnableHighlightsModal = ({
size="lg"
isOpen={isOpen}
onClose={close}
- footerNode={(
+ footerNode={
{intl.formatMessage(messages.cancelButton)}
@@ -35,7 +38,7 @@ const EnableHighlightsModal = ({
{intl.formatMessage(messages.submitButton)}
- )}
+ }
>
{intl.formatMessage(messages.description_1)}
diff --git a/src/course-outline/enable-highlights-modal/EnableHighlightsModal.test.jsx b/src/course-outline/enable-highlights-modal/EnableHighlightsModal.test.jsx
index 50c5955998..8b4ac258e1 100644
--- a/src/course-outline/enable-highlights-modal/EnableHighlightsModal.test.jsx
+++ b/src/course-outline/enable-highlights-modal/EnableHighlightsModal.test.jsx
@@ -27,18 +27,19 @@ jest.mock('../../help-urls/hooks', () => ({
const onEnableHighlightsSubmitMock = jest.fn();
const closeMock = jest.fn();
-const renderComponent = (props) => render(
-
-
-
- ,
- ,
-);
+const renderComponent = (props) =>
+ render(
+
+
+
+ ,
+ ,
+ );
describe(' ', () => {
beforeEach(() => {
diff --git a/src/course-outline/header-navigations/HeaderActions.test.tsx b/src/course-outline/header-navigations/HeaderActions.test.tsx
index f07848e84e..0d38212367 100644
--- a/src/course-outline/header-navigations/HeaderActions.test.tsx
+++ b/src/course-outline/header-navigations/HeaderActions.test.tsx
@@ -1,6 +1,9 @@
import { userEvent } from '@testing-library/user-event';
import {
- fireEvent, initializeMocks, render, screen,
+ fireEvent,
+ initializeMocks,
+ render,
+ screen,
} from '@src/testUtils';
import { CourseOutlineProvider, OutlineSidebarProvider } from '@src/course-outline';
@@ -29,24 +32,25 @@ jest.mock('../outline-sidebar/OutlineSidebarContext', () => ({
}),
}));
-const renderComponent = (props?: Partial) => render(
- ,
- {
- extraWrapper: ({ children }) => (
-
-
-
- {children}
-
-
-
- ),
- },
-);
+const renderComponent = (props?: Partial) =>
+ render(
+ ,
+ {
+ extraWrapper: ({ children }) => (
+
+
+
+ {children}
+
+
+
+ ),
+ },
+ );
describe(' ', () => {
beforeEach(() => {
diff --git a/src/course-outline/header-navigations/HeaderActions.tsx b/src/course-outline/header-navigations/HeaderActions.tsx
index 5406c96b15..24eac4798d 100644
--- a/src/course-outline/header-navigations/HeaderActions.tsx
+++ b/src/course-outline/header-navigations/HeaderActions.tsx
@@ -1,9 +1,14 @@
import { useIntl } from '@edx/frontend-platform/i18n';
import {
- Button, OverlayTrigger, Stack, Tooltip,
+ Button,
+ OverlayTrigger,
+ Stack,
+ Tooltip,
} from '@openedx/paragon';
import {
- Add as IconAdd, FindInPage, InfoOutline,
+ Add as IconAdd,
+ FindInPage,
+ InfoOutline,
} from '@openedx/paragon/icons';
import { OutlinePageErrors, XBlockActions } from '@src/data/types';
@@ -14,10 +19,10 @@ import messages from './messages';
export interface HeaderActionsProps {
actions: {
- lmsLink: string,
- },
- courseActions: XBlockActions,
- errors?: OutlinePageErrors,
+ lmsLink: string;
+ };
+ courseActions: XBlockActions;
+ errors?: OutlinePageErrors;
}
const HeaderActions = ({
@@ -40,11 +45,11 @@ const HeaderActions = ({
{intl.formatMessage(messages.courseInfoButtonTooltip)}
- )}
+ }
>
{intl.formatMessage(messages.newSectionButtonTooltip)}
- )}
+ }
>
{intl.formatMessage(messages.viewLiveButtonTooltip)}
- )}
+ }
>
) => render(
- ,
-);
+const renderComponent = (props?: Partial) =>
+ render(
+ ,
+ );
describe(' ', () => {
beforeEach(() => {
@@ -124,7 +129,7 @@ describe(' ', () => {
isDisabledReindexButton: true,
});
await user.pointer({
- target: (await screen.findByRole('button', { name: messages.reindexButton.defaultMessage })),
+ target: await screen.findByRole('button', { name: messages.reindexButton.defaultMessage }),
});
await waitFor(() => {
expect(screen.queryByText(messages.reindexButtonTooltip.defaultMessage)).not.toBeInTheDocument();
diff --git a/src/course-outline/header-navigations/HeaderNavigations.tsx b/src/course-outline/header-navigations/HeaderNavigations.tsx
index 90c98038d7..6a1970a32d 100644
--- a/src/course-outline/header-navigations/HeaderNavigations.tsx
+++ b/src/course-outline/header-navigations/HeaderNavigations.tsx
@@ -11,18 +11,18 @@ import { OutlinePageErrors, XBlockActions } from '@src/data/types';
import messages from './messages';
export interface HeaderNavigationsProps {
- isReIndexShow: boolean,
- isSectionsExpanded: boolean,
- isDisabledReindexButton: boolean,
+ isReIndexShow: boolean;
+ isSectionsExpanded: boolean;
+ isDisabledReindexButton: boolean;
headerNavigationsActions: {
- handleNewSection: () => void,
- handleReIndex: () => void,
- handleExpandAll: () => void,
- lmsLink: string,
- },
- hasSections: boolean,
- courseActions: XBlockActions,
- errors?: OutlinePageErrors,
+ handleNewSection: () => void;
+ handleReIndex: () => void;
+ handleExpandAll: () => void;
+ lmsLink: string;
+ };
+ hasSections: boolean;
+ courseActions: XBlockActions;
+ errors?: OutlinePageErrors;
}
const HeaderNavigations = ({
@@ -36,7 +36,10 @@ const HeaderNavigations = ({
}: HeaderNavigationsProps) => {
const intl = useIntl();
const {
- handleNewSection, handleReIndex, handleExpandAll, lmsLink,
+ handleNewSection,
+ handleReIndex,
+ handleExpandAll,
+ lmsLink,
} = headerNavigationsActions;
return (
@@ -44,11 +47,11 @@ const HeaderNavigations = ({
{courseActions.childAddable && (
{intl.formatMessage(messages.newSectionButtonTooltip)}
- )}
+ }
>
- {intl.formatMessage(messages.reindexButtonTooltip)}
-
- ) : }
+ overlay={!isDisabledReindexButton ?
+ (
+
+ {intl.formatMessage(messages.reindexButtonTooltip)}
+
+ ) :
+ }
>
{intl.formatMessage(messages.viewLiveButtonTooltip)}
- )}
+ }
>
', () => {
it('disables save button when pristine', async () => {
render( );
- const saveBtn = await screen.findByRole('button', { name: messages.saveButton.defaultMessage }) as HTMLButtonElement;
+ const saveBtn = await screen.findByRole('button', {
+ name: messages.saveButton.defaultMessage,
+ }) as HTMLButtonElement;
expect(saveBtn.disabled).toBe(true);
});
@@ -201,7 +207,8 @@ describe(' ', () => {
,
);
- expect(await screen.findByRole('button', { name: messages.addHighlightsButton.defaultMessage })).toBeInTheDocument();
+ expect(await screen.findByRole('button', { name: messages.addHighlightsButton.defaultMessage }))
+ .toBeInTheDocument();
});
it('transitions to editing mode on edit button click', async () => {
diff --git a/src/course-outline/highlights-modal/HighlightsModal.tsx b/src/course-outline/highlights-modal/HighlightsModal.tsx
index 470891d42f..67ee155b8b 100644
--- a/src/course-outline/highlights-modal/HighlightsModal.tsx
+++ b/src/course-outline/highlights-modal/HighlightsModal.tsx
@@ -98,7 +98,10 @@ const HighlightsFormInner = ({
]);
const {
- values, dirty, handleSubmit, resetForm,
+ values,
+ dirty,
+ handleSubmit,
+ resetForm,
} = useFormikContext();
// Notify parent of dirty state changes
@@ -183,7 +186,7 @@ const HighlightsViewCard = ({
- )}
+ }
/>
- {nonEmptyHighlights.map((highlight) => (
- {highlight}
- ))}
+ {nonEmptyHighlights.map((highlight) => {highlight}
)}
);
};
-const HighlightsEmptyState = ({ onAdd }: { onAdd: () => void }) => {
+const HighlightsEmptyState = ({ onAdd }: { onAdd: () => void; }) => {
const intl = useIntl();
return (
@@ -265,7 +266,7 @@ export const HighlightsCard = ({ sectionId, onSubmit }: HighlightsCardProps) =>
{
+ onCancel={/* istanbul ignore next */ () => {
blocker.reset?.();
}}
/>
diff --git a/src/course-outline/hooks.jsx b/src/course-outline/hooks.jsx
index ab2d1e07c6..582c0c87ca 100644
--- a/src/course-outline/hooks.jsx
+++ b/src/course-outline/hooks.jsx
@@ -88,7 +88,7 @@ const useCourseOutline = ({ courseId }) => {
const statusBarData = useSelector(getStatusBarData);
const savingStatus = useSelector(getSavingStatus);
const courseActions = useSelector(getCourseActions);
-
+
const isCustomRelativeDatesActive = useSelector(getCustomRelativeDatesActiveFlag);
const genericSavingStatus = useSelector(getGenericSavingStatus);
const errors = useSelector(getErrors);
diff --git a/src/course-outline/index.ts b/src/course-outline/index.ts
index e744ba23bb..3178bdd367 100644
--- a/src/course-outline/index.ts
+++ b/src/course-outline/index.ts
@@ -1,4 +1,4 @@
export { default as CourseOutline } from './CourseOutline';
-export { OutlineSidebarPagesProvider } from './outline-sidebar/OutlineSidebarPagesContext';
-export { OutlineSidebarProvider } from './outline-sidebar/OutlineSidebarContext';
export { CourseOutlineProvider, useCourseOutlineContext } from './CourseOutlineContext';
+export { OutlineSidebarProvider } from './outline-sidebar/OutlineSidebarContext';
+export { OutlineSidebarPagesProvider } from './outline-sidebar/OutlineSidebarPagesContext';
diff --git a/src/course-outline/outline-sidebar/AddSidebar.test.tsx b/src/course-outline/outline-sidebar/AddSidebar.test.tsx
index 2cfe9f4b24..702ae00907 100644
--- a/src/course-outline/outline-sidebar/AddSidebar.test.tsx
+++ b/src/course-outline/outline-sidebar/AddSidebar.test.tsx
@@ -1,6 +1,9 @@
import { courseOutlineIndexMock } from '@src/course-outline/__mocks__';
import {
- initializeMocks, render, screen, waitFor,
+ initializeMocks,
+ render,
+ screen,
+ waitFor,
} from '@src/testUtils';
import { userEvent } from '@testing-library/user-event';
import mockResult from '@src/library-authoring/__mocks__/library-search.json';
@@ -81,17 +84,18 @@ jest.mock('../outline-sidebar/OutlineSidebarContext', () => ({
}),
}));
-const renderComponent = () => render( , {
- extraWrapper: ({ children }) => (
-
-
-
- {children}
-
-
-
- ),
-});
+const renderComponent = () =>
+ render( , {
+ extraWrapper: ({ children }) => (
+
+
+
+ {children}
+
+
+
+ ),
+ });
const searchResult = {
...mockResult,
results: [
@@ -122,7 +126,9 @@ describe('AddSidebar', () => {
newMockResult.results[0].query = query;
// And fake the required '_formatted' fields; it contains the highlighting ... around matched words
// eslint-disable-next-line no-underscore-dangle, no-param-reassign
- newMockResult.results[0]?.hits.forEach((hit) => { hit._formatted = { ...hit }; });
+ newMockResult.results[0]?.hits.forEach((hit) => {
+ hit._formatted = { ...hit };
+ });
return newMockResult;
});
outlineChildren = courseOutlineIndexMock.courseStructure.childInfo.children;
@@ -328,7 +334,9 @@ describe('AddSidebar', () => {
// Check existing tab content
await user.click(await screen.findByRole('tab', { name: 'Add Existing' }));
// Check existing tab content is rendered by default
- await waitFor(() => { expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post'); });
+ await waitFor(() => {
+ expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post');
+ });
expect(fetchMock).toHaveLastFetched((_url, req) => {
const requestData = JSON.parse((req.body ?? '') as string);
const requestedFilter = requestData?.queries[0].filter;
@@ -377,9 +385,11 @@ describe('AddSidebar', () => {
// render existing tab as well
await user.click(await screen.findByRole('tab', { name: 'Add Existing' }));
// One in new tab and one in existing tab
- expect((await screen.findAllByText(
- `${currentItemData.displayName} is a library section. Content cannot be added to Library referenced sections.`,
- )).length).toEqual(2);
+ expect(
+ (await screen.findAllByText(
+ `${currentItemData.displayName} is a library section. Content cannot be added to Library referenced sections.`,
+ )).length,
+ ).toEqual(2);
});
it('back button is rendered and works', async () => {
diff --git a/src/course-outline/outline-sidebar/AddSidebar.tsx b/src/course-outline/outline-sidebar/AddSidebar.tsx
index 6e9f267934..30c9f1903d 100644
--- a/src/course-outline/outline-sidebar/AddSidebar.tsx
+++ b/src/course-outline/outline-sidebar/AddSidebar.tsx
@@ -8,11 +8,16 @@ import { useCourseAuthoringContext } from '@src/CourseAuthoringContext';
import { useCourseOutlineContext } from '@src/course-outline/CourseOutlineContext';
import { SidebarFilters } from '@src/library-authoring/library-filters/SidebarFilters';
import {
- Stack, Tab, Tabs,
+ Stack,
+ Tab,
+ Tabs,
} from '@openedx/paragon';
import { getItemIcon } from '@src/generic/block-type-utils';
import {
- useCallback, useEffect, useMemo, useState,
+ useCallback,
+ useEffect,
+ useMemo,
+ useState,
} from 'react';
import { ComponentSelectedEvent } from '@src/library-authoring/common/context/ComponentPickerContext';
import { COMPONENT_TYPES } from '@src/generic/block-type-utils/constants';
@@ -43,12 +48,12 @@ const CannotAddContentAlert = () => {
};
type AddContentButtonProps = {
- name: string,
- blockType: ContainerType,
+ name: string;
+ blockType: ContainerType;
};
/** Add Content Button */
-const AddContentButton = ({ name, blockType } : AddContentButtonProps) => {
+const AddContentButton = ({ name, blockType }: AddContentButtonProps) => {
const { courseUsageKey } = useCourseAuthoringContext();
const {
handleAddBlock,
@@ -122,9 +127,7 @@ const AddContentButton = ({ name, blockType } : AddContentButtonProps) => {
}
break;
case 'unit':
- sectionParentId = (
- currentFlow?.grandParentLocator || lastEditableSubsection?.sectionId || sectionParentId
- );
+ sectionParentId = currentFlow?.grandParentLocator || lastEditableSubsection?.sectionId || sectionParentId;
subsectionParentId = currentFlow?.parentLocator || subsectionParentId;
if (subsectionParentId) {
addUnit(subsectionParentId, sectionParentId);
@@ -249,9 +252,7 @@ const ShowLibraryContent = () => {
}
break;
case 'unit':
- sectionParentId = (
- currentFlow?.grandParentLocator || lastEditableSubsection?.sectionId || sectionParentId
- );
+ sectionParentId = currentFlow?.grandParentLocator || lastEditableSubsection?.sectionId || sectionParentId;
subsectionParentId = currentFlow?.parentLocator || subsectionParentId;
if (subsectionParentId) {
await handleAddBlock.mutateAsync({
diff --git a/src/course-outline/outline-sidebar/OutlineAlignSidebar.tsx b/src/course-outline/outline-sidebar/OutlineAlignSidebar.tsx
index f432208f21..ebd8477b69 100644
--- a/src/course-outline/outline-sidebar/OutlineAlignSidebar.tsx
+++ b/src/course-outline/outline-sidebar/OutlineAlignSidebar.tsx
@@ -24,11 +24,9 @@ export const OutlineAlignSidebar = () => {
return (
diff --git a/src/course-outline/outline-sidebar/OutlineHelpSidebar.tsx b/src/course-outline/outline-sidebar/OutlineHelpSidebar.tsx
index aef1bcdd24..47eb83aeed 100644
--- a/src/course-outline/outline-sidebar/OutlineHelpSidebar.tsx
+++ b/src/course-outline/outline-sidebar/OutlineHelpSidebar.tsx
@@ -40,9 +40,7 @@ const OutlineHelpSideBar = () => {
key={title}
title={title}
>
- {descriptions.map((description) => (
- {description}
- ))}
+ {descriptions.map((description) => {description}
)}
{!!link?.href && (
(
);
-const renderComponent = () => render(
- ,
- { extraWrapper },
-);
+const renderComponent = () =>
+ render(
+ ,
+ { extraWrapper },
+ );
describe('', () => {
beforeEach(() => {
diff --git a/src/course-outline/outline-sidebar/OutlineSidebarContext.tsx b/src/course-outline/outline-sidebar/OutlineSidebarContext.tsx
index 1e93894663..ff56832a09 100644
--- a/src/course-outline/outline-sidebar/OutlineSidebarContext.tsx
+++ b/src/course-outline/outline-sidebar/OutlineSidebarContext.tsx
@@ -47,7 +47,7 @@ interface OutlineSidebarContextData {
/** Stores last section that allows adding subsections inside it. */
lastEditableSection?: XBlock;
/** Stores last subsection that allows adding units inside it and its parent sectionId */
- lastEditableSubsection?: { data?: XBlock, sectionId?: string };
+ lastEditableSubsection?: { data?: XBlock; sectionId?: string; };
/** XBlock data of selectedContainerState.currentId */
currentItemData?: XBlock;
}
@@ -59,7 +59,7 @@ const getLastEditableItem = (blockList: Array) => findLast(blockList, (i
const getLastEditableSubsection = (
blockList: Array,
startIndex?: number,
-): { data: XBlock, sectionId: string } | undefined => {
+): { data: XBlock; sectionId: string; } | undefined => {
const lastSectionIndex = findLastIndex(blockList, (item) => item.actions.childAddable, startIndex);
if (lastSectionIndex !== -1) {
const lastSubsectionIndex = findLastIndex(
@@ -79,7 +79,7 @@ const getLastEditableSubsection = (
return undefined;
};
-export const OutlineSidebarProvider = ({ children }: { children?: React.ReactNode }) => {
+export const OutlineSidebarProvider = ({ children }: { children?: React.ReactNode; }) => {
const [currentPageKey, setCurrentPageKeyState] = useStateWithUrlSearchParam(
'info',
'sidebar',
@@ -95,22 +95,22 @@ export const OutlineSidebarProvider = ({ children }: { children?: React.ReactNod
const [isOpen, open, , toggle] = useToggle(true);
/**
- * Use this to store the selected container's information and should always contain full ancestor info.
- * If selected container is a section, set containerId and sectionId to same value and subsectionId should
- * be undefined.
- * If selected container is a subsection, set containerId and subsectionId to same value and sectionId
- * should be set to its parent section id.
- * If selected container is an unit, set containerId as unitId, subsectionId as its parent subsection's id
- * and sectionId should be set to its top parent section's id.
- */
+ * Use this to store the selected container's information and should always contain full ancestor info.
+ * If selected container is a section, set containerId and sectionId to same value and subsectionId should
+ * be undefined.
+ * If selected container is a subsection, set containerId and subsectionId to same value and sectionId
+ * should be set to its parent section id.
+ * If selected container is an unit, set containerId as unitId, subsectionId as its parent subsection's id
+ * and sectionId should be set to its top parent section's id.
+ */
const [selectedContainerState, setSelectedContainerState] = useState();
const { setCurrentSelection } = useCourseOutlineContext();
/**
- * Set currentSelection to same as selectedContainerState whenever
- * selectedContainerState or currentPageKey changes.
- * This allows us to reset the currentSelection.
- */
+ * Set currentSelection to same as selectedContainerState whenever
+ * selectedContainerState or currentPageKey changes.
+ * This allows us to reset the currentSelection.
+ */
useEffect(() => {
// To allow tag buttons on other cards to jump to align page and not loose its selection
if (currentPageKey !== 'align') {
@@ -146,10 +146,10 @@ export const OutlineSidebarProvider = ({ children }: { children?: React.ReactNod
}, [selectedContainerState]);
/**
- * Starts add content flow.
- * The sidebar enters an add content flow which allows user to add content in a specific container.
- * A placeholder container is added in the location when the flow is started.
- */
+ * Starts add content flow.
+ * The sidebar enters an add content flow which allows user to add content in a specific container.
+ * A placeholder container is added in the location when the flow is started.
+ */
const startCurrentFlow = useCallback((flow: OutlineFlow) => {
setCurrentPageKey('add');
setCurrentFlow(flow);
diff --git a/src/course-outline/outline-sidebar/OutlineSidebarPagesContext.tsx b/src/course-outline/outline-sidebar/OutlineSidebarPagesContext.tsx
index fc4e3d427a..e95adfce4f 100644
--- a/src/course-outline/outline-sidebar/OutlineSidebarPagesContext.tsx
+++ b/src/course-outline/outline-sidebar/OutlineSidebarPagesContext.tsx
@@ -1,7 +1,10 @@
import { createContext, useContext, useMemo } from 'react';
import { getConfig } from '@edx/frontend-platform';
import {
- HelpOutline, Info, Plus, Tag,
+ HelpOutline,
+ Info,
+ Plus,
+ Tag,
} from '@openedx/paragon/icons';
import type { SidebarPage } from '@src/generic/sidebar';
@@ -95,6 +98,10 @@ export const OutlineSidebarPagesProvider = ({ children }: OutlineSidebarPagesPro
export const useOutlineSidebarPagesContext = (): OutlineSidebarPages => {
const ctx = useContext(OutlineSidebarPagesContext);
// istanbul ignore if: this should never happen
- if (ctx === undefined) { throw new Error('useOutlineSidebarPages must be used within an OutlineSidebarPagesProvider'); }
+ if (ctx === undefined) {
+ throw new Error(
+ 'useOutlineSidebarPages must be used within an OutlineSidebarPagesProvider',
+ );
+ }
return ctx;
};
diff --git a/src/course-outline/outline-sidebar/info-sidebar/InfoSidebar.test.tsx b/src/course-outline/outline-sidebar/info-sidebar/InfoSidebar.test.tsx
index 62308b27da..a8e27aaf3d 100644
--- a/src/course-outline/outline-sidebar/info-sidebar/InfoSidebar.test.tsx
+++ b/src/course-outline/outline-sidebar/info-sidebar/InfoSidebar.test.tsx
@@ -1,4 +1,4 @@
-import { fireEvent,initializeMocks, render, screen } from '@src/testUtils';
+import { fireEvent, initializeMocks, render, screen } from '@src/testUtils';
import { getCourseSettingsApiUrl } from '@src/data/api';
import type { SelectionState } from '@src/data/types';
import { OutlineSidebarProvider } from '@src/course-outline/outline-sidebar/OutlineSidebarContext';
@@ -102,7 +102,7 @@ describe('InfoSidebar component', () => {
it('shows the settings link for the course', async () => {
const user = userEvent.setup();
renderComponent();
- await user.click((await screen.findByRole('tab', { name: 'Settings' })));
+ await user.click(await screen.findByRole('tab', { name: 'Settings' }));
const links = await screen.findAllByRole('link');
expect(links).toHaveLength(5);
expect(links[0]).toHaveTextContent('Schedule & details');
@@ -760,4 +760,4 @@ describe('InfoSidebar component', () => {
});
});
});
-});
\ No newline at end of file
+});
diff --git a/src/course-outline/outline-sidebar/info-sidebar/InfoSidebar.tsx b/src/course-outline/outline-sidebar/info-sidebar/InfoSidebar.tsx
index 756e657800..064f5fa3e6 100644
--- a/src/course-outline/outline-sidebar/info-sidebar/InfoSidebar.tsx
+++ b/src/course-outline/outline-sidebar/info-sidebar/InfoSidebar.tsx
@@ -8,9 +8,7 @@ import { UnitSidebar } from './UnitInfoSidebar';
export const InfoSidebar = () => {
const { selectedContainerState } = useOutlineSidebarContext();
if (!selectedContainerState) {
- return (
-
- );
+ return ;
}
const itemType = getBlockType(selectedContainerState.currentId);
diff --git a/src/course-outline/outline-sidebar/info-sidebar/SectionInfoSidebar.tsx b/src/course-outline/outline-sidebar/info-sidebar/SectionInfoSidebar.tsx
index 7ea24993b5..2ecd19ffb3 100644
--- a/src/course-outline/outline-sidebar/info-sidebar/SectionInfoSidebar.tsx
+++ b/src/course-outline/outline-sidebar/info-sidebar/SectionInfoSidebar.tsx
@@ -51,7 +51,9 @@ export const SectionSidebar = () => {
const handleMove = (step: number) => {
if (index !== undefined) {
updateSectionOrderByIndex(index, index + step);
- setSelectedContainerState(selectedContainerState ? { ...selectedContainerState, index: index + step } : undefined);
+ setSelectedContainerState(
+ selectedContainerState ? { ...selectedContainerState, index: index + step } : undefined,
+ );
}
};
diff --git a/src/course-outline/outline-sidebar/info-sidebar/SectionSettings.test.tsx b/src/course-outline/outline-sidebar/info-sidebar/SectionSettings.test.tsx
index 977dafd1ef..d2c3d5654c 100644
--- a/src/course-outline/outline-sidebar/info-sidebar/SectionSettings.test.tsx
+++ b/src/course-outline/outline-sidebar/info-sidebar/SectionSettings.test.tsx
@@ -12,9 +12,14 @@ jest.mock('@src/course-outline/highlights-modal/HighlightsModal', () => ({
onSubmit({
- highlight_1: 'one', highlight_2: '', highlight_3: 'two', highlight_4: '', highlight_5: '',
- })}
+ onClick={() =>
+ onSubmit({
+ highlight_1: 'one',
+ highlight_2: '',
+ highlight_3: 'two',
+ highlight_4: '',
+ highlight_5: '',
+ })}
>
Submit Highlights
@@ -69,7 +74,10 @@ describe('SectionSettings', () => {
it('renders highlights, release and visibility and calls mutates with expected payloads', async () => {
// course not self paced -> ReleaseSection should render
apiHooks.useCourseDetails.mockReturnValue({ data: { selfPaced: false } });
- apiHooks.useCourseItemData.mockReturnValue({ data: { visibilityState: 'staff_only', start: '2020-01-01' }, isPending: false });
+ apiHooks.useCourseItemData.mockReturnValue({
+ data: { visibilityState: 'staff_only', start: '2020-01-01' },
+ isPending: false,
+ });
const user = userEvent.setup();
render(
);
@@ -80,11 +88,15 @@ describe('SectionSettings', () => {
// Release button should be present and calling it should call configure mutate
await user.click(await screen.findByRole('button', { name: 'Release' }));
- expect(configureMutate).toHaveBeenCalledWith(expect.objectContaining({ sectionId, isVisibleToStaffOnly: true, startDatetime: '2025-01-01' }));
+ expect(configureMutate).toHaveBeenCalledWith(
+ expect.objectContaining({ sectionId, isVisibleToStaffOnly: true, startDatetime: '2025-01-01' }),
+ );
// Visibility button should also call configure mutate
await user.click(await screen.findByRole('button', { name: 'Visibility' }));
- expect(configureMutate).toHaveBeenCalledWith(expect.objectContaining({ sectionId, isVisibleToStaffOnly: true, visibility: 'changed' }));
+ expect(configureMutate).toHaveBeenCalledWith(
+ expect.objectContaining({ sectionId, isVisibleToStaffOnly: true, visibility: 'changed' }),
+ );
});
it('does not render ReleaseSection when course is self paced', () => {
diff --git a/src/course-outline/outline-sidebar/info-sidebar/SectionSettings.tsx b/src/course-outline/outline-sidebar/info-sidebar/SectionSettings.tsx
index 27c049b126..d5c6d8b7b4 100644
--- a/src/course-outline/outline-sidebar/info-sidebar/SectionSettings.tsx
+++ b/src/course-outline/outline-sidebar/info-sidebar/SectionSettings.tsx
@@ -1,5 +1,8 @@
import {
- useConfigureSection, useCourseDetails, useCourseItemData, useUpdateCourseSectionHighlights,
+ useConfigureSection,
+ useCourseDetails,
+ useCourseItemData,
+ useUpdateCourseSectionHighlights,
} from '@src/course-outline/data/apiHooks';
import { useCourseAuthoringContext } from '@src/CourseAuthoringContext';
import { SidebarContent } from '@src/generic/sidebar';
@@ -22,9 +25,7 @@ const Highlights = ({ sectionId }: Props) => {
highlights: dataToSend,
});
};
- return (
-
- );
+ return
;
};
export const SectionSettings = ({ sectionId }: Props) => {
@@ -48,12 +49,12 @@ export const SectionSettings = ({ sectionId }: Props) => {
return (
- { !courseDetails?.selfPaced && (
- onChange({ startDatetime: val })}
- />
- ) }
+ {!courseDetails?.selfPaced && (
+ onChange({ startDatetime: val })}
+ />
+ )}
{
if (isLoading || !subsectionData) {
return ;
}
-
+
// re-create actions object for customizations
const actions = { ...subsectionData.actions };
actions.deletable = actions.deletable && !section?.upstreamInfo?.upstreamRef;
actions.duplicable = actions.duplicable && !section?.upstreamInfo?.upstreamRef;
- const getPossibleMoves = section ? possibleSubsectionMoves(
- [...sections],
- sectionIndex ?? -1,
- section,
- section.childInfo.children,
- ) : undefined;
+ const getPossibleMoves = section ?
+ possibleSubsectionMoves(
+ [...sections],
+ sectionIndex ?? -1,
+ section,
+ section.childInfo.children,
+ ) :
+ undefined;
const canMoveSubsection = (oldIndex: number, step: number) => {
if (getPossibleMoves && section) {
@@ -91,14 +93,18 @@ export const SubsectionSidebar = () => {
? (step === -1 ? sections[newSectionIndex].childInfo.children.length : 0)
: index + step;
// istanbul ignore next
- setSelectedContainerState(selectedContainerState ? {
- ...selectedContainerState,
- sectionId: newSectionId,
- index: newIndex,
- } : undefined);
+ setSelectedContainerState(
+ selectedContainerState ?
+ {
+ ...selectedContainerState,
+ sectionId: newSectionId,
+ index: newIndex,
+ } :
+ undefined,
+ );
}
}
- }
+ };
return (
<>
@@ -114,10 +120,11 @@ export const SubsectionSidebar = () => {
onClickDuplicate: handleDuplicateSubsectionSubmit,
onClickMoveUp: () => handleMove(-1),
onClickMoveDown: () => handleMove(1),
- onClickUnlink: () => openUnlinkModal({
- value: subsectionData,
- sectionId: selectedContainerState?.sectionId,
- }),
+ onClickUnlink: () =>
+ openUnlinkModal({
+ value: subsectionData,
+ sectionId: selectedContainerState?.sectionId,
+ }),
onClickDelete: openDeleteModal,
onClickViewLibrary: () => {
const upstreamRef = subsectionData?.upstreamInfo?.upstreamRef;
diff --git a/src/course-outline/outline-sidebar/info-sidebar/SubsectionSettings.test.tsx b/src/course-outline/outline-sidebar/info-sidebar/SubsectionSettings.test.tsx
index 3cd14e194b..42eebde572 100644
--- a/src/course-outline/outline-sidebar/info-sidebar/SubsectionSettings.test.tsx
+++ b/src/course-outline/outline-sidebar/info-sidebar/SubsectionSettings.test.tsx
@@ -36,9 +36,7 @@ jest.mock('@src/generic/datepicker-control', () => ({
// Mock nested components: ReleaseSection, VisibilitySection, AdvancedTab
jest.mock('./sharedSettings/ReleaseSection', () => ({
__esModule: true,
- ReleaseSection: ({ onChange }: any) => (
- onChange('2030-01-01')}>Release
- ),
+ ReleaseSection: ({ onChange }: any) => onChange('2030-01-01')}>Release ,
}));
jest.mock('./sharedSettings/VisibilitySection', () => ({
@@ -112,11 +110,15 @@ describe('SubsectionSettings', () => {
// Release
await user.click(await screen.findByRole('button', { name: 'Release' }));
- expect(mutate).toHaveBeenCalledWith(expect.objectContaining({ itemId: subsectionId, sectionId: 'section-abc', releaseDate: '2030-01-01' }));
+ expect(mutate).toHaveBeenCalledWith(
+ expect.objectContaining({ itemId: subsectionId, sectionId: 'section-abc', releaseDate: '2030-01-01' }),
+ );
// Visibility
await user.click(await screen.findByRole('button', { name: 'Visibility' }));
- expect(mutate).toHaveBeenCalledWith(expect.objectContaining({ itemId: subsectionId, sectionId: 'section-abc', visibility: 'v' }));
+ expect(mutate).toHaveBeenCalledWith(
+ expect.objectContaining({ itemId: subsectionId, sectionId: 'section-abc', visibility: 'v' }),
+ );
// Grading -> Ungraded
await user.click(await screen.findByRole('button', { name: 'Ungraded' }));
@@ -131,7 +133,10 @@ describe('SubsectionSettings', () => {
apiHooks.useCourseDetails.mockReturnValue({ data: { selfPaced: false } });
apiHooks.useCourseItemData.mockReturnValue({
data: {
- ...baseItemData, graded: false, prereqMinScore: '50', prereqMinCompletion: '75',
+ ...baseItemData,
+ graded: false,
+ prereqMinScore: '50',
+ prereqMinCompletion: '75',
},
isPending: false,
});
@@ -199,7 +204,10 @@ describe('SubsectionSettings', () => {
it('resets grading local state when itemData changes', async () => {
apiHooks.useCourseDetails.mockReturnValue({ data: { selfPaced: false } });
const firstItemData = {
- ...baseItemData, format: 'g1', due: '2024-01-01', graded: true,
+ ...baseItemData,
+ format: 'g1',
+ due: '2024-01-01',
+ graded: true,
};
const secondItemData = { ...firstItemData, format: 'g2', due: '2024-02-02' };
diff --git a/src/course-outline/outline-sidebar/info-sidebar/SubsectionSettings.tsx b/src/course-outline/outline-sidebar/info-sidebar/SubsectionSettings.tsx
index 766e6fd47f..10fa8e279c 100644
--- a/src/course-outline/outline-sidebar/info-sidebar/SubsectionSettings.tsx
+++ b/src/course-outline/outline-sidebar/info-sidebar/SubsectionSettings.tsx
@@ -1,6 +1,9 @@
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import {
- Button, ButtonGroup, Form, Stack,
+ Button,
+ ButtonGroup,
+ Form,
+ Stack,
} from '@openedx/paragon';
import { useConfigureSubsection, useCourseDetails, useCourseItemData } from '@src/course-outline/data/apiHooks';
import { getProctoredExamsFlag, getTimedExamsFlag } from '@src/course-outline/data/selectors';
@@ -12,7 +15,10 @@ import { DatepickerControl, DATEPICKER_TYPES } from '@src/generic/datepicker-con
import { SidebarContent, SidebarSection } from '@src/generic/sidebar';
import { useStateWithCallback } from '@src/hooks';
import {
- useCallback, useEffect, useRef, useState,
+ useCallback,
+ useEffect,
+ useRef,
+ useState,
} from 'react';
import { useSelector } from 'react-redux';
import { ReleaseSection } from './sharedSettings/ReleaseSection';
@@ -71,9 +77,8 @@ const GradingSection = ({ subsectionId, onChange }: SubProps) => {
onChange({ graderType: 'notgraded' });
};
- const createOptions = () => itemData?.courseGraders?.map((option) => (
- {option}
- ));
+ const createOptions = () =>
+ itemData?.courseGraders?.map((option) => {option} );
return (
{
{graded
&& (
-
-
-
-
- setLocalState((prev) => ({ ...prev, graderType: e.target.value }))}
- data-testid="grader-type-select"
- >
-
- {intl.formatMessage(messages.subsectionGradingDropdownPlaceholder)}
-
- {createOptions()}
-
-
+
+
+
+
+ setLocalState((prev) => ({ ...prev, graderType: e.target.value }))}
+ data-testid="grader-type-select"
+ >
+
+ {intl.formatMessage(messages.subsectionGradingDropdownPlaceholder)}
+
+ {createOptions()}
+
+
)}
{!courseDetails?.selfPaced && graded
&& (
-
- setLocalState((prev) => ({ ...prev, dueDate: val }))}
- data-testid="due-date-picker"
- />
- setLocalState((prev) => ({ ...prev, dueDate: val }))}
- />
-
+
+ setLocalState((prev) => ({ ...prev, dueDate: val }))}
+ data-testid="due-date-picker"
+ />
+ setLocalState((prev) => ({ ...prev, dueDate: val }))}
+ />
+
)}
);
@@ -183,9 +188,10 @@ const AssessmentResultVisibilitySection = ({ subsectionId, onChange }: SubProps)
) => setLocalState({
- showCorrectness: e.target.checked ? 'past_due' : 'never',
- })}
+ onChange={(e: React.ChangeEvent) =>
+ setLocalState({
+ showCorrectness: e.target.checked ? 'past_due' : 'never',
+ })}
>
@@ -282,12 +288,12 @@ export const SubsectionSettings = ({ subsectionId }: Props) => {
return (
- { !courseDetails?.selfPaced && (
- onChange({ releaseDate: val })}
- />
- ) }
+ {!courseDetails?.selfPaced && (
+ onChange({ releaseDate: val })}
+ />
+ )}
({
useCourseOutlineContext: jest.fn(),
}));
-jest.mock('./PublishButon', () => ({ PublishButon: ({ onClick }: any) => Publish }));
+jest.mock(
+ './PublishButon',
+ () => ({ PublishButon: ({ onClick }: any) => Publish }),
+);
jest.mock('./InfoSection', () => ({ InfoSection: ({ itemId }: any) => InfoSection:{itemId}
}));
-jest.mock('@src/course-unit/unit-sidebar/unit-info/GenericUnitInfoSettings', () => ({ GenericUnitInfoSettings: () => GenericUnitInfoSettings
}));
+jest.mock(
+ '@src/course-unit/unit-sidebar/unit-info/GenericUnitInfoSettings',
+ () => ({ GenericUnitInfoSettings: () => GenericUnitInfoSettings
}),
+);
jest.mock('@src/generic/block-type-utils', () => ({ getItemIcon: () => () => null }));
-jest.mock('@src/course-unit/xblock-container-iframe', () => function XBlockIframe() {
- return XBlockIframe
;
-});
-jest.mock('@src/generic/hooks/context/iFrameContext', () => ({ IframeProvider: ({ children }: any) => {children}
}));
+jest.mock('@src/course-unit/xblock-container-iframe', () =>
+ function XBlockIframe() {
+ return XBlockIframe
;
+ });
+jest.mock(
+ '@src/generic/hooks/context/iFrameContext',
+ () => ({ IframeProvider: ({ children }: any) => {children}
}),
+);
const apiHooks = jest.requireMock('@src/course-outline/data/apiHooks') as any;
const outlineContext = jest.requireMock('../OutlineSidebarContext') as any;
@@ -60,7 +70,10 @@ describe('UnitSidebar', () => {
it('renders title and info tab by default', () => {
apiHooks.useCourseItemData.mockReturnValue({
data: {
- displayName: 'Unit 1', hasChanges: false, category: 'vertical', id: 'unit-1',
+ displayName: 'Unit 1',
+ hasChanges: false,
+ category: 'vertical',
+ id: 'unit-1',
actions: { deletable: true, duplicable: true },
},
isPending: false,
@@ -87,7 +100,10 @@ describe('UnitSidebar', () => {
});
apiHooks.useCourseItemData.mockReturnValue({
data: {
- displayName: 'Unit 2', hasChanges: true, category: 'vertical', id: 'unit-2',
+ displayName: 'Unit 2',
+ hasChanges: true,
+ category: 'vertical',
+ id: 'unit-2',
actions: { deletable: true, duplicable: true },
},
isPending: false,
@@ -108,7 +124,10 @@ describe('UnitSidebar', () => {
});
apiHooks.useCourseItemData.mockReturnValue({
data: {
- displayName: 'Unit 3', hasChanges: false, category: 'vertical', id: 'unit-3',
+ displayName: 'Unit 3',
+ hasChanges: false,
+ category: 'vertical',
+ id: 'unit-3',
actions: { deletable: true, duplicable: true },
},
isPending: false,
@@ -127,8 +146,13 @@ describe('UnitSidebar', () => {
});
apiHooks.useCourseItemData.mockReturnValue({
data: {
- displayName: 'Unit 4', hasChanges: false, category: 'vertical', id: 'unit-4',
- visibilityState: undefined, discussionEnabled: false, userPartitionInfo: null,
+ displayName: 'Unit 4',
+ hasChanges: false,
+ category: 'vertical',
+ id: 'unit-4',
+ visibilityState: undefined,
+ discussionEnabled: false,
+ userPartitionInfo: null,
actions: { deletable: true, duplicable: true },
},
isPending: false,
diff --git a/src/course-outline/outline-sidebar/info-sidebar/UnitInfoSidebar.tsx b/src/course-outline/outline-sidebar/info-sidebar/UnitInfoSidebar.tsx
index 1a6f324c0e..d0169ed41a 100644
--- a/src/course-outline/outline-sidebar/info-sidebar/UnitInfoSidebar.tsx
+++ b/src/course-outline/outline-sidebar/info-sidebar/UnitInfoSidebar.tsx
@@ -3,7 +3,10 @@ import { isEmpty } from 'lodash';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
- Button, Stack, Tab, Tabs,
+ Button,
+ Stack,
+ Tab,
+ Tabs,
} from '@openedx/paragon';
import {
OpenInFull,
@@ -146,16 +149,21 @@ export const UnitSidebar = () => {
/* istanbul ignore next */
const newIndex = isCrossSubsection
? (step === -1
- ? sections[newSectionIndex].childInfo.children.find((s) => s.id === newSubsectionId)?.childInfo.children.length ?? 0
+ ? sections[newSectionIndex].childInfo.children.find((s) => s.id === newSubsectionId)?.childInfo.children
+ .length ?? 0
: 0)
: index + step;
/* istanbul ignore next */
- setSelectedContainerState(selectedContainerState ? {
- ...selectedContainerState,
- sectionId: newSectionId,
- subsectionId: newSubsectionId,
- index: newIndex,
- } : undefined);
+ setSelectedContainerState(
+ selectedContainerState ?
+ {
+ ...selectedContainerState,
+ sectionId: newSectionId,
+ subsectionId: newSubsectionId,
+ index: newIndex,
+ } :
+ undefined,
+ );
}
}
};
@@ -170,7 +178,7 @@ export const UnitSidebar = () => {
if (navigator.clipboard) {
// Modern approach: requires HTTPS (secure context)
void navigator.clipboard.writeText(locationId);
- } else /* istanbul ignore next */ {
+ } /* istanbul ignore next */ else {
// Fallback for HTTP (non-secure) dev environments
// Note: execCommand is deprecated but still widely supported as fallback
const textarea = document.createElement('textarea');
@@ -197,11 +205,12 @@ export const UnitSidebar = () => {
onClickDuplicate: unitData?.actions?.duplicable ? handleDuplicateUnitSubmit : undefined,
onClickMoveUp: () => handleMove(-1),
onClickMoveDown: () => handleMove(1),
- onClickUnlink: () => openUnlinkModal({
- value: unitData,
- sectionId: selectedContainerState?.sectionId,
- subsectionId: selectedContainerState?.subsectionId,
- }),
+ onClickUnlink: () =>
+ openUnlinkModal({
+ value: unitData,
+ sectionId: selectedContainerState?.sectionId,
+ subsectionId: selectedContainerState?.subsectionId,
+ }),
onClickDelete: openDeleteModal,
onClickViewLibrary: () => {
const upstreamRef = unitData?.upstreamInfo?.upstreamRef;
@@ -224,9 +233,7 @@ export const UnitSidebar = () => {
>
{intl.formatMessage(messages.openUnitPage)}
- {unitData?.hasChanges && (
-
- )}
+ {unitData?.hasChanges && }
({
jest.mock('@src/generic/datepicker-control', () => ({
DATEPICKER_TYPES: { date: 'date', time: 'time' },
DatepickerControl: ({ onChange, type }: any) => (
- onChange(type === 'date' ? '2025-12-31' : '12:00')}>
+ onChange(type === 'date' ? '2025-12-31' : '12:00')}
+ >
{type}
),
diff --git a/src/course-outline/outline-sidebar/info-sidebar/sharedSettings/ReleaseSection.tsx b/src/course-outline/outline-sidebar/info-sidebar/sharedSettings/ReleaseSection.tsx
index 45c48d45d7..388c28657e 100644
--- a/src/course-outline/outline-sidebar/info-sidebar/sharedSettings/ReleaseSection.tsx
+++ b/src/course-outline/outline-sidebar/info-sidebar/sharedSettings/ReleaseSection.tsx
@@ -40,6 +40,5 @@ export const ReleaseSection = ({ itemId, onChange }: Props) => {
/>
-
);
};
diff --git a/src/course-outline/outline-sidebar/info-sidebar/sharedSettings/VisibilitySection.test.tsx b/src/course-outline/outline-sidebar/info-sidebar/sharedSettings/VisibilitySection.test.tsx
index 23d226f205..6662da23b7 100644
--- a/src/course-outline/outline-sidebar/info-sidebar/sharedSettings/VisibilitySection.test.tsx
+++ b/src/course-outline/outline-sidebar/info-sidebar/sharedSettings/VisibilitySection.test.tsx
@@ -1,5 +1,8 @@
import {
- initializeMocks, render, screen, waitFor,
+ initializeMocks,
+ render,
+ screen,
+ waitFor,
} from '@src/testUtils';
import userEvent from '@testing-library/user-event';
import { useCourseItemData } from '@src/course-outline/data/apiHooks';
diff --git a/src/course-outline/outline-sidebar/info-sidebar/sharedSettings/VisibilitySection.tsx b/src/course-outline/outline-sidebar/info-sidebar/sharedSettings/VisibilitySection.tsx
index d8c1807fad..0482f9dce0 100644
--- a/src/course-outline/outline-sidebar/info-sidebar/sharedSettings/VisibilitySection.tsx
+++ b/src/course-outline/outline-sidebar/info-sidebar/sharedSettings/VisibilitySection.tsx
@@ -48,27 +48,29 @@ export const VisibilitySection = ({ itemId, isSubsection, onChange }: Props) =>
setLocalState((prev) => ({
- ...prev,
- isVisibleToStaffOnly: true,
- hideAfterDue: false,
- }))}
+ onClick={() =>
+ setLocalState((prev) => ({
+ ...prev,
+ isVisibleToStaffOnly: true,
+ hideAfterDue: false,
+ }))}
>
{isSubsection && !localState?.isVisibleToStaffOnly && (
- ) => setLocalState((prev) => ({
- ...prev,
- hideAfterDue: e.target.checked,
- isVisibleToStaffOnly: false,
- }))}
- >
-
-
+ ) =>
+ setLocalState((prev) => ({
+ ...prev,
+ hideAfterDue: e.target.checked,
+ isVisibleToStaffOnly: false,
+ }))}
+ >
+
+
)}
);
diff --git a/src/course-outline/page-alerts/PageAlerts.jsx b/src/course-outline/page-alerts/PageAlerts.jsx
index b949fe2e36..902b17910d 100644
--- a/src/course-outline/page-alerts/PageAlerts.jsx
+++ b/src/course-outline/page-alerts/PageAlerts.jsx
@@ -1,7 +1,10 @@
import { getConfig } from '@edx/frontend-platform';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import {
- Alert, Button, Hyperlink, Truncate,
+ Alert,
+ Button,
+ Hyperlink,
+ Truncate,
} from '@openedx/paragon';
import {
Campaign as CampaignIcon,
@@ -223,7 +226,8 @@ const PageAlerts = ({
),
}}
/>
- ) : (
+ ) :
+ (
(
- msgObj.dismissible ? (
- dispatch(dismissError(msgObj.key))}
- >
- {msgObj.title}
- {msgObj.desc}
-
- ) : (
-
- {msgObj.title}
- {msgObj.desc}
-
- )
+ msgObj.dismissible ?
+ (
+ dispatch(dismissError(msgObj.key))}
+ >
+ {msgObj.title}
+ {msgObj.desc}
+
+ ) :
+ (
+
+ {msgObj.title}
+ {msgObj.desc}
+
+ )
))
);
};
diff --git a/src/course-outline/page-alerts/PageAlerts.test.jsx b/src/course-outline/page-alerts/PageAlerts.test.jsx
index 152b7e3266..9cf9c3420d 100644
--- a/src/course-outline/page-alerts/PageAlerts.test.jsx
+++ b/src/course-outline/page-alerts/PageAlerts.test.jsx
@@ -50,16 +50,17 @@ const pageAlertsData = {
savingStatus: '',
};
-const renderComponent = (props) => render(
-
-
-
-
- ,
-);
+const renderComponent = (props) =>
+ render(
+
+
+
+
+ ,
+ );
describe(' ', () => {
beforeEach(() => {
@@ -222,7 +223,10 @@ describe(' ', () => {
...pageAlertsData,
errors: {
outlineIndexApi: {
- data: 'some error', status: 403, type: API_ERROR_TYPES.forbidden, dismissable: false,
+ data: 'some error',
+ status: 403,
+ type: API_ERROR_TYPES.forbidden,
+ dismissable: false,
},
},
});
@@ -235,7 +239,10 @@ describe(' ', () => {
...pageAlertsData,
errors: {
outlineIndexApi: {
- data: 'some error', status: 500, type: API_ERROR_TYPES.serverError, dismissable: true,
+ data: 'some error',
+ status: 500,
+ type: API_ERROR_TYPES.serverError,
+ dismissable: true,
},
},
});
diff --git a/src/course-outline/publish-modal/PublishModal.test.tsx b/src/course-outline/publish-modal/PublishModal.test.tsx
index a1700d7190..cbd92788c6 100644
--- a/src/course-outline/publish-modal/PublishModal.test.tsx
+++ b/src/course-outline/publish-modal/PublishModal.test.tsx
@@ -83,9 +83,10 @@ jest.mock('@src/course-outline/data/apiHooks', () => ({
}),
}));
-const renderComponent = () => render(
- ,
-);
+const renderComponent = () =>
+ render(
+ ,
+ );
describe(' ', () => {
beforeEach(() => {
diff --git a/src/course-outline/publish-modal/PublishModal.tsx b/src/course-outline/publish-modal/PublishModal.tsx
index 060c59664c..7d16b9bfb5 100644
--- a/src/course-outline/publish-modal/PublishModal.tsx
+++ b/src/course-outline/publish-modal/PublishModal.tsx
@@ -17,7 +17,9 @@ const PublishModal = () => {
const intl = useIntl();
const { isPublishModalOpen, currentPublishModalData, closePublishModal } = useCourseOutlineContext();
const {
- id, displayName, category,
+ id,
+ displayName,
+ category,
} = currentPublishModalData?.value || {};
const categoryName = COURSE_BLOCK_NAMES[category || '']?.name.toLowerCase();
const childInfo = (currentPublishModalData?.value && 'childInfo' in currentPublishModalData.value)
@@ -63,26 +65,28 @@ const PublishModal = () => {
let grandChildren = 'childInfo' in child ? child.childInfo?.children : undefined;
grandChildren = grandChildren?.filter(grandChild => grandChild.hasChanges);
- return grandChildren?.length ? (
-
- {child.displayName}
- {grandChildren.map((grandChild) => (
-
- {grandChild.displayName}
-
- ))}
-
- ) : (
-
- {child.displayName}
-
- );
+ return grandChildren?.length ?
+ (
+
+ {child.displayName}
+ {grandChildren.map((grandChild) => (
+
+ {grandChild.displayName}
+
+ ))}
+
+ ) :
+ (
+
+ {child.displayName}
+
+ );
})}
@@ -95,7 +99,6 @@ const PublishModal = () => {
onClick={onPublishSubmit}
label={intl.formatMessage(messages.publishButton)}
/>
-
diff --git a/src/course-outline/section-card/SectionCard.test.tsx b/src/course-outline/section-card/SectionCard.test.tsx
index 2a15bb9696..e30e533e26 100644
--- a/src/course-outline/section-card/SectionCard.test.tsx
+++ b/src/course-outline/section-card/SectionCard.test.tsx
@@ -1,6 +1,12 @@
import { getConfig, setConfig } from '@edx/frontend-platform';
import {
- act, fireEvent, initializeMocks, render, screen, waitFor, within,
+ act,
+ fireEvent,
+ initializeMocks,
+ render,
+ screen,
+ waitFor,
+ within,
} from '@src/testUtils';
import { XBlock } from '@src/data/types';
import { Info } from '@openedx/paragon/icons';
@@ -90,32 +96,33 @@ const section = {
},
} satisfies Partial as XBlock;
-const renderComponent = (props?: object, entry = '/course/:courseId') => render(
-
- children
- ,
- {
- path: '/course/:courseId',
- params: { courseId: '5' },
- routerProps: {
- initialEntries: [entry],
+const renderComponent = (props?: object, entry = '/course/:courseId') =>
+ render(
+
+ children
+ ,
+ {
+ path: '/course/:courseId',
+ params: { courseId: '5' },
+ routerProps: {
+ initialEntries: [entry],
+ },
+ extraWrapper: OutlineSidebarContext.OutlineSidebarProvider,
},
- extraWrapper: OutlineSidebarContext.OutlineSidebarProvider,
- },
-);
+ );
let axiosMock;
describe(' ', () => {
@@ -149,7 +156,7 @@ describe(' ', () => {
expect(screen.getByTestId('section-card-header')).toBeInTheDocument();
// The card is not selected
- expect((await screen.findByTestId('section-card'))).not.toHaveClass('outline-card-selected');
+ expect(await screen.findByTestId('section-card')).not.toHaveClass('outline-card-selected');
// Get the that contains the card and click it to select the card
const el = container.querySelector('div.row.mx-0') as HTMLInputElement;
diff --git a/src/course-outline/section-card/SectionCard.tsx b/src/course-outline/section-card/SectionCard.tsx
index 0a32893ca8..a184c8583f 100644
--- a/src/course-outline/section-card/SectionCard.tsx
+++ b/src/course-outline/section-card/SectionCard.tsx
@@ -1,8 +1,16 @@
import {
- useContext, useEffect, useState, useRef, useCallback, ReactNode, useMemo,
+ useContext,
+ useEffect,
+ useState,
+ useRef,
+ useCallback,
+ ReactNode,
+ useMemo,
} from 'react';
import {
- Bubble, Button, useToggle,
+ Bubble,
+ Button,
+ useToggle,
} from '@openedx/paragon';
import { useSearchParams } from 'react-router-dom';
import classNames from 'classnames';
@@ -29,18 +37,18 @@ import { handleResponseErrors } from '@src/generic/saving-error-alert';
import messages from './messages';
interface SectionCardProps {
- section: XBlock,
- isSelfPaced: boolean,
- isCustomRelativeDatesActive: boolean,
- children: ReactNode,
- onOpenHighlightsModal: (section: XBlock) => void,
- onOpenConfigureModal: () => void,
- onOpenDeleteModal: () => void,
- onDuplicateSubmit: () => void,
- isSectionsExpanded: boolean,
- index: number,
- canMoveItem: (oldIndex: number, newIndex: number) => boolean,
- onOrderChange: (oldIndex: number, newIndex: number) => void,
+ section: XBlock;
+ isSelfPaced: boolean;
+ isCustomRelativeDatesActive: boolean;
+ children: ReactNode;
+ onOpenHighlightsModal: (section: XBlock) => void;
+ onOpenConfigureModal: () => void;
+ onOpenDeleteModal: () => void;
+ onDuplicateSubmit: () => void;
+ isSectionsExpanded: boolean;
+ index: number;
+ canMoveItem: (oldIndex: number, newIndex: number) => boolean;
+ onOrderChange: (oldIndex: number, newIndex: number) => void;
}
const SectionCard = ({
@@ -110,7 +118,7 @@ const SectionCard = ({
if (moment(initialData.editedOnRaw).isAfter(moment(section.editedOnRaw))) {
queryClient.cancelQueries({
queryKey: courseOutlineQueryKeys.courseItemId(initialData.id),
- // eslint-disable-next-line no-console
+ // eslint-disable-next-line no-console
}).catch((error) => console.error('Error cancelling query:', error));
queryClient.setQueryData(courseOutlineQueryKeys.courseItemId(initialData.id), initialData);
}
@@ -229,13 +237,13 @@ const SectionCard = ({
isExpanded={isExpanded}
onTitleClick={handleExpandContent}
namePrefix={namePrefix}
- prefixIcon={(
+ prefixIcon={
- )}
+ }
/>
);
@@ -285,10 +293,11 @@ const SectionCard = ({
status={sectionStatus}
hasChanges={hasChanges}
onClickMenuButton={handleClickMenuButton}
- onClickPublish={/* istanbul ignore next */ () => openPublishModal({
- value: section,
- sectionId: section.id,
- })}
+ onClickPublish={/* istanbul ignore next */ () =>
+ openPublishModal({
+ value: section,
+ sectionId: section.id,
+ })}
onClickConfigure={onOpenConfigureModal}
onClickDelete={onOpenDeleteModal}
onClickUnlink={() => openUnlinkModal({ value: section, sectionId: section.id })}
diff --git a/src/course-outline/status-bar/LegacyStatusBar.test.tsx b/src/course-outline/status-bar/LegacyStatusBar.test.tsx
index e6669d7f31..467c52e042 100644
--- a/src/course-outline/status-bar/LegacyStatusBar.test.tsx
+++ b/src/course-outline/status-bar/LegacyStatusBar.test.tsx
@@ -54,22 +54,23 @@ const statusBarData: CourseOutlineStatusBar = {
const queryClient = new QueryClient();
-const renderComponent = (props?: Partial) => render(
-
-
-
-
-
-
- ,
-);
+const renderComponent = (props?: Partial) =>
+ render(
+
+
+
+
+
+
+ ,
+ );
describe(' ', () => {
beforeEach(() => {
diff --git a/src/course-outline/status-bar/LegacyStatusBar.tsx b/src/course-outline/status-bar/LegacyStatusBar.tsx
index 5eb5449d14..d0370fa82f 100644
--- a/src/course-outline/status-bar/LegacyStatusBar.tsx
+++ b/src/course-outline/status-bar/LegacyStatusBar.tsx
@@ -2,7 +2,11 @@ import moment from 'moment/moment';
import { FormattedDate, useIntl } from '@edx/frontend-platform/i18n';
import { getConfig } from '@edx/frontend-platform/config';
import {
- Button, Hyperlink, Form, Stack, useToggle,
+ Button,
+ Hyperlink,
+ Form,
+ Stack,
+ useToggle,
} from '@openedx/paragon';
import { Link } from 'react-router-dom';
import { type ReactNode } from 'react';
@@ -18,8 +22,8 @@ import { getVideoSharingOptionText } from '@src/course-outline/utils';
import messages from './messages';
interface StatusBarItemProps {
- title: string,
- children: ReactNode,
+ title: string;
+ children: ReactNode;
}
const StatusBarItem = ({ title, children }: StatusBarItemProps) => (
@@ -32,11 +36,11 @@ const StatusBarItem = ({ title, children }: StatusBarItemProps) => (
);
export interface LegacyStatusBarProps {
- courseId: string,
- isLoading: boolean,
- openEnableHighlightsModal: () => void,
- handleVideoSharingOptionChange: (value: string) => void,
- statusBarData: CourseOutlineStatusBar,
+ courseId: string;
+ isLoading: boolean;
+ openEnableHighlightsModal: () => void;
+ handleVideoSharingOptionChange: (value: string) => void;
+ statusBarData: CourseOutlineStatusBar;
}
export const LegacyStatusBar = ({
@@ -65,7 +69,9 @@ export const LegacyStatusBar = ({
} = checklist;
const courseReleaseDateObj = moment.utc(courseReleaseDate, 'MMM DD, YYYY [at] HH:mm UTC', true);
- const checkListTitle = `${completedCourseLaunchChecks + completedCourseBestPracticesChecks}/${totalCourseLaunchChecks + totalCourseBestPracticesChecks}`;
+ const checkListTitle = `${completedCourseLaunchChecks + completedCourseBestPracticesChecks}/${
+ totalCourseLaunchChecks + totalCourseBestPracticesChecks
+ }`;
const {
contentHighlights: contentHighlightsUrl,
@@ -82,22 +88,29 @@ export const LegacyStatusBar = ({
return (
<>
-
+
- {courseReleaseDateObj.isValid() ? (
-
- ) : courseReleaseDate}
+ {courseReleaseDateObj.isValid() ?
+ (
+
+ ) :
+ courseReleaseDate}
@@ -117,15 +130,17 @@ export const LegacyStatusBar = ({
- {highlightsEnabledForMessaging ? (
-
- {intl.formatMessage(messages.highlightEmailsEnabled)}
-
- ) : (
-
- {intl.formatMessage(messages.highlightEmailsButton)}
-
- )}
+ {highlightsEnabledForMessaging ?
+ (
+
+ {intl.formatMessage(messages.highlightEmailsEnabled)}
+
+ ) :
+ (
+
+ {intl.formatMessage(messages.highlightEmailsButton)}
+
+ )}
- { /* eslint-disable-next-line jsx-a11y/anchor-is-valid */ }
+ {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
- {intl.formatMessage(messages.videoSharingTitle)}
-
+ {intl.formatMessage(messages.videoSharingTitle)}
-
)}
({
}),
}));
-const renderComponent = () => render(
- ,
-);
+const renderComponent = () =>
+ render(
+ ,
+ );
describe('NotificationStatusIcon', () => {
beforeEach(() => {
diff --git a/src/course-outline/status-bar/NotificationStatusIcon.tsx b/src/course-outline/status-bar/NotificationStatusIcon.tsx
index e988c31b1f..afc97f06e0 100644
--- a/src/course-outline/status-bar/NotificationStatusIcon.tsx
+++ b/src/course-outline/status-bar/NotificationStatusIcon.tsx
@@ -5,7 +5,7 @@ import { HookType, useDynamicHookShim } from './hooks';
import messages from './messages';
// Component that actually calls the loaded hook
-const NotificationHookConsumer = ({ hook }: { hook: () => HookType }) => {
+const NotificationHookConsumer = ({ hook }: { hook: () => HookType; }) => {
// The hook is now called on **every** render of this component
const { notificationAppData } = hook();
diff --git a/src/course-outline/status-bar/StatusBar.test.tsx b/src/course-outline/status-bar/StatusBar.test.tsx
index 25d1fb3604..5c7bd3cab5 100644
--- a/src/course-outline/status-bar/StatusBar.test.tsx
+++ b/src/course-outline/status-bar/StatusBar.test.tsx
@@ -37,14 +37,15 @@ jest.mock('@src/course-outline/data/apiHooks', () => ({
}),
}));
-const renderComponent = (props?: Partial) => render(
- ,
-);
+const renderComponent = (props?: Partial) =>
+ render(
+ ,
+ );
describe(' ', () => {
beforeEach(() => {
diff --git a/src/course-outline/status-bar/StatusBar.tsx b/src/course-outline/status-bar/StatusBar.tsx
index a2c1d0895a..a3d2f79b16 100644
--- a/src/course-outline/status-bar/StatusBar.tsx
+++ b/src/course-outline/status-bar/StatusBar.tsx
@@ -3,7 +3,10 @@ import { FormattedDate, FormattedMessage } from '@edx/frontend-platform/i18n';
import { Badge, Icon, Stack } from '@openedx/paragon';
import { Link } from 'react-router-dom';
import {
- Cached, ChecklistRtl, Description, Event,
+ Cached,
+ ChecklistRtl,
+ Description,
+ Event,
} from '@openedx/paragon/icons';
import type { ChecklistType, CourseOutlineStatusBar } from '@src/course-outline/data/types';
@@ -13,7 +16,7 @@ import { useCourseDetails } from '@src/course-outline/data/apiHooks';
import messages from './messages';
import { NotificationStatusIcon } from './NotificationStatusIcon';
-const CourseBadge = ({ startDate, endDate }: { startDate: Moment, endDate: Moment }) => {
+const CourseBadge = ({ startDate, endDate }: { startDate: Moment; endDate: Moment; }) => {
const now = moment().utc();
switch (true) {
case !startDate.isValid():
@@ -42,7 +45,7 @@ const CourseBadge = ({ startDate, endDate }: { startDate: Moment, endDate: Momen
}
};
-const UnpublishedBadgeStatus = ({ courseId }: { courseId: string }) => {
+const UnpublishedBadgeStatus = ({ courseId }: { courseId: string; }) => {
const { data } = useCourseDetails(courseId);
if (!data?.hasChanges) {
return null;
@@ -60,7 +63,7 @@ const UnpublishedBadgeStatus = ({ courseId }: { courseId: string }) => {
);
};
-const LibraryUpdates = ({ courseId }: { courseId: string }) => {
+const LibraryUpdates = ({ courseId }: { courseId: string; }) => {
const { data } = useEntityLinksSummaryByDownstreamContext(courseId);
const outOfSyncCount = data?.reduce((count, lib) => count + (lib.readyToSyncCount || 0), 0);
const url = `/course/${courseId}/libraries?tab=review`;
@@ -86,7 +89,10 @@ const LibraryUpdates = ({ courseId }: { courseId: string }) => {
};
const CourseDates = ({
- startDate, endDate, startDateRaw, datesLink,
+ startDate,
+ endDate,
+ startDateRaw,
+ datesLink,
}: {
startDate: Moment;
endDate: Moment;
diff --git a/src/course-outline/status-bar/hooks.ts b/src/course-outline/status-bar/hooks.ts
index 833f2f9b6d..a78ebc8051 100644
--- a/src/course-outline/status-bar/hooks.ts
+++ b/src/course-outline/status-bar/hooks.ts
@@ -5,8 +5,8 @@ export interface HookType {
notificationAppData: {
tabsCount?: {
count?: number;
- }
- }
+ };
+ };
}
// Load the hook module asynchronously
diff --git a/src/course-outline/subsection-card/SubsectionCard.test.tsx b/src/course-outline/subsection-card/SubsectionCard.test.tsx
index b2a1a3db56..586fb269e3 100644
--- a/src/course-outline/subsection-card/SubsectionCard.test.tsx
+++ b/src/course-outline/subsection-card/SubsectionCard.test.tsx
@@ -1,7 +1,13 @@
import { getConfig, setConfig } from '@edx/frontend-platform';
import { COMPONENT_TYPES } from '@src/generic/block-type-utils/constants';
import {
- act, fireEvent, initializeMocks, render, screen, waitFor, within,
+ act,
+ fireEvent,
+ initializeMocks,
+ render,
+ screen,
+ waitFor,
+ within,
} from '@src/testUtils';
import { XBlock } from '@src/data/types';
import { Info } from '@openedx/paragon/icons';
@@ -119,33 +125,34 @@ const section: XBlock = {
},
} satisfies Partial as XBlock;
-const renderComponent = (props?: object, entry = '/course/:courseId') => render(
-
- children
- ,
- {
- path: '/course/:courseId',
- params: { courseId: '5' },
- routerProps: {
- initialEntries: [entry],
+const renderComponent = (props?: object, entry = '/course/:courseId') =>
+ render(
+
+ children
+ ,
+ {
+ path: '/course/:courseId',
+ params: { courseId: '5' },
+ routerProps: {
+ initialEntries: [entry],
+ },
+ extraWrapper: OutlineSidebarContext.OutlineSidebarProvider,
},
- extraWrapper: OutlineSidebarContext.OutlineSidebarProvider,
- },
-);
+ );
describe(' ', () => {
beforeEach(() => {
diff --git a/src/course-outline/subsection-card/SubsectionCard.tsx b/src/course-outline/subsection-card/SubsectionCard.tsx
index 5cba67bbcd..2667533586 100644
--- a/src/course-outline/subsection-card/SubsectionCard.tsx
+++ b/src/course-outline/subsection-card/SubsectionCard.tsx
@@ -1,5 +1,11 @@
import {
- useContext, useEffect, useState, useRef, useCallback, ReactNode, useMemo,
+ useContext,
+ useEffect,
+ useState,
+ useRef,
+ useCallback,
+ ReactNode,
+ useMemo,
} from 'react';
import { useSearchParams } from 'react-router-dom';
import { useIntl } from '@edx/frontend-platform/i18n';
@@ -31,23 +37,23 @@ import { handleResponseErrors } from '@src/generic/saving-error-alert';
import messages from './messages';
interface SubsectionCardProps {
- section: XBlock,
- subsection: XBlock,
- children: ReactNode
- isSectionsExpanded: boolean,
- isSelfPaced: boolean,
- isCustomRelativeDatesActive: boolean,
- onOpenDeleteModal: () => void,
- onDuplicateSubmit: () => void,
- index: number,
- getPossibleMoves: (index: number, step: number) => void,
- onOrderChange: (section: XBlock, moveDetails: any) => void,
- onOpenConfigureModal: () => void,
+ section: XBlock;
+ subsection: XBlock;
+ children: ReactNode;
+ isSectionsExpanded: boolean;
+ isSelfPaced: boolean;
+ isCustomRelativeDatesActive: boolean;
+ onOpenDeleteModal: () => void;
+ onDuplicateSubmit: () => void;
+ index: number;
+ getPossibleMoves: (index: number, step: number) => void;
+ onOrderChange: (section: XBlock, moveDetails: any) => void;
+ onOpenConfigureModal: () => void;
onPasteClick: (
parentLocator: string,
subsectionId: string,
- sectionId: string
- ) => void,
+ sectionId: string,
+ ) => void;
}
const SubsectionCard = ({
@@ -149,7 +155,7 @@ const SubsectionCard = ({
if (moment(initialData.editedOnRaw).isAfter(moment(subsection.editedOnRaw))) {
queryClient.cancelQueries({
queryKey: courseOutlineQueryKeys.courseItemId(initialData.id),
- // eslint-disable-next-line no-console
+ // eslint-disable-next-line no-console
}).catch((error) => console.error('Error cancelling query:', error));
queryClient.setQueryData(courseOutlineQueryKeys.courseItemId(initialData.id), initialData);
}
@@ -202,13 +208,13 @@ const SubsectionCard = ({
isExpanded={isExpanded}
onTitleClick={handleExpandContent}
namePrefix={namePrefix}
- prefixIcon={(
+ prefixIcon={
- )}
+ }
/>
);
@@ -243,12 +249,10 @@ const SubsectionCard = ({
setIsExpanded((prevState) => (containsSearchResult() || prevState));
}, [locatorId, setIsExpanded]);
- const isDraggable = (
- actions.draggable
- && (actions.allowMoveUp || actions.allowMoveDown)
- && !(isHeaderVisible === false)
- && !section.upstreamInfo?.upstreamRef
- );
+ const isDraggable = actions.draggable
+ && (actions.allowMoveUp || actions.allowMoveDown)
+ && !(isHeaderVisible === false)
+ && !section.upstreamInfo?.upstreamRef;
const onClickCard = useCallback((e: React.MouseEvent, preventNodeEvents: boolean) => {
if (!preventNodeEvents || e.target === e.currentTarget) {
@@ -298,10 +302,11 @@ const SubsectionCard = ({
onClickMenuButton={handleClickMenuButton}
onClickPublish={() => openPublishModal({ value: subsection, sectionId: section.id })}
onClickDelete={onOpenDeleteModal}
- onClickUnlink={/* istanbul ignore next */ () => openUnlinkModal({
- value: subsection,
- sectionId: section.id,
- })}
+ onClickUnlink={/* istanbul ignore next */ () =>
+ openUnlinkModal({
+ value: subsection,
+ sectionId: section.id,
+ })}
onClickMoveUp={handleSubsectionMoveUp}
onClickMoveDown={handleSubsectionMoveDown}
onClickConfigure={onOpenConfigureModal}
@@ -338,7 +343,7 @@ const SubsectionCard = ({
>
)}
- {(isExpanded) && (
+ {isExpanded && (
as XBlock;
-const renderComponent = (props?: object) => render(
-
,
- {
- path: '/course/:courseId',
- params: { courseId: '5' },
- extraWrapper: OutlineSidebarContext.OutlineSidebarProvider,
- },
-);
+const renderComponent = (props?: object) =>
+ render(
+
,
+ {
+ path: '/course/:courseId',
+ params: { courseId: '5' },
+ extraWrapper: OutlineSidebarContext.OutlineSidebarProvider,
+ },
+ );
describe('
', () => {
beforeEach(() => {
diff --git a/src/course-outline/unit-card/UnitCard.tsx b/src/course-outline/unit-card/UnitCard.tsx
index a25993f6b4..4a3db964bd 100644
--- a/src/course-outline/unit-card/UnitCard.tsx
+++ b/src/course-outline/unit-card/UnitCard.tsx
@@ -36,8 +36,8 @@ interface UnitCardProps {
onOpenDeleteModal: () => void;
onDuplicateSubmit: () => void;
index: number;
- getPossibleMoves: (index: number, step: number) => void,
- onOrderChange: (section: XBlock, moveDetails: any) => void,
+ getPossibleMoves: (index: number, step: number) => void;
+ onOrderChange: (section: XBlock, moveDetails: any) => void;
isSelfPaced: boolean;
isCustomRelativeDatesActive: boolean;
discussionsSettings: {
@@ -183,13 +183,13 @@ const UnitCard = ({
title={displayName}
titleLink={getUnitUrl(id)}
namePrefix={namePrefix}
- prefixIcon={(
+ prefixIcon={
- )}
+ }
/>
);
@@ -208,7 +208,7 @@ const UnitCard = ({
if (moment(initialData.editedOnRaw).isAfter(moment(unit.editedOnRaw))) {
queryClient.cancelQueries({
queryKey: courseOutlineQueryKeys.courseItemId(initialData.id),
- // eslint-disable-next-line no-console
+ // eslint-disable-next-line no-console
}).catch((error) => console.error('Error cancelling query:', error));
queryClient.setQueryData(courseOutlineQueryKeys.courseItemId(initialData.id), initialData);
}
@@ -228,11 +228,9 @@ const UnitCard = ({
return null;
}
- const isDraggable = (
- actions.draggable
- && (actions.allowMoveUp || actions.allowMoveDown)
- && !subsection.upstreamInfo?.upstreamRef
- );
+ const isDraggable = actions.draggable
+ && (actions.allowMoveUp || actions.allowMoveDown)
+ && !subsection.upstreamInfo?.upstreamRef;
return (
<>
@@ -269,18 +267,20 @@ const UnitCard = ({
hasChanges={hasChanges}
cardId={id}
onClickMenuButton={selectAndTrigger}
- onClickPublish={() => openPublishModal({
- value: unit,
- sectionId: section.id,
- subsectionId: subsection.id,
- })}
+ onClickPublish={() =>
+ openPublishModal({
+ value: unit,
+ sectionId: section.id,
+ subsectionId: subsection.id,
+ })}
onClickConfigure={onOpenConfigureModal}
onClickDelete={onOpenDeleteModal}
- onClickUnlink={/* istanbul ignore next */ () => openUnlinkModal({
- value: unit,
- sectionId: section.id,
- subsectionId: subsection.id,
- })}
+ onClickUnlink={/* istanbul ignore next */ () =>
+ openUnlinkModal({
+ value: unit,
+ sectionId: section.id,
+ subsectionId: subsection.id,
+ })}
onClickMoveUp={handleUnitMoveUp}
onClickMoveDown={handleUnitMoveDown}
onClickSync={openSyncModal}
diff --git a/src/course-outline/utils/getChecklistForStatusBar.js b/src/course-outline/utils/getChecklistForStatusBar.js
index acab5d7eb3..fc0417c117 100644
--- a/src/course-outline/utils/getChecklistForStatusBar.js
+++ b/src/course-outline/utils/getChecklistForStatusBar.js
@@ -73,7 +73,4 @@ const getCourseBestPracticesChecklist = (data) => {
};
};
-export {
- getCourseLaunchChecklist,
- getCourseBestPracticesChecklist,
-};
+export { getCourseLaunchChecklist, getCourseBestPracticesChecklist };
diff --git a/src/course-outline/utils/getChecklistValues.js b/src/course-outline/utils/getChecklistValues.js
index ad9a49faaf..342c0a4714 100644
--- a/src/course-outline/utils/getChecklistValues.js
+++ b/src/course-outline/utils/getChecklistValues.js
@@ -55,21 +55,31 @@ const getChecklistValues = ({
let filteredCheckList;
if (isSelfPaced) {
- filteredCheckList = checklist.filter(({ pacingTypeFilter }) => pacingTypeFilter === CHECKLIST_FILTERS.ALL
- || pacingTypeFilter === CHECKLIST_FILTERS.SELF_PACED);
+ filteredCheckList = checklist.filter(({ pacingTypeFilter }) =>
+ pacingTypeFilter === CHECKLIST_FILTERS.ALL
+ || pacingTypeFilter === CHECKLIST_FILTERS.SELF_PACED
+ );
} else {
- filteredCheckList = checklist.filter(({ pacingTypeFilter }) => pacingTypeFilter === CHECKLIST_FILTERS.ALL
- || pacingTypeFilter === CHECKLIST_FILTERS.INSTRUCTOR_PACED);
+ filteredCheckList = checklist.filter(({ pacingTypeFilter }) =>
+ pacingTypeFilter === CHECKLIST_FILTERS.ALL
+ || pacingTypeFilter === CHECKLIST_FILTERS.INSTRUCTOR_PACED
+ );
}
- filteredCheckList = filteredCheckList.filter(({ id }) => id !== 'certificate'
- || hasCertificatesEnabled);
+ filteredCheckList = filteredCheckList.filter(({ id }) =>
+ id !== 'certificate'
+ || hasCertificatesEnabled
+ );
- filteredCheckList = filteredCheckList.filter(({ id }) => id !== 'weeklyHighlights'
- || hasHighlightsEnabled);
+ filteredCheckList = filteredCheckList.filter(({ id }) =>
+ id !== 'weeklyHighlights'
+ || hasHighlightsEnabled
+ );
- filteredCheckList = filteredCheckList.filter(({ id }) => id !== 'proctoringEmail'
- || needsProctoringEscalationEmail);
+ filteredCheckList = filteredCheckList.filter(({ id }) =>
+ id !== 'proctoringEmail'
+ || needsProctoringEscalationEmail
+ );
return filteredCheckList;
};
diff --git a/src/course-outline/utils/getChecklistValues.test.js b/src/course-outline/utils/getChecklistValues.test.js
index 24ac32e973..9e52047f16 100644
--- a/src/course-outline/utils/getChecklistValues.test.js
+++ b/src/course-outline/utils/getChecklistValues.test.js
@@ -45,10 +45,12 @@ describe('getChecklistValues utility function', () => {
it('returns only checklist items with filters ALL and SELF_PACED when isSelfPaced is true', () => {
const filteredChecklist = getChecklistValues({ checklist, ...courseData });
- filteredChecklist.forEach(((
- item => expect(item.pacingTypeFilter === CHECKLIST_FILTERS.ALL
- || item.pacingTypeFilter === CHECKLIST_FILTERS.SELF_PACED)
- )));
+ filteredChecklist.forEach(item =>
+ expect(
+ item.pacingTypeFilter === CHECKLIST_FILTERS.ALL
+ || item.pacingTypeFilter === CHECKLIST_FILTERS.SELF_PACED,
+ )
+ );
expect(filteredChecklist.filter(item => item.pacingTypeFilter === CHECKLIST_FILTERS.ALL).length)
.toEqual(checklist.filter(item => item.pacingTypeFilter === CHECKLIST_FILTERS.ALL).length);
@@ -60,15 +62,19 @@ describe('getChecklistValues utility function', () => {
courseData.isSelfPaced = false;
const filteredChecklist = getChecklistValues({ checklist, ...courseData });
- filteredChecklist.forEach(((
- item => expect(item.pacingTypeFilter === CHECKLIST_FILTERS.ALL
- || item.pacingTypeFilter === CHECKLIST_FILTERS.INSTRUCTOR_PACED)
- )));
+ filteredChecklist.forEach(item =>
+ expect(
+ item.pacingTypeFilter === CHECKLIST_FILTERS.ALL
+ || item.pacingTypeFilter === CHECKLIST_FILTERS.INSTRUCTOR_PACED,
+ )
+ );
expect(filteredChecklist.filter(item => item.pacingTypeFilter === CHECKLIST_FILTERS.ALL).length)
.toEqual(checklist.filter(item => item.pacingTypeFilter === CHECKLIST_FILTERS.ALL).length);
- expect(filteredChecklist
- .filter(item => item.pacingTypeFilter === CHECKLIST_FILTERS.INSTRUCTOR_PACED).length)
+ expect(
+ filteredChecklist
+ .filter(item => item.pacingTypeFilter === CHECKLIST_FILTERS.INSTRUCTOR_PACED).length,
+ )
.toEqual(checklist.filter(item => item.pacingTypeFilter === CHECKLIST_FILTERS.INSTRUCTOR_PACED).length);
});
diff --git a/src/course-outline/utils/getErrorDetails.test.js b/src/course-outline/utils/getErrorDetails.test.js
index 5794859333..901113bac2 100644
--- a/src/course-outline/utils/getErrorDetails.test.js
+++ b/src/course-outline/utils/getErrorDetails.test.js
@@ -12,7 +12,10 @@ describe('getErrorDetails', () => {
const error = { response: { data: 'some data', status: 500 } };
const result = getErrorDetails(error);
expect(result).toEqual({
- dismissible: true, data: '"some data"', status: 500, type: API_ERROR_TYPES.serverError,
+ dismissible: true,
+ data: '"some data"',
+ status: 500,
+ type: API_ERROR_TYPES.serverError,
});
});
diff --git a/src/course-outline/xblock-status/GradingTypeAndDueDate.jsx b/src/course-outline/xblock-status/GradingTypeAndDueDate.jsx
index b02e138346..bce8addafc 100644
--- a/src/course-outline/xblock-status/GradingTypeAndDueDate.jsx
+++ b/src/course-outline/xblock-status/GradingTypeAndDueDate.jsx
@@ -84,7 +84,8 @@ const GradingTypeAndDueDate = ({
{showRelativeWeeks && (selfPacedRelativeDueWeeksDiv())}
>
);
- } if ((dueDate && !isSelfPaced) || graded) {
+ }
+ if ((dueDate && !isSelfPaced) || graded) {
return (
<>
@@ -94,7 +95,8 @@ const GradingTypeAndDueDate = ({
{showRelativeWeeks && (selfPacedRelativeDueWeeksDiv())}
>
);
- } if (showRelativeWeeks) {
+ }
+ if (showRelativeWeeks) {
return (
<>
{gradingTypeDiv()}
diff --git a/src/course-outline/xblock-status/StatusMessages.tsx b/src/course-outline/xblock-status/StatusMessages.tsx
index 547cc84413..f9054cd290 100644
--- a/src/course-outline/xblock-status/StatusMessages.tsx
+++ b/src/course-outline/xblock-status/StatusMessages.tsx
@@ -11,11 +11,11 @@ import messages from './messages';
interface StatusMessagesProps {
isVertical: boolean;
- staffOnlyMessage?: boolean,
- prereq?: string,
- prereqs?: XBlockPrereqs[],
- userPartitionInfo?: UserPartitionInfoTypes,
- hasPartitionGroupComponents?: boolean,
+ staffOnlyMessage?: boolean;
+ prereq?: string;
+ prereqs?: XBlockPrereqs[];
+ userPartitionInfo?: UserPartitionInfoTypes;
+ hasPartitionGroupComponents?: boolean;
}
interface StatusMessagesText {
diff --git a/src/course-outline/xblock-status/XBlockStatus.test.jsx b/src/course-outline/xblock-status/XBlockStatus.test.jsx
index bd932b4783..5a6bd74cc4 100644
--- a/src/course-outline/xblock-status/XBlockStatus.test.jsx
+++ b/src/course-outline/xblock-status/XBlockStatus.test.jsx
@@ -46,17 +46,18 @@ const section = {
hideAfterDue: true,
};
-const renderComponent = (props) => render(
-
-
-
- ,
- ,
-);
+const renderComponent = (props) =>
+ render(
+
+
+
+ ,
+ ,
+ );
describe('
for Instructor paced Section', () => {
beforeEach(() => {
diff --git a/src/course-outline/xblock-status/XBlockStatus.tsx b/src/course-outline/xblock-status/XBlockStatus.tsx
index 20ecd82c2a..905877740b 100644
--- a/src/course-outline/xblock-status/XBlockStatus.tsx
+++ b/src/course-outline/xblock-status/XBlockStatus.tsx
@@ -10,8 +10,8 @@ import NeverShowAssessmentResultMessage from './NeverShowAssessmentResultMessage
interface XBlockStatusProps {
isSelfPaced: boolean;
- isCustomRelativeDatesActive: boolean,
- blockData: XBlock | UnitXBlock,
+ isCustomRelativeDatesActive: boolean;
+ blockData: XBlock | UnitXBlock;
}
const XBlockStatus = ({
@@ -73,9 +73,7 @@ const XBlockStatus = ({
relativeWeeksDue={relativeWeeksDue}
/>
)}
- {hideAfterDue && (
-
- )}
+ {hideAfterDue &&
}
', () => {
it('renders description successfully', () => {
const { getByText } = render(
);
- expect(getByText('Provide identifying information for this re-run of the course. The original course is not affected in any way by a re-run', { exact: false })).toBeInTheDocument();
+ expect(
+ getByText(
+ 'Provide identifying information for this re-run of the course. The original course is not affected in any way by a re-run',
+ { exact: false },
+ ),
+ ).toBeInTheDocument();
});
});
diff --git a/src/course-rerun/course-rerun-form/index.jsx b/src/course-rerun/course-rerun-form/index.jsx
index 426166e5ad..8c4b695e90 100644
--- a/src/course-rerun/course-rerun-form/index.jsx
+++ b/src/course-rerun/course-rerun-form/index.jsx
@@ -9,11 +9,10 @@ const CourseRerunForm = ({ initialFormValues, onClickCancel }) => {
const intl = useIntl();
return (
-
{intl.formatMessage(messages.rerunCourseDescription, {
- strong: (
-
{intl.formatMessage(messages.rerunCourseDescriptionStrong)}
- ),
- })}
+
+ {intl.formatMessage(messages.rerunCourseDescription, {
+ strong: {intl.formatMessage(messages.rerunCourseDescriptionStrong)} ,
+ })}
baseRender(
-
-
- ,
- { path: mockPathname },
-);
+const render = () =>
+ baseRender(
+
+
+ ,
+ { path: mockPathname },
+ );
describe(' ', () => {
beforeEach(() => {
diff --git a/src/course-team/CourseTeam.tsx b/src/course-team/CourseTeam.tsx
index f27e7235bd..81fc318062 100644
--- a/src/course-team/CourseTeam.tsx
+++ b/src/course-team/CourseTeam.tsx
@@ -84,17 +84,19 @@ const CourseTeam = () => {
- {intl.formatMessage(messages.addNewMemberButton)}
-
- ) : undefined}
+ headerActions={isAllowActions ?
+ (
+
+ {intl.formatMessage(messages.addNewMemberButton)}
+
+ ) :
+ undefined}
/>
@@ -104,19 +106,21 @@ const CourseTeam = () => {
onCancel={hideForm}
/>
)}
- {courseTeamUsers.length ? courseTeamUsers.map(({ username, role, email }) => (
-
- )) : null}
+ {courseTeamUsers.length ?
+ courseTeamUsers.map(({ username, role, email }) => (
+
+ )) :
+ null}
{isShowAddTeamMember && (
render(
-
-
- ,
-);
+const renderComponent = (props) =>
+ render(
+
+
+ ,
+ );
describe(' ', () => {
it('render AddTeamMember component correctly', () => {
diff --git a/src/course-team/add-user-form/AddUserForm.test.tsx b/src/course-team/add-user-form/AddUserForm.test.tsx
index 57207c4d2c..eb509058aa 100644
--- a/src/course-team/add-user-form/AddUserForm.test.tsx
+++ b/src/course-team/add-user-form/AddUserForm.test.tsx
@@ -23,12 +23,13 @@ jest.mock('react-router-dom', () => ({
const onSubmitMock = jest.fn();
const onCancelMock = jest.fn();
-const renderComponent = () => render(
- ,
-);
+const renderComponent = () =>
+ render(
+ ,
+ );
describe(' ', () => {
beforeEach(() => {
@@ -50,7 +51,9 @@ describe(' ', () => {
const user = userEvent.setup();
renderComponent();
- const emailInput = screen.getByPlaceholderText(messages.formPlaceholder.defaultMessage.replace('{email}', EXAMPLE_USER_EMAIL));
+ const emailInput = screen.getByPlaceholderText(
+ messages.formPlaceholder.defaultMessage.replace('{email}', EXAMPLE_USER_EMAIL),
+ );
const addUserButton = screen.getByRole('button', { name: messages.addUserButton.defaultMessage });
fireEvent.change(emailInput, { target: { value: EXAMPLE_USER_EMAIL } });
diff --git a/src/course-team/add-user-form/messages.ts b/src/course-team/add-user-form/messages.ts
index c61543b170..862d575456 100644
--- a/src/course-team/add-user-form/messages.ts
+++ b/src/course-team/add-user-form/messages.ts
@@ -25,7 +25,6 @@ const messages = defineMessages({
id: 'course-authoring.course-team.form.button.cancel',
defaultMessage: 'Cancel',
},
-
});
export default messages;
diff --git a/src/course-team/course-team-member/CourseTeamMember.jsx b/src/course-team/course-team-member/CourseTeamMember.jsx
index 98b3bc35c3..5bfb567a17 100644
--- a/src/course-team/course-team-member/CourseTeamMember.jsx
+++ b/src/course-team/course-team-member/CourseTeamMember.jsx
@@ -43,29 +43,31 @@ const CourseTeamMember = ({
{/* eslint-disable-next-line no-nested-ternary */}
{isAllowActions && (
- !isHideActions ? (
-
- onChangeRole(email, isAdminRole ? USER_ROLES.staff : USER_ROLES.admin)}
- >
- {isAdminRole ? intl.formatMessage(messages.removeButton) : intl.formatMessage(messages.addButton)}
-
- onDelete(email)}
- iconAs={Icon}
- alt={intl.formatMessage(messages.deleteUserButton)}
- data-testid="delete-button"
- />
-
- ) : (
-
- {intl.formatMessage(messages.hint)}
-
- )
+ !isHideActions ?
+ (
+
+ onChangeRole(email, isAdminRole ? USER_ROLES.staff : USER_ROLES.admin)}
+ >
+ {isAdminRole ? intl.formatMessage(messages.removeButton) : intl.formatMessage(messages.addButton)}
+
+ onDelete(email)}
+ iconAs={Icon}
+ alt={intl.formatMessage(messages.deleteUserButton)}
+ data-testid="delete-button"
+ />
+
+ ) :
+ (
+
+ {intl.formatMessage(messages.hint)}
+
+ )
)}
);
diff --git a/src/course-team/course-team-member/CourseTeamMember.test.jsx b/src/course-team/course-team-member/CourseTeamMember.test.jsx
index be6719ac6a..be7ac40dda 100644
--- a/src/course-team/course-team-member/CourseTeamMember.test.jsx
+++ b/src/course-team/course-team-member/CourseTeamMember.test.jsx
@@ -12,21 +12,22 @@ const currentUserEmailMock = 'user@example.com';
const onChangeRoleMock = jest.fn();
const onDeleteMock = jest.fn();
-const renderComponent = (props) => render(
-
-
- ,
-);
+const renderComponent = (props) =>
+ render(
+
+
+ ,
+ );
describe('
', () => {
it('render CourseTeamMember component correctly', () => {
diff --git a/src/course-team/data/api.ts b/src/course-team/data/api.ts
index 993ed9f765..49da0875ad 100644
--- a/src/course-team/data/api.ts
+++ b/src/course-team/data/api.ts
@@ -3,8 +3,10 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { USER_ROLES } from '@src/constants';
const getApiBaseUrl = () => getConfig().STUDIO_BASE_URL;
-export const getCourseTeamApiUrl = (courseId: string) => `${getApiBaseUrl()}/api/contentstore/v1/course_team/${courseId}`;
-export const updateCourseTeamUserApiUrl = (courseId: string, email: string) => `${getApiBaseUrl()}/course_team/${courseId}/${email}`;
+export const getCourseTeamApiUrl = (courseId: string) =>
+ `${getApiBaseUrl()}/api/contentstore/v1/course_team/${courseId}`;
+export const updateCourseTeamUserApiUrl = (courseId: string, email: string) =>
+ `${getApiBaseUrl()}/course_team/${courseId}/${email}`;
export interface CourseTeamUser {
id: number;
diff --git a/src/course-team/hooks.tsx b/src/course-team/hooks.tsx
index df33a2e3a1..799ccdd1e4 100644
--- a/src/course-team/hooks.tsx
+++ b/src/course-team/hooks.tsx
@@ -51,7 +51,7 @@ const useCourseTeam = () => {
openInfoModal();
};
- const handleAddUserSubmit = (body: { email: string }) => {
+ const handleAddUserSubmit = (body: { email: string; }) => {
const { email } = body;
const isUserContains = courseTeamUsers.some((user) => user.email === email);
diff --git a/src/course-team/info-modal/InfoModal.jsx b/src/course-team/info-modal/InfoModal.jsx
index d9ab33852c..c5cb68c622 100644
--- a/src/course-team/info-modal/InfoModal.jsx
+++ b/src/course-team/info-modal/InfoModal.jsx
@@ -38,7 +38,7 @@ const InfoModal = ({
variant={variant}
isOpen={isOpen && !isEmptyErrorMessage}
onClose={close}
- footerNode={(
+ footerNode={
{closeButtonText}
@@ -54,7 +54,7 @@ const InfoModal = ({
)}
- )}
+ }
>
{message}
diff --git a/src/course-team/info-modal/InfoModal.test.jsx b/src/course-team/info-modal/InfoModal.test.jsx
index f97f8a0baf..1c11cfd843 100644
--- a/src/course-team/info-modal/InfoModal.test.jsx
+++ b/src/course-team/info-modal/InfoModal.test.jsx
@@ -12,20 +12,21 @@ const currentEmailMock = 'user@example.com';
const errorMessageMock = 'Error text error@example.com';
const courseNameMock = 'Course Name';
-const renderComponent = (props) => render(
-
-
- ,
-);
+const renderComponent = (props) =>
+ render(
+
+
+ ,
+ );
describe('
', () => {
it('render InfoModal component with type delete correctly', () => {
diff --git a/src/course-team/utils.js b/src/course-team/utils.js
index 2d9399e00c..a0f6f7d494 100644
--- a/src/course-team/utils.js
+++ b/src/course-team/utils.js
@@ -8,12 +8,12 @@ import messages from './info-modal/messages';
* @param {string} errorEmail - email from wrong request
* @param {string} courseName - current course name
* @returns {{
- * title: string,
- * message: string,
- * variant: string,
- * closeButtonText: string,
- * submitButtonText: string,
- * closeButtonVariant: string
+ * title: string,
+ * message: string,
+ * variant: string,
+ * closeButtonText: string,
+ * submitButtonText: string,
+ * closeButtonVariant: string
* }}
*/
diff --git a/src/course-unit/CourseUnit.test.tsx b/src/course-unit/CourseUnit.test.tsx
index 53e2f5dda4..f34aa295c7 100644
--- a/src/course-unit/CourseUnit.test.tsx
+++ b/src/course-unit/CourseUnit.test.tsx
@@ -179,10 +179,14 @@ describe('
', () => {
const unitHeaderTitle = await screen.findByTestId('unit-header-title');
expect(await screen.findByText(unitDisplayName)).toBeInTheDocument();
- expect(within(unitHeaderTitle).getByRole('button', { name: headerTitleMessages.altButtonEdit.defaultMessage })).toBeInTheDocument();
- expect(within(unitHeaderTitle).getByRole('button', { name: headerTitleMessages.altButtonSettings.defaultMessage })).toBeInTheDocument();
- expect(await screen.findByRole('button', { name: headerNavigationsMessages.viewLiveButton.defaultMessage })).toBeInTheDocument();
- expect(await screen.findByRole('button', { name: headerNavigationsMessages.previewButton.defaultMessage })).toBeInTheDocument();
+ expect(within(unitHeaderTitle).getByRole('button', { name: headerTitleMessages.altButtonEdit.defaultMessage }))
+ .toBeInTheDocument();
+ expect(within(unitHeaderTitle).getByRole('button', { name: headerTitleMessages.altButtonSettings.defaultMessage }))
+ .toBeInTheDocument();
+ expect(await screen.findByRole('button', { name: headerNavigationsMessages.viewLiveButton.defaultMessage }))
+ .toBeInTheDocument();
+ expect(await screen.findByRole('button', { name: headerNavigationsMessages.previewButton.defaultMessage }))
+ .toBeInTheDocument();
expect(await screen.findByRole('button', { name: currentSectionName })).toBeInTheDocument();
expect(await screen.findByRole('button', { name: currentSubSectionName })).toBeInTheDocument();
});
@@ -382,14 +386,18 @@ describe('
', () => {
await user.click(publishBtn);
// check if the sidebar status is Published and Live
- expect(await screen.findByText(
- legacySidebarMessages.sidebarTitlePublishedAndLive.defaultMessage,
- )).toBeInTheDocument();
- expect(await screen.findByText(
- unitInfoMessages.publishLastPublished.defaultMessage
- .replace('{publishedOn}', courseSectionVerticalMock.xblock_info.published_on)
- .replace('{publishedBy}', userName),
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ legacySidebarMessages.sidebarTitlePublishedAndLive.defaultMessage,
+ ),
+ ).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ unitInfoMessages.publishLastPublished.defaultMessage
+ .replace('{publishedOn}', courseSectionVerticalMock.xblock_info.published_on)
+ .replace('{publishedBy}', userName),
+ ),
+ ).toBeInTheDocument();
expect(screen.queryByRole('button', {
name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage,
})).not.toBeInTheDocument();
@@ -401,11 +409,14 @@ describe('
', () => {
axiosMock
.onGet(getCourseSectionVerticalApiUrl(courseId))
.reply(200, courseSectionVerticalMock);
- await executeThunk(deleteUnitItemQuery(
- courseId,
- courseVerticalChildrenMock.children[0].block_id,
- simulatePostMessageEvent,
- ), store.dispatch);
+ await executeThunk(
+ deleteUnitItemQuery(
+ courseId,
+ courseVerticalChildrenMock.children[0].block_id,
+ simulatePostMessageEvent,
+ ),
+ store.dispatch,
+ );
const updatedCourseVerticalChildren = courseVerticalChildrenMock.children.filter(
child => child.block_id !== courseVerticalChildrenMock.children[0].block_id,
@@ -425,34 +436,44 @@ describe('
', () => {
.reply(200, courseSectionVerticalMock);
await user.click(publishBtn);
- expect(await screen.findByTitle(
- xblockContainerIframeMessages.xblockIframeTitle.defaultMessage,
- )).toHaveAttribute(
+ expect(
+ await screen.findByTitle(
+ xblockContainerIframeMessages.xblockIframeTitle.defaultMessage,
+ ),
+ ).toHaveAttribute(
'aria-label',
xblockContainerIframeMessages.xblockIframeLabel.defaultMessage
.replace('{xblockCount}', updatedCourseVerticalChildren.length.toString()),
);
// after removing the xblock, the sidebar status changes to Draft (unpublished changes)
- expect(await screen.findByText(
- legacySidebarMessages.sidebarTitleDraftUnpublishedChanges.defaultMessage,
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ legacySidebarMessages.sidebarTitleDraftUnpublishedChanges.defaultMessage,
+ ),
+ ).toBeInTheDocument();
expect(await screen.findByText(legacySidebarMessages.releaseStatusTitle.defaultMessage)).toBeInTheDocument();
expect(await screen.findByText(unitInfoMessages.visibilityVisibleToTitle.defaultMessage)).toBeInTheDocument();
expect(await screen.findByText(unitInfoMessages.visibilityCheckboxTitle.defaultMessage)).toBeInTheDocument();
expect(await screen.findByText(legacySidebarMessages.actionButtonPublishTitle.defaultMessage)).toBeInTheDocument();
- expect(await screen.findByText(
- legacySidebarMessages.actionButtonDiscardChangesTitle.defaultMessage,
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ legacySidebarMessages.actionButtonDiscardChangesTitle.defaultMessage,
+ ),
+ ).toBeInTheDocument();
expect(await screen.findByText(courseSectionVerticalMock.xblock_info.release_date)).toBeInTheDocument();
- expect(await screen.findByText(
- unitInfoMessages.publishInfoDraftSaved.defaultMessage
- .replace('{editedOn}', courseSectionVerticalMock.xblock_info.edited_on)
- .replace('{editedBy}', courseSectionVerticalMock.xblock_info.edited_by),
- )).toBeInTheDocument();
- expect(await screen.findByText(
- legacySidebarMessages.releaseInfoWithSection.defaultMessage
- .replace('{sectionName}', courseSectionVerticalMock.xblock_info.release_date_from),
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ unitInfoMessages.publishInfoDraftSaved.defaultMessage
+ .replace('{editedOn}', courseSectionVerticalMock.xblock_info.edited_on)
+ .replace('{editedBy}', courseSectionVerticalMock.xblock_info.edited_by),
+ ),
+ ).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ legacySidebarMessages.releaseInfoWithSection.defaultMessage
+ .replace('{sectionName}', courseSectionVerticalMock.xblock_info.release_date_from),
+ ),
+ ).toBeInTheDocument();
});
it('checks if the xblock unlink is called when the corresponding unlink button is clicked', async () => {
@@ -520,12 +541,15 @@ describe('
', () => {
expect(
await screen.findByText(legacySidebarMessages.sidebarTitlePublishedAndLive.defaultMessage),
).toBeInTheDocument();
- expect(await screen.findByText(
- unitInfoMessages.publishLastPublished.defaultMessage
- .replace('{publishedOn}', courseSectionVerticalMock.xblock_info.published_on)
- .replace('{publishedBy}', userName),
- )).toBeInTheDocument();
- expect(screen.queryByRole('button', { name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage })).not.toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ unitInfoMessages.publishLastPublished.defaultMessage
+ .replace('{publishedOn}', courseSectionVerticalMock.xblock_info.published_on)
+ .replace('{publishedBy}', userName),
+ ),
+ ).toBeInTheDocument();
+ expect(screen.queryByRole('button', { name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage })).not
+ .toBeInTheDocument();
expect(await screen.findByText(unitDisplayName)).toBeInTheDocument();
const updatedCourseVerticalChildren = [
@@ -564,9 +588,11 @@ describe('
', () => {
);
// after duplicate the xblock, the sidebar status changes to Draft (unpublished changes)
- expect(await screen.findByText(
- legacySidebarMessages.sidebarTitleDraftUnpublishedChanges.defaultMessage,
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ legacySidebarMessages.sidebarTitleDraftUnpublishedChanges.defaultMessage,
+ ),
+ ).toBeInTheDocument();
expect(await screen.findByText(legacySidebarMessages.releaseStatusTitle.defaultMessage)).toBeInTheDocument();
expect(await screen.findByText(unitInfoMessages.visibilityVisibleToTitle.defaultMessage)).toBeInTheDocument();
expect(await screen.findByText(unitInfoMessages.visibilityCheckboxTitle.defaultMessage)).toBeInTheDocument();
@@ -575,15 +601,19 @@ describe('
', () => {
await screen.findByText(legacySidebarMessages.actionButtonDiscardChangesTitle.defaultMessage),
).toBeInTheDocument();
expect(await screen.findByText(courseSectionVerticalMock.xblock_info.release_date)).toBeInTheDocument();
- expect(await screen.findByText(
- unitInfoMessages.publishInfoDraftSaved.defaultMessage
- .replace('{editedOn}', courseSectionVerticalMock.xblock_info.edited_on)
- .replace('{editedBy}', courseSectionVerticalMock.xblock_info.edited_by),
- )).toBeInTheDocument();
- expect(await screen.findByText(
- legacySidebarMessages.releaseInfoWithSection.defaultMessage
- .replace('{sectionName}', courseSectionVerticalMock.xblock_info.release_date_from),
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ unitInfoMessages.publishInfoDraftSaved.defaultMessage
+ .replace('{editedOn}', courseSectionVerticalMock.xblock_info.edited_on)
+ .replace('{editedBy}', courseSectionVerticalMock.xblock_info.edited_by),
+ ),
+ ).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ legacySidebarMessages.releaseInfoWithSection.defaultMessage
+ .replace('{sectionName}', courseSectionVerticalMock.xblock_info.release_date_from),
+ ),
+ ).toBeInTheDocument();
});
it('handles CourseUnit header action buttons', async () => {
@@ -596,12 +626,16 @@ describe('
', () => {
published_preview_link: publishedPreviewLink,
} = courseSectionVerticalMock;
- const viewLiveButton = await screen.findByRole('button', { name: headerNavigationsMessages.viewLiveButton.defaultMessage });
+ const viewLiveButton = await screen.findByRole('button', {
+ name: headerNavigationsMessages.viewLiveButton.defaultMessage,
+ });
await user.click(viewLiveButton);
expect(window.open).toHaveBeenCalled();
expect(window.open).toHaveBeenCalledWith(publishedPreviewLink, '_blank');
- const previewButton = await screen.findByRole('button', { name: headerNavigationsMessages.previewButton.defaultMessage });
+ const previewButton = await screen.findByRole('button', {
+ name: headerNavigationsMessages.previewButton.defaultMessage,
+ });
await user.click(previewButton);
expect(window.open).toHaveBeenCalled();
expect(window.open).toHaveBeenCalledWith(draftPreviewLink, '_blank');
@@ -747,9 +781,11 @@ describe('
', () => {
.reply(200, courseSectionVerticalMock);
// after creating problem xblock, the sidebar status changes to Draft (unpublished changes)
- expect(await screen.findByText(
- legacySidebarMessages.sidebarTitleDraftUnpublishedChanges.defaultMessage,
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ legacySidebarMessages.sidebarTitleDraftUnpublishedChanges.defaultMessage,
+ ),
+ ).toBeInTheDocument();
expect(await screen.findByText(legacySidebarMessages.releaseStatusTitle.defaultMessage)).toBeInTheDocument();
expect(await screen.findByText(unitInfoMessages.visibilityVisibleToTitle.defaultMessage)).toBeInTheDocument();
expect(await screen.findByText(unitInfoMessages.visibilityCheckboxTitle.defaultMessage)).toBeInTheDocument();
@@ -758,15 +794,19 @@ describe('
', () => {
await screen.findByText(legacySidebarMessages.actionButtonDiscardChangesTitle.defaultMessage),
).toBeInTheDocument();
expect(await screen.findByText(courseSectionVerticalMock.xblock_info.release_date)).toBeInTheDocument();
- expect(await screen.findByText(
- unitInfoMessages.publishInfoDraftSaved.defaultMessage
- .replace('{editedOn}', courseSectionVerticalMock.xblock_info.edited_on)
- .replace('{editedBy}', courseSectionVerticalMock.xblock_info.edited_by),
- )).toBeInTheDocument();
- expect(await screen.findByText(
- legacySidebarMessages.releaseInfoWithSection.defaultMessage
- .replace('{sectionName}', courseSectionVerticalMock.xblock_info.release_date_from),
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ unitInfoMessages.publishInfoDraftSaved.defaultMessage
+ .replace('{editedOn}', courseSectionVerticalMock.xblock_info.edited_on)
+ .replace('{editedBy}', courseSectionVerticalMock.xblock_info.edited_by),
+ ),
+ ).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ legacySidebarMessages.releaseInfoWithSection.defaultMessage
+ .replace('{sectionName}', courseSectionVerticalMock.xblock_info.release_date_from),
+ ),
+ ).toBeInTheDocument();
});
it('correct addition of a new course unit after click on the "Add new unit" button', async () => {
@@ -871,10 +911,14 @@ describe('
', () => {
const unitHeaderTitle = screen.getByTestId('unit-header-title');
- const editTitleButton = within(unitHeaderTitle).getByRole('button', { name: headerTitleMessages.altButtonEdit.defaultMessage });
+ const editTitleButton = within(unitHeaderTitle).getByRole('button', {
+ name: headerTitleMessages.altButtonEdit.defaultMessage,
+ });
await user.click(editTitleButton);
- const titleEditField = within(unitHeaderTitle).getByRole('textbox', { name: headerTitleMessages.ariaLabelButtonEdit.defaultMessage });
+ const titleEditField = within(unitHeaderTitle).getByRole('textbox', {
+ name: headerTitleMessages.ariaLabelButtonEdit.defaultMessage,
+ });
await user.clear(titleEditField);
await user.type(titleEditField, newDisplayName);
@@ -895,7 +939,9 @@ describe('
', () => {
.reply(200, courseCreateXblockMock);
render(
);
- const publishButton = await screen.findByRole('button', { name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage });
+ const publishButton = await screen.findByRole('button', {
+ name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage,
+ });
await user.click(publishButton);
axiosMock
@@ -927,7 +973,8 @@ describe('
', () => {
.replace('{publishedOn}', courseSectionVerticalMock.xblock_info.published_on)
.replace('{publishedBy}', userName),
)).toBeInTheDocument();
- expect(screen.queryByRole('button', { name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage })).not.toBeInTheDocument();
+ expect(screen.queryByRole('button', { name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage })).not
+ .toBeInTheDocument();
axiosMock
.onGet(getCourseSectionVerticalApiUrl(blockId))
@@ -941,9 +988,11 @@ describe('
', () => {
await user.click(videoButton);
// after creating video xblock, the sidebar status changes to Draft (unpublished changes)
- expect(await screen.findByText(
- legacySidebarMessages.sidebarTitleDraftUnpublishedChanges.defaultMessage,
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ legacySidebarMessages.sidebarTitleDraftUnpublishedChanges.defaultMessage,
+ ),
+ ).toBeInTheDocument();
expect(await screen.findByText(legacySidebarMessages.releaseStatusTitle.defaultMessage)).toBeInTheDocument();
expect(await screen.findByText(unitInfoMessages.visibilityVisibleToTitle.defaultMessage)).toBeInTheDocument();
expect(await screen.findByText(unitInfoMessages.visibilityCheckboxTitle.defaultMessage)).toBeInTheDocument();
@@ -952,19 +1001,25 @@ describe('
', () => {
await screen.findByText(legacySidebarMessages.actionButtonDiscardChangesTitle.defaultMessage),
).toBeInTheDocument();
expect(await screen.findByText(courseSectionVerticalMock.xblock_info.release_date)).toBeInTheDocument();
- expect(await screen.findByText(
- unitInfoMessages.publishInfoDraftSaved.defaultMessage
- .replace('{editedOn}', courseSectionVerticalMock.xblock_info.edited_on)
- .replace('{editedBy}', courseSectionVerticalMock.xblock_info.edited_by),
- )).toBeInTheDocument();
- expect(await screen.findByText(
- legacySidebarMessages.releaseInfoWithSection.defaultMessage
- .replace('{sectionName}', courseSectionVerticalMock.xblock_info.release_date_from),
- )).toBeInTheDocument();
- expect(await screen.findByRole('heading', {
- name: /add video to your course/i,
- hidden: true,
- })).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ unitInfoMessages.publishInfoDraftSaved.defaultMessage
+ .replace('{editedOn}', courseSectionVerticalMock.xblock_info.edited_on)
+ .replace('{editedBy}', courseSectionVerticalMock.xblock_info.edited_by),
+ ),
+ ).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ legacySidebarMessages.releaseInfoWithSection.defaultMessage
+ .replace('{sectionName}', courseSectionVerticalMock.xblock_info.release_date_from),
+ ),
+ ).toBeInTheDocument();
+ expect(
+ await screen.findByRole('heading', {
+ name: /add video to your course/i,
+ hidden: true,
+ }),
+ ).toBeInTheDocument();
waffleSpy.mockRestore();
});
@@ -976,7 +1031,9 @@ describe('
', () => {
const user = userEvent.setup();
render(
);
- await user.click(await screen.findByRole('button', { name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage }));
+ await user.click(
+ await screen.findByRole('button', { name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage }),
+ );
axiosMock
.onPost(getXBlockBaseApiUrl(blockId), {
@@ -995,19 +1052,24 @@ describe('
', () => {
},
});
- const publishButton = await screen.findByRole('button', { name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage });
+ const publishButton = await screen.findByRole('button', {
+ name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage,
+ });
await user.click(publishButton);
// check if the sidebar status is Published and Live
expect(
await screen.findByText(legacySidebarMessages.sidebarTitlePublishedAndLive.defaultMessage),
).toBeInTheDocument();
- expect(await screen.findByText(
- unitInfoMessages.publishLastPublished.defaultMessage
- .replace('{publishedOn}', courseSectionVerticalMock.xblock_info.published_on)
- .replace('{publishedBy}', userName),
- )).toBeInTheDocument();
- expect(screen.queryByRole('button', { name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage })).not.toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ unitInfoMessages.publishLastPublished.defaultMessage
+ .replace('{publishedOn}', courseSectionVerticalMock.xblock_info.published_on)
+ .replace('{publishedBy}', userName),
+ ),
+ ).toBeInTheDocument();
+ expect(screen.queryByRole('button', { name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage })).not
+ .toBeInTheDocument();
axiosMock
.onGet(getCourseSectionVerticalApiUrl(blockId))
@@ -1032,9 +1094,11 @@ describe('
', () => {
.reply(200, courseSectionVerticalMock);
// after creating video xblock, the sidebar status changes to Draft (unpublished changes)
- expect(await screen.findByText(
- legacySidebarMessages.sidebarTitleDraftUnpublishedChanges.defaultMessage,
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ legacySidebarMessages.sidebarTitleDraftUnpublishedChanges.defaultMessage,
+ ),
+ ).toBeInTheDocument();
expect(await screen.findByText(legacySidebarMessages.releaseStatusTitle.defaultMessage)).toBeInTheDocument();
expect(await screen.findByText(unitInfoMessages.visibilityVisibleToTitle.defaultMessage)).toBeInTheDocument();
expect(await screen.findByText(unitInfoMessages.visibilityCheckboxTitle.defaultMessage)).toBeInTheDocument();
@@ -1043,15 +1107,19 @@ describe('
', () => {
await screen.findByText(legacySidebarMessages.actionButtonDiscardChangesTitle.defaultMessage),
).toBeInTheDocument();
expect(await screen.findByText(courseSectionVerticalMock.xblock_info.release_date)).toBeInTheDocument();
- expect(await screen.findByText(
- unitInfoMessages.publishInfoDraftSaved.defaultMessage
- .replace('{editedOn}', courseSectionVerticalMock.xblock_info.edited_on)
- .replace('{editedBy}', courseSectionVerticalMock.xblock_info.edited_by),
- )).toBeInTheDocument();
- expect(await screen.findByText(
- legacySidebarMessages.releaseInfoWithSection.defaultMessage
- .replace('{sectionName}', courseSectionVerticalMock.xblock_info.release_date_from),
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ unitInfoMessages.publishInfoDraftSaved.defaultMessage
+ .replace('{editedOn}', courseSectionVerticalMock.xblock_info.edited_on)
+ .replace('{editedBy}', courseSectionVerticalMock.xblock_info.edited_by),
+ ),
+ ).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ legacySidebarMessages.releaseInfoWithSection.defaultMessage
+ .replace('{sectionName}', courseSectionVerticalMock.xblock_info.release_date_from),
+ ),
+ ).toBeInTheDocument();
});
it('renders course unit details for a draft with unpublished changes', async () => {
@@ -1164,24 +1232,36 @@ describe('
', () => {
await waitFor(async () => {
expect(visibilityCheckbox).toBeChecked();
});
- expect(within(courseUnitSidebar)
- .getByText(legacySidebarMessages.sidebarTitleVisibleToStaffOnly.defaultMessage)).toBeInTheDocument();
- expect(within(courseUnitSidebar)
- .getByText(unitInfoMessages.visibilityStaffOnlyTitle.defaultMessage)).toBeInTheDocument();
+ expect(
+ within(courseUnitSidebar)
+ .getByText(legacySidebarMessages.sidebarTitleVisibleToStaffOnly.defaultMessage),
+ ).toBeInTheDocument();
+ expect(
+ within(courseUnitSidebar)
+ .getByText(unitInfoMessages.visibilityStaffOnlyTitle.defaultMessage),
+ ).toBeInTheDocument();
await user.click(visibilityCheckbox);
const modalNotification = screen.getByRole('dialog');
- const makeVisibilityBtn = within(modalNotification).getByRole('button', { name: unitInfoMessages.modalMakeVisibilityActionButtonText.defaultMessage });
- const cancelBtn = within(modalNotification).getByRole('button', { name: unitInfoMessages.modalMakeVisibilityCancelButtonText.defaultMessage });
- const headingElement = within(modalNotification).getByRole('heading', { name: unitInfoMessages.modalMakeVisibilityTitle.defaultMessage });
+ const makeVisibilityBtn = within(modalNotification).getByRole('button', {
+ name: unitInfoMessages.modalMakeVisibilityActionButtonText.defaultMessage,
+ });
+ const cancelBtn = within(modalNotification).getByRole('button', {
+ name: unitInfoMessages.modalMakeVisibilityCancelButtonText.defaultMessage,
+ });
+ const headingElement = within(modalNotification).getByRole('heading', {
+ name: unitInfoMessages.modalMakeVisibilityTitle.defaultMessage,
+ });
expect(makeVisibilityBtn).toBeInTheDocument();
expect(cancelBtn).toBeInTheDocument();
expect(headingElement).toBeInTheDocument();
expect(headingElement).toHaveClass('pgn__modal-title');
- expect(within(modalNotification)
- .getByText(unitInfoMessages.modalMakeVisibilityDescription.defaultMessage)).toBeInTheDocument();
+ expect(
+ within(modalNotification)
+ .getByText(unitInfoMessages.modalMakeVisibilityDescription.defaultMessage),
+ ).toBeInTheDocument();
await user.click(makeVisibilityBtn);
@@ -1197,9 +1277,11 @@ describe('
', () => {
await user.click(visibilityCheckbox);
- await user.click(await within(await screen.findByRole('dialog')).findByRole('button', {
- name: unitInfoMessages.modalMakeVisibilityActionButtonText.defaultMessage,
- }));
+ await user.click(
+ await within(await screen.findByRole('dialog')).findByRole('button', {
+ name: unitInfoMessages.modalMakeVisibilityActionButtonText.defaultMessage,
+ }),
+ );
await waitFor(async () => {
expect(visibilityCheckbox).not.toBeChecked();
@@ -1215,7 +1297,9 @@ describe('
', () => {
await waitFor(async () => {
courseUnitSidebar = screen.getByTestId('course-unit-sidebar');
- publishBtn = within(courseUnitSidebar).queryByRole('button', { name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage });
+ publishBtn = within(courseUnitSidebar).queryByRole('button', {
+ name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage,
+ });
expect(publishBtn).toBeInTheDocument();
await user.click(publishBtn);
@@ -1238,16 +1322,22 @@ describe('
', () => {
},
});
- const publishButton = await screen.findByRole('button', { name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage });
+ const publishButton = await screen.findByRole('button', {
+ name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage,
+ });
await user.click(publishButton);
- expect(within(courseUnitSidebar)
- .getByText(legacySidebarMessages.sidebarTitlePublishedAndLive.defaultMessage)).toBeInTheDocument();
- expect(within(courseUnitSidebar).getByText(
- unitInfoMessages.publishLastPublished.defaultMessage
- .replace('{publishedOn}', courseSectionVerticalMock.xblock_info.published_on)
- .replace('{publishedBy}', userName),
- )).toBeInTheDocument();
+ expect(
+ within(courseUnitSidebar)
+ .getByText(legacySidebarMessages.sidebarTitlePublishedAndLive.defaultMessage),
+ ).toBeInTheDocument();
+ expect(
+ within(courseUnitSidebar).getByText(
+ unitInfoMessages.publishLastPublished.defaultMessage
+ .replace('{publishedOn}', courseSectionVerticalMock.xblock_info.published_on)
+ .replace('{publishedBy}', userName),
+ ),
+ ).toBeInTheDocument();
expect(publishBtn).not.toBeInTheDocument();
});
@@ -1263,21 +1353,31 @@ describe('
', () => {
const draftUnpublishedChangesHeading = within(courseUnitSidebar)
.getByText(legacySidebarMessages.sidebarTitleDraftUnpublishedChanges.defaultMessage);
expect(draftUnpublishedChangesHeading).toBeInTheDocument();
- discardChangesBtn = await within(courseUnitSidebar).findByRole('button', { name: legacySidebarMessages.actionButtonDiscardChangesTitle.defaultMessage });
+ discardChangesBtn = await within(courseUnitSidebar).findByRole('button', {
+ name: legacySidebarMessages.actionButtonDiscardChangesTitle.defaultMessage,
+ });
expect(discardChangesBtn).toBeInTheDocument();
await user.click(discardChangesBtn);
const modalNotification = screen.getByRole('dialog');
expect(modalNotification).toBeInTheDocument();
- expect(within(modalNotification)
- .getByText(unitInfoMessages.modalDiscardUnitChangesDescription.defaultMessage)).toBeInTheDocument();
- expect(within(modalNotification)
- .getByText(unitInfoMessages.modalDiscardUnitChangesCancelButtonText.defaultMessage)).toBeInTheDocument();
- const headingElement = within(modalNotification).getByRole('heading', { name: unitInfoMessages.modalDiscardUnitChangesTitle.defaultMessage });
+ expect(
+ within(modalNotification)
+ .getByText(unitInfoMessages.modalDiscardUnitChangesDescription.defaultMessage),
+ ).toBeInTheDocument();
+ expect(
+ within(modalNotification)
+ .getByText(unitInfoMessages.modalDiscardUnitChangesCancelButtonText.defaultMessage),
+ ).toBeInTheDocument();
+ const headingElement = within(modalNotification).getByRole('heading', {
+ name: unitInfoMessages.modalDiscardUnitChangesTitle.defaultMessage,
+ });
expect(headingElement).toBeInTheDocument();
expect(headingElement).toHaveClass('pgn__modal-title');
- const actionBtn = within(modalNotification).getByRole('button', { name: unitInfoMessages.modalDiscardUnitChangesActionButtonText.defaultMessage });
+ const actionBtn = within(modalNotification).getByRole('button', {
+ name: unitInfoMessages.modalDiscardUnitChangesActionButtonText.defaultMessage,
+ });
expect(actionBtn).toBeInTheDocument();
await user.click(actionBtn);
@@ -1299,23 +1399,31 @@ describe('
', () => {
},
});
- await user.click(await screen.findByRole('button', {
- name: legacySidebarMessages.actionButtonDiscardChangesTitle.defaultMessage,
- }));
- await user.click(await within(await screen.findByRole('dialog')).findByRole('button', {
- name: legacySidebarMessages.actionButtonDiscardChangesTitle.defaultMessage,
- }));
+ await user.click(
+ await screen.findByRole('button', {
+ name: legacySidebarMessages.actionButtonDiscardChangesTitle.defaultMessage,
+ }),
+ );
+ await user.click(
+ await within(await screen.findByRole('dialog')).findByRole('button', {
+ name: legacySidebarMessages.actionButtonDiscardChangesTitle.defaultMessage,
+ }),
+ );
- expect(await within(courseUnitSidebar)
- .findByText(legacySidebarMessages.sidebarTitlePublishedNotYetReleased.defaultMessage)).toBeInTheDocument();
+ expect(
+ await within(courseUnitSidebar)
+ .findByText(legacySidebarMessages.sidebarTitlePublishedNotYetReleased.defaultMessage),
+ ).toBeInTheDocument();
expect(discardChangesBtn).not.toBeInTheDocument();
});
it('should toggle visibility from header configure modal and update course unit state accordingly', async () => {
const user = userEvent.setup();
render(
);
- expect(await within(await screen.findByTestId('course-unit-sidebar'))
- .findByLabelText(unitInfoMessages.visibilityCheckboxTitle.defaultMessage)).not.toBeChecked();
+ expect(
+ await within(await screen.findByTestId('course-unit-sidebar'))
+ .findByLabelText(unitInfoMessages.visibilityCheckboxTitle.defaultMessage),
+ ).not.toBeChecked();
const headerConfigureBtn = await screen.findByRole('button', { name: /settings/i });
expect(headerConfigureBtn).toBeInTheDocument();
@@ -1324,10 +1432,14 @@ describe('
', () => {
const configureModal = await screen.findByTestId('configure-modal');
const restrictAccessSelect = await within(configureModal)
.findByRole('combobox', { name: configureModalMessages.restrictAccessTo.defaultMessage });
- expect(await within(configureModal)
- .findByText(configureModalMessages.unitVisibility.defaultMessage)).toBeInTheDocument();
- expect(await within(configureModal)
- .findByText(configureModalMessages.restrictAccessTo.defaultMessage)).toBeInTheDocument();
+ expect(
+ await within(configureModal)
+ .findByText(configureModalMessages.unitVisibility.defaultMessage),
+ ).toBeInTheDocument();
+ expect(
+ await within(configureModal)
+ .findByText(configureModalMessages.restrictAccessTo.defaultMessage),
+ ).toBeInTheDocument();
expect(restrictAccessSelect).toBeInTheDocument();
expect(restrictAccessSelect).toHaveValue('-1');
@@ -1368,12 +1480,18 @@ describe('
', () => {
.findByRole('button', { name: configureModalMessages.saveButton.defaultMessage });
await user.click(modalSaveBtn);
- expect(await within(await screen.findByTestId('course-unit-sidebar'))
- .findByLabelText(unitInfoMessages.visibilityCheckboxTitle.defaultMessage)).toBeChecked();
- expect(await within(await screen.findByTestId('course-unit-sidebar'))
- .findByText(legacySidebarMessages.sidebarTitleVisibleToStaffOnly.defaultMessage)).toBeInTheDocument();
- expect(await within(await screen.findByTestId('course-unit-sidebar'))
- .findByText(unitInfoMessages.visibilityStaffOnlyTitle.defaultMessage)).toBeInTheDocument();
+ expect(
+ await within(await screen.findByTestId('course-unit-sidebar'))
+ .findByLabelText(unitInfoMessages.visibilityCheckboxTitle.defaultMessage),
+ ).toBeChecked();
+ expect(
+ await within(await screen.findByTestId('course-unit-sidebar'))
+ .findByText(legacySidebarMessages.sidebarTitleVisibleToStaffOnly.defaultMessage),
+ ).toBeInTheDocument();
+ expect(
+ await within(await screen.findByTestId('course-unit-sidebar'))
+ .findByText(unitInfoMessages.visibilityStaffOnlyTitle.defaultMessage),
+ ).toBeInTheDocument();
});
it('shows the Tags sidebar when enabled', async () => {
@@ -1382,7 +1500,9 @@ describe('
', () => {
ENABLE_TAGGING_TAXONOMY_PAGES: 'true',
});
render(
);
- await waitFor(() => { expect(screen.getByText('Unit tags')).toBeInTheDocument(); });
+ await waitFor(() => {
+ expect(screen.getByText('Unit tags')).toBeInTheDocument();
+ });
});
it('hides the Tags sidebar when not enabled', async () => {
@@ -1391,7 +1511,9 @@ describe('
', () => {
ENABLE_TAGGING_TAXONOMY_PAGES: 'false',
});
render(
);
- await waitFor(() => { expect(screen.queryByText('Unit tags')).not.toBeInTheDocument(); });
+ await waitFor(() => {
+ expect(screen.queryByText('Unit tags')).not.toBeInTheDocument();
+ });
});
describe('Copy paste functionality', () => {
@@ -1411,7 +1533,9 @@ describe('
', () => {
await executeThunk(fetchCourseSectionVerticalData(blockId), store.dispatch);
- await user.click(screen.getByRole('button', { name: legacySidebarMessages.actionButtonCopyUnitTitle.defaultMessage }));
+ await user.click(
+ screen.getByRole('button', { name: legacySidebarMessages.actionButtonCopyUnitTitle.defaultMessage }),
+ );
await user.click(screen.getByRole('button', { name: courseSequenceMessages.pasteAsNewUnitLink.defaultMessage }));
let units: HTMLElement[] | null = null;
@@ -1446,7 +1570,9 @@ describe('
', () => {
expect(units.length).toEqual(updatedCourseUnits.length);
expect(mockedUsedNavigate).toHaveBeenCalled();
expect(mockedUsedNavigate)
- .toHaveBeenCalledWith(`/course/${courseId}/container/${blockId}/${updatedAncestorsChild.id}`, { replace: true });
+ .toHaveBeenCalledWith(`/course/${courseId}/container/${blockId}/${updatedAncestorsChild.id}`, {
+ replace: true,
+ });
});
it('should increase the number of course XBlocks after copying and pasting a block', async () => {
@@ -1468,7 +1594,9 @@ describe('
', () => {
});
await executeThunk(fetchCourseSectionVerticalData(blockId), store.dispatch);
- await user.click(screen.getByRole('button', { name: legacySidebarMessages.actionButtonCopyUnitTitle.defaultMessage }));
+ await user.click(
+ screen.getByRole('button', { name: legacySidebarMessages.actionButtonCopyUnitTitle.defaultMessage }),
+ );
await waitFor(() => {
const iframe = screen.getByTitle(xblockContainerIframeMessages.xblockIframeTitle.defaultMessage);
@@ -1532,7 +1660,9 @@ describe('
', () => {
await executeThunk(fetchCourseSectionVerticalData(blockId), store.dispatch);
- await user.click(screen.getByRole('button', { name: legacySidebarMessages.actionButtonCopyUnitTitle.defaultMessage }));
+ await user.click(
+ screen.getByRole('button', { name: legacySidebarMessages.actionButtonCopyUnitTitle.defaultMessage }),
+ );
await user.click(screen.getByRole('button', { name: courseSequenceMessages.pasteAsNewUnitLink.defaultMessage }));
const updatedCourseSectionVerticalData = cloneDeep(courseSectionVerticalMock);
@@ -1554,12 +1684,18 @@ describe('
', () => {
await executeThunk(createNewCourseXBlock(camelCaseObject(postXBlockBody), null, blockId), store.dispatch);
const newFilesAlert = screen.getByTestId('has-new-files-alert');
- expect(within(newFilesAlert)
- .getByText(pasteNotificationsMessages.hasNewFilesTitle.defaultMessage)).toBeInTheDocument();
- expect(within(newFilesAlert)
- .getByText(pasteNotificationsMessages.hasNewFilesDescription.defaultMessage)).toBeInTheDocument();
- expect(within(newFilesAlert)
- .getByText(pasteNotificationsMessages.hasNewFilesButtonText.defaultMessage)).toBeInTheDocument();
+ expect(
+ within(newFilesAlert)
+ .getByText(pasteNotificationsMessages.hasNewFilesTitle.defaultMessage),
+ ).toBeInTheDocument();
+ expect(
+ within(newFilesAlert)
+ .getByText(pasteNotificationsMessages.hasNewFilesDescription.defaultMessage),
+ ).toBeInTheDocument();
+ expect(
+ within(newFilesAlert)
+ .getByText(pasteNotificationsMessages.hasNewFilesButtonText.defaultMessage),
+ ).toBeInTheDocument();
clipboardMockResponse.staticFileNotices.newFiles.forEach((fileName) => {
expect(within(newFilesAlert).getByText(fileName)).toBeInTheDocument();
});
@@ -1585,7 +1721,9 @@ describe('
', () => {
await executeThunk(fetchCourseSectionVerticalData(blockId), store.dispatch);
- await user.click(screen.getByRole('button', { name: legacySidebarMessages.actionButtonCopyUnitTitle.defaultMessage }));
+ await user.click(
+ screen.getByRole('button', { name: legacySidebarMessages.actionButtonCopyUnitTitle.defaultMessage }),
+ );
await user.click(screen.getByRole('button', { name: courseSequenceMessages.pasteAsNewUnitLink.defaultMessage }));
const updatedCourseSectionVerticalData = cloneDeep(courseSectionVerticalMock);
@@ -1609,12 +1747,18 @@ describe('
', () => {
await executeThunk(createNewCourseXBlock(camelCaseObject(postXBlockBody), null, blockId), store.dispatch);
const conflictingErrorsAlert = screen.getByTestId('has-conflicting-errors-alert');
- expect(within(conflictingErrorsAlert)
- .getByText(pasteNotificationsMessages.hasConflictingErrorsTitle.defaultMessage)).toBeInTheDocument();
- expect(within(conflictingErrorsAlert)
- .getByText(pasteNotificationsMessages.hasConflictingErrorsDescription.defaultMessage)).toBeInTheDocument();
- expect(within(conflictingErrorsAlert)
- .getByText(pasteNotificationsMessages.hasConflictingErrorsButtonText.defaultMessage)).toBeInTheDocument();
+ expect(
+ within(conflictingErrorsAlert)
+ .getByText(pasteNotificationsMessages.hasConflictingErrorsTitle.defaultMessage),
+ ).toBeInTheDocument();
+ expect(
+ within(conflictingErrorsAlert)
+ .getByText(pasteNotificationsMessages.hasConflictingErrorsDescription.defaultMessage),
+ ).toBeInTheDocument();
+ expect(
+ within(conflictingErrorsAlert)
+ .getByText(pasteNotificationsMessages.hasConflictingErrorsButtonText.defaultMessage),
+ ).toBeInTheDocument();
clipboardMockResponse.staticFileNotices.conflictingFiles.forEach((fileName) => {
expect(within(conflictingErrorsAlert).getByText(fileName)).toBeInTheDocument();
});
@@ -1640,7 +1784,9 @@ describe('
', () => {
await executeThunk(fetchCourseSectionVerticalData(blockId), store.dispatch);
- await user.click(screen.getByRole('button', { name: legacySidebarMessages.actionButtonCopyUnitTitle.defaultMessage }));
+ await user.click(
+ screen.getByRole('button', { name: legacySidebarMessages.actionButtonCopyUnitTitle.defaultMessage }),
+ );
await user.click(screen.getByRole('button', { name: courseSequenceMessages.pasteAsNewUnitLink.defaultMessage }));
const updatedCourseSectionVerticalData = cloneDeep(courseSectionVerticalMock);
@@ -1664,10 +1810,14 @@ describe('
', () => {
await executeThunk(createNewCourseXBlock(camelCaseObject(postXBlockBody), null, blockId), store.dispatch);
const errorFilesAlert = screen.getByTestId('has-error-files-alert');
- expect(within(errorFilesAlert)
- .getByText(pasteNotificationsMessages.hasErrorsTitle.defaultMessage)).toBeInTheDocument();
- expect(within(errorFilesAlert)
- .getByText(pasteNotificationsMessages.hasErrorsDescription.defaultMessage)).toBeInTheDocument();
+ expect(
+ within(errorFilesAlert)
+ .getByText(pasteNotificationsMessages.hasErrorsTitle.defaultMessage),
+ ).toBeInTheDocument();
+ expect(
+ within(errorFilesAlert)
+ .getByText(pasteNotificationsMessages.hasErrorsDescription.defaultMessage),
+ ).toBeInTheDocument();
await user.click(within(errorFilesAlert).getByText(/Dismiss/i));
@@ -1737,8 +1887,10 @@ describe('
', () => {
await screen.findByText(
moveModalMessages.moveModalTitle.defaultMessage.replace('{displayName}', requestData.title),
);
- expect(screen.getByRole('button', { name: moveModalMessages.moveModalSubmitButton.defaultMessage })).toBeInTheDocument();
- expect(screen.getByRole('button', { name: moveModalMessages.moveModalCancelButton.defaultMessage })).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: moveModalMessages.moveModalSubmitButton.defaultMessage }))
+ .toBeInTheDocument();
+ expect(screen.getByRole('button', { name: moveModalMessages.moveModalCancelButton.defaultMessage }))
+ .toBeInTheDocument();
});
it('should navigates to xBlock current unit', async () => {
@@ -1760,7 +1912,8 @@ describe('
', () => {
const currentSection = courseOutlineInfoMock.child_info.children[1];
const currentSectionItemBtn = screen.getByRole('button', {
- name: `${currentSection.display_name} ${moveModalMessages.moveModalOutlineItemCurrentLocationText.defaultMessage} ${moveModalMessages.moveModalOutlineItemViewText.defaultMessage}`,
+ name:
+ `${currentSection.display_name} ${moveModalMessages.moveModalOutlineItemCurrentLocationText.defaultMessage} ${moveModalMessages.moveModalOutlineItemViewText.defaultMessage}`,
});
expect(currentSectionItemBtn).toBeInTheDocument();
await user.click(currentSectionItemBtn);
@@ -1768,7 +1921,8 @@ describe('
', () => {
await waitFor(async () => {
const currentSubsection = currentSection.child_info.children[0];
const currentSubsectionItemBtn = screen.getByRole('button', {
- name: `${currentSubsection.display_name} ${moveModalMessages.moveModalOutlineItemCurrentLocationText.defaultMessage} ${moveModalMessages.moveModalOutlineItemViewText.defaultMessage}`,
+ name:
+ `${currentSubsection.display_name} ${moveModalMessages.moveModalOutlineItemCurrentLocationText.defaultMessage} ${moveModalMessages.moveModalOutlineItemViewText.defaultMessage}`,
});
expect(currentSubsectionItemBtn).toBeInTheDocument();
await user.click(currentSubsectionItemBtn);
@@ -1809,7 +1963,8 @@ describe('
', () => {
const currentSection = courseOutlineInfoMock.child_info.children[1];
const currentSectionItemBtn = screen.getByRole('button', {
- name: `${currentSection.display_name} ${moveModalMessages.moveModalOutlineItemCurrentLocationText.defaultMessage} ${moveModalMessages.moveModalOutlineItemViewText.defaultMessage}`,
+ name:
+ `${currentSection.display_name} ${moveModalMessages.moveModalOutlineItemCurrentLocationText.defaultMessage} ${moveModalMessages.moveModalOutlineItemViewText.defaultMessage}`,
});
expect(currentSectionItemBtn).toBeInTheDocument();
await user.click(currentSectionItemBtn);
@@ -1853,25 +2008,31 @@ describe('
', () => {
.onPatch(postXBlockBaseApiUrl())
.reply(200, {});
- await executeThunk(patchUnitItemQuery({
- sourceLocator: requestData.sourceLocator,
- targetParentLocator: requestData.targetParentLocator,
- title: requestData.title,
- currentParentLocator: requestData.currentParentLocator,
- isMoving: requestData.isMoving,
- callbackFn: requestData.callbackFn,
- }), store.dispatch);
+ await executeThunk(
+ patchUnitItemQuery({
+ sourceLocator: requestData.sourceLocator,
+ targetParentLocator: requestData.targetParentLocator,
+ title: requestData.title,
+ currentParentLocator: requestData.currentParentLocator,
+ isMoving: requestData.isMoving,
+ callbackFn: requestData.callbackFn,
+ }),
+ store.dispatch,
+ );
simulatePostMessageEvent(messageTypes.rollbackMovedXBlock, { locator: requestData.sourceLocator });
const dismissButton = screen.getByRole('button', {
- name: /dismiss/i, hidden: true,
+ name: /dismiss/i,
+ hidden: true,
});
const undoButton = screen.getByRole('button', {
- name: messages.undoMoveButton.defaultMessage, hidden: true,
+ name: messages.undoMoveButton.defaultMessage,
+ hidden: true,
});
const newLocationButton = screen.getByRole('button', {
- name: messages.newLocationButton.defaultMessage, hidden: true,
+ name: messages.newLocationButton.defaultMessage,
+ hidden: true,
});
expect(screen.getByText(messages.alertMoveSuccessTitle.defaultMessage)).toBeInTheDocument();
@@ -1901,17 +2062,21 @@ describe('
', () => {
.onPatch(postXBlockBaseApiUrl())
.reply(200, {});
- await executeThunk(patchUnitItemQuery({
- sourceLocator: requestData.sourceLocator,
- targetParentLocator: requestData.targetParentLocator,
- title: requestData.title,
- currentParentLocator: requestData.currentParentLocator,
- isMoving: requestData.isMoving,
- callbackFn: requestData.callbackFn,
- }), store.dispatch);
+ await executeThunk(
+ patchUnitItemQuery({
+ sourceLocator: requestData.sourceLocator,
+ targetParentLocator: requestData.targetParentLocator,
+ title: requestData.title,
+ currentParentLocator: requestData.currentParentLocator,
+ isMoving: requestData.isMoving,
+ callbackFn: requestData.callbackFn,
+ }),
+ store.dispatch,
+ );
const newLocationButton = screen.getByRole('button', {
- name: messages.newLocationButton.defaultMessage, hidden: true,
+ name: messages.newLocationButton.defaultMessage,
+ hidden: true,
});
await user.click(newLocationButton);
expect(mockedUsedNavigate).toHaveBeenCalledWith(
@@ -1963,9 +2128,11 @@ describe('
', () => {
await waitFor(async () => {
const configureModal = screen.getByTestId('configure-modal');
expect(configureModal).toBeInTheDocument();
- await user.click(within(configureModal).getByRole('button', {
- name: configureModalMessages.cancelButton.defaultMessage,
- }));
+ await user.click(
+ within(configureModal).getByRole('button', {
+ name: configureModalMessages.cancelButton.defaultMessage,
+ }),
+ );
expect(handleConfigureSubmitMock).not.toHaveBeenCalled();
});
@@ -2063,12 +2230,18 @@ describe('
', () => {
configureModal = getByTestId('configure-modal');
restrictAccessSelect = within(configureModal)
.getByRole('combobox', { name: configureModalMessages.restrictAccessTo.defaultMessage });
- expect(within(configureModal)
- .getByRole('heading', { name: configureModalMessages[headingMessageId].defaultMessage })).toBeInTheDocument();
- expect(within(configureModal)
- .queryByText(configureModalMessages.unitVisibility.defaultMessage)).not.toBeInTheDocument();
- expect(within(configureModal)
- .getByText(configureModalMessages.restrictAccessTo.defaultMessage)).toBeInTheDocument();
+ expect(
+ within(configureModal)
+ .getByRole('heading', { name: configureModalMessages[headingMessageId].defaultMessage }),
+ ).toBeInTheDocument();
+ expect(
+ within(configureModal)
+ .queryByText(configureModalMessages.unitVisibility.defaultMessage),
+ ).not.toBeInTheDocument();
+ expect(
+ within(configureModal)
+ .getByText(configureModalMessages.restrictAccessTo.defaultMessage),
+ ).toBeInTheDocument();
expect(restrictAccessSelect).toBeInTheDocument();
expect(restrictAccessSelect).toHaveValue('-1');
});
@@ -2121,14 +2294,19 @@ describe('
', () => {
const unitHeaderTitle = await findByTestId('unit-header-title');
await findByText(unitDisplayName);
await waitFor(() => {
- expect(within(unitHeaderTitle).getByRole('button', { name: headerTitleMessages.altButtonEdit.defaultMessage })).toBeInTheDocument();
- expect(within(unitHeaderTitle).getByRole('button', { name: headerTitleMessages.altButtonSettings.defaultMessage })).toBeInTheDocument();
+ expect(within(unitHeaderTitle).getByRole('button', { name: headerTitleMessages.altButtonEdit.defaultMessage }))
+ .toBeInTheDocument();
+ expect(
+ within(unitHeaderTitle).getByRole('button', { name: headerTitleMessages.altButtonSettings.defaultMessage }),
+ ).toBeInTheDocument();
expect(getByRole('button', { name: currentSectionName })).toBeInTheDocument();
expect(getByRole('button', { name: currentSubSectionName })).toBeInTheDocument();
expect(queryByRole('heading', { name: addComponentMessages.title.defaultMessage })).not.toBeInTheDocument();
- expect(queryByRole('button', { name: headerNavigationsMessages.viewLiveButton.defaultMessage })).not.toBeInTheDocument();
- expect(queryByRole('button', { name: headerNavigationsMessages.previewButton.defaultMessage })).not.toBeInTheDocument();
+ expect(queryByRole('button', { name: headerNavigationsMessages.viewLiveButton.defaultMessage })).not
+ .toBeInTheDocument();
+ expect(queryByRole('button', { name: headerNavigationsMessages.previewButton.defaultMessage })).not
+ .toBeInTheDocument();
expect(queryByRole('heading', { name: /unit tags/i })).not.toBeInTheDocument();
expect(queryByRole('heading', { name: /unit location/i })).not.toBeInTheDocument();
@@ -2206,29 +2384,47 @@ describe('
', () => {
const currentSectionName = courseSectionVerticalMock.xblock_info.ancestor_info.ancestors[1].display_name;
const currentSubSectionName = courseSectionVerticalMock.xblock_info.ancestor_info.ancestors[1].display_name;
- const helpLinkUrl = 'https://docs.openedx.org/en/latest/educators/references/course_development/parent_child_components.html';
+ const helpLinkUrl =
+ 'https://docs.openedx.org/en/latest/educators/references/course_development/parent_child_components.html';
await waitFor(() => {
const unitHeaderTitle = screen.getByTestId('unit-header-title');
expect(screen.getByText(unitDisplayName)).toBeInTheDocument();
- expect(within(unitHeaderTitle).getByRole('button', { name: headerTitleMessages.altButtonEdit.defaultMessage })).toBeInTheDocument();
- expect(within(unitHeaderTitle).getByRole('button', { name: headerTitleMessages.altButtonSettings.defaultMessage })).toBeInTheDocument();
+ expect(within(unitHeaderTitle).getByRole('button', { name: headerTitleMessages.altButtonEdit.defaultMessage }))
+ .toBeInTheDocument();
+ expect(
+ within(unitHeaderTitle).getByRole('button', { name: headerTitleMessages.altButtonSettings.defaultMessage }),
+ ).toBeInTheDocument();
expect(screen.getByRole('button', { name: currentSectionName })).toBeInTheDocument();
expect(screen.getByRole('button', { name: currentSubSectionName })).toBeInTheDocument();
- expect(screen.queryByRole('heading', { name: addComponentMessages.title.defaultMessage })).not.toBeInTheDocument();
- expect(screen.queryByRole('button', { name: headerNavigationsMessages.viewLiveButton.defaultMessage })).not.toBeInTheDocument();
- expect(screen.queryByRole('button', { name: headerNavigationsMessages.previewButton.defaultMessage })).not.toBeInTheDocument();
+ expect(screen.queryByRole('heading', { name: addComponentMessages.title.defaultMessage })).not
+ .toBeInTheDocument();
+ expect(screen.queryByRole('button', { name: headerNavigationsMessages.viewLiveButton.defaultMessage })).not
+ .toBeInTheDocument();
+ expect(screen.queryByRole('button', { name: headerNavigationsMessages.previewButton.defaultMessage })).not
+ .toBeInTheDocument();
expect(screen.queryByRole('heading', { name: /unit tags/i })).not.toBeInTheDocument();
expect(screen.queryByRole('heading', { name: /unit location/i })).not.toBeInTheDocument();
// Sidebar
const sidebarContent = [
- { query: screen.queryByRole, type: 'heading', name: legacySidebarMessages.sidebarSplitTestAddComponentTitle.defaultMessage },
- { query: screen.queryByText, name: legacySidebarMessages.sidebarSplitTestSelectComponentType.defaultMessage.replaceAll('{bold_tag}', '') },
+ {
+ query: screen.queryByRole,
+ type: 'heading',
+ name: legacySidebarMessages.sidebarSplitTestAddComponentTitle.defaultMessage,
+ },
+ {
+ query: screen.queryByText,
+ name: legacySidebarMessages.sidebarSplitTestSelectComponentType.defaultMessage.replaceAll('{bold_tag}', ''),
+ },
{ query: screen.queryByText, name: legacySidebarMessages.sidebarSplitTestComponentAdded.defaultMessage },
- { query: screen.queryByRole, type: 'heading', name: legacySidebarMessages.sidebarSplitTestEditComponentTitle.defaultMessage },
+ {
+ query: screen.queryByRole,
+ type: 'heading',
+ name: legacySidebarMessages.sidebarSplitTestEditComponentTitle.defaultMessage,
+ },
{
query: screen.queryByText,
name: legacySidebarMessages.sidebarSplitTestEditComponentInstruction.defaultMessage
@@ -2747,9 +2943,11 @@ describe('
', () => {
await executeThunk(fetchCourseSectionVerticalData(blockId, courseId), store.dispatch);
expect(await screen.findByRole('heading', { name: /draft \(unpublished changes\)/i })).toBeInTheDocument();
expect(await screen.findByText(/access restrictions applied/i)).toBeInTheDocument();
- expect(await screen.findByText(
- /access to some content in this unit is restricted to specific groups of learners\./i,
- ));
+ expect(
+ await screen.findByText(
+ /access to some content in this unit is restricted to specific groups of learners\./i,
+ ),
+ );
});
it('should render never published state in the unit sidebar', async () => {
@@ -2987,7 +3185,9 @@ describe('
', () => {
newMockResult.results[0].query = query;
// And fake the required '_formatted' fields; it contains the highlighting
... around matched words
// eslint-disable-next-line no-underscore-dangle, no-param-reassign
- newMockResult.results[0]?.hits.forEach((hit) => { hit._formatted = { ...hit }; });
+ newMockResult.results[0]?.hits.forEach((hit) => {
+ hit._formatted = { ...hit };
+ });
return newMockResult;
});
@@ -3356,9 +3556,11 @@ describe('
', () => {
const moveBtn = await screen.findByText('Move');
await user.click(moveBtn);
- expect(await screen.findByText(
- moveModalMessages.moveModalTitle.defaultMessage.replace('{displayName}', componentData.displayName),
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ moveModalMessages.moveModalTitle.defaultMessage.replace('{displayName}', componentData.displayName),
+ ),
+ ).toBeInTheDocument();
});
it('opens unlink modal and unlinks component from sidebar menu', async () => {
diff --git a/src/course-unit/CourseUnit.tsx b/src/course-unit/CourseUnit.tsx
index 8cfeff516f..1e27ae9082 100644
--- a/src/course-unit/CourseUnit.tsx
+++ b/src/course-unit/CourseUnit.tsx
@@ -49,7 +49,7 @@ import { UnitSidebarPagesProvider } from './unit-sidebar/UnitSidebarPagesContext
import { UNIT_VISIBILITY_STATES } from './constants';
import { isUnitPageNewDesignEnabled } from './utils';
-const StatusBar = ({ courseUnit }: { courseUnit: any }) => {
+const StatusBar = ({ courseUnit }: { courseUnit: any; }) => {
const { selectedPartitionIndex, selectedGroupsLabel } = courseUnit.userPartitionInfo ?? {};
const hasGroups = selectedPartitionIndex !== -1 && !Number.isNaN(selectedPartitionIndex) && selectedGroupsLabel;
let groupsCount = 0;
@@ -63,10 +63,10 @@ const StatusBar = ({ courseUnit }: { courseUnit: any }) => {
text: messages.statusBarDraftNeverPublished,
icon: DraftIcon,
} as {
- variant: string,
- className?: string,
- text: MessageDescriptor,
- icon: React.ComponentType,
+ variant: string;
+ className?: string;
+ text: MessageDescriptor;
+ icon: React.ComponentType;
};
if (courseUnit.currentlyVisibleToStudents) {
@@ -131,11 +131,11 @@ const StatusBar = ({ courseUnit }: { courseUnit: any }) => {
{groupsCount > 1 && (
{selectedGroupsLabel}
- )}
+ }
>
@@ -238,38 +238,40 @@ const CourseUnit = () => {
- {movedXBlockParams.isSuccess ? (
-
- {intl.formatMessage(messages.undoMoveButton)}
- ,
-
- {intl.formatMessage(messages.newLocationButton)}
- ,
- ]}
- onClose={handleCloseXBlockMovedAlert}
- />
- ) : null}
+ {movedXBlockParams.isSuccess ?
+ (
+
+ {intl.formatMessage(messages.undoMoveButton)}
+ ,
+
+ {intl.formatMessage(messages.newLocationButton)}
+ ,
+ ]}
+ onClose={handleCloseXBlockMovedAlert}
+ />
+ ) :
+ null}
{courseUnit.upstreamInfo?.upstreamLink && (
{
)}
- )}
- breadcrumbs={(
+ }
+ breadcrumbs={
- )}
- headerActions={(
+ }
+ headerActions={
- )}
+ }
/>
- {isUnitPageNewDesignEnabled() && isUnitVerticalType && (
-
- )}
+ {isUnitPageNewDesignEnabled() && isUnitVerticalType && }
{isUnitVerticalType && (
{
const originalModule = jest.requireActual('react-router-dom');
return {
...originalModule,
- Navigate: ({ to }: { to: string }) => Mocked Navigate
,
+ Navigate: ({ to }: { to: string; }) => Mocked Navigate
,
};
});
describe('SubsectionUnitRedirect', () => {
@@ -66,9 +69,11 @@ describe('SubsectionUnitRedirect', () => {
expect(mockNavigate).toBeInTheDocument();
expect(mockNavigate).toHaveAttribute(
'data-to',
- `/course/${courseId}/container/${encodeURIComponent(
- 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@1',
- )}`,
+ `/course/${courseId}/container/${
+ encodeURIComponent(
+ 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@1',
+ )
+ }`,
);
});
});
diff --git a/src/course-unit/__mocks__/courseOutlineInfo.ts b/src/course-unit/__mocks__/courseOutlineInfo.ts
index 3c7ce5a56e..ff7d466acf 100644
--- a/src/course-unit/__mocks__/courseOutlineInfo.ts
+++ b/src/course-unit/__mocks__/courseOutlineInfo.ts
@@ -18,7 +18,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
category: 'sequential',
display_name: 'Subsection',
@@ -30,7 +31,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
category: 'vertical',
display_name: 'Unit',
@@ -42,7 +44,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -52,7 +55,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@f7cc083ff66d442eafafd48152881276',
@@ -61,7 +65,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@video+block@0b9e39477cf34507a7a48f74be381fdd',
@@ -70,7 +75,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@video+block@6e72ebc448694e42ac56553af74304e7',
@@ -79,7 +85,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -94,7 +101,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -106,7 +114,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
category: 'sequential',
display_name: 'Subsection',
@@ -118,7 +127,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
category: 'vertical',
display_name: 'Unit',
@@ -130,7 +140,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -140,7 +151,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -152,7 +164,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -162,7 +175,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@video+block@7e9b434e6de3435ab99bd3fb25bde807',
@@ -171,7 +185,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@412dc8dbb6674014862237b23c1f643f',
@@ -180,7 +195,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -192,7 +208,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -202,7 +219,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@video+block@5c90cffecd9b48b188cbfea176bf7fe9',
@@ -211,7 +229,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@722085be27c84ac693cfebc8ac5da700',
@@ -220,7 +239,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -232,7 +252,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -242,7 +263,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@9f9e1373cc8243b985c8750cc8acec7d',
@@ -251,7 +273,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -263,7 +286,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -273,7 +297,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@video+block@636541acbae448d98ab484b028c9a7f6',
@@ -282,7 +307,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@e2cb0e0994f84b0abfa5f4ae42ed9d44',
@@ -291,7 +317,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -303,7 +330,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -313,7 +341,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@3169f89efde2452993f2f2d9bc74f5b2',
@@ -322,7 +351,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -334,7 +364,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -344,7 +375,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@1c8d47c425724346a7968fa1bc745dcd',
@@ -353,7 +385,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -365,7 +398,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -375,7 +409,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@2574c523e97b477a9d72fbb37bfb995f',
@@ -384,7 +419,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@932e6f2ce8274072a355a94560216d1a',
@@ -393,7 +429,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@303034da25524878a2e66fb57c91cf85',
@@ -402,7 +439,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@ffa5817d49e14fec83ad6187cbe16358',
@@ -411,7 +449,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -423,7 +462,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -433,7 +473,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -448,7 +489,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
category: 'vertical',
display_name: 'Unit',
@@ -460,7 +502,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -470,7 +513,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@e5eac7e1a5a24f5fa7ed77bb6d136591',
@@ -479,7 +523,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -491,7 +536,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -501,7 +547,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@5ab88e67d46049b9aa694cb240c39cef',
@@ -510,7 +557,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -522,7 +570,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -532,7 +581,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@67c26b1e826e47aaa29757f62bcd1ad0',
@@ -541,7 +591,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -553,7 +604,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -563,7 +615,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@870371212ba04dcf9536d7c7b8f3109e',
@@ -572,7 +625,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -584,7 +638,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -594,7 +649,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@4d672c5893cb4f1dad0de67d2008522e',
@@ -603,7 +659,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -615,7 +672,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -625,7 +683,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@501aed9d902349eeb2191fa505548de2',
@@ -634,7 +693,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -646,7 +706,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -656,7 +717,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@6244918637ed4ff4b5f94a840a7e4b43',
@@ -665,7 +727,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -677,7 +740,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [],
},
@@ -695,41 +759,45 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
category: 'sequential',
display_name: 'Subsection',
children: [
{
id: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@simulations',
- display_name: "Lesson 2 - Let's Get Interactive!",
+ display_name: 'Lesson 2 - Let\'s Get Interactive!',
category: 'sequential',
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
category: 'vertical',
display_name: 'Unit',
children: [
{
id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@d0d804e8863c4a95a659c04d8a2b2bc0',
- display_name: "Lesson 2 - Let's Get Interactive! ",
+ display_name: 'Lesson 2 - Let\'s Get Interactive! ',
category: 'vertical',
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@78d7d3642f3a4dbabbd1b017861aa5f2',
- display_name: "Lesson 2: Let's Get Interactive!",
+ display_name: 'Lesson 2: Let\'s Get Interactive!',
category: 'html',
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -741,7 +809,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -751,7 +820,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@6f7a6670f87147149caeff6afa07a526',
@@ -760,7 +830,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -772,7 +843,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -782,7 +854,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@e0d7423118ab432582d03e8e8dad8e36',
@@ -791,7 +864,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -803,7 +877,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -813,7 +888,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@03f051f9a8814881a3783d2511613aa6',
@@ -822,7 +898,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -834,7 +911,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -844,7 +922,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -859,7 +938,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
category: 'vertical',
display_name: 'Unit',
@@ -871,7 +951,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -881,7 +962,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -893,7 +975,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -903,7 +986,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@python_grader',
@@ -912,7 +996,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@c6cd4bea43454aaea60ad01beb0cf213',
@@ -921,7 +1006,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -933,7 +1019,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -943,7 +1030,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@free_form_simulation',
@@ -952,7 +1040,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@logic_gate_problem',
@@ -961,7 +1050,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@4f06b358a96f4d1dae57d6d81acd06f2',
@@ -970,7 +1060,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -982,7 +1073,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -992,7 +1084,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@700x_proteinmake',
@@ -1001,7 +1094,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@ed01bcd164e64038a78964a16eac3edc',
@@ -1010,7 +1104,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -1022,7 +1117,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -1032,7 +1128,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -1047,7 +1144,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
category: 'vertical',
display_name: 'Unit',
@@ -1059,17 +1157,20 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
- id: 'block-v1:edX+DemoX+Demo_Course+type@openassessment+block@b24c33ea35954c7889e1d2944d3fe397',
+ id:
+ 'block-v1:edX+DemoX+Demo_Course+type@openassessment+block@b24c33ea35954c7889e1d2944d3fe397',
display_name: 'Open Response Assessment',
category: 'openassessment',
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@12ad4f3ff4c14114a6e629b00e000976',
@@ -1078,7 +1179,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -1096,7 +1198,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
category: 'sequential',
display_name: 'Subsection',
@@ -1108,7 +1211,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
category: 'vertical',
display_name: 'Unit',
@@ -1120,7 +1224,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -1130,7 +1235,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -1142,7 +1248,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -1152,7 +1259,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@discussion_5deb6081620d',
@@ -1161,7 +1269,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -1173,7 +1282,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -1183,7 +1293,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -1195,7 +1306,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -1205,7 +1317,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -1220,7 +1333,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
category: 'vertical',
display_name: 'Unit',
@@ -1232,7 +1346,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -1242,7 +1357,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -1257,7 +1373,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
category: 'vertical',
display_name: 'Unit',
@@ -1269,7 +1386,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -1279,7 +1397,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@55cbc99f262443d886a25cf84594eafb',
@@ -1288,7 +1407,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@ade92343df3d4953a40ab3adc8805390',
@@ -1297,7 +1417,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -1315,7 +1436,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
category: 'sequential',
display_name: 'Subsection',
@@ -1327,7 +1449,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
category: 'vertical',
display_name: 'Unit',
@@ -1339,7 +1462,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -1349,7 +1473,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -1361,7 +1486,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -1371,7 +1497,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@4aba537a78774bd5a862485a8563c345',
@@ -1380,7 +1507,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -1392,7 +1520,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -1402,7 +1531,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@f480df4ce91347c5ae4301ddf6146238',
@@ -1411,7 +1541,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -1423,7 +1554,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -1433,7 +1565,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@b8cec2a19ebf463f90cd3544c7927b0e',
@@ -1442,7 +1575,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -1454,7 +1588,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -1464,7 +1599,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@d1b84dcd39b0423d9e288f27f0f7f242',
@@ -1473,7 +1609,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@cd177caa62444fbca48aa8f843f09eac',
@@ -1482,7 +1619,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -1494,7 +1632,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -1504,7 +1643,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@ddede76df71045ffa16de9d1481d2119',
@@ -1513,7 +1653,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -1525,7 +1666,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -1535,7 +1677,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@1a810b1a3b2447b998f0917d0e5a802b',
@@ -1544,7 +1687,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -1556,7 +1700,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -1566,7 +1711,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@23e6eda482c04335af2bb265beacaf59',
@@ -1575,7 +1721,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -1587,7 +1734,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -1597,7 +1745,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
{
id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@6b6bee43c7c641509da71c9299cc9f5a',
@@ -1606,7 +1755,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -1624,7 +1774,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
category: 'sequential',
display_name: 'Subsection',
@@ -1636,7 +1787,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
category: 'vertical',
display_name: 'Unit',
@@ -1648,7 +1800,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
child_info: {
children: [
{
@@ -1658,7 +1811,8 @@ export default {
has_children: false,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
@@ -1673,7 +1827,8 @@ export default {
has_children: true,
video_sharing_enabled: true,
video_sharing_options: 'per-video',
- video_sharing_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
+ video_sharing_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
},
],
},
diff --git a/src/course-unit/__mocks__/courseSectionVertical.ts b/src/course-unit/__mocks__/courseSectionVertical.ts
index 7be7b6454f..3056091c23 100644
--- a/src/course-unit/__mocks__/courseSectionVertical.ts
+++ b/src/course-unit/__mocks__/courseSectionVertical.ts
@@ -10,34 +10,40 @@ export default {
is_collapsible: false,
position: 1,
prev_url: '%2Fcontainer%2Fblock-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40vertical%2Bblock%40vertical_0270f6de40fc',
- next_url: '%2Fcontainer%2Fblock-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40vertical%2Bblock%404f6c1b4e316a419ab5b6bf30e6c708e9',
+ next_url:
+ '%2Fcontainer%2Fblock-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40vertical%2Bblock%404f6c1b4e316a419ab5b6bf30e6c708e9',
new_unit_category: 'vertical',
outline_url: '/course/course-v1:edX+DemoX+Demo_Course?format=concise',
ancestor_xblocks: [
{
children: [
{
- url: '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40chapter%2Bblock%40d8a6192ade314473a78242dfeedfbf5b',
+ url:
+ '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40chapter%2Bblock%40d8a6192ade314473a78242dfeedfbf5b',
display_name: 'Introduction 2',
usage_key: 'block-v1:edX+DemoX+Demo_Course+type@chapter+block@v3v57d5h5j4a8s33a78242dfeedfbf5b',
},
{
- url: '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40chapter%2Bblock%40interactive_demonstrations',
+ url:
+ '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40chapter%2Bblock%40interactive_demonstrations',
display_name: 'Example Week 1: Getting Started',
usage_key: 'block-v1:edX+DemoX+Demo_Course+type@chapter+block@4bgkas5384h6f686f8ghj53feedfbf2f',
},
{
- url: '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40chapter%2Bblock%40graded_interactions',
+ url:
+ '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40chapter%2Bblock%40graded_interactions',
display_name: 'Example Week 2: Get Interactive',
usage_key: 'block-v1:edX+DemoX+Demo_Course+type@chapter+block@v3v57d5h5j4a8s33nsdajdsh876fbf3g',
},
{
- url: '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40chapter%2Bblock%40social_integration',
+ url:
+ '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40chapter%2Bblock%40social_integration',
display_name: 'Example Week 3: Be Social',
usage_key: 'block-v1:edX+DemoX+Demo_Course+type@chapter+block@sg8b76g7b68s7s33a78242dfeedfbf4c',
},
{
- url: '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40chapter%2Bblock%401414ffd5143b4b508f739b563ab468b7',
+ url:
+ '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40chapter%2Bblock%401414ffd5143b4b508f739b563ab468b7',
display_name: 'About Exams and Certificates',
usage_key: 'block-v1:edX+DemoX+Demo_Course+type@chapter+block@jhk76823jh42j5kl23kjl2dfeedfbf8d',
},
@@ -48,12 +54,14 @@ export default {
{
children: [
{
- url: '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40sequential%2Bblock%4019a30717eff543078a5d94ae9d6c18a5',
+ url:
+ '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40sequential%2Bblock%4019a30717eff543078a5d94ae9d6c18a5',
display_name: 'Lesson 1 - Getting Started',
usage_key: 'block-v1+edX+DemoX+Demo_Course+type@sequential+block@19a30717eff543078a5d94ae9d6c18a5',
},
{
- url: '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40sequential%2Bblock%40basic_questions',
+ url:
+ '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40sequential%2Bblock%40basic_questions',
display_name: 'Homework - Question Styles',
usage_key: 'block-v1+edX+DemoX+Demo_Course+type@sequential+block@basic_questions',
},
@@ -421,7 +429,8 @@ export default {
edited_on: 'Jan 04, 2024 at 10:32 UTC',
published: true,
published_on: 'Dec 28, 2023 at 10:00 UTC',
- studio_url: '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40sequential%2Bblock%4019a30717eff543078a5d94ae9d6c18a5',
+ studio_url:
+ '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40sequential%2Bblock%4019a30717eff543078a5d94ae9d6c18a5',
released_to_students: true,
release_date: 'Feb 05, 2013 at 05:00 UTC',
visibility_state: 'needs_attention',
@@ -491,7 +500,8 @@ export default {
edited_on: 'Jan 04, 2024 at 10:32 UTC',
published: true,
published_on: 'Dec 28, 2023 at 10:00 UTC',
- studio_url: '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@867dddb6f55d410caaa9c1eb9c6743ec',
+ studio_url:
+ '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@867dddb6f55d410caaa9c1eb9c6743ec',
released_to_students: true,
release_date: 'Feb 05, 2013 at 05:00 UTC',
visibility_state: 'needs_attention',
@@ -575,7 +585,8 @@ export default {
edited_on: 'Dec 28, 2023 at 10:00 UTC',
published: true,
published_on: 'Dec 28, 2023 at 10:00 UTC',
- studio_url: '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@4f6c1b4e316a419ab5b6bf30e6c708e9',
+ studio_url:
+ '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@4f6c1b4e316a419ab5b6bf30e6c708e9',
released_to_students: true,
release_date: 'Feb 05, 2013 at 05:00 UTC',
visibility_state: 'live',
@@ -659,7 +670,8 @@ export default {
edited_on: 'Dec 28, 2023 at 10:00 UTC',
published: true,
published_on: 'Dec 28, 2023 at 10:00 UTC',
- studio_url: '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@3dc16db8d14842e38324e95d4030b8a0',
+ studio_url:
+ '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@3dc16db8d14842e38324e95d4030b8a0',
released_to_students: true,
release_date: 'Feb 05, 2013 at 05:00 UTC',
visibility_state: 'live',
@@ -743,7 +755,8 @@ export default {
edited_on: 'Dec 28, 2023 at 10:00 UTC',
published: true,
published_on: 'Dec 28, 2023 at 10:00 UTC',
- studio_url: '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@4a1bba2a403f40bca5ec245e945b0d76',
+ studio_url:
+ '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@4a1bba2a403f40bca5ec245e945b0d76',
released_to_students: true,
release_date: 'Feb 05, 2013 at 05:00 UTC',
visibility_state: 'live',
@@ -827,7 +840,8 @@ export default {
edited_on: 'Dec 28, 2023 at 10:00 UTC',
published: true,
published_on: 'Dec 28, 2023 at 10:00 UTC',
- studio_url: '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@256f17a44983429fb1a60802203ee4e0',
+ studio_url:
+ '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@256f17a44983429fb1a60802203ee4e0',
released_to_students: true,
release_date: 'Feb 05, 2013 at 05:00 UTC',
visibility_state: 'live',
@@ -911,7 +925,8 @@ export default {
edited_on: 'Dec 28, 2023 at 10:00 UTC',
published: true,
published_on: 'Dec 28, 2023 at 10:00 UTC',
- studio_url: '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@e3601c0abee6427d8c17e6d6f8fdddd1',
+ studio_url:
+ '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@e3601c0abee6427d8c17e6d6f8fdddd1',
released_to_students: true,
release_date: 'Feb 05, 2013 at 05:00 UTC',
visibility_state: 'live',
@@ -995,7 +1010,8 @@ export default {
edited_on: 'Dec 28, 2023 at 10:00 UTC',
published: true,
published_on: 'Dec 28, 2023 at 10:00 UTC',
- studio_url: '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@a79d59cd72034188a71d388f4954a606',
+ studio_url:
+ '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@a79d59cd72034188a71d388f4954a606',
released_to_students: true,
release_date: 'Feb 05, 2013 at 05:00 UTC',
visibility_state: 'live',
@@ -1079,7 +1095,8 @@ export default {
edited_on: 'Dec 28, 2023 at 10:00 UTC',
published: true,
published_on: 'Dec 28, 2023 at 10:00 UTC',
- studio_url: '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@134df56c516a4a0dbb24dd5facef746e',
+ studio_url:
+ '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@134df56c516a4a0dbb24dd5facef746e',
released_to_students: true,
release_date: 'Feb 05, 2013 at 05:00 UTC',
visibility_state: 'live',
@@ -1163,7 +1180,8 @@ export default {
edited_on: 'Dec 28, 2023 at 10:00 UTC',
published: true,
published_on: 'Dec 28, 2023 at 10:00 UTC',
- studio_url: '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@d91b9e5d8bc64d57a1332d06bf2f2193',
+ studio_url:
+ '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@d91b9e5d8bc64d57a1332d06bf2f2193',
released_to_students: true,
release_date: 'Feb 05, 2013 at 05:00 UTC',
visibility_state: 'live',
@@ -1276,7 +1294,8 @@ export default {
edited_on: 'Jan 04, 2024 at 10:32 UTC',
published: true,
published_on: 'Dec 28, 2023 at 10:00 UTC',
- studio_url: '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40chapter%2Bblock%40interactive_demonstrations',
+ studio_url:
+ '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40chapter%2Bblock%40interactive_demonstrations',
released_to_students: true,
release_date: 'Feb 05, 2013 at 05:00 UTC',
visibility_state: 'live',
@@ -1325,7 +1344,8 @@ export default {
highlights: [],
highlights_enabled: true,
highlights_preview_only: false,
- highlights_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/manage_course_highlight_emails.html',
+ highlights_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/manage_course_highlight_emails.html',
ancestor_has_staff_lock: false,
user_partition_info: {
selectable_partitions: [
@@ -1411,7 +1431,8 @@ export default {
highlights_enabled_for_messaging: false,
highlights_enabled: true,
highlights_preview_only: false,
- highlights_doc_url: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/manage_course_highlight_emails.html',
+ highlights_doc_url:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/manage_course_highlight_emails.html',
enable_proctored_exams: false,
enable_timed_exams: true,
ancestor_has_staff_lock: false,
@@ -1477,8 +1498,10 @@ export default {
release_date_from: 'Section "Example Week 1: Getting Started"',
staff_lock_from: null,
},
- draft_preview_link: '//preview.localhost:18000/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@vertical+block@867dddb6f55d410caaa9c1eb9c6743ec',
- published_preview_link: '//localhost:18000/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@vertical+block@867dddb6f55d410caaa9c1eb9c6743ec',
+ draft_preview_link:
+ '//preview.localhost:18000/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@vertical+block@867dddb6f55d410caaa9c1eb9c6743ec',
+ published_preview_link:
+ '//localhost:18000/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@vertical+block@867dddb6f55d410caaa9c1eb9c6743ec',
show_unit_tags: false,
user_clipboard: {
content: null,
diff --git a/src/course-unit/__mocks__/index.ts b/src/course-unit/__mocks__/index.ts
index 0b8b7f5f44..e58b559e4d 100644
--- a/src/course-unit/__mocks__/index.ts
+++ b/src/course-unit/__mocks__/index.ts
@@ -1,6 +1,6 @@
+export { default as clipboardMockResponse } from './clipboardResponse';
+export { default as courseCreateXblockMock } from './courseCreateXblock';
+export { default as courseOutlineInfoMock } from './courseOutlineInfo';
export { default as courseSectionVerticalMock } from './courseSectionVertical';
export { default as courseUnitMock } from './courseUnit';
-export { default as courseCreateXblockMock } from './courseCreateXblock';
export { default as courseVerticalChildrenMock } from './courseVerticalChildren';
-export { default as clipboardMockResponse } from './clipboardResponse';
-export { default as courseOutlineInfoMock } from './courseOutlineInfo';
diff --git a/src/course-unit/add-component/AddComponent.test.tsx b/src/course-unit/add-component/AddComponent.test.tsx
index 0031f905da..a44d44917b 100644
--- a/src/course-unit/add-component/AddComponent.test.tsx
+++ b/src/course-unit/add-component/AddComponent.test.tsx
@@ -59,16 +59,17 @@ jest.mock('../../generic/hooks/context/hooks', () => ({
}),
}));
-const renderComponent = (props?: AddComponentProps) => render(
-
-
- ,
-);
+const renderComponent = (props?: AddComponentProps) =>
+ render(
+
+
+ ,
+ );
describe(' ', () => {
beforeEach(async () => {
@@ -89,8 +90,9 @@ describe(' ', () => {
Object.keys(componentTemplates).forEach((component) => {
const btn = getByRole('button', {
name: new RegExp(
- `${componentTemplates[component].type
- } ${messages.buttonText.defaultMessage} ${componentTemplates[component].display_name}`,
+ `${componentTemplates[component].type} ${messages.buttonText.defaultMessage} ${
+ componentTemplates[component].display_name
+ }`,
'i',
),
});
@@ -147,8 +149,9 @@ describe(' ', () => {
return expect(getByRole('button', {
name: new RegExp(
- `${componentTemplates[component].type
- } ${messages.buttonText.defaultMessage} ${componentTemplates[component].display_name}`,
+ `${componentTemplates[component].type} ${messages.buttonText.defaultMessage} ${
+ componentTemplates[component].display_name
+ }`,
'i',
),
})).toBeInTheDocument();
@@ -289,10 +292,14 @@ describe(' ', () => {
await user.click(advancedBtn);
const modalContainer = getByRole('dialog');
- expect(within(modalContainer).getByRole('button', { name: messages.modalContainerCancelBtnText.defaultMessage })).toBeInTheDocument();
- expect(within(modalContainer).getByRole('button', { name: messages.modalBtnText.defaultMessage })).toBeInTheDocument();
+ expect(within(modalContainer).getByRole('button', { name: messages.modalContainerCancelBtnText.defaultMessage }))
+ .toBeInTheDocument();
+ expect(within(modalContainer).getByRole('button', { name: messages.modalBtnText.defaultMessage }))
+ .toBeInTheDocument();
- await user.click(within(modalContainer).getByRole('button', { name: messages.modalContainerCancelBtnText.defaultMessage }));
+ await user.click(
+ within(modalContainer).getByRole('button', { name: messages.modalContainerCancelBtnText.defaultMessage }),
+ );
expect(queryByRole('button', { name: messages.modalContainerCancelBtnText.defaultMessage })).toBeNull();
expect(queryByRole('button', { name: messages.modalBtnText.defaultMessage })).toBeNull();
@@ -323,9 +330,9 @@ describe(' ', () => {
const createPdfBlock = async (
{ getByRole, queryAllByRole, user }: {
- getByRole: RenderResult['getByRole']
- queryAllByRole: RenderResult['queryAllByRole'],
- user: UserEvent,
+ getByRole: RenderResult['getByRole'];
+ queryAllByRole: RenderResult['queryAllByRole'];
+ user: UserEvent;
},
) => {
const advancedBtn = getByRole('button', {
diff --git a/src/course-unit/add-component/AddComponent.tsx b/src/course-unit/add-component/AddComponent.tsx
index d7fa1e5648..9dd8078f41 100644
--- a/src/course-unit/add-component/AddComponent.tsx
+++ b/src/course-unit/add-component/AddComponent.tsx
@@ -3,7 +3,10 @@ import { useDispatch, useSelector } from 'react-redux';
import { getConfig } from '@edx/frontend-platform';
import { useIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
import {
- ActionRow, Button, StandardModal, useToggle,
+ ActionRow,
+ Button,
+ StandardModal,
+ useToggle,
} from '@openedx/paragon';
import { useWaffleFlags } from '@src/data/apiHooks';
@@ -23,37 +26,37 @@ import ComponentModalView from './add-component-modals/ComponentModalView';
import { getCourseSectionVertical, getCourseUnitData } from '../data/selectors';
type ComponentTemplateData = {
- displayName: string,
- category?: string,
- type: string,
- beta?: boolean,
+ displayName: string;
+ category?: string;
+ type: string;
+ beta?: boolean;
templates: Array<{
- boilerplateName?: string,
- category?: string,
- displayName: string,
- supportLevel?: string | boolean,
- }>,
+ boilerplateName?: string;
+ category?: string;
+ displayName: string;
+ supportLevel?: string | boolean;
+ }>;
supportLegend: {
- allowUnsupportedXblocks?: boolean,
- documentationLabel?: string,
- showLegend?: boolean,
- },
+ allowUnsupportedXblocks?: boolean;
+ documentationLabel?: string;
+ showLegend?: boolean;
+ };
};
export interface AddComponentProps {
- isSplitTestType?: boolean,
- isUnitVerticalType?: boolean,
- parentLocator: string,
+ isSplitTestType?: boolean;
+ isUnitVerticalType?: boolean;
+ parentLocator: string;
handleCreateNewCourseXBlock: (
args: object,
- callback?: (args: { courseKey: string, locator: string }) => void
- ) => void,
- isProblemBankType?: boolean,
+ callback?: (args: { courseKey: string; locator: string; }) => void,
+ ) => void;
+ isProblemBankType?: boolean;
addComponentTemplateData?: {
- blockId: string,
- parentLocator?: string,
- model: ComponentTemplateData,
- },
+ blockId: string;
+ parentLocator?: string;
+ model: ComponentTemplateData;
+ };
}
const AddComponent = ({
@@ -215,71 +218,71 @@ const AddComponent = ({
if (isUnitVerticalType || isSplitTestType || isProblemBankType) {
return (
- {Object.keys(componentTemplates).length && isUnitVerticalType ? (
- <>
-
{intl.formatMessage(messages.title)}
-
- {componentTemplates.map((component: ComponentTemplateData) => {
- const { type, displayName, beta } = component;
- let modalParams: { open: () => void, close: () => void, isOpen: boolean };
+ {Object.keys(componentTemplates).length && isUnitVerticalType ?
+ (
+ <>
+ {intl.formatMessage(messages.title)}
+
+ {componentTemplates.map((component: ComponentTemplateData) => {
+ const { type, displayName, beta } = component;
+ let modalParams: { open: () => void; close: () => void; isOpen: boolean; };
- if (!component.templates.length) {
- return null;
- }
+ if (!component.templates.length) {
+ return null;
+ }
- switch (type) {
- case COMPONENT_TYPES.advanced:
- modalParams = {
- open: openAdvanced,
- close: closeAdvanced,
- isOpen: isOpenAdvanced,
- };
- break;
- case COMPONENT_TYPES.html:
- modalParams = {
- open: openHtml,
- close: closeHtml,
- isOpen: isOpenHtml,
- };
- break;
- case COMPONENT_TYPES.openassessment:
- modalParams = {
- open: openOpenAssessment,
- close: closeOpenAssessment,
- isOpen: isOpenOpenAssessment,
- };
- break;
- default:
- return (
-
- handleCreateNewXBlock(type)}
- displayName={displayName}
- type={type}
- beta={beta}
- />
-
- );
- }
+ switch (type) {
+ case COMPONENT_TYPES.advanced:
+ modalParams = {
+ open: openAdvanced,
+ close: closeAdvanced,
+ isOpen: isOpenAdvanced,
+ };
+ break;
+ case COMPONENT_TYPES.html:
+ modalParams = {
+ open: openHtml,
+ close: closeHtml,
+ isOpen: isOpenHtml,
+ };
+ break;
+ case COMPONENT_TYPES.openassessment:
+ modalParams = {
+ open: openOpenAssessment,
+ close: closeOpenAssessment,
+ isOpen: isOpenOpenAssessment,
+ };
+ break;
+ default:
+ return (
+
+ handleCreateNewXBlock(type)}
+ displayName={displayName}
+ type={type}
+ beta={beta}
+ />
+
+ );
+ }
- return (
-
- );
- })}
-
- >
- ) : null}
+ return (
+
+ );
+ })}
+
+ >
+ ) :
+ null}
{
closeAddLibraryContentModal();
@@ -287,15 +290,13 @@ const AddComponent = ({
}}
isOverflowVisible={false}
size="xl"
- footerNode={
- isSelectLibraryContentModalOpen && (
-
-
-
-
-
- )
- }
+ footerNode={isSelectLibraryContentModalOpen && (
+
+
+
+
+
+ )}
>
{
const intl = useIntl();
diff --git a/src/course-unit/add-component/add-component-modals/ComponentModalView.jsx b/src/course-unit/add-component/add-component-modals/ComponentModalView.jsx
index a0ae6a186e..6ca35afe5e 100644
--- a/src/course-unit/add-component/add-component-modals/ComponentModalView.jsx
+++ b/src/course-unit/add-component/add-component-modals/ComponentModalView.jsx
@@ -21,7 +21,10 @@ const ComponentModalView = ({
const [moduleTitle, setModuleTitle] = useState('');
const { open, close, isOpen } = modalParams;
const {
- type, displayName, templates, supportLegend,
+ type,
+ displayName,
+ templates,
+ supportLegend,
} = component;
const supportLabels = getXBlockSupportMessages(intl);
@@ -76,11 +79,11 @@ const ComponentModalView = ({
{isDisplaySupportLabel && (
{supportLabels[componentTemplate.supportLevel].tooltip}
- )}
+ }
>
{supportLabels[componentTemplate.supportLevel].label}
diff --git a/src/course-unit/add-component/add-component-modals/ModalContainer.jsx b/src/course-unit/add-component/add-component-modals/ModalContainer.jsx
index 047e26d34f..5a939031e5 100644
--- a/src/course-unit/add-component/add-component-modals/ModalContainer.jsx
+++ b/src/course-unit/add-component/add-component-modals/ModalContainer.jsx
@@ -5,7 +5,15 @@ import { useIntl } from '@edx/frontend-platform/i18n';
import messages from '../messages';
const ModalContainer = ({
- title, isOpen, close, children, btnText, size, onSubmit, hasValue, resetDisabled,
+ title,
+ isOpen,
+ close,
+ children,
+ btnText,
+ size,
+ onSubmit,
+ hasValue,
+ resetDisabled,
}) => {
const intl = useIntl();
@@ -25,7 +33,7 @@ const ModalContainer = ({
isOpen={isOpen}
onClose={handleClose}
size={size}
- footerNode={(
+ footerNode={
@@ -35,7 +43,7 @@ const ModalContainer = ({
{btnText}
- )}
+ }
>
{children}
diff --git a/src/course-unit/breadcrumbs/Breadcrumbs.test.tsx b/src/course-unit/breadcrumbs/Breadcrumbs.test.tsx
index 523413ee91..5f47f25251 100644
--- a/src/course-unit/breadcrumbs/Breadcrumbs.test.tsx
+++ b/src/course-unit/breadcrumbs/Breadcrumbs.test.tsx
@@ -1,7 +1,9 @@
import userEvent from '@testing-library/user-event';
import { getConfig } from '@edx/frontend-platform';
import {
- initializeMocks, waitFor, render,
+ initializeMocks,
+ waitFor,
+ render,
} from '../../testUtils';
import { executeThunk } from '../../utils';
@@ -31,9 +33,10 @@ jest.mock('react-router-dom', () => ({
useNavigate: () => mockNavigate,
}));
-const renderComponent = () => render(
-
,
-);
+const renderComponent = () =>
+ render(
+
,
+ );
describe('
', () => {
beforeEach(async () => {
diff --git a/src/course-unit/breadcrumbs/Breadcrumbs.tsx b/src/course-unit/breadcrumbs/Breadcrumbs.tsx
index 875c811b64..1790ff1917 100644
--- a/src/course-unit/breadcrumbs/Breadcrumbs.tsx
+++ b/src/course-unit/breadcrumbs/Breadcrumbs.tsx
@@ -11,12 +11,13 @@ import { useWaffleFlags } from '../../data/apiHooks';
import { getCourseSectionVertical } from '../data/selectors';
import { adoptCourseSectionUrl, subsectionFirstUnitEditUrl } from '../utils';
-const Breadcrumbs = ({ courseId, parentUnitId }: { courseId: string, parentUnitId: string }) => {
+const Breadcrumbs = ({ courseId, parentUnitId }: { courseId: string; parentUnitId: string; }) => {
const { ancestorXblocks = [] } = useSelector(getCourseSectionVertical);
const waffleFlags = useWaffleFlags(courseId);
const getPathToCourseOutlinePage = (url) => (waffleFlags.useNewCourseOutlinePage
- ? url : `${getConfig().STUDIO_BASE_URL}${url}`);
+ ? url :
+ `${getConfig().STUDIO_BASE_URL}${url}`);
const getPathToCourseUnitPage = (url) => (waffleFlags.useNewUnitPage
? adoptCourseSectionUrl({ url, courseId, parentUnitId })
@@ -38,7 +39,7 @@ const Breadcrumbs = ({ courseId, parentUnitId }: { courseId: string, parentUnitI
}
const hasChildWithUrl = (children = []) => (
- !!children.filter((child : any) => child?.url).length
+ !!children.filter((child: any) => child?.url).length
);
return (
@@ -50,42 +51,44 @@ const Breadcrumbs = ({ courseId, parentUnitId }: { courseId: string, parentUnitI
// eslint-disable-next-line react/no-array-index-key
key={`${title}-${index}`}
>
- {hasChildWithUrl(children) ? (
-
-
+ {hasChildWithUrl(children) ?
+ (
+
+
+
+ {title}
+
+
+
+
+ {children.map(({ url, displayName, usageKey }) => (
+
+ {displayName}
+
+ ))}
+
+
+ ) :
+ (
+
{title}
-
-
-
- {children.map(({ url, displayName, usageKey }) => (
-
- {displayName}
-
- ))}
-
-
- ) : (
-
-
- {title}
-
- )}
+ )}
{!isLast && (
(
- {fileList.map((fileName) => (
- {fileName}
- ))}
+ {fileList.map((fileName) => {fileName} )}
);
diff --git a/src/course-unit/clipboard/paste-notification/components/index.ts b/src/course-unit/clipboard/paste-notification/components/index.ts
index ccee5ba494..5ae5d6edb6 100644
--- a/src/course-unit/clipboard/paste-notification/components/index.ts
+++ b/src/course-unit/clipboard/paste-notification/components/index.ts
@@ -1,3 +1,3 @@
+export { default as ActionButton } from './ActionButton';
export { default as AlertContent } from './AlertContent';
export { default as FileList } from './FileList';
-export { default as ActionButton } from './ActionButton';
diff --git a/src/course-unit/clipboard/paste-notification/index.jsx b/src/course-unit/clipboard/paste-notification/index.jsx
index 53f437a185..e16dad1beb 100644
--- a/src/course-unit/clipboard/paste-notification/index.jsx
+++ b/src/course-unit/clipboard/paste-notification/index.jsx
@@ -37,12 +37,12 @@ const PastNotificationAlert = ({ staticFileNotices, courseId }) => {
className="course-unit__alert"
title={intl.formatMessage(messages.hasConflictingErrorsTitle)}
onClose={() => handleCloseNotificationAlert('conflictingFilesAlert')}
- description={(
+ description={
- )}
+ }
variant="warning"
icon={WarningIcon}
dismissible
@@ -61,12 +61,12 @@ const PastNotificationAlert = ({ staticFileNotices, courseId }) => {
className="course-unit__alert"
title={intl.formatMessage(messages.hasErrorsTitle)}
onClose={() => handleCloseNotificationAlert('errorFilesAlert')}
- description={(
+ description={
- )}
+ }
variant="danger"
icon={ErrorIcon}
dismissible
@@ -78,12 +78,12 @@ const PastNotificationAlert = ({ staticFileNotices, courseId }) => {
className="course-unit__alert"
title={intl.formatMessage(messages.hasNewFilesTitle)}
onClose={() => handleCloseNotificationAlert('newFilesAlert')}
- description={(
+ description={
- )}
+ }
variant="info"
icon={InfoIcon}
dismissible
@@ -102,12 +102,11 @@ const PastNotificationAlert = ({ staticFileNotices, courseId }) => {
PastNotificationAlert.propTypes = {
courseId: PropTypes.string.isRequired,
- staticFileNotices:
- PropTypes.shape({
- conflictingFiles: PropTypes.arrayOf(PropTypes.string),
- errorFiles: PropTypes.arrayOf(PropTypes.string),
- newFiles: PropTypes.arrayOf(PropTypes.string),
- }),
+ staticFileNotices: PropTypes.shape({
+ conflictingFiles: PropTypes.arrayOf(PropTypes.string),
+ errorFiles: PropTypes.arrayOf(PropTypes.string),
+ newFiles: PropTypes.arrayOf(PropTypes.string),
+ }),
};
PastNotificationAlert.defaultProps = {
diff --git a/src/course-unit/clipboard/paste-notification/utils.js b/src/course-unit/clipboard/paste-notification/utils.js
index 55428a011d..ae3c0356c2 100644
--- a/src/course-unit/clipboard/paste-notification/utils.js
+++ b/src/course-unit/clipboard/paste-notification/utils.js
@@ -8,4 +8,5 @@
* `false` if it does not, and `null` if fileList is not defined.
*/
export const getAlertStatus = (fileList, alertKey, alertState) => (
- fileList?.length ? fileList && alertState[alertKey] : null);
+ fileList?.length ? fileList && alertState[alertKey] : null
+);
diff --git a/src/course-unit/course-sequence/Sequence.jsx b/src/course-unit/course-sequence/Sequence.jsx
index e17db25a72..96a85e1411 100644
--- a/src/course-unit/course-sequence/Sequence.jsx
+++ b/src/course-unit/course-sequence/Sequence.jsx
@@ -24,7 +24,9 @@ const Sequence = ({
const defaultContent = (
-
+
{intl.formatMessage(messages.sequenceNoContent)}
);
+ return
{intl.formatMessage(messages.sequenceNoContent)}
;
}
return
;
diff --git a/src/course-unit/course-sequence/hooks.js b/src/course-unit/course-sequence/hooks.js
index 28035e1afd..51f2c777ef 100644
--- a/src/course-unit/course-sequence/hooks.js
+++ b/src/course-unit/course-sequence/hooks.js
@@ -40,7 +40,10 @@ export function useSequenceNavigationMetadata(courseId, currentSequenceId, curre
}
return {
- isFirstUnit, isLastUnit, nextLink, previousLink,
+ isFirstUnit,
+ isLastUnit,
+ nextLink,
+ previousLink,
};
}
diff --git a/src/course-unit/course-sequence/sequence-navigation/SequenceNavigation.jsx b/src/course-unit/course-sequence/sequence-navigation/SequenceNavigation.jsx
index fcadcd9cf5..9694992203 100644
--- a/src/course-unit/course-sequence/sequence-navigation/SequenceNavigation.jsx
+++ b/src/course-unit/course-sequence/sequence-navigation/SequenceNavigation.jsx
@@ -3,7 +3,9 @@ import { useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import {
- useIntl, isRtl, getLocale,
+ useIntl,
+ isRtl,
+ getLocale,
} from '@edx/frontend-platform/i18n';
import { Button, useWindowSize, breakpoints } from '@openedx/paragon';
import {
@@ -29,16 +31,17 @@ const SequenceNavigation = ({
const intl = useIntl();
const sequenceStatus = useSelector(getSequenceStatus);
const {
- isFirstUnit, isLastUnit, nextLink, previousLink,
+ isFirstUnit,
+ isLastUnit,
+ nextLink,
+ previousLink,
} = useSequenceNavigationMetadata(courseId, sequenceId, unitId);
const sequence = useModel('sequences', sequenceId);
const shouldDisplayNotificationTriggerInSequence = useWindowSize().width < breakpoints.small.minWidth;
const renderUnitButtons = () => {
if (sequence.unitIds.length === 0 || unitId === null) {
- return (
-
- );
+ return
;
}
return (
diff --git a/src/course-unit/course-sequence/sequence-navigation/SequenceNavigationTabs.jsx b/src/course-unit/course-sequence/sequence-navigation/SequenceNavigationTabs.jsx
index 12fad29b99..0f4ca66bff 100644
--- a/src/course-unit/course-sequence/sequence-navigation/SequenceNavigationTabs.jsx
+++ b/src/course-unit/course-sequence/sequence-navigation/SequenceNavigationTabs.jsx
@@ -14,7 +14,10 @@ import SequenceNavigationDropdown from './SequenceNavigationDropdown';
import UnitButton from './UnitButton';
const SequenceNavigationTabs = ({
- unitIds, unitId, handleCreateNewCourseXBlock, showPasteUnit,
+ unitIds,
+ unitId,
+ handleCreateNewCourseXBlock,
+ showPasteUnit,
}) => {
const intl = useIntl();
const dispatch = useDispatch();
@@ -33,10 +36,13 @@ const SequenceNavigationTabs = ({
const handleAddNewSequenceUnit = () => {
dispatch(updateQueryPendingStatus(true));
- handleCreateNewCourseXBlock({ parentLocator: sequenceId, category: 'vertical', displayName: 'Unit' }, ({ courseKey, locator }) => {
- navigate(`/course/${courseKey}/container/${locator}/${sequenceId}`, courseId);
- dispatch(changeEditTitleFormOpen(true));
- });
+ handleCreateNewCourseXBlock(
+ { parentLocator: sequenceId, category: 'vertical', displayName: 'Unit' },
+ ({ courseKey, locator }) => {
+ navigate(`/course/${courseKey}/container/${locator}/${sequenceId}`, courseId);
+ dispatch(changeEditTitleFormOpen(true));
+ },
+ );
};
const handlePasteNewSequenceUnit = () => {
@@ -62,14 +68,14 @@ const SequenceNavigationTabs = ({
/>
))}
{sequenceChildAddable && (
-
- {intl.formatMessage(messages.newUnitBtnText)}
-
+
+ {intl.formatMessage(messages.newUnitBtnText)}
+
)}
{showPasteUnit && (
getConfig().STUDIO_BASE_URL;
export const getXBlockBaseApiUrl = (itemId: string) => `${getStudioBaseUrl()}/xblock/${itemId}`;
-export const getCourseSectionVerticalApiUrl = (itemId: string) => `${getStudioBaseUrl()}/api/contentstore/v1/container_handler/${itemId}`;
-export const getCourseVerticalChildrenApiUrl = (itemId: string, getUpstreamInfo: boolean = false) => `${getStudioBaseUrl()}/api/contentstore/v1/container/${itemId}/children?get_upstream_info=${getUpstreamInfo}`;
+export const getCourseSectionVerticalApiUrl = (itemId: string) =>
+ `${getStudioBaseUrl()}/api/contentstore/v1/container_handler/${itemId}`;
+export const getCourseVerticalChildrenApiUrl = (itemId: string, getUpstreamInfo: boolean = false) =>
+ `${getStudioBaseUrl()}/api/contentstore/v1/container/${itemId}/children?get_upstream_info=${getUpstreamInfo}`;
export const getCourseOutlineInfoUrl = (courseId: string) => `${getStudioBaseUrl()}/course/${courseId}?format=concise`;
export const postXBlockBaseApiUrl = () => `${getStudioBaseUrl()}/xblock/`;
-export const libraryBlockChangesUrl = (blockId: string) => `${getStudioBaseUrl()}/api/contentstore/v2/downstreams/${blockId}/sync`;
+export const libraryBlockChangesUrl = (blockId: string) =>
+ `${getStudioBaseUrl()}/api/contentstore/v2/downstreams/${blockId}/sync`;
/**
* Edit course unit display name.
@@ -107,8 +110,8 @@ export async function acceptLibraryBlockChanges({
blockId,
overrideCustomizations = false,
}: {
- blockId: string,
- overrideCustomizations?: boolean,
+ blockId: string;
+ overrideCustomizations?: boolean;
}) {
await getAuthenticatedHttpClient()
.post(libraryBlockChangesUrl(blockId), { override_customizations: overrideCustomizations });
@@ -117,7 +120,7 @@ export async function acceptLibraryBlockChanges({
/**
* Ignore the changes from upstream library block in course
*/
-export async function ignoreLibraryBlockChanges({ blockId } : { blockId: string }) {
+export async function ignoreLibraryBlockChanges({ blockId }: { blockId: string; }) {
await getAuthenticatedHttpClient()
.delete(libraryBlockChangesUrl(blockId));
}
diff --git a/src/course-unit/data/apiHooks.ts b/src/course-unit/data/apiHooks.ts
index 05d44a37e7..4bcc8dcff4 100644
--- a/src/course-unit/data/apiHooks.ts
+++ b/src/course-unit/data/apiHooks.ts
@@ -16,17 +16,19 @@ import {
* Hook that provides a "mutation" that can be used to accept library block changes.
*/
// eslint-disable-next-line import/prefer-default-export
-export const useAcceptLibraryBlockChanges = () => useMutation({
- mutationFn: acceptLibraryBlockChanges,
-});
+export const useAcceptLibraryBlockChanges = () =>
+ useMutation({
+ mutationFn: acceptLibraryBlockChanges,
+ });
/**
* Hook that provides a "mutation" that can be used to ignore library block changes.
*/
// eslint-disable-next-line import/prefer-default-export
-export const useIgnoreLibraryBlockChanges = () => useMutation({
- mutationFn: ignoreLibraryBlockChanges,
-});
+export const useIgnoreLibraryBlockChanges = () =>
+ useMutation({
+ mutationFn: ignoreLibraryBlockChanges,
+ });
/**
* Wrapper around useConfigureUnit that updates unit data after processing
@@ -36,19 +38,23 @@ export const useConfigureUnitWithPageUpdates = () => {
const dispatch = useDispatch();
return {
...mutationFn,
- mutate: (mutationArgs: ConfigureUnitData & ParentIds, options?: UseMutationOptions<
- object,
- DefaultError,
- ConfigureUnitData & ParentIds
- >) => mutationFn.mutate(mutationArgs, {
- ...options,
- onSuccess: async (...onMutateArgs) => {
- const courseSectionVerticalData = await getVerticalData(onMutateArgs[1].unitId);
- dispatch(fetchCourseSectionVerticalDataSuccess(courseSectionVerticalData));
- const courseVerticalChildrenData = await getCourseContainerChildren(onMutateArgs[1].unitId);
- dispatch(updateCourseVerticalChildren(courseVerticalChildrenData));
- options?.onSuccess?.(...onMutateArgs);
- },
- }),
+ mutate: (
+ mutationArgs: ConfigureUnitData & ParentIds,
+ options?: UseMutationOptions<
+ object,
+ DefaultError,
+ ConfigureUnitData & ParentIds
+ >,
+ ) =>
+ mutationFn.mutate(mutationArgs, {
+ ...options,
+ onSuccess: async (...onMutateArgs) => {
+ const courseSectionVerticalData = await getVerticalData(onMutateArgs[1].unitId);
+ dispatch(fetchCourseSectionVerticalDataSuccess(courseSectionVerticalData));
+ const courseVerticalChildrenData = await getCourseContainerChildren(onMutateArgs[1].unitId);
+ dispatch(updateCourseVerticalChildren(courseVerticalChildrenData));
+ options?.onSuccess?.(...onMutateArgs);
+ },
+ }),
};
};
diff --git a/src/course-unit/data/selectors.js b/src/course-unit/data/selectors.js
index 00861c60c4..7331799ab9 100644
--- a/src/course-unit/data/selectors.js
+++ b/src/course-unit/data/selectors.js
@@ -18,6 +18,7 @@ export const getMovedXBlockParams = (state) => state.courseUnit.movedXBlockParam
const getLoadingStatuses = (state) => state.courseUnit.loadingStatus;
export const getIsLoading = createSelector(
[getLoadingStatuses],
- loadingStatus => Object.values(loadingStatus)
- .some((status) => status === RequestStatus.IN_PROGRESS),
+ loadingStatus =>
+ Object.values(loadingStatus)
+ .some((status) => status === RequestStatus.IN_PROGRESS),
);
diff --git a/src/course-unit/data/types.ts b/src/course-unit/data/types.ts
index 6624dac893..a2ea541623 100644
--- a/src/course-unit/data/types.ts
+++ b/src/course-unit/data/types.ts
@@ -27,7 +27,7 @@ export interface CourseOutlineData {
category: string;
displayName: string;
children: XBlock[];
- }
+ };
}
export interface ContainerChildData {
diff --git a/src/course-unit/header-navigations/HeaderNavigations.test.tsx b/src/course-unit/header-navigations/HeaderNavigations.test.tsx
index a650677232..192d1c050d 100644
--- a/src/course-unit/header-navigations/HeaderNavigations.test.tsx
+++ b/src/course-unit/header-navigations/HeaderNavigations.test.tsx
@@ -18,15 +18,16 @@ const headerNavigationsActions = {
handleEdit: handleEditFn,
};
-const renderComponent = (props) => render(
-
-
- ,
-);
+const renderComponent = (props) =>
+ render(
+
+
+ ,
+ );
jest.mock('../unit-sidebar/UnitSidebarContext', () => ({
useUnitSidebarContext: () => ({
diff --git a/src/course-unit/header-navigations/HeaderNavigations.tsx b/src/course-unit/header-navigations/HeaderNavigations.tsx
index 093dd0cb54..de7d0c997e 100644
--- a/src/course-unit/header-navigations/HeaderNavigations.tsx
+++ b/src/course-unit/header-navigations/HeaderNavigations.tsx
@@ -1,9 +1,14 @@
import { useIntl } from '@edx/frontend-platform/i18n';
import {
- Button, ButtonGroup, Stack,
+ Button,
+ ButtonGroup,
+ Stack,
} from '@openedx/paragon';
import {
- Add, Edit as EditIcon, FindInPage, InfoOutline,
+ Add,
+ Edit as EditIcon,
+ FindInPage,
+ InfoOutline,
} from '@openedx/paragon/icons';
import { COURSE_BLOCK_NAMES } from '@src/constants';
@@ -42,9 +47,11 @@ const HeaderNavigations = ({ headerNavigationsActions, category }: HeaderNavigat
return (
- {/**
- * Action buttons used in the unit page
- */}
+ {
+ /**
+ * Action buttons used in the unit page
+ */
+ }
{category === COURSE_BLOCK_NAMES.vertical.id && (
{showNewDesignButtons && (
@@ -81,13 +88,14 @@ const HeaderNavigations = ({ headerNavigationsActions, category }: HeaderNavigat
>
{intl.formatMessage(messages.viewLiveButton)}
-
)}
- {/**
- * Action buttons used in legacy libraries content page and split test page
- */}
+ {
+ /**
+ * Action buttons used in legacy libraries content page and split test page
+ */
+ }
{[COURSE_BLOCK_NAMES.libraryContent.id, COURSE_BLOCK_NAMES.splitTest.id].includes(category) && (
render(
-
- ,
- ,
-);
+const renderComponent = (props?: any) =>
+ render(
+
+ ,
+ ,
+ );
describe(' ', () => {
beforeEach(async () => {
diff --git a/src/course-unit/header-title/HeaderTitle.tsx b/src/course-unit/header-title/HeaderTitle.tsx
index 00b67eb235..67991c98b5 100644
--- a/src/course-unit/header-title/HeaderTitle.tsx
+++ b/src/course-unit/header-title/HeaderTitle.tsx
@@ -1,7 +1,9 @@
import { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import {
- Form, IconButton, useToggle,
+ Form,
+ IconButton,
+ useToggle,
} from '@openedx/paragon';
import {
EditOutline as EditIcon,
@@ -60,10 +62,11 @@ const HeaderTitle = ({
type: PUBLISH_TYPES.republish,
unitId: currentItemData.id,
}, {
- onSuccess: () => sendMessageToIframe(
- messageTypes.completeManageXBlockAccess,
- { locator: currentItemData.id },
- ),
+ onSuccess: () =>
+ sendMessageToIframe(
+ messageTypes.completeManageXBlockAccess,
+ { locator: currentItemData.id },
+ ),
onSettled: () => closeConfigureModal(),
});
};
@@ -75,23 +78,25 @@ const HeaderTitle = ({
return (
- {isTitleEditFormOpen ? (
-
- e && e.focus()}
- value={titleValue}
- name="displayName"
- onChange={(e) => setTitleValue(e.target.value)}
- aria-label={intl.formatMessage(messages.ariaLabelButtonEdit)}
- onBlur={() => handleTitleEditSubmit(titleValue)}
- onKeyDown={(e) => {
- if (e.key === 'Enter') {
- handleTitleEditSubmit(titleValue);
- }
- }}
- />
-
- ) : unitTitle}
+ {isTitleEditFormOpen ?
+ (
+
+ e && e.focus()}
+ value={titleValue}
+ name="displayName"
+ onChange={(e) => setTitleValue(e.target.value)}
+ aria-label={intl.formatMessage(messages.ariaLabelButtonEdit)}
+ onBlur={() => handleTitleEditSubmit(titleValue)}
+ onKeyDown={(e) => {
+ if (e.key === 'Enter') {
+ handleTitleEditSubmit(titleValue);
+ }
+ }}
+ />
+
+ ) :
+ unitTitle}
{
+}: { courseId: string; blockId: string; }) => {
const dispatch = useDispatch();
const [searchParams] = useSearchParams();
const { sendMessageToIframe } = useIframe();
@@ -132,10 +135,11 @@ export const useCourseUnit = ({
dispatch(duplicateUnitItemQuery(
blockId,
XBlockId,
- (courseKey: string, locator: string) => sendMessageToIframe(
- messageTypes.completeXBlockDuplicating,
- { courseKey, locator },
- ),
+ (courseKey: string, locator: string) =>
+ sendMessageToIframe(
+ messageTypes.completeXBlockDuplicating,
+ { courseKey, locator },
+ ),
));
},
handleUnlink: async (XBlockId: string) => {
@@ -150,7 +154,10 @@ export const useCourseUnit = ({
const handleRollbackMovedXBlock = () => {
const {
- sourceLocator, targetParentLocator, title, currentParentLocator,
+ sourceLocator,
+ targetParentLocator,
+ title,
+ currentParentLocator,
} = movedXBlockParams;
dispatch(patchUnitItemQuery({
sourceLocator,
@@ -273,12 +280,12 @@ export const useCourseUnit = ({
};
};
-export const useHandleCreateNewCourseXBlock = ({ blockId }: { blockId: string }) => {
+export const useHandleCreateNewCourseXBlock = ({ blockId }: { blockId: string; }) => {
const dispatch = useDispatch();
const { sendMessageToIframe } = useIframe();
// oxlint-disable typescript-eslint(await-thenable)
- return async (body: object, callback?: (args: { courseKey: string, locator: string }) => void) => (
+ return async (body: object, callback?: (args: { courseKey: string; locator: string; }) => void) => (
// eslint-disable-next-line @typescript-eslint/return-await
await dispatch(createNewCourseXBlock(body, callback, blockId, sendMessageToIframe))
);
diff --git a/src/course-unit/iframeEvents.ts b/src/course-unit/iframeEvents.ts
index f8d2103888..3b2b961017 100644
--- a/src/course-unit/iframeEvents.ts
+++ b/src/course-unit/iframeEvents.ts
@@ -13,13 +13,15 @@ export const dispatchShowMoveXBlockModal = (
sourceXBlockInfo: XBlockInfo,
sourceParentXBlockInfo: XBlockInfo,
) => {
- window.dispatchEvent(new MessageEvent('message', {
- data: {
- type: messageTypes.showMoveXBlockModal,
- payload: {
- sourceXBlockInfo,
- sourceParentXBlockInfo,
+ window.dispatchEvent(
+ new MessageEvent('message', {
+ data: {
+ type: messageTypes.showMoveXBlockModal,
+ payload: {
+ sourceXBlockInfo,
+ sourceParentXBlockInfo,
+ },
},
- },
- }));
+ }),
+ );
};
diff --git a/src/course-unit/legacy-sidebar/SidebarSection.tsx b/src/course-unit/legacy-sidebar/SidebarSection.tsx
index 2feccdcc82..53faf933eb 100644
--- a/src/course-unit/legacy-sidebar/SidebarSection.tsx
+++ b/src/course-unit/legacy-sidebar/SidebarSection.tsx
@@ -1,7 +1,7 @@
import classNames from 'classnames';
import { Card } from '@openedx/paragon';
-const SidebarSection = ({ className = null, children = null, ...props }:SidebarSectionProps) => (
+const SidebarSection = ({ className = null, children = null, ...props }: SidebarSectionProps) => (
{
diff --git a/src/course-unit/legacy-sidebar/components/SidebarBody.jsx b/src/course-unit/legacy-sidebar/components/SidebarBody.jsx
index b7dce23a23..59bb403641 100644
--- a/src/course-unit/legacy-sidebar/components/SidebarBody.jsx
+++ b/src/course-unit/legacy-sidebar/components/SidebarBody.jsx
@@ -25,36 +25,39 @@ const SidebarBody = ({
} = useSelector(getCourseUnitData);
return (
-
- {displayUnitLocation ? (
-
-
- {intl.formatMessage(messages.unitLocationTitle)}
-
-
- {locationId}
-
-
- ) : (
- <>
+ {displayUnitLocation ?
+ (
- {getPublishInfo(intl, hasChanges, editedBy, editedOn, publishedBy, publishedOn)}
-
-
- {releaseLabel}
+ {intl.formatMessage(messages.unitLocationTitle)}
-
+
+ {locationId}
+
-
- {intl.formatMessage(messages.sidebarBodyNote)}
-
- >
- )}
+ ) :
+ (
+ <>
+
+ {getPublishInfo(intl, hasChanges, editedBy, editedOn, publishedBy, publishedOn)}
+
+
+
+ {releaseLabel}
+
+
+
+
+ {intl.formatMessage(messages.sidebarBodyNote)}
+
+ >
+ )}
);
diff --git a/src/course-unit/legacy-sidebar/components/index.ts b/src/course-unit/legacy-sidebar/components/index.ts
index 6637529e61..c7b6c75cca 100644
--- a/src/course-unit/legacy-sidebar/components/index.ts
+++ b/src/course-unit/legacy-sidebar/components/index.ts
@@ -1,3 +1,3 @@
-export { default as SidebarHeader } from './SidebarHeader';
-export { default as SidebarBody } from './SidebarBody';
export { default as SidebarFooter } from './sidebar-footer';
+export { default as SidebarBody } from './SidebarBody';
+export { default as SidebarHeader } from './SidebarHeader';
diff --git a/src/course-unit/legacy-sidebar/components/sidebar-footer/ActionButtons.test.jsx b/src/course-unit/legacy-sidebar/components/sidebar-footer/ActionButtons.test.jsx
index 652b0234d1..56cd476610 100644
--- a/src/course-unit/legacy-sidebar/components/sidebar-footer/ActionButtons.test.jsx
+++ b/src/course-unit/legacy-sidebar/components/sidebar-footer/ActionButtons.test.jsx
@@ -22,15 +22,16 @@ let axiosMock;
let queryClient;
const courseId = '123';
-const renderComponent = (props = {}) => render(
-
-
-
-
-
-
- ,
-);
+const renderComponent = (props = {}) =>
+ render(
+
+
+
+
+
+
+ ,
+ );
describe(' ', () => {
beforeEach(async () => {
diff --git a/src/course-unit/legacy-sidebar/components/sidebar-footer/ActionButtons.tsx b/src/course-unit/legacy-sidebar/components/sidebar-footer/ActionButtons.tsx
index 82572b5d89..c86636d577 100644
--- a/src/course-unit/legacy-sidebar/components/sidebar-footer/ActionButtons.tsx
+++ b/src/course-unit/legacy-sidebar/components/sidebar-footer/ActionButtons.tsx
@@ -8,9 +8,9 @@ import { useClipboard } from '@src/generic/clipboard';
import messages from '../../messages';
interface ActionButtonsProps {
- openDiscardModal: () => void,
- handlePublishing: () => void,
- hideCopyButton?: boolean,
+ openDiscardModal: () => void;
+ handlePublishing: () => void;
+ hideCopyButton?: boolean;
}
const ActionButtons = ({
diff --git a/src/course-unit/legacy-sidebar/components/sidebar-footer/index.tsx b/src/course-unit/legacy-sidebar/components/sidebar-footer/index.tsx
index 88c601c436..681c736e8a 100644
--- a/src/course-unit/legacy-sidebar/components/sidebar-footer/index.tsx
+++ b/src/course-unit/legacy-sidebar/components/sidebar-footer/index.tsx
@@ -5,11 +5,11 @@ import messages from '../../messages';
import ActionButtons from './ActionButtons';
interface SidebarFooterProps {
- locationId?: string,
- displayUnitLocation?: boolean,
- openDiscardModal: () => void,
- handlePublishing: () => void,
- hideCopyButton?: boolean,
+ locationId?: string;
+ displayUnitLocation?: boolean;
+ openDiscardModal: () => void;
+ handlePublishing: () => void;
+ hideCopyButton?: boolean;
}
const SidebarFooter = ({
@@ -24,17 +24,19 @@ const SidebarFooter = ({
return (
- {displayUnitLocation ? (
-
- {intl.formatMessage(messages.unitLocationDescription, { id: locationId })}
-
- ) : (
-
- )}
+ {displayUnitLocation ?
+ (
+
+ {intl.formatMessage(messages.unitLocationDescription, { id: locationId })}
+
+ ) :
+ (
+
+ )}
);
diff --git a/src/course-unit/legacy-sidebar/hooks.jsx b/src/course-unit/legacy-sidebar/hooks.jsx
index 94e9087cbf..336be4f8c4 100644
--- a/src/course-unit/legacy-sidebar/hooks.jsx
+++ b/src/course-unit/legacy-sidebar/hooks.jsx
@@ -5,7 +5,10 @@ import messages from './messages';
import { extractCourseUnitId } from './utils';
const useCourseUnitData = ({
- hasChanges, published, visibilityState, id,
+ hasChanges,
+ published,
+ visibilityState,
+ id,
}) => {
const intl = useIntl();
const releaseStatus = getUnitReleaseStatus(intl);
@@ -16,7 +19,8 @@ const useCourseUnitData = ({
[UNIT_VISIBILITY_STATES.live]: messages.sidebarTitlePublishedAndLive,
// eslint-disable-next-line no-nested-ternary
default: published
- ? (hasChanges ? messages.sidebarTitleDraftUnpublishedChanges
+ ? (hasChanges ?
+ messages.sidebarTitleDraftUnpublishedChanges
: messages.sidebarTitlePublishedNotYetReleased)
: messages.sidebarTitleDraftNeverPublished,
};
diff --git a/src/course-unit/legacy-sidebar/index.tsx b/src/course-unit/legacy-sidebar/index.tsx
index 399a2f00c3..e5ea7cd56b 100644
--- a/src/course-unit/legacy-sidebar/index.tsx
+++ b/src/course-unit/legacy-sidebar/index.tsx
@@ -10,9 +10,9 @@ import SplitTestSidebarInfo from './SplitTestSidebarInfo';
import PublishControls from '../unit-sidebar/unit-info/PublishControls';
export type XBlock = {
- id: string,
- name: string,
- blockType: string,
+ id: string;
+ name: string;
+ blockType: string;
};
export interface LegacySidebarProps {
diff --git a/src/course-unit/move-modal/components/CategoryIndicator.tsx b/src/course-unit/move-modal/components/CategoryIndicator.tsx
index 58160b51b4..64065f76ae 100644
--- a/src/course-unit/move-modal/components/CategoryIndicator.tsx
+++ b/src/course-unit/move-modal/components/CategoryIndicator.tsx
@@ -2,7 +2,7 @@ import { useIntl } from '@edx/frontend-platform/i18n';
import messages from '../messages';
-const CategoryIndicator = ({ categoryText, displayName }: { categoryText: string, displayName: string }) => {
+const CategoryIndicator = ({ categoryText, displayName }: { categoryText: string; displayName: string; }) => {
const intl = useIntl();
return (
diff --git a/src/course-unit/move-modal/components/EmptyMessage.tsx b/src/course-unit/move-modal/components/EmptyMessage.tsx
index 99737b0aa3..0254bf9302 100644
--- a/src/course-unit/move-modal/components/EmptyMessage.tsx
+++ b/src/course-unit/move-modal/components/EmptyMessage.tsx
@@ -2,7 +2,7 @@ import { useIntl } from '@edx/frontend-platform/i18n';
import messages from '../messages';
-const EmptyMessage = ({ category, categoryText }: { category: string, categoryText: string }) => {
+const EmptyMessage = ({ category, categoryText }: { category: string; categoryText: string; }) => {
const intl = useIntl();
return (
diff --git a/src/course-unit/move-modal/components/index.ts b/src/course-unit/move-modal/components/index.ts
index 4d07788092..2d8a78733d 100644
--- a/src/course-unit/move-modal/components/index.ts
+++ b/src/course-unit/move-modal/components/index.ts
@@ -1,3 +1,3 @@
+export { default as CategoryIndicator } from './CategoryIndicator';
export { default as EmptyMessage } from './EmptyMessage';
export { default as ModalLoader } from './ModalLoader';
-export { default as CategoryIndicator } from './CategoryIndicator';
diff --git a/src/course-unit/move-modal/hooks.tsx b/src/course-unit/move-modal/hooks.tsx
index be06cf1b3f..9723fff7a2 100644
--- a/src/course-unit/move-modal/hooks.tsx
+++ b/src/course-unit/move-modal/hooks.tsx
@@ -1,5 +1,8 @@
import {
- useCallback, useEffect, useState, useMemo,
+ useCallback,
+ useEffect,
+ useState,
+ useMemo,
} from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useParams } from 'react-router-dom';
@@ -15,17 +18,26 @@ import { useIframe } from '../../generic/hooks/context/hooks';
import { messageTypes } from '../constants';
import { CATEGORIES, MOVE_DIRECTIONS } from './constants';
import {
- findParentIds, getBreadcrumbs, getXBlockType, isValidCategory,
+ findParentIds,
+ getBreadcrumbs,
+ getXBlockType,
+ isValidCategory,
} from './utils';
import {
- IState, IUseMoveModalParams, IUseMoveModalReturn, IXBlockInfo,
+ IState,
+ IUseMoveModalParams,
+ IUseMoveModalReturn,
+ IXBlockInfo,
} from './interfaces';
// eslint-disable-next-line import/prefer-default-export
export const useMoveModal = ({
- isOpenModal, closeModal, openModal, courseId,
+ isOpenModal,
+ closeModal,
+ openModal,
+ courseId,
}: IUseMoveModalParams): IUseMoveModalReturn => {
- const { blockId } = useParams<{ blockId: string }>();
+ const { blockId } = useParams<{ blockId: string; }>();
const intl = useIntl();
const dispatch = useDispatch();
const { sendMessageToIframe } = useIframe();
@@ -49,7 +61,7 @@ export const useMoveModal = ({
[courseOutlineInfo, state.sourceXBlockInfo.current.id],
);
- const receiveMessage = useCallback(({ data }: { data: any }) => {
+ const receiveMessage = useCallback(({ data }: { data: any; }) => {
const { payload, type } = data;
if (type === messageTypes.showMoveXBlockModal) {
@@ -211,8 +223,12 @@ export const useMoveModal = ({
enableMoveOperation(state.parentInfo.parent);
}
}, [
- state.parentInfo, isOpenModal, courseOutlineInfoLoadingStatus, updateChildrenItemsData,
- setDisplayedXBlocksCategories, enableMoveOperation,
+ state.parentInfo,
+ isOpenModal,
+ courseOutlineInfoLoadingStatus,
+ updateChildrenItemsData,
+ setDisplayedXBlocksCategories,
+ enableMoveOperation,
]);
return {
diff --git a/src/course-unit/move-modal/index.tsx b/src/course-unit/move-modal/index.tsx
index 5168d54e9c..c40525ef3d 100644
--- a/src/course-unit/move-modal/index.tsx
+++ b/src/course-unit/move-modal/index.tsx
@@ -18,7 +18,10 @@ import { EmptyMessage, ModalLoader, CategoryIndicator } from './components';
import messages from './messages';
const MoveModal: FC = ({
- isOpenModal, closeModal, openModal, courseId,
+ isOpenModal,
+ closeModal,
+ openModal,
+ courseId,
}) => {
const intl = useIntl();
@@ -38,7 +41,10 @@ const MoveModal: FC = ({
handleCLoseModal,
handleMoveXBlock,
} = useMoveModal({
- isOpenModal, closeModal, openModal, courseId,
+ isOpenModal,
+ closeModal,
+ openModal,
+ courseId,
});
const renderBreadcrumbs = useCallback(() => (
@@ -74,26 +80,32 @@ const MoveModal: FC = ({
), [currentXBlockParentIds, handleXBlockClick]);
- const renderCourseStructureItemSpan = useCallback((xBlock: IXBlock) => (
-
-
- {xBlock?.displayName}
-
- {currentXBlockParentIds.includes(xBlock.id) && (
-
- {intl.formatMessage(messages.moveModalOutlineItemCurrentComponentLocationText)}
+ const renderCourseStructureItemSpan = useCallback(
+ (xBlock: IXBlock) => (
+
+
+ {xBlock?.displayName}
- )}
-
- ), [currentXBlockParentIds]);
+ {currentXBlockParentIds.includes(xBlock.id) && (
+
+ {intl.formatMessage(messages.moveModalOutlineItemCurrentComponentLocationText)}
+
+ )}
+
+ ),
+ [currentXBlockParentIds],
+ );
- const renderCourseStructureListItem = useCallback((xBlock: IXBlock, index: number) => (
-
- {sourceXBlockId !== xBlock.id && (xBlock?.childInfo || childrenInfo.category !== CATEGORIES.KEYS.component)
- ? getCourseStructureItemButton(xBlock, index)
- : renderCourseStructureItemSpan(xBlock)}
-
- ), [sourceXBlockId, childrenInfo.category, getCourseStructureItemButton, renderCourseStructureItemSpan]);
+ const renderCourseStructureListItem = useCallback(
+ (xBlock: IXBlock, index: number) => (
+
+ {sourceXBlockId !== xBlock.id && (xBlock?.childInfo || childrenInfo.category !== CATEGORIES.KEYS.component)
+ ? getCourseStructureItemButton(xBlock, index)
+ : renderCourseStructureItemSpan(xBlock)}
+
+ ),
+ [sourceXBlockId, childrenInfo.category, getCourseStructureItemButton, renderCourseStructureItemSpan],
+ );
return (
render(
-
-
-
-
-
-
- ,
-);
+const renderComponent = (props?: any) =>
+ render(
+
+
+
+
+
+
+ ,
+ );
describe(' ', () => {
beforeEach(async () => {
diff --git a/src/course-unit/move-modal/utils.test.ts b/src/course-unit/move-modal/utils.test.ts
index 8721787de2..9c563188a2 100644
--- a/src/course-unit/move-modal/utils.test.ts
+++ b/src/course-unit/move-modal/utils.test.ts
@@ -1,7 +1,10 @@
import { CATEGORIES } from './constants';
import { ITreeNode, IXBlockInfo, IAncestor } from './interfaces';
import {
- getXBlockType, findParentIds, isValidCategory, getBreadcrumbs,
+ getXBlockType,
+ findParentIds,
+ isValidCategory,
+ getBreadcrumbs,
} from './utils';
import messages from './messages';
diff --git a/src/course-unit/move-modal/utils.ts b/src/course-unit/move-modal/utils.ts
index e875d672c6..7b52da8c19 100644
--- a/src/course-unit/move-modal/utils.ts
+++ b/src/course-unit/move-modal/utils.ts
@@ -9,7 +9,7 @@ import messages from './messages';
* @returns {string} - The determined XBlock type (e.g., 'section', 'subsection', 'unit').
*/
export const getXBlockType = (category: string): string => {
- const categoryMap: { [key: string]: string } = {
+ const categoryMap: { [key: string]: string; } = {
[CATEGORIES.KEYS.chapter]: CATEGORIES.KEYS.section,
[CATEGORIES.KEYS.sequential]: CATEGORIES.KEYS.subsection,
[CATEGORIES.KEYS.vertical]: CATEGORIES.KEYS.unit,
@@ -74,17 +74,17 @@ export const isValidCategory = (
if (
sourceParentHasChildren
- && sourceParentCategory
- && !(BASIC_BLOCK_TYPES as readonly string[]).includes(sourceParentCategory)
+ && sourceParentCategory
+ && !(BASIC_BLOCK_TYPES as readonly string[]).includes(sourceParentCategory)
) {
sourceParentCategory = CATEGORIES.KEYS.vertical;
}
if (
targetParentHasChildren
- && targetParentCategory
- && !(BASIC_BLOCK_TYPES as readonly string[]).includes(targetParentCategory)
- && targetParentCategory !== CATEGORIES.KEYS.split_test
+ && targetParentCategory
+ && !(BASIC_BLOCK_TYPES as readonly string[]).includes(targetParentCategory)
+ && targetParentCategory !== CATEGORIES.KEYS.split_test
) {
targetParentCategory = CATEGORIES.KEYS.vertical;
}
diff --git a/src/course-unit/preview-changes/index.tsx b/src/course-unit/preview-changes/index.tsx
index ecee04f7fa..82a9f0a3ff 100644
--- a/src/course-unit/preview-changes/index.tsx
+++ b/src/course-unit/preview-changes/index.tsx
@@ -1,8 +1,15 @@
import {
- useCallback, useContext, useMemo, useState,
+ useCallback,
+ useContext,
+ useMemo,
+ useState,
} from 'react';
import {
- ActionRow, Button, Icon, ModalDialog, useToggle,
+ ActionRow,
+ Button,
+ Icon,
+ ModalDialog,
+ useToggle,
} from '@openedx/paragon';
import { Info } from '@openedx/paragon/icons';
import { useIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
@@ -29,9 +36,9 @@ const ConfirmationModal = ({
onClose,
updateAndRefresh,
}: {
- modalType: ConfirmationModalType,
- onClose: () => void,
- updateAndRefresh: (accept: boolean, overrideCustomizations: boolean) => void,
+ modalType: ConfirmationModalType;
+ onClose: () => void;
+ updateAndRefresh: (accept: boolean, overrideCustomizations: boolean) => void;
}) => {
const intl = useIntl();
@@ -98,21 +105,21 @@ const ConfirmationModal = ({
};
export interface LibraryChangesMessageData {
- displayName: string,
- downstreamBlockId: string,
- upstreamBlockId: string,
- upstreamBlockVersionSynced: number,
- isLocallyModified?: boolean,
- isContainer: boolean,
- blockType?: string | null,
- isReadyToSyncIndividually?: boolean,
+ displayName: string;
+ downstreamBlockId: string;
+ upstreamBlockId: string;
+ upstreamBlockVersionSynced: number;
+ isLocallyModified?: boolean;
+ isContainer: boolean;
+ blockType?: string | null;
+ isReadyToSyncIndividually?: boolean;
}
export interface PreviewLibraryXBlockChangesProps {
- blockData: LibraryChangesMessageData,
- isModalOpen: boolean,
- closeModal: () => void,
- postChange: (accept: boolean) => void,
+ blockData: LibraryChangesMessageData;
+ isModalOpen: boolean;
+ closeModal: () => void;
+ postChange: (accept: boolean) => void;
}
/**
@@ -133,7 +140,7 @@ export const PreviewLibraryXBlockChanges = ({
const acceptChangesMutation = useAcceptLibraryBlockChanges();
const ignoreChangesMutation = useIgnoreLibraryBlockChanges();
- const isTextWithLocalChanges = (blockData.blockType === 'html' && blockData.isLocallyModified);
+ const isTextWithLocalChanges = blockData.blockType === 'html' && blockData.isLocallyModified;
const getBody = useCallback(() => {
if (!blockData) {
@@ -249,33 +256,37 @@ export const PreviewLibraryXBlockChanges = ({
- {isTextWithLocalChanges ? (
- setConfirmationModalType('update')}
- >
-
-
- ) : (
- updateAndRefresh(true, false)}
- label={intl.formatMessage(messages.acceptChangesBtn)}
- />
- )}
- {isTextWithLocalChanges ? (
- setConfirmationModalType('keep')}
- >
-
-
- ) : (
- setConfirmationModalType('ignore')}
- >
-
-
- )}
+ {isTextWithLocalChanges ?
+ (
+ setConfirmationModalType('update')}
+ >
+
+
+ ) :
+ (
+ updateAndRefresh(true, false)}
+ label={intl.formatMessage(messages.acceptChangesBtn)}
+ />
+ )}
+ {isTextWithLocalChanges ?
+ (
+ setConfirmationModalType('keep')}
+ >
+
+
+ ) :
+ (
+ setConfirmationModalType('ignore')}
+ >
+
+
+ )}
{
data: {
payload: LibraryChangesMessageData;
type: string;
- }
+ };
}) => {
const { payload, type } = data;
diff --git a/src/course-unit/unit-sidebar/AddSidebar.tsx b/src/course-unit/unit-sidebar/AddSidebar.tsx
index e85af37118..425ba0f97f 100644
--- a/src/course-unit/unit-sidebar/AddSidebar.tsx
+++ b/src/course-unit/unit-sidebar/AddSidebar.tsx
@@ -4,7 +4,11 @@ import { useParams } from 'react-router-dom';
import {
Button,
Icon,
- Stack, StandardModal, Tab, Tabs, useToggle,
+ Stack,
+ StandardModal,
+ Tab,
+ Tabs,
+ useToggle,
} from '@openedx/paragon';
import { ChevronLeft, ChevronRight } from '@openedx/paragon/icons';
import { getConfig } from '@edx/frontend-platform';
diff --git a/src/course-unit/unit-sidebar/UnitAlignSidebar.test.tsx b/src/course-unit/unit-sidebar/UnitAlignSidebar.test.tsx
index 36736284be..a90ad0bd43 100644
--- a/src/course-unit/unit-sidebar/UnitAlignSidebar.test.tsx
+++ b/src/course-unit/unit-sidebar/UnitAlignSidebar.test.tsx
@@ -16,13 +16,14 @@ jest.mock('react-router-dom', () => ({
useParams: () => ({ blockId: 'unit-id-1' }),
}));
-const renderComponent = () => render(
-
-
-
-
- ,
-);
+const renderComponent = () =>
+ render(
+
+
+
+
+ ,
+ );
describe('OutlineAlignSidebar', () => {
beforeEach(() => {
diff --git a/src/course-unit/unit-sidebar/UnitAlignSidebar.tsx b/src/course-unit/unit-sidebar/UnitAlignSidebar.tsx
index 4ea33d837c..4ecbb28ff9 100644
--- a/src/course-unit/unit-sidebar/UnitAlignSidebar.tsx
+++ b/src/course-unit/unit-sidebar/UnitAlignSidebar.tsx
@@ -26,10 +26,9 @@ export const UnitAlignSidebar = () => {
return (
diff --git a/src/course-unit/unit-sidebar/UnitSidebar.tsx b/src/course-unit/unit-sidebar/UnitSidebar.tsx
index 0c1593fdc6..72f2743cf1 100644
--- a/src/course-unit/unit-sidebar/UnitSidebar.tsx
+++ b/src/course-unit/unit-sidebar/UnitSidebar.tsx
@@ -6,7 +6,7 @@ import { UnitSidebarPageKeys, useUnitSidebarContext } from './UnitSidebarContext
import { useUnitSidebarPagesContext } from './UnitSidebarPagesContext';
export type UnitSidebarProps = {
- legacySidebarProps: LegacySidebarProps,
+ legacySidebarProps: LegacySidebarProps;
};
/**
@@ -26,9 +26,7 @@ export const UnitSidebar = ({
const sidebarPages = useUnitSidebarPagesContext();
if (!isUnitPageNewDesignEnabled()) {
- return (
-
- );
+ return ;
}
const handleChangePage = (key: UnitSidebarPageKeys) => {
diff --git a/src/course-unit/unit-sidebar/UnitSidebarContext.tsx b/src/course-unit/unit-sidebar/UnitSidebarContext.tsx
index bb8b75cf87..1c1e397d2f 100644
--- a/src/course-unit/unit-sidebar/UnitSidebarContext.tsx
+++ b/src/course-unit/unit-sidebar/UnitSidebarContext.tsx
@@ -1,5 +1,9 @@
import {
- createContext, useCallback, useContext, useMemo, useState,
+ createContext,
+ useCallback,
+ useContext,
+ useMemo,
+ useState,
} from 'react';
import { SidebarPage } from '@src/generic/sidebar';
import { useToggle } from '@openedx/paragon';
@@ -29,8 +33,8 @@ export const UnitSidebarProvider = ({
children,
readOnly,
}: {
- children?: React.ReactNode,
- readOnly: boolean,
+ children?: React.ReactNode;
+ readOnly: boolean;
}) => {
const { sendMessageToIframe } = useIframe();
const [currentPageKey, setCurrentPageKeyState] = useStateWithUrlSearchParam(
@@ -41,7 +45,7 @@ export const UnitSidebarProvider = ({
);
const [currentTabKey, setCurrentTabKey] = useState();
const [selectedComponentId, setSelectedComponentId] = useState();
- const [isOpen, open,, toggle] = useToggle(true);
+ const [isOpen, open, , toggle] = useToggle(true);
const setCurrentPageKey = useCallback(/* istanbul ignore next */ (
pageKey: UnitSidebarPageKeys,
diff --git a/src/course-unit/unit-sidebar/unit-info/ComponentInfoSidebar.test.tsx b/src/course-unit/unit-sidebar/unit-info/ComponentInfoSidebar.test.tsx
index c58e7c5770..e4eb761aad 100644
--- a/src/course-unit/unit-sidebar/unit-info/ComponentInfoSidebar.test.tsx
+++ b/src/course-unit/unit-sidebar/unit-info/ComponentInfoSidebar.test.tsx
@@ -30,7 +30,10 @@ const componentData = {
displayName: 'Component Name',
category: 'problem',
actions: {
- deletable: true, duplicable: true, draggable: true, childAddable: false,
+ deletable: true,
+ duplicable: true,
+ draggable: true,
+ childAddable: false,
},
upstreamInfo: null,
};
@@ -88,17 +91,18 @@ const mockSidebarContext = {
readOnly: false,
};
-const renderComponent = () => render(
-
-
-
-
- ,
- {
- path: '/course/:courseId',
- params: { courseId: 'course-v1:UNIX+UX1+2025_T3' },
- },
-);
+const renderComponent = () =>
+ render(
+
+
+
+
+ ,
+ {
+ path: '/course/:courseId',
+ params: { courseId: 'course-v1:UNIX+UX1+2025_T3' },
+ },
+ );
describe(' ', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -145,4 +149,4 @@ describe(' ', () => {
expect(screen.queryByText('Delete')).not.toBeInTheDocument();
expect(screen.queryByText('Duplicate')).not.toBeInTheDocument();
});
-});
\ No newline at end of file
+});
diff --git a/src/course-unit/unit-sidebar/unit-info/ComponentInfoSidebar.tsx b/src/course-unit/unit-sidebar/unit-info/ComponentInfoSidebar.tsx
index 462dc074d8..e827175273 100644
--- a/src/course-unit/unit-sidebar/unit-info/ComponentInfoSidebar.tsx
+++ b/src/course-unit/unit-sidebar/unit-info/ComponentInfoSidebar.tsx
@@ -21,7 +21,11 @@ import { useUnlinkDownstream, UnlinkModal } from '@src/generic/unlink-modal';
import { useClipboard } from '@src/generic/clipboard';
import DeleteModal from '@src/generic/delete-modal/DeleteModal';
import Loading from '@src/generic/Loading';
-import { deleteUnitItemQuery, duplicateUnitItemQuery, fetchCourseVerticalChildrenData } from '@src/course-unit/data/thunk';
+import {
+ deleteUnitItemQuery,
+ duplicateUnitItemQuery,
+ fetchCourseVerticalChildrenData,
+} from '@src/course-unit/data/thunk';
import { useUnitSidebarContext } from '../UnitSidebarContext';
import messages from './messages';
@@ -90,10 +94,11 @@ export const ComponentInfoSidebar = () => {
dispatch(duplicateUnitItemQuery(
unitData.id,
selectedComponentId,
- (courseKey: string, locator: string) => sendMessageToIframe(
- messageTypes.completeXBlockDuplicating,
- { courseKey, locator },
- ),
+ (courseKey: string, locator: string) =>
+ sendMessageToIframe(
+ messageTypes.completeXBlockDuplicating,
+ { courseKey, locator },
+ ),
));
}
};
diff --git a/src/course-unit/unit-sidebar/unit-info/GenericUnitInfoSettings.tsx b/src/course-unit/unit-sidebar/unit-info/GenericUnitInfoSettings.tsx
index 8f2b23f9a6..8e1e4926ab 100644
--- a/src/course-unit/unit-sidebar/unit-info/GenericUnitInfoSettings.tsx
+++ b/src/course-unit/unit-sidebar/unit-info/GenericUnitInfoSettings.tsx
@@ -143,7 +143,9 @@ export const GenericUnitInfoSettings = (props: UnitInfoSettingsProps) => {
onSubmit={handleSaveGroups}
>
{({
- values, setFieldValue, dirty,
+ values,
+ setFieldValue,
+ dirty,
}) => (
diff --git a/src/editors/containers/PdfEditor/api.ts b/src/editors/containers/PdfEditor/api.ts
index f74c0fa472..039f27be57 100644
--- a/src/editors/containers/PdfEditor/api.ts
+++ b/src/editors/containers/PdfEditor/api.ts
@@ -7,28 +7,35 @@ import type { Axios, AxiosResponse } from 'axios';
import * as urls from '@src/editors/data/services/cms/urls';
interface UseBlockDataParams {
- blockId: string,
- uniqueId: string,
- handlerName: string,
- defaultData: T,
+ blockId: string;
+ uniqueId: string;
+ handlerName: string;
+ defaultData: T;
}
interface DeriveHandlerUrlParams {
- studioEndpointUrl: string,
- blockId: string,
- handlerName: string,
- isLibrary: boolean,
- client: Axios,
+ studioEndpointUrl: string;
+ blockId: string;
+ handlerName: string;
+ isLibrary: boolean;
+ client: Axios;
}
-export const immediate = (val: T) => new Promise((resolve) => { resolve(val); });
+export const immediate = (val: T) =>
+ new Promise((resolve) => {
+ resolve(val);
+ });
const deriveHandlerUrl = async ({
- studioEndpointUrl, blockId, handlerName, isLibrary, client,
+ studioEndpointUrl,
+ blockId,
+ handlerName,
+ isLibrary,
+ client,
}: DeriveHandlerUrlParams) => {
if (isLibrary) {
return client.get(urls.boundHandlerUrl({ studioEndpointUrl, blockId, handlerName })).then(
- (response: AxiosResponse<{ handler_url: string }>) => response.data.handler_url,
+ (response: AxiosResponse<{ handler_url: string; }>) => response.data.handler_url,
);
}
return urls.handlerUrl({ blockId, studioEndpointUrl, handlerName });
@@ -36,7 +43,10 @@ const deriveHandlerUrl = async ({
// Unique ID required due to intractable race conditions. See ./contexts.tsx file.
export const useBlockHandlerData = ({
- blockId, uniqueId, handlerName, defaultData,
+ blockId,
+ uniqueId,
+ handlerName,
+ defaultData,
}: UseBlockDataParams) => {
const studioEndpointUrl = useSelector(selectors.app.studioEndpointUrl)!;
const isLibrary = useSelector(selectors.app.isLibrary);
@@ -51,7 +61,11 @@ export const useBlockHandlerData = ({
}
return client.get(
await deriveHandlerUrl({
- blockId, studioEndpointUrl, handlerName, isLibrary, client,
+ blockId,
+ studioEndpointUrl,
+ handlerName,
+ isLibrary,
+ client,
}),
{ cancelSource: signal },
).then((res: AxiosResponse) => camelizeKeys(res.data) as T);
diff --git a/src/editors/containers/PdfEditor/components/PdfEditingModal.tsx b/src/editors/containers/PdfEditor/components/PdfEditingModal.tsx
index f671bb5a66..5ca2369750 100644
--- a/src/editors/containers/PdfEditor/components/PdfEditingModal.tsx
+++ b/src/editors/containers/PdfEditor/components/PdfEditingModal.tsx
@@ -1,7 +1,10 @@
import { EditorComponent } from '@src/editors/EditorComponent';
import { useFormikContext } from 'formik';
import React, {
- PropsWithChildren, useContext, useEffect, useRef,
+ PropsWithChildren,
+ useContext,
+ useEffect,
+ useRef,
} from 'react';
import EditorContainer from '@src/editors/containers/EditorContainer';
import { PdfBlockContext, PdfState } from '@src/editors/containers/PdfEditor/contexts';
diff --git a/src/editors/containers/PdfEditor/contexts.tsx b/src/editors/containers/PdfEditor/contexts.tsx
index ba32ac325d..5fade7dc4d 100644
--- a/src/editors/containers/PdfEditor/contexts.tsx
+++ b/src/editors/containers/PdfEditor/contexts.tsx
@@ -1,5 +1,8 @@
import React, {
- createContext, useEffect, useMemo, useState,
+ createContext,
+ useEffect,
+ useMemo,
+ useState,
} from 'react';
import { v4 as uuidv4 } from 'uuid';
import { useQueryClient } from '@tanstack/react-query';
@@ -8,21 +11,21 @@ import { selectors } from '@src/editors/data/redux';
import { useBlockHandlerData } from './api';
export interface PdfState {
- displayName: string,
- url: string,
- allowDownload: boolean,
- sourceText: string,
- sourceUrl: string,
+ displayName: string;
+ url: string;
+ allowDownload: boolean;
+ sourceText: string;
+ sourceUrl: string;
// Note: Not a field, so can't be set.
- disableAllDownload: boolean,
+ disableAllDownload: boolean;
}
declare interface PdfBlockContextInterface {
- fields: PdfState,
- fetchError: Error | null,
- isPending: boolean,
- blockId: string,
- isLibrary: boolean,
+ fields: PdfState;
+ fetchError: Error | null;
+ isPending: boolean;
+ blockId: string;
+ isLibrary: boolean;
}
export const initialPdfState: () => PdfState = () => ({
@@ -42,13 +45,16 @@ export const PdfBlockContext = createContext({
isLibrary: false,
});
-export const PdfBlockContextProvider: React.FC<{ blockId: string, children: React.ReactNode }> = (
+export const PdfBlockContextProvider: React.FC<{ blockId: string; children: React.ReactNode; }> = (
{ blockId, children },
) => {
const [uniqueId] = useState(() => uuidv4());
const defaultData = useMemo(initialPdfState, []);
const { data, error, isPending } = useBlockHandlerData({
- blockId, uniqueId, handlerName: 'load_pdf', defaultData,
+ blockId,
+ uniqueId,
+ handlerName: 'load_pdf',
+ defaultData,
});
const isLibrary = useSelector(selectors.app.isLibrary);
@@ -82,7 +88,5 @@ export const PdfBlockContextProvider: React.FC<{ blockId: string, children: Reac
isLibrary,
}), [data, error, isPending]);
- return (
- {children}
- );
+ return {children} ;
};
diff --git a/src/editors/containers/PdfEditor/index.test.tsx b/src/editors/containers/PdfEditor/index.test.tsx
index c00b7f9518..5e26a8dc70 100644
--- a/src/editors/containers/PdfEditor/index.test.tsx
+++ b/src/editors/containers/PdfEditor/index.test.tsx
@@ -10,73 +10,74 @@ import editorMessages from '@src/editors/containers/EditorContainer/messages';
import { fireEvent, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
-const render = () => editorRender(
- undefined} returnFunction={() => () => undefined} />,
- {
- initialState: {
- app: {
- blockValue: {
- data: {
- id: 'pdf-block-id',
- display_name: 'PDF',
- category: 'pdf',
- has_children: false,
- has_changes: null,
- explanatory_message: null,
- group_access: {},
- data: '',
- metadata: {
+const render = () =>
+ editorRender(
+ undefined} returnFunction={() => () => undefined} />,
+ {
+ initialState: {
+ app: {
+ blockValue: {
+ data: {
+ id: 'pdf-block-id',
display_name: 'PDF',
+ category: 'pdf',
+ has_children: false,
+ has_changes: null,
+ explanatory_message: null,
+ group_access: {},
+ data: '',
+ metadata: {
+ display_name: 'PDF',
+ },
},
},
- },
- unitUrl: {
- data: {
- ancestors: [
- {
- id: 'block-v1:Test+TS102+2026+type@vertical+block@29f73003508e47e0af00b495ecdc66f1',
- display_name: 'Unit',
- category: 'vertical',
- has_children: true,
- },
- {
- id: 'block-v1:Test+TS102+2026+type@sequential+block@a9f3bc6ad94a4e108449b5c84a46f7ba',
- display_name: 'Subsection',
- category: 'sequential',
- has_children: true,
- },
- {
- id: 'block-v1:Test+TS102+2026+type@chapter+block@606d3cab05a94551b71c5abbd0009baf',
- display_name: 'Section',
- category: 'chapter',
- has_children: true,
- },
- {
- id: 'block-v1:Test+TS102+2026+type@course+block@course',
- display_name: 'New Test Course',
- category: 'course',
- has_children: true,
- unit_level_discussions: true,
- },
- ],
+ unitUrl: {
+ data: {
+ ancestors: [
+ {
+ id: 'block-v1:Test+TS102+2026+type@vertical+block@29f73003508e47e0af00b495ecdc66f1',
+ display_name: 'Unit',
+ category: 'vertical',
+ has_children: true,
+ },
+ {
+ id: 'block-v1:Test+TS102+2026+type@sequential+block@a9f3bc6ad94a4e108449b5c84a46f7ba',
+ display_name: 'Subsection',
+ category: 'sequential',
+ has_children: true,
+ },
+ {
+ id: 'block-v1:Test+TS102+2026+type@chapter+block@606d3cab05a94551b71c5abbd0009baf',
+ display_name: 'Section',
+ category: 'chapter',
+ has_children: true,
+ },
+ {
+ id: 'block-v1:Test+TS102+2026+type@course+block@course',
+ display_name: 'New Test Course',
+ category: 'course',
+ has_children: true,
+ unit_level_discussions: true,
+ },
+ ],
+ },
},
+ blockId: 'pdf-block-id',
+ blockTitle: 'PDF',
+ blockType: 'pdf',
+ learningContextId: 'course-v1:Test+TS102+2026',
+ editorInitialized: false,
+ studioEndpointUrl: 'https://studio.local',
+ lmsEndpointUrl: 'http://local.openedx.io:8000',
+ images: {},
+ imageCount: 0,
+ videos: {},
+ courseDetails: {},
+ showRawEditor: false,
},
- blockId: 'pdf-block-id',
- blockTitle: 'PDF',
- blockType: 'pdf',
- learningContextId: 'course-v1:Test+TS102+2026',
- editorInitialized: false,
- studioEndpointUrl: 'https://studio.local',
- lmsEndpointUrl: 'http://local.openedx.io:8000',
- images: {},
- imageCount: 0,
- videos: {},
- courseDetails: {},
- showRawEditor: false,
},
},
- },
-);
+ );
describe('PdfEditor', () => {
let axiosMock: MockAdapter;
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.jsx
index 5fffc0de61..852a05acbb 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.jsx
@@ -87,12 +87,11 @@ const AnswerOption = ({
}
}}
placeholder={intl.formatMessage(messages.answerTextboxPlaceholder)}
-
/>
{(!data?.isValid) && (
-
-
-
+
+
+
)}
);
@@ -152,7 +151,10 @@ const AnswerOption = ({
-
+
{
const myProps = { ...props, answer: { ...answerWithOnlyFeedback, isAnswerRange: false } };
render( );
expect(
- screen.getByText('Error: This input type only supports numeric answers. Did you mean to make a Text input or Math expression input problem?'),
+ screen.getByText(
+ 'Error: This input type only supports numeric answers. Did you mean to make a Text input or Math expression input problem?',
+ ),
).toBeInTheDocument();
});
});
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.jsx
index c849dbde22..e7ed7a6dfe 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.jsx
@@ -33,41 +33,45 @@ const AnswersContainer = ({ problemType }) => {
/>
))}
- {problemType !== ProblemTypeKeys.NUMERIC ? (
-
-
-
- ) : (
-
-
-
-
-
-
+ ) :
+ (
+
+
+
-
- 1 || (answers.length === 1 && answers[0].isAnswerRange) ? 'disabled' : ''}`}
- >
-
-
-
-
- )}
+
+
+
+
+
+ 1 || (answers.length === 1 && answers[0].isAnswerRange) ? 'disabled' : ''
+ }`}
+ >
+
+
+
+
+ )}
);
};
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.test.tsx b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.test.tsx
index 2f6bebdb9e..0b9719ef6d 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.test.tsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.test.tsx
@@ -2,7 +2,10 @@ import React from 'react';
import { ProblemTypeKeys } from '@src/editors/data/constants/problem';
import {
- render, screen, fireEvent, initializeMocks,
+ render,
+ screen,
+ fireEvent,
+ initializeMocks,
} from '@src/testUtils';
import { actions } from '@src/editors/data/redux';
import AnswersContainer from './AnswersContainer';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/index.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/index.jsx
index 308e175477..9ea0c1b783 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/index.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/index.jsx
@@ -22,9 +22,7 @@ const Checker = ({
isValid={answer.correct}
disabled={disabled}
/>
-
+
{answer.id}
>
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/index.test.tsx b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/index.test.tsx
index 5f32e4c774..14ed39620c 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/index.test.tsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/index.test.tsx
@@ -1,5 +1,8 @@
import {
- render, screen, initializeMocks, fireEvent,
+ render,
+ screen,
+ initializeMocks,
+ fireEvent,
} from '@src/testUtils';
import Checker from '.';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Feedback/FeedbackBox.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Feedback/FeedbackBox.jsx
index 52cbc5c24f..92695dc73a 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Feedback/FeedbackBox.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Feedback/FeedbackBox.jsx
@@ -25,40 +25,42 @@ export const FeedbackBox = ({
learningContextId,
};
- return ((problemType === ProblemTypeKeys.MULTISELECT) ? (
-
-
-
-
- ) : (
-
-
-
- ));
+ return ((problemType === ProblemTypeKeys.MULTISELECT) ?
+ (
+
+
+
+
+ ) :
+ (
+
+
+
+ ));
};
FeedbackBox.propTypes = {
answer: answerOptionProps.isRequired,
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Feedback/FeedbackBox.test.tsx b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Feedback/FeedbackBox.test.tsx
index 7e2f21e76b..f4f7d5b20c 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Feedback/FeedbackBox.test.tsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Feedback/FeedbackBox.test.tsx
@@ -1,11 +1,13 @@
import { render, screen, initializeMocks } from '@src/testUtils';
import { FeedbackBox } from './FeedbackBox';
-jest.mock('../../../../../../../sharedComponents/ExpandableTextArea', () => jest.fn(({
- id, value, setContent, placeholder,
-}) => (
-
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Feedback/FeedbackControl.test.tsx b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Feedback/FeedbackControl.test.tsx
index b6959cf33e..c7edcb78a8 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Feedback/FeedbackControl.test.tsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Feedback/FeedbackControl.test.tsx
@@ -1,14 +1,19 @@
import React from 'react';
import {
- render, screen, fireEvent, initializeMocks,
+ render,
+ screen,
+ fireEvent,
+ initializeMocks,
} from '../../../../../../../../testUtils';
import FeedbackControl from './FeedbackControl';
-jest.mock('../../../../../../../sharedComponents/ExpandableTextArea', () => jest.fn(({
- id, value, setContent, placeholder,
-}) => (
- setContent(e.target.value)} />
-)));
+jest.mock('../../../../../../../sharedComponents/ExpandableTextArea', () =>
+ jest.fn(({
+ id,
+ value,
+ setContent,
+ placeholder,
+ }) => setContent(e.target.value)} />));
const defaultProps = {
feedback: 'Initial feedback',
@@ -50,12 +55,14 @@ describe('FeedbackControl', () => {
});
it('renders with different isLibrary, images, and learningContextId', () => {
- render( );
+ render(
+ ,
+ );
expect(screen.getByRole('textbox', { name: '' })).toBeInTheDocument();
});
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Feedback/messages.ts b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Feedback/messages.ts
index b8b9ad8b2f..19e8a1aa9f 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Feedback/messages.ts
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Feedback/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
feedbackPlaceholder: {
id: 'authoring.answerwidget.feedback.placeholder',
defaultMessage: 'Feedback message',
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/hooks.js b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/hooks.js
index b94de1ca15..13fd9275eb 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/hooks.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/hooks.js
@@ -17,7 +17,8 @@ export const state = StrictDict({
export const removeAnswer = ({
answer,
dispatch,
-}) => () => {
+}) =>
+() => {
dispatch(actions.problem.deleteAnswer({
id: answer.id,
correct: answer.correct,
@@ -34,7 +35,8 @@ export const setAnswerTitle = ({
hasSingleAnswer,
dispatch,
problemType,
-}) => (updatedTitle, isDirty) => {
+}) =>
+(updatedTitle, isDirty) => {
let title = updatedTitle;
if ([ProblemTypeKeys.TEXTINPUT, ProblemTypeKeys.NUMERIC, ProblemTypeKeys.DROPDOWN].includes(problemType)) {
title = updatedTitle.target.value;
@@ -106,5 +108,11 @@ export const useAnswerContainer = ({ answers, updateField }) => {
};
export default {
- state, removeAnswer, setAnswer, setAnswerTitle, useFeedback, isSingleAnswerProblem, useAnswerContainer,
+ state,
+ removeAnswer,
+ setAnswer,
+ setAnswerTitle,
+ useFeedback,
+ isSingleAnswerProblem,
+ useAnswerContainer,
};
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/hooks.test.js b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/hooks.test.js
index 5400365c16..da85d82273 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/hooks.test.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/hooks.test.js
@@ -15,7 +15,7 @@ jest.mock('react', () => {
const updateState = jest.fn();
return {
useEffect: jest.fn(),
- useState: jest.fn(val => ([{ state: val }, (newVal) => updateState({ val, newVal })])),
+ useState: jest.fn(val => [{ state: val }, (newVal) => updateState({ val, newVal })]),
};
});
jest.mock('@edx/frontend-platform/i18n', () => ({
@@ -179,14 +179,18 @@ describe('Answer Options Hooks', () => {
test('toggleFeedback with selected feedback', () => {
const key = state.keys.isFeedbackVisible;
output = module.useFeedback(answerWithOnlyFeedback);
- windowSpy.mockImplementation(() => ({ tinymce: { editors: { 'selectedFeedback-A': { getContent: () => 'string' } } } }));
+ windowSpy.mockImplementation(() => ({
+ tinymce: { editors: { 'selectedFeedback-A': { getContent: () => 'string' } } },
+ }));
output.toggleFeedback(false);
expect(state.setState[key]).toHaveBeenCalledWith(true);
});
test('toggleFeedback with unselected feedback', () => {
const key = state.keys.isFeedbackVisible;
output = module.useFeedback(answerWithOnlyFeedback);
- windowSpy.mockImplementation(() => ({ tinymce: { editors: { 'unselectedFeedback-A': { getContent: () => 'string' } } } }));
+ windowSpy.mockImplementation(() => ({
+ tinymce: { editors: { 'unselectedFeedback-A': { getContent: () => 'string' } } },
+ }));
output.toggleFeedback(false);
expect(state.setState[key]).toHaveBeenCalledWith(true);
});
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.jsx
index cbe42ee20c..960bcf4ff8 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.jsx
@@ -27,7 +27,7 @@ const ExplanationWidget = ({
const solutionContent = newContent || initialContent;
let staticRootUrl;
if (isLibrary) {
- staticRootUrl = `${getConfig().STUDIO_BASE_URL }/library_assets/blocks/${ blockId }/`;
+ staticRootUrl = `${getConfig().STUDIO_BASE_URL}/library_assets/blocks/${blockId}/`;
}
if (!refReady) { return null; }
return (
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/messages.ts b/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/messages.ts
index 5b0eeda7d9..3c3952f132 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/messages.ts
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
solutionWidgetTitle: {
id: 'authoring.problemEditor.explanationwidget.explanationWidgetTitle',
defaultMessage: 'Explanation',
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.jsx
index f8020721a1..a02aa01d75 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.jsx
@@ -27,7 +27,7 @@ const QuestionWidget = ({
const questionContent = newContent || initialContent;
let staticRootUrl;
if (isLibrary) {
- staticRootUrl = `${getConfig().STUDIO_BASE_URL }/library_assets/blocks/${ blockId }/`;
+ staticRootUrl = `${getConfig().STUDIO_BASE_URL}/library_assets/blocks/${blockId}/`;
}
if (!refReady) { return null; }
return (
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/messages.ts b/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/messages.ts
index a3a61fd957..8e1bb7e002 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/messages.ts
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
questionWidgetTitle: {
id: 'authoring.questionwidget.question.questionWidgetTitle',
defaultMessage: 'Question',
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/CardSection.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/CardSection.jsx
index 4c0157c0e2..663e977023 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/CardSection.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/CardSection.jsx
@@ -1,11 +1,16 @@
import React from 'react';
import { Collapsible, Card } from '@openedx/paragon';
import {
- bool, string, node,
+ bool,
+ string,
+ node,
} from 'prop-types';
const CardSection = ({
- children, none, isCardCollapsibleOpen, summary,
+ children,
+ none,
+ isCardCollapsibleOpen,
+ summary,
}) => {
const show = isCardCollapsibleOpen || summary;
if (!show) { return null; }
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/CardSection.test.tsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/CardSection.test.tsx
index fd45c9e319..837857df81 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/CardSection.test.tsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/CardSection.test.tsx
@@ -4,19 +4,31 @@ import CardSection from './CardSection';
describe('CardSection', () => {
beforeEach(() => initializeMocks());
test('renders children when open', () => {
- render(Section Text );
+ render(
+
+ Section Text
+ ,
+ );
expect(screen.getByText('Section Text')).toBeInTheDocument();
expect(screen.queryByText('summary')).not.toBeInTheDocument();
});
test('renders summary when closed', () => {
- render(Section Text );
+ render(
+
+ Section Text
+ ,
+ );
expect(screen.queryByText('Section Text')).not.toBeInTheDocument();
expect(screen.getByText('summary')).toBeInTheDocument();
});
test('renders nothing when closed and not summary', () => {
- const { container } = render(Not showing text );
+ const { container } = render(
+
+ Not showing text
+ ,
+ );
expect(screen.queryByText('Not showing text')).not.toBeInTheDocument();
expect(container.textContent).toBe('');
});
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/SettingsOption.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/SettingsOption.jsx
index 929bedb245..7375003001 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/SettingsOption.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/SettingsOption.jsx
@@ -12,7 +12,13 @@ import { showFullCard } from './hooks';
import CardSection from './CardSection';
const SettingsOption = ({
- title, className, extraSections, children, summary, hasExpandableTextArea, ...passThroughProps
+ title,
+ className,
+ extraSections,
+ children,
+ summary,
+ hasExpandableTextArea,
+ ...passThroughProps
}) => {
const { isCardCollapsibleOpen, toggleCardCollapse } = showFullCard(hasExpandableTextArea);
@@ -34,14 +40,23 @@ const SettingsOption = ({
-
+
{children}
{extraSections.map((section, index) => (
<>
{isCardCollapsibleOpen && }
{/* eslint-disable-next-line react/no-array-index-key */}
-
+
{section.children}
>
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/SettingsOption.test.tsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/SettingsOption.test.tsx
index 8aa5c1fba8..0f81cf7c14 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/SettingsOption.test.tsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/SettingsOption.test.tsx
@@ -1,6 +1,8 @@
import React from 'react';
import {
- render, screen, initializeMocks,
+ render,
+ screen,
+ initializeMocks,
} from '@src/testUtils';
import SettingsOption from './SettingsOption';
@@ -34,7 +36,7 @@ describe('SettingsOption', () => {
});
test('renders sections when expanded', () => {
- const children = (First Section );
+ const children = First Section ;
const sections = [{ children: Second Section }, { children: Third Section }];
render({children} );
expect(screen.getByText('First Section')).toBeInTheDocument();
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.js
index 04ed2ccf29..f5e03aaa82 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.js
@@ -1,7 +1,11 @@
import { useState, useEffect } from 'react';
import {
- includes, isEmpty, isFinite, isNaN, isNil,
+ includes,
+ isEmpty,
+ isFinite,
+ isNaN,
+ isNil,
} from 'lodash';
import {
ProblemTypeKeys,
@@ -62,7 +66,7 @@ export const hintsCardHooks = (hints, updateSettings) => {
if (hintsNumber === 0) {
setSummary({ message: messages.noHintSummary, values: {} });
} else {
- setSummary({ message: messages.hintSummary, values: { hint: hints[0].value, count: (hintsNumber - 1) } });
+ setSummary({ message: messages.hintSummary, values: { hint: hints[0].value, count: hintsNumber - 1 } });
}
}, [hints]);
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.test.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.test.js
index beba825ed6..9709eeacfa 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.test.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.test.js
@@ -12,7 +12,7 @@ jest.mock('react', () => {
return {
updateState,
useEffect: jest.fn(),
- useState: jest.fn(val => ([{ state: val }, (newVal) => updateState({ val, newVal })])),
+ useState: jest.fn(val => [{ state: val }, (newVal) => updateState({ val, newVal })]),
};
});
@@ -95,7 +95,7 @@ describe('Problem settings hooks', () => {
expect(state.setState[state.keys.summary])
.toHaveBeenCalledWith({
message: messages.hintSummary,
- values: { hint: hints[0].value, count: (hints.length - 1) },
+ values: { hint: hints[0].value, count: hints.length - 1 },
});
});
test('test handleAdd triggers updateSettings', () => {
@@ -339,9 +339,21 @@ describe('Problem settings hooks', () => {
output = hooks.typeRowHooks(typeRowProps);
output.onClick();
expect(typeRowProps.setBlockTitle).toHaveBeenCalledWith(ProblemTypes[ProblemTypeKeys.DROPDOWN].title);
- expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(1, { ...typeRowProps.answers[0], correct: false, title: 'testA' });
- expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(2, { ...typeRowProps.answers[1], correct: false, title: 'testB' });
- expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(3, { ...typeRowProps.answers[2], correct: false, title: 'testC' });
+ expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(1, {
+ ...typeRowProps.answers[0],
+ correct: false,
+ title: 'testA',
+ });
+ expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(2, {
+ ...typeRowProps.answers[1],
+ correct: false,
+ title: 'testB',
+ });
+ expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(3, {
+ ...typeRowProps.answers[2],
+ correct: false,
+ title: 'testC',
+ });
expect(typeRowProps.updateField).toHaveBeenCalledWith({ problemType: ProblemTypeKeys.DROPDOWN });
});
@@ -358,9 +370,18 @@ describe('Problem settings hooks', () => {
output = hooks.typeRowHooks(oneAnswerTypeRowProps);
output.onClick();
expect(typeRowProps.setBlockTitle).toHaveBeenCalledWith(ProblemTypes[ProblemTypeKeys.DROPDOWN].title);
- expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(1, { ...oneAnswerTypeRowProps.answers[0], title: 'testA' });
- expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(2, { ...oneAnswerTypeRowProps.answers[1], title: 'testB' });
- expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(3, { ...oneAnswerTypeRowProps.answers[2], title: 'testC' });
+ expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(1, {
+ ...oneAnswerTypeRowProps.answers[0],
+ title: 'testA',
+ });
+ expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(2, {
+ ...oneAnswerTypeRowProps.answers[1],
+ title: 'testB',
+ });
+ expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(3, {
+ ...oneAnswerTypeRowProps.answers[2],
+ title: 'testC',
+ });
expect(typeRowProps.updateField).toHaveBeenCalledWith({ problemType: ProblemTypeKeys.DROPDOWN });
});
test('test onClick Multi-select to Numeric', () => {
@@ -370,9 +391,21 @@ describe('Problem settings hooks', () => {
});
output.onClick();
expect(typeRowProps.setBlockTitle).toHaveBeenCalledWith(ProblemTypes[ProblemTypeKeys.NUMERIC].title);
- expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(1, { ...typeRowProps.answers[0], correct: true, title: 'testA' });
- expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(2, { ...typeRowProps.answers[1], correct: true, title: 'testB' });
- expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(3, { ...typeRowProps.answers[2], correct: true, title: 'testC' });
+ expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(1, {
+ ...typeRowProps.answers[0],
+ correct: true,
+ title: 'testA',
+ });
+ expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(2, {
+ ...typeRowProps.answers[1],
+ correct: true,
+ title: 'testB',
+ });
+ expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(3, {
+ ...typeRowProps.answers[2],
+ correct: true,
+ title: 'testC',
+ });
expect(typeRowProps.updateField).toHaveBeenCalledWith({ problemType: ProblemTypeKeys.NUMERIC });
});
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.jsx
index 2e917acad7..ce99fa0d00 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.jsx
@@ -3,7 +3,8 @@ import PropTypes from 'prop-types';
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import { connect, useSelector } from 'react-redux';
import {
- Button, Collapsible,
+ Button,
+ Collapsible,
} from '@openedx/paragon';
import { useEditorContext } from '@src/editors/EditorContext';
import { selectors, actions } from '@src/editors/data/redux';
@@ -51,16 +52,17 @@ const SettingsWidget = ({
const feedbackCard = () => {
if ([ProblemTypeKeys.MULTISELECT].includes(problemType)) {
return (
-
+
+
);
}
// eslint-disable-next-line react/jsx-no-useless-fragment
- return (<>>);
+ return <>>;
};
return (
@@ -77,7 +79,7 @@ const SettingsWidget = ({
/>
{ProblemTypeKeys.NUMERIC === problemType
- && (
+ && (
- )}
+ )}
{!isLibrary && (
)}
- {
- problemType === ProblemTypeKeys.ADVANCED && (
+ {problemType === ProblemTypeKeys.ADVANCED && (
- )
- }
+ )}
{!isLibrary && (
@@ -162,12 +162,12 @@ const SettingsWidget = ({
- { (showMarkdownEditorButton && !isMarkdownEditorEnabled) // Only show button if not already in markdown editor
- && (
-
-
-
- )}
+ {(showMarkdownEditorButton && !isMarkdownEditorEnabled) // Only show button if not already in markdown editor
+ && (
+
+
+
+ )}
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.test.tsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.test.tsx
index f8184ff4de..6e8a83597d 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.test.tsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.test.tsx
@@ -48,7 +48,6 @@ describe('SettingsWidget', () => {
correctAnswerCount: 0,
groupFeedbackList: [],
showMarkdownEditorButton: false,
-
};
const editorRef = { current: null };
@@ -56,12 +55,13 @@ describe('SettingsWidget', () => {
const renderSettingsWidget = (
overrideProps = {},
options = {},
- ) => editorRender(
-
-
- ,
- options,
- );
+ ) =>
+ editorRender(
+
+
+ ,
+ options,
+ );
beforeEach(() => {
initializeMocks();
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/messages.ts b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/messages.ts
index a854ac67fc..e167ee9f82 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/messages.ts
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
settingsWidgetTitle: {
id: 'authoring.problemeditor.settings.settingsWidgetTitle',
defaultMessage: 'Settings',
@@ -64,7 +63,7 @@ const messages = defineMessages({
},
resetSettingText: {
id: 'authoring.problemeditor.settings.reset.text',
- defaultMessage: "Determines whether a 'Reset' button is shown so the user may reset their answer, generally for use in practice or formative assessments.",
+ defaultMessage: 'Determines whether a \'Reset\' button is shown so the user may reset their answer, generally for use in practice or formative assessments.',
description: 'Reset settings card text',
},
scoringSettingsTitle: {
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/hooks.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/hooks.js
index c8aba6a229..282a519030 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/hooks.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/hooks.js
@@ -14,7 +14,9 @@ export const state = {
export const generalFeedbackHooks = (generalFeedback, updateSettings) => {
const [summary, setSummary] = module.state.summary({
- message: messages.noGeneralFeedbackSummary, values: {}, intl: true,
+ message: messages.noGeneralFeedbackSummary,
+ values: {},
+ intl: true,
});
// eslint-disable-next-line react-hooks/rules-of-hooks
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/hooks.test.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/hooks.test.js
index 5d5c98d528..1873c90e3d 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/hooks.test.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/hooks.test.js
@@ -8,7 +8,7 @@ jest.mock('react', () => {
return {
updateState,
useEffect: jest.fn(),
- useState: jest.fn(val => ([{ state: val }, (newVal) => updateState({ val, newVal })])),
+ useState: jest.fn(val => [{ state: val }, (newVal) => updateState({ val, newVal })]),
};
});
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/index.test.tsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/index.test.tsx
index 9e87791a23..cdab94e166 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/index.test.tsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/index.test.tsx
@@ -1,6 +1,9 @@
import React from 'react';
import {
- render, screen, initializeMocks, fireEvent,
+ render,
+ screen,
+ initializeMocks,
+ fireEvent,
} from '@src/testUtils';
import { GeneralFeedbackCard } from './index';
import * as hooks from './hooks';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/messages.ts b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/messages.ts
index acec226278..c07e47cf9d 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/messages.ts
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
generalFeebackSettingTitle: {
id: 'authoring.problemeditor.settings.generalFeebackSettingTitle',
defaultMessage: 'General Feedback',
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/GroupFeedbackRow.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/GroupFeedbackRow.jsx
index 3086f0ff16..589832c668 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/GroupFeedbackRow.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/GroupFeedbackRow.jsx
@@ -1,6 +1,10 @@
import React from 'react';
import {
- ActionRow, Form, Icon, IconButton, Row,
+ ActionRow,
+ Form,
+ Icon,
+ IconButton,
+ Row,
} from '@openedx/paragon';
import { DeleteOutline } from '@openedx/paragon/icons';
import PropTypes from 'prop-types';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/hooks.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/hooks.js
index 4dbe89c00c..bfceb4df5d 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/hooks.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/hooks.js
@@ -96,6 +96,8 @@ export const groupFeedbackRowHooks = ({ id, groupFeedbacks, updateSettings }) =>
};
return {
- handleAnswersSelectedChange, handleFeedbackChange, handleDelete,
+ handleAnswersSelectedChange,
+ handleFeedbackChange,
+ handleDelete,
};
};
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/hooks.test.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/hooks.test.js
index 14adde6d3b..9e094f5850 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/hooks.test.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/hooks.test.js
@@ -8,7 +8,7 @@ jest.mock('react', () => {
return {
updateState,
useEffect: jest.fn(),
- useState: jest.fn(val => ([{ state: val }, (newVal) => updateState({ val, newVal })])),
+ useState: jest.fn(val => [{ state: val }, (newVal) => updateState({ val, newVal })]),
};
});
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/index.test.tsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/index.test.tsx
index c8ff74aa7b..3f6c13e65e 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/index.test.tsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/index.test.tsx
@@ -1,6 +1,9 @@
import React from 'react';
import {
- render, screen, initializeMocks, fireEvent,
+ render,
+ screen,
+ initializeMocks,
+ fireEvent,
} from '@src/testUtils';
import GroupFeedbackCard from './index';
import * as hooks from './hooks';
@@ -14,10 +17,16 @@ jest.mock('./hooks', () => ({
describe('HintsCard', () => {
const answers = ['A', 'B', 'C'];
const groupFeedback1 = {
- id: 1, value: 'groupFeedback1', answers: ['A', 'C'], feedback: 'sOmE FeEDBACK',
+ id: 1,
+ value: 'groupFeedback1',
+ answers: ['A', 'C'],
+ feedback: 'sOmE FeEDBACK',
};
const groupFeedback2 = {
- id: 2, value: '', answers: ['A'], feedback: 'sOmE FeEDBACK oTher FeEdback',
+ id: 2,
+ value: '',
+ answers: ['A'],
+ feedback: 'sOmE FeEDBACK oTher FeEdback',
};
const groupFeedbacks0 = [];
const groupFeedbacks1 = [groupFeedback1];
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/messages.ts b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/messages.ts
index de4a5c6feb..98017de6e7 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/messages.ts
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
noGroupFeedbackSummary: {
id: 'authoring.problemeditor.settings.GroupFeedbackSummary.nonMessage',
defaultMessage: 'None',
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintRow.test.tsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintRow.test.tsx
index b16fcfd879..7a2ca303e7 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintRow.test.tsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintRow.test.tsx
@@ -1,6 +1,9 @@
import React from 'react';
import {
- render, screen, initializeMocks, fireEvent,
+ render,
+ screen,
+ initializeMocks,
+ fireEvent,
} from '@src/testUtils';
import HintRow from './HintRow';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/hooks.test.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/hooks.test.js
index dc4cf2cb1c..b1049ddb2b 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/hooks.test.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/hooks.test.js
@@ -8,7 +8,7 @@ jest.mock('react', () => {
return {
updateState,
useEffect: jest.fn(),
- useState: jest.fn(val => ([{ state: val }, (newVal) => updateState({ val, newVal })])),
+ useState: jest.fn(val => [{ state: val }, (newVal) => updateState({ val, newVal })]),
};
});
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/index.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/index.jsx
index e6d602d93a..3e826387f9 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/index.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/index.jsx
@@ -34,19 +34,16 @@ export const RandomizationCard = ({
value={curretRandomization}
onChange={handleChange}
>
- {
- Object.values(RandomizationTypesKeys).map((randomizationType) => (
-
- {intl.formatMessage(RandomizationTypes[randomizationType])}
-
- ))
- }
+ {Object.values(RandomizationTypesKeys).map((randomizationType) => (
+
+ {intl.formatMessage(RandomizationTypes[randomizationType])}
+
+ ))}
-
);
};
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/index.test.tsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/index.test.tsx
index e5b0d4f47a..47da314e1f 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/index.test.tsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/index.test.tsx
@@ -1,6 +1,9 @@
import React from 'react';
import {
- render, screen, initializeMocks, fireEvent,
+ render,
+ screen,
+ initializeMocks,
+ fireEvent,
} from '@src/testUtils';
import { RandomizationCard } from './index';
import * as hooks from './hooks';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/messages.ts b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/messages.ts
index 3f622bd327..d0027fde50 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/messages.ts
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
randomizationSettingTitle: {
id: 'authoring.problemeditor.settings.randomization.SettingTitle',
defaultMessage: 'Randomization',
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ResetCard.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ResetCard.jsx
index cef04feeda..642758f72d 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ResetCard.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ResetCard.jsx
@@ -16,13 +16,16 @@ const ResetCard = ({
const intl = useIntl();
const isLibrary = useSelector(selectors.app.isLibrary);
const { setResetTrue, setResetFalse } = resetCardHooks(updateSettings);
- const advancedSettingsLink = `${useSelector(selectors.app.studioEndpointUrl)}/settings/advanced/${useSelector(selectors.app.learningContextId)}#show_reset_button`;
+ const advancedSettingsLink = `${useSelector(selectors.app.studioEndpointUrl)}/settings/advanced/${
+ useSelector(selectors.app.learningContextId)
+ }#show_reset_button`;
const currentResetButton = showResetButton !== null ? showResetButton : defaultValue;
return (
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ResetCard.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ResetCard.test.jsx
index 09886bef18..509a73ea51 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ResetCard.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ResetCard.test.jsx
@@ -1,6 +1,9 @@
import React from 'react';
import {
- render, screen, initializeMocks, fireEvent,
+ render,
+ screen,
+ initializeMocks,
+ fireEvent,
} from '@src/testUtils';
import * as reactredux from 'react-redux';
import { formatMessage } from '../../../../../../testUtils';
@@ -8,7 +11,8 @@ import ResetCard from './ResetCard';
import * as hooks from '../hooks';
describe('ResetCard', () => {
- const resetText = "Determines whether a 'Reset' button is shown so the user may reset their answer, generally for use in practice or formative assessments.";
+ const resetText =
+ 'Determines whether a \'Reset\' button is shown so the user may reset their answer, generally for use in practice or formative assessments.';
const props = {
showResetButton: false,
updateSettings: jest.fn().mockName('args.updateSettings'),
@@ -53,7 +57,8 @@ describe('ResetCard', () => {
expect(resetOption).toBeInTheDocument();
fireEvent.click(resetOption);
expect(screen.getByText(resetText)).toBeInTheDocument();
- expect(screen.getByRole('link', { name: 'Set a default value in advanced settings in a new tab' })).toBeInTheDocument();
+ expect(screen.getByRole('link', { name: 'Set a default value in advanced settings in a new tab' }))
+ .toBeInTheDocument();
});
test('do not render link when isLibrary is true', () => {
@@ -63,7 +68,8 @@ describe('ResetCard', () => {
expect(resetOption).toBeInTheDocument();
fireEvent.click(resetOption);
expect(screen.getByText(resetText)).toBeInTheDocument();
- expect(screen.queryByRole('link', { name: 'Set a default value in advanced settings in a new tab' })).not.toBeInTheDocument();
+ expect(screen.queryByRole('link', { name: 'Set a default value in advanced settings in a new tab' })).not
+ .toBeInTheDocument();
});
});
});
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ScoringCard.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ScoringCard.jsx
index f93880e5f4..a5f1acb272 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ScoringCard.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ScoringCard.jsx
@@ -123,7 +123,10 @@ const ScoringCard = ({
{!isLibrary && (
-
+
)}
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ScoringCard.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ScoringCard.test.jsx
index 6e05f50cca..f123f62420 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ScoringCard.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ScoringCard.test.jsx
@@ -1,6 +1,9 @@
import React from 'react';
import {
- render, screen, initializeMocks, fireEvent,
+ render,
+ screen,
+ initializeMocks,
+ fireEvent,
} from '@src/testUtils';
import ScoringCard from './ScoringCard';
import { selectors } from '../../../../../../data/redux';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ShowAnswerCard.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ShowAnswerCard.jsx
index 414233d53f..65ed956a56 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ShowAnswerCard.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ShowAnswerCard.jsx
@@ -36,7 +36,10 @@ const ShowAnswerCard = ({
{!isLibrary && (
-
+
@@ -50,7 +53,10 @@ const ShowAnswerCard = ({
{Object.values(ShowAnswerTypesKeys).map((answerType) => {
let optionDisplayName = ShowAnswerTypes[answerType];
if (answerType === defaultValue) {
- optionDisplayName = { ...optionDisplayName, defaultMessage: `${optionDisplayName.defaultMessage} (Default)` };
+ optionDisplayName = {
+ ...optionDisplayName,
+ defaultMessage: `${optionDisplayName.defaultMessage} (Default)`,
+ };
}
return (
{showAttempts
&& (
-
-
-
+
+
+
)}
>
);
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ShowAnswerCard.test.tsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ShowAnswerCard.test.tsx
index 84ba1b371e..4ef9471dfb 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ShowAnswerCard.test.tsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ShowAnswerCard.test.tsx
@@ -1,6 +1,8 @@
import React from 'react';
import {
- render, screen, initializeMocks,
+ render,
+ screen,
+ initializeMocks,
} from '@src/testUtils';
import { selectors } from '../../../../../../data/redux';
import { ShowAnswerCardInternal as ShowAnswerCard, mapStateToProps, mapDispatchToProps } from './ShowAnswerCard';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/SwitchEditorCard.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/SwitchEditorCard.jsx
index b047b15062..df3a9bcac3 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/SwitchEditorCard.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/SwitchEditorCard.jsx
@@ -24,20 +24,23 @@ const SwitchEditorCard = ({
{ setConfirmOpen(false); }}
+ close={() => {
+ setConfirmOpen(false);
+ }}
title={ }
- confirmAction={(
+ confirmAction={
handleConfirmEditorSwitch({
- switchEditor: () => dispatch(thunkActions.problem.switchEditor(editorType, editorRef)),
- setConfirmOpen,
- })}
+ onClick={() =>
+ handleConfirmEditorSwitch({
+ switchEditor: () => dispatch(thunkActions.problem.switchEditor(editorType, editorRef)),
+ setConfirmOpen,
+ })}
variant="primary"
>
- )}
+ }
size="md"
>
@@ -46,7 +49,9 @@ const SwitchEditorCard = ({
className="my-3 ml-2 py-0"
variant="link"
size="sm"
- onClick={() => { setConfirmOpen(true); }}
+ onClick={() => {
+ setConfirmOpen(true);
+ }}
>
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/SwitchEditorCard.test.tsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/SwitchEditorCard.test.tsx
index dcd28379c0..43c88aa025 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/SwitchEditorCard.test.tsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/SwitchEditorCard.test.tsx
@@ -16,11 +16,12 @@ describe('SwitchEditorCard - markdown', () => {
};
const editorRef = { current: null };
- const renderSwitchEditorCard = (overrideProps = {}) => editorRender(
-
-
- ,
- );
+ const renderSwitchEditorCard = (overrideProps = {}) =>
+ editorRender(
+
+
+ ,
+ );
beforeEach(() => {
initializeMocks();
@@ -63,7 +64,7 @@ describe('SwitchEditorCard - markdown', () => {
test('renders nothing for advanced problemType', () => {
const { container } = renderSwitchEditorCard({ problemType: 'advanced' });
- const reduxWrapper = (container.firstChild as HTMLElement | null);
+ const reduxWrapper = container.firstChild as HTMLElement | null;
expect(reduxWrapper?.innerHTML).toBe('');
});
});
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TimerCard.test.tsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TimerCard.test.tsx
index e3bf7c056c..3c4091c005 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TimerCard.test.tsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TimerCard.test.tsx
@@ -1,6 +1,8 @@
import React from 'react';
import {
- render, screen, initializeMocks,
+ render,
+ screen,
+ initializeMocks,
} from '@src/testUtils';
import TimerCard from './TimerCard';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/index.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/index.jsx
index ab587a3aba..134f98f6ca 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/index.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/index.jsx
@@ -56,7 +56,9 @@ export const ToleranceCard = ({
const isAnswerRange = isAnswerRangeSet({ answers });
const hasMultipleCorrectAnswers = correctAnswerCount > 1;
let summary = getSummary({ tolerance, intl });
- useEffect(() => { summary = getSummary({ tolerance, intl }); }, [tolerance]);
+ useEffect(() => {
+ summary = getSummary({ tolerance, intl });
+ }, [tolerance]);
useEffect(() => {
if (hasMultipleCorrectAnswers) {
updateSettings({ tolerance: { value: null, type: ToleranceTypes.none.type } });
@@ -69,24 +71,18 @@ export const ToleranceCard = ({
summary={summary}
none={tolerance.type === ToleranceTypes.none.type}
>
- { isAnswerRange
- && (
-
-
-
- )}
- {
- hasMultipleCorrectAnswers
+ {isAnswerRange
+ && (
+
+
+
+ )}
+ {hasMultipleCorrectAnswers
&& (
-
+
- )
- }
+ )}
@@ -108,20 +104,19 @@ export const ToleranceCard = ({
))}
- { tolerance?.type !== ToleranceTypes.none.type && (!isAnswerRange || !hasMultipleCorrectAnswers)
+ {tolerance?.type !== ToleranceTypes.none.type && (!isAnswerRange || !hasMultipleCorrectAnswers)
&& (
-
+
)}
-
);
};
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/index.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/index.test.jsx
index c9e9212703..d490588c2e 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/index.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/index.test.jsx
@@ -1,5 +1,7 @@
import {
- render, screen, fireEvent,
+ render,
+ screen,
+ fireEvent,
} from '@testing-library/react';
import React from 'react';
import messages from './messages';
@@ -10,32 +12,38 @@ import { formatMessage } from '../../../../../../../testUtils';
jest.mock('@edx/frontend-platform/i18n', () => ({
__esmodule: true,
...jest.requireActual('@edx/frontend-platform/i18n'),
- FormattedMessage: jest.fn(({ defaultMessage }) => (
- { defaultMessage }
- )),
+ FormattedMessage: jest.fn(({ defaultMessage }) => {defaultMessage}
),
useIntl: () => ({
formatMessage: (message) => message.defaultMessage,
}),
}));
// eslint-disable-next-line react/prop-types
-jest.mock('../../SettingsOption', () => function mockSettingsOption({ children, summary }) {
- return {summary}{children}
;
-});
+jest.mock('../../SettingsOption', () =>
+ function mockSettingsOption({ children, summary }) {
+ return {summary}{children}
;
+ });
jest.mock('@openedx/paragon', () => ({
- Alert: jest.fn(({ children }) => (
- {children}
)),
+ Alert: jest.fn(({ children }) => {children}
),
Form: {
Control: jest.fn(({
- children, onChange, as, value, disabled,
+ children,
+ onChange,
+ as,
+ value,
+ disabled,
}) => {
if (as === 'select') {
- return ({children} );
+ return (
+
+ {children}
+
+ );
}
- return ( );
+ return ;
}),
- Group: jest.fn(({ children }) => ({children}
)),
+ Group: jest.fn(({ children }) => {children}
),
},
}));
@@ -61,8 +69,7 @@ describe('ToleranceCard', () => {
title: 'An Answer',
isAnswerRange: false,
unselectedFeedback: '',
- },
- ],
+ }],
updateSettings: jest.fn(),
intl: {
formatMessage,
@@ -97,18 +104,19 @@ describe('ToleranceCard', () => {
title: 'An Answer',
isAnswerRange: true,
unselectedFeedback: '',
- },
- ],
+ }],
updateSettings: jest.fn(),
intl: {
formatMessage,
},
};
- render( );
+ render(
+ ,
+ );
const NumberText = screen.getByText(messages.toleranceAnswerRangeWarning.defaultMessage);
expect(NumberText).toBeDefined();
expect(screen.getByTestId('select').getAttributeNames().includes('disabled')).toBeTruthy();
@@ -122,27 +130,27 @@ describe('ToleranceCard', () => {
title: 'An Answer A',
isAnswerRange: false,
unselectedFeedback: '',
- },
- {
+ }, {
id: 'B',
correct: true,
selectedFeedback: '',
title: 'An Answer B',
isAnswerRange: false,
unselectedFeedback: '',
- },
- ],
+ }],
updateSettings: jest.fn(),
intl: {
formatMessage,
},
};
- render( );
+ render(
+ ,
+ );
const warningMessage = screen.getByText(messages.toleranceMultipleAnswersWarning.defaultMessage);
expect(warningMessage).toBeDefined();
expect(screen.getByTestId('select').getAttributeNames().includes('disabled')).toBeTruthy();
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/messages.ts b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/messages.ts
index 0f929473b1..3ac330ddcb 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/messages.ts
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/messages.ts
@@ -35,20 +35,17 @@ const messages = defineMessages({
id: 'problemEditor.settings.tolerance.type.percent',
defaultMessage: 'Percentage',
description: 'A possible value type for a tolerance',
-
},
typesNumber: {
id: 'problemEditor.settings.tolerance.type.number',
defaultMessage: 'Number',
description: 'A possible value type for a tolerance',
-
},
typesNone: {
id: 'problemEditor.settings.tolerance.type.none',
defaultMessage: 'None',
description: 'A possible value type for a tolerance',
},
-
});
export default messages;
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeRow.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeRow.jsx
index f3b29f6aff..819e5d3033 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeRow.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeRow.jsx
@@ -38,7 +38,9 @@ const TypeRow = ({
<>
{label}
-
+
+
+
>
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeRow.test.tsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeRow.test.tsx
index 32e887bbd6..50759b91bf 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeRow.test.tsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeRow.test.tsx
@@ -1,6 +1,9 @@
import React from 'react';
import {
- render, screen, fireEvent, initializeMocks,
+ render,
+ screen,
+ fireEvent,
+ initializeMocks,
} from '../../../../../../../testUtils';
import TypeRow from './TypeRow';
@@ -12,10 +15,18 @@ jest.mock('../hooks', () => ({
const defaultProps = {
answers: [
{
- correct: true, id: '1', selectedFeedback: 'Good', title: 'A', unselectedFeedback: 'Try again',
+ correct: true,
+ id: '1',
+ selectedFeedback: 'Good',
+ title: 'A',
+ unselectedFeedback: 'Try again',
},
{
- correct: false, id: '2', selectedFeedback: 'No', title: 'B', unselectedFeedback: 'Nope',
+ correct: false,
+ id: '2',
+ selectedFeedback: 'No',
+ title: 'B',
+ unselectedFeedback: 'Nope',
},
],
blockTitle: 'Block Title',
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.js b/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.js
index 31134b0666..e8e47c5445 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.js
@@ -71,7 +71,8 @@ export const parseState = ({
isMarkdownEditorEnabled,
ref,
lmsEndpointUrl,
-}) => () => {
+}) =>
+() => {
// Constructs the save payload by parsing the current state of the problem editor.
// If the Markdown editor is enabled, the editor content is converted to OLX using convertMarkdownToXml.
// For advanced problems, raw editor content is used as OLX; for visual ones, it's built via ReactStateOLXParser.
@@ -149,7 +150,10 @@ export const checkForNoAnswers = ({ openSaveWarningModal, problem }) => {
};
export const checkForSettingDiscrepancy = ({
- problem, ref, openSaveWarningModal, isMarkdownEditorEnabled,
+ problem,
+ ref,
+ openSaveWarningModal,
+ isMarkdownEditorEnabled,
}) => {
const contentString = ref?.current?.state.doc.toString();
const rawOLX = isMarkdownEditorEnabled ? convertMarkdownToXml(contentString) : contentString;
@@ -184,12 +188,14 @@ export const getContent = ({
problem,
openSaveWarningModal,
});
- const hasMismatchedSettings = isAdvancedProblemType || isMarkdownEditorEnabled ? checkForSettingDiscrepancy({
- ref: editorRef,
- problem,
- openSaveWarningModal,
- isMarkdownEditorEnabled,
- }) : false;
+ const hasMismatchedSettings = isAdvancedProblemType || isMarkdownEditorEnabled ?
+ checkForSettingDiscrepancy({
+ ref: editorRef,
+ problem,
+ openSaveWarningModal,
+ isMarkdownEditorEnabled,
+ }) :
+ false;
if (!hasNoAnswers && !hasMismatchedSettings) {
const data = parseState({
isAdvanced: isAdvancedProblemType,
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.test.js b/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.test.js
index a94bdca92f..d21b71a24d 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.test.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.test.js
@@ -219,7 +219,10 @@ describe('EditProblemView hooks parseState', () => {
jest.clearAllMocks();
});
it('should call openSaveWarningModal for single select problem with empty title', () => {
- window.tinymce.editors = { 'answer-A': { getContent: () => '' }, 'answer-B': { getContent: () => 'sOmevALUe' } };
+ window.tinymce.editors = {
+ 'answer-A': { getContent: () => '' },
+ 'answer-B': { getContent: () => 'sOmevALUe' },
+ };
const expected = hooks.checkForNoAnswers({
openSaveWarningModal,
problem: {
@@ -313,7 +316,11 @@ describe('EditProblemView hooks parseState', () => {
const openSaveWarningModal = jest.fn();
it('default visual save and returns parseState data', () => {
- const problem = { ...problemState, problemType: ProblemTypeKeys.NUMERIC, answers: [{ id: 'A', title: 'problem', correct: true }] };
+ const problem = {
+ ...problemState,
+ problemType: ProblemTypeKeys.NUMERIC,
+ answers: [{ id: 'A', title: 'problem', correct: true }],
+ };
const content = hooks.getContent({
isAdvancedProblemType: false,
isMarkdownEditorEnabled: false,
@@ -379,7 +386,11 @@ describe('EditProblemView hooks parseState', () => {
});
});
it('should return null', () => {
- const problem = { ...problemState, problemType: ProblemTypeKeys.NUMERIC, answers: [{ id: 'A', title: '', correct: true }] };
+ const problem = {
+ ...problemState,
+ problemType: ProblemTypeKeys.NUMERIC,
+ answers: [{ id: 'A', title: '', correct: true }],
+ };
const content = hooks.getContent({
isAdvancedProblemType: false,
problemState: problem,
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/index.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/index.jsx
index 0da11922fc..855fe9703e 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/index.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/index.jsx
@@ -19,7 +19,10 @@ import RawEditor from '../../../../sharedComponents/RawEditor';
import { ProblemTypeKeys } from '../../../../data/constants/problem';
import {
- checkIfEditorsDirty, parseState, saveWarningModalToggle, getContent,
+ checkIfEditorsDirty,
+ parseState,
+ saveWarningModalToggle,
+ getContent,
} from './hooks';
import './index.scss';
@@ -61,14 +64,15 @@ const EditProblemView = ({ returnFunction }) => {
return (
getContent({
- problemState,
- openSaveWarningModal,
- isAdvancedProblemType,
- isMarkdownEditorEnabled,
- editorRef,
- lmsEndpointUrl,
- })}
+ getContent={() =>
+ getContent({
+ problemState,
+ openSaveWarningModal,
+ isAdvancedProblemType,
+ isMarkdownEditorEnabled,
+ editorRef,
+ lmsEndpointUrl,
+ })}
isDirty={checkIfDirty}
returnFunction={returnFunction}
>
@@ -78,34 +82,33 @@ const EditProblemView = ({ returnFunction }) => {
: intl.formatMessage(messages.noAnswerTitle)}
isOpen={isSaveWarningModalOpen}
onClose={closeSaveWarningModal}
- footerNode={(
+ footerNode={
saveBlock({
- content: parseState({
- problem: problemState,
- isAdvanced: isAdvancedProblemType,
- isMarkdown: isMarkdownEditorEnabled,
- ref: editorRef,
- lmsEndpointUrl,
- })(),
- returnFunction,
- destination: returnUrl,
- dispatch,
- analytics,
- })}
+ onClick={() =>
+ saveBlock({
+ content: parseState({
+ problem: problemState,
+ isAdvanced: isAdvancedProblemType,
+ isMarkdown: isMarkdownEditorEnabled,
+ ref: editorRef,
+ lmsEndpointUrl,
+ })(),
+ returnFunction,
+ destination: returnUrl,
+ dispatch,
+ analytics,
+ })}
>
- )}
+ }
>
- {isAdvancedProblemType ? (
-
- ) : (
+ {isAdvancedProblemType ? : (
<>
@@ -118,21 +121,23 @@ const EditProblemView = ({ returnFunction }) => {
- {isAdvancedProblemType || isMarkdownEditorEnabled ? (
-
-
-
- ) : (
-
-
-
-
-
- )}
+ {isAdvancedProblemType || isMarkdownEditorEnabled ?
+ (
+
+
+
+ ) :
+ (
+
+
+
+
+
+ )}
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/index.test.tsx b/src/editors/containers/ProblemEditor/components/EditProblemView/index.test.tsx
index 3fd279b66e..9ad079e183 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/index.test.tsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/index.test.tsx
@@ -8,24 +8,30 @@ import EditProblemView from './index';
const { saveBlock } = require('../../../../hooks');
const { saveWarningModalToggle } = require('./hooks');
-jest.mock('./AnswerWidget', () => function mockAnswerWidget() {
- return AnswerWidget
;
-});
-jest.mock('./SettingsWidget', () => function mockSettingsWidget() {
- return SettingsWidget
;
-});
-jest.mock('./QuestionWidget', () => function mmockQuestionWidget() {
- return QuestionWidget
;
-});
-jest.mock('../../../EditorContainer', () => function mockEditorContainer({ children }) {
- return ;
-});
-jest.mock('../../../../sharedComponents/RawEditor', () => function mockRawEditor({ lang, content }) {
- return {lang}:{content}
;
-});
-jest.mock('./ExplanationWidget', () => function mockExplanationWidget() {
- return ExplanationWidget
;
-});
+jest.mock('./AnswerWidget', () =>
+ function mockAnswerWidget() {
+ return AnswerWidget
;
+ });
+jest.mock('./SettingsWidget', () =>
+ function mockSettingsWidget() {
+ return SettingsWidget
;
+ });
+jest.mock('./QuestionWidget', () =>
+ function mmockQuestionWidget() {
+ return QuestionWidget
;
+ });
+jest.mock('../../../EditorContainer', () =>
+ function mockEditorContainer({ children }) {
+ return ;
+ });
+jest.mock('../../../../sharedComponents/RawEditor', () =>
+ function mockRawEditor({ lang, content }) {
+ return {lang}:{content}
;
+ });
+jest.mock('./ExplanationWidget', () =>
+ function mockExplanationWidget() {
+ return ExplanationWidget
;
+ });
jest.mock('../../../../hooks', () => ({
saveBlock: jest.fn(),
}));
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/index.test.tsx b/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/index.test.tsx
index ee99b3a212..d630ea95ae 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/index.test.tsx
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/index.test.tsx
@@ -1,6 +1,8 @@
import React from 'react';
import {
- screen, fireEvent, initializeMocks,
+ screen,
+ fireEvent,
+ initializeMocks,
} from '@src/testUtils';
import { editorRender } from '@src/editors/editorTestRender';
import SelectTypeWrapper from './index';
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/messages.ts b/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/messages.ts
index ba83fa78f6..6b5d9b3f8b 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/messages.ts
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
selectTypeTitle: {
id: 'authoring.problemEditor.selectType.title',
defaultMessage: 'Select problem type',
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/AdvanceTypeSelect.test.tsx b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/AdvanceTypeSelect.test.tsx
index 436968e3ff..03cdb37a5f 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/AdvanceTypeSelect.test.tsx
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/AdvanceTypeSelect.test.tsx
@@ -2,7 +2,10 @@ import React from 'react';
import { ProblemTypeKeys, AdvanceProblems } from '@src/editors/data/constants/problem';
import {
- render, screen, fireEvent, initializeMocks,
+ render,
+ screen,
+ fireEvent,
+ initializeMocks,
} from '../../../../../../testUtils';
import AdvanceTypeSelect from './AdvanceTypeSelect';
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/AdvanceTypeSelect.tsx b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/AdvanceTypeSelect.tsx
index 032767f878..d2ead343b3 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/AdvanceTypeSelect.tsx
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/AdvanceTypeSelect.tsx
@@ -32,7 +32,9 @@ const AdvanceTypeSelect: React.FC = ({
}) => {
const intl = useIntl();
- const handleChange = e => { setSelected(e.target.value); };
+ const handleChange = e => {
+ setSelected(e.target.value);
+ };
return (
@@ -65,13 +67,15 @@ const AdvanceTypeSelect: React.FC = ({
- {intl.formatMessage(messages.supportStatusTooltipMessage, { supportStatus: problemData.status.replace(' ', '_') })}
+ {intl.formatMessage(messages.supportStatusTooltipMessage, {
+ supportStatus: problemData.status.replace(' ', '_'),
+ })}
- )}
+ }
>
{intl.formatMessage(messages.problemSupportStatus, { supportStatus: problemData.status })}
@@ -92,7 +96,9 @@ const AdvanceTypeSelect: React.FC
= ({
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/Preview.jsx b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/Preview.jsx
index 98e9e43165..59734b4cf3 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/Preview.jsx
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/Preview.jsx
@@ -21,7 +21,8 @@ const Preview = ({
return (
- {intl.formatMessage(messages.problemTextInPreviewTitle)}
+ {' '}
+ {intl.formatMessage(messages.problemTextInPreviewTitle)}
{
expect(screen.getByText('Single select problem')).toBeInTheDocument();
// Check that the description is rendered correctly
- expect(screen.getByText('Learners must select the correct answer from a list of possible options.')).toBeInTheDocument();
+ expect(screen.getByText('Learners must select the correct answer from a list of possible options.'))
+ .toBeInTheDocument();
// Check that the image has correct src attribute
const image = screen.getByRole('img');
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/ProblemTypeSelect.test.tsx b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/ProblemTypeSelect.test.tsx
index 76a94bbe05..d6c8dd9fec 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/ProblemTypeSelect.test.tsx
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/ProblemTypeSelect.test.tsx
@@ -2,7 +2,10 @@ import React from 'react';
import { ProblemTypeKeys } from '@src/editors/data/constants/problem';
import {
- render, screen, fireEvent, initializeMocks,
+ render,
+ screen,
+ fireEvent,
+ initializeMocks,
} from '../../../../../../testUtils';
import ProblemTypeSelect from './ProblemTypeSelect';
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/messages.ts b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/messages.ts
index fe7141ddde..8a2163456e 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/messages.ts
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
advanceProblemButtonLabel: {
id: 'authoring.problemEditor.problemSelect.advanceButton.label',
defaultMessage: 'Advanced problem types',
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/hooks.js b/src/editors/containers/ProblemEditor/components/SelectTypeModal/hooks.js
index b239baa682..ed2af66a70 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/hooks.js
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/hooks.js
@@ -1,6 +1,11 @@
import { useEffect } from 'react';
import {
- AdvanceProblemKeys, AdvanceProblems, ProblemTypeKeys, ProblemTypes, getProblemTypes, getAdvanceProblems,
+ AdvanceProblemKeys,
+ AdvanceProblems,
+ ProblemTypeKeys,
+ ProblemTypes,
+ getProblemTypes,
+ getAdvanceProblems,
} from '@src/editors/data/constants/problem';
import { snakeCaseKeys } from '../../../../utils';
import { getDataFromOlx } from '../../../../data/redux/thunkActions/problem';
@@ -11,7 +16,8 @@ export const onSelect = ({
setBlockTitle,
defaultSettings,
formatMessage,
-}) => () => {
+}) =>
+() => {
if (Object.values(AdvanceProblemKeys).includes(selected)) {
updateField({ problemType: ProblemTypeKeys.ADVANCED, rawOLX: AdvanceProblems[selected].template });
if (formatMessage) {
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/index.tsx b/src/editors/containers/ProblemEditor/components/SelectTypeModal/index.tsx
index 701d9c53de..6a30845ca3 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/index.tsx
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/index.tsx
@@ -32,12 +32,14 @@ const SelectTypeModal: React.FC = ({
return (
- {(!isAdvancedProblemType(selected)) ? (
-
-
-
-
- ) : }
+ {(!isAdvancedProblemType(selected)) ?
+ (
+
+
+
+
+ ) :
+ }
);
diff --git a/src/editors/containers/ProblemEditor/data/OLXParser.js b/src/editors/containers/ProblemEditor/data/OLXParser.js
index 68210f7ba7..43817b91d9 100644
--- a/src/editors/containers/ProblemEditor/data/OLXParser.js
+++ b/src/editors/containers/ProblemEditor/data/OLXParser.js
@@ -3,7 +3,11 @@
import { XMLParser, XMLBuilder } from 'fast-xml-parser';
import {
- get, has, keys, isArray, isEmpty,
+ get,
+ has,
+ keys,
+ isArray,
+ isEmpty,
} from 'lodash';
import {
ProblemTypeKeys,
@@ -95,7 +99,8 @@ export const responseKeys = [
* [--5,10]
* []
*/
-export const answerRangeFormatRegex = /^[([]\s*-?(?:\d+(?:\.\d+)?|\d+\/\d+)\s*,\s*-?(?:\d+(?:\.\d+)?|\d+\/\d+)\s*[)\]]$/m;
+export const answerRangeFormatRegex =
+ /^[([]\s*-?(?:\d+(?:\.\d+)?|\d+\/\d+)\s*,\s*-?(?:\d+(?:\.\d+)?|\d+\/\d+)\s*[)\]]$/m;
export const stripNonTextTags = ({ input, tag }) => {
const stripedTags = {};
@@ -250,8 +255,12 @@ export class OLXParser {
);
} else if (isArray(choice)) {
choice.forEach((element, index) => {
- const preservedAnswer = preservedAnswers[index].filter(answer => !Object.keys(answer).includes(`${option}hint`));
- const preservedFeedback = preservedAnswers[index].filter(answer => Object.keys(answer).includes(`${option}hint`));
+ const preservedAnswer = preservedAnswers[index].filter(answer =>
+ !Object.keys(answer).includes(`${option}hint`)
+ );
+ const preservedFeedback = preservedAnswers[index].filter(answer =>
+ Object.keys(answer).includes(`${option}hint`)
+ );
let title = String(element['#text']);
if (isComplexAnswer && preservedAnswer) {
@@ -579,7 +588,10 @@ export class OLXParser {
}
replaceOlxDescriptionTag(questionString) {
- return questionString.replace(//gm, '').replace(/<\/description>/gm, ' ');
+ return questionString.replace(//gm, '').replace(
+ /<\/description>/gm,
+ ' ',
+ );
}
/** getHints()
@@ -677,9 +689,11 @@ export class OLXParser {
return ProblemTypeKeys.ADVANCED;
}
// make sure compound problems are treated as advanced
- if ((problemTypeKeys.length > 1)
+ if (
+ (problemTypeKeys.length > 1)
|| (isArray(this.problem[problemTypeKeys[0]])
- && this.problem[problemTypeKeys[0]].length > 1)) {
+ && this.problem[problemTypeKeys[0]].length > 1)
+ ) {
return ProblemTypeKeys.ADVANCED;
}
const problemType = problemTypeKeys[0];
@@ -703,8 +717,8 @@ export class OLXParser {
const firstIncorrectAnswerText = answers.find(answer => answer.correct === false)?.selectedFeedback;
const isAllIncorrectSelectedFeedbackTheSame = answers.every(answer => (answer.correct
? true
- : answer?.selectedFeedback === firstIncorrectAnswerText
- ));
+ : answer?.selectedFeedback === firstIncorrectAnswerText)
+ );
if (isAllIncorrectSelectedFeedbackTheSame) {
return firstIncorrectAnswerText;
}
diff --git a/src/editors/containers/ProblemEditor/data/OLXParser.test.js b/src/editors/containers/ProblemEditor/data/OLXParser.test.js
index 49cc87d1ff..fceb9de2c4 100644
--- a/src/editors/containers/ProblemEditor/data/OLXParser.test.js
+++ b/src/editors/containers/ProblemEditor/data/OLXParser.test.js
@@ -68,7 +68,9 @@ describe('OLXParser', () => {
describe('when question parser finds script tags', () => {
it('should throw error and contain message regarding opening advanced editor', () => {
const olxparser = new OLXParser(scriptProblemOlX.rawOLX);
- expect(() => olxparser.parseQuestions('numericalresponse')).toThrow(new Error('Script Tag, reverting to Advanced Editor'));
+ expect(() => olxparser.parseQuestions('numericalresponse')).toThrow(
+ new Error('Script Tag, reverting to Advanced Editor'),
+ );
});
});
describe('when multi select problem finds partial_credit attribute', () => {
@@ -261,7 +263,11 @@ describe('OLXParser', () => {
});
});
describe('given multiple choice olx with feedback and hints', () => {
- const { answers } = multipleChoiceOlxParser.parseMultipleChoiceAnswers('multiplechoiceresponse', 'choicegroup', 'choice');
+ const { answers } = multipleChoiceOlxParser.parseMultipleChoiceAnswers(
+ 'multiplechoiceresponse',
+ 'choicegroup',
+ 'choice',
+ );
it('should equal an array of objects with length three', () => {
expect(answers).toEqual(multipleChoiceWithFeedbackAndHintsOLX.data.answers);
expect(answers).toHaveLength(3);
diff --git a/src/editors/containers/ProblemEditor/data/ReactStateOLXParser.js b/src/editors/containers/ProblemEditor/data/ReactStateOLXParser.js
index d32abeac88..94d055a4a6 100644
--- a/src/editors/containers/ProblemEditor/data/ReactStateOLXParser.js
+++ b/src/editors/containers/ProblemEditor/data/ReactStateOLXParser.js
@@ -4,7 +4,37 @@ import { ProblemTypeKeys } from '../../../data/constants/problem';
import { ToleranceTypes } from '../components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/constants';
import { findNodesAndRemoveTheirParentNodes } from './reactStateOLXHelpers';
-const HtmlBlockTags = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'pre', 'blockquote', 'ol', 'ul', 'li', 'dl', 'dt', 'dd', 'hr', 'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'colgroup', 'col', 'address', 'fieldset', 'legend'];
+const HtmlBlockTags = [
+ 'p',
+ 'h1',
+ 'h2',
+ 'h3',
+ 'h4',
+ 'h5',
+ 'h6',
+ 'div',
+ 'pre',
+ 'blockquote',
+ 'ol',
+ 'ul',
+ 'li',
+ 'dl',
+ 'dt',
+ 'dd',
+ 'hr',
+ 'table',
+ 'thead',
+ 'caption',
+ 'tbody',
+ 'tr',
+ 'th',
+ 'td',
+ 'colgroup',
+ 'col',
+ 'address',
+ 'fieldset',
+ 'legend',
+];
class ReactStateOLXParser {
constructor(problemState) {
diff --git a/src/editors/containers/ProblemEditor/data/ReactStateOLXParser.test.js b/src/editors/containers/ProblemEditor/data/ReactStateOLXParser.test.js
index 9a4bad892d..6bf8db7a74 100644
--- a/src/editors/containers/ProblemEditor/data/ReactStateOLXParser.test.js
+++ b/src/editors/containers/ProblemEditor/data/ReactStateOLXParser.test.js
@@ -79,7 +79,8 @@ describe('Check React State OLXParser problem', () => {
problem,
editorObject: multipleChoiceWithFeedbackAndHints,
});
- stateParser.editorObject.question = 'You can use this template as a guide to the simple editor markdown and OLX markup to use for multiple choice with hints and feedback problems. Edit this component to replace this template with your own assessment.
\nAdd the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. Just a generic em tag
';
+ stateParser.editorObject.question =
+ 'You can use this template as a guide to the simple editor markdown and OLX markup to use for multiple choice with hints and feedback problems. Edit this component to replace this template with your own assessment.
\nAdd the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. Just a generic em tag
';
it('parser should not delete tags', () => {
const buildOLX = stateParser.buildOLX();
@@ -90,10 +91,18 @@ describe('Check React State OLXParser problem', () => {
const received = stateParser.addQuestion();
expect(received).toEqual(
[
- { p: [{ '#text': 'You can use this template as a guide to the simple editor markdown and OLX markup to use for multiple choice with hints and feedback problems. Edit this component to replace this template with your own assessment.' }] },
+ {
+ p: [{
+ '#text':
+ 'You can use this template as a guide to the simple editor markdown and OLX markup to use for multiple choice with hints and feedback problems. Edit this component to replace this template with your own assessment.',
+ }],
+ },
{ label: [{ '#text': 'Add the question text, or prompt, here. This text is required.' }] },
{ '#text': ' ' },
- { em: [{ '#text': 'You can add an optional tip or note related to the prompt like this. ' }], ':@': { '@_class': 'olx_description' } },
+ {
+ em: [{ '#text': 'You can add an optional tip or note related to the prompt like this. ' }],
+ ':@': { '@_class': 'olx_description' },
+ },
{ em: [{ '#text': 'Just a generic em tag' }] },
],
);
@@ -129,7 +138,9 @@ describe('Check React State OLXParser problem', () => {
editorObject: textInputWithFeedbackAndHintsWithMultipleAnswers,
});
const buildOLX = stateParser.buildOLX();
- expect(buildOLX.replace(/\s/g, '')).toEqual(textInputWithFeedbackAndHintsOLXWithMultipleAnswers.buildOLX.replace(/\s/g, ''));
+ expect(buildOLX.replace(/\s/g, '')).toEqual(
+ textInputWithFeedbackAndHintsOLXWithMultipleAnswers.buildOLX.replace(/\s/g, ''),
+ );
});
describe('encode/decode', () => {
test('does not change hex values to dec and does not remove leading 0s', () => {
diff --git a/src/editors/containers/ProblemEditor/data/ReactStateSettingsParser.js b/src/editors/containers/ProblemEditor/data/ReactStateSettingsParser.js
index b8d292b35a..3c792bfbfb 100644
--- a/src/editors/containers/ProblemEditor/data/ReactStateSettingsParser.js
+++ b/src/editors/containers/ProblemEditor/data/ReactStateSettingsParser.js
@@ -31,16 +31,42 @@ class ReactStateSettingsParser {
ShowAnswerTypesKeys.AFTER_ALL_ATTEMPTS_OR_CORRECT,
];
- settings = popuplateItem(settings, 'number', 'max_attempts', stateSettings.scoring.attempts, defaultSettings?.maxAttempts, true);
+ settings = popuplateItem(
+ settings,
+ 'number',
+ 'max_attempts',
+ stateSettings.scoring.attempts,
+ defaultSettings?.maxAttempts,
+ true,
+ );
settings = popuplateItem(settings, 'weight', 'weight', stateSettings.scoring);
settings = popuplateItem(settings, 'gradingMethod', 'grading_method', stateSettings.scoring);
settings = popuplateItem(settings, 'on', 'showanswer', stateSettings.showAnswer, defaultSettings?.showanswer, true);
if (includes(numberOfAttemptsChoice, stateSettings.showAnswer.on)) {
- settings = popuplateItem(settings, 'afterAttempts', 'attempts_before_showanswer_button', stateSettings.showAnswer);
+ settings = popuplateItem(
+ settings,
+ 'afterAttempts',
+ 'attempts_before_showanswer_button',
+ stateSettings.showAnswer,
+ );
}
- settings = popuplateItem(settings, 'showResetButton', 'show_reset_button', stateSettings, defaultSettings?.showResetButton, true);
+ settings = popuplateItem(
+ settings,
+ 'showResetButton',
+ 'show_reset_button',
+ stateSettings,
+ defaultSettings?.showResetButton,
+ true,
+ );
settings = popuplateItem(settings, 'timeBetween', 'submission_wait_seconds', stateSettings);
- settings = popuplateItem(settings, 'randomization', 'rerandomize', stateSettings, defaultSettings?.rerandomize, true);
+ settings = popuplateItem(
+ settings,
+ 'randomization',
+ 'rerandomize',
+ stateSettings,
+ defaultSettings?.rerandomize,
+ true,
+ );
return settings;
}
diff --git a/src/editors/containers/ProblemEditor/data/SettingsParser.js b/src/editors/containers/ProblemEditor/data/SettingsParser.js
index 78a6959761..cf34c11818 100644
--- a/src/editors/containers/ProblemEditor/data/SettingsParser.js
+++ b/src/editors/containers/ProblemEditor/data/SettingsParser.js
@@ -1,5 +1,8 @@
import {
- get, isEmpty, isFinite, isNil,
+ get,
+ isEmpty,
+ isFinite,
+ isNil,
} from 'lodash';
import { ShowAnswerTypes, RandomizationTypesKeys } from '../../../data/constants/problem';
diff --git a/src/editors/containers/ProblemEditor/data/apiHooks.ts b/src/editors/containers/ProblemEditor/data/apiHooks.ts
index e565103d15..94fd420741 100644
--- a/src/editors/containers/ProblemEditor/data/apiHooks.ts
+++ b/src/editors/containers/ProblemEditor/data/apiHooks.ts
@@ -10,16 +10,20 @@ interface ValidationResult {
preview?: string;
}
-export const useValidateInputBlock = () => useMutation({
- mutationFn: async (title : string): Promise => {
- try {
- const res = await api.validateBlockNumericInput({ studioEndpointUrl: `${getApiBaseUrl()}`, data: { formula: title } });
- return camelCaseObject(res.data);
- } catch (err: any) {
- return {
- isValid: false,
- error: err.response?.data?.error ?? 'Unknown error',
- };
- }
- },
-});
+export const useValidateInputBlock = () =>
+ useMutation({
+ mutationFn: async (title: string): Promise => {
+ try {
+ const res = await api.validateBlockNumericInput({
+ studioEndpointUrl: `${getApiBaseUrl()}`,
+ data: { formula: title },
+ });
+ return camelCaseObject(res.data);
+ } catch (err: any) {
+ return {
+ isValid: false,
+ error: err.response?.data?.error ?? 'Unknown error',
+ };
+ }
+ },
+ });
diff --git a/src/editors/containers/ProblemEditor/data/mockData/editorTestData.js b/src/editors/containers/ProblemEditor/data/mockData/editorTestData.js
index 989a926b7a..6b10064fca 100644
--- a/src/editors/containers/ProblemEditor/data/mockData/editorTestData.js
+++ b/src/editors/containers/ProblemEditor/data/mockData/editorTestData.js
@@ -7,7 +7,8 @@ export const checkboxesWithFeedbackAndHints = {
`,
- question: 'You can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
+ question:
+ 'You can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
answers: {
A: 'a correct answer
',
B: 'an incorrect answer
',
@@ -47,12 +48,14 @@ export const dropdownWithFeedbackAndHints = {
'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.
',
'If you add more than one hint, a different hint appears each time learners select the hint button.
',
],
- question: 'You can use this template as a guide to the simple editor markdown and OLX markup to use for dropdown with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
+ question:
+ 'You can use this template as a guide to the simple editor markdown and OLX markup to use for dropdown with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
};
export const multipleChoiceWithFeedbackAndHints = {
solution: 'You can add a solution
',
- question: `You can use this template as a guide to the simple editor markdown and OLX markup to use for multiple choice with hints and feedback problems. Edit this component to replace this template with your own assessment.
+ question:
+ `You can use this template as a guide to the simple editor markdown and OLX markup to use for multiple choice with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required.
You can add an optional tip or note related to the prompt like this. `,
answers: {
@@ -81,13 +84,15 @@ export const numericInputWithFeedbackAndHints = {
'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.
',
'If you add more than one hint, a different hint appears each time learners select the hint button.
',
],
- question: 'You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
+ question:
+ 'You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
};
export const numericInputWithAnswerRange = {
solution: '',
hints: [],
- question: 'You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
+ question:
+ 'You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
};
export const textInputWithFeedbackAndHints = {
@@ -101,7 +106,8 @@ export const textInputWithFeedbackAndHints = {
'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.
',
'If you add more than one hint, a different hint appears each time learners select the hint button.
',
],
- question: 'You can use this template as a guide to the simple editor markdown and OLX markup to use for text input with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
+ question:
+ 'You can use this template as a guide to the simple editor markdown and OLX markup to use for text input with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
};
export const textInputWithFeedbackAndHintsWithMultipleAnswers = {
@@ -116,7 +122,8 @@ export const textInputWithFeedbackAndHintsWithMultipleAnswers = {
'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.
',
'If you add more than one hint, a different hint appears each time learners select the hint button.
',
],
- question: 'You can use this template as a guide to the simple editor markdown and OLX markup to use for text input with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
+ question:
+ 'You can use this template as a guide to the simple editor markdown and OLX markup to use for text input with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
};
export const numberParseTest = {
diff --git a/src/editors/containers/ProblemEditor/data/mockData/olxTestData.js b/src/editors/containers/ProblemEditor/data/mockData/olxTestData.js
index e23adccfe3..eed9eeeaf9 100644
--- a/src/editors/containers/ProblemEditor/data/mockData/olxTestData.js
+++ b/src/editors/containers/ProblemEditor/data/mockData/olxTestData.js
@@ -41,11 +41,13 @@ export const checkboxesOLXWithFeedbackAndHintsOLX = {
hints: [
{
id: 0,
- value: 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.
',
+ value:
+ 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.
',
},
{
id: 1,
- value: 'If you add more than one hint, a different hint appears each time learners select the hint button.
',
+ value:
+ 'If you add more than one hint, a different hint appears each time learners select the hint button.
',
},
],
solutionExplanation: `
@@ -61,8 +63,10 @@ export const checkboxesOLXWithFeedbackAndHintsOLX = {
id: 'A',
title: `a correct answer
\n \n \n `,
correct: true,
- selectedFeedback: 'You can specify optional feedback that appears after the learner selects and submits this answer.
',
- unselectedFeedback: 'You can specify optional feedback that appears after the learner clears and submits this answer.
',
+ selectedFeedback:
+ 'You can specify optional feedback that appears after the learner selects and submits this answer.
',
+ unselectedFeedback:
+ 'You can specify optional feedback that appears after the learner clears and submits this answer.
',
},
{
id: 'B',
@@ -90,7 +94,8 @@ export const checkboxesOLXWithFeedbackAndHintsOLX = {
'B',
'D',
],
- feedback: 'You can specify optional feedback for a combination of answers which appears after the specified set of answers is submitted.',
+ feedback:
+ 'You can specify optional feedback for a combination of answers which appears after the specified set of answers is submitted.',
},
{
id: 1,
@@ -104,7 +109,8 @@ export const checkboxesOLXWithFeedbackAndHintsOLX = {
},
],
},
- question: 'You can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
+ question:
+ 'You can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
buildOLX: `
You can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.
@@ -200,14 +206,18 @@ export const multipleChoiceSingleAnswer = {
answers: [
{
id: 'A',
- title: `a correct answer
image with
caption .
\n \n \n `,
+ title:
+ `a correct answer
image with
caption .
\n \n \n `,
correct: true,
- selectedFeedback: 'You can specify optional feedback that appears after the learner selects and submits this answer.
',
- unselectedFeedback: 'You can specify optional feedback that appears after the learner clears and submits this answer.
',
+ selectedFeedback:
+ 'You can specify optional feedback that appears after the learner selects and submits this answer.
',
+ unselectedFeedback:
+ 'You can specify optional feedback that appears after the learner clears and submits this answer.
',
},
],
},
- question: 'You can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
+ question:
+ 'You can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
buildOLX: `
You can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.
@@ -256,20 +266,20 @@ export const dropdownOLXWithFeedbackAndHintsOLX = {
`,
hints: [{
id: 0,
- value: 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.
',
- },
- {
+ value:
+ 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.
',
+ }, {
id: 1,
value: 'If you add more than one hint, a different hint appears each time learners select the hint button.
',
- },
- ],
+ }],
data: {
answers: [
{
id: 'A',
title: 'an incorrect answer',
correct: false,
- selectedFeedback: 'You can specify optional feedback like this, which appears after this answer is submitted.
',
+ selectedFeedback:
+ 'You can specify optional feedback like this, which appears after this answer is submitted.
',
},
{
id: 'B',
@@ -284,7 +294,8 @@ export const dropdownOLXWithFeedbackAndHintsOLX = {
},
],
},
- question: 'You can use this template as a guide to the simple editor markdown and OLX markup to use for dropdown with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
+ question:
+ 'You can use this template as a guide to the simple editor markdown and OLX markup to use for dropdown with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
buildOLX: `
You can use this template as a guide to the simple editor markdown and OLX markup to use for dropdown with hints and feedback problems. Edit this component to replace this template with your own assessment.
@@ -331,13 +342,12 @@ export const multipleChoiceWithFeedbackAndHintsOLX = {
`,
hints: [{
id: 0,
- value: 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.
',
- },
- {
+ value:
+ 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.
',
+ }, {
id: 1,
value: 'If you add more than one hint, a different hint appears each time learners select the hint button.
',
- },
- ],
+ }],
solutionExplanation: 'You can add a solution
',
data: {
answers: [
@@ -345,7 +355,8 @@ export const multipleChoiceWithFeedbackAndHintsOLX = {
id: 'A',
title: 'an incorrect answer
',
correct: false,
- selectedFeedback: 'You can specify optional feedback like this, which appears after this answer is submitted.
',
+ selectedFeedback:
+ 'You can specify optional feedback like this, which appears after this answer is submitted.
',
},
{
id: 'B',
@@ -360,7 +371,8 @@ export const multipleChoiceWithFeedbackAndHintsOLX = {
},
],
},
- question: 'You can use this template as a guide to the simple editor markdown and OLX markup to use for multiple choice with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. Just a generic em tag ',
+ question:
+ 'You can use this template as a guide to the simple editor markdown and OLX markup to use for multiple choice with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. Just a generic em tag ',
buildOLX: `
You can use this template as a guide to the simple editor markdown and OLX markup to use for multiple choice with hints and feedback problems. Edit this component to replace this template with your own assessment.
@@ -409,20 +421,20 @@ export const numericInputWithFeedbackAndHintsOLX = {
`,
hints: [{
id: 0,
- value: 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.
',
- },
- {
+ value:
+ 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.
',
+ }, {
id: 1,
value: 'If you add more than one hint, a different hint appears each time learners select the hint button.
',
- },
- ],
+ }],
data: {
answers: [
{
id: 'A',
title: '100',
correct: true,
- selectedFeedback: 'You can specify optional feedback like this, which appears after this answer is submitted.
',
+ selectedFeedback:
+ 'You can specify optional feedback like this, which appears after this answer is submitted.
',
isAnswerRange: false,
tolerance: '5',
},
@@ -431,11 +443,13 @@ export const numericInputWithFeedbackAndHintsOLX = {
title: '200',
correct: true,
isAnswerRange: false,
- selectedFeedback: 'You can specify optional feedback like this, which appears after this answer is submitted.
',
+ selectedFeedback:
+ 'You can specify optional feedback like this, which appears after this answer is submitted.
',
},
],
},
- question: 'You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
+ question:
+ 'You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
buildOLX: `
You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required.
@@ -471,12 +485,14 @@ export const numericInputWithAnswerRangeOLX = {
id: 'A',
title: '[32,-1.3)',
correct: true,
- selectedFeedback: 'You can specify optional feedback like this, which appears after this answer is submitted.
',
+ selectedFeedback:
+ 'You can specify optional feedback like this, which appears after this answer is submitted.
',
isAnswerRange: true,
},
],
},
- question: 'You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
+ question:
+ 'You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
buildOLX: `
You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required.
@@ -506,20 +522,20 @@ export const textInputWithFeedbackAndHintsOLX = {
`,
hints: [{
id: 0,
- value: 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.
',
- },
- {
+ value:
+ 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.
',
+ }, {
id: 1,
value: 'If you add more than one hint, a different hint appears each time learners select the hint button.
',
- },
- ],
+ }],
data: {
answers: [
{
id: 'A',
title: 'the correct answer',
correct: true,
- selectedFeedback: 'You can specify optional feedback like this, which appears after this answer is submitted.
',
+ selectedFeedback:
+ 'You can specify optional feedback like this, which appears after this answer is submitted.
',
},
{
id: 'B',
@@ -541,7 +557,8 @@ export const textInputWithFeedbackAndHintsOLX = {
},
},
},
- question: `You can use this template as a guide to the simple editor markdown and OLX markup to use for text input with hints and feedback problems. Edit this component to replace this template with your own assessment.
+ question:
+ `You can use this template as a guide to the simple editor markdown and OLX markup to use for text input with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required.
You can add an optional tip or note related to the prompt like this. `,
buildOLX: `
@@ -580,13 +597,12 @@ export const textInputWithFeedbackInIncorrectAnswerOnlyOLX = {
`,
hints: [{
id: 0,
- value: 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.
',
- },
- {
+ value:
+ 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.
',
+ }, {
id: 1,
value: 'If you add more than one hint, a different hint appears each time learners select the hint button.
',
- },
- ],
+ }],
data: {
answers: [
{
@@ -621,7 +637,8 @@ export const textInputWithFeedbackInIncorrectAnswerOnlyOLX = {
},
},
},
- question: `You can use this template as a guide to the simple editor markdown and OLX markup to use for text input with hints and feedback problems. Edit this component to replace this template with your own assessment.
+ question:
+ `You can use this template as a guide to the simple editor markdown and OLX markup to use for text input with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required.
You can add an optional tip or note related to the prompt like this. `,
buildOLX: `
@@ -661,13 +678,12 @@ export const textInputWithFeedbackAndHintsOLXWithMultipleAnswers = {
`,
hints: [{
id: 0,
- value: 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.
',
- },
- {
+ value:
+ 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.
',
+ }, {
id: 1,
value: 'If you add more than one hint, a different hint appears each time learners select the hint button.
',
- },
- ],
+ }],
data: {
answers: [
{
@@ -702,7 +718,8 @@ export const textInputWithFeedbackAndHintsOLXWithMultipleAnswers = {
},
},
},
- question: 'You can use this template as a guide to the simple editor markdown and OLX markup to use for text input with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
+ question:
+ 'You can use this template as a guide to the simple editor markdown and OLX markup to use for text input with hints and feedback problems. Edit this component to replace this template with your own assessment.
Add the question text, or prompt, here. This text is required. You can add an optional tip or note related to the prompt like this. ',
buildOLX: `
You can use this template as a guide to the simple editor markdown and OLX markup to use for text input with hints and feedback problems. Edit this component to replace this template with your own assessment.
@@ -833,8 +850,7 @@ export const shuffleProblemOLX = {
};
export const labelDescriptionQuestionOLX = {
- rawOLX:
-`
+ rawOLX: `
Taking the system as just the water , as indicated by the red dashed line, what would be the correct expression for the first law of thermodynamics applied to this system?
@@ -852,15 +868,15 @@ export const labelDescriptionQuestionOLX = {
`,
- question: `
+ question:
+ `
Taking the system as just the water , as indicated by the red dashed line, what would be the correct expression for the first law of thermodynamics applied to this system?
Watch out, boiling water is hot `,
};
export const htmlEntityTestOLX = {
- rawOLX:
- `
+ rawOLX: `
What is the content of the register x2 after executing the following three lines of instructions?
Address assembly instructions 0x0 addi x1, x0, 1 0x4 slli x2, x1, 4 0x8 sub x1, x2, x1
@@ -892,7 +908,8 @@ export const htmlEntityTestOLX = {
},
question: `What is the content of the register x2 after executing the following three lines of instructions?
Address assembly instructions 0x0 addi x1, x0, 1 0x4 slli x2, x1, 4 0x8 sub x1, x2, x1
`,
- solutionExplanation: `Address assembly instructions comment 0x0 addi x1, x0, 1 x1 = 0x1 0x4 slli x2, x1, 4 x2 = x1 << 4 = 0x10 0x8 sub x1, x2, x1 x1 = x2 - x1 = 0x10 - 0x01 = 0xf
`,
+ solutionExplanation:
+ `Address assembly instructions comment 0x0 addi x1, x0, 1 x1 = 0x1 0x4 slli x2, x1, 4 x2 = x1 << 4 = 0x10 0x8 sub x1, x2, x1 x1 = x2 - x1 = 0x10 - 0x01 = 0xf
`,
};
export const numberParseTestOLX = {
@@ -1224,7 +1241,7 @@ export const parseOutExplanationTests = {
solution meat
- `
+ `,
};
export const multiSelectPartialCredit = {
@@ -1239,8 +1256,8 @@ export const multiSelectPartialCredit = {
tomato
- `
-}
+ `,
+};
export const singleSelectPartialCredit = {
rawOLX: `
@@ -1253,8 +1270,8 @@ export const singleSelectPartialCredit = {
The vegetable peeler
- `
-}
+ `,
+};
export const numericalProblemPartialCredit = {
rawOLX: `
@@ -1264,8 +1281,8 @@ export const numericalProblemPartialCredit = {
- `
-}
+ `,
+};
export const unexpectOlxAfterProblemTypeTags = {
rawOLX: `
@@ -1282,5 +1299,5 @@ export const unexpectOlxAfterProblemTypeTags = {
You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.
If you add more than one hint, a different hint appears each time learners select the hint button.
- `
-}
+ `,
+};
diff --git a/src/editors/containers/ProblemEditor/data/mockData/problemTestData.js b/src/editors/containers/ProblemEditor/data/mockData/problemTestData.js
index 5829c901cb..c4aa484094 100644
--- a/src/editors/containers/ProblemEditor/data/mockData/problemTestData.js
+++ b/src/editors/containers/ProblemEditor/data/mockData/problemTestData.js
@@ -1,15 +1,19 @@
export const checklistWithFeebackHints = {
state: {
- rawOLX: '\n \n You can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.
\n Add the question text, or prompt, here. This text is required. \n You can add an optional tip or note related to the prompt like this. \n \n a correct answer\n You can specify optional feedback that appears after the learner selects and submits this answer. \n You can specify optional feedback that appears after the learner clears and submits this answer. \n \n an incorrect answer\n \n an incorrect answer\n You can specify optional feedback for none, all, or a subset of the answers. \n You can specify optional feedback for selected answers, cleared answers, or both. \n \n a correct answer\n \n You can specify optional feedback for a combination of answers which appears after the specified set of answers is submitted. \n You can specify optional feedback for one, several, or all answer combinations. \n \n \n\n \n You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button. \n If you add more than one hint, a different hint appears each time learners select the hint button. \n \n \n',
+ rawOLX:
+ '\n \n You can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.
\n Add the question text, or prompt, here. This text is required. \n You can add an optional tip or note related to the prompt like this. \n \n a correct answer\n You can specify optional feedback that appears after the learner selects and submits this answer. \n You can specify optional feedback that appears after the learner clears and submits this answer. \n \n an incorrect answer\n \n an incorrect answer\n You can specify optional feedback for none, all, or a subset of the answers. \n You can specify optional feedback for selected answers, cleared answers, or both. \n \n a correct answer\n \n You can specify optional feedback for a combination of answers which appears after the specified set of answers is submitted. \n You can specify optional feedback for one, several, or all answer combinations. \n \n \n\n \n You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button. \n If you add more than one hint, a different hint appears each time learners select the hint button. \n \n \n',
problemType: 'MULTISELECT',
- question: 'You can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.\n\nAdd the question text, or prompt, here. This text is required.||You can add an optional tip or note related to the prompt like this.
\n\n',
+ question:
+ 'You can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.\n\nAdd the question text, or prompt, here. This text is required.||You can add an optional tip or note related to the prompt like this.
\n\n',
answers: [
{
id: 'A',
title: 'a correct answer',
correct: true,
- selectedFeedback: ' You can specify optional feedback that appears after the learner selects and submits this answer.',
- unselectedFeedback: 'You can specify optional feedback that appears after the learner clears and submits this answer.',
+ selectedFeedback:
+ ' You can specify optional feedback that appears after the learner selects and submits this answer.',
+ unselectedFeedback:
+ 'You can specify optional feedback that appears after the learner clears and submits this answer.',
},
{
id: 'B',
@@ -41,7 +45,8 @@ export const checklistWithFeebackHints = {
'B',
'D',
],
- selectedFeedback: 'You can specify optional feedback for a combination of answers which appears after the specified set of answers is submitted.',
+ selectedFeedback:
+ 'You can specify optional feedback for a combination of answers which appears after the specified set of answers is submitted.',
},
{
id: 4,
@@ -58,7 +63,8 @@ export const checklistWithFeebackHints = {
hints: [
{
id: 14,
- value: 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.',
+ value:
+ 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.',
},
{
id: 15,
@@ -81,7 +87,8 @@ export const checklistWithFeebackHints = {
},
},
metadata: {
- markdown: `You can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.
+ markdown:
+ `You can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.
>>Add the question text, or prompt, here. This text is required.||You can add an optional tip or note related to the prompt like this.<<
[x] a correct answer{{selected: You can specify optional feedback that appears after the learner selects and submits this answer.},{unselected: You can specify optional feedback that appears after the learner clears and submits this answer.}}
@@ -105,9 +112,11 @@ export const checklistWithFeebackHints = {
export const dropdownWithFeedbackHints = {
state: {
- rawOLX: '\n \n You can use this template as a guide to the simple editor markdown and OLX markup to use for dropdown with hints and feedback problems. Edit this component to replace this template with your own assessment.
\n Add the question text, or prompt, here. This text is required. \n You can add an optional tip or note related to the prompt like this. \n \n an incorrect answer You can specify optional feedback like this, which appears after this answer is submitted. \n the correct answer \n an incorrect answer You can specify optional feedback for none, a subset, or all of the answers. \n \n \n \n You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button. \n If you add more than one hint, a different hint appears each time learners select the hint button. \n \n \n',
+ rawOLX:
+ '\n \n You can use this template as a guide to the simple editor markdown and OLX markup to use for dropdown with hints and feedback problems. Edit this component to replace this template with your own assessment.
\n Add the question text, or prompt, here. This text is required. \n You can add an optional tip or note related to the prompt like this. \n \n an incorrect answer You can specify optional feedback like this, which appears after this answer is submitted. \n the correct answer \n an incorrect answer You can specify optional feedback for none, a subset, or all of the answers. \n \n \n \n You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button. \n If you add more than one hint, a different hint appears each time learners select the hint button. \n \n \n',
problemType: 'DROPDOWN',
- question: 'You can use this template as a guide to the simple editor markdown and OLX markup to use for dropdown with hints and feedback problems. Edit this component to replace this template with your own assessment.\nAdd the question text, or prompt, here. This text is required.||You can add an optional tip or note related to the prompt like this.
\n',
+ question:
+ 'You can use this template as a guide to the simple editor markdown and OLX markup to use for dropdown with hints and feedback problems. Edit this component to replace this template with your own assessment.\nAdd the question text, or prompt, here. This text is required.||You can add an optional tip or note related to the prompt like this.
\n',
answers: [
{
id: 'A',
@@ -133,7 +142,8 @@ export const dropdownWithFeedbackHints = {
hints: [
{
id: 8,
- value: 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.',
+ value:
+ 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.',
},
{
id: 9,
@@ -156,7 +166,8 @@ export const dropdownWithFeedbackHints = {
},
},
metadata: {
- markdown: `You can use this template as a guide to the simple editor markdown and OLX markup to use for dropdown with hints and feedback problems. Edit this component to replace this template with your own assessment.
+ markdown:
+ `You can use this template as a guide to the simple editor markdown and OLX markup to use for dropdown with hints and feedback problems. Edit this component to replace this template with your own assessment.
>>Add the question text, or prompt, here. This text is required.||You can add an optional tip or note related to the prompt like this. <<
[[
an incorrect answer {{You can specify optional feedback like this, which appears after this answer is submitted.}}
@@ -178,9 +189,11 @@ export const dropdownWithFeedbackHints = {
export const numericWithHints = {
state: {
- rawOLX: '\n \n You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.
\n Add the question text, or prompt, here. This text is required. \n You can add an optional tip or note related to the prompt like this. \n \n \n You can specify optional feedback like this, which appears after this answer is submitted. \n \n \n You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button. \n If you add more than one hint, a different hint appears each time learners select the hint button. \n \n \n',
+ rawOLX:
+ '\n \n You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.
\n Add the question text, or prompt, here. This text is required. \n You can add an optional tip or note related to the prompt like this. \n \n \n You can specify optional feedback like this, which appears after this answer is submitted. \n \n \n You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button. \n If you add more than one hint, a different hint appears each time learners select the hint button. \n \n \n',
problemType: 'TEXTINPUT',
- question: 'You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.\n\nAdd the question text, or prompt, here. This text is required.||You can add an optional tip or note related to the prompt like this.
\n\n',
+ question:
+ 'You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.\n\nAdd the question text, or prompt, here. This text is required.||You can add an optional tip or note related to the prompt like this.
\n\n',
answers: [
{
id: 'A',
@@ -206,7 +219,8 @@ export const numericWithHints = {
hints: [
{
id: 6,
- value: 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.',
+ value:
+ 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.',
},
{
id: 7,
@@ -229,7 +243,8 @@ export const numericWithHints = {
},
},
metadata: {
- markdown: `You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.
+ markdown:
+ `You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.
>>Add the question text, or prompt, here. This text is required.||You can add an optional tip or note related to the prompt like this. <<
=100 +-5 {{You can specify optional feedback like this, which appears after this answer is submitted.}}
@@ -248,9 +263,11 @@ not=60 +-5 {{You can specify optional feedback like this, which appears after th
export const textInputWithHints = {
state: {
- rawOLX: '\n \n You can use this template as a guide to the simple editor markdown and OLX markup to use for text input with hints and feedback problems. Edit this component to replace this template with your own assessment.
\n Add the question text, or prompt, here. This text is required. \n You can add an optional tip or note related to the prompt like this. \n You can specify optional feedback like this, which appears after this answer is submitted. \n \n You can specify optional feedback for none, a subset, or all of the answers. \n \n \n \n You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button. \n If you add more than one hint, a different hint appears each time learners select the hint button. \n \n \n',
+ rawOLX:
+ '\n \n You can use this template as a guide to the simple editor markdown and OLX markup to use for text input with hints and feedback problems. Edit this component to replace this template with your own assessment.
\n Add the question text, or prompt, here. This text is required. \n You can add an optional tip or note related to the prompt like this. \n You can specify optional feedback like this, which appears after this answer is submitted. \n \n You can specify optional feedback for none, a subset, or all of the answers. \n \n \n \n You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button. \n If you add more than one hint, a different hint appears each time learners select the hint button. \n \n \n',
problemType: 'TEXTINPUT',
- question: 'You can use this template as a guide to the simple editor markdown and OLX markup to use for text input with hints and feedback problems. Edit this component to replace this template with your own assessment.\n\nAdd the question text, or prompt, here. This text is required.||You can add an optional tip or note related to the prompt like this.
\n\n',
+ question:
+ 'You can use this template as a guide to the simple editor markdown and OLX markup to use for text input with hints and feedback problems. Edit this component to replace this template with your own assessment.\n\nAdd the question text, or prompt, here. This text is required.||You can add an optional tip or note related to the prompt like this.
\n\n',
answers: [
{
id: 'A',
@@ -276,7 +293,8 @@ export const textInputWithHints = {
hints: [
{
id: 9,
- value: 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.',
+ value:
+ 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.',
},
{
id: 10,
@@ -299,7 +317,8 @@ export const textInputWithHints = {
},
},
metadata: {
- markdown: `You can use this template as a guide to the simple editor markdown and OLX markup to use for text input with hints and feedback problems. Edit this component to replace this template with your own assessment.
+ markdown:
+ `You can use this template as a guide to the simple editor markdown and OLX markup to use for text input with hints and feedback problems. Edit this component to replace this template with your own assessment.
>>Add the question text, or prompt, here. This text is required.||You can add an optional tip or note related to the prompt like this. <<
=the correct answer {{You can specify optional feedback like this, which appears after this answer is submitted.}}
@@ -314,9 +333,11 @@ not=optional incorrect answer such as a frequent misconception {{You can specify
export const singleSelectWithHints = {
state: {
- rawOLX: '\nYou can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.
\n\nAdd the question text, or prompt, here. This text is required. \nYou can add an optional tip or note related to the prompt like this. \n\n \n a correct answer selected: You can specify optional feedback that appears after the learner selects and submits this answer. }, { unselected: You can specify optional feedback that appears after the learner clears and submits this answer. \n an incorrect answer \n an incorrect answer selected: You can specify optional feedback for none, all, or a subset of the answers. }, { unselected: You can specify optional feedback for selected answers, cleared answers, or both. \n an incorrect answer again \n \n \n\n \n You can specify optional feedback for a combination of answers which appears after the specified set of answers is submitted. \n You can specify optional feedback for one, several, or all answer combinations. \n \n \n\n\n\n You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button. \n If you add more than one hint, a different hint appears each time learners select the hint button. \n \n ',
+ rawOLX:
+ '\nYou can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.
\n\nAdd the question text, or prompt, here. This text is required. \nYou can add an optional tip or note related to the prompt like this. \n\n \n a correct answer selected: You can specify optional feedback that appears after the learner selects and submits this answer. }, { unselected: You can specify optional feedback that appears after the learner clears and submits this answer. \n an incorrect answer \n an incorrect answer selected: You can specify optional feedback for none, all, or a subset of the answers. }, { unselected: You can specify optional feedback for selected answers, cleared answers, or both. \n an incorrect answer again \n \n \n\n \n You can specify optional feedback for a combination of answers which appears after the specified set of answers is submitted. \n You can specify optional feedback for one, several, or all answer combinations. \n \n \n\n\n\n You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button. \n If you add more than one hint, a different hint appears each time learners select the hint button. \n \n ',
problemType: 'SINGLESELECT',
- question: 'You can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.\n\nAdd the question text, or prompt, here. This text is required.||You can add an optional tip or note related to the prompt like this.
\n\n',
+ question:
+ 'You can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.\n\nAdd the question text, or prompt, here. This text is required.||You can add an optional tip or note related to the prompt like this.
\n\n',
answers: [
{
id: 'A',
@@ -348,7 +369,8 @@ export const singleSelectWithHints = {
hints: [
{
id: 13,
- value: 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.',
+ value:
+ 'You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.',
},
{
id: 14,
@@ -370,7 +392,8 @@ export const singleSelectWithHints = {
},
},
metadata: {
- markdown: `You can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.
+ markdown:
+ `You can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.
>>Add the question text, or prompt, here. This text is required.||You can add an optional tip or note related to the prompt like this.<<
(x) a correct answer {{Some new feedback}}
@@ -385,7 +408,8 @@ export const singleSelectWithHints = {
export const negativeAttempts = {
state: {
- rawOLX: '\n \n \n \n \n \n',
+ rawOLX:
+ '\n \n \n \n \n \n',
problemType: 'TEXTINPUT',
question: '',
answers: [
diff --git a/src/editors/containers/ProblemEditor/data/reactStateOLXHelpers.js b/src/editors/containers/ProblemEditor/data/reactStateOLXHelpers.js
index fcece04feb..e807b130be 100644
--- a/src/editors/containers/ProblemEditor/data/reactStateOLXHelpers.js
+++ b/src/editors/containers/ProblemEditor/data/reactStateOLXHelpers.js
@@ -9,9 +9,11 @@ import { flatten } from 'lodash';
* @returns {void}
*/
function flattenSubNodes(node, subNodes, options = { recursive: false }) {
- const values = Array.isArray(node) ? (
- flatten(node.map(n => Object.values(n)))
- ) : Object.values(node);
+ const values = Array.isArray(node) ?
+ (
+ flatten(node.map(n => Object.values(n)))
+ ) :
+ Object.values(node);
values.forEach(value => {
if (Array.isArray(value)) {
diff --git a/src/editors/containers/ProblemEditor/data/reactStateOLXHelpers.test.js b/src/editors/containers/ProblemEditor/data/reactStateOLXHelpers.test.js
index ab5b31c1bf..cdf8989dac 100644
--- a/src/editors/containers/ProblemEditor/data/reactStateOLXHelpers.test.js
+++ b/src/editors/containers/ProblemEditor/data/reactStateOLXHelpers.test.js
@@ -3,58 +3,49 @@ import { nodeContainsChildTags, findNodesAndRemoveTheirParentNodes, tagName } fr
describe('reactStateOLXHelpers', () => {
describe('findNodesWithChildTags', () => {
const node = {
- div:
- [
- {
- label:
- [
- { '#text': 'def' },
- ],
- },
- { '#text': ' ' },
- {
- em:
- [
- { '#text': 'ghi' },
- ],
- ':@': { '@_class': 'olx_description' },
- },
- {
- em:
- [
- { '#text': 'jkl' },
- ],
- },
- ],
+ div: [
+ {
+ label: [
+ { '#text': 'def' },
+ ],
+ },
+ { '#text': ' ' },
+ {
+ em: [
+ { '#text': 'ghi' },
+ ],
+ ':@': { '@_class': 'olx_description' },
+ },
+ {
+ em: [
+ { '#text': 'jkl' },
+ ],
+ },
+ ],
};
const nodeWithNestedLabel = {
- div:
- [
- {
- div:
- [{
- label:
- [
+ div: [
+ {
+ div: [{
+ label: [
{ '#text': 'def' },
],
- }],
- },
- { '#text': ' ' },
- {
- em:
- [
- { '#text': 'ghi' },
- ],
- ':@': { '@_class': 'olx_description' },
- },
- {
- em:
- [
- { '#text': 'jkl' },
- ],
- },
- ],
+ }],
+ },
+ { '#text': ' ' },
+ {
+ em: [
+ { '#text': 'ghi' },
+ ],
+ ':@': { '@_class': 'olx_description' },
+ },
+ {
+ em: [
+ { '#text': 'jkl' },
+ ],
+ },
+ ],
};
it('should return true if node contains specified child tags', () => {
@@ -91,16 +82,13 @@ describe('reactStateOLXHelpers', () => {
}],
},
{
- div:
- [
+ div: [
{
- label:
- [{ '#text': 'def' }],
+ label: [{ '#text': 'def' }],
},
{ '#text': ' ' },
{
- em:
- [{
+ em: [{
'#text': 'ghi',
}],
':@': { '@_class': 'olx_description' },
@@ -121,10 +109,9 @@ describe('reactStateOLXHelpers', () => {
},
{ '#text': ' ' },
{
- em:
- [{
- '#text': 'ghi',
- }],
+ em: [{
+ '#text': 'ghi',
+ }],
':@': { '@_class': 'olx_description' },
},
{ em: [{ '#text': 'Just a generic em tag' }] },
@@ -172,10 +159,9 @@ describe('reactStateOLXHelpers', () => {
expect(tagName({
':@': { '@_class': 'olx_description' },
'#text': 'abc',
- em:
- [{
- '#text': 'ghi',
- }],
+ em: [{
+ '#text': 'ghi',
+ }],
})).toEqual('em');
});
});
diff --git a/src/editors/containers/ProblemEditor/index.test.tsx b/src/editors/containers/ProblemEditor/index.test.tsx
index c831bbb5b0..2ceefb8324 100644
--- a/src/editors/containers/ProblemEditor/index.test.tsx
+++ b/src/editors/containers/ProblemEditor/index.test.tsx
@@ -7,12 +7,14 @@ import ProblemEditor from './index';
import messages from './messages';
// Mock child components for easy selection
-jest.mock('./components/SelectTypeModal', () => function mockSelectTypeModal(props: any) {
- return SelectTypeModal {props.onClose && 'withOnClose'}
;
-});
-jest.mock('./components/EditProblemView', () => function mockEditProblemView(props: any) {
- return EditProblemView {props.onClose && 'withOnClose'} {props.returnFunction && 'withReturnFunction'}
;
-});
+jest.mock('./components/SelectTypeModal', () =>
+ function mockSelectTypeModal(props: any) {
+ return SelectTypeModal {props.onClose && 'withOnClose'}
;
+ });
+jest.mock('./components/EditProblemView', () =>
+ function mockEditProblemView(props: any) {
+ return EditProblemView {props.onClose && 'withOnClose'} {props.returnFunction && 'withReturnFunction'}
;
+ });
// Mock the initializeProblem method:
jest.spyOn(thunkActions.problem, 'initializeProblem').mockImplementation(
() => () => Promise.resolve(),
@@ -91,7 +93,6 @@ describe('ProblemEditor', () => {
requests: {
fetchBlock: { status: 'completed' },
fetchAdvancedSettings: { status: 'completed' },
-
},
};
editorRender( , { initialState });
@@ -109,7 +110,6 @@ describe('ProblemEditor', () => {
fetchBlock: { status: 'completed' },
fetchAdvancedSettings: { status: 'completed' },
},
-
};
editorRender( , { initialState });
diff --git a/src/editors/containers/ProblemEditor/index.tsx b/src/editors/containers/ProblemEditor/index.tsx
index 4e6ccb3d34..89311e3caf 100644
--- a/src/editors/containers/ProblemEditor/index.tsx
+++ b/src/editors/containers/ProblemEditor/index.tsx
@@ -3,7 +3,10 @@ import { useSelector, useDispatch } from 'react-redux';
import { Spinner } from '@openedx/paragon';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import {
- EditorState, selectors, actions, thunkActions,
+ EditorState,
+ selectors,
+ actions,
+ thunkActions,
} from '@src/editors/data/redux';
import { RequestKeys } from '@src/editors/data/constants/requests';
import { EditorComponent } from '@src/editors/EditorComponent';
@@ -29,8 +32,10 @@ const ProblemEditor: React.FC = ({
const intl = useIntl();
const dispatch = useDispatch();
- const blockFinished = useSelector((state: EditorState) => selectors.app.shouldCreateBlock(state)
- || selectors.requests.isFinished(state, { requestKey: RequestKeys.fetchBlock }));
+ const blockFinished = useSelector((state: EditorState) =>
+ selectors.app.shouldCreateBlock(state)
+ || selectors.requests.isFinished(state, { requestKey: RequestKeys.fetchBlock })
+ );
const blockFailed = useSelector(
(state: EditorState) => selectors.requests.isFailed(state, { requestKey: RequestKeys.fetchBlock }),
@@ -42,8 +47,10 @@ const ProblemEditor: React.FC = ({
const updateField = React.useCallback((data) => dispatch(actions.problem.updateField(data)), [dispatch]);
const setBlockTitle = React.useCallback((title) => dispatch(actions.app.setBlockTitle(title)), [dispatch]);
- const advancedSettingsFinished = useSelector((state: EditorState) => selectors.app.shouldCreateBlock(state)
- || selectors.requests.isFinished(state, { requestKey: RequestKeys.fetchAdvancedSettings }));
+ const advancedSettingsFinished = useSelector((state: EditorState) =>
+ selectors.app.shouldCreateBlock(state)
+ || selectors.requests.isFinished(state, { requestKey: RequestKeys.fetchAdvancedSettings })
+ );
useEffect(() => {
const run = async () => {
@@ -89,10 +96,10 @@ const ProblemEditor: React.FC = ({
}
if (problemType === null) {
- return ( );
+ return ;
}
- return ( );
+ return ;
};
export default ProblemEditor;
diff --git a/src/editors/containers/ProblemEditor/messages.ts b/src/editors/containers/ProblemEditor/messages.ts
index d9fa05cb42..ce34e8accb 100644
--- a/src/editors/containers/ProblemEditor/messages.ts
+++ b/src/editors/containers/ProblemEditor/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
blockFailed: {
id: 'authoring.problemEditor.blockFailed',
defaultMessage: 'Problem failed to load',
diff --git a/src/editors/containers/TextEditor/hooks.js b/src/editors/containers/TextEditor/hooks.js
index 6271776f0d..27238e2584 100644
--- a/src/editors/containers/TextEditor/hooks.js
+++ b/src/editors/containers/TextEditor/hooks.js
@@ -4,9 +4,9 @@ import { setAssetToStaticUrl } from '../../sharedComponents/TinyMceWidget/hooks'
export const { nullMethod, navigateCallback, navigateTo } = appHooks;
export const getContent = ({ editorRef, showRawEditor }) => () => {
- const content = (showRawEditor && editorRef && editorRef.current
+ const content = showRawEditor && editorRef && editorRef.current
? editorRef.current.state.doc.toString()
- : editorRef.current?.getContent());
+ : editorRef.current?.getContent();
return setAssetToStaticUrl({ editorValue: content });
};
@@ -15,8 +15,8 @@ export const isDirty = ({ editorRef, showRawEditor }) => () => {
if (!editorRef?.current) {
return false;
}
- const dirty = (showRawEditor && editorRef && editorRef.current
+ const dirty = showRawEditor && editorRef && editorRef.current
? editorRef.current.observer?.lastChange !== 0
- : !editorRef.current.isNotDirty);
+ : !editorRef.current.isNotDirty;
return dirty;
};
diff --git a/src/editors/containers/TextEditor/index.jsx b/src/editors/containers/TextEditor/index.jsx
index 03fb498e9f..c45c518013 100644
--- a/src/editors/containers/TextEditor/index.jsx
+++ b/src/editors/containers/TextEditor/index.jsx
@@ -43,7 +43,7 @@ const TextEditor = ({
const editorContent = newContent || initialContent;
let staticRootUrl;
if (isLibrary) {
- staticRootUrl = `${getConfig().STUDIO_BASE_URL }/library_assets/blocks/${ blockId }/`;
+ staticRootUrl = `${getConfig().STUDIO_BASE_URL}/library_assets/blocks/${blockId}/`;
}
if (!refReady) { return null; }
@@ -85,7 +85,7 @@ const TextEditor = ({
>
- { intl.formatMessage(messages.couldNotLoadTextContext) }
+ {intl.formatMessage(messages.couldNotLoadTextContext)}
{(!blockFinished)
@@ -97,7 +97,8 @@ const TextEditor = ({
screenreadertext={intl.formatMessage(messages.spinnerScreenReaderText)}
/>
- ) : (selectEditor())}
+ ) :
+ (selectEditor())}
);
@@ -130,7 +131,7 @@ export const mapStateToProps = (state) => ({
blockId: selectors.app.blockId(state),
showRawEditor: selectors.app.showRawEditor(state),
blockFinished: selectors.app.shouldCreateBlock(state)
- || selectors.requests.isFinished(state, { requestKey: RequestKeys.fetchBlock }),
+ || selectors.requests.isFinished(state, { requestKey: RequestKeys.fetchBlock }),
learningContextId: selectors.app.learningContextId(state),
images: selectors.app.images(state),
isLibrary: selectors.app.isLibrary(state),
diff --git a/src/editors/containers/TextEditor/index.test.tsx b/src/editors/containers/TextEditor/index.test.tsx
index 0844ffb932..fd8279c2ce 100644
--- a/src/editors/containers/TextEditor/index.test.tsx
+++ b/src/editors/containers/TextEditor/index.test.tsx
@@ -75,7 +75,9 @@ describe('TextEditor', () => {
const { container } = render( );
const element = container.querySelector('tinymcewidget');
expect(element).toBeInTheDocument();
- expect(element?.getAttribute('editorcontenthtml')).toBe('eDiTablE Text with ');
+ expect(element?.getAttribute('editorcontenthtml')).toBe(
+ 'eDiTablE Text with ',
+ );
});
test('not yet loaded, Spinner appears', () => {
const { container } = render( );
@@ -108,8 +110,10 @@ describe('TextEditor', () => {
test('blockFinished from requests.isFinished', () => {
expect(
mapStateToProps(testState).blockFinished,
- ).toEqual(selectors.app.shouldCreateBlock(testState)
- || selectors.requests.isFinished(testState, { requestKey: RequestKeys.fetchBlock }));
+ ).toEqual(
+ selectors.app.shouldCreateBlock(testState)
+ || selectors.requests.isFinished(testState, { requestKey: RequestKeys.fetchBlock }),
+ );
});
test('learningContextId from app.learningContextId', () => {
expect(
diff --git a/src/editors/containers/TextEditor/messages.ts b/src/editors/containers/TextEditor/messages.ts
index e6f870a4b6..d987a3a60a 100644
--- a/src/editors/containers/TextEditor/messages.ts
+++ b/src/editors/containers/TextEditor/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
couldNotLoadTextContext: {
id: 'authoring.texteditor.load.error',
defaultMessage: 'Error: Could Not Load Text Content',
diff --git a/src/editors/containers/VideoEditor/components/SelectVideoModal.jsx b/src/editors/containers/VideoEditor/components/SelectVideoModal.jsx
index bd7a7507f9..f183e170bb 100644
--- a/src/editors/containers/VideoEditor/components/SelectVideoModal.jsx
+++ b/src/editors/containers/VideoEditor/components/SelectVideoModal.jsx
@@ -43,9 +43,7 @@ export const SelectVideoModal = ({
>
{/* Content selection */}
{videos && (videos.map(
- img => (
- {img.externalUrl}
- ),
+ img => {img.externalUrl}
,
))}
);
diff --git a/src/editors/containers/VideoEditor/components/SelectVideoModal.test.jsx b/src/editors/containers/VideoEditor/components/SelectVideoModal.test.jsx
index 6901b878a9..326cd96810 100644
--- a/src/editors/containers/VideoEditor/components/SelectVideoModal.test.jsx
+++ b/src/editors/containers/VideoEditor/components/SelectVideoModal.test.jsx
@@ -1,6 +1,9 @@
import React from 'react';
import {
- render, screen, fireEvent, waitFor,
+ render,
+ screen,
+ fireEvent,
+ waitFor,
} from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { Provider } from 'react-redux';
@@ -105,7 +108,9 @@ describe('SelectVideoModal hooks', () => {
render( );
- await waitFor(() => expect(screen.getByTestId('videos').textContent).toBe(videos.map((v) => v.externalUrl).join(', ')));
+ await waitFor(() =>
+ expect(screen.getByTestId('videos').textContent).toBe(videos.map((v) => v.externalUrl).join(', '))
+ );
expect(fetchVideos).toHaveBeenCalled();
});
diff --git a/src/editors/containers/VideoEditor/components/VideoEditorModal.test.tsx b/src/editors/containers/VideoEditor/components/VideoEditorModal.test.tsx
index 296d59c89f..9285515045 100644
--- a/src/editors/containers/VideoEditor/components/VideoEditorModal.test.tsx
+++ b/src/editors/containers/VideoEditor/components/VideoEditorModal.test.tsx
@@ -66,19 +66,20 @@ describe('VideoUploader', () => {
});
});
- const renderComponent = async () => render(
-
-
-
-
-
-
- ,
- );
+ const renderComponent = async () =>
+ render(
+
+
+
+
+
+
+ ,
+ );
it('should render the component and call loadVideoData with correct parameters', async () => {
await renderComponent();
diff --git a/src/editors/containers/VideoEditor/components/VideoEditorModal.tsx b/src/editors/containers/VideoEditor/components/VideoEditorModal.tsx
index 55d36c3556..c03d0f2639 100644
--- a/src/editors/containers/VideoEditor/components/VideoEditorModal.tsx
+++ b/src/editors/containers/VideoEditor/components/VideoEditorModal.tsx
@@ -7,7 +7,7 @@ import VideoSettingsModal from './VideoSettingsModal';
import { RequestKeys } from '../../../data/constants/requests';
interface Props {
- onReturn?: (() => void);
+ onReturn?: () => void;
isLibrary: boolean;
onClose?: (() => void) | null;
}
@@ -47,11 +47,12 @@ const VideoEditorModal: React.FC = ({
}, [isLoaded, dispatch, selectedVideoId, selectedVideoUrl]);
return (
-
);
// TODO: add logic to show SelectVideoModal if no selection
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/ErrorSummary.test.tsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/ErrorSummary.test.tsx
index 938f9bf7cf..773528612e 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/ErrorSummary.test.tsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/ErrorSummary.test.tsx
@@ -1,6 +1,8 @@
import React from 'react';
import {
- render, screen, initializeMocks,
+ render,
+ screen,
+ initializeMocks,
} from '@src/testUtils';
import * as mod from './ErrorSummary';
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/hooks.js b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/hooks.js
index ba84d31dfa..262ea94fda 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/hooks.js
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/hooks.js
@@ -24,14 +24,15 @@ export const durationWidget = ({ duration, updateField }) => {
return {
unsavedDuration,
onBlur: (index) => (
- (e) => module.updateDuration({
- duration,
- setDuration,
- unsavedDuration,
- setUnsavedDuration,
- index,
- inputString: e.target.value,
- })
+ (e) =>
+ module.updateDuration({
+ duration,
+ setDuration,
+ unsavedDuration,
+ setUnsavedDuration,
+ index,
+ inputString: e.target.value,
+ })
),
onChange: (index) => (
(e) => setUnsavedDuration(module.onDurationChange(unsavedDuration, index, e.target.value))
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/hooks.test.js b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/hooks.test.js
index f05de3fbbd..4c7bbdb6ab 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/hooks.test.js
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/hooks.test.js
@@ -8,7 +8,7 @@ jest.mock('react', () => {
return {
...jest.requireActual('react'),
updateState,
- useState: jest.fn(val => ([{ state: val }, (newVal) => updateState({ val, newVal })])),
+ useState: jest.fn(val => [{ state: val }, (newVal) => updateState({ val, newVal })]),
useCallback: (cb, prereqs) => ({ useCallback: { cb, prereqs } }),
useEffect: jest.fn(),
};
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/hooks.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/hooks.jsx
index 7f65b2e326..751da883d3 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/hooks.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/hooks.jsx
@@ -40,12 +40,14 @@ export const fileInput = ({ fileSizeError }) => {
const click = () => ref.current.click();
const addFile = (e) => {
const file = e.target.files[0];
- if (file && module.checkValidFileSize({
- file,
- onSizeFail: () => {
- fileSizeError.set();
- },
- })) {
+ if (
+ file && module.checkValidFileSize({
+ file,
+ onSizeFail: () => {
+ fileSizeError.set();
+ },
+ })
+ ) {
dispatch(thunkActions.video.uploadHandout({
file,
}));
@@ -70,5 +72,8 @@ export const fileSizeError = () => {
};
export default {
- fileInput, fileSizeError, parseHandoutName, checkValidFileSize,
+ fileInput,
+ fileSizeError,
+ parseHandoutName,
+ checkValidFileSize,
};
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/index.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/index.jsx
index 0f0b60bee4..78486b0c63 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/index.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/index.jsx
@@ -42,70 +42,74 @@ const HandoutWidget = ({
const handoutName = hooks.parseHandoutName({ handout });
const downloadLink = getHandoutDownloadUrl({ handout });
- return (!isLibrary ? (
-
-
-
-
-
-
- {handout ? (
-
-
- {handoutName}
-
-
-
-
-
-
-
-
-
-
- updateField({ handout: null })}>
-
-
-
-
-
-
-
- ) : (
-
-
-
-
-
-
- )}
-
- ) : null);
+
+
+
+
+
+ {handout ?
+ (
+
+
+ {handoutName}
+
+
+
+
+
+
+
+
+
+
+ updateField({ handout: null })}>
+
+
+
+
+
+
+
+ ) :
+ (
+
+
+
+
+
+
+ )}
+
+ ) :
+ null);
};
HandoutWidget.propTypes = {
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/index.test.tsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/index.test.tsx
index fe32314514..6aba1a65d5 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/index.test.tsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/index.test.tsx
@@ -10,7 +10,9 @@ jest.mock('@src/editors/data/redux', () => ({
},
selectors: {
video: {
- getHandoutDownloadUrl: jest.fn(args => ({ getHandoutDownloadUrl: args })).mockName('selectors.video.getHandoutDownloadUrl'),
+ getHandoutDownloadUrl: jest.fn(args => ({ getHandoutDownloadUrl: args })).mockName(
+ 'selectors.video.getHandoutDownloadUrl',
+ ),
handout: jest.fn(state => ({ handout: state })),
},
app: {
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/messages.ts b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/messages.ts
index 4e7114ef70..b75ff9e8dc 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/messages.ts
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
titleLabel: {
id: 'authoring.videoeditor.handout.title.label',
defaultMessage: 'Handout',
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseBlurb.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseBlurb.jsx
index 68e0ce6de2..5d2da6d067 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseBlurb.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseBlurb.jsx
@@ -22,17 +22,31 @@ const LicenseBlurb = ({
}) => (
{/* not sure how to handle the edge cases when some of the icons are not displayed */}
- {license === LicenseTypes.allRightsReserved ?
: null}
- {license === LicenseTypes.creativeCommons ?
: null}
- {details.attribution ?
: null}
+ {license === LicenseTypes.allRightsReserved
+ ?
+ : null}
+ {license === LicenseTypes.creativeCommons
+ ?
+ : null}
+ {details.attribution
+ ?
+ : null}
{details.noncommercial ?
: null}
{details.noDerivatives ?
: null}
{details.shareAlike ?
: null}
{license === LicenseTypes.allRightsReserved
- ?
+ ? (
+
+
+
+ )
: null}
{license === LicenseTypes.creativeCommons
- ?
+ ? (
+
+
+
+ )
: null}
);
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseBlurb.test.tsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseBlurb.test.tsx
index 24c9f207b4..e1d5b894eb 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseBlurb.test.tsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseBlurb.test.tsx
@@ -1,6 +1,8 @@
import React from 'react';
import {
- render, screen, initializeMocks,
+ render,
+ screen,
+ initializeMocks,
} from '@src/testUtils';
import LicenseBlurb from './LicenseBlurb';
@@ -13,7 +15,6 @@ describe('LicenseBlurb', () => {
noncommercial: false,
noDerivatives: false,
shareAlike: false,
-
},
};
@@ -38,17 +39,23 @@ describe('LicenseBlurb', () => {
});
test('renders as expected when details.attribution and details.noncommercial equal true', () => {
- const { container } = render( );
+ const { container } = render(
+ ,
+ );
expect(container.querySelectorAll('span.pgn__icon')).toHaveLength(2);
});
test('renders as expected when details.attribution and details.noDerivatives equal true', () => {
- const { container } = render( );
+ const { container } = render(
+ ,
+ );
expect(container.querySelectorAll('span.pgn__icon')).toHaveLength(2);
});
test('renders as expected when details.attribution and details.shareAlike equal true', () => {
- const { container } = render( );
+ const { container } = render(
+ ,
+ );
expect(container.querySelectorAll('span.pgn__icon')).toHaveLength(2);
});
});
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDetails.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDetails.jsx
index 5f955b63ae..176356c81e 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDetails.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDetails.jsx
@@ -72,12 +72,13 @@ const LicenseDetails = ({
updateField({
- licenseDetails: {
- ...details,
- noncommercial: e.target.checked,
- },
- })}
+ onChange={(e) =>
+ updateField({
+ licenseDetails: {
+ ...details,
+ noncommercial: e.target.checked,
+ },
+ })}
/>
@@ -96,13 +97,14 @@ const LicenseDetails = ({
updateField({
- licenseDetails: {
- ...details,
- noDerivatives: e.target.checked,
- shareAlike: e.target.checked ? false : details.shareAlike,
- },
- })}
+ onChange={(e) =>
+ updateField({
+ licenseDetails: {
+ ...details,
+ noDerivatives: e.target.checked,
+ shareAlike: e.target.checked ? false : details.shareAlike,
+ },
+ })}
/>
@@ -121,13 +123,14 @@ const LicenseDetails = ({
updateField({
- licenseDetails: {
- ...details,
- shareAlike: e.target.checked,
- noDerivatives: e.target.checked ? false : details.noDerivatives,
- },
- })}
+ onChange={(e) =>
+ updateField({
+ licenseDetails: {
+ ...details,
+ shareAlike: e.target.checked,
+ noDerivatives: e.target.checked ? false : details.noDerivatives,
+ },
+ })}
/>
@@ -136,7 +139,8 @@ const LicenseDetails = ({
- ) : null}
+ ) :
+ null}
)
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDetails.test.tsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDetails.test.tsx
index 0bf69f8ac6..9ac015056f 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDetails.test.tsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDetails.test.tsx
@@ -1,6 +1,8 @@
import React from 'react';
import {
- render, screen, initializeMocks,
+ render,
+ screen,
+ initializeMocks,
} from '@src/testUtils';
import { actions } from '../../../../../../data/redux';
@@ -34,7 +36,7 @@ describe('LicenseDetails', () => {
describe('renders', () => {
test('renders as expected with default props', () => {
const { container } = render( );
- const reduxWrapper = (container.firstChild as HTMLElement);
+ const reduxWrapper = container.firstChild as HTMLElement;
expect(reduxWrapper?.innerHTML).toBe('');
expect(screen.queryByText('License Details')).not.toBeInTheDocument();
});
@@ -46,7 +48,7 @@ describe('LicenseDetails', () => {
test('renders as expected with level set to block and license set to select', () => {
const { container } = render( );
- const reduxWrapper = (container.firstChild as HTMLElement);
+ const reduxWrapper = container.firstChild as HTMLElement;
expect(reduxWrapper?.innerHTML).toBe('');
expect(screen.queryByText('License Details')).not.toBeInTheDocument();
});
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDisplay.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDisplay.jsx
index 845b0e5b68..2088db88aa 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDisplay.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDisplay.jsx
@@ -23,7 +23,9 @@ const LicenseDisplay = ({
if (license !== LicenseTypes.select) {
return (
-
+
+
+
{licenseDescription}
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseSelector.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseSelector.jsx
index a8727554da..f89dc5c87d 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseSelector.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseSelector.jsx
@@ -42,26 +42,28 @@ const LicenseSelector = ({
onChange={(e) => onLicenseChange(e.target.value)}
>
{Object.entries(LicenseNames).map(([key, text]) => {
- if (license === key) { return (
{text} ); }
- if (key === LicenseTypes.select) { return (
{text} ); }
- return (
{text} );
+ if (license === key) { return
{text} ; }
+ if (key === LicenseTypes.select) { return
{text} ; }
+ return
{text} ;
})}
- {level !== LicenseLevel.course ? (
- <>
-
-
{
- ref.current.value = courseLicenseType;
- updateField({ licenseType: '', licenseDetails: {} });
- }}
- tooltipPlacement="top"
- tooltipContent={ }
- />
- >
- ) : null }
+ {level !== LicenseLevel.course ?
+ (
+ <>
+
+ {
+ ref.current.value = courseLicenseType;
+ updateField({ licenseType: '', licenseDetails: {} });
+ }}
+ tooltipPlacement="top"
+ tooltipContent={ }
+ />
+ >
+ ) :
+ null}
{levelDescription}
{license === LicenseTypes.select ? null :
}
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseSelector.test.tsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseSelector.test.tsx
index b85057bb38..95bb43a789 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseSelector.test.tsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseSelector.test.tsx
@@ -1,6 +1,9 @@
import React from 'react';
import {
- render, fireEvent, screen, initializeMocks,
+ render,
+ fireEvent,
+ screen,
+ initializeMocks,
} from '@src/testUtils';
import { LicenseSelectorInternal } from './LicenseSelector';
import * as hooks from './hooks';
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/hooks.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/hooks.jsx
index 87f64fd543..d2ff144e57 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/hooks.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/hooks.jsx
@@ -52,7 +52,8 @@ export const determineText = ({ level }) => {
export const onSelectLicense = ({
dispatch,
-}) => (license) => {
+}) =>
+(license) => {
switch (license) {
case LicenseTypes.allRightsReserved:
dispatch(actions.video.updateField({
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/index.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/index.jsx
index a664232b37..c4603ef578 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/index.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/index.jsx
@@ -43,40 +43,44 @@ const LicenseWidget = ({
const { licenseDescription, levelDescription } = hooks.determineText({ level });
return (
{levelDescription}
- )}
+ }
title={intl.formatMessage(messages.title)}
>
- {license ? (
- <>
-
-
-
- >
- ) : null }
- {!licenseType ? (
- <>
-
- updateField({ licenseType: 'select', licenseDetails: {} })}
- >
-
-
- >
- ) : null }
+ {license ?
+ (
+ <>
+
+
+
+ >
+ ) :
+ null}
+ {!licenseType ?
+ (
+ <>
+
+ updateField({ licenseType: 'select', licenseDetails: {} })}
+ >
+
+
+ >
+ ) :
+ null}
);
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/messages.ts b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/messages.ts
index 9c388caa27..12015741e8 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/messages.ts
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
title: {
id: 'authoring.videoeditor.license.title',
defaultMessage: 'License',
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/index.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/index.jsx
index edd5a06077..8ee4e4ef48 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/index.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/index.jsx
@@ -31,7 +31,8 @@ const SocialShareWidget = ({
const intl = useIntl();
const isSetByCourse = allowVideoSharing.level === 'course';
const videoSharingEnabled = isLibrary ? videoSharingEnabledForAll : videoSharingEnabledForCourse;
- const learnMoreLink = videoSharingLearnMoreLink || getExternalLinkUrl('https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html');
+ const learnMoreLink = videoSharingLearnMoreLink ||
+ getExternalLinkUrl('https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html');
const onSocialSharingCheckboxChange = hooks.useTrackSocialSharingChange({ updateField });
const getSubtitle = () => {
@@ -41,42 +42,44 @@ const SocialShareWidget = ({
return intl.formatMessage(messages.disabledSubtitle);
};
- return (videoSharingEnabled ? (
-
-
-
-
-
-
- {intl.formatMessage(messages.socialSharingCheckboxLabel)}
+
+
-
- {isSetByCourse && (
- <>
-
-
+
+
+ {intl.formatMessage(messages.socialSharingCheckboxLabel)}
-
-
-
- >
- )}
-
-
- {intl.formatMessage(messages.learnMoreLinkLabel)}
-
-
-
- ) : null);
+
+ {isSetByCourse && (
+ <>
+
+
+
+
+
+
+ >
+ )}
+
+
+ {intl.formatMessage(messages.learnMoreLinkLabel)}
+
+
+
+ ) :
+ null);
};
SocialShareWidget.defaultProps = {
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/index.test.tsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/index.test.tsx
index b93e847a1d..394cebbe63 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/index.test.tsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/index.test.tsx
@@ -1,6 +1,8 @@
import React from 'react';
import {
- render, screen, initializeMocks,
+ render,
+ screen,
+ initializeMocks,
fireEvent,
} from '@src/testUtils';
@@ -76,25 +78,29 @@ describe('SocialShareWidget', () => {
describe('and allowVideoSharing value equals true', () => {
describe(' with level equal to course', () => {
it('should have setting location message', () => {
- render(
);
+ render(
+
,
+ );
expect(screen.getByText('Change this setting on the course outline page.')).toBeInTheDocument();
});
it('should have checkbox disabled prop equal true', () => {
- render(
);
+ render(
+
,
+ );
const checkbox = screen.getByRole('checkbox', { name: 'This video is shareable to social media' });
expect(checkbox).toBeInTheDocument();
expect(checkbox).toBeDisabled();
@@ -102,36 +108,43 @@ describe('SocialShareWidget', () => {
});
describe(' with level equal to block', () => {
it('should not have setting location message', () => {
- render(
);
+ render(
+
,
+ );
expect(screen.queryByText('Change this setting on the course outline page.')).not.toBeInTheDocument();
});
it('should not have override note', () => {
- render(
);
- expect(screen.queryByText('Note: This setting is overridden by the course outline page.')).not.toBeInTheDocument();
+ render(
+
,
+ );
+ expect(screen.queryByText('Note: This setting is overridden by the course outline page.')).not
+ .toBeInTheDocument();
});
it('should have checkbox disabled prop equal false', () => {
- render(
);
+ render(
+
,
+ );
const checkbox = screen.getByRole('checkbox', { name: 'This video is shareable to social media' });
expect(checkbox).toBeInTheDocument();
expect(checkbox).not.toBeDisabled();
@@ -139,53 +152,62 @@ describe('SocialShareWidget', () => {
});
describe('isLibrary equals true', () => {
it('should not have setting location message', () => {
- render(
);
+ render(
+
,
+ );
expect(screen.queryByText('Change this setting on the course outline page.')).not.toBeInTheDocument();
});
it('should not have override note', () => {
- render(
);
- expect(screen.queryByText('Note: This setting is overridden by the course outline page.')).not.toBeInTheDocument();
+ render(
+
,
+ );
+ expect(screen.queryByText('Note: This setting is overridden by the course outline page.')).not
+ .toBeInTheDocument();
});
it('should have checkbox disabled prop equal false', () => {
- render(
);
+ render(
+
,
+ );
const checkbox = screen.getByRole('checkbox', { name: 'This video is shareable to social media' });
expect(checkbox).toBeInTheDocument();
expect(checkbox).not.toBeDisabled();
});
});
it('should have subtitle with text that reads Enabled', () => {
- render(
);
+ render(
+
,
+ );
expect(screen.getByText('Social Sharing')).toBeInTheDocument();
fireEvent.click(screen.getByText('Social Sharing'));
const subtitle = screen.getByText('Enabled');
@@ -196,25 +218,29 @@ describe('SocialShareWidget', () => {
describe('and allowVideoSharing value equals false', () => {
describe(' with level equal to course', () => {
it('should have setting location message', () => {
- render(
);
+ render(
+
,
+ );
expect(screen.getByText('Change this setting on the course outline page.')).toBeInTheDocument();
});
it('should have checkbox disabled prop equal true', () => {
- render(
);
+ render(
+
,
+ );
const checkbox = screen.getByRole('checkbox', { name: 'This video is shareable to social media' });
expect(checkbox).toBeInTheDocument();
expect(checkbox).toBeDisabled();
@@ -223,36 +249,43 @@ describe('SocialShareWidget', () => {
describe(' with level equal to block', () => {
it('should not have setting location message', () => {
- render(
);
+ render(
+
,
+ );
expect(screen.queryByText('Change this setting on the course outline page.')).not.toBeInTheDocument();
});
it('should not have override note', () => {
- render(
);
- expect(screen.queryByText('Note: This setting is overridden by the course outline page.')).not.toBeInTheDocument();
+ render(
+
,
+ );
+ expect(screen.queryByText('Note: This setting is overridden by the course outline page.')).not
+ .toBeInTheDocument();
});
it('should have checkbox disabled prop equal false', () => {
- render(
);
+ render(
+
,
+ );
const checkbox = screen.getByRole('checkbox', { name: 'This video is shareable to social media' });
expect(checkbox).toBeInTheDocument();
expect(checkbox).toBeEnabled();
@@ -261,53 +294,62 @@ describe('SocialShareWidget', () => {
describe('isLibrary equals true', () => {
it('should not have setting location message', () => {
- render(
);
+ render(
+
,
+ );
expect(screen.queryByText('Change this setting on the course outline page.')).not.toBeInTheDocument();
});
it('should not have override note', () => {
- render(
);
- expect(screen.queryByText('Note: This setting is overridden by the course outline page.')).not.toBeInTheDocument();
+ render(
+
,
+ );
+ expect(screen.queryByText('Note: This setting is overridden by the course outline page.')).not
+ .toBeInTheDocument();
});
it('should have checkbox disabled prop equal false', () => {
- render(
);
+ render(
+
,
+ );
const checkbox = screen.getByRole('checkbox', { name: 'This video is shareable to social media' });
expect(checkbox).toBeInTheDocument();
expect(checkbox).toBeEnabled();
});
});
it('should have subtitle with text that reads Enabled', () => {
- render(
);
+ render(
+
,
+ );
expect(screen.getByText('Social Sharing')).toBeInTheDocument();
fireEvent.click(screen.getByText('Social Sharing'));
const subtitle = screen.getByText('Disabled');
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.js b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.js
index 6277ac4bd5..8b4c31d3f7 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.js
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.js
@@ -98,12 +98,14 @@ export const fileInput = ({ setThumbnailSrc, imgRef, fileSizeError }) => {
const addFile = (e) => {
const file = e.target.files[0];
const reader = new FileReader();
- if (file && module.checkValidSize({
- file,
- onSizeFail: () => {
- fileSizeError.set();
- },
- })) {
+ if (
+ file && module.checkValidSize({
+ file,
+ onSizeFail: () => {
+ fileSizeError.set();
+ },
+ })
+ ) {
reader.onload = () => {
setThumbnailSrc(reader.result);
const image = imgRef.current;
@@ -149,7 +151,11 @@ export const deleteThumbnail = ({ dispatch }) => () => {
emptyCanvas.height = constants.MAX_HEIGHT;
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, emptyCanvas.width, emptyCanvas.height);
- const file = createResampledFile({ canvasUrl: emptyCanvas.toDataURL(), filename: 'blankThumbnail.png', mimeType: 'image/png' });
+ const file = createResampledFile({
+ canvasUrl: emptyCanvas.toDataURL(),
+ filename: 'blankThumbnail.png',
+ mimeType: 'image/png',
+ });
dispatch(thunkActions.video.uploadThumbnail({ thumbnail: file, emptyCanvas }));
};
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.test.jsx
index d59b541fad..7ce5e11960 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.test.jsx
@@ -43,7 +43,11 @@ describe('state hooks', () => {
describe('createResampledFile', () => {
it('should return resampled file object', () => {
- hook = hooks.createResampledFile({ canvasUrl: 'data:MimETYpe,sOMEUrl', filename: testValue, mimeType: 'sOmEuiMAge' });
+ hook = hooks.createResampledFile({
+ canvasUrl: 'data:MimETYpe,sOMEUrl',
+ filename: testValue,
+ mimeType: 'sOmEuiMAge',
+ });
expect(hook).toEqual(resampledFile);
});
});
@@ -55,7 +59,11 @@ describe('resampleImage', () => {
image.height = '800';
image.width = '800';
hook = hooks.resampleImage({ image, filename: testValue });
- expect(spy).toHaveBeenCalledWith({ canvasUrl: 'data:image/png;base64,00', filename: testValue, mimeType: 'image/png' });
+ expect(spy).toHaveBeenCalledWith({
+ canvasUrl: 'data:image/png;base64,00',
+ filename: testValue,
+ mimeType: 'image/png',
+ });
expect(spy.mock.calls.length).toEqual(1);
expect(spy).toHaveReturnedWith(resampledFile);
expect(hook).toEqual(['data:image/png;base64,00', resampledFile]);
@@ -139,9 +147,12 @@ describe('fileInput', () => {
const testFile = new File([selectedFileSuccess], 'sOMEUrl.jpg');
hooks.deleteThumbnail({ dispatch })();
expect(dispatch).toHaveBeenNthCalledWith(1, actions.video.updateField({ thumbnail: null }));
- expect(dispatch).toHaveBeenNthCalledWith(2, thunkActions.video.uploadThumbnail({
- thumbnail: testFile,
- emptyCanvas: true,
- }));
+ expect(dispatch).toHaveBeenNthCalledWith(
+ 2,
+ thunkActions.video.uploadThumbnail({
+ thumbnail: testFile,
+ emptyCanvas: true,
+ }),
+ );
});
});
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.jsx
index 41b7c3617b..95d00b6dcd 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.jsx
@@ -58,68 +58,72 @@ const ThumbnailWidget = ({
}
return intl.formatMessage(messages.unavailableSubtitle);
};
- return (!isLibrary && edxVideo ? (
-
-
-
-
- {!allowThumbnailUpload && (
-
-
-
- )}
- {thumbnail ? (
-
-
- {allowThumbnailUpload && (
-
+
+
+
+ {!allowThumbnailUpload && (
+
+
+
+ )}
+ {thumbnail ?
+ (
+
+
+ {allowThumbnailUpload && (
+
+ )}
+
+ ) :
+ (
+
+
+
+
+
+
+
)}
-
- ) : (
-
-
-
-
-
-
-
- )}
-
- ) : null);
+
+ ) :
+ null);
};
ThumbnailWidget.propTypes = {
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.test.tsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.test.tsx
index 3042763775..8313e71150 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.test.tsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.test.tsx
@@ -22,7 +22,7 @@ jest.mock('../../../../../../data/redux', () => ({
}));
jest.mock('../../../../../../data/services/cms/api', () => ({
- isEdxVideo: (args) => (args),
+ isEdxVideo: (args) => args,
}));
describe('ThumbnailWidget', () => {
@@ -57,7 +57,9 @@ describe('ThumbnailWidget', () => {
expect(screen.getByRole('img', { name: 'Image used as thumbnail for video' })).toBeInTheDocument();
});
test('snapshots: renders as expected where thumbnail uploads are allowed', () => {
- const { container } = render(
);
+ const { container } = render(
+
,
+ );
const reduxWrapper = container.getRootNode();
expect(reduxWrapper.textContent).toBe(null);
});
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/messages.ts b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/messages.ts
index e930448cbe..63e798e287 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/messages.ts
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
title: {
id: 'authoring.videoeditor.thumbnail.title',
defaultMessage: 'Thumbnail',
@@ -24,8 +23,7 @@ const messages = defineMessages({
},
unavailableMessage: {
id: 'authoring.videoeditor.thumbnail.unavailable.message',
- defaultMessage:
- 'Select a video from your library to enable this feature (applies only to courses that run on the edx.org site).',
+ defaultMessage: 'Select a video from your library to enable this feature (applies only to courses that run on the edx.org site).',
description: 'Message for unavailable thumbnail widget',
},
uploadButtonLabel: {
@@ -55,10 +53,8 @@ const messages = defineMessages({
},
fileSizeError: {
id: 'authoring.videoeditor.thumbnail.error.fileSizeError',
- defaultMessage:
- 'The file size for thumbnails must be larger than 2 KB or less than 2 MB. Please resize your image and try again.',
- description:
- ' Message presented to user when file size of image is less than 2 KB or larger than 2 MB',
+ defaultMessage: 'The file size for thumbnails must be larger than 2 KB or less than 2 MB. Please resize your image and try again.',
+ description: ' Message presented to user when file size of image is less than 2 KB or larger than 2 MB',
},
});
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/ImportTranscriptCard.test.tsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/ImportTranscriptCard.test.tsx
index 51be872556..e20fcc5faa 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/ImportTranscriptCard.test.tsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/ImportTranscriptCard.test.tsx
@@ -1,6 +1,9 @@
import React from 'react';
import {
- render, screen, fireEvent, initializeMocks,
+ render,
+ screen,
+ fireEvent,
+ initializeMocks,
} from '@src/testUtils';
import { ImportTranscriptCardInternal as ImportTranscriptCard } from './ImportTranscriptCard';
@@ -25,7 +28,8 @@ describe('ImportTranscriptCard (RTL)', () => {
,
);
expect(screen.getByText('Import transcript from YouTube?')).toBeInTheDocument();
- expect(screen.getByText('We found transcript for this video on YouTube. Would you like to import it now?')).toBeInTheDocument();
+ expect(screen.getByText('We found transcript for this video on YouTube. Would you like to import it now?'))
+ .toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Import Transcript' })).toBeInTheDocument();
});
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/LanguageSelector.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/LanguageSelector.jsx
index 058a74a445..ad03a9f493 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/LanguageSelector.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/LanguageSelector.jsx
@@ -18,8 +18,12 @@ import messages from './messages';
export const hooks = {
onSelectLanguage: ({
- dispatch, languageBeforeChange, triggerupload, setLocalLang,
- }) => ({ newLang }) => {
+ dispatch,
+ languageBeforeChange,
+ triggerupload,
+ setLocalLang,
+ }) =>
+ ({ newLang }) => {
// IF Language is unset, set language and begin upload prompt.
setLocalLang(newLang);
if (languageBeforeChange === '') {
@@ -29,7 +33,8 @@ export const hooks = {
// Else: update language
dispatch(
thunkActions.video.updateTranscriptLanguage({
- newLanguageCode: newLang, languageBeforeChange,
+ newLanguageCode: newLang,
+ languageBeforeChange,
}),
);
},
@@ -41,7 +46,6 @@ export const hooks = {
language: localLang,
}));
},
-
};
const LanguageSelector = ({
@@ -53,7 +57,10 @@ const LanguageSelector = ({
const [localLang, setLocalLang] = React.useState(language);
const input = fileInput({ onAddFile: hooks.addFileCallback({ dispatch: useDispatch(), localLang }) });
const onLanguageChange = hooks.onSelectLanguage({
- dispatch: useDispatch(), languageBeforeChange: localLang, setLocalLang, triggerupload: input.click,
+ dispatch: useDispatch(),
+ languageBeforeChange: localLang,
+ setLocalLang,
+ triggerupload: input.click,
});
const getTitle = () => {
@@ -64,7 +71,6 @@ const LanguageSelector = ({
-
);
}
return (
@@ -77,10 +83,7 @@ const LanguageSelector = ({
return (
<>
-
-
+
{Object.entries(videoTranscriptLanguages).map(([lang, text]) => {
if (language === lang) {
- return {text} ;
+ return (
+
+ {text}
+
+
+ );
}
if (openLanguages.some(row => row.includes(lang))) {
return (
onLanguageChange({ newLang: lang })}>{text}
);
}
- return ({text} );
+ return {text} ;
})}
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/LanguageSelector.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/LanguageSelector.test.jsx
index 360455f737..0e0270678f 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/LanguageSelector.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/LanguageSelector.test.jsx
@@ -1,6 +1,9 @@
import React from 'react';
import {
- render, screen, initializeMocks, fireEvent,
+ render,
+ screen,
+ initializeMocks,
+ fireEvent,
} from '@src/testUtils';
import { useDispatch } from 'react-redux';
import LanguageSelector from './LanguageSelector';
@@ -32,7 +35,9 @@ jest.mock('../../../../../../data/constants/video', () => ({
jest.mock('../../../../../../data/redux', () => ({
thunkActions: {
video: {
- updateTranscriptLanguage: jest.fn((args) => ({ updateTranscriptLanguage: args })).mockName('thunkActions.video.updateTranscriptLanguage'),
+ updateTranscriptLanguage: jest.fn((args) => ({ updateTranscriptLanguage: args })).mockName(
+ 'thunkActions.video.updateTranscriptLanguage',
+ ),
uploadTranscript: jest.fn().mockName('thunkActions.video.uploadTranscript'),
},
},
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/Transcript.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/Transcript.jsx
index 1d28e7d1aa..d25d63c2af 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/Transcript.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/Transcript.jsx
@@ -26,7 +26,7 @@ import messages from './messages';
export const hooks = {
state: {
- // eslint-disable-next-line react-hooks/rules-of-hooks
+ // eslint-disable-next-line react-hooks/rules-of-hooks
inDeleteConfirmation: (args) => React.useState(args),
},
setUpDeleteConfirmation: () => {
@@ -53,7 +53,7 @@ const Transcript = ({
{inDeleteConfirmation
? (
- )} />
+ } />
@@ -84,20 +84,22 @@ const Transcript = ({
language={language}
/>
- { language === '' ? (
- launchDeleteConfirmation()}
- />
- ) : (
-
- )}
+ {language === '' ?
+ (
+ launchDeleteConfirmation()}
+ />
+ ) :
+ (
+
+ )}
)}
>
@@ -115,8 +117,7 @@ Transcript.propTypes = {
deleteTranscript: PropTypes.func.isRequired,
};
-export const mapStateToProps = () => ({
-});
+export const mapStateToProps = () => ({});
export const mapDispatchToProps = {
deleteTranscript: thunkActions.video.deleteTranscript,
};
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/Transcript.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/Transcript.test.jsx
index b091d383b4..003c11bc45 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/Transcript.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/Transcript.test.jsx
@@ -1,6 +1,9 @@
import React from 'react';
import {
- render, fireEvent, screen, initializeMocks,
+ render,
+ fireEvent,
+ screen,
+ initializeMocks,
} from 'CourseAuthoring/testUtils';
import { TranscriptInternal, hooks } from './Transcript';
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/TranscriptActionMenu.test.tsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/TranscriptActionMenu.test.tsx
index d7e2d4840c..d9e063be64 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/TranscriptActionMenu.test.tsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/TranscriptActionMenu.test.tsx
@@ -1,6 +1,9 @@
import React from 'react';
import {
- render, screen, initializeMocks, fireEvent,
+ render,
+ screen,
+ initializeMocks,
+ fireEvent,
} from '@src/testUtils';
import { thunkActions, selectors } from '../../../../../../data/redux';
@@ -21,14 +24,20 @@ jest.mock('../../../../../../data/redux', () => ({
thunkActions: {
video: {
deleteTranscript: jest.fn().mockName('thunkActions.video.deleteTranscript'),
- replaceTranscript: jest.fn((args) => ({ replaceTranscript: args })).mockName('thunkActions.video.replaceTranscript'),
+ replaceTranscript: jest.fn((args) => ({ replaceTranscript: args })).mockName(
+ 'thunkActions.video.replaceTranscript',
+ ),
downloadTranscript: jest.fn().mockName('thunkActions.video.downloadTranscript'),
},
},
selectors: {
video: {
- getTranscriptDownloadUrl: jest.fn(args => ({ getTranscriptDownloadUrl: args })).mockName('selectors.video.getTranscriptDownloadUrl'),
- buildTranscriptUrl: jest.fn(args => ({ buildTranscriptUrl: args })).mockName('selectors.video.buildTranscriptUrl'),
+ getTranscriptDownloadUrl: jest.fn(args => ({ getTranscriptDownloadUrl: args })).mockName(
+ 'selectors.video.getTranscriptDownloadUrl',
+ ),
+ buildTranscriptUrl: jest.fn(args => ({ buildTranscriptUrl: args })).mockName(
+ 'selectors.video.buildTranscriptUrl',
+ ),
},
},
}));
@@ -50,7 +59,8 @@ describe('TranscriptActionMenu', () => {
test('it dispatches the correct thunk', () => {
const cb = componentModule.hooks.replaceFileCallback({
- dispatch: mockDispatch, language: lang1Code,
+ dispatch: mockDispatch,
+ language: lang1Code,
});
cb(mockEvent);
expect(thunkActions.video.replaceTranscript).toHaveBeenCalledWith(result);
@@ -66,7 +76,9 @@ describe('TranscriptActionMenu', () => {
launchDeleteConfirmation: jest.fn().mockName('launchDeleteConfirmation'),
// redux
getTranscriptDownloadUrl: jest.fn().mockName('selectors.video.getTranscriptDownloadUrl'),
- buildTranscriptUrl: jest.fn().mockName('selectors.video.buildTranscriptUrl').mockImplementation((url) => url.transcriptUrl),
+ buildTranscriptUrl: jest.fn().mockName('selectors.video.buildTranscriptUrl').mockImplementation((url) =>
+ url.transcriptUrl
+ ),
};
beforeEach(() => {
initializeMocks();
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/index.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/index.jsx
index cf18123e61..4c819ea4d3 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/index.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/index.jsx
@@ -37,7 +37,7 @@ import * as module from './index';
export const hooks = {
updateErrors: ({ isUploadError, isDeleteError }) => {
- // eslint-disable-next-line react-hooks/rules-of-hooks
+ // eslint-disable-next-line react-hooks/rules-of-hooks
const [error, setError] = React.useContext(ErrorContext).transcripts;
if (isUploadError) {
setError({ ...error, uploadError: messages.uploadTranscriptError.defaultMessage });
@@ -108,11 +108,11 @@ const TranscriptWidget = ({
{intl.formatMessage(messages.title)}
- )}
+ }
>
{intl.formatMessage(messages.videoCreationWarning)}
@@ -143,57 +143,59 @@ const TranscriptWidget = ({
- {hasTranscripts ? (
-
- {transcripts.map((language, index) => (
-
- ))}
-
+ {hasTranscripts ?
+ (
+
+ {transcripts.map((language, index) => (
+
+ ))}
+
+ updateField({ allowTranscriptDownloads: e.target.checked })}
+ >
+
+
+
+
+
+
+
+ }
+ >
+
+
+
+
updateField({ allowTranscriptDownloads: e.target.checked })}
+ checked={showTranscriptByDefault}
+ className="mt-3 decorative-control-label"
+ onChange={(e) => updateField({ showTranscriptByDefault: e.target.checked })}
>
-
+
-
-
-
- )}
- >
-
-
-
-
- updateField({ showTranscriptByDefault: e.target.checked })}
- >
-
-
-
-
-
- ) : (
- <>
-
- {showImportCard && allowTranscriptImport
- ?
- : null}
- >
- )}
+
+ ) :
+ (
+ <>
+
+ {showImportCard && allowTranscriptImport
+ ?
+ : null}
+ >
+ )}
({
@@ -42,7 +47,10 @@ jest.mock('../../../../../../data/redux', () => ({
},
},
}));
-jest.mock('../../../../../../sharedComponents/CollapsibleFormWidget/CollapsibleFormWidget', () => 'CollapsibleFormWidget');
+jest.mock(
+ '../../../../../../sharedComponents/CollapsibleFormWidget/CollapsibleFormWidget',
+ () => 'CollapsibleFormWidget',
+);
jest.mock('./Transcript', () => 'Transcript');
jest.mock('react-redux', () => ({
@@ -123,12 +131,14 @@ describe('TranscriptWidget', () => {
test('renders as expected with default props', () => {
const { container } = render( );
expect(container.querySelector('collapsibleformwidget')).toBeInTheDocument();
- expect(screen.getByText('Add video transcripts (.srt files only) for improved accessibility.')).toBeInTheDocument();
+ expect(screen.getByText('Add video transcripts (.srt files only) for improved accessibility.'))
+ .toBeInTheDocument();
});
test('renders as expected with allowTranscriptImport true', () => {
render( );
- expect(screen.getByText('We found transcript for this video on YouTube. Would you like to import it now?')).toBeInTheDocument();
+ expect(screen.getByText('We found transcript for this video on YouTube. Would you like to import it now?'))
+ .toBeInTheDocument();
});
test('renders as expected with transcripts', () => {
@@ -138,7 +148,9 @@ describe('TranscriptWidget', () => {
});
test('renders as expected with transcripts and urls', () => {
- const { container } = render( );
+ const { container } = render(
+ ,
+ );
expect(container.querySelector('transcript')).toBeInTheDocument();
expect(container.querySelector('transcript')).toHaveAttribute('language', 'en');
expect(container.querySelector('transcript')).toHaveAttribute('transcriptUrl', 'url');
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/messages.ts b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/messages.ts
index 0d13bce210..3f9b86ea9c 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/messages.ts
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
title: {
id: 'authoring.videoeditor.transcripts.title',
defaultMessage: 'Transcripts',
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoPreviewWidget/index.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoPreviewWidget/index.jsx
index 610984556e..f53d2debe4 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoPreviewWidget/index.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoPreviewWidget/index.jsx
@@ -1,6 +1,9 @@
import { useIntl } from '@edx/frontend-platform/i18n';
import {
- Collapsible, Image, Stack, Hyperlink,
+ Collapsible,
+ Image,
+ Stack,
+ Hyperlink,
} from '@openedx/paragon';
import PropTypes from 'prop-types';
import React from 'react';
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/index.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/index.jsx
index 1ea0b2c7ef..9dec19ca33 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/index.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/index.jsx
@@ -96,27 +96,29 @@ const VideoSourceWidget = () => {
- {fallbackVideos.formValue.length > 0 ? fallbackVideos.formValue.map((videoUrl, index) => (
- // eslint-disable-next-line react/no-array-index-key
-
-
-
- deleteFallbackVideo(index)}
- />
-
-
- )) : null}
+ {fallbackVideos.formValue.length > 0 ?
+ fallbackVideos.formValue.map((videoUrl, index) => (
+ // eslint-disable-next-line react/no-array-index-key
+
+
+
+ deleteFallbackVideo(index)}
+ />
+
+
+ )) :
+ null}
{
- )}
+ }
>
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/index.test.tsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/index.test.tsx
index de02953efe..34289efc88 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/index.test.tsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/index.test.tsx
@@ -1,6 +1,9 @@
import React from 'react';
import {
- render, screen, fireEvent, initializeMocks,
+ render,
+ screen,
+ fireEvent,
+ initializeMocks,
} from '@src/testUtils';
import VideoSourceWidget from '.';
import * as hooks from './hooks';
@@ -23,13 +26,22 @@ describe('VideoSourceWidget', () => {
it('renders all main fields and labels', () => {
widgetValuesSpy.mockReturnValue({
videoId: {
- onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
+ onChange: jest.fn(),
+ onBlur: jest.fn(),
+ local: '',
+ formValue: '',
},
videoSource: {
- onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
+ onChange: jest.fn(),
+ onBlur: jest.fn(),
+ local: '',
+ formValue: '',
},
fallbackVideos: {
- formValue: [], onChange: jest.fn(), onBlur: jest.fn(), local: [],
+ formValue: [],
+ onChange: jest.fn(),
+ onBlur: jest.fn(),
+ local: [],
},
allowVideoDownloads: { local: false, onCheckedChange: jest.fn() },
});
@@ -57,13 +69,22 @@ describe('VideoSourceWidget', () => {
const updateVideoId = jest.fn();
widgetValuesSpy.mockReturnValue({
videoId: {
- onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
+ onChange: jest.fn(),
+ onBlur: jest.fn(),
+ local: '',
+ formValue: '',
},
videoSource: {
- onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
+ onChange: jest.fn(),
+ onBlur: jest.fn(),
+ local: '',
+ formValue: '',
},
fallbackVideos: {
- formValue: [], onChange: jest.fn(), onBlur: jest.fn(), local: [],
+ formValue: [],
+ onChange: jest.fn(),
+ onBlur: jest.fn(),
+ local: [],
},
allowVideoDownloads: { local: false, onCheckedChange: jest.fn() },
});
@@ -89,13 +110,22 @@ describe('VideoSourceWidget', () => {
const updateVideoURL = jest.fn();
widgetValuesSpy.mockReturnValue({
videoId: {
- onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
+ onChange: jest.fn(),
+ onBlur: jest.fn(),
+ local: '',
+ formValue: '',
},
videoSource: {
- onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
+ onChange: jest.fn(),
+ onBlur: jest.fn(),
+ local: '',
+ formValue: '',
},
fallbackVideos: {
- formValue: [], onChange: jest.fn(), onBlur: jest.fn(), local: [],
+ formValue: [],
+ onChange: jest.fn(),
+ onBlur: jest.fn(),
+ local: [],
},
allowVideoDownloads: { local: false, onCheckedChange: jest.fn() },
});
@@ -121,10 +151,16 @@ describe('VideoSourceWidget', () => {
const deleteFallbackVideo = jest.fn();
widgetValuesSpy.mockReturnValue({
videoId: {
- onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
+ onChange: jest.fn(),
+ onBlur: jest.fn(),
+ local: '',
+ formValue: '',
},
videoSource: {
- onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
+ onChange: jest.fn(),
+ onBlur: jest.fn(),
+ local: '',
+ formValue: '',
},
fallbackVideos: {
formValue: ['url1', 'url2'],
@@ -157,13 +193,22 @@ describe('VideoSourceWidget', () => {
const addFallbackVideo = jest.fn();
widgetValuesSpy.mockReturnValue({
videoId: {
- onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
+ onChange: jest.fn(),
+ onBlur: jest.fn(),
+ local: '',
+ formValue: '',
},
videoSource: {
- onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
+ onChange: jest.fn(),
+ onBlur: jest.fn(),
+ local: '',
+ formValue: '',
},
fallbackVideos: {
- formValue: [], onChange: jest.fn(), onBlur: jest.fn(), local: [],
+ formValue: [],
+ onChange: jest.fn(),
+ onBlur: jest.fn(),
+ local: [],
},
allowVideoDownloads: { local: false, onCheckedChange: jest.fn() },
});
@@ -189,13 +234,22 @@ describe('VideoSourceWidget', () => {
const onCheckedChange = jest.fn();
widgetValuesSpy.mockReturnValue({
videoId: {
- onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
+ onChange: jest.fn(),
+ onBlur: jest.fn(),
+ local: '',
+ formValue: '',
},
videoSource: {
- onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
+ onChange: jest.fn(),
+ onBlur: jest.fn(),
+ local: '',
+ formValue: '',
},
fallbackVideos: {
- formValue: [], onChange: jest.fn(), onBlur: jest.fn(), local: [],
+ formValue: [],
+ onChange: jest.fn(),
+ onBlur: jest.fn(),
+ local: [],
},
allowVideoDownloads: { local: false, onCheckedChange },
});
@@ -220,13 +274,22 @@ describe('VideoSourceWidget', () => {
it('shows error alert when videoIdChangeAlert.show is true', () => {
widgetValuesSpy.mockReturnValue({
videoId: {
- onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
+ onChange: jest.fn(),
+ onBlur: jest.fn(),
+ local: '',
+ formValue: '',
},
videoSource: {
- onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
+ onChange: jest.fn(),
+ onBlur: jest.fn(),
+ local: '',
+ formValue: '',
},
fallbackVideos: {
- formValue: [], onChange: jest.fn(), onBlur: jest.fn(), local: [],
+ formValue: [],
+ onChange: jest.fn(),
+ onBlur: jest.fn(),
+ local: [],
},
allowVideoDownloads: { local: false, onCheckedChange: jest.fn() },
});
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/messages.ts b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/messages.ts
index b0d104cc96..bd11383430 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/messages.ts
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
titleLabel: {
id: 'authoring.videoeditor.videoSource.title.label',
defaultMessage: 'Video source',
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/handlers.js b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/handlers.js
index 1c8bb1ff5a..539452464d 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/handlers.js
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/handlers.js
@@ -25,7 +25,8 @@ export const handleIndexTransformEvent = ({
local,
setter,
transform,
-}) => (index) => (
+}) =>
+(index) => (
handler(val => setter(transform(local, index, val)))
);
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/hooks.js b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/hooks.js
index d0b8503e2b..4471d50e55 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/hooks.js
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/hooks.js
@@ -78,11 +78,12 @@ export const updatedObject = (obj, index, val) => ({ ...obj, [index]: val });
* @param {string} key - form key
* @return {func} - callback taking a value and updating the video redux field
*/
-// eslint-disable-next-line react-hooks/rules-of-hooks
-export const updateFormField = ({ dispatch, key }) => useCallback(
- (val) => dispatch(actions.video.updateField({ [key]: val })),
- [],
-);
+export const updateFormField = ({ dispatch, key }) =>
+ // eslint-disable-next-line react-hooks/rules-of-hooks
+ useCallback(
+ (val) => dispatch(actions.video.updateField({ [key]: val })),
+ [],
+ );
/**
* valueHooks({ dispatch, key })
@@ -251,10 +252,11 @@ export const objectWidget = ({ dispatch, key }) => {
* @param {func} dispatch - redux dispatch method
* @return {object} - { : }
*/
-export const widgetValues = ({ fields, dispatch }) => Object.keys(fields).reduce(
- (obj, key) => ({
- ...obj,
- [key]: fields[key]({ key, dispatch }),
- }),
- {},
-);
+export const widgetValues = ({ fields, dispatch }) =>
+ Object.keys(fields).reduce(
+ (obj, key) => ({
+ ...obj,
+ [key]: fields[key]({ key, dispatch }),
+ }),
+ {},
+ );
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/hooks.test.js b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/hooks.test.js
index ebfa493729..4c25c49852 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/hooks.test.js
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/hooks.test.js
@@ -140,9 +140,10 @@ describe('Video Settings modal hooks', () => {
});
});
describe('returned object', () => {
- const mockUpdateFormField = (args) => jest.fn(
- (val) => ({ updateFormField: { args, val } }),
- );
+ const mockUpdateFormField = (args) =>
+ jest.fn(
+ (val) => ({ updateFormField: { args, val } }),
+ );
beforeEach(() => {
jest.spyOn(hooks, keys.hooks.updateFormField)
.mockImplementationOnce(mockUpdateFormField);
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/index.tsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/index.tsx
index 3718b3ca54..8483883908 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/index.tsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/index.tsx
@@ -47,9 +47,7 @@ const VideoSettingsModal: React.FC = ({
- {!isLibrary && (
-
- )}
+ {!isLibrary && }
diff --git a/src/editors/containers/VideoEditor/hooks.ts b/src/editors/containers/VideoEditor/hooks.ts
index 511342e0c4..a4de645de7 100644
--- a/src/editors/containers/VideoEditor/hooks.ts
+++ b/src/editors/containers/VideoEditor/hooks.ts
@@ -35,7 +35,7 @@ export const state = StrictDict({
/* eslint-enable react-hooks/rules-of-hooks */
});
-export const errorsHook = (): { error: ErrorContextData, validateEntry: () => boolean } => {
+export const errorsHook = (): { error: ErrorContextData; validateEntry: () => boolean; } => {
const [durationErrors, setDurationErrors] = state.durationErrors({});
const [handoutErrors, setHandoutErrors] = state.handoutErrors({});
const [licenseErrors, setLicenseErrors] = state.licenseErrors({});
diff --git a/src/editors/containers/VideoEditor/index.tsx b/src/editors/containers/VideoEditor/index.tsx
index 2177c04851..75c9f20d75 100644
--- a/src/editors/containers/VideoEditor/index.tsx
+++ b/src/editors/containers/VideoEditor/index.tsx
@@ -37,25 +37,28 @@ const VideoEditor: React.FC = ({
returnFunction={returnFunction}
validateEntry={validateEntry}
>
- {(isCreateWorkflow || studioViewFinished) ? (
-
-
-
- ) : (
-
-
-
- )}
+ {(isCreateWorkflow || studioViewFinished) ?
+ (
+
+
+
+ ) :
+ (
+
+
+
+ )}
);
diff --git a/src/editors/containers/VideoGallery/hooks.js b/src/editors/containers/VideoGallery/hooks.js
index a65ee30138..22b50b31c9 100644
--- a/src/editors/containers/VideoGallery/hooks.js
+++ b/src/editors/containers/VideoGallery/hooks.js
@@ -10,7 +10,11 @@ import * as appHooks from '../../hooks';
import { selectors } from '../../data/redux';
import analyticsEvt from '../../data/constants/analyticsEvt';
import {
- filterKeys, filterMessages, sortFunctions, sortKeys, sortMessages,
+ filterKeys,
+ filterMessages,
+ sortFunctions,
+ sortKeys,
+ sortMessages,
} from './utils';
export const {
@@ -47,8 +51,10 @@ export const filterListBySearch = ({
searchString,
videoList,
}) => (
- videoList.filter(({ displayName }) => displayName.toLowerCase()
- .includes(searchString.toLowerCase()))
+ videoList.filter(({ displayName }) =>
+ displayName.toLowerCase()
+ .includes(searchString.toLowerCase())
+ )
);
export const filterListByStatus = ({ statusFilter, videoList }) => {
@@ -88,7 +94,7 @@ export const useVideoListProps = ({
videos,
returnFunction,
}) => {
- const [highlighted, setHighlighted] = React.useState(/** @type {string | null} */(null));
+ const [highlighted, setHighlighted] = React.useState(/** @type {string | null} */ (null));
const [
showSelectVideoError,
setShowSelectVideoError,
diff --git a/src/editors/containers/VideoGallery/index.jsx b/src/editors/containers/VideoGallery/index.jsx
index ac25c85268..f5c086448e 100644
--- a/src/editors/containers/VideoGallery/index.jsx
+++ b/src/editors/containers/VideoGallery/index.jsx
@@ -2,7 +2,9 @@ import React, { useCallback, useEffect } from 'react';
import PropTypes from 'prop-types';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
- Image, useToggle, StandardModal,
+ Image,
+ useToggle,
+ StandardModal,
} from '@openedx/paragon';
import { useSearchParams } from 'react-router-dom';
import { useSelector } from 'react-redux';
diff --git a/src/editors/containers/VideoGallery/index.test.jsx b/src/editors/containers/VideoGallery/index.test.jsx
index 6e45a02d27..43b7549056 100644
--- a/src/editors/containers/VideoGallery/index.test.jsx
+++ b/src/editors/containers/VideoGallery/index.test.jsx
@@ -4,7 +4,10 @@ import { configureStore } from '@reduxjs/toolkit';
import '@testing-library/jest-dom';
import React from 'react';
import {
- act, fireEvent, render, screen,
+ act,
+ fireEvent,
+ render,
+ screen,
} from '@testing-library/react';
import * as reactRouterDom from 'react-router-dom';
import * as reduxThunks from '../../data/redux';
@@ -37,7 +40,8 @@ const initialVideos = [
status_nontranslated: 'In Progress',
duration: 2,
transcripts: [],
- }, {
+ },
+ {
edx_video_id: 'id_3',
client_video_id: 'client_id_3',
course_video_image_url: 'course_video_image_url_3',
diff --git a/src/editors/containers/VideoGallery/messages.ts b/src/editors/containers/VideoGallery/messages.ts
index 3dd446b7c9..012bc2ccf7 100644
--- a/src/editors/containers/VideoGallery/messages.ts
+++ b/src/editors/containers/VideoGallery/messages.ts
@@ -2,8 +2,7 @@ const messages = {
// Gallery
emptyGalleryLabel: {
id: 'authoring.selectvideomodal.emptyGalleryLabel',
- defaultMessage:
- 'No results found.',
+ defaultMessage: 'No results found.',
description: 'Label for when video gallery is empty.',
},
selectVideoButtonlabel: {
@@ -101,15 +100,12 @@ const messages = {
selectVideoError: {
id: 'authoring.selectvideomodal.error.selectVideoError',
defaultMessage: 'Select a video to continue.',
- description:
- 'Message presented to user when clicking Next without selecting a video',
+ description: 'Message presented to user when clicking Next without selecting a video',
},
fileSizeError: {
id: 'authoring.selectvideomodal.error.fileSizeError',
- defaultMessage:
- 'Video must be 10 MB or less. Please resize image and try again.',
- description:
- 'Message presented to user when file size of video is larger than 10 MB',
+ defaultMessage: 'Video must be 10 MB or less. Please resize image and try again.',
+ description: 'Message presented to user when file size of video is larger than 10 MB',
},
uploadVideoError: {
id: 'authoring.selectvideomodal.error.uploadVideoError',
diff --git a/src/editors/containers/VideoUploadEditor/VideoUploader.jsx b/src/editors/containers/VideoUploadEditor/VideoUploader.jsx
index e269932fbb..15506343b6 100644
--- a/src/editors/containers/VideoUploadEditor/VideoUploader.jsx
+++ b/src/editors/containers/VideoUploadEditor/VideoUploader.jsx
@@ -2,7 +2,11 @@ import React from 'react';
import PropTypes from 'prop-types';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
- Icon, IconButton, Dropzone, InputGroup, FormControl,
+ Icon,
+ IconButton,
+ Dropzone,
+ InputGroup,
+ FormControl,
} from '@openedx/paragon';
import { ArrowForward, FileUpload, Close } from '@openedx/paragon/icons';
import { useDispatch } from 'react-redux';
@@ -34,9 +38,13 @@ const URLUploader = ({ onUpload }) => {
aria-label={intl.formatMessage(messages.pasteURL)}
aria-describedby="basic-addon2"
borderless
- onClick={(event) => { event.stopPropagation(); }}
- onChange={(event) => { setTextInputValue(event.target.value); }}
- trailingElement={(
+ onClick={(event) => {
+ event.stopPropagation();
+ }}
+ onChange={(event) => {
+ setTextInputValue(event.target.value);
+ }}
+ trailingElement={
{
}
}}
/>
- )}
+ }
/>
diff --git a/src/editors/containers/VideoUploadEditor/VideoUploader.test.jsx b/src/editors/containers/VideoUploadEditor/VideoUploader.test.jsx
index 47157470a1..4838e6936d 100644
--- a/src/editors/containers/VideoUploadEditor/VideoUploader.test.jsx
+++ b/src/editors/containers/VideoUploadEditor/VideoUploader.test.jsx
@@ -1,6 +1,9 @@
import React from 'react';
import {
- render, fireEvent, act, screen,
+ render,
+ fireEvent,
+ act,
+ screen,
} from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { initializeMockApp } from '@edx/frontend-platform';
@@ -42,13 +45,14 @@ describe('VideoUploader', () => {
});
});
- const renderComponent = async (storeParam, setLoadingMockParam) => render(
-
-
-
- ,
- ,
- );
+ const renderComponent = async (storeParam, setLoadingMockParam) =>
+ render(
+
+
+
+ ,
+ ,
+ );
afterEach(() => {
jest.clearAllMocks();
diff --git a/src/editors/containers/VideoUploadEditor/index.jsx b/src/editors/containers/VideoUploadEditor/index.jsx
index 91664d3e0a..20a6db6806 100644
--- a/src/editors/containers/VideoUploadEditor/index.jsx
+++ b/src/editors/containers/VideoUploadEditor/index.jsx
@@ -10,25 +10,28 @@ const VideoUploadEditor = ({ onUpload, onClose }) => {
const [loading, setLoading] = React.useState(false);
const intl = useIntl();
- return (!loading) ? (
-
-
-
- ) : (
-
-
-
- );
+ return (!loading) ?
+ (
+
+
+
+ ) :
+ (
+
+
+
+ );
};
VideoUploadEditor.propTypes = {
diff --git a/src/editors/containers/VideoUploadEditor/index.test.jsx b/src/editors/containers/VideoUploadEditor/index.test.jsx
index 2bb94a813d..a73cd854a0 100644
--- a/src/editors/containers/VideoUploadEditor/index.test.jsx
+++ b/src/editors/containers/VideoUploadEditor/index.test.jsx
@@ -15,13 +15,14 @@ jest.unmock('@openedx/paragon/icons');
describe('VideoUploadEditor', () => {
let store;
- const renderComponent = async (storeParam) => render(
-
-
-
- ,
- ,
- );
+ const renderComponent = async (storeParam) =>
+ render(
+
+
+
+ ,
+ ,
+ );
beforeEach(async () => {
store = configureStore({
diff --git a/src/editors/data/constants/advancedOlxTemplates/index.ts b/src/editors/data/constants/advancedOlxTemplates/index.ts
index 16602efdb2..886e838e88 100644
--- a/src/editors/data/constants/advancedOlxTemplates/index.ts
+++ b/src/editors/data/constants/advancedOlxTemplates/index.ts
@@ -7,5 +7,10 @@ import jsInputResponse from './jsinput_response';
import problemWithHint from './problem_with_hint';
export default StrictDict({
- circuitSchematic, customGrader, formulaResponse, imageResponse, jsInputResponse, problemWithHint,
+ circuitSchematic,
+ customGrader,
+ formulaResponse,
+ imageResponse,
+ jsInputResponse,
+ problemWithHint,
});
diff --git a/src/editors/data/constants/basicProblemTemplates/dropdown.js b/src/editors/data/constants/basicProblemTemplates/dropdown.js
index ec51411e73..cfafbe8bec 100644
--- a/src/editors/data/constants/basicProblemTemplates/dropdown.js
+++ b/src/editors/data/constants/basicProblemTemplates/dropdown.js
@@ -7,12 +7,12 @@ const olx = `
- `
+`;
const markdown = `[[
an incorrect answer
(the correct answer)
an incorrect answer
-]]`
+]]`;
export default { olx, markdown };
diff --git a/src/editors/data/constants/basicProblemTemplates/index.ts b/src/editors/data/constants/basicProblemTemplates/index.ts
index 977d3b7a54..2318367ca4 100644
--- a/src/editors/data/constants/basicProblemTemplates/index.ts
+++ b/src/editors/data/constants/basicProblemTemplates/index.ts
@@ -6,5 +6,9 @@ import singleSelect from './singleSelect';
import textInput from './textInput';
export default StrictDict({
- dropdown, multiSelect, numeric, singleSelect, textInput,
+ dropdown,
+ multiSelect,
+ numeric,
+ singleSelect,
+ textInput,
});
diff --git a/src/editors/data/constants/basicProblemTemplates/multiSelect.js b/src/editors/data/constants/basicProblemTemplates/multiSelect.js
index 7ed6963bbd..f9c6e37e7b 100644
--- a/src/editors/data/constants/basicProblemTemplates/multiSelect.js
+++ b/src/editors/data/constants/basicProblemTemplates/multiSelect.js
@@ -1,5 +1,5 @@
/* eslint-disable */
- const olx= `
+const olx = `
@@ -7,12 +7,12 @@
- `
+ `;
const markdown = `[x] a correct answer
[ ] an incorrect answer
[ ] an incorrect answer
[x] a correct answer
-`
+`;
export default { olx, markdown };
diff --git a/src/editors/data/constants/basicProblemTemplates/numeric.js b/src/editors/data/constants/basicProblemTemplates/numeric.js
index d39c9a6e58..7b7e2648cd 100644
--- a/src/editors/data/constants/basicProblemTemplates/numeric.js
+++ b/src/editors/data/constants/basicProblemTemplates/numeric.js
@@ -4,8 +4,8 @@ const olx = `
- `
+`;
-const markdown = `= 100 +-5`
+const markdown = `= 100 +-5`;
export default { olx, markdown };
diff --git a/src/editors/data/constants/basicProblemTemplates/singleSelect.js b/src/editors/data/constants/basicProblemTemplates/singleSelect.js
index ef4e2f2620..9370242a19 100644
--- a/src/editors/data/constants/basicProblemTemplates/singleSelect.js
+++ b/src/editors/data/constants/basicProblemTemplates/singleSelect.js
@@ -7,11 +7,11 @@ const olx = `
- `
+`;
const markdown = `( ) an incorrect answer
(x) the correct answer
( ) an incorrect answer
-`
+`;
-export default { olx, markdown };
\ No newline at end of file
+export default { olx, markdown };
diff --git a/src/editors/data/constants/basicProblemTemplates/textInput.js b/src/editors/data/constants/basicProblemTemplates/textInput.js
index 7240bfb188..4ccf518b35 100644
--- a/src/editors/data/constants/basicProblemTemplates/textInput.js
+++ b/src/editors/data/constants/basicProblemTemplates/textInput.js
@@ -1,13 +1,13 @@
/* eslint-disable */
-const olx =`
+const olx = `
- `
+ `;
const markdown = `= the correct answer
or= optional acceptable variant of the correct answer
-`
+`;
export default { olx, markdown };
diff --git a/src/editors/data/constants/problem.ts b/src/editors/data/constants/problem.ts
index a0be26389d..3ccc5158c4 100644
--- a/src/editors/data/constants/problem.ts
+++ b/src/editors/data/constants/problem.ts
@@ -9,14 +9,16 @@ import advancedOlxTemplates from './advancedOlxTemplates';
import basicProblemTemplates from './basicProblemTemplates';
import problemMessages from '../../containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/messages';
-export const ProblemTypeKeys = StrictDict({
- SINGLESELECT: 'multiplechoiceresponse',
- MULTISELECT: 'choiceresponse',
- DROPDOWN: 'optionresponse',
- NUMERIC: 'numericalresponse',
- TEXTINPUT: 'stringresponse',
- ADVANCED: 'advanced',
-} as const);
+export const ProblemTypeKeys = StrictDict(
+ {
+ SINGLESELECT: 'multiplechoiceresponse',
+ MULTISELECT: 'choiceresponse',
+ DROPDOWN: 'optionresponse',
+ NUMERIC: 'numericalresponse',
+ TEXTINPUT: 'stringresponse',
+ ADVANCED: 'advanced',
+ } as const,
+);
export type ProblemType = typeof ProblemTypeKeys[keyof typeof ProblemTypeKeys];
/**
@@ -42,7 +44,9 @@ export const getProblemTypes = (formatMessage) => ({
preview: singleSelect,
previewDescription: formatMessage(problemMessages.singleSelectDescription),
description: formatMessage(problemMessages.singleSelectInstruction),
- helpLink: getExternalLinkUrl('https://docs.openedx.org/en/latest/educators/concepts/exercise_tools/about_multi_select.html'),
+ helpLink: getExternalLinkUrl(
+ 'https://docs.openedx.org/en/latest/educators/concepts/exercise_tools/about_multi_select.html',
+ ),
prev: ProblemTypeKeys.TEXTINPUT,
next: ProblemTypeKeys.MULTISELECT,
template: basicProblemTemplates.singleSelect.olx,
@@ -53,7 +57,9 @@ export const getProblemTypes = (formatMessage) => ({
preview: multiSelect,
previewDescription: formatMessage(problemMessages.multiSelectDescription),
description: formatMessage(problemMessages.multiSelectInstruction),
- helpLink: getExternalLinkUrl('https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/add_multi_select.html'),
+ helpLink: getExternalLinkUrl(
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/add_multi_select.html',
+ ),
next: ProblemTypeKeys.DROPDOWN,
prev: ProblemTypeKeys.SINGLESELECT,
template: basicProblemTemplates.multiSelect.olx,
@@ -64,7 +70,9 @@ export const getProblemTypes = (formatMessage) => ({
preview: dropdown,
previewDescription: formatMessage(problemMessages.dropdownDescription),
description: formatMessage(problemMessages.dropdownInstruction),
- helpLink: getExternalLinkUrl('https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/add_dropdown.html'),
+ helpLink: getExternalLinkUrl(
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/add_dropdown.html',
+ ),
next: ProblemTypeKeys.NUMERIC,
prev: ProblemTypeKeys.MULTISELECT,
template: basicProblemTemplates.dropdown.olx,
@@ -75,7 +83,9 @@ export const getProblemTypes = (formatMessage) => ({
preview: numericalInput,
previewDescription: formatMessage(problemMessages.numericalInputDescription),
description: formatMessage(problemMessages.numericalInputInstruction),
- helpLink: getExternalLinkUrl('https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/manage_numerical_input_problem.html'),
+ helpLink: getExternalLinkUrl(
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/manage_numerical_input_problem.html',
+ ),
next: ProblemTypeKeys.TEXTINPUT,
prev: ProblemTypeKeys.DROPDOWN,
template: basicProblemTemplates.numeric.olx,
@@ -86,7 +96,9 @@ export const getProblemTypes = (formatMessage) => ({
preview: textInput,
previewDescription: formatMessage(problemMessages.textInputDescription),
description: formatMessage(problemMessages.textInputInstruction),
- helpLink: getExternalLinkUrl('https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/add_text_input.html'),
+ helpLink: getExternalLinkUrl(
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/add_text_input.html',
+ ),
prev: ProblemTypeKeys.NUMERIC,
next: ProblemTypeKeys.SINGLESELECT,
template: basicProblemTemplates.textInput.olx,
@@ -94,7 +106,7 @@ export const getProblemTypes = (formatMessage) => ({
},
[ProblemTypeKeys.ADVANCED]: {
title: formatMessage(problemMessages.advancedProblemTitle),
- preview: ('
'),
+ preview: '
',
description: formatMessage(problemMessages.advancedProblemDescription),
helpLink: 'something.com',
},
@@ -105,8 +117,11 @@ export const ProblemTypes = StrictDict({
title: 'Single select',
preview: singleSelect,
previewDescription: 'Learners must select the correct answer from a list of possible options.',
- description: 'Enter your single select answers below and select which choices are correct. Learners must choose one correct answer.',
- helpLink: getExternalLinkUrl('https://docs.openedx.org/en/latest/educators/concepts/exercise_tools/about_multi_select.html'),
+ description:
+ 'Enter your single select answers below and select which choices are correct. Learners must choose one correct answer.',
+ helpLink: getExternalLinkUrl(
+ 'https://docs.openedx.org/en/latest/educators/concepts/exercise_tools/about_multi_select.html',
+ ),
prev: ProblemTypeKeys.TEXTINPUT,
next: ProblemTypeKeys.MULTISELECT,
template: basicProblemTemplates.singleSelect.olx,
@@ -116,8 +131,11 @@ export const ProblemTypes = StrictDict({
title: 'Multi-select',
preview: multiSelect,
previewDescription: 'Learners must select all correct answers from a list of possible options.',
- description: 'Enter your multi select answers below and select which choices are correct. Learners must choose all correct answers.',
- helpLink: getExternalLinkUrl('https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/add_multi_select.html'),
+ description:
+ 'Enter your multi select answers below and select which choices are correct. Learners must choose all correct answers.',
+ helpLink: getExternalLinkUrl(
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/add_multi_select.html',
+ ),
next: ProblemTypeKeys.DROPDOWN,
prev: ProblemTypeKeys.SINGLESELECT,
template: basicProblemTemplates.multiSelect.olx,
@@ -127,8 +145,11 @@ export const ProblemTypes = StrictDict({
title: 'Dropdown',
preview: dropdown,
previewDescription: 'Learners must select the correct answer from a list of possible options',
- description: 'Enter your dropdown answers below and select which choice is correct. Learners must select one correct answer.',
- helpLink: getExternalLinkUrl('https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/add_dropdown.html'),
+ description:
+ 'Enter your dropdown answers below and select which choice is correct. Learners must select one correct answer.',
+ helpLink: getExternalLinkUrl(
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/add_dropdown.html',
+ ),
next: ProblemTypeKeys.NUMERIC,
prev: ProblemTypeKeys.MULTISELECT,
template: basicProblemTemplates.dropdown.olx,
@@ -139,7 +160,9 @@ export const ProblemTypes = StrictDict({
preview: numericalInput,
previewDescription: 'Specify one or more correct numeric answers, submitted in a response field.',
description: 'Enter correct numerical input answers below. Learners must enter one correct answer.',
- helpLink: getExternalLinkUrl('https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/manage_numerical_input_problem.html'),
+ helpLink: getExternalLinkUrl(
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/manage_numerical_input_problem.html',
+ ),
next: ProblemTypeKeys.TEXTINPUT,
prev: ProblemTypeKeys.DROPDOWN,
template: basicProblemTemplates.numeric.olx,
@@ -148,9 +171,13 @@ export const ProblemTypes = StrictDict({
[ProblemTypeKeys.TEXTINPUT]: {
title: 'Text input',
preview: textInput,
- previewDescription: 'Specify one or more correct text answers, including numbers and special characters, submitted in a response field.',
- description: 'Enter your text input answers below and select which choices are correct. Learners must enter one correct answer.',
- helpLink: getExternalLinkUrl('https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/add_text_input.html'),
+ previewDescription:
+ 'Specify one or more correct text answers, including numbers and special characters, submitted in a response field.',
+ description:
+ 'Enter your text input answers below and select which choices are correct. Learners must enter one correct answer.',
+ helpLink: getExternalLinkUrl(
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/add_text_input.html',
+ ),
prev: ProblemTypeKeys.NUMERIC,
next: ProblemTypeKeys.SINGLESELECT,
template: basicProblemTemplates.textInput.olx,
@@ -158,21 +185,23 @@ export const ProblemTypes = StrictDict({
},
[ProblemTypeKeys.ADVANCED]: {
title: 'Advanced Problem',
- preview: ('
'),
+ preview: '
',
description: 'An Advanced Problem Type',
helpLink: 'something.com',
},
});
-export const AdvanceProblemKeys = StrictDict({
- BLANK: 'blankadvanced',
- CIRCUITSCHEMATIC: 'circuitschematic',
- JSINPUT: 'jsinputresponse',
- CUSTOMGRADER: 'customgrader',
- IMAGE: 'imageresponse',
- FORMULA: 'formularesponse',
- PROBLEMWITHHINT: 'problemwithhint',
-} as const);
+export const AdvanceProblemKeys = StrictDict(
+ {
+ BLANK: 'blankadvanced',
+ CIRCUITSCHEMATIC: 'circuitschematic',
+ JSINPUT: 'jsinputresponse',
+ CUSTOMGRADER: 'customgrader',
+ IMAGE: 'imageresponse',
+ FORMULA: 'formularesponse',
+ PROBLEMWITHHINT: 'problemwithhint',
+ } as const,
+);
export type AdvancedProblemType = typeof AdvanceProblemKeys[keyof typeof AdvanceProblemKeys];
export function isAdvancedProblemType(pt: ProblemType | AdvancedProblemType): pt is AdvancedProblemType {
@@ -234,135 +263,145 @@ export const getAdvanceProblems = (formatMessage) => ({
},
});
-export const AdvanceProblems = StrictDict({
- [AdvanceProblemKeys.BLANK]: {
- title: 'Blank problem',
- status: '',
- template: ' ',
- },
- [AdvanceProblemKeys.CIRCUITSCHEMATIC]: {
- title: 'Circuit schematic builder',
- status: 'Not supported',
- template: advancedOlxTemplates.circuitSchematic,
- },
- [AdvanceProblemKeys.JSINPUT]: {
- title: 'Custom JavaScript display and grading',
- status: '',
- template: advancedOlxTemplates.jsInputResponse,
- },
- [AdvanceProblemKeys.CUSTOMGRADER]: {
- title: 'Custom Python-evaluated input',
- status: 'Provisional',
- template: advancedOlxTemplates.customGrader,
- },
- [AdvanceProblemKeys.IMAGE]: {
- title: 'Image mapped input',
- status: 'Not supported',
- template: advancedOlxTemplates.imageResponse,
- },
- [AdvanceProblemKeys.FORMULA]: {
- title: 'Math expression input',
- status: '',
- template: advancedOlxTemplates.formulaResponse,
- },
- [AdvanceProblemKeys.PROBLEMWITHHINT]: {
- title: 'Problem with adaptive hint',
- status: 'Not supported',
- template: advancedOlxTemplates.problemWithHint,
- },
-} as const);
+export const AdvanceProblems = StrictDict(
+ {
+ [AdvanceProblemKeys.BLANK]: {
+ title: 'Blank problem',
+ status: '',
+ template: ' ',
+ },
+ [AdvanceProblemKeys.CIRCUITSCHEMATIC]: {
+ title: 'Circuit schematic builder',
+ status: 'Not supported',
+ template: advancedOlxTemplates.circuitSchematic,
+ },
+ [AdvanceProblemKeys.JSINPUT]: {
+ title: 'Custom JavaScript display and grading',
+ status: '',
+ template: advancedOlxTemplates.jsInputResponse,
+ },
+ [AdvanceProblemKeys.CUSTOMGRADER]: {
+ title: 'Custom Python-evaluated input',
+ status: 'Provisional',
+ template: advancedOlxTemplates.customGrader,
+ },
+ [AdvanceProblemKeys.IMAGE]: {
+ title: 'Image mapped input',
+ status: 'Not supported',
+ template: advancedOlxTemplates.imageResponse,
+ },
+ [AdvanceProblemKeys.FORMULA]: {
+ title: 'Math expression input',
+ status: '',
+ template: advancedOlxTemplates.formulaResponse,
+ },
+ [AdvanceProblemKeys.PROBLEMWITHHINT]: {
+ title: 'Problem with adaptive hint',
+ status: 'Not supported',
+ template: advancedOlxTemplates.problemWithHint,
+ },
+ } as const,
+);
-export const ShowAnswerTypesKeys = StrictDict({
- ALWAYS: 'always',
- ANSWERED: 'answered',
- ATTEMPTED: 'attempted',
- CLOSED: 'closed',
- FINISHED: 'finished',
- CORRECT_OR_PAST_DUE: 'correct_or_past_due',
- PAST_DUE: 'past_due',
- NEVER: 'never',
- AFTER_SOME_NUMBER_OF_ATTEMPTS: 'after_attempts',
- AFTER_ALL_ATTEMPTS: 'after_all_attempts',
- AFTER_ALL_ATTEMPTS_OR_CORRECT: 'after_all_attempts_or_correct',
- ATTEMPTED_NO_PAST_DUE: 'attempted_no_past_due',
-} as const);
+export const ShowAnswerTypesKeys = StrictDict(
+ {
+ ALWAYS: 'always',
+ ANSWERED: 'answered',
+ ATTEMPTED: 'attempted',
+ CLOSED: 'closed',
+ FINISHED: 'finished',
+ CORRECT_OR_PAST_DUE: 'correct_or_past_due',
+ PAST_DUE: 'past_due',
+ NEVER: 'never',
+ AFTER_SOME_NUMBER_OF_ATTEMPTS: 'after_attempts',
+ AFTER_ALL_ATTEMPTS: 'after_all_attempts',
+ AFTER_ALL_ATTEMPTS_OR_CORRECT: 'after_all_attempts_or_correct',
+ ATTEMPTED_NO_PAST_DUE: 'attempted_no_past_due',
+ } as const,
+);
-export const ShowAnswerTypes = StrictDict({
- [ShowAnswerTypesKeys.ALWAYS]: {
- id: 'authoring.problemeditor.settings.showanswertype.always',
- defaultMessage: 'Always',
- },
- [ShowAnswerTypesKeys.ANSWERED]: {
- id: 'authoring.problemeditor.settings.showanswertype.answered',
- defaultMessage: 'Answered',
- },
- [ShowAnswerTypesKeys.ATTEMPTED]: {
- id: 'authoring.problemeditor.settings.showanswertype.attempted',
- defaultMessage: 'Attempted or Past Due',
- },
- [ShowAnswerTypesKeys.CLOSED]: {
- id: 'authoring.problemeditor.settings.showanswertype.closed',
- defaultMessage: 'Closed',
- },
- [ShowAnswerTypesKeys.FINISHED]: {
- id: 'authoring.problemeditor.settings.showanswertype.finished',
- defaultMessage: 'Finished',
- },
- [ShowAnswerTypesKeys.CORRECT_OR_PAST_DUE]: {
- id: 'authoring.problemeditor.settings.showanswertype.correct_or_past_due',
- defaultMessage: 'Correct or Past Due',
- },
- [ShowAnswerTypesKeys.PAST_DUE]: {
- id: 'authoring.problemeditor.settings.showanswertype.past_due',
- defaultMessage: 'Past Due',
- },
- [ShowAnswerTypesKeys.NEVER]: {
- id: 'authoring.problemeditor.settings.showanswertype.never',
- defaultMessage: 'Never',
- },
- [ShowAnswerTypesKeys.AFTER_SOME_NUMBER_OF_ATTEMPTS]: {
- id: 'authoring.problemeditor.settings.showanswertype.after_attempts',
- defaultMessage: 'After Some Number of Attempts',
- },
- [ShowAnswerTypesKeys.AFTER_ALL_ATTEMPTS]: {
- id: 'authoring.problemeditor.settings.showanswertype.after_all_attempts',
- defaultMessage: 'After All Attempts',
- },
- [ShowAnswerTypesKeys.AFTER_ALL_ATTEMPTS_OR_CORRECT]: {
- id: 'authoring.problemeditor.settings.showanswertype.after_all_attempts_or_correct',
- defaultMessage: 'After All Attempts or Correct',
- },
- [ShowAnswerTypesKeys.ATTEMPTED_NO_PAST_DUE]: {
- id: 'authoring.problemeditor.settings.showanswertype.attempted_no_past_due',
- defaultMessage: 'Attempted',
- },
-} as const);
+export const ShowAnswerTypes = StrictDict(
+ {
+ [ShowAnswerTypesKeys.ALWAYS]: {
+ id: 'authoring.problemeditor.settings.showanswertype.always',
+ defaultMessage: 'Always',
+ },
+ [ShowAnswerTypesKeys.ANSWERED]: {
+ id: 'authoring.problemeditor.settings.showanswertype.answered',
+ defaultMessage: 'Answered',
+ },
+ [ShowAnswerTypesKeys.ATTEMPTED]: {
+ id: 'authoring.problemeditor.settings.showanswertype.attempted',
+ defaultMessage: 'Attempted or Past Due',
+ },
+ [ShowAnswerTypesKeys.CLOSED]: {
+ id: 'authoring.problemeditor.settings.showanswertype.closed',
+ defaultMessage: 'Closed',
+ },
+ [ShowAnswerTypesKeys.FINISHED]: {
+ id: 'authoring.problemeditor.settings.showanswertype.finished',
+ defaultMessage: 'Finished',
+ },
+ [ShowAnswerTypesKeys.CORRECT_OR_PAST_DUE]: {
+ id: 'authoring.problemeditor.settings.showanswertype.correct_or_past_due',
+ defaultMessage: 'Correct or Past Due',
+ },
+ [ShowAnswerTypesKeys.PAST_DUE]: {
+ id: 'authoring.problemeditor.settings.showanswertype.past_due',
+ defaultMessage: 'Past Due',
+ },
+ [ShowAnswerTypesKeys.NEVER]: {
+ id: 'authoring.problemeditor.settings.showanswertype.never',
+ defaultMessage: 'Never',
+ },
+ [ShowAnswerTypesKeys.AFTER_SOME_NUMBER_OF_ATTEMPTS]: {
+ id: 'authoring.problemeditor.settings.showanswertype.after_attempts',
+ defaultMessage: 'After Some Number of Attempts',
+ },
+ [ShowAnswerTypesKeys.AFTER_ALL_ATTEMPTS]: {
+ id: 'authoring.problemeditor.settings.showanswertype.after_all_attempts',
+ defaultMessage: 'After All Attempts',
+ },
+ [ShowAnswerTypesKeys.AFTER_ALL_ATTEMPTS_OR_CORRECT]: {
+ id: 'authoring.problemeditor.settings.showanswertype.after_all_attempts_or_correct',
+ defaultMessage: 'After All Attempts or Correct',
+ },
+ [ShowAnswerTypesKeys.ATTEMPTED_NO_PAST_DUE]: {
+ id: 'authoring.problemeditor.settings.showanswertype.attempted_no_past_due',
+ defaultMessage: 'Attempted',
+ },
+ } as const,
+);
-export const RandomizationTypesKeys = StrictDict({
- NEVER: 'never',
- ALWAYS: 'always',
- ONRESET: 'onreset',
- PERSTUDENT: 'per_student',
-} as const);
+export const RandomizationTypesKeys = StrictDict(
+ {
+ NEVER: 'never',
+ ALWAYS: 'always',
+ ONRESET: 'onreset',
+ PERSTUDENT: 'per_student',
+ } as const,
+);
-export const RandomizationTypes = StrictDict({
- [RandomizationTypesKeys.ALWAYS]: {
- id: 'authoring.problemeditor.settings.RandomizationTypes.always',
- defaultMessage: 'Always',
- },
- [RandomizationTypesKeys.NEVER]: {
- id: 'authoring.problemeditor.settings.RandomizationTypes.never',
- defaultMessage: 'Never',
- },
- [RandomizationTypesKeys.ONRESET]: {
- id: 'authoring.problemeditor.settings.RandomizationTypes.onreset',
- defaultMessage: 'On Reset',
- },
- [RandomizationTypesKeys.PERSTUDENT]: {
- id: 'authoring.problemeditor.settings.RandomizationTypes.perstudent',
- defaultMessage: 'Per Student',
- },
-} as const);
+export const RandomizationTypes = StrictDict(
+ {
+ [RandomizationTypesKeys.ALWAYS]: {
+ id: 'authoring.problemeditor.settings.RandomizationTypes.always',
+ defaultMessage: 'Always',
+ },
+ [RandomizationTypesKeys.NEVER]: {
+ id: 'authoring.problemeditor.settings.RandomizationTypes.never',
+ defaultMessage: 'Never',
+ },
+ [RandomizationTypesKeys.ONRESET]: {
+ id: 'authoring.problemeditor.settings.RandomizationTypes.onreset',
+ defaultMessage: 'On Reset',
+ },
+ [RandomizationTypesKeys.PERSTUDENT]: {
+ id: 'authoring.problemeditor.settings.RandomizationTypes.perstudent',
+ defaultMessage: 'Per Student',
+ },
+ } as const,
+);
export const GradingMethodKeys = StrictDict({
LAST_SCORE: 'last_score',
@@ -415,15 +454,18 @@ export const ignoredOlxAttributes = [
] as const;
// Useful for the block creation workflow.
-export const problemTitles = new Set([...Object.values(ProblemTypes).map((problem) => problem.title),
- ...Object.values(AdvanceProblems).map((problem) => problem.title)]);
+export const problemTitles = new Set([
+ ...Object.values(ProblemTypes).map((problem) => problem.title),
+ ...Object.values(AdvanceProblems).map((problem) => problem.title),
+]);
/**
* Get problem titles with internationalization support
* @param {Function} formatMessage - The intl.formatMessage function
* @returns {Set} Set of localized problem titles
*/
-export const getProblemTitles = (formatMessage) => new Set([
- ...Object.values(getProblemTypes(formatMessage)).map((problem) => problem.title),
- ...Object.values(getAdvanceProblems(formatMessage)).map((problem) => problem.title),
-]);
+export const getProblemTitles = (formatMessage) =>
+ new Set([
+ ...Object.values(getProblemTypes(formatMessage)).map((problem) => problem.title),
+ ...Object.values(getAdvanceProblems(formatMessage)).map((problem) => problem.title),
+ ]);
diff --git a/src/editors/data/constants/requests.ts b/src/editors/data/constants/requests.ts
index f9f907bedc..0de97d3f16 100644
--- a/src/editors/data/constants/requests.ts
+++ b/src/editors/data/constants/requests.ts
@@ -1,33 +1,37 @@
import { StrictDict } from '../../utils';
-export const RequestStates = StrictDict({
- inactive: 'inactive',
- pending: 'pending',
- completed: 'completed',
- failed: 'failed',
-} as const);
+export const RequestStates = StrictDict(
+ {
+ inactive: 'inactive',
+ pending: 'pending',
+ completed: 'completed',
+ failed: 'failed',
+ } as const,
+);
-export const RequestKeys = StrictDict({
- fetchVideos: 'fetchVideos',
- fetchBlock: 'fetchBlock',
- fetchImages: 'fetchImages',
- fetchUnit: 'fetchUnit',
- fetchStudioView: 'fetchStudioView',
- createBlock: 'createBlock',
- saveBlock: 'saveBlock',
- uploadVideo: 'uploadVideo',
- allowThumbnailUpload: 'allowThumbnailUpload',
- uploadThumbnail: 'uploadThumbnail',
- uploadTranscript: 'uploadTranscript',
- deleteTranscript: 'deleteTranscript',
- fetchCourseDetails: 'fetchCourseDetails',
- updateTranscriptLanguage: 'updateTranscriptLanguage',
- getTranscriptFile: 'getTranscriptFile',
- checkTranscriptsForImport: 'checkTranscriptsForImport',
- importTranscript: 'importTranscript',
- uploadAsset: 'uploadAsset',
- batchUploadAssets: 'batchUploadAssets',
- fetchAdvancedSettings: 'fetchAdvancedSettings',
- fetchVideoFeatures: 'fetchVideoFeatures',
- getHandlerUrl: 'getHandlerUrl',
-} as const);
+export const RequestKeys = StrictDict(
+ {
+ fetchVideos: 'fetchVideos',
+ fetchBlock: 'fetchBlock',
+ fetchImages: 'fetchImages',
+ fetchUnit: 'fetchUnit',
+ fetchStudioView: 'fetchStudioView',
+ createBlock: 'createBlock',
+ saveBlock: 'saveBlock',
+ uploadVideo: 'uploadVideo',
+ allowThumbnailUpload: 'allowThumbnailUpload',
+ uploadThumbnail: 'uploadThumbnail',
+ uploadTranscript: 'uploadTranscript',
+ deleteTranscript: 'deleteTranscript',
+ fetchCourseDetails: 'fetchCourseDetails',
+ updateTranscriptLanguage: 'updateTranscriptLanguage',
+ getTranscriptFile: 'getTranscriptFile',
+ checkTranscriptsForImport: 'checkTranscriptsForImport',
+ importTranscript: 'importTranscript',
+ uploadAsset: 'uploadAsset',
+ batchUploadAssets: 'batchUploadAssets',
+ fetchAdvancedSettings: 'fetchAdvancedSettings',
+ fetchVideoFeatures: 'fetchVideoFeatures',
+ getHandlerUrl: 'getHandlerUrl',
+ } as const,
+);
diff --git a/src/editors/data/constants/tinyMCE.js b/src/editors/data/constants/tinyMCE.js
index a6e40203a5..2e8a3f170f 100644
--- a/src/editors/data/constants/tinyMCE.js
+++ b/src/editors/data/constants/tinyMCE.js
@@ -1,8 +1,9 @@
import { StrictDict } from '../../utils';
-const listKeyStore = (list) => StrictDict(
- list.reduce((obj, val) => ({ ...obj, [val]: val }), {}),
-);
+const listKeyStore = (list) =>
+ StrictDict(
+ list.reduce((obj, val) => ({ ...obj, [val]: val }), {}),
+ );
export const commands = StrictDict({
insertContent: 'mceInsertContent',
@@ -73,4 +74,5 @@ export const plugins = listKeyStore([
'embediframe',
]);
-export const textToSpeechIcon = ' ';
+export const textToSpeechIcon =
+ ' ';
diff --git a/src/editors/data/redux/app/reducer.ts b/src/editors/data/redux/app/reducer.ts
index 91ce052564..8de85320cc 100644
--- a/src/editors/data/redux/app/reducer.ts
+++ b/src/editors/data/redux/app/reducer.ts
@@ -67,8 +67,4 @@ const actions = StrictDict(app.actions);
const { reducer } = app;
-export {
- actions,
- initialState,
- reducer,
-};
+export { actions, initialState, reducer };
diff --git a/src/editors/data/redux/app/selectors.test.ts b/src/editors/data/redux/app/selectors.test.ts
index aab64b080a..9b41c413e8 100644
--- a/src/editors/data/redux/app/selectors.test.ts
+++ b/src/editors/data/redux/app/selectors.test.ts
@@ -67,8 +67,12 @@ describe('app selectors unit tests', () => {
data: {
ancestors: [
{
- id: 'unit id', display_name: 'Unit', category: 'vertical' as const, has_children: true,
- }],
+ id: 'unit id',
+ display_name: 'Unit',
+ category: 'vertical' as const,
+ has_children: true,
+ },
+ ],
},
};
const learningContextId = 'some learning context';
@@ -77,7 +81,10 @@ describe('app selectors unit tests', () => {
cb(unitUrl, studioEndpointUrl, learningContextId, blockId),
).toEqual(
urls.returnUrl({
- unitUrl, studioEndpointUrl, learningContextId, blockId,
+ unitUrl,
+ studioEndpointUrl,
+ learningContextId,
+ blockId,
}),
);
});
diff --git a/src/editors/data/redux/app/selectors.ts b/src/editors/data/redux/app/selectors.ts
index 60f23820c5..8d63ab7902 100644
--- a/src/editors/data/redux/app/selectors.ts
+++ b/src/editors/data/redux/app/selectors.ts
@@ -29,11 +29,18 @@ export const simpleSelectors = {
};
export const returnUrl = createSelector(
- [simpleSelectors.unitUrl, simpleSelectors.studioEndpointUrl, simpleSelectors.learningContextId,
- simpleSelectors.blockId],
+ [
+ simpleSelectors.unitUrl,
+ simpleSelectors.studioEndpointUrl,
+ simpleSelectors.learningContextId,
+ simpleSelectors.blockId,
+ ],
(unitUrl, studioEndpointUrl, learningContextId, blockId) => (
urls.returnUrl({
- studioEndpointUrl, unitUrl, learningContextId, blockId,
+ studioEndpointUrl,
+ unitUrl,
+ learningContextId,
+ blockId,
})
),
);
@@ -55,9 +62,7 @@ export const isLibrary = createSelector(
);
export const shouldCreateBlock = createSelector(
- [simpleSelectors.blockId,
- simpleSelectors.blockType,
- ],
+ [simpleSelectors.blockId, simpleSelectors.blockType],
(blockId, blockType) => {
if (blockId === '' && blockType) {
return true;
diff --git a/src/editors/data/redux/game/reducers.js b/src/editors/data/redux/game/reducers.js
index 93d0f02ffe..7bf9cfd80c 100644
--- a/src/editors/data/redux/game/reducers.js
+++ b/src/editors/data/redux/game/reducers.js
@@ -24,8 +24,4 @@ const actions = StrictDict(game.actions);
const { reducer } = game;
-export {
- actions,
- initialState,
- reducer,
-};
+export { actions, initialState, reducer };
diff --git a/src/editors/data/redux/index.ts b/src/editors/data/redux/index.ts
index 5c4d8269c2..94705c6970 100644
--- a/src/editors/data/redux/index.ts
+++ b/src/editors/data/redux/index.ts
@@ -61,9 +61,9 @@ export interface EditorState {
data: string | Record;
metadata: Record;
[otherKey: string]: any;
- },
+ };
// There are other fields; this is an AxiosResponse object. But we don't want to rely on those details.
- },
+ };
unitUrl: null | {
data: {
ancestors: {
@@ -73,9 +73,9 @@ export interface EditorState {
has_children: boolean;
unit_level_discussions?: boolean;
}[];
- },
+ };
// There are other fields; this is an AxiosResponse object. But we don't want to rely on those details.
- },
+ };
blockContent: null;
studioView: null;
saveResponse: null;
@@ -108,17 +108,17 @@ export interface EditorState {
videos: Record;
courseDetails: Record;
showRawEditor: boolean;
- },
+ };
requests: Record
+ }>;
video: {
videoSource: string; // default: ""
videoId: string; // default: ""
fallbackVideos: string[];
allowVideoDownloads: boolean;
- allowVideoSharing: { level: string; value: boolean };
+ allowVideoSharing: { level: string; value: boolean; };
videoSharingEnabledForAll: boolean;
videoSharingEnabledForCourse: boolean;
videoSharingLearnMoreLink: string;
@@ -131,26 +131,26 @@ export interface EditorState {
startTime: string;
stopTime: string;
total: string;
- },
+ };
showTranscriptByDefault: boolean;
- handout: null,
- licenseType: null,
+ handout: null;
+ licenseType: null;
licenseDetails: {
attribution: boolean;
noncommercial: boolean;
noDerivatives: boolean;
shareAlike: boolean;
- },
+ };
courseLicenseType: string | null;
courseLicenseDetails: {
attribution: boolean;
noncommercial: boolean;
noDerivatives: boolean;
shareAlike: boolean;
- },
+ };
allowThumbnailUpload: boolean | null; // TODO: why is this null?
allowTranscriptImport: boolean;
- },
+ };
problem: {
/** Has the user made changes to this problem since opening the editor? */
isDirty: boolean;
@@ -177,34 +177,33 @@ export interface EditorState {
weight: number;
attempts: { unlimited: boolean; number: number | null; };
gradingMethod: GradingMethodKey;
- },
+ };
hints: any[];
timeBetween: number;
showAnswer: {
on: string;
afterAttempts: number;
- },
+ };
showResetButton: boolean | null;
solutionExplanation: string;
tolerance: {
value: number | null;
type: 'Percent' | 'Number' | 'None';
- }
- }
- },
+ };
+ };
+ };
game: {
settings: Record;
exampleValue: 'this is an example value from the redux state';
- }
+ };
}
export { actions, selectors };
type RecursivePartial = {
- [P in keyof T]?:
- T[P] extends (infer U)[] ? RecursivePartial[] :
+ [P in keyof T]?: T[P] extends (infer U)[] ? RecursivePartial[] :
T[P] extends object | undefined ? RecursivePartial :
- T[P];
+ T[P];
};
export type PartialEditorState = RecursivePartial;
diff --git a/src/editors/data/redux/problem/reducers.test.ts b/src/editors/data/redux/problem/reducers.test.ts
index 9f4287850b..281e4cc66d 100644
--- a/src/editors/data/redux/problem/reducers.test.ts
+++ b/src/editors/data/redux/problem/reducers.test.ts
@@ -397,8 +397,7 @@ describe('problem reducer', () => {
correct: true,
selectedFeedback: '',
unselectedFeedback: '',
- },
- {
+ }, {
id: 'B',
correct: false,
selectedFeedback: '',
diff --git a/src/editors/data/redux/problem/reducers.ts b/src/editors/data/redux/problem/reducers.ts
index e7fc0a4cba..4afceb5ac0 100644
--- a/src/editors/data/redux/problem/reducers.ts
+++ b/src/editors/data/redux/problem/reducers.ts
@@ -242,8 +242,4 @@ const actions = StrictDict(problem.actions);
const { reducer } = problem;
-export {
- actions,
- initialState,
- reducer,
-};
+export { actions, initialState, reducer };
diff --git a/src/editors/data/redux/requests/reducer.js b/src/editors/data/redux/requests/reducer.js
index 4383be7a65..11877c1526 100644
--- a/src/editors/data/redux/requests/reducer.js
+++ b/src/editors/data/redux/requests/reducer.js
@@ -60,8 +60,4 @@ const requests = createSlice({
const actions = StrictDict(requests.actions);
const { reducer } = requests;
-export {
- actions,
- reducer,
- initialState,
-};
+export { actions, reducer, initialState };
diff --git a/src/editors/data/redux/requests/selectors.test.js b/src/editors/data/redux/requests/selectors.test.js
index d987a72e75..156ac33fa4 100644
--- a/src/editors/data/redux/requests/selectors.test.js
+++ b/src/editors/data/redux/requests/selectors.test.js
@@ -26,10 +26,12 @@ describe('request selectors', () => {
describe('statusSelector', () => {
it('returns a state selector that applies a fn against request state by requestKey', () => {
const myMethod = ({ data }) => ({ myData: data });
- expect(selectors.statusSelector(myMethod)(
- { requests: { [testKey]: { data: testValue } } },
- { requestKey: testKey },
- )).toEqual({ myData: testValue });
+ expect(
+ selectors.statusSelector(myMethod)(
+ { requests: { [testKey]: { data: testValue } } },
+ { requestKey: testKey },
+ ),
+ ).toEqual({ myData: testValue });
});
});
describe('state selectors', () => {
diff --git a/src/editors/data/redux/thunkActions/app.js b/src/editors/data/redux/thunkActions/app.js
index bc71c71b3e..7bfa9b8947 100644
--- a/src/editors/data/redux/thunkActions/app.js
+++ b/src/editors/data/redux/thunkActions/app.js
@@ -21,30 +21,33 @@ export const fetchBlock = () => (dispatch) => {
dispatch(actions.app.setBlockValue(response));
dispatch(actions.app.setShowRawEditor(response));
},
- onFailure: (error) => dispatch(actions.requests.failRequest({
- requestKey: RequestKeys.fetchBlock,
- error,
- })),
+ onFailure: (error) =>
+ dispatch(actions.requests.failRequest({
+ requestKey: RequestKeys.fetchBlock,
+ error,
+ })),
}));
};
export const fetchStudioView = () => (dispatch) => {
dispatch(requests.fetchStudioView({
onSuccess: (response) => dispatch(actions.app.setStudioView(response)),
- onFailure: (error) => dispatch(actions.requests.failRequest({
- requestKey: RequestKeys.fetchStudioView,
- error,
- })),
+ onFailure: (error) =>
+ dispatch(actions.requests.failRequest({
+ requestKey: RequestKeys.fetchStudioView,
+ error,
+ })),
}));
};
export const fetchUnit = () => (dispatch) => {
dispatch(requests.fetchUnit({
onSuccess: (response) => dispatch(actions.app.setUnitUrl(response)),
- onFailure: (error) => dispatch(actions.requests.failRequest({
- requestKey: RequestKeys.fetchUnit,
- error,
- })),
+ onFailure: (error) =>
+ dispatch(actions.requests.failRequest({
+ requestKey: RequestKeys.fetchUnit,
+ error,
+ })),
}));
};
@@ -52,30 +55,33 @@ export const fetchImages = ({ pageNumber }) => (dispatch) => {
dispatch(requests.fetchImages({
pageNumber,
onSuccess: ({ images, imageCount }) => dispatch(actions.app.setImages({ images, imageCount })),
- onFailure: (error) => dispatch(actions.requests.failRequest({
- requestKey: RequestKeys.fetchImages,
- error,
- })),
+ onFailure: (error) =>
+ dispatch(actions.requests.failRequest({
+ requestKey: RequestKeys.fetchImages,
+ error,
+ })),
}));
};
export const fetchVideos = () => (dispatch) => {
dispatch(requests.fetchVideos({
onSuccess: (response) => dispatch(actions.app.setVideos(response.data.videos)),
- onFailure: (error) => dispatch(actions.requests.failRequest({
- requestKey: RequestKeys.fetchVideos,
- error,
- })),
+ onFailure: (error) =>
+ dispatch(actions.requests.failRequest({
+ requestKey: RequestKeys.fetchVideos,
+ error,
+ })),
}));
};
export const fetchCourseDetails = () => (dispatch) => {
dispatch(requests.fetchCourseDetails({
onSuccess: (response) => dispatch(actions.app.setCourseDetails(response)),
- onFailure: (error) => dispatch(actions.requests.failRequest({
- requestKey: RequestKeys.fetchCourseDetails,
- error,
- })),
+ onFailure: (error) =>
+ dispatch(actions.requests.failRequest({
+ requestKey: RequestKeys.fetchCourseDetails,
+ error,
+ })),
}));
};
@@ -130,10 +136,12 @@ export const saveBlock = (content, returnToUnit) => (dispatch) => {
const storageKey = 'courseRefreshTriggerOnComponentEditSave';
sessionStorage.setItem(storageKey, Date.now());
- window.dispatchEvent(new StorageEvent('storage', {
- key: storageKey,
- newValue: Date.now().toString(),
- }));
+ window.dispatchEvent(
+ new StorageEvent('storage', {
+ key: storageKey,
+ newValue: Date.now().toString(),
+ }),
+ );
}
returnToUnit(response.data);
},
@@ -157,16 +165,18 @@ export const createBlock = (content, returnToUnit) => (dispatch, getState) => {
assets: newImages,
content,
onSuccess: (updatedContent) => dispatch(saveBlock(updatedContent, returnToUnit)),
- onFailure: (error) => dispatch(actions.requests.failRequest({
- requestKey: RequestKeys.batchUploadAssets,
- error,
- })),
+ onFailure: (error) =>
+ dispatch(actions.requests.failRequest({
+ requestKey: RequestKeys.batchUploadAssets,
+ error,
+ })),
}));
},
- onFailure: (error) => dispatch(actions.requests.failRequest({
- requestKey: RequestKeys.createBlock,
- error,
- })),
+ onFailure: (error) =>
+ dispatch(actions.requests.failRequest({
+ requestKey: RequestKeys.createBlock,
+ error,
+ })),
}));
};
diff --git a/src/editors/data/redux/thunkActions/app.test.js b/src/editors/data/redux/thunkActions/app.test.js
index 3f8dc10c9e..580e039f45 100644
--- a/src/editors/data/redux/thunkActions/app.test.js
+++ b/src/editors/data/redux/thunkActions/app.test.js
@@ -19,7 +19,7 @@ jest.mock('./requests', () => ({
}));
jest.mock('../../../utils', () => ({
- camelizeKeys: (args) => ([{ camelizeKeys: args }]),
+ camelizeKeys: (args) => [{ camelizeKeys: args }],
...jest.requireActual('../../../utils'),
}));
diff --git a/src/editors/data/redux/thunkActions/problem.test.ts b/src/editors/data/redux/thunkActions/problem.test.ts
index 92a55ee6b4..4d541646db 100644
--- a/src/editors/data/redux/thunkActions/problem.test.ts
+++ b/src/editors/data/redux/thunkActions/problem.test.ts
@@ -8,12 +8,19 @@ import {
fetchAdvancedSettings,
loadProblem,
} from './problem';
-import { checkboxesOLXWithFeedbackAndHintsOLX, advancedProblemOlX, blankProblemOLX } from '../../../containers/ProblemEditor/data/mockData/olxTestData';
+import {
+ checkboxesOLXWithFeedbackAndHintsOLX,
+ advancedProblemOlX,
+ blankProblemOLX,
+} from '../../../containers/ProblemEditor/data/mockData/olxTestData';
import { ProblemTypeKeys } from '../../constants/problem';
const mockOlx = 'SOmEVALue';
const mockBuildOlx = jest.fn(() => mockOlx);
-jest.mock('../../../containers/ProblemEditor/data/ReactStateOLXParser', () => jest.fn().mockImplementation(() => ({ buildOLX: mockBuildOlx })));
+jest.mock(
+ '../../../containers/ProblemEditor/data/ReactStateOLXParser',
+ () => jest.fn().mockImplementation(() => ({ buildOLX: mockBuildOlx })),
+);
jest.mock('../problem', () => ({
actions: {
@@ -187,14 +194,20 @@ describe('problem thunkActions', () => {
test('initializeProblem advanced Problem', () => {
rawOLX = advancedProblemOlX.rawOLX;
loadProblem({
- rawOLX, rawSettings, defaultSettings, isMarkdownEditorEnabled: true,
+ rawOLX,
+ rawSettings,
+ defaultSettings,
+ isMarkdownEditorEnabled: true,
})(dispatch);
expect(dispatch).toHaveBeenCalledWith(actions.problem.load(undefined));
});
test('initializeProblem blank Problem', () => {
rawOLX = blankProblemOLX.rawOLX;
loadProblem({
- rawOLX, rawSettings, defaultSettings, isMarkdownEditorEnabled: true,
+ rawOLX,
+ rawSettings,
+ defaultSettings,
+ isMarkdownEditorEnabled: true,
})(dispatch);
expect(dispatch).toHaveBeenCalledWith(actions.problem.setEnableTypeSelection(undefined));
});
diff --git a/src/editors/data/redux/thunkActions/problem.ts b/src/editors/data/redux/thunkActions/problem.ts
index 2711c3b772..544b590f0e 100644
--- a/src/editors/data/redux/thunkActions/problem.ts
+++ b/src/editors/data/redux/thunkActions/problem.ts
@@ -84,8 +84,12 @@ export const getDataFromOlx = ({ rawOLX, rawSettings, defaultSettings }) => {
};
export const loadProblem = ({
- rawOLX, rawSettings, defaultSettings, isMarkdownEditorEnabled,
-}) => (dispatch) => {
+ rawOLX,
+ rawSettings,
+ defaultSettings,
+ isMarkdownEditorEnabled,
+}) =>
+(dispatch) => {
if (isBlankProblem({ rawOLX })) {
dispatch(actions.problem.setEnableTypeSelection(camelizeKeys(defaultSettings)));
} else {
@@ -101,45 +105,47 @@ export const fetchAdvancedSettings = ({
rawOLX,
rawSettings,
isMarkdownEditorEnabled,
-}) => (dispatch) => new Promise((resolve) => {
- const advancedProblemSettingKeys = ['max_attempts', 'showanswer', 'show_reset_button', 'rerandomize'];
-
- dispatch(requests.fetchAdvancedSettings({
- onSuccess: (response) => {
- const defaultSettings = {};
-
- Object.entries(response.data as Record).forEach(([key, value]) => {
- if (advancedProblemSettingKeys.includes(key)) {
- defaultSettings[key] = value.value;
- }
- });
-
- dispatch(actions.problem.updateField({
- defaultSettings: camelizeKeys(defaultSettings),
- }));
-
- loadProblem({
- rawOLX,
- rawSettings,
- defaultSettings,
- isMarkdownEditorEnabled,
- })(dispatch);
-
- resolve(true);
- },
-
- onFailure: () => {
- loadProblem({
- rawOLX,
- rawSettings,
- defaultSettings: {},
- isMarkdownEditorEnabled,
- })(dispatch);
-
- resolve(false);
- },
- }));
-});
+}) =>
+(dispatch) =>
+ new Promise((resolve) => {
+ const advancedProblemSettingKeys = ['max_attempts', 'showanswer', 'show_reset_button', 'rerandomize'];
+
+ dispatch(requests.fetchAdvancedSettings({
+ onSuccess: (response) => {
+ const defaultSettings = {};
+
+ Object.entries(response.data as Record).forEach(([key, value]) => {
+ if (advancedProblemSettingKeys.includes(key)) {
+ defaultSettings[key] = value.value;
+ }
+ });
+
+ dispatch(actions.problem.updateField({
+ defaultSettings: camelizeKeys(defaultSettings),
+ }));
+
+ loadProblem({
+ rawOLX,
+ rawSettings,
+ defaultSettings,
+ isMarkdownEditorEnabled,
+ })(dispatch);
+
+ resolve(true);
+ },
+
+ onFailure: () => {
+ loadProblem({
+ rawOLX,
+ rawSettings,
+ defaultSettings: {},
+ isMarkdownEditorEnabled,
+ })(dispatch);
+
+ resolve(false);
+ },
+ }));
+ });
export const initializeProblem = (blockValue) => (dispatch, getState) => {
const rawOLX = get(blockValue, 'data.data', '');
@@ -152,7 +158,10 @@ export const initializeProblem = (blockValue) => (dispatch, getState) => {
// Though first we need to fake the request or else the problem type selection UI won't display:
dispatch(actions.requests.completeRequest({ requestKey: RequestKeys.fetchAdvancedSettings, response: {} }));
return dispatch(loadProblem({
- rawOLX, rawSettings, defaultSettings: {}, isMarkdownEditorEnabled,
+ rawOLX,
+ rawSettings,
+ defaultSettings: {},
+ isMarkdownEditorEnabled,
}));
}
// Load the defaults (for max_attempts, etc.) from the course's advanced settings, then proceed:
@@ -160,5 +169,8 @@ export const initializeProblem = (blockValue) => (dispatch, getState) => {
};
export default {
- initializeProblem, switchEditor, switchToAdvancedEditor, fetchAdvancedSettings,
+ initializeProblem,
+ switchEditor,
+ switchToAdvancedEditor,
+ fetchAdvancedSettings,
};
diff --git a/src/editors/data/redux/thunkActions/requests.js b/src/editors/data/redux/thunkActions/requests.js
index a46be37336..3115c83136 100644
--- a/src/editors/data/redux/thunkActions/requests.js
+++ b/src/editors/data/redux/thunkActions/requests.js
@@ -39,7 +39,8 @@ export const networkRequest = ({
promise,
onSuccess,
onFailure,
-}) => (dispatch) => {
+}) =>
+(dispatch) => {
dispatch(actions.requests.startRequest(requestKey));
return promise
.then((response) => {
@@ -164,8 +165,10 @@ export const removeTemporalLink = (response, asset, content, resolve) => {
const imagePath = `/${response.data.asset.portableUrl}`;
const reader = new FileReader();
reader.addEventListener('load', () => {
- const imageBS64 = /** @type {string} */(reader.result);
- const parsedContent = typeof content === 'string' ? content.replace(imageBS64, imagePath) : { ...content, olx: content.olx.replace(imageBS64, imagePath) };
+ const imageBS64 = /** @type {string} */ (reader.result);
+ const parsedContent = typeof content === 'string'
+ ? content.replace(imageBS64, imagePath)
+ : { ...content, olx: content.olx.replace(imageBS64, imagePath) };
URL.revokeObjectURL(asset);
resolve(parsedContent);
});
@@ -173,13 +176,16 @@ export const removeTemporalLink = (response, asset, content, resolve) => {
};
export const batchUploadAssets = ({ assets, content, ...rest }) => (dispatch) => {
- const promises = assets.reduce((promiseChain, asset) => promiseChain
- .then((parsedContent) => new Promise((resolve) => {
- dispatch(module.uploadAsset({
- asset,
- onSuccess: (response) => removeTemporalLink(response, asset, parsedContent, resolve),
- }));
- })), Promise.resolve(content));
+ const promises = assets.reduce((promiseChain, asset) =>
+ promiseChain
+ .then((parsedContent) =>
+ new Promise((resolve) => {
+ dispatch(module.uploadAsset({
+ asset,
+ onSuccess: (response) => removeTemporalLink(response, asset, parsedContent, resolve),
+ }));
+ })
+ ), Promise.resolve(content));
dispatch(module.networkRequest({
requestKey: RequestKeys.batchUploadAssets,
@@ -336,7 +342,8 @@ export const uploadTranscript = ({
videoId,
language,
...rest
-}) => (dispatch, getState) => {
+}) =>
+(dispatch, getState) => {
const state = getState();
const isLibrary = selectors.app.isLibrary(state);
if (isLibrary) {
@@ -371,7 +378,8 @@ export const updateTranscriptLanguage = ({
newLanguageCode,
videoId,
...rest
-}) => (dispatch, getState) => {
+}) =>
+(dispatch, getState) => {
const state = getState();
const isLibrary = selectors.app.isLibrary(state);
if (isLibrary) {
diff --git a/src/editors/data/redux/thunkActions/requests.test.js b/src/editors/data/redux/thunkActions/requests.test.js
index 82bf74cfcc..557dd80750 100644
--- a/src/editors/data/redux/thunkActions/requests.test.js
+++ b/src/editors/data/redux/thunkActions/requests.test.js
@@ -79,7 +79,7 @@ describe('requests thunkActions module', () => {
describe('networkRequest', () => {
const requestKey = 'test-request';
- const testData = ({ some: 'test data' });
+ const testData = { some: 'test data' };
let resolveFn;
let rejectFn;
describe('without success and failure handlers', () => {
@@ -266,9 +266,11 @@ describe('requests thunkActions module', () => {
let dispatchedAction;
describe('courses', () => {
beforeEach(() => {
- fetchImages = jest.fn((args) => new Promise((resolve) => {
- resolve({ data: { assets: { fetchImages: args } } });
- }));
+ fetchImages = jest.fn((args) =>
+ new Promise((resolve) => {
+ resolve({ data: { assets: { fetchImages: args } } });
+ })
+ );
jest.spyOn(api, apiKeys.fetchCourseImages).mockImplementationOnce(fetchImages);
loadImages = jest.spyOn(api, apiKeys.loadImages).mockImplementationOnce(() => ({}));
requests.fetchImages({ ...fetchParams, onSuccess, onFailure })(dispatch, () => testState);
@@ -304,12 +306,16 @@ describe('requests thunkActions module', () => {
};
beforeEach(() => {
jest.spyOn(selectors.app, 'learningContextId').mockImplementationOnce(() => ('lib:demo'));
- fetchImages = jest.fn((args) => new Promise((resolve) => {
- resolve({ data: { files: { fetchImages: args } } });
- }));
+ fetchImages = jest.fn((args) =>
+ new Promise((resolve) => {
+ resolve({ data: { files: { fetchImages: args } } });
+ })
+ );
jest.spyOn(api, apiKeys.fetchLibraryImages).mockImplementationOnce(fetchImages);
requests.fetchImages({
- ...fetchParams, onSuccess, onFailure,
+ ...fetchParams,
+ onSuccess,
+ onFailure,
})(dispatch, () => testState);
[[dispatchedAction]] = dispatch.mock.calls;
});
@@ -327,9 +333,11 @@ describe('requests thunkActions module', () => {
let fetchVideos;
let dispatchedAction;
beforeEach(() => {
- fetchVideos = jest.fn((args) => new Promise((resolve) => {
- resolve({ data: { videos: { fetchVideos: args } } });
- }));
+ fetchVideos = jest.fn((args) =>
+ new Promise((resolve) => {
+ resolve({ data: { videos: { fetchVideos: args } } });
+ })
+ );
jest.spyOn(api, apiKeys.fetchVideos).mockImplementationOnce(fetchVideos);
requests.fetchVideos({ ...fetchParams, onSuccess, onFailure })(dispatch, () => testState);
[[dispatchedAction]] = dispatch.mock.calls;
@@ -394,12 +402,17 @@ describe('requests thunkActions module', () => {
asset,
};
beforeEach(() => {
- uploadAsset = jest.fn((args) => new Promise((resolve) => {
- resolve({ data: { asset: args } });
- }));
+ uploadAsset = jest.fn((args) =>
+ new Promise((resolve) => {
+ resolve({ data: { asset: args } });
+ })
+ );
jest.spyOn(api, apiKeys.uploadAsset).mockImplementationOnce(uploadAsset);
requests.uploadAsset({
- asset, ...fetchParams, onSuccess, onFailure,
+ asset,
+ ...fetchParams,
+ onSuccess,
+ onFailure,
})(dispatch, () => testState);
[[dispatchedAction]] = dispatch.mock.calls;
});
@@ -423,12 +436,17 @@ describe('requests thunkActions module', () => {
};
beforeEach(() => {
jest.spyOn(selectors.app, 'learningContextId').mockImplementationOnce(() => ('lib:demo'));
- uploadAsset = jest.fn((args) => new Promise((resolve) => {
- resolve({ data: { asset: args } });
- }));
+ uploadAsset = jest.fn((args) =>
+ new Promise((resolve) => {
+ resolve({ data: { asset: args } });
+ })
+ );
jest.spyOn(api, apiKeys.uploadAsset).mockImplementationOnce(uploadAsset);
requests.uploadAsset({
- asset, ...fetchParams, onSuccess, onFailure,
+ asset,
+ ...fetchParams,
+ onSuccess,
+ onFailure,
})(dispatch, () => testState);
[[dispatchedAction]] = dispatch.mock.calls;
});
@@ -448,11 +466,14 @@ describe('requests thunkActions module', () => {
expectedData: {
...fetchParams,
requestKey: RequestKeys.batchUploadAssets,
- promise: assets.reduce((acc, asset) => acc.then(() => requests.uploadAsset({
- asset,
- learningContextId: selectors.app.learningContextId(testState),
- studioEndpointUrl: selectors.app.studioEndpointUrl(testState),
- })), Promise.resolve()),
+ promise: assets.reduce((acc, asset) =>
+ acc.then(() =>
+ requests.uploadAsset({
+ asset,
+ learningContextId: selectors.app.learningContextId(testState),
+ studioEndpointUrl: selectors.app.studioEndpointUrl(testState),
+ })
+ ), Promise.resolve()),
},
});
describe('removeTemporalLink', () => {
diff --git a/src/editors/data/redux/thunkActions/testUtils.js b/src/editors/data/redux/thunkActions/testUtils.js
index aaaa71a985..f1386d23ae 100644
--- a/src/editors/data/redux/thunkActions/testUtils.js
+++ b/src/editors/data/redux/thunkActions/testUtils.js
@@ -33,14 +33,17 @@ export const createTestFetcher = (
thunkAction,
args,
onDispatch,
-) => (
+) =>
+(
resolveFn,
expectedActions,
) => {
const store = mockStore({});
- mockedMethod.mockReturnValue(new Promise(resolve => {
- resolve(new Promise(resolveFn));
- }));
+ mockedMethod.mockReturnValue(
+ new Promise(resolve => {
+ resolve(new Promise(resolveFn));
+ }),
+ );
return store.dispatch(thunkAction(...args)).then(() => {
onDispatch();
if (expectedActions !== undefined) {
diff --git a/src/editors/data/redux/thunkActions/video.js b/src/editors/data/redux/thunkActions/video.js
index 1bb2a8db62..aae9107473 100644
--- a/src/editors/data/redux/thunkActions/video.js
+++ b/src/editors/data/redux/thunkActions/video.js
@@ -60,7 +60,8 @@ export const loadVideoData = (selectedVideoId, selectedVideoUrl) => (dispatch, g
const [licenseType, licenseOptions] = module.parseLicense({ licenseData: studioView, level: 'block' });
// eslint-disable-next-line no-console
console.log(licenseType);
- const transcripts = rawVideoData.transcriptsFromSelected ? rawVideoData.transcriptsFromSelected
+ const transcripts = rawVideoData.transcriptsFromSelected ?
+ rawVideoData.transcriptsFromSelected
: module.parseTranscripts({ transcriptsData: studioView });
const [courseLicenseType, courseLicenseDetails] = module.parseLicense({
@@ -106,10 +107,11 @@ export const loadVideoData = (selectedVideoId, selectedVideoUrl) => (dispatch, g
thumbnail: rawVideoData.thumbnail,
}));
dispatch(requests.fetchVideoFeatures({
- onSuccess: (response) => dispatch(actions.video.updateField({
- allowThumbnailUpload: response.data.allowThumbnailUpload,
- videoSharingEnabledForAll: response.data.videoSharingEnabled,
- })),
+ onSuccess: (response) =>
+ dispatch(actions.video.updateField({
+ allowThumbnailUpload: response.data.allowThumbnailUpload,
+ videoSharingEnabledForAll: response.data.videoSharingEnabled,
+ })),
}));
const youTubeId = parseYoutubeId(videoSourceUrl);
if (youTubeId) {
@@ -197,7 +199,10 @@ export const parseLicense = ({ licenseData, level }) => {
metadataArr.forEach(arr => {
const parsedStr = arr.replace(/"/g, '"');
if (parsedStr.includes('license')) {
- license = parsedStr.substring(parsedStr.indexOf('"value"'), parsedStr.indexOf(', "type"')).replace(/"value": |"/g, '');
+ license = parsedStr.substring(parsedStr.indexOf('"value"'), parsedStr.indexOf(', "type"')).replace(
+ /"value": |"/g,
+ '',
+ );
}
});
}
@@ -306,7 +311,8 @@ export const importTranscript = () => (dispatch, getState) => {
dispatch(actions.video.updateField({
transcripts: [
...transcriptsPlaceholderRemoved,
- 'en'],
+ 'en',
+ ],
}));
if (selectors.video.videoId(state) === '') {
@@ -333,7 +339,8 @@ export const uploadTranscript = ({ language, file }) => (dispatch, getState) =>
dispatch(actions.video.updateField({
transcripts: [
...transcriptsPlaceholderRemoved,
- language],
+ language,
+ ],
}));
}
@@ -369,7 +376,9 @@ export const updateTranscriptLanguage = ({ newLanguageCode, languageBeforeChange
onSuccess: (response) => {
dispatch(requests.updateTranscriptLanguage({
languageBeforeChange,
- file: new File([new Blob([response.data], { type: 'text/plain' })], `${videoId}_${newLanguageCode}.srt`, { type: 'text/plain' }),
+ file: new File([new Blob([response.data], { type: 'text/plain' })], `${videoId}_${newLanguageCode}.srt`, {
+ type: 'text/plain',
+ }),
newLanguageCode,
videoId,
onSuccess: () => {
@@ -419,35 +428,37 @@ export const uploadVideo = ({ supportedFiles, setLoadSpinner, postUploadRedirect
data,
onSuccess: async (response) => {
const { files } = response.data;
- await Promise.all(Object.values(files).map(async (fileObj) => {
- const fileName = fileObj.file_name;
- const edxVideoId = fileObj.edx_video_id;
- const uploadUrl = fileObj.upload_url;
- const uploadFile = supportedFiles.find((file) => file.get('file').name === fileName);
- if (!uploadFile) {
- // eslint-disable-next-line no-console
- console.error(`Could not find file object with name "${fileName}" in supportedFiles array.`);
- return;
- }
- const file = uploadFile.get('file');
- await fetch(uploadUrl, {
- method: 'PUT',
- headers: {
- 'Content-Disposition': `attachment; filename="${file.name}"`,
- 'Content-Type': file.type,
- },
- multipart: false,
- body: file,
- })
- .then((resp) => {
- if (!resp.ok) {
- throw new Error('Failed to connect with server');
- }
- postUploadRedirect(edxVideoId);
+ await Promise.all(
+ Object.values(files).map(async (fileObj) => {
+ const fileName = fileObj.file_name;
+ const edxVideoId = fileObj.edx_video_id;
+ const uploadUrl = fileObj.upload_url;
+ const uploadFile = supportedFiles.find((file) => file.get('file').name === fileName);
+ if (!uploadFile) {
+ // eslint-disable-next-line no-console
+ console.error(`Could not find file object with name "${fileName}" in supportedFiles array.`);
+ return;
+ }
+ const file = uploadFile.get('file');
+ await fetch(uploadUrl, {
+ method: 'PUT',
+ headers: {
+ 'Content-Disposition': `attachment; filename="${file.name}"`,
+ 'Content-Type': file.type,
+ },
+ multipart: false,
+ body: file,
})
- // eslint-disable-next-line no-console
- .catch((error) => console.error('Error uploading file:', error));
- }));
+ .then((resp) => {
+ if (!resp.ok) {
+ throw new Error('Failed to connect with server');
+ }
+ postUploadRedirect(edxVideoId);
+ })
+ // eslint-disable-next-line no-console
+ .catch((error) => console.error('Error uploading file:', error));
+ }),
+ );
setLoadSpinner(false);
},
}));
diff --git a/src/editors/data/redux/thunkActions/video.test.js b/src/editors/data/redux/thunkActions/video.test.js
index 4c501cc447..f46feb870d 100644
--- a/src/editors/data/redux/thunkActions/video.test.js
+++ b/src/editors/data/redux/thunkActions/video.test.js
@@ -38,11 +38,11 @@ jest.mock('./requests', () => ({
jest.mock('../../../utils', () => ({
...jest.requireActual('../../../utils'),
- removeItemOnce: (args) => (args),
+ removeItemOnce: (args) => args,
}));
jest.mock('../../services/cms/api', () => ({
- parseYoutubeId: (args) => (args),
+ parseYoutubeId: (args) => args,
}));
const thunkActionsKeys = keyStore(thunkActions);
@@ -489,8 +489,10 @@ describe('video thunkActions', () => {
});
});
describe('parseTranscripts', () => {
- const testStudioViewDataWithTranscripts = 'de descarga debajo del video.", "value": "", "type": "Generic", "options": []}, "transcripts": {"explicitly_set": false, "default_value": {}, "field_name": "transcripts", "display_name": "Idiomas de transcripci\\u00f3n", "help": "A\\u00f1ada transcripciones en diferentes idiomas. Haga clic a continuaci\\u00f3n para especificar un idioma y subir un archivo .srt de transcripci\\u00f3n para dicho idioma.", "value": {"aa": "non_existent_dummy_file_name", "ab": "non_existent_dummy_file_name", "ba": "non_existent_dummy_file_name", "en": "external video-en.txt"}, "type": "VideoTranslations", "options": [], "custom": true, "languages": [{"label": "Abkhazian", "code": "ab"}], "urlRoot": "/xblock/block-v1:GalileoX+XS_Mate001+3T2022+type@video+block@20bc09f5522d430f8e43c2bc377b348c/handler/studio_transcript/translation"}, "youtube_id_0_75": {';
- const testStudioViewData = 'de descarga debajo del video.", "value": "", "type": "Generic", "options": []}, "transcripts": {"explicitly_set": false, "default_value": {}, "field_name": "transcripts", "display_name": "Idiomas de transcripci\\u00f3n", "help": "A\\u00f1ada transcripciones en diferentes idiomas. Haga clic a continuaci\\u00f3n para especificar un idioma y subir un archivo .srt de transcripci\\u00f3n para dicho idioma.", "value": {}, "type": "VideoTranslations", "options": [], "custom": true, "languages": [{"label": "Abkhazian", "code": "ab"}], "urlRoot": "/xblock/block-v1:GalileoX+XS_Mate001+3T2022+type@video+block@20bc09f5522d430f8e43c2bc377b348c/handler/studio_transcript/translation"}, "youtube_id_0_75": {';
+ const testStudioViewDataWithTranscripts =
+ 'de descarga debajo del video.", "value": "", "type": "Generic", "options": []}, "transcripts": {"explicitly_set": false, "default_value": {}, "field_name": "transcripts", "display_name": "Idiomas de transcripci\\u00f3n", "help": "A\\u00f1ada transcripciones en diferentes idiomas. Haga clic a continuaci\\u00f3n para especificar un idioma y subir un archivo .srt de transcripci\\u00f3n para dicho idioma.", "value": {"aa": "non_existent_dummy_file_name", "ab": "non_existent_dummy_file_name", "ba": "non_existent_dummy_file_name", "en": "external video-en.txt"}, "type": "VideoTranslations", "options": [], "custom": true, "languages": [{"label": "Abkhazian", "code": "ab"}], "urlRoot": "/xblock/block-v1:GalileoX+XS_Mate001+3T2022+type@video+block@20bc09f5522d430f8e43c2bc377b348c/handler/studio_transcript/translation"}, "youtube_id_0_75": {';
+ const testStudioViewData =
+ 'de descarga debajo del video.", "value": "", "type": "Generic", "options": []}, "transcripts": {"explicitly_set": false, "default_value": {}, "field_name": "transcripts", "display_name": "Idiomas de transcripci\\u00f3n", "help": "A\\u00f1ada transcripciones en diferentes idiomas. Haga clic a continuaci\\u00f3n para especificar un idioma y subir un archivo .srt de transcripci\\u00f3n para dicho idioma.", "value": {}, "type": "VideoTranslations", "options": [], "custom": true, "languages": [{"label": "Abkhazian", "code": "ab"}], "urlRoot": "/xblock/block-v1:GalileoX+XS_Mate001+3T2022+type@video+block@20bc09f5522d430f8e43c2bc377b348c/handler/studio_transcript/translation"}, "youtube_id_0_75": {';
const testBadStudioViewData = 'tHiSiSaBAdDaTa';
it('returns an array of languages given a JSON string', () => {
expect(thunkActions.parseTranscripts({
@@ -530,7 +532,8 @@ describe('video thunkActions', () => {
]);
});
it('returns expected values for a license with all rights reserved', () => {
- const license = 'sOMeHTml data-metadata "license" "value": "all-rights-reserved", "type"';
+ const license =
+ 'sOMeHTml data-metadata "license" "value": "all-rights-reserved", "type"';
expect(thunkActions.parseLicense({
licenseData: license,
level: 'block',
@@ -540,7 +543,8 @@ describe('video thunkActions', () => {
]);
});
it('returns expected type and options for creative commons', () => {
- const license = 'sOMeHTml data-metadata "license" "value": "creative-commons: ver=4.0 BY NC ND", "type"';
+ const license =
+ 'sOMeHTml data-metadata "license" "value": "creative-commons: ver=4.0 BY NC ND", "type"';
expect(thunkActions.parseLicense({
licenseData: license,
level: 'block',
@@ -820,6 +824,8 @@ describe('uploadVideo', () => {
thunkActions.uploadVideo({ supportedFiles, setLoadSpinner, postUploadRedirect })(dispatch);
dispatchedAction.uploadVideo.onSuccess(mockRequestResponse);
- expect(spyConsoleError).toHaveBeenCalledWith('Could not find file object with name "file2.gif" in supportedFiles array.');
+ expect(spyConsoleError).toHaveBeenCalledWith(
+ 'Could not find file object with name "file2.gif" in supportedFiles array.',
+ );
});
});
diff --git a/src/editors/data/redux/video/reducer.js b/src/editors/data/redux/video/reducer.js
index 8770c306fe..47f694823a 100644
--- a/src/editors/data/redux/video/reducer.js
+++ b/src/editors/data/redux/video/reducer.js
@@ -66,8 +66,4 @@ const actions = StrictDict(video.actions);
const { reducer } = video;
-export {
- actions,
- initialState,
- reducer,
-};
+export { actions, initialState, reducer };
diff --git a/src/editors/data/redux/video/selectors.js b/src/editors/data/redux/video/selectors.js
index 4829321835..bab83b992f 100644
--- a/src/editors/data/redux/video/selectors.js
+++ b/src/editors/data/redux/video/selectors.js
@@ -84,18 +84,20 @@ export const getTranscriptDownloadUrl = createSelector(
export const buildTranscriptUrl = createSelector(
[AppSelectors.simpleSelectors.studioEndpointUrl],
- (studioEndpointUrl) => ({ transcriptUrl }) => mediaTranscriptURL({
- studioEndpointUrl,
- transcriptUrl,
- }),
+ (studioEndpointUrl) => ({ transcriptUrl }) =>
+ mediaTranscriptURL({
+ studioEndpointUrl,
+ transcriptUrl,
+ }),
);
export const getHandoutDownloadUrl = createSelector(
[AppSelectors.simpleSelectors.studioEndpointUrl],
- (studioEndpointUrl) => ({ handout }) => downloadVideoHandoutUrl({
- studioEndpointUrl,
- handout,
- }),
+ (studioEndpointUrl) => ({ handout }) =>
+ downloadVideoHandoutUrl({
+ studioEndpointUrl,
+ handout,
+ }),
);
export const videoSettings = createSelector(
diff --git a/src/editors/data/services/cms/api.test.ts b/src/editors/data/services/cms/api.test.ts
index d34d28833f..45a4bb4806 100644
--- a/src/editors/data/services/cms/api.test.ts
+++ b/src/editors/data/services/cms/api.test.ts
@@ -1,7 +1,10 @@
import * as api from './api';
import * as urls from './urls';
import {
- get, post, put, deleteObject,
+ get,
+ post,
+ put,
+ deleteObject,
} from './utils';
jest.mock('./urls', () => ({
@@ -110,7 +113,9 @@ describe('cms api', () => {
describe('fetchCourseImages', () => {
it('should call get with url.courseAssets', async () => {
await apiMethods.fetchCourseImages({
- learningContextId, studioEndpointUrl, pageNumber: 0,
+ learningContextId,
+ studioEndpointUrl,
+ pageNumber: 0,
});
const params = {
asset_type: 'Images',
@@ -164,7 +169,8 @@ describe('cms api', () => {
describe('normalizeContent', () => {
test('return value for blockType: html', () => {
- const content = 'Im baby palo santo ugh celiac fashion axe. La croix lo-fi venmo whatever. Beard man braid migas single-origin coffee forage ramps.';
+ const content =
+ 'Im baby palo santo ugh celiac fashion axe. La croix lo-fi venmo whatever. Beard man braid migas single-origin coffee forage ramps.';
expect(apiMethods.normalizeContent({
blockId,
blockType: 'html',
@@ -242,14 +248,17 @@ describe('cms api', () => {
jest.restoreAllMocks();
});
test('throw error for invalid blockType', () => {
- // @ts-expect-error because we're not passing 'blockId' or other parameters
- expect(() => { apiMethods.normalizeContent({ blockType: 'somethingINVALID' }); })
+ expect(() => {
+ // @ts-expect-error because we're not passing 'blockId' or other parameters
+ apiMethods.normalizeContent({ blockType: 'somethingINVALID' });
+ })
.toThrow(TypeError);
});
});
describe('saveBlock', () => {
- const content = 'Im baby palo santo ugh celiac fashion axe. La croix lo-fi venmo whatever. Beard man braid migas single-origin coffee forage ramps.';
+ const content =
+ 'Im baby palo santo ugh celiac fashion axe. La croix lo-fi venmo whatever. Beard man braid migas single-origin coffee forage ramps.';
it('should call post with urls.block and normalizeContent', async () => {
await apiMethods.saveBlock({
blockId,
@@ -375,7 +384,8 @@ describe('cms api', () => {
const videoId = 'sOmeVIDeoiD';
const youTubeId = 'SOMeyoutUBeid';
describe('checkTranscriptsForImport', () => {
- const getJSON = `{"locator":"${blockId}","videos":[{"mode":"youtube","video":"${youTubeId}","type":"youtube"},{"mode":"edx_video_id","type":"edx_video_id","video":"${videoId}"}]}`;
+ const getJSON =
+ `{"locator":"${blockId}","videos":[{"mode":"youtube","video":"${youTubeId}","type":"youtube"},{"mode":"edx_video_id","type":"edx_video_id","video":"${videoId}"}]}`;
it('should call get with url.checkTranscriptsForImport', async () => {
await apiMethods.checkTranscriptsForImport({
studioEndpointUrl,
diff --git a/src/editors/data/services/cms/api.ts b/src/editors/data/services/cms/api.ts
index 8c96ffd949..dc33a8b9ec 100644
--- a/src/editors/data/services/cms/api.ts
+++ b/src/editors/data/services/cms/api.ts
@@ -3,7 +3,10 @@ import { snakeCaseKeys, camelizeKeys } from '@src/editors/utils';
import { isLibraryKey } from '../../../../generic/key-utils';
import * as urls from './urls';
import {
- get, post, put, deleteObject,
+ get,
+ post,
+ put,
+ deleteObject,
} from './utils';
import { durationStringFromValue } from '../../../containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/hooks';
@@ -41,13 +44,15 @@ export const loadImage = (imageData) => ({
dateAdded: new Date(imageData.dateAdded.replace(' at', '')).getTime(),
});
-export const loadImages = (rawImages) => camelizeKeys(rawImages).reduce(
- (obj, image) => ({ ...obj, [image.id]: loadImage(image) }),
- {},
-);
+export const loadImages = (rawImages) =>
+ camelizeKeys(rawImages).reduce(
+ (obj, image) => ({ ...obj, [image.id]: loadImage(image) }),
+ {},
+ );
export const parseYoutubeId = (src: string): string | null => {
- const youtubeRegex = /^((?:https?:)?\/\/)?((?:www|m)\.)?((?:youtube\.com|youtu.be))(\/(?:[\w-]+\?v=|embed\/|v\/)?)([\w-]+)(\S+)?$/;
+ const youtubeRegex =
+ /^((?:https?:)?\/\/)?((?:www|m)\.)?((?:youtube\.com|youtu.be))(\/(?:[\w-]+\?v=|embed\/|v\/)?)([\w-]+)(\S+)?$/;
const match = src.match(youtubeRegex);
if (!match) {
return null;
@@ -59,7 +64,7 @@ export const processVideoIds = ({
videoId,
videoUrl,
fallbackVideos,
-}: { videoId: string, videoUrl: string, fallbackVideos: string[] }) => {
+}: { videoId: string; videoUrl: string; fallbackVideos: string[]; }) => {
let youtubeId: string | null = '';
const html5Sources: string[] = [];
@@ -93,10 +98,10 @@ export const isEdxVideo = (src: string): boolean => {
export const processLicense = (licenseType, licenseDetails) => {
if (licenseType === 'creative-commons') {
return 'creative-commons: ver=4.0'.concat(
- (licenseDetails.attribution ? ' BY' : ''),
- (licenseDetails.noncommercial ? ' NC' : ''),
- (licenseDetails.noDerivatives ? ' ND' : ''),
- (licenseDetails.shareAlike ? ' SA' : ''),
+ licenseDetails.attribution ? ' BY' : '',
+ licenseDetails.noncommercial ? ' NC' : '',
+ licenseDetails.noDerivatives ? ' ND' : '',
+ licenseDetails.shareAlike ? ' SA' : '',
);
}
if (licenseType === 'all-rights-reserved') {
@@ -106,22 +111,25 @@ export const processLicense = (licenseType, licenseDetails) => {
};
export const apiMethods = {
- fetchBlockById: ({ blockId, studioEndpointUrl }): Promise<{ data: FieldsResponse }> => get(
- urls.block({ blockId, studioEndpointUrl }),
- ),
+ fetchBlockById: ({ blockId, studioEndpointUrl }): Promise<{ data: FieldsResponse; }> =>
+ get(
+ urls.block({ blockId, studioEndpointUrl }),
+ ),
/** A better name for this would be 'get ancestors of block' */
- fetchByUnitId: ({ blockId, studioEndpointUrl }): Promise<{ data: AncestorsResponse }> => get(
- urls.blockAncestor({ studioEndpointUrl, blockId }),
- fetchByUnitIdOptions,
- ),
- fetchStudioView: ({ blockId, studioEndpointUrl }) => get(
- urls.blockStudioView({ studioEndpointUrl, blockId }),
- ),
+ fetchByUnitId: ({ blockId, studioEndpointUrl }): Promise<{ data: AncestorsResponse; }> =>
+ get(
+ urls.blockAncestor({ studioEndpointUrl, blockId }),
+ fetchByUnitIdOptions,
+ ),
+ fetchStudioView: ({ blockId, studioEndpointUrl }) =>
+ get(
+ urls.blockStudioView({ studioEndpointUrl, blockId }),
+ ),
fetchCourseImages: ({
learningContextId,
studioEndpointUrl,
pageNumber,
- }): Promise<{ data: AssetResponse & Pagination }> => {
+ }): Promise<{ data: AssetResponse & Pagination; }> => {
const params = {
asset_type: 'Images',
page: pageNumber,
@@ -131,18 +139,22 @@ export const apiMethods = {
{ params },
);
},
- fetchLibraryImages: ({ blockId }) => get(
- `${urls.libraryAssets({ blockId })}`,
- ),
- fetchVideos: ({ studioEndpointUrl, learningContextId }) => get(
- urls.courseVideos({ studioEndpointUrl, learningContextId }),
- ),
- fetchCourseDetails: ({ studioEndpointUrl, learningContextId }) => get(
- urls.courseDetailsUrl({ studioEndpointUrl, learningContextId }),
- ),
- fetchAdvancedSettings: ({ studioEndpointUrl, learningContextId }) => get(
- urls.courseAdvanceSettings({ studioEndpointUrl, learningContextId }),
- ),
+ fetchLibraryImages: ({ blockId }) =>
+ get(
+ `${urls.libraryAssets({ blockId })}`,
+ ),
+ fetchVideos: ({ studioEndpointUrl, learningContextId }) =>
+ get(
+ urls.courseVideos({ studioEndpointUrl, learningContextId }),
+ ),
+ fetchCourseDetails: ({ studioEndpointUrl, learningContextId }) =>
+ get(
+ urls.courseDetailsUrl({ studioEndpointUrl, learningContextId }),
+ ),
+ fetchAdvancedSettings: ({ studioEndpointUrl, learningContextId }) =>
+ get(
+ urls.courseAdvanceSettings({ studioEndpointUrl, learningContextId }),
+ ),
uploadAsset: ({
blockId,
learningContextId,
@@ -182,7 +194,8 @@ export const apiMethods = {
youTubeId,
videoId,
}) => {
- const getJSON = `{"locator":"${blockId}","videos":[{"mode":"youtube","video":"${youTubeId}","type":"youtube"},{"mode":"edx_video_id","type":"edx_video_id","video":"${videoId}"}]}`;
+ const getJSON =
+ `{"locator":"${blockId}","videos":[{"mode":"youtube","video":"${youTubeId}","type":"youtube"},{"mode":"edx_video_id","type":"edx_video_id","video":"${videoId}"}]}`;
return get(
urls.checkTranscriptsForImport({
studioEndpointUrl,
@@ -291,11 +304,11 @@ export const apiMethods = {
learningContextId,
title,
}: {
- blockId: string,
- blockType: string,
- content: any, // string for 'html' blocks, otherwise Record
- learningContextId: string,
- title: string,
+ blockId: string;
+ blockType: string;
+ content: any; // string for 'html' blocks, otherwise Record
+ learningContextId: string;
+ title: string;
}) => {
let response = {};
if (blockType === 'html') {
@@ -368,43 +381,48 @@ export const apiMethods = {
learningContextId,
studioEndpointUrl,
title,
- }) => post(
- urls.block({ studioEndpointUrl, blockId }),
- apiMethods.normalizeContent({
- blockType,
- content,
- blockId,
- learningContextId,
- title,
- }),
- ),
+ }) =>
+ post(
+ urls.block({ studioEndpointUrl, blockId }),
+ apiMethods.normalizeContent({
+ blockType,
+ content,
+ blockId,
+ learningContextId,
+ title,
+ }),
+ ),
fetchVideoFeatures: ({
studioEndpointUrl,
- }) => get(
- urls.videoFeatures({ studioEndpointUrl }),
- ),
+ }) =>
+ get(
+ urls.videoFeatures({ studioEndpointUrl }),
+ ),
uploadVideo: ({
data,
studioEndpointUrl,
learningContextId,
- }) => post(
- urls.courseVideos({ studioEndpointUrl, learningContextId }),
- data,
- ),
+ }) =>
+ post(
+ urls.courseVideos({ studioEndpointUrl, learningContextId }),
+ data,
+ ),
getHandlerUrl: ({
studioEndpointUrl,
blockId,
handlerName,
- }) => get(
- urls.boundHandlerUrl({ studioEndpointUrl, blockId, handlerName }),
- ),
+ }) =>
+ get(
+ urls.boundHandlerUrl({ studioEndpointUrl, blockId, handlerName }),
+ ),
validateBlockNumericInput: ({
studioEndpointUrl,
data,
- }) => post(
- urls.validateNumericInputUrl({ studioEndpointUrl }),
- data,
- ),
+ }) =>
+ post(
+ urls.validateNumericInputUrl({ studioEndpointUrl }),
+ data,
+ ),
};
export default apiMethods;
diff --git a/src/editors/data/services/cms/urls.test.ts b/src/editors/data/services/cms/urls.test.ts
index 3a34037c48..3409e83c5b 100644
--- a/src/editors/data/services/cms/urls.test.ts
+++ b/src/editors/data/services/cms/urls.test.ts
@@ -50,7 +50,10 @@ describe('cms url methods', () => {
};
it('returns the library page when given the v1 library', () => {
expect(returnUrl({
- studioEndpointUrl, unitUrl, learningContextId: libraryLearningContextId, blockId: libraryV1Id,
+ studioEndpointUrl,
+ unitUrl,
+ learningContextId: libraryLearningContextId,
+ blockId: libraryV1Id,
}))
.toEqual(`${studioEndpointUrl}/library/${libraryLearningContextId}`);
});
@@ -60,24 +63,36 @@ describe('cms url methods', () => {
// });
it('returns empty url when given the v2 library', () => {
expect(returnUrl({
- studioEndpointUrl, unitUrl, learningContextId: libraryV2Id, blockId: libraryV2Id,
+ studioEndpointUrl,
+ unitUrl,
+ learningContextId: libraryV2Id,
+ blockId: libraryV2Id,
})).toEqual('');
});
it('returnUrl function should return url with studioEndpointUrl, unitUrl, and blockId', () => {
expect(returnUrl({
- studioEndpointUrl, unitUrl, learningContextId: courseId, blockId,
+ studioEndpointUrl,
+ unitUrl,
+ learningContextId: courseId,
+ blockId,
}))
.toEqual(`${studioEndpointUrl}/container/${unitUrl.data.ancestors[0].id}#${blockId}`);
});
it('returns blank url for v2 block', () => {
expect(returnUrl({
- studioEndpointUrl, unitUrl, learningContextId: courseId, blockId: v2BlockId,
+ studioEndpointUrl,
+ unitUrl,
+ learningContextId: courseId,
+ blockId: v2BlockId,
}))
.toEqual('');
});
it('throws error if no unit url', () => {
expect(returnUrl({
- studioEndpointUrl, unitUrl: null, learningContextId: courseId, blockId,
+ studioEndpointUrl,
+ unitUrl: null,
+ learningContextId: courseId,
+ blockId,
}))
.toEqual('');
});
@@ -106,7 +121,9 @@ describe('cms url methods', () => {
.toEqual(`${block({ studioEndpointUrl, blockId })}?fields=ancestorInfo`);
});
it('throws error with studioEndpointUrl, v2 blockId and ancestor query', () => {
- expect(() => { blockAncestor({ studioEndpointUrl, blockId: v2BlockId }); })
+ expect(() => {
+ blockAncestor({ studioEndpointUrl, blockId: v2BlockId });
+ })
.toThrow('Block ancestor not available (and not needed) for V2 blocks');
});
});
diff --git a/src/editors/data/services/cms/urls.ts b/src/editors/data/services/cms/urls.ts
index 408a57055f..d24bd6bcc2 100644
--- a/src/editors/data/services/cms/urls.ts
+++ b/src/editors/data/services/cms/urls.ts
@@ -16,7 +16,10 @@ export const unit = ({ studioEndpointUrl, unitUrl, blockId }) => (
);
export const returnUrl = ({
- studioEndpointUrl, unitUrl, learningContextId, blockId,
+ studioEndpointUrl,
+ unitUrl,
+ learningContextId,
+ blockId,
}): string => {
// Is this a v1 library?
if (isLibraryV1Key(learningContextId)) {
diff --git a/src/editors/decisions/0002-text-editor-adr.md b/src/editors/decisions/0002-text-editor-adr.md
index 34b3cc1d59..e102f4eeb0 100644
--- a/src/editors/decisions/0002-text-editor-adr.md
+++ b/src/editors/decisions/0002-text-editor-adr.md
@@ -16,12 +16,13 @@ a user-friendly interface".
1. Rely on cross-editor XBlock network access support, per "Network Request Layer" ADR in this repo
2. Continue using the tinyMCE editor
3. Wrap the tinyMCE editor so as to be able to handle it as a vanilla React component
-4. Use a mix of configuration and tinyMCE API calls to customize the editor as needed
- * (e.g., offer image upload and image gallery selection)
-
+4. Use a mix of configuration and tinyMCE API calls to customize the editor as needed
+ - (e.g., offer image upload and image gallery selection)
+
# Consequences
## Rely on editors-wide XBlock API (network access) decision
+
No complexity associated with CRUD operations on XBlock content, irrespective of where the XBlocks are stored.
## Continue using the tinyMCE editor
@@ -35,8 +36,8 @@ Wrapping of the tinyMCE editor to behave like a react component is done by the s
Interaction with the tinyMCE editor is via a reference, saved at editor initialization.
When wrapping the tinyMCE component we assign a `ref` to the created component so that we can access its state and apis to update the content and draw it back out.
-
-* initialize with html content from xblock
+
+- initialize with html content from xblock
# Editor customization
@@ -48,12 +49,13 @@ specifically including the image upload/settings modal.
Much of the editor configuration is actually defined in `TextEditor/pluginConfig.js`, and the editorHook mostly draws from this configuration to populate the editor."
## Image upload/gallery selection
+
The tinyMCE editor is extended to offer an image upload/select button. When the end-user pushes this button, the editor's window is occluded by a modal dialog capable of uploading an image. The end-user can also interact with this modal window to toggle between uploading a new image, or selecting from among previously uploaded images (aka, the image gallery), to save, or to cancel out.
On its initialization, the tinyMCE editor is provided with an icon and a callback to associate with the image upload button.
-* Tiny MCE needs a "configured" button to open the modal dialog to select/upload an image.
- * This verbiage is somewhat important distinction, because this is a configuration, not a coding feature
+- Tiny MCE needs a "configured" button to open the modal dialog to select/upload an image.
+ - This verbiage is somewhat important distinction, because this is a configuration, not a coding feature
Later, on invocation of the modal dialog, this window is initialized with a reference to the tinyMCE editor.
If the modal window is driven to a save operation on an uploaded or a selected image, the window uses this reference to provide an image tag and image metadata to the tinyMCE editor, for inclusion at the current cursor location.
@@ -61,9 +63,8 @@ If the modal window is driven to a save operation on an uploaded or a selected i
The wrapping modal around upload/settings has a hook that calls the editor execCommand to insert the image tag on a button click.
The hook runs before everything renders and produces a button callback that will save a passed image to the (_sic_ tinyMCE) editor context
-* [on image upload or gallery selection] insert image tag at cursor location with source, dimensions, and alt text
-* [on image update] Update and replace a given image tag selection with a new one, updating source, dimensions, and/or alt-text
- * Update and replace are utilizing exposed tinyMCE editor api accessed from the ref associated with the created component.
-* Modal must have a "Save" option that inserts appropriately formatted tags into the tinyMCE editor context.
- * Does not always update on relinquishing control, and communicates nothing on cancel
-
+- [on image upload or gallery selection] insert image tag at cursor location with source, dimensions, and alt text
+- [on image update] Update and replace a given image tag selection with a new one, updating source, dimensions, and/or alt-text
+ - Update and replace are utilizing exposed tinyMCE editor api accessed from the ref associated with the created component.
+- Modal must have a "Save" option that inserts appropriately formatted tags into the tinyMCE editor context.
+ - Does not always update on relinquishing control, and communicates nothing on cancel
diff --git a/src/editors/decisions/0005-internal-editor-testability-decisions.md b/src/editors/decisions/0005-internal-editor-testability-decisions.md
index dc6e9e76bd..eab3149264 100644
--- a/src/editors/decisions/0005-internal-editor-testability-decisions.md
+++ b/src/editors/decisions/0005-internal-editor-testability-decisions.md
@@ -1,25 +1,29 @@
# Internal editor testability decision
# Increased complexity for the sake of testability
+
The internally-managed editors in this repo (as of now planned to include text, video, and problem types) follow a number of patterns that increase the complexity of parts of the code slightly, in favor of providing increased testability around their behavior.
## Note - Strict Dictionaries
-Javacript is generally fairly lackadaisical with regards to dictionary access of missing/invalid keys. This is fine and expected in many cases, but also prevents us from using dictionary access on something like a key store to ensure we are calling something that actually exists.
+
+Javacript is generally fairly lackadaisical with regards to dictionary access of missing/invalid keys. This is fine and expected in many cases, but also prevents us from using dictionary access on something like a key store to ensure we are calling something that actually exists.
For this purpose, there are a pair of utilities in this repo called `StrictDict` and `keyStore`.
`StrictDict` takes an object and returns a version that will complain (throw an error) if called with an invalid key.
-`keyStore` takes an object and returns a StrictDict of just the keys of that object. (this is useful particularly for mocking and spying on specific methods and fields)
+`keyStore` takes an object and returns a StrictDict of just the keys of that object. (this is useful particularly for mocking and spying on specific methods and fields)
## Note - Self imports
-Javascript webpack imports can be problematic around the specific issue of attempting to mock a single method being used in another method in the same file.
-Problem: File A includes methodA and methodB (which calls methodA). We want to be able to test methodA and then test methodB *without* having to re-test methodA as part of that test. We want to be able to mock methodA *only* while we are testing methodB.
+Javascript webpack imports can be problematic around the specific issue of attempting to mock a single method being used in another method in the same file.
+
+Problem: File A includes methodA and methodB (which calls methodA). We want to be able to test methodA and then test methodB _without_ having to re-test methodA as part of that test. We want to be able to mock methodA _only_ while we are testing methodB.
-Solution: Self-imports. By importing the module into itself (which webpack handles nicely, don't worry), we provide tests the ability to spy on and mock individual methods from that module separately on a per-test basis.
+Solution: Self-imports. By importing the module into itself (which webpack handles nicely, don't worry), we provide tests the ability to spy on and mock individual methods from that module separately on a per-test basis.
Ex:
+
```javascript
// myFile.js
import * as module from './myFile';
@@ -49,7 +53,8 @@ describe('myFile', () => {
```
## Hooks and Snapshots - Separation from components for increased viability of snapshots
-As part of the testing of these internal editors, we are relying on snapshot testing to ensure stability of the display of the components themselves. This can be a fragile solution in certain situations where components are too large or complex to adequately snapshot and verify.
+
+As part of the testing of these internal editors, we are relying on snapshot testing to ensure stability of the display of the components themselves. This can be a fragile solution in certain situations where components are too large or complex to adequately snapshot and verify.
For this purpose, we have opted for a general pattern of separating all of the behavior of components withing these editors into separate `hooks` files.
@@ -57,13 +62,16 @@ These hook files contain methods that utilize both `react` and `react-redux` hoo
From there, components are tested by mocking out the behavior of these hooks to return verifyable data in the snapshots.
-As part of this separation, there are a number of additional patterns that are followed
+As part of this separation, there are a number of additional patterns that are followed
### Snapshot considerations
+
#### Callbacks
+
Any callback that is included in render in a component should be separated such that is is either passed in as a prop or derived from a hook, and should be mocked with a `mockName` using jest, to ensure that they are uniquely identifyable in the snapshots.
-Ex:
+Ex:
+
```javascript
const props = {
onClick: jest.fn().mockName('props.onClick');
@@ -72,11 +80,13 @@ expect(shallow( )).toMatchSnapshot();
```
#### Imported components
-Imported compoents are mocked to return simple string components based on their existing name. This results in shallow renders that display the components by name, with passed props, but do not attempt to render *any* logic from those components.
+
+Imported compoents are mocked to return simple string components based on their existing name. This results in shallow renders that display the components by name, with passed props, but do not attempt to render _any_ logic from those components.
This is a bit more complex for components with sub-components, but we have provided a test utility in `src/testUtils` called `mockNestedComponent` that will allow you to easily mock these for your snapshots as well.
Ex:
+
```javascript
jest.mock('componentModule', () => {
const { mockNestedComponent } = jest.requireActual('./testUtils');
@@ -88,11 +98,15 @@ jest.mock('componentModule', () => {
}),
});
```
+
#### Top-level mocked imports
+
We have mocked out all paragon components and icons being used in the repo, as well as a number of other common methods, hooks, and components in our module's `setupTests` file, which will ensure that those components show up reasonably in snapshots.
### Hook Considerations
+
#### useState and mockUseState
+
React's useState hook is a very powerful alternative to class components, but is also somewhat problematic to test, as it returns different values based on where it is called in a hook, as well as based on previous runs of that hook.
To resolve this, we are using a custom test utility to mock a hook modules state values for easy testing.
@@ -100,6 +114,7 @@ To resolve this, we are using a custom test utility to mock a hook modules state
This requires a particular structure to hook modules that use the useState, for the sake of enabling the mock process (which is documented with the utility).
Ex:
+
```javascript
import * as module from './hooks';
const state = {
@@ -109,25 +124,30 @@ const myHook = () => {
const [myStateValue, setMyStateValue] = module.state.myStateValue('initialValue');
};
```
+
Examples on how to use this for testing are included with the mock class in `src/testUtils`
#### useCallback, useEffect
+
These hooks provide behavior that calls a method based on given prerequisite behaviors.
For this reason, we use general-purpose mocks for these hooks that return an object containing the passed callback and prerequisites for easy test access.
#### Additional Considrations
-*useIntl not available*
-We are using react-intl under the hood for our i18n support, but do not have access to some of the more recent features in that library due to the pinned version in frontend-platform. Specifically, this includes a `useIntl` hook available in later versions that is still unavailable to us, requiring us to use the older `injectIntl` pattern.
+_useIntl not available_
+
+We are using react-intl under the hood for our i18n support, but do not have access to some of the more recent features in that library due to the pinned version in frontend-platform. Specifically, this includes a `useIntl` hook available in later versions that is still unavailable to us, requiring us to use the older `injectIntl` pattern.
-*useDispatch*
+_useDispatch_
-React-redux's `useDispatch` hook does not play nicely with being called in a method called by a component, and really wants to be called *in* the component. For this reason, the dispatch method is generated in components and passed through to hook components.
+React-redux's `useDispatch` hook does not play nicely with being called in a method called by a component, and really wants to be called _in_ the component. For this reason, the dispatch method is generated in components and passed through to hook components.
## Notes for integration testing
+
Because of the top-level mocks in setupTest, any integration tests will need to be sure to unmock most of these.
Ex:
+
```javascript
jest.unmock('@edx/frontend-platform/i18n');
jest.unmock('@openedx/paragon');
diff --git a/src/editors/editorTestRender.tsx b/src/editors/editorTestRender.tsx
index 79c2f995f2..d374c880d4 100644
--- a/src/editors/editorTestRender.tsx
+++ b/src/editors/editorTestRender.tsx
@@ -9,7 +9,6 @@ import { initializeStore, type PartialEditorState } from './data/redux'; // adju
*
* Wraps the provided UI in both the EditorContextProvider and Redux Provider,
* ensuring that components under test have access to the necessary context and store.
- *
*/
export const editorRender = (
ui: React.ReactElement,
@@ -17,7 +16,7 @@ export const editorRender = (
initialState = {},
learningContextId = 'course-v1:Org+COURSE+RUN',
...options
- }: Omit & { initialState?: PartialEditorState, learningContextId?: string } = {},
+ }: Omit & { initialState?: PartialEditorState; learningContextId?: string; } = {},
) => {
// We might need a way for the test cases to access this store directly. In that case we could allow either an
// initialState parameter OR an editorStore parameter.
diff --git a/src/editors/example.jsx b/src/editors/example.jsx
index 63abb78c00..3480ab27ae 100644
--- a/src/editors/example.jsx
+++ b/src/editors/example.jsx
@@ -63,9 +63,8 @@ export const ThumbEditor = (
)
: (
- Your Editor Goes here.
- You can get at the xblock data with the blockValue field.
- here is what is in your xblock: {JSON.stringify(blockValue)}
+ Your Editor Goes here. You can get at the xblock data with the blockValue field. here is what is in your
+ xblock: {JSON.stringify(blockValue)}
)}
diff --git a/src/editors/hooks.ts b/src/editors/hooks.ts
index 5669dd6527..d7006da84e 100644
--- a/src/editors/hooks.ts
+++ b/src/editors/hooks.ts
@@ -25,7 +25,8 @@ export const navigateCallback = ({
destination,
analyticsEvent,
analytics,
-}) => (response) => {
+}) =>
+(response) => {
if (process.env.NODE_ENV !== 'development' && analyticsEvent && analytics) {
sendTrackEvent(analyticsEvent, analytics);
}
@@ -91,8 +92,10 @@ export const createBlock = ({
};
export const clearSaveError = ({
dispatch,
-}) => () => dispatch(actions.requests.clearRequest({ requestKey: RequestKeys.saveBlock }));
+}) =>
+() => dispatch(actions.requests.clearRequest({ requestKey: RequestKeys.saveBlock }));
export const clearCreateError = ({
dispatch,
-}) => () => dispatch(actions.requests.clearRequest({ requestKey: RequestKeys.createBlock }));
+}) =>
+() => dispatch(actions.requests.clearRequest({ requestKey: RequestKeys.createBlock }));
diff --git a/src/editors/setupEditorTest.js b/src/editors/setupEditorTest.js
index efccc0bc13..85c5885af8 100644
--- a/src/editors/setupEditorTest.js
+++ b/src/editors/setupEditorTest.js
@@ -26,82 +26,83 @@ jest.mock('@edx/frontend-platform/i18n', () => {
};
});
-jest.mock('@openedx/paragon', () => jest.requireActual('./testUtils').mockNestedComponents({
- Alert: {
- Heading: 'Alert.Heading',
- },
- AlertModal: 'AlertModal',
- ActionRow: {
- Spacer: 'ActionRow.Spacer',
- },
- Badge: 'Badge',
- Button: 'Button',
- ButtonGroup: 'ButtonGroup',
- Collapsible: {
- Advanced: 'Advanced',
- Body: 'Body',
- Trigger: 'Trigger',
- Visible: 'Visible',
- },
- Card: {
- Header: 'Card.Header',
- Section: 'Card.Section',
- Footer: 'Card.Footer',
- Body: 'Card.Body',
- },
- CheckboxControl: 'CheckboxControl',
- Col: 'Col',
- Container: 'Container',
- Dropdown: {
- Item: 'Dropdown.Item',
- Menu: 'Dropdown.Menu',
- Toggle: 'Dropdown.Toggle',
- },
- ErrorContext: {
- Provider: 'ErrorContext.Provider',
- },
- Hyperlink: 'Hyperlink',
- Icon: 'Icon',
- IconButton: 'IconButton',
- IconButtonWithTooltip: 'IconButtonWithTooltip',
- Image: 'Image',
- MailtoLink: 'MailtoLink',
- ModalDialog: {
- Footer: 'ModalDialog.Footer',
- Header: 'ModalDialog.Header',
- Title: 'ModalDialog.Title',
- Body: 'ModalDialog.Body',
- CloseButton: 'ModalDialog.CloseButton',
- },
- Form: {
- Checkbox: 'Form.Checkbox',
- Control: {
- Feedback: 'Form.Control.Feedback',
+jest.mock('@openedx/paragon', () =>
+ jest.requireActual('./testUtils').mockNestedComponents({
+ Alert: {
+ Heading: 'Alert.Heading',
+ },
+ AlertModal: 'AlertModal',
+ ActionRow: {
+ Spacer: 'ActionRow.Spacer',
+ },
+ Badge: 'Badge',
+ Button: 'Button',
+ ButtonGroup: 'ButtonGroup',
+ Collapsible: {
+ Advanced: 'Advanced',
+ Body: 'Body',
+ Trigger: 'Trigger',
+ Visible: 'Visible',
+ },
+ Card: {
+ Header: 'Card.Header',
+ Section: 'Card.Section',
+ Footer: 'Card.Footer',
+ Body: 'Card.Body',
+ },
+ CheckboxControl: 'CheckboxControl',
+ Col: 'Col',
+ Container: 'Container',
+ Dropdown: {
+ Item: 'Dropdown.Item',
+ Menu: 'Dropdown.Menu',
+ Toggle: 'Dropdown.Toggle',
+ },
+ ErrorContext: {
+ Provider: 'ErrorContext.Provider',
+ },
+ Hyperlink: 'Hyperlink',
+ Icon: 'Icon',
+ IconButton: 'IconButton',
+ IconButtonWithTooltip: 'IconButtonWithTooltip',
+ Image: 'Image',
+ MailtoLink: 'MailtoLink',
+ ModalDialog: {
+ Footer: 'ModalDialog.Footer',
+ Header: 'ModalDialog.Header',
+ Title: 'ModalDialog.Title',
+ Body: 'ModalDialog.Body',
+ CloseButton: 'ModalDialog.CloseButton',
+ },
+ Form: {
+ Checkbox: 'Form.Checkbox',
+ Control: {
+ Feedback: 'Form.Control.Feedback',
+ },
+ Group: 'Form.Group',
+ Label: 'Form.Label',
+ Text: 'Form.Text',
+ Row: 'Form.Row',
+ Radio: 'Radio',
+ RadioSet: 'RadioSet',
+ },
+ OverlayTrigger: 'OverlayTrigger',
+ Tooltip: 'Tooltip',
+ FullscreenModal: 'FullscreenModal',
+ Row: 'Row',
+ Scrollable: 'Scrollable',
+ SelectableBox: {
+ Set: 'SelectableBox.Set',
},
- Group: 'Form.Group',
- Label: 'Form.Label',
- Text: 'Form.Text',
- Row: 'Form.Row',
- Radio: 'Radio',
- RadioSet: 'RadioSet',
- },
- OverlayTrigger: 'OverlayTrigger',
- Tooltip: 'Tooltip',
- FullscreenModal: 'FullscreenModal',
- Row: 'Row',
- Scrollable: 'Scrollable',
- SelectableBox: {
- Set: 'SelectableBox.Set',
- },
- Spinner: 'Spinner',
- Stack: 'Stack',
- Toast: 'Toast',
- Truncate: {
- Deprecated: 'Truncate.Deprecated',
- },
- useWindowSize: { height: '500px' },
-}));
+ Spinner: 'Spinner',
+ Stack: 'Stack',
+ Toast: 'Toast',
+ Truncate: {
+ Deprecated: 'Truncate.Deprecated',
+ },
+ useWindowSize: { height: '500px' },
+ }));
jest.mock('@openedx/paragon/icons', () => ({
Close: jest.fn().mockName('icons.Close'),
diff --git a/src/editors/sharedComponents/BaseModal/messages.ts b/src/editors/sharedComponents/BaseModal/messages.ts
index 8a5823b459..85a9cc3bb3 100644
--- a/src/editors/sharedComponents/BaseModal/messages.ts
+++ b/src/editors/sharedComponents/BaseModal/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
cancelButtonLabel: {
id: 'authoring.baseModal.cancelButtonLabel',
defaultMessage: 'Cancel',
diff --git a/src/editors/sharedComponents/Button/index.jsx b/src/editors/sharedComponents/Button/index.jsx
index 29e28294bd..ce89f512f8 100644
--- a/src/editors/sharedComponents/Button/index.jsx
+++ b/src/editors/sharedComponents/Button/index.jsx
@@ -7,7 +7,11 @@ import { getButtonProps } from './hooks';
import './index.scss';
const Button = ({
- variant, className, text, children, ...props
+ variant,
+ className,
+ text,
+ children,
+ ...props
}) => (
,
+ label: string;
+ id: string;
+ hint: string;
+ disabled?: boolean;
+ fieldConfig: string | FieldHookConfig;
}
const CheckboxField: React.FC = ({
- label, id, hint = '', disabled = false, fieldConfig,
+ label,
+ id,
+ hint = '',
+ disabled = false,
+ fieldConfig,
}) => {
const [field, meta] = useField(fieldConfig);
return (
diff --git a/src/editors/sharedComponents/CodeEditor/index.jsx b/src/editors/sharedComponents/CodeEditor/index.jsx
index 6e18862cf2..68e57753d2 100644
--- a/src/editors/sharedComponents/CodeEditor/index.jsx
+++ b/src/editors/sharedComponents/CodeEditor/index.jsx
@@ -20,7 +20,10 @@ const CodeEditor = ({
const DOMref = useRef();
const btnRef = useRef();
hooks.createCodeMirrorDomNode({
- ref: DOMref, initialText: value, upstreamRef: innerRef, lang,
+ ref: DOMref,
+ initialText: value,
+ upstreamRef: innerRef,
+ lang,
});
const { showBtnEscapeHTML, hideBtn } = hooks.prepareShowBtnEscapeHTML();
diff --git a/src/editors/sharedComponents/CodeEditor/index.test.tsx b/src/editors/sharedComponents/CodeEditor/index.test.tsx
index 7c9ab7853c..7acec9812b 100644
--- a/src/editors/sharedComponents/CodeEditor/index.test.tsx
+++ b/src/editors/sharedComponents/CodeEditor/index.test.tsx
@@ -1,6 +1,9 @@
import React from 'react';
import {
- render, screen, initializeMocks, fireEvent,
+ render,
+ screen,
+ initializeMocks,
+ fireEvent,
} from '@src/testUtils';
import { waitFor } from '@testing-library/react';
import { formatMessage, MockUseState } from '../../testUtils';
@@ -25,14 +28,18 @@ describe('CodeEditor', () => {
hook.hideBtn();
expect(state.setState.showBtnEscapeHTML).toHaveBeenCalledWith(false);
});
- afterEach(() => { state.restore(); });
+ afterEach(() => {
+ state.restore();
+ });
});
describe('cleanHTML', () => {
const dirtyText = `&${Object.keys(alphanumericMap).join('; , &')};`;
const cleanText = `${Object.values(alphanumericMap).join(' , ')}`;
- const dirtyTextWithAlt = ' and ≤ and ≥';
- const cleanTextWithAlt = ' and ≤ and ≥';
+ const dirtyTextWithAlt =
+ ' and ≤ and ≥';
+ const cleanTextWithAlt =
+ ' and ≤ and ≥';
it('escapes alphanumerics and sets them to be literals', () => {
expect(hooks.cleanHTML({ initialText: dirtyText })).toEqual(cleanText);
diff --git a/src/editors/sharedComponents/CodeEditor/messages.ts b/src/editors/sharedComponents/CodeEditor/messages.ts
index 84c5554653..b7fe0a975d 100644
--- a/src/editors/sharedComponents/CodeEditor/messages.ts
+++ b/src/editors/sharedComponents/CodeEditor/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
escapeHTMLButtonLabel: {
id: 'authoring.texteditor.codeEditor.escapeHTMLButton',
defaultMessage: 'Unescape HTML Literals',
diff --git a/src/editors/sharedComponents/CollapsibleFormWidget/CollapsibleFormWidget.jsx b/src/editors/sharedComponents/CollapsibleFormWidget/CollapsibleFormWidget.jsx
index 91a575919c..f2939ce302 100644
--- a/src/editors/sharedComponents/CollapsibleFormWidget/CollapsibleFormWidget.jsx
+++ b/src/editors/sharedComponents/CollapsibleFormWidget/CollapsibleFormWidget.jsx
@@ -39,13 +39,23 @@ const CollapsibleFormWidget = ({
{isError && }
-
+
{title}
-
+
diff --git a/src/editors/sharedComponents/CollapsibleFormWidget/CollapsibleFormWidget.test.tsx b/src/editors/sharedComponents/CollapsibleFormWidget/CollapsibleFormWidget.test.tsx
index 6e3bcdb440..94abe86918 100644
--- a/src/editors/sharedComponents/CollapsibleFormWidget/CollapsibleFormWidget.test.tsx
+++ b/src/editors/sharedComponents/CollapsibleFormWidget/CollapsibleFormWidget.test.tsx
@@ -1,6 +1,8 @@
import React from 'react';
import {
- render, screen, initializeMocks,
+ render,
+ screen,
+ initializeMocks,
} from '@src/testUtils';
import CollapsibleFormWidget from './CollapsibleFormWidget';
@@ -11,7 +13,7 @@ describe('CollapsibleFormWidget', () => {
title: 'Sample title',
fontSize: 'x-small',
};
- const testContent = (
Some test string
);
+ const testContent =
Some test string
;
beforeEach(() => {
initializeMocks();
diff --git a/src/editors/sharedComponents/ErrorAlerts/ErrorAlert.test.tsx b/src/editors/sharedComponents/ErrorAlerts/ErrorAlert.test.tsx
index 4ef684acdf..ee19965269 100644
--- a/src/editors/sharedComponents/ErrorAlerts/ErrorAlert.test.tsx
+++ b/src/editors/sharedComponents/ErrorAlerts/ErrorAlert.test.tsx
@@ -1,6 +1,9 @@
import React from 'react';
import {
- render, screen, fireEvent, initializeMocks,
+ render,
+ screen,
+ fireEvent,
+ initializeMocks,
} from '../../../testUtils';
import ErrorAlert, { hooks } from './ErrorAlert';
diff --git a/src/editors/sharedComponents/ErrorAlerts/ErrorAlert.tsx b/src/editors/sharedComponents/ErrorAlerts/ErrorAlert.tsx
index 0ba85c63fd..ea8b481a13 100644
--- a/src/editors/sharedComponents/ErrorAlerts/ErrorAlert.tsx
+++ b/src/editors/sharedComponents/ErrorAlerts/ErrorAlert.tsx
@@ -8,7 +8,7 @@ import messages from './messages';
export const hooks = {
state: {
- // eslint-disable-next-line react-hooks/rules-of-hooks
+ // eslint-disable-next-line react-hooks/rules-of-hooks
isDismissed: (val) => React.useState(val),
},
dismissalHooks: ({ dismissError, isError }) => {
@@ -33,9 +33,9 @@ export const hooks = {
};
declare interface ErrorAlertProps {
- dismissError?: () => void,
- hideHeading?: boolean,
- isError: boolean,
+ dismissError?: () => void;
+ hideHeading?: boolean;
+ isError: boolean;
}
const ErrorAlert: React.FC
> = ({
diff --git a/src/editors/sharedComponents/ErrorAlerts/FetchErrorAlert.jsx b/src/editors/sharedComponents/ErrorAlerts/FetchErrorAlert.jsx
index e8a8167174..230657edd7 100644
--- a/src/editors/sharedComponents/ErrorAlerts/FetchErrorAlert.jsx
+++ b/src/editors/sharedComponents/ErrorAlerts/FetchErrorAlert.jsx
@@ -24,7 +24,6 @@ FetchErrorAlert.propTypes = {
description: PropTypes.string,
}).isRequired,
isFetchError: PropTypes.bool.isRequired,
-
};
export default FetchErrorAlert;
diff --git a/src/editors/sharedComponents/ErrorAlerts/messages.ts b/src/editors/sharedComponents/ErrorAlerts/messages.ts
index 7857cc991d..a885f5def2 100644
--- a/src/editors/sharedComponents/ErrorAlerts/messages.ts
+++ b/src/editors/sharedComponents/ErrorAlerts/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
errorTitle: {
id: 'authoring.texteditor.selectimagemodal.error.errorTitle',
defaultMessage: 'Error',
diff --git a/src/editors/sharedComponents/ErrorBoundary/ErrorPage.jsx b/src/editors/sharedComponents/ErrorBoundary/ErrorPage.jsx
index 36e7614ffe..7ac36ba6ad 100644
--- a/src/editors/sharedComponents/ErrorBoundary/ErrorPage.jsx
+++ b/src/editors/sharedComponents/ErrorBoundary/ErrorPage.jsx
@@ -1,7 +1,10 @@
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import {
- Button, Container, Row, Col,
+ Button,
+ Container,
+ Row,
+ Col,
} from '@openedx/paragon';
import { useIntl } from '@edx/frontend-platform/i18n';
import messages from './messages';
@@ -38,15 +41,17 @@ const ErrorPage = ({
)}
- {learningContextId && (unitUrl && outlineType !== 'library' ? (
- navigateTo(unitUrl)}>
- {intl.formatMessage(messages.returnToUnitPageLabel)}
-
- ) : (
- navigateTo(outlineUrl)}>
- {intl.formatMessage(messages.returnToOutlineLabel, { outlineType })}
-
- ))}
+ {learningContextId && (unitUrl && outlineType !== 'library' ?
+ (
+ navigateTo(unitUrl)}>
+ {intl.formatMessage(messages.returnToUnitPageLabel)}
+
+ ) :
+ (
+ navigateTo(outlineUrl)}>
+ {intl.formatMessage(messages.returnToOutlineLabel, { outlineType })}
+
+ ))}
global.location.reload()}>
{intl.formatMessage(messages.unexpectedErrorButtonLabel)}
diff --git a/src/editors/sharedComponents/ErrorBoundary/index.test.jsx b/src/editors/sharedComponents/ErrorBoundary/index.test.jsx
index 7f6ef81297..4d7fe4e20a 100644
--- a/src/editors/sharedComponents/ErrorBoundary/index.test.jsx
+++ b/src/editors/sharedComponents/ErrorBoundary/index.test.jsx
@@ -11,9 +11,10 @@ jest.mock('@edx/frontend-platform/logging', () => ({
}));
// stubbing this to avoid needing to inject a stubbed intl into an internal component
-jest.mock('./ErrorPage', () => function mockErrorPage() {
- return Error Page
;
-});
+jest.mock('./ErrorPage', () =>
+ function mockErrorPage() {
+ return Error Page
;
+ });
describe('ErrorBoundary', () => {
it('should render children if no error', () => {
diff --git a/src/editors/sharedComponents/FileInput/index.test.jsx b/src/editors/sharedComponents/FileInput/index.test.jsx
index 8ce4e3af1b..376e099e2b 100644
--- a/src/editors/sharedComponents/FileInput/index.test.jsx
+++ b/src/editors/sharedComponents/FileInput/index.test.jsx
@@ -15,7 +15,9 @@ describe('FileInput component', () => {
acceptedFiles: '.srt',
fileInput: {
addFile: () => mockOnChange(),
- ref: (input) => { container.ref = input; },
+ ref: (input) => {
+ container.ref = input;
+ },
},
};
el = render( );
diff --git a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/AltTextControls.jsx b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/AltTextControls.jsx
index e4ece2222a..00518a8c9e 100644
--- a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/AltTextControls.jsx
+++ b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/AltTextControls.jsx
@@ -39,11 +39,11 @@ const AltTextControls = ({
value={value}
/>
{validation.show
- && (
-
-
-
- )}
+ && (
+
+
+
+ )}
{
test('renders component on screen', () => {
render( );
- expect(screen.getByRole('checkbox', { name: 'This image is decorative (no alt text required).' })).toBeInTheDocument();
+ expect(screen.getByRole('checkbox', { name: 'This image is decorative (no alt text required).' }))
+ .toBeInTheDocument();
expect(screen.getByRole('textbox', { name: 'Accessibility' })).toBeInTheDocument();
});
diff --git a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/DimensionControls.jsx b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/DimensionControls.jsx
index c9b56e07e1..29f4ea4fa2 100644
--- a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/DimensionControls.jsx
+++ b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/DimensionControls.jsx
@@ -57,11 +57,9 @@ const DimensionControls = ({
/>
{
const dimensions = hooks.dimensionHooks('altText');
useEffect(() => {
- dimensions.onImgLoad({ })({ target: { naturalWidth: 1517, naturalHeight: 803 } });
+ dimensions.onImgLoad({})({ target: { naturalWidth: 1517, naturalHeight: 803 } });
}, []);
return ;
@@ -19,7 +23,7 @@ const UnlockedDimensionControls = () => {
const dimensions = hooks.dimensionHooks('altText');
useEffect(() => {
- dimensions.onImgLoad({ })({ target: { naturalWidth: 1517, naturalHeight: 803 } });
+ dimensions.onImgLoad({})({ target: { naturalWidth: 1517, naturalHeight: 803 } });
dimensions.unlock();
}, []);
diff --git a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/hooks.js b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/hooks.js
index c89044f623..5d9e26657e 100644
--- a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/hooks.js
+++ b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/hooks.js
@@ -207,12 +207,13 @@ export const dimensionHooks = (altTextHook) => {
value: local,
setHeight,
setWidth,
- updateDimensions: () => setAll(module.getValidDimensions({
- dimensions,
- local,
- isLocked,
- lockAspectRatio,
- })),
+ updateDimensions: () =>
+ setAll(module.getValidDimensions({
+ dimensions,
+ local,
+ isLocked,
+ lockAspectRatio,
+ })),
};
};
@@ -320,15 +321,18 @@ export const onSaveClick = ({
dimensions,
isDecorative,
saveToEditor,
-}) => () => {
- if (module.checkFormValidation({
- altText: altText.value,
- isDecorative,
- onAltTextFail: () => {
- altText.error.set();
- altText.validation.set();
- },
- })) {
+}) =>
+() => {
+ if (
+ module.checkFormValidation({
+ altText: altText.value,
+ isDecorative,
+ onAltTextFail: () => {
+ altText.error.set();
+ altText.validation.set();
+ },
+ })
+ ) {
altText.error.dismiss();
altText.validation.dismiss();
// Replaces double quotes with " to prevent the alt text from being truncated
diff --git a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/hooks.test.js b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/hooks.test.js
index 78d34714fb..300ceec33d 100644
--- a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/hooks.test.js
+++ b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/hooks.test.js
@@ -19,10 +19,12 @@ const multiDims = {
const state = new MockUseState(hooks);
-const hookKeys = StrictDict(Object.keys(hooks).reduce(
- (obj, key) => ({ ...obj, [key]: key }),
- {},
-));
+const hookKeys = StrictDict(
+ Object.keys(hooks).reduce(
+ (obj, key) => ({ ...obj, [key]: key }),
+ {},
+ ),
+);
let hook;
@@ -30,12 +32,13 @@ const testVal = 'MY test VALUE';
describe('state values', () => {
const testStateMethod = (key) => {
- // eslint-disable-next-line react-hooks/rules-of-hooks
+ // eslint-disable-next-line react-hooks/rules-of-hooks
expect(hooks.state[key](testVal)).toEqual(React.useState(testVal));
};
test('provides altText state value', () => testStateMethod(state.keys.altText));
test('provides dimensions state value', () => testStateMethod(state.keys.dimensions));
- test('provides showAltTextDismissibleError state value', () => testStateMethod(state.keys.showAltTextDismissibleError));
+ test('provides showAltTextDismissibleError state value', () =>
+ testStateMethod(state.keys.showAltTextDismissibleError));
test('provides showAltTextSubmissionError state value', () => testStateMethod(state.keys.showAltTextSubmissionError));
test('provides isDecorative state value', () => testStateMethod(state.keys.isDecorative));
test('provides isLocked state value', () => testStateMethod(state.keys.isLocked));
diff --git a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/index.jsx b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/index.jsx
index cc93a2ae55..4d41f03fbd 100644
--- a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/index.jsx
+++ b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/index.jsx
@@ -42,14 +42,14 @@ const ImageSettingsModal = ({
return (
- )}
+ }
isOpen={isOpen}
title={intl.formatMessage(messages.titleLabel)}
>
diff --git a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/messages.ts b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/messages.ts
index a20a492a01..4fb362faef 100644
--- a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/messages.ts
+++ b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
// index
titleLabel: {
id: 'authoring.texteditor.imagesettingsmodal.titleLabel',
@@ -47,7 +46,7 @@ const messages = defineMessages({
},
decorativeDimensionCheckboxLabel: {
id: 'authoring.texteditor.imagesettingsmodal.decorativeDimensionCheckboxLabel',
- defaultMessage: "Use percentages for the image's width and height",
+ defaultMessage: 'Use percentages for the image\'s width and height',
description: 'Checkbox label for whether or not an image uses percentages for width and height.',
},
diff --git a/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/hooks.js b/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/hooks.js
index 92a1f513ef..8f4efc5ad4 100644
--- a/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/hooks.js
+++ b/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/hooks.js
@@ -45,7 +45,8 @@ export const displayList = ({ sortBy, searchString, images }) => (
module.filteredList({
searchString,
imageList: images,
- }).sort(sortFunctions[sortBy in sortKeys ? sortKeys[sortBy] : sortKeys.dateNewest]));
+ }).sort(sortFunctions[sortBy in sortKeys ? sortKeys[sortBy] : sortKeys.dateNewest])
+);
export const imgListHooks = ({
searchSortProps,
@@ -124,13 +125,15 @@ export const fileInputHooks = ({ setSelection, clearSelection, imgList }) => {
const click = () => ref.current.click();
const addFile = (e) => {
const selectedFile = e.target.files[0];
- if (selectedFile && module.checkValidFileSize({
- selectedFile,
- clearSelection,
- onSizeFail: () => {
- imgList.inputError.set();
- },
- })) {
+ if (
+ selectedFile && module.checkValidFileSize({
+ selectedFile,
+ clearSelection,
+ onSizeFail: () => {
+ imgList.inputError.set();
+ },
+ })
+ ) {
dispatch(
thunkActions.app.uploadAsset({
file: selectedFile,
diff --git a/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/hooks.test.js b/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/hooks.test.js
index 4029bd9f0d..f7478b05af 100644
--- a/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/hooks.test.js
+++ b/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/hooks.test.js
@@ -51,8 +51,12 @@ describe('SelectImageModal hooks', () => {
});
describe('using state', () => {
- beforeEach(() => { state.mock(); });
- afterEach(() => { state.restore(); });
+ beforeEach(() => {
+ state.mock();
+ });
+ afterEach(() => {
+ state.restore();
+ });
describe('searchAndSortHooks', () => {
beforeEach(() => {
@@ -104,7 +108,6 @@ describe('SelectImageModal hooks', () => {
images: ['data1', 'data2', 'other distinct data'],
sortBy: sortKeys.dateNewest,
searchString: 'test search string',
-
};
const load = (loadProps = {}) => {
jest.spyOn(hooks, hookKeys.filteredList).mockImplementationOnce(
@@ -294,14 +297,19 @@ describe('SelectImageModal hooks', () => {
spies.file = jest.spyOn(hooks, hookKeys.fileInputHooks)
.mockReturnValueOnce(fileInputHooks);
hook = hooks.imgHooks({
- setSelection, clearSelection, images, imageCount,
+ setSelection,
+ clearSelection,
+ images,
+ imageCount,
});
});
it('forwards fileInputHooks as fileInput, called with uploadAsset prop', () => {
expect(hook.fileInput).toEqual(fileInputHooks);
expect(spies.file.mock.calls.length).toEqual(1);
expect(spies.file).toHaveBeenCalledWith({
- setSelection, clearSelection, imgList: imgListHooks,
+ setSelection,
+ clearSelection,
+ imgList: imgListHooks,
});
});
it('initializes imgListHooks with setSelection,searchAndSortHooks, and images', () => {
@@ -317,7 +325,9 @@ describe('SelectImageModal hooks', () => {
expect(hook.searchSortProps).toEqual(searchAndSortHooks);
expect(spies.file.mock.calls.length).toEqual(1);
expect(spies.file).toHaveBeenCalledWith({
- setSelection, clearSelection, imgList: imgListHooks,
+ setSelection,
+ clearSelection,
+ imgList: imgListHooks,
});
});
it('forwards galleryProps and selectBtnProps from the image list hooks', () => {
diff --git a/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/messages.ts b/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/messages.ts
index 14794b641f..b2ffae406c 100644
--- a/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/messages.ts
+++ b/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
nextButtonLabel: {
id: 'authoring.texteditor.selectimagemodal.next.label',
defaultMessage: 'Next',
@@ -43,8 +42,7 @@ const messages = defineMessages({
// Gallery
emptyGalleryLabel: {
id: 'authoring.texteditor.selectimagemodal.emptyGalleryLabel',
- defaultMessage:
- 'No images found in your gallery. Please upload an image using the button below.',
+ defaultMessage: 'No images found in your gallery. Please upload an image using the button below.',
description: 'Label for when image gallery is empty.',
},
@@ -61,16 +59,13 @@ const messages = defineMessages({
},
fileSizeError: {
id: 'authoring.texteditor.selectimagemodal.error.fileSizeError',
- defaultMessage:
- 'Images must be 10 MB or less. Please resize image and try again.',
- description:
- ' Message presented to user when file size of image is larger than 10 MB',
+ defaultMessage: 'Images must be 10 MB or less. Please resize image and try again.',
+ description: ' Message presented to user when file size of image is larger than 10 MB',
},
selectImageError: {
id: 'authoring.texteditor.selectimagemodal.error.selectImageError',
defaultMessage: 'Select an image to continue.',
- description:
- 'Message presented to user when clicking Next without selecting an image',
+ description: 'Message presented to user when clicking Next without selecting an image',
},
});
diff --git a/src/editors/sharedComponents/ImageUploadModal/index.jsx b/src/editors/sharedComponents/ImageUploadModal/index.jsx
index 07353c4845..3756eeb0bf 100644
--- a/src/editors/sharedComponents/ImageUploadModal/index.jsx
+++ b/src/editors/sharedComponents/ImageUploadModal/index.jsx
@@ -40,7 +40,12 @@ export const imgProps = ({
};
export const saveToEditor = ({
- settings, selection, lmsEndpointUrl, editorType, editorRef, isLibrary,
+ settings,
+ selection,
+ lmsEndpointUrl,
+ editorType,
+ editorRef,
+ isLibrary,
}) => {
const newImgTag = module.hooks.imgTag({
settings,
@@ -58,10 +63,17 @@ export const saveToEditor = ({
};
export const updateImagesRef = ({
- images, selection, height, width, newImage,
+ images,
+ selection,
+ height,
+ width,
+ newImage,
}) => {
const { result: mappedImages, foundMatch: imageAlreadyExists } = updateImageDimensions({
- images: images.current, url: selection.externalUrl, height, width,
+ images: images.current,
+ url: selection.externalUrl,
+ height,
+ width,
});
// eslint-disable-next-line no-param-reassign
@@ -69,7 +81,10 @@ export const updateImagesRef = ({
};
export const updateReactState = ({
- settings, selection, setSelection, images,
+ settings,
+ selection,
+ setSelection,
+ images,
}) => {
const { height, width } = settings.dimensions;
const newImage = {
@@ -80,7 +95,11 @@ export const updateReactState = ({
};
updateImagesRef({
- images, selection, height, width, newImage,
+ images,
+ selection,
+ height,
+ width,
+ newImage,
});
setSelection(newImage);
@@ -90,7 +109,8 @@ export const hooks = {
createSaveCallback: ({
close,
...args
- }) => (
+ }) =>
+ (
settings,
) => {
saveToEditor({ settings, ...args });
diff --git a/src/editors/sharedComponents/ImageUploadModal/index.test.tsx b/src/editors/sharedComponents/ImageUploadModal/index.test.tsx
index 4218f244cf..f16b1972f4 100644
--- a/src/editors/sharedComponents/ImageUploadModal/index.test.tsx
+++ b/src/editors/sharedComponents/ImageUploadModal/index.test.tsx
@@ -33,7 +33,8 @@ const mockImage = {
portableUrl: '/static/DALL_E_2023-03-10.png',
thumbnail: '/asset-v1:TestX+Test01+Test0101+type@thumbnail+block@DALL_E_2023-03-10.jpg',
locked: false,
- staticFullUrl: '/assets/courseware/v1/af2bf9ac70804e54c534107160a8e51e/asset-v1:TestX+Test01+Test0101+type@asset+block@DALL_E_2023-03-10.png',
+ staticFullUrl:
+ '/assets/courseware/v1/af2bf9ac70804e54c534107160a8e51e/asset-v1:TestX+Test01+Test0101+type@asset+block@DALL_E_2023-03-10.png',
id: 'asset-v1:TestX+Test01+Test0101+type@asset+block@DALL_E_2023-03-10.png',
width: 100,
height: 150,
@@ -95,7 +96,13 @@ describe('ImageUploadModal', () => {
beforeEach(() => {
output = hooks.createSaveCallback({
- close, settings, images, editorRef, setSelection, selection, lmsEndpointUrl,
+ close,
+ settings,
+ images,
+ editorRef,
+ setSelection,
+ selection,
+ lmsEndpointUrl,
});
});
afterEach(() => {
@@ -176,7 +183,7 @@ describe('ImageUploadModal', () => {
expect(container.querySelector('ImageSettingsModal')).toBeInTheDocument();
});
test('snapshot: selection has no externalUrl (Select Image Modal)', () => {
- const { container } = render( );
+ const { container } = render( );
expect(container.querySelector('SelectImageModal')).toBeInTheDocument();
});
test('snapshot: no selection (Select Image Modal)', () => {
diff --git a/src/editors/sharedComponents/RawEditor/index.jsx b/src/editors/sharedComponents/RawEditor/index.jsx
index a33540b0e0..b50d2b8437 100644
--- a/src/editors/sharedComponents/RawEditor/index.jsx
+++ b/src/editors/sharedComponents/RawEditor/index.jsx
@@ -25,15 +25,16 @@ const RawEditor = ({
You are using the raw {lang} editor.
)}
- { value ? (
-
- ) : null}
-
+ {value ?
+ (
+
+ ) :
+ null}
);
};
diff --git a/src/editors/sharedComponents/RawEditor/index.test.jsx b/src/editors/sharedComponents/RawEditor/index.test.jsx
index 8748317373..f2d32b1347 100644
--- a/src/editors/sharedComponents/RawEditor/index.test.jsx
+++ b/src/editors/sharedComponents/RawEditor/index.test.jsx
@@ -7,11 +7,12 @@ import RawEditor from '.';
jest.unmock('@openedx/paragon');
-const renderComponent = (props) => render(
-
-
- ,
-);
+const renderComponent = (props) =>
+ render(
+
+
+ ,
+ );
describe('RawEditor', () => {
const defaultProps = {
editorRef: {
@@ -52,7 +53,8 @@ describe('RawEditor', () => {
it('updates the assets to static srcs', () => {
const updatedProps = {
...defaultProps,
- content: 'pick
or
',
+ content:
+ 'pick
or
',
};
renderComponent(updatedProps);
expect(screen.getByText('"/static/img.jpeg"')).toBeVisible();
@@ -61,7 +63,8 @@ describe('RawEditor', () => {
expect(screen.queryByText('"/asset-v1:org+run+term+type@asset+block@img.jpeg"')).toBeNull();
- expect(screen.queryByText('"/assets/courseware/v1/hash/asset-v1:org+run+term+type@asset+block/img2.jpeg"')).toBeNull();
+ expect(screen.queryByText('"/assets/courseware/v1/hash/asset-v1:org+run+term+type@asset+block/img2.jpeg"'))
+ .toBeNull();
});
it('renders as expected with lang equal to xml', () => {
diff --git a/src/editors/sharedComponents/SelectableBox/FormCheckbox.jsx b/src/editors/sharedComponents/SelectableBox/FormCheckbox.jsx
index d2e1951ba5..99ac325c9c 100644
--- a/src/editors/sharedComponents/SelectableBox/FormCheckbox.jsx
+++ b/src/editors/sharedComponents/SelectableBox/FormCheckbox.jsx
@@ -66,10 +66,12 @@ const FormCheckbox = React.forwardRef(({
const { hasFormGroupProvider, useSetIsControlGroupEffect, getControlProps } = useFormGroupContext();
useSetIsControlGroupEffect(true);
const shouldActAsGroup = hasFormGroupProvider && !hasCheckboxSetProvider;
- const groupProps = shouldActAsGroup ? {
- ...getControlProps({}),
- role: 'group',
- } : {};
+ const groupProps = shouldActAsGroup ?
+ {
+ ...getControlProps({}),
+ role: 'group',
+ } :
+ {};
const control = React.createElement(controlAs, { ...props, className: controlClassName, ref });
return (
diff --git a/src/editors/sharedComponents/SelectableBox/FormCheckboxSetContext.jsx b/src/editors/sharedComponents/SelectableBox/FormCheckboxSetContext.jsx
index 1dd45b5240..3a7bf04461 100644
--- a/src/editors/sharedComponents/SelectableBox/FormCheckboxSetContext.jsx
+++ b/src/editors/sharedComponents/SelectableBox/FormCheckboxSetContext.jsx
@@ -71,7 +71,4 @@ FormCheckboxSetContextProvider.defaultProps = {
};
export default FormCheckboxSetContext;
-export {
- useCheckboxSetContext,
- FormCheckboxSetContextProvider,
-};
+export { useCheckboxSetContext, FormCheckboxSetContextProvider };
diff --git a/src/editors/sharedComponents/SelectableBox/FormControlSet.jsx b/src/editors/sharedComponents/SelectableBox/FormControlSet.jsx
index 69052e7675..00ce5e7373 100644
--- a/src/editors/sharedComponents/SelectableBox/FormControlSet.jsx
+++ b/src/editors/sharedComponents/SelectableBox/FormControlSet.jsx
@@ -8,16 +8,17 @@ const FormControlSet = ({
isInline,
children,
...props
-}) => React.createElement(as, {
- className: classNames(
- className,
- {
- 'pgn__form-control-set': !isInline,
- 'pgn__form-control-set-inline': isInline,
- },
- ),
- ...props,
-}, children);
+}) =>
+ React.createElement(as, {
+ className: classNames(
+ className,
+ {
+ 'pgn__form-control-set': !isInline,
+ 'pgn__form-control-set-inline': isInline,
+ },
+ ),
+ ...props,
+ }, children);
FormControlSet.propTypes = {
/** Specifies the base element */
diff --git a/src/editors/sharedComponents/SelectableBox/FormGroupContext.jsx b/src/editors/sharedComponents/SelectableBox/FormGroupContext.jsx
index af38a4f8ab..7d3ce6213d 100644
--- a/src/editors/sharedComponents/SelectableBox/FormGroupContext.jsx
+++ b/src/editors/sharedComponents/SelectableBox/FormGroupContext.jsx
@@ -1,5 +1,8 @@
import React, {
- useState, useEffect, useMemo, useCallback,
+ useState,
+ useEffect,
+ useMemo,
+ useCallback,
} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
@@ -114,8 +117,4 @@ FormGroupContextProvider.defaultProps = {
size: undefined,
};
-export {
- FormGroupContext,
- FormGroupContextProvider,
- useFormGroupContext,
-};
+export { FormGroupContext, FormGroupContextProvider, useFormGroupContext };
diff --git a/src/editors/sharedComponents/SelectableBox/FormRadio.jsx b/src/editors/sharedComponents/SelectableBox/FormRadio.jsx
index 43e4133d66..484a42fe68 100644
--- a/src/editors/sharedComponents/SelectableBox/FormRadio.jsx
+++ b/src/editors/sharedComponents/SelectableBox/FormRadio.jsx
@@ -24,9 +24,7 @@ const RadioControl = React.forwardRef((props, ref) => {
}
};
- return (
-
- );
+ return
;
});
RadioControl.propTypes = {
diff --git a/src/editors/sharedComponents/SelectableBox/FormRadioSetContext.jsx b/src/editors/sharedComponents/SelectableBox/FormRadioSetContext.jsx
index 41716cadd1..3a06c802a9 100644
--- a/src/editors/sharedComponents/SelectableBox/FormRadioSetContext.jsx
+++ b/src/editors/sharedComponents/SelectableBox/FormRadioSetContext.jsx
@@ -73,7 +73,4 @@ FormRadioSetContextProvider.defaultProps = {
};
export default FormRadioSetContext;
-export {
- useRadioSetContext,
- FormRadioSetContextProvider,
-};
+export { useRadioSetContext, FormRadioSetContextProvider };
diff --git a/src/editors/sharedComponents/SelectableBox/FormText.jsx b/src/editors/sharedComponents/SelectableBox/FormText.jsx
index f6469a1512..8deeb96e28 100644
--- a/src/editors/sharedComponents/SelectableBox/FormText.jsx
+++ b/src/editors/sharedComponents/SelectableBox/FormText.jsx
@@ -52,7 +52,12 @@ const resolveTextType = ({ isInvalid, isValid }) => {
// };
const FormText = ({
- children, type, icon, muted, hasIcon, ...props
+ children,
+ type,
+ icon,
+ muted,
+ hasIcon,
+ ...props
}) => {
const className = classNames(
props.className,
diff --git a/src/editors/sharedComponents/SelectableBox/README.md b/src/editors/sharedComponents/SelectableBox/README.md
index 4ab1f417da..3766a2e945 100644
--- a/src/editors/sharedComponents/SelectableBox/README.md
+++ b/src/editors/sharedComponents/SelectableBox/README.md
@@ -15,14 +15,14 @@ notes: |
A box that has selection states. It can be used as an alternative to a radio button or checkbox set.
-The ``SelectableBox`` can contain any kind of content as long as it is not clickable. In other words, there should be no clickable targets distinct from selection.
+The `SelectableBox` can contain any kind of content as long as it is not clickable. In other words, there should be no clickable targets distinct from selection.
## Basic Usage
-As ``Checkbox``
+As `Checkbox`
```jsx live
-() => {
+(() => {
const type = 'checkbox';
const allCheeseOptions = ['swiss', 'cheddar', 'pepperjack'];
const [checkedCheeses, { add, remove, set, clear }] = useCheckboxSetValues(['swiss']);
@@ -30,10 +30,10 @@ As ``Checkbox``
const handleChange = e => {
e.target.checked ? add(e.target.value) : remove(e.target.value);
};
-
+
const isInvalid = () => checkedCheeses.includes('swiss');
const isExtraSmall = useMediaQuery({ maxWidth: breakpoints.extraSmall.maxWidth });
-
+
return (
);
-}
+});
```
## As Radio
```jsx live
-() => {
+(() => {
const type = 'radio';
const [value, setValue] = useState('green');
const handleChange = e => setValue(e.target.value);
@@ -102,13 +102,15 @@ As ``Checkbox``
);
-}
+});
```
+
## As Checkbox
-As ``Checkbox`` with ``isIndeterminate``
+
+As `Checkbox` with `isIndeterminate`
```jsx live
-() => {
+(() => {
const type = 'checkbox';
const allCheeseOptions = ['swiss', 'cheddar', 'pepperjack'];
const [checkedCheeses, { add, remove, set, clear }] = useCheckboxSetValues(['swiss']);
@@ -163,13 +165,13 @@ As ``Checkbox`` with ``isIndeterminate``
>
);
-}
+});
```
-As ``Checkbox`` with ``ariaLabelledby``
+As `Checkbox` with `ariaLabelledby`
```jsx live
-() => {
+(() => {
const type = 'checkbox';
const allCheeseOptions = ['swiss', 'cheddar', 'pepperjack'];
const [checkedCheeses, { add, remove, set, clear }] = useCheckboxSetValues(['swiss']);
@@ -177,9 +179,9 @@ As ``Checkbox`` with ``ariaLabelledby``
const handleChange = e => {
e.target.checked ? add(e.target.value) : remove(e.target.value);
};
-
+
const isExtraSmall = useMediaQuery({ maxWidth: breakpoints.extraSmall.maxWidth });
-
+
return (
@@ -211,5 +213,5 @@ As ``Checkbox`` with ``ariaLabelledby``
);
-}
+});
```
diff --git a/src/editors/sharedComponents/SelectableBox/fieldUtils.js b/src/editors/sharedComponents/SelectableBox/fieldUtils.js
index 5c0d980a17..1e795976aa 100644
--- a/src/editors/sharedComponents/SelectableBox/fieldUtils.js
+++ b/src/editors/sharedComponents/SelectableBox/fieldUtils.js
@@ -2,13 +2,14 @@ import classNames from 'classnames';
import { useState, useEffect } from 'react';
import newId from './newId';
-const omitUndefinedProperties = (obj = {}) => Object.entries(obj)
- .reduce((acc, [key, value]) => {
- if (value !== undefined) {
- acc[key] = value;
- }
- return acc;
- }, {});
+const omitUndefinedProperties = (obj = {}) =>
+ Object.entries(obj)
+ .reduce((acc, [key, value]) => {
+ if (value !== undefined) {
+ acc[key] = value;
+ }
+ return acc;
+ }, {});
const callAllHandlers = (...handlers) => {
const unifiedEventHandler = (event) => {
@@ -61,10 +62,4 @@ const mergeAttributeValues = (...values) => {
return mergedValues || undefined;
};
-export {
- callAllHandlers,
- useHasValue,
- mergeAttributeValues,
- useIdList,
- omitUndefinedProperties,
-};
+export { callAllHandlers, useHasValue, mergeAttributeValues, useIdList, omitUndefinedProperties };
diff --git a/src/editors/sharedComponents/SelectableBox/tests/SelectableBox.test.jsx b/src/editors/sharedComponents/SelectableBox/tests/SelectableBox.test.jsx
index 4fbd481398..1732ce7398 100644
--- a/src/editors/sharedComponents/SelectableBox/tests/SelectableBox.test.jsx
+++ b/src/editors/sharedComponents/SelectableBox/tests/SelectableBox.test.jsx
@@ -115,7 +115,9 @@ describe('
', () => {
it('ref is passed to onClick function', async () => {
const user = userEvent.setup();
let inputRef;
- const onClick = (ref) => { inputRef = ref; };
+ const onClick = (ref) => {
+ inputRef = ref;
+ };
render(
);
const radio = screen.getByRole('button');
await user.click(radio);
diff --git a/src/editors/sharedComponents/SelectableBox/tests/SelectableBoxSet.test.jsx b/src/editors/sharedComponents/SelectableBox/tests/SelectableBoxSet.test.jsx
index d14d009070..9de44fe411 100644
--- a/src/editors/sharedComponents/SelectableBox/tests/SelectableBoxSet.test.jsx
+++ b/src/editors/sharedComponents/SelectableBox/tests/SelectableBoxSet.test.jsx
@@ -94,15 +94,17 @@ describe('
', () => {
expect(screen.getByLabelText('test-radio-set-label')).toBeInTheDocument();
});
it('renders with an aria-labelledby attribute', () => {
- render((
- <>
-
Radio Set Label text
-
- >
- ));
+ render(
+ (
+ <>
+
Radio Set Label text
+
+ >
+ ),
+ );
expect(screen.getByLabelText('Radio Set Label text')).toBeInTheDocument();
});
});
diff --git a/src/editors/sharedComponents/SelectionModal/Gallery.jsx b/src/editors/sharedComponents/SelectionModal/Gallery.jsx
index 4baded574e..dbf0061f9a 100644
--- a/src/editors/sharedComponents/SelectionModal/Gallery.jsx
+++ b/src/editors/sharedComponents/SelectionModal/Gallery.jsx
@@ -33,12 +33,13 @@ const Gallery = ({
if (!isLoaded && !allowLazyLoad) {
return (
-
- )) }
+ ))}
{(allowLazyLoad && !isLibrary) && (
{
- const Set = (props: { children: React.ReactNode }) => {props?.children}
;
+ const Set = (props: { children: React.ReactNode; }) => {props?.children}
;
return { Set };
});
-jest.mock('./GalleryCard', () => function mockGalleryCard(props) {
- return GalleryCard {props?.asset?.id}
;
-});
+jest.mock('./GalleryCard', () =>
+ function mockGalleryCard(props) {
+ return GalleryCard {props?.asset?.id}
;
+ });
-jest.mock('./GalleryLoadMoreButton', () => function mockGalleryLoadMoreButton(props) {
- return Load More ;
-});
+jest.mock('./GalleryLoadMoreButton', () =>
+ function mockGalleryLoadMoreButton(props) {
+ return Load More ;
+ });
describe('Gallery', () => {
beforeEach(() => {
diff --git a/src/editors/sharedComponents/SelectionModal/GalleryCard.jsx b/src/editors/sharedComponents/SelectionModal/GalleryCard.jsx
index ac6036154d..7d788ea197 100644
--- a/src/editors/sharedComponents/SelectionModal/GalleryCard.jsx
+++ b/src/editors/sharedComponents/SelectionModal/GalleryCard.jsx
@@ -27,26 +27,26 @@ const GalleryCard = ({
value={asset.id}
>
-
- {(thumbnailError && thumbnailFallback) ? (
-
- { thumbnailFallback }
-
- ) : (
-
setThumbnailError(true))}
- />
- )}
- { asset.statusMessage && asset.statusBadgeVariant && (
+
+ {(thumbnailError && thumbnailFallback) ?
+ (
+
+ {thumbnailFallback}
+
+ ) :
+ (
+
setThumbnailError(true))}
+ />
+ )}
+ {asset.statusMessage && asset.statusBadgeVariant && (
)}
- { asset.duration >= 0 && (
+ {asset.duration >= 0 && (
{asset.displayName}
- { asset.transcripts && (
+ {asset.transcripts && (
)}
{asset.dateAdded && (
-
- ,
- time: ,
- }}
- />
-
+
+ ,
+ time: ,
+ }}
+ />
+
)}
diff --git a/src/editors/sharedComponents/SelectionModal/GalleryCard.test.tsx b/src/editors/sharedComponents/SelectionModal/GalleryCard.test.tsx
index eb937da9d1..4bc5c51c65 100644
--- a/src/editors/sharedComponents/SelectionModal/GalleryCard.test.tsx
+++ b/src/editors/sharedComponents/SelectionModal/GalleryCard.test.tsx
@@ -1,6 +1,9 @@
import React from 'react';
import {
- render, screen, fireEvent, initializeMocks,
+ render,
+ screen,
+ fireEvent,
+ initializeMocks,
} from '../../../testUtils';
import GalleryCard from './GalleryCard';
@@ -10,9 +13,10 @@ jest.mock('../../utils', () => ({
jest.mock(
'../../containers/VideoEditor/components/VideoSettingsModal/components/VideoPreviewWidget/LanguageNamesWidget',
- () => function mockLanguageNamesWidget({ transcripts }) {
- return Languages: {transcripts && transcripts.join(', ')}
;
- },
+ () =>
+ function mockLanguageNamesWidget({ transcripts }) {
+ return Languages: {transcripts && transcripts.join(', ')}
;
+ },
);
const baseAsset = {
diff --git a/src/editors/sharedComponents/SelectionModal/SearchSort.jsx b/src/editors/sharedComponents/SelectionModal/SearchSort.jsx
index a2470edc57..273d552019 100644
--- a/src/editors/sharedComponents/SelectionModal/SearchSort.jsx
+++ b/src/editors/sharedComponents/SelectionModal/SearchSort.jsx
@@ -2,7 +2,13 @@ import React from 'react';
import PropTypes from 'prop-types';
import {
- ActionRow, Dropdown, Form, Icon, IconButton, SelectMenu, MenuItem,
+ ActionRow,
+ Dropdown,
+ Form,
+ Icon,
+ IconButton,
+ SelectMenu,
+ MenuItem,
} from '@openedx/paragon';
import { Check, Close, Search } from '@openedx/paragon/icons';
import {
@@ -37,26 +43,24 @@ const SearchSort = ({
autoFocus
onChange={onSearchChange}
placeholder={intl.formatMessage(messages.searchPlaceholder)}
- trailingElement={
- searchString
- ? (
-
- )
- :
- }
+ trailingElement={searchString
+ ? (
+
+ )
+ : }
value={searchString}
/>
- { !showSwitch && }
+ {!showSwitch && }
{Object.keys(sortKeys).map(key => (
-
+
))}
- { onFilterClick && (
-
-
-
-
-
- {Object.keys(filterKeys).map(key => (
-
-
-
- ))}
-
-
+ {onFilterClick && (
+
+
+
+
+
+ {Object.keys(filterKeys).map(key => (
+
+
+
+ ))}
+
+
)}
- { showSwitch && (
+ {showSwitch && (
<>
>
)}
-
);
};
diff --git a/src/editors/sharedComponents/SelectionModal/SearchSort.test.jsx b/src/editors/sharedComponents/SelectionModal/SearchSort.test.jsx
index c63798f083..5c8c2580b6 100644
--- a/src/editors/sharedComponents/SelectionModal/SearchSort.test.jsx
+++ b/src/editors/sharedComponents/SelectionModal/SearchSort.test.jsx
@@ -1,11 +1,16 @@
import '@testing-library/jest-dom';
import {
- fireEvent, render, screen,
+ fireEvent,
+ render,
+ screen,
} from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import {
- filterKeys, filterMessages, sortKeys, sortMessages,
+ filterKeys,
+ filterMessages,
+ sortKeys,
+ sortMessages,
} from '../../containers/VideoGallery/utils';
import SearchSort from './SearchSort';
import messages from './messages';
diff --git a/src/editors/sharedComponents/SelectionModal/index.jsx b/src/editors/sharedComponents/SelectionModal/index.jsx
index c345f8232d..29b036f0bc 100644
--- a/src/editors/sharedComponents/SelectionModal/index.jsx
+++ b/src/editors/sharedComponents/SelectionModal/index.jsx
@@ -62,15 +62,15 @@ const SelectionModal = ({
return (
- )}
+ }
isOpen={isOpen}
size={size}
isFullscreenScroll={isFullscreenScroll}
- footerAction={(
+ footerAction={
- )}
+ }
title={intl.formatMessage(titleMsg)}
bodyStyle={{ background }}
headerComponent={!isLibrary && (
@@ -92,10 +92,12 @@ const SelectionModal = ({
)}
className="selection-modal"
>
- {/*
+ {
+ /*
If the modal dialog content is zero height, it shows a bottom shadow
as if there was content to scroll to, so make the min-height 1px.
- */}
+ */
+ }
{/* Error Alerts */}
diff --git a/src/editors/sharedComponents/SelectionModal/index.test.jsx b/src/editors/sharedComponents/SelectionModal/index.test.jsx
index 91186e8d69..4614ff6a97 100644
--- a/src/editors/sharedComponents/SelectionModal/index.test.jsx
+++ b/src/editors/sharedComponents/SelectionModal/index.test.jsx
@@ -85,27 +85,31 @@ const mockUploadErrorAlertFn = jest.fn();
jest.mock('../BaseModal', () => 'BaseModal');
jest.mock('./SearchSort', () => 'SearchSort');
-jest.mock('./Gallery', () => function mockGallery(componentProps) {
- mockGalleryFn(componentProps);
- return (Gallery
);
-});
+jest.mock('./Gallery', () =>
+ function mockGallery(componentProps) {
+ mockGalleryFn(componentProps);
+ return Gallery
;
+ });
jest.mock('../FileInput', () => ({
FileInput: function mockFileInput(componentProps) {
mockFileInputFn(componentProps);
- return (FileInput
);
+ return FileInput
;
},
}));
-jest.mock('../ErrorAlerts/ErrorAlert', () => function mockErrorAlert() {
- return ErrorAlert
;
-});
-jest.mock('../ErrorAlerts/FetchErrorAlert', () => function mockFetchErrorAlert(componentProps) {
- mockFetchErrorAlertFn(componentProps);
- return (FetchErrorAlert
);
-});
-jest.mock('../ErrorAlerts/UploadErrorAlert', () => function mockUploadErrorAlert(componentProps) {
- mockUploadErrorAlertFn(componentProps);
- return (UploadErrorAlert
);
-});
+jest.mock('../ErrorAlerts/ErrorAlert', () =>
+ function mockErrorAlert() {
+ return ErrorAlert
;
+ });
+jest.mock('../ErrorAlerts/FetchErrorAlert', () =>
+ function mockFetchErrorAlert(componentProps) {
+ mockFetchErrorAlertFn(componentProps);
+ return FetchErrorAlert
;
+ });
+jest.mock('../ErrorAlerts/UploadErrorAlert', () =>
+ function mockUploadErrorAlert(componentProps) {
+ mockUploadErrorAlertFn(componentProps);
+ return UploadErrorAlert
;
+ });
describe('Selection Modal', () => {
beforeEach(() => {
diff --git a/src/editors/sharedComponents/SourceCodeModal/hooks.test.js b/src/editors/sharedComponents/SourceCodeModal/hooks.test.js
index 08df5a2f73..abb45a9c5f 100644
--- a/src/editors/sharedComponents/SourceCodeModal/hooks.test.js
+++ b/src/editors/sharedComponents/SourceCodeModal/hooks.test.js
@@ -13,11 +13,10 @@ describe('SourceCodeModal hooks', () => {
const mockContent = 'sOmEMockHtML';
const mockSetContent = jest.fn();
const mockEditorRef = {
- current:
- {
- setContent: mockSetContent,
- getContent: jest.fn(() => mockContent),
- },
+ current: {
+ setContent: mockSetContent,
+ getContent: jest.fn(() => mockContent),
+ },
};
const mockClose = jest.fn();
test('getSaveBtnProps', () => {
diff --git a/src/editors/sharedComponents/SourceCodeModal/index.jsx b/src/editors/sharedComponents/SourceCodeModal/index.jsx
index f800a42315..d6baa8c4a1 100644
--- a/src/editors/sharedComponents/SourceCodeModal/index.jsx
+++ b/src/editors/sharedComponents/SourceCodeModal/index.jsx
@@ -25,14 +25,14 @@ const SourceCodeModal = ({
- )}
+ }
isOpen={isOpen}
title={intl.formatMessage(messages.titleLabel)}
- bodyStyle={{ maxHeight: (height - 180) }}
+ bodyStyle={{ maxHeight: height - 180 }}
>
jest.fn(({ children, ...props }) => (
- {children}
-)));
-jest.mock('../CodeEditor', () => jest.fn(({ innerRef, value, lang }) => (
- CodeEditor
-)));
+jest.mock('../BaseModal', () => jest.fn(({ children, ...props }) => {children}
));
+jest.mock(
+ '../CodeEditor',
+ () =>
+ jest.fn(({ innerRef, value, lang }) => (
+ CodeEditor
+ )),
+);
jest.mock('./hooks', () => ({
prepareSourceCodeModal: jest.fn().mockReturnValue({
saveBtnProps: { onClick: jest.fn() },
diff --git a/src/editors/sharedComponents/SourceCodeModal/messages.ts b/src/editors/sharedComponents/SourceCodeModal/messages.ts
index 2f1bfe200e..e3a704e2f9 100644
--- a/src/editors/sharedComponents/SourceCodeModal/messages.ts
+++ b/src/editors/sharedComponents/SourceCodeModal/messages.ts
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
-
saveButtonLabel: {
id: 'authoring.texteditor.sourcecodemodal.next.label',
defaultMessage: 'Save',
diff --git a/src/editors/sharedComponents/TextField/TextField.tsx b/src/editors/sharedComponents/TextField/TextField.tsx
index 367fab0bed..170161ba04 100644
--- a/src/editors/sharedComponents/TextField/TextField.tsx
+++ b/src/editors/sharedComponents/TextField/TextField.tsx
@@ -3,19 +3,25 @@ import { useField, FieldHookConfig } from 'formik';
import React from 'react';
declare interface TextFieldProps {
- label: string,
- id: string,
- type?: string,
- hint?: string,
- placeholder?: string,
- name: string,
- disabled?: boolean,
+ label: string;
+ id: string;
+ type?: string;
+ hint?: string;
+ placeholder?: string;
+ name: string;
+ disabled?: boolean;
// For any other formik settings.
- fieldConfig?: Omit, 'name'>,
+ fieldConfig?: Omit, 'name'>;
}
const TextField: React.FC = ({
- label, name, id, hint = '', type = 'text', placeholder = '', fieldConfig,
+ label,
+ name,
+ id,
+ hint = '',
+ type = 'text',
+ placeholder = '',
+ fieldConfig,
disabled = false,
}) => {
const [field, meta] = useField({ name, ...fieldConfig } as FieldHookConfig);
diff --git a/src/editors/sharedComponents/TinyMceWidget/customTinyMcePlugins/embedIframePlugin.js b/src/editors/sharedComponents/TinyMceWidget/customTinyMcePlugins/embedIframePlugin.js
index 04057ca3a1..fd2bf0e296 100644
--- a/src/editors/sharedComponents/TinyMceWidget/customTinyMcePlugins/embedIframePlugin.js
+++ b/src/editors/sharedComponents/TinyMceWidget/customTinyMcePlugins/embedIframePlugin.js
@@ -146,7 +146,13 @@ function tinyMCEEmbedIframePlugin(editor) {
};
if (data.source) {
const {
- size, sizeType, name, title, longDescriptionURL, border, scrollbar,
+ size,
+ sizeType,
+ name,
+ title,
+ longDescriptionURL,
+ border,
+ scrollbar,
} = data;
const { width, height } = sizeTypes[sizeType] || { width: size.width, height: size.height };
@@ -155,7 +161,8 @@ function tinyMCEEmbedIframePlugin(editor) {
const heightFormat = pxRegex.test(height) ? height : '300px';
const hasScroll = scrollbar ? 'yes' : 'no';
- let iframeCode = `
diff --git a/src/editors/sharedComponents/TypeaheadDropdown/index.test.jsx b/src/editors/sharedComponents/TypeaheadDropdown/index.test.jsx
index 077ea4c0d8..267ba85273 100644
--- a/src/editors/sharedComponents/TypeaheadDropdown/index.test.jsx
+++ b/src/editors/sharedComponents/TypeaheadDropdown/index.test.jsx
@@ -76,13 +76,17 @@ describe('common/OrganizationDropdown.jsx', () => {
await act(async () => {
fireEvent.click(screen.getByTestId('expand-more-button'));
});
- expect(within(screen.getByTestId('dropdown-container'))
- .queryAllByRole('button').length).toEqual(newProps.options.length);
+ expect(
+ within(screen.getByTestId('dropdown-container'))
+ .queryAllByRole('button').length,
+ ).toEqual(newProps.options.length);
await act(async () => {
fireEvent.click(screen.getByTestId('expand-less-button'));
});
- expect(within(screen.getByTestId('dropdown-container'))
- .queryAllByRole('button').length).toEqual(0);
+ expect(
+ within(screen.getByTestId('dropdown-container'))
+ .queryAllByRole('button').length,
+ ).toEqual(0);
});
it('shows options list depends on field value', async () => {
const user = userEvent.setup();
@@ -91,8 +95,10 @@ describe('common/OrganizationDropdown.jsx', () => {
const formInput = screen.getByTestId('formControl');
fireEvent.focus(formInput);
await user.type(formInput, 'opt1');
- expect(within(screen.getByTestId('dropdown-container'))
- .queryAllByRole('button').length).toEqual(1);
+ expect(
+ within(screen.getByTestId('dropdown-container'))
+ .queryAllByRole('button').length,
+ ).toEqual(1);
});
it('closes options list on click outside', async () => {
const user = userEvent.setup();
@@ -100,11 +106,15 @@ describe('common/OrganizationDropdown.jsx', () => {
renderComponent(newProps);
const formInput = screen.getByTestId('formControl');
fireEvent.click(formInput);
- expect(within(screen.getByTestId('dropdown-container'))
- .queryAllByRole('button').length).toEqual(2);
+ expect(
+ within(screen.getByTestId('dropdown-container'))
+ .queryAllByRole('button').length,
+ ).toEqual(2);
await user.click(document.body);
- expect(within(screen.getByTestId('dropdown-container'))
- .queryAllByRole('button').length).toEqual(0);
+ expect(
+ within(screen.getByTestId('dropdown-container'))
+ .queryAllByRole('button').length,
+ ).toEqual(0);
});
describe('empty options list', () => {
it('shows empty options list depends on field value', async () => {
diff --git a/src/editors/sharedComponents/UploadWidget/UploadWidget.test.tsx b/src/editors/sharedComponents/UploadWidget/UploadWidget.test.tsx
index 17aa77c1a4..6a319fa874 100644
--- a/src/editors/sharedComponents/UploadWidget/UploadWidget.test.tsx
+++ b/src/editors/sharedComponents/UploadWidget/UploadWidget.test.tsx
@@ -9,11 +9,11 @@ import MockAdapter from 'axios-mock-adapter';
import { waitFor } from '@testing-library/react';
import messages from './messages';
-declare type UploadForm = FormikConfig<{ url: string }>;
+declare type UploadForm = FormikConfig<{ url: string; }>;
declare interface RenderOpts {
- props: UploadWidgetProps,
- formikProps: UploadForm,
+ props: UploadWidgetProps;
+ formikProps: UploadForm;
}
const defaultProps: (overrides?: Partial
) => UploadWidgetProps = (overrides) => ({
@@ -32,12 +32,13 @@ const defaultFormikProps: (overrides?: Partial) => UploadForm = (ove
...overrides,
});
-const renderWidget = ({ props, formikProps }: RenderOpts) => editorRender(
-
-
- ,
- { initialState: { app: { studioEndpointUrl: 'https://studio.local' } } },
-);
+const renderWidget = ({ props, formikProps }: RenderOpts) =>
+ editorRender(
+
+
+ ,
+ { initialState: { app: { studioEndpointUrl: 'https://studio.local' } } },
+ );
describe('UploadWidget', () => {
let axiosMock: MockAdapter;
@@ -72,12 +73,13 @@ describe('UploadWidget', () => {
});
it('handles a file upload in a library.', async () => {
const user = userEvent.setup();
- axiosMock.onPut('http://localhost:18010/api/libraries/v2/blocks/pdf-block/assets/static/my-test-pdf.pdf').withDelayInMs(1000).reply(
- 201,
- {
- path: '/static/my-saved-pdf.pdf',
- },
- );
+ axiosMock.onPut('http://localhost:18010/api/libraries/v2/blocks/pdf-block/assets/static/my-test-pdf.pdf')
+ .withDelayInMs(1000).reply(
+ 201,
+ {
+ path: '/static/my-saved-pdf.pdf',
+ },
+ );
const screen = renderWidget({ props: defaultProps({ isLibrary: true }), formikProps: defaultFormikProps() });
const dropdown = screen.getByLabelText(messages.actionsDropdown.defaultMessage);
screen.getByText(messages.libraryFileHint.defaultMessage);
diff --git a/src/editors/sharedComponents/UploadWidget/UploadWidget.tsx b/src/editors/sharedComponents/UploadWidget/UploadWidget.tsx
index 25bbac48ff..15b755ebf1 100644
--- a/src/editors/sharedComponents/UploadWidget/UploadWidget.tsx
+++ b/src/editors/sharedComponents/UploadWidget/UploadWidget.tsx
@@ -1,7 +1,15 @@
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import { FileInput, useFileInput } from '@src/files-and-videos/generic';
import {
- ActionRow, Dropdown, Icon, IconButton, Button, Stack, Form, Col, Card,
+ ActionRow,
+ Dropdown,
+ Icon,
+ IconButton,
+ Button,
+ Stack,
+ Form,
+ Col,
+ Card,
} from '@openedx/paragon';
import { MoreHoriz } from '@openedx/paragon/icons';
import React, { useState } from 'react';
@@ -12,17 +20,17 @@ import { useAssetUpload } from '@src/editors/api';
import defaultMessages from './messages';
export interface UploadWidgetProps {
- id: string,
- label: string,
- supportedFileFormats?: string | string[] | Record,
- urlFieldName: string,
- messages?: typeof defaultMessages
- blockId: string,
- isLibrary: boolean,
+ id: string;
+ label: string;
+ supportedFileFormats?: string | string[] | Record;
+ urlFieldName: string;
+ messages?: typeof defaultMessages;
+ blockId: string;
+ isLibrary: boolean;
}
-type LibraryAsset = { path: string };
-type CourseAsset = { asset: { external_url: string } };
+type LibraryAsset = { path: string; };
+type CourseAsset = { asset: { external_url: string; }; };
declare type AssetResponse = AxiosResponse | AxiosResponse;
@@ -56,7 +64,7 @@ const UploadWidget = ({
// the URL to the appropriate one after rendering the fragment.
//
// It is not clear how this would work in the case of a React-based student view.
- void urlFieldControl.setValue(`/${ (result.data as LibraryAsset).path}`); // eslint-disable-line no-void
+ void urlFieldControl.setValue(`/${(result.data as LibraryAsset).path}`); // eslint-disable-line no-void
} else {
void urlFieldControl.setValue((result.data as CourseAsset).asset.external_url); // eslint-disable-line no-void
}
@@ -90,11 +98,11 @@ const UploadWidget = ({
return (
{intl.formatMessage(messages.urlFieldLabel)}
- )}
+ }
>
{intl.formatMessage(messages.blockCreationWarning)}
@@ -110,45 +118,47 @@ const UploadWidget = ({
{manualMode && }
{!manualMode && (
- <>
- {label}
-
-
-
-
- {mutation.isPending ? : deriveFileName(urlField.value)}
-
-
-
-
-
-
-
-
-
-
- setManualMode(true)}
- >
-
-
-
-
-
- {urlFieldMeta.error && {urlFieldMeta.error} }
-
- >
+ <>
+ {label}
+
+
+
+
+
+
+ {mutation.isPending ? : deriveFileName(urlField.value)}
+
+
+
+
+
+
+
+
+
+
+ setManualMode(true)}
+ >
+
+
+
+
+
+ {urlFieldMeta.error && {urlFieldMeta.error} }
+
+ >
)}
{manualMode && (
diff --git a/src/editors/sharedComponents/UploadWidget/messages.ts b/src/editors/sharedComponents/UploadWidget/messages.ts
index b69184e92c..93c64f5392 100644
--- a/src/editors/sharedComponents/UploadWidget/messages.ts
+++ b/src/editors/sharedComponents/UploadWidget/messages.ts
@@ -30,7 +30,7 @@ const messages = defineMessages({
manualUrl: {
id: 'authoring.sharedComponents.uploadWidget.manualUrl',
defaultMessage: 'Manually specify URL',
- description: "Dropdown menu item to switch to manually inputting a URL for a file's location.",
+ description: 'Dropdown menu item to switch to manually inputting a URL for a file\'s location.',
},
simpleMode: {
id: 'authoring.sharedComponents.uploadWidget.simpleMode',
@@ -45,7 +45,7 @@ const messages = defineMessages({
defaultName: {
id: 'authoring.sharedComponents.uploadWidget.defaultName',
defaultMessage: 'Unknown Filename',
- description: "Default 'file name' shown if one can't be determined.",
+ description: 'Default \'file name\' shown if one can\'t be determined.',
},
emptyLabel: {
id: 'authoring.sharedComponents.uploadWidget.defaultName',
@@ -55,12 +55,12 @@ const messages = defineMessages({
uploading: {
id: 'authoring.sharedComponents.uploadWidget.uploading',
defaultMessage: 'Uploading...',
- description: "Uploading status message to let the user know we're working on their request.",
+ description: 'Uploading status message to let the user know we\'re working on their request.',
},
uploadError: {
id: 'authoring.sharedComponents.uploadWidget.uploadError',
defaultMessage: 'There was an error uploading your file. Please try again later or contact support if the issue persists.',
- description: "Error message to show if there's been a problem with the file upload.",
+ description: 'Error message to show if there\'s been a problem with the file upload.',
},
actionsDropdown: {
id: 'authoring.sharedComponents.uploadWidget.actionsDropdown',
diff --git a/src/editors/testUtils.js b/src/editors/testUtils.js
index 54904c0e2f..36b19c5b23 100644
--- a/src/editors/testUtils.js
+++ b/src/editors/testUtils.js
@@ -54,13 +54,14 @@ export const mockNestedComponent = (name, contents) => {
* IconButton: 'IconButton',
* })
*/
-export const mockNestedComponents = (mapping) => Object.entries(mapping).reduce(
- (obj, [name, value]) => ({
- ...obj,
- [name]: mockNestedComponent(name, value),
- }),
- {},
-);
+export const mockNestedComponents = (mapping) =>
+ Object.entries(mapping).reduce(
+ (obj, [name, value]) => ({
+ ...obj,
+ [name]: mockNestedComponent(name, value),
+ }),
+ {},
+ );
/**
* Mock utility for working with useState in a hooks module.
@@ -132,10 +133,12 @@ export class MockUseState {
* @return {object} - StrictDict of state object keys
*/
get keys() {
- return StrictDict(Object.keys(this.hooks.state).reduce(
- (obj, key) => ({ ...obj, [key]: key }),
- {},
- ));
+ return StrictDict(
+ Object.keys(this.hooks.state).reduce(
+ (obj, key) => ({ ...obj, [key]: key }),
+ {},
+ ),
+ );
}
/**
diff --git a/src/editors/utils/camelizeKeys.test.js b/src/editors/utils/camelizeKeys.test.js
index 3bdd209c59..78b251acab 100644
--- a/src/editors/utils/camelizeKeys.test.js
+++ b/src/editors/utils/camelizeKeys.test.js
@@ -1,26 +1,24 @@
import { camelizeKeys } from './index';
const snakeCaseObject = {
- some_attribute:
- {
- another_attribute: [
- { a_list: 'a lIsT' },
- { of_attributes: 'iN diFferent' },
- { different_cases: 'to Test' },
- ],
- },
+ some_attribute: {
+ another_attribute: [
+ { a_list: 'a lIsT' },
+ { of_attributes: 'iN diFferent' },
+ { different_cases: 'to Test' },
+ ],
+ },
a_final_attribute: null,
a_last_one: undefined,
};
const camelCaseObject = {
- someAttribute:
- {
- anotherAttribute: [
- { aList: 'a lIsT' },
- { ofAttributes: 'iN diFferent' },
- { differentCases: 'to Test' },
- ],
- },
+ someAttribute: {
+ anotherAttribute: [
+ { aList: 'a lIsT' },
+ { ofAttributes: 'iN diFferent' },
+ { differentCases: 'to Test' },
+ ],
+ },
aFinalAttribute: null,
aLastOne: undefined,
};
diff --git a/src/editors/utils/convertMarkdownToXML.js b/src/editors/utils/convertMarkdownToXML.js
index 04f162f22b..ecfa95f2a9 100644
--- a/src/editors/utils/convertMarkdownToXML.js
+++ b/src/editors/utils/convertMarkdownToXML.js
@@ -4,9 +4,15 @@ export const convertMarkdownToXml = (markdown) => {
// Comprehensive XML conversion function
const toXml = (partialMarkdown) => {
let xml = partialMarkdown;
- let i; let makeParagraph; let demandhints;
+ let i;
+ let makeParagraph;
+ let demandhints;
const responseTypes = [
- 'optionresponse', 'multiplechoiceresponse', 'stringresponse', 'numericalresponse', 'choiceresponse',
+ 'optionresponse',
+ 'multiplechoiceresponse',
+ 'stringresponse',
+ 'numericalresponse',
+ 'choiceresponse',
];
// fix DOS \r\n line endings to look like \n
@@ -21,14 +27,14 @@ export const convertMarkdownToXml = (markdown) => {
// question description
xml = xml.replace(/>>([^]+?)< {
const result = questionText.split('||');
- const label = `${ result[0] } \n`;
+ const label = `${result[0]} \n`;
// don't add empty tag
if (result.length === 1 || !result[1]) {
return label;
}
- return `${label }${ result[1] } \n`;
+ return `${label}${result[1]} \n`;
});
// Pull out demand hints, || a hint ||
@@ -39,7 +45,7 @@ export const convertMarkdownToXml = (markdown) => {
for (i = 0; i < options.length; i += 1) {
inner = /\s*\|\|(.*?)\|\|/.exec(options[i]);
if (inner) {
- demandhints += ` ${ inner[1].trim() } \n`;
+ demandhints += ` ${inner[1].trim()} \n`;
}
}
return '';
@@ -69,7 +75,7 @@ export const convertMarkdownToXml = (markdown) => {
if (labelmatch) {
hint = hint.replace(labelmatch[0], '').trim();
label = labelmatch[1].trim();
- labelassign = ` label="${ label }"`;
+ labelassign = ` label="${label}"`;
}
}
if (detectParens) {
@@ -88,15 +94,23 @@ export const convertMarkdownToXml = (markdown) => {
};
xml = xml.replace(/\[\[((.|\n)+?)\]\]/g, (match, group1) => {
- let textHint; let options; let optiontag; let correct;
- let optionlines; let line; let correctstr; let hintstr; let label;
+ let textHint;
+ let options;
+ let optiontag;
+ let correct;
+ let optionlines;
+ let line;
+ let correctstr;
+ let hintstr;
+ let label;
// decide if this is old style or new style
if (match.indexOf('\n') === -1) { // OLD style, [[ .... ]] on one line
options = group1.split(/,\s*/g);
optiontag = ' ';
- return `\n\n${ optiontag } \n\n\n`;
+ return `\n\n${optiontag}\n \n\n`;
}
// new style [[ many-lines ]]
@@ -114,32 +128,33 @@ export const convertMarkdownToXml = (markdown) => {
line = lines[i].trim();
if (line.length > 0) {
textHint = extractHint(line, true);
- correctstr = ` correct="${ textHint.parens ? 'True' : 'False' }"`;
+ correctstr = ` correct="${textHint.parens ? 'True' : 'False'}"`;
hintstr = '';
if (textHint.hint) {
label = textHint.label;
if (label) {
- label = ` label="${ label }"`;
+ label = ` label="${label}"`;
}
- hintstr = ` ${ textHint.hint } `;
+ hintstr = ` ${textHint.hint} `;
}
- optionlines += ` ${ textHint.nothint }${hintstr } \n`;
+ optionlines += ` ${textHint.nothint}${hintstr} \n`;
}
}
- return `\n\n \n${ optionlines } \n \n\n`;
+ return `\n\n \n${optionlines} \n \n\n`;
});
xml = xml.replace(/(^\s*\(.{0,3}\).*?$\n*)+/gm, (match) => {
let choices = '';
let shuffle = false;
const options = match.split('\n');
let correct;
- let fixed; let hint; let
- result;
+ let fixed;
+ let hint;
+ let result;
for (i = 0; i < options.length; i++) {
options[i] = options[i].trim(); // trim off leading/trailing whitespace
if (options[i].length > 0) {
let [, value] = options[i].split(/^\s*\(.{0,3}\)\s*/);
- const [,inparens] = /^\s*\((.{0,3})\)\s*/.exec(options[i]);
+ const [, inparens] = /^\s*\((.{0,3})\)\s*/.exec(options[i]);
correct = /x/i.test(inparens);
fixed = '';
if (/@/.test(inparens)) {
@@ -152,9 +167,9 @@ export const convertMarkdownToXml = (markdown) => {
hint = extractHint(value);
if (hint.hint) {
value = hint.nothint;
- value = `${value } ${ hint.hint } `;
+ value = `${value} ${hint.hint} `;
}
- choices += ` ${ value } \n`;
+ choices += ` ${value} \n`;
}
}
result = '\n';
@@ -174,9 +189,13 @@ export const convertMarkdownToXml = (markdown) => {
xml = xml.replace(/(^\s*((\[.?\])|({{.*?}})).*?$\n*)+/gm, (match) => {
let groupString = '\n';
const options = match.split('\n');
- let correct; let abhint; let endHints;
- let hint; let inner; let select; let
- hints;
+ let correct;
+ let abhint;
+ let endHints;
+ let hint;
+ let inner;
+ let select;
+ let hints;
groupString += ' \n';
endHints = ''; // save these up to emit at the end
@@ -191,7 +210,7 @@ export const convertMarkdownToXml = (markdown) => {
// lone case of hint text processing outside of extractHint, since syntax here is unique
let [, , hintbody] = abhint;
hintbody = hintbody.replace('&lf;', '\n').trim();
- endHints += ` ${ hintbody } \n`;
+ endHints += ` ${hintbody} \n`;
// eslint-disable-next-line no-continue
continue;
}
@@ -203,18 +222,18 @@ export const convertMarkdownToXml = (markdown) => {
// {unselected: Remember that apple is also a fruit.}}
hint = extractHint(value);
if (hint.hint) {
- inner = `{${ hint.hint }}`; // parsing is easier if we put outer { } back
+ inner = `{${hint.hint}}`; // parsing is easier if we put outer { } back
// include \n since we are downstream of extractHint()
select = /{\s*(s|selected):((.|\n)*?)}/i.exec(inner);
// checkbox choicehints get their own line, since there can be two of them
// You’re right that apple is a fruit.
if (select) {
- hints += `\n ${ select[2].trim() } `;
+ hints += `\n ${select[2].trim()} `;
}
select = /{\s*(u|unselected):((.|\n)*?)}/i.exec(inner);
if (select) {
- hints += `\n ${ select[2].trim() } `;
+ hints += `\n ${select[2].trim()} `;
}
// Blank out the original text only if the specific "selected" syntax is found
@@ -223,7 +242,7 @@ export const convertMarkdownToXml = (markdown) => {
value = hint.nothint;
}
}
- groupString += ` ${ value }${hints } \n`;
+ groupString += ` ${value}${hints} \n`;
}
}
@@ -275,9 +294,15 @@ export const convertMarkdownToXml = (markdown) => {
};
const processNumericalResponse = (answerValues) => {
- let firstAnswer; let answerData; let numericalResponseString; let additionalAnswerString;
- let hintLine; let additionalTextHint; let additionalHintLine; let orMatch; let
- hasTolerance;
+ let firstAnswer;
+ let answerData;
+ let numericalResponseString;
+ let additionalAnswerString;
+ let hintLine;
+ let additionalTextHint;
+ let additionalHintLine;
+ let orMatch;
+ let hasTolerance;
// First string case is s?= [e.g. = 100]
firstAnswer = answerValues[0].replace(/^=\s*/, '');
@@ -291,19 +316,19 @@ export const convertMarkdownToXml = (markdown) => {
hintLine = '';
if (textHint.hint) {
firstAnswer = textHint.nothint;
- hintLine = ` ${ textHint.hint } \n`;
+ hintLine = ` ${textHint.hint} \n`;
}
// Range case
if (isRangeToleranceCase(firstAnswer)) {
// [5, 7) or (5, 7), or (1.2345 * (2+3), 7*4 ] - range tolerance case
// = (5*2)*3 should not be used as range tolerance
- numericalResponseString = `\n`;
+ numericalResponseString = `\n`;
} else {
answerData = getAnswerData(firstAnswer);
- numericalResponseString = `\n`;
+ numericalResponseString = `\n`;
if (answerData.default) {
- numericalResponseString += ` \n`;
+ numericalResponseString += ` \n`;
}
}
@@ -319,18 +344,21 @@ export const convertMarkdownToXml = (markdown) => {
// Do not add additional_answer if additional answer is not numerical (eg. or= ABC)
// or contains range tolerance case (eg. or= (5,7)
// or has tolerance (eg. or= 10 +- 0.02)
- if (Number.isNaN(Number(orMatch[1]))
- || isRangeToleranceCase(orMatch[1])
- || hasTolerance) {
- // eslint-disable-next-line no-continue
+ if (
+ Number.isNaN(Number(orMatch[1]))
+ || isRangeToleranceCase(orMatch[1])
+ || hasTolerance
+ ) {
+ // eslint-disable-next-line no-continue
continue;
}
if (additionalTextHint.hint) {
- additionalHintLine = `${ additionalTextHint.hint } `;
+ additionalHintLine =
+ `${additionalTextHint.hint} `;
}
- additionalAnswerString += ` `;
+ additionalAnswerString += ` `;
additionalAnswerString += additionalHintLine;
additionalAnswerString += ' \n';
}
@@ -349,9 +377,13 @@ export const convertMarkdownToXml = (markdown) => {
};
const processStringResponse = (values) => {
- let firstAnswer; let textHint; let typ; let string; let orMatch; let
- notMatch;
- // First string case is s?=
+ let firstAnswer;
+ let textHint;
+ let typ;
+ let string;
+ let orMatch;
+ let notMatch;
+ // First string case is s?=
firstAnswer = values.shift();
firstAnswer = firstAnswer.replace(/^s?=\s*/, '');
textHint = extractHint(firstAnswer);
@@ -361,10 +393,9 @@ export const convertMarkdownToXml = (markdown) => {
typ = ' type="ci regexp"';
firstAnswer = firstAnswer.slice(1).trim();
}
- string = `\n`;
+ string = `\n`;
if (textHint.hint) {
- string += ` ${
- textHint.hint } \n`;
+ string += ` ${textHint.hint} \n`;
}
// Subsequent cases are not= or or=
@@ -372,16 +403,18 @@ export const convertMarkdownToXml = (markdown) => {
textHint = extractHint(values[i]);
notMatch = /^not=\s*(.*)/.exec(textHint.nothint);
if (notMatch) {
- string += ` ${ textHint.hint } \n`;
+ string += ` ${textHint.hint} \n`;
// eslint-disable-next-line no-continue
continue;
}
orMatch = /^or=\s*(.*)/.exec(textHint.nothint);
if (orMatch) {
// additional_answer with answer= attribute
- string += ` `;
+ string += ` `;
if (textHint.hint) {
- string += `${ textHint.hint } `;
+ string += `${textHint.hint} `;
}
string += ' \n';
}
@@ -395,10 +428,13 @@ export const convertMarkdownToXml = (markdown) => {
});
// replace explanations
- xml = xml.replace(/\[explanation\]\n?([^\]]*)\[\/?explanation\]/gmi, (match, p1) => `\n\nExplanation\n\n${ p1 }\n
\n `);
+ xml = xml.replace(
+ /\[explanation\]\n?([^\]]*)\[\/?explanation\]/gmi,
+ (match, p1) => `\n\nExplanation\n\n${p1}\n
\n `,
+ );
// replace code blocks
- xml = xml.replace(/\[code\]\n?([^\]]*)\[\/?code\]/gmi, (match, p1) => `${ p1 } `);
+ xml = xml.replace(/\[code\]\n?([^\]]*)\[\/?code\]/gmi, (match, p1) => `${p1} `);
// split scripts and preformatted sections, and wrap paragraphs
const splits = xml.split(/(<\/?(?:script|pre|label|description).*?>)/g);
@@ -435,7 +471,7 @@ export const convertMarkdownToXml = (markdown) => {
// make temporary xml
const parser = new DOMParser();
- const xmlDoc = parser.parseFromString(`${ xml } `, 'application/xml');
+ const xmlDoc = parser.parseFromString(`${xml} `, 'application/xml');
let responseType = xmlDoc.querySelectorAll(responseTypesSelector);
// convert if there is only one responsetype
if (responseType.length === 1) {
diff --git a/src/editors/utils/convertMarkdownToXML.test.ts b/src/editors/utils/convertMarkdownToXML.test.ts
index 5d8e51519c..54e4e49532 100644
--- a/src/editors/utils/convertMarkdownToXML.test.ts
+++ b/src/editors/utils/convertMarkdownToXML.test.ts
@@ -214,7 +214,8 @@ describe('convertMarkdownToXml', () => {
describe('explanations and code blocks', () => {
it('should convert explanations', () => {
const markdown = '[explanation]\nThis is an explanation\n[/explanation]';
- const expected = '\n\n
Explanation
\n\n
This is an explanation
\n
\n ';
+ const expected =
+ '\n\n
Explanation
\n\n
This is an explanation
\n
\n ';
const result = convertMarkdownToXml(markdown);
expect(normalizeWhitespace(result)).toContain(normalizeWhitespace(expected));
});
@@ -268,7 +269,9 @@ Paris is the capital and most populous city of France.
expect(result).toContain('Choose the correct answer ');
expect(result).toContain('');
expect(result).toContain('');
- expect(result).toContain('Paris Correct! Paris is indeed the capital of France. \n ');
+ expect(result).toContain(
+ 'Paris Correct! Paris is indeed the capital of France. \n ',
+ );
expect(result).toContain('');
expect(result).toContain('');
expect(result).toContain('Need a hint? Think about the Eiffel Tower! ');
diff --git a/src/editors/utils/formatLibraryImgRequest.ts b/src/editors/utils/formatLibraryImgRequest.ts
index e5f1780da0..8a77fb1c7d 100644
--- a/src/editors/utils/formatLibraryImgRequest.ts
+++ b/src/editors/utils/formatLibraryImgRequest.ts
@@ -1,13 +1,13 @@
import { LibraryAssetResponse } from '../../library-authoring/data/api';
type GalleryImageData = {
- displayName: string,
- url: string,
- externalUrl: string,
- portableUrl: string,
- thumbnail: string,
- id: string,
- locked: boolean,
+ displayName: string;
+ url: string;
+ externalUrl: string;
+ portableUrl: string;
+ thumbnail: string;
+ id: string;
+ locked: boolean;
};
/**
@@ -36,7 +36,7 @@ export const getFileName = (data: LibraryAssetResponse): string => data.path.rep
* const isImg = isImage(data); // Returns true
*/
-export const isImage = (data: LibraryAssetResponse, acceptedImgExt:string[]): boolean => {
+export const isImage = (data: LibraryAssetResponse, acceptedImgExt: string[]): boolean => {
const ext = data.path.split('.').pop()?.toLowerCase() ?? ''; // Extract and lowercase the file extension
return ext !== '' && acceptedImgExt.includes(ext);
};
@@ -100,11 +100,12 @@ export const parseLibraryImageData = (data: LibraryAssetResponse): GalleryImageD
export const getLibraryImageAssets = (
librariesAssets: Array,
- acceptedImgExt:string[],
-): Record => librariesAssets.reduce((obj, file) => {
- if (isImage(file, acceptedImgExt)) {
- const imageData = parseLibraryImageData(file);
- return { ...obj, [imageData.displayName]: imageData };
- }
- return obj;
-}, {} as Record);
+ acceptedImgExt: string[],
+): Record =>
+ librariesAssets.reduce((obj, file) => {
+ if (isImage(file, acceptedImgExt)) {
+ const imageData = parseLibraryImageData(file);
+ return { ...obj, [imageData.displayName]: imageData };
+ }
+ return obj;
+ }, {} as Record);
diff --git a/src/editors/utils/formatLibreryImgRequest.test.ts b/src/editors/utils/formatLibreryImgRequest.test.ts
index 3e4a05d55c..cd89a8c346 100644
--- a/src/editors/utils/formatLibreryImgRequest.test.ts
+++ b/src/editors/utils/formatLibreryImgRequest.test.ts
@@ -1,5 +1,8 @@
import {
- parseLibraryImageData, getLibraryImageAssets, isImage, getFileName,
+ parseLibraryImageData,
+ getLibraryImageAssets,
+ isImage,
+ getFileName,
} from './formatLibraryImgRequest';
import { LibraryAssetResponse } from '../../library-authoring/data/api';
diff --git a/src/editors/utils/index.ts b/src/editors/utils/index.ts
index 12436ce9b3..867017f372 100644
--- a/src/editors/utils/index.ts
+++ b/src/editors/utils/index.ts
@@ -1,8 +1,8 @@
-export { default as StrictDict } from './StrictDict';
-export { default as keyStore } from './keyStore';
export { default as camelizeKeys } from './camelizeKeys';
-export { default as removeItemOnce } from './removeOnce';
-export { default as formatDuration } from './formatDuration';
-export { default as snakeCaseKeys } from './snakeCaseKeys';
export { convertMarkdownToXml } from './convertMarkdownToXML';
+export { default as formatDuration } from './formatDuration';
export * from './formatLibraryImgRequest';
+export { default as keyStore } from './keyStore';
+export { default as removeItemOnce } from './removeOnce';
+export { default as snakeCaseKeys } from './snakeCaseKeys';
+export { default as StrictDict } from './StrictDict';
diff --git a/src/editors/utils/keyStore.ts b/src/editors/utils/keyStore.ts
index 560a6f7800..a5c6c14107 100644
--- a/src/editors/utils/keyStore.ts
+++ b/src/editors/utils/keyStore.ts
@@ -1,10 +1,11 @@
import StrictDict from './StrictDict';
-const keyStore = >(collection: Obj): { [K in keyof Obj]: K } => StrictDict(
- Object.keys(collection).reduce(
- (obj, key) => ({ ...obj, [key]: key }),
- {},
- ),
-) as any;
+const keyStore = >(collection: Obj): { [K in keyof Obj]: K; } =>
+ StrictDict(
+ Object.keys(collection).reduce(
+ (obj, key) => ({ ...obj, [key]: key }),
+ {},
+ ),
+ ) as any;
export default keyStore;
diff --git a/src/editors/utils/snakeCaseKeys.test.js b/src/editors/utils/snakeCaseKeys.test.js
index 3bdd209c59..78b251acab 100644
--- a/src/editors/utils/snakeCaseKeys.test.js
+++ b/src/editors/utils/snakeCaseKeys.test.js
@@ -1,26 +1,24 @@
import { camelizeKeys } from './index';
const snakeCaseObject = {
- some_attribute:
- {
- another_attribute: [
- { a_list: 'a lIsT' },
- { of_attributes: 'iN diFferent' },
- { different_cases: 'to Test' },
- ],
- },
+ some_attribute: {
+ another_attribute: [
+ { a_list: 'a lIsT' },
+ { of_attributes: 'iN diFferent' },
+ { different_cases: 'to Test' },
+ ],
+ },
a_final_attribute: null,
a_last_one: undefined,
};
const camelCaseObject = {
- someAttribute:
- {
- anotherAttribute: [
- { aList: 'a lIsT' },
- { ofAttributes: 'iN diFferent' },
- { differentCases: 'to Test' },
- ],
- },
+ someAttribute: {
+ anotherAttribute: [
+ { aList: 'a lIsT' },
+ { ofAttributes: 'iN diFferent' },
+ { differentCases: 'to Test' },
+ ],
+ },
aFinalAttribute: null,
aLastOne: undefined,
};
diff --git a/src/export-page/CourseExportPage.test.tsx b/src/export-page/CourseExportPage.test.tsx
index 6170edd33d..d53e9408d2 100644
--- a/src/export-page/CourseExportPage.test.tsx
+++ b/src/export-page/CourseExportPage.test.tsx
@@ -33,13 +33,14 @@ jest.mock('universal-cookie', () => {
return jest.fn(() => mCookie);
});
-const renderComponent = () => render(
-
-
-
-
- ,
-);
+const renderComponent = () =>
+ render(
+
+
+
+
+ ,
+ );
describe(' ', () => {
beforeEach(() => {
@@ -95,14 +96,21 @@ describe(' ', () => {
it('should show modal error', async () => {
axiosMock
.onGet(getExportStatusApiUrl(courseId))
- .reply(200, { exportStatus: EXPORT_STAGES.EXPORTING, exportError: { rawErrorMsg: 'test error', editUnitUrl: 'http://test-url.test' } });
+ .reply(200, {
+ exportStatus: EXPORT_STAGES.EXPORTING,
+ exportError: { rawErrorMsg: 'test error', editUnitUrl: 'http://test-url.test' },
+ });
const user = userEvent.setup();
const { container } = renderComponent();
const startExportButton = container.querySelector('.btn-primary')!;
await user.click(startExportButton);
// eslint-disable-next-line no-promise-executor-return
await new Promise((r) => setTimeout(r, 3500));
- expect(screen.getByText(/There has been a failure to export to XML at least one component. It is recommended that you go to the edit page and repair the error before attempting another export. Please check that all components on the page are valid and do not display any error messages. The raw error message is: test error/i));
+ expect(
+ screen.getByText(
+ /There has been a failure to export to XML at least one component. It is recommended that you go to the edit page and repair the error before attempting another export. Please check that all components on the page are valid and do not display any error messages. The raw error message is: test error/i,
+ ),
+ );
const closeModalWindowButton = screen.getByText('Return to export');
await user.click(closeModalWindowButton);
expect(screen.queryByText(modalErrorMessages.errorCancelButtonUnit.defaultMessage)).not.toBeInTheDocument();
diff --git a/src/export-page/CourseExportPage.tsx b/src/export-page/CourseExportPage.tsx
index 8f34d1c493..931f2fed46 100644
--- a/src/export-page/CourseExportPage.tsx
+++ b/src/export-page/CourseExportPage.tsx
@@ -1,6 +1,9 @@
import { useIntl } from '@edx/frontend-platform/i18n';
import {
- Container, Layout, Button, Card,
+ Container,
+ Layout,
+ Button,
+ Card,
} from '@openedx/paragon';
import { ArrowCircleDown as ArrowCircleDownIcon } from '@openedx/paragon/icons';
import { getConfig } from '@edx/frontend-platform';
@@ -68,7 +71,9 @@ const CourseExportPage = () => {
title={intl.formatMessage(messages.headingTitle)}
subtitle={intl.formatMessage(messages.headingSubtitle)}
/>
- {intl.formatMessage(messages.description1, { studioShortName: getConfig().STUDIO_SHORT_NAME })}
+
+ {intl.formatMessage(messages.description1, { studioShortName: getConfig().STUDIO_SHORT_NAME })}
+
{intl.formatMessage(messages.description2)}
{
diff --git a/src/export-page/data/apiHooks.ts b/src/export-page/data/apiHooks.ts
index dee0df77b2..d3150e6756 100644
--- a/src/export-page/data/apiHooks.ts
+++ b/src/export-page/data/apiHooks.ts
@@ -1,7 +1,10 @@
/* eslint-disable import/no-extraneous-dependencies */
import { AxiosError } from 'axios';
import {
- useQueryClient, skipToken, useMutation, useQuery,
+ useQueryClient,
+ skipToken,
+ useMutation,
+ useQuery,
} from '@tanstack/react-query';
import { getExportStatus, startCourseExporting, type ExportStatusData } from './api';
diff --git a/src/export-page/export-modal-error/ExportModalError.tsx b/src/export-page/export-modal-error/ExportModalError.tsx
index c63e4fa61f..9b7f700393 100644
--- a/src/export-page/export-modal-error/ExportModalError.tsx
+++ b/src/export-page/export-modal-error/ExportModalError.tsx
@@ -24,26 +24,28 @@ const ExportModalError = () => {
}
}, [fetchExportErrorMessage]);
- const handleUnitRedirect = () => { window.location.assign(errorUnitUrl ?? ''); };
- const handleRedirectCourseHome = () => { window.location.assign(`${getConfig().STUDIO_BASE_URL}/course/${courseId}`); };
+ const handleUnitRedirect = () => {
+ window.location.assign(errorUnitUrl ?? '');
+ };
+ const handleRedirectCourseHome = () => {
+ window.location.assign(`${getConfig().STUDIO_BASE_URL}/course/${courseId}`);
+ };
return (
setIsErrorModalOpen(false)}
handleAction={errorUnitUrl ? handleUnitRedirect : handleRedirectCourseHome}
variant="danger"
diff --git a/src/export-page/export-sidebar/ExportSidebar.test.tsx b/src/export-page/export-sidebar/ExportSidebar.test.tsx
index 5783f2fc3f..1da2a004ae 100644
--- a/src/export-page/export-sidebar/ExportSidebar.test.tsx
+++ b/src/export-page/export-sidebar/ExportSidebar.test.tsx
@@ -7,13 +7,14 @@ import { CourseExportProvider } from '../CourseExportContext';
const courseId = 'course-123';
-const renderComponent = () => render(
-
-
-
-
- ,
-);
+const renderComponent = () =>
+ render(
+
+
+
+
+ ,
+ );
describe(' ', () => {
beforeEach(() => {
diff --git a/src/export-page/export-sidebar/ExportSidebar.tsx b/src/export-page/export-sidebar/ExportSidebar.tsx
index 7434399ae0..d8b1dff761 100644
--- a/src/export-page/export-sidebar/ExportSidebar.tsx
+++ b/src/export-page/export-sidebar/ExportSidebar.tsx
@@ -15,7 +15,9 @@ const ExportSidebar = () => {
return (
{intl.formatMessage(messages.title1)}
- {intl.formatMessage(messages.description1, { studioShortName: getConfig().STUDIO_SHORT_NAME })}
+
+ {intl.formatMessage(messages.description1, { studioShortName: getConfig().STUDIO_SHORT_NAME })}
+
{intl.formatMessage(messages.exportedContent)}
{intl.formatMessage(messages.exportedContentHeading)}
diff --git a/src/export-page/export-stepper/ExportStepper.test.tsx b/src/export-page/export-stepper/ExportStepper.test.tsx
index e23091b964..f0439d1cbe 100644
--- a/src/export-page/export-stepper/ExportStepper.test.tsx
+++ b/src/export-page/export-stepper/ExportStepper.test.tsx
@@ -7,13 +7,14 @@ import { CourseExportProvider } from '../CourseExportContext';
const courseId = 'course-123';
-const renderComponent = () => render(
-
-
-
-
- ,
-);
+const renderComponent = () =>
+ render(
+
+
+
+
+ ,
+ );
describe(' ', () => {
beforeEach(() => {
diff --git a/src/export-page/export-stepper/ExportStepper.tsx b/src/export-page/export-stepper/ExportStepper.tsx
index 2ed56ebadb..5185a7fee3 100644
--- a/src/export-page/export-stepper/ExportStepper.tsx
+++ b/src/export-page/export-stepper/ExportStepper.tsx
@@ -18,16 +18,18 @@ const ExportStepper = () => {
const successTitle = intl.formatMessage(messages.stepperSuccessTitle);
let successTitleComponent;
- const localizedSuccessDate = successDate ? (
-
- ) : null;
+ const localizedSuccessDate = successDate ?
+ (
+
+ ) :
+ null;
if (localizedSuccessDate && currentStage === EXPORT_STAGES.SUCCESS) {
successTitleComponent = (
@@ -42,15 +44,18 @@ const ExportStepper = () => {
title: intl.formatMessage(messages.stepperPreparingTitle),
description: intl.formatMessage(messages.stepperPreparingDescription),
key: EXPORT_STAGES.PREPARING,
- }, {
+ },
+ {
title: intl.formatMessage(messages.stepperExportingTitle),
description: intl.formatMessage(messages.stepperExportingDescription),
key: EXPORT_STAGES.EXPORTING,
- }, {
+ },
+ {
title: intl.formatMessage(messages.stepperCompressingTitle),
description: intl.formatMessage(messages.stepperCompressingDescription),
key: EXPORT_STAGES.COMPRESSING,
- }, {
+ },
+ {
title: successTitle,
description: intl.formatMessage(messages.stepperSuccessDescription),
key: EXPORT_STAGES.SUCCESS,
diff --git a/src/files-and-videos/files-page/CourseFilesTable.tsx b/src/files-and-videos/files-page/CourseFilesTable.tsx
index 1fc9e885eb..77f08bc2e8 100644
--- a/src/files-and-videos/files-page/CourseFilesTable.tsx
+++ b/src/files-and-videos/files-page/CourseFilesTable.tsx
@@ -31,7 +31,7 @@ import { useParams } from 'react-router-dom';
export const CourseFilesTable = () => {
const intl = useIntl();
- const { courseId } = useParams() as { courseId: string };
+ const { courseId } = useParams() as { courseId: string; };
const dispatch = useDispatch();
const {
assetIds,
@@ -42,10 +42,11 @@ export const CourseFilesTable = () => {
const handleErrorReset = (error) => dispatch(resetErrors(error));
const handleDeleteFile = (id) => dispatch(deleteAssetFile(courseId, id));
- const handleDownloadFile = (selectedRows) => dispatch(fetchAssetDownload({
- selectedRows,
- courseId,
- }));
+ const handleDownloadFile = (selectedRows) =>
+ dispatch(fetchAssetDownload({
+ selectedRows,
+ courseId,
+ }));
const handleAddFile = (files) => {
handleErrorReset({ errorType: 'add' });
dispatch(validateAssetFiles(courseId, files));
@@ -64,10 +65,11 @@ export const CourseFilesTable = () => {
};
const thumbnailPreview = (props) => FileThumbnail(props);
- const infoModalSidebar = (asset) => FileInfoModalSidebar({
- asset,
- handleLockedAsset: handleLockFile,
- });
+ const infoModalSidebar = (asset) =>
+ FileInfoModalSidebar({
+ asset,
+ handleLockedAsset: handleLockFile,
+ });
const assets = useModels('assets', assetIds);
const data = {
diff --git a/src/files-and-videos/files-page/FileThumbnail.jsx b/src/files-and-videos/files-page/FileThumbnail.jsx
index af31472ce7..c43823ba88 100644
--- a/src/files-and-videos/files-page/FileThumbnail.jsx
+++ b/src/files-and-videos/files-page/FileThumbnail.jsx
@@ -26,27 +26,29 @@ const FileThumbnail = ({
return (
- {thumbnail ? (
-
- ) : (
-
-
-
- )}
+ {thumbnail ?
+ (
+
+ ) :
+ (
+
+
+
+ )}
);
};
diff --git a/src/files-and-videos/files-page/FilesPage.jsx b/src/files-and-videos/files-page/FilesPage.jsx
index 210c43bdc1..22f9e00980 100644
--- a/src/files-and-videos/files-page/FilesPage.jsx
+++ b/src/files-and-videos/files-page/FilesPage.jsx
@@ -64,9 +64,7 @@ const FilesPage = () => {
{intl.formatMessage(messages.heading)}
- {loadingStatus !== RequestStatus.FAILED && (
-
- )}
+ {loadingStatus !== RequestStatus.FAILED && }
);
diff --git a/src/files-and-videos/files-page/FilesPage.test.jsx b/src/files-and-videos/files-page/FilesPage.test.jsx
index 7dbe06474d..14753ba53b 100644
--- a/src/files-and-videos/files-page/FilesPage.test.jsx
+++ b/src/files-and-videos/files-page/FilesPage.test.jsx
@@ -230,7 +230,8 @@ describe('FilesAndUploads', () => {
const { asset: newDefaultAssetResponse } = generateNewAssetApiResponse();
const responseData = {
asset: {
- ...newDefaultAssetResponse, id: 'mOckID6',
+ ...newDefaultAssetResponse,
+ id: 'mOckID6',
},
};
@@ -414,11 +415,14 @@ describe('FilesAndUploads', () => {
fireEvent.click(within(assetMenuButton).getByLabelText('file-menu-toggle'));
fireEvent.click(screen.getByText('Info'));
- await executeThunk(getUsagePaths({
- courseId,
- asset: { id: 'mOckID1', displayName: 'mOckID1' },
- setSelectedRows: jest.fn(),
- }), store.dispatch);
+ await executeThunk(
+ getUsagePaths({
+ courseId,
+ asset: { id: 'mOckID1', displayName: 'mOckID1' },
+ setSelectedRows: jest.fn(),
+ }),
+ store.dispatch,
+ );
await waitFor(() => {
expect(screen.getAllByLabelText('mOckID1')[0]).toBeVisible();
});
@@ -436,21 +440,27 @@ describe('FilesAndUploads', () => {
axiosMock.onGet(`${getAssetsUrl(courseId)}mOckID1/usage`).reply(201, { usage_locations: { mOckID1: [] } });
fireEvent.click(within(assetMenuButton).getByLabelText('file-menu-toggle'));
fireEvent.click(screen.getByText('Info'));
- await executeThunk(getUsagePaths({
- courseId,
- asset: { id: 'mOckID1', displayName: 'mOckID1' },
- setSelectedRows: jest.fn(),
- }), store.dispatch);
+ await executeThunk(
+ getUsagePaths({
+ courseId,
+ asset: { id: 'mOckID1', displayName: 'mOckID1' },
+ setSelectedRows: jest.fn(),
+ }),
+ store.dispatch,
+ );
await waitFor(() => {
expect(screen.getAllByLabelText('mOckID1')[0]).toBeVisible();
});
fireEvent.click(screen.getByLabelText('Checkbox'));
- await executeThunk(updateAssetLock({
- courseId,
- assetId: 'mOckID1',
- locked: false,
- }), store.dispatch);
+ await executeThunk(
+ updateAssetLock({
+ courseId,
+ assetId: 'mOckID1',
+ locked: false,
+ }),
+ store.dispatch,
+ );
expect(screen.getByText(messages.usageNotInUseMessage.defaultMessage)).toBeVisible();
const updateStatus = store.getState().assets.updatingStatus;
@@ -465,11 +475,14 @@ describe('FilesAndUploads', () => {
axiosMock.onPut(`${getAssetsUrl(courseId)}mOckID1`).reply(201, { locked: false });
fireEvent.click(within(assetMenuButton).getByLabelText('file-menu-toggle'));
fireEvent.click(screen.getByText('Unlock'));
- await executeThunk(updateAssetLock({
- courseId,
- assetId: 'mOckID1',
- locked: false,
- }), store.dispatch);
+ await executeThunk(
+ updateAssetLock({
+ courseId,
+ assetId: 'mOckID1',
+ locked: false,
+ }),
+ store.dispatch,
+ );
await waitFor(() => {
const updateStatus = store.getState().assets.updatingStatus;
expect(updateStatus).toEqual(RequestStatus.SUCCESSFUL);
@@ -484,11 +497,14 @@ describe('FilesAndUploads', () => {
axiosMock.onPut(`${getAssetsUrl(courseId)}mOckID3`).reply(201, { locked: true });
fireEvent.click(within(assetMenuButton).getByLabelText('file-menu-toggle'));
fireEvent.click(screen.getByText('Lock'));
- await executeThunk(updateAssetLock({
- courseId,
- assetId: 'mOckID3',
- locked: true,
- }), store.dispatch);
+ await executeThunk(
+ updateAssetLock({
+ courseId,
+ assetId: 'mOckID3',
+ locked: true,
+ }),
+ store.dispatch,
+ );
await waitFor(() => {
const updateStatus = store.getState().assets.updatingStatus;
expect(updateStatus).toEqual(RequestStatus.SUCCESSFUL);
@@ -626,11 +642,14 @@ describe('FilesAndUploads', () => {
axiosMock.onGet(`${getAssetsUrl(courseId)}mOckID3/usage`).reply(404);
fireEvent.click(within(assetMenuButton).getByLabelText('file-menu-toggle'));
fireEvent.click(screen.getByText('Info'));
- await executeThunk(getUsagePaths({
- courseId,
- asset: { id: 'mOckID3', displayName: 'mOckID3' },
- setSelectedRows: jest.fn(),
- }), store.dispatch);
+ await executeThunk(
+ getUsagePaths({
+ courseId,
+ asset: { id: 'mOckID3', displayName: 'mOckID3' },
+ setSelectedRows: jest.fn(),
+ }),
+ store.dispatch,
+ );
await waitFor(() => {
const { usageStatus } = store.getState().assets;
expect(usageStatus).toEqual(RequestStatus.FAILED);
@@ -645,11 +664,14 @@ describe('FilesAndUploads', () => {
axiosMock.onPut(`${getAssetsUrl(courseId)}mOckID3`).reply(404);
fireEvent.click(within(assetMenuButton).getByLabelText('file-menu-toggle'));
fireEvent.click(screen.getByText('Lock'));
- await executeThunk(updateAssetLock({
- courseId,
- assetId: 'mOckID3',
- locked: true,
- }), store.dispatch);
+ await executeThunk(
+ updateAssetLock({
+ courseId,
+ assetId: 'mOckID3',
+ locked: true,
+ }),
+ store.dispatch,
+ );
await waitFor(() => {
const updateStatus = store.getState().assets.updatingStatus;
expect(updateStatus).toEqual(RequestStatus.FAILED);
diff --git a/src/files-and-videos/files-page/data/api.js b/src/files-and-videos/files-page/data/api.js
index fe34ff8dbb..afad4bf969 100644
--- a/src/files-and-videos/files-page/data/api.js
+++ b/src/files-and-videos/files-page/data/api.js
@@ -90,7 +90,6 @@ export async function getDownload(selectedRows, courseId) {
/**
* Fetch where asset is used in a course.
* @param {blockId} courseId Course ID for the course to operate on
-
*/
export async function getAssetUsagePaths({ courseId, assetId }) {
const { data } = await getAuthenticatedHttpClient()
@@ -102,7 +101,6 @@ export async function getAssetUsagePaths({ courseId, assetId }) {
/**
* Delete asset to course.
* @param {blockId} courseId Course ID for the course to operate on
-
*/
export async function deleteAsset(courseId, assetId) {
await getAuthenticatedHttpClient()
@@ -112,7 +110,6 @@ export async function deleteAsset(courseId, assetId) {
/**
* Add asset to course.
* @param {blockId} courseId Course ID for the course to operate on
-
*/
export async function addAsset(courseId, file) {
const formData = new FormData();
@@ -125,7 +122,6 @@ export async function addAsset(courseId, file) {
/**
* Update locked attribute for provided asset.
* @param {blockId} courseId Course ID for the course to operate on
-
*/
export async function updateLockStatus({ assetId, courseId, locked }) {
const { data } = await getAuthenticatedHttpClient()
diff --git a/src/files-and-videos/files-page/data/thunks.js b/src/files-and-videos/files-page/data/thunks.js
index d648fc3b07..21989b16f3 100644
--- a/src/files-and-videos/files-page/data/thunks.js
+++ b/src/files-and-videos/files-page/data/thunks.js
@@ -186,7 +186,9 @@ export function updateAssetLock({ assetId, courseId, locked }) {
}
export function resetErrors({ errorType }) {
- return (dispatch) => { dispatch(clearErrors({ error: errorType })); };
+ return (dispatch) => {
+ dispatch(clearErrors({ error: errorType }));
+ };
}
export function getUsagePaths({ asset, courseId }) {
@@ -206,7 +208,9 @@ export function getUsagePaths({ asset, courseId }) {
}));
dispatch(updateEditStatus({ editType: 'usageMetrics', status: RequestStatus.SUCCESSFUL }));
} catch {
- dispatch(updateErrors({ error: 'usageMetrics', message: `Failed to get usage metrics for ${asset.displayName}.` }));
+ dispatch(
+ updateErrors({ error: 'usageMetrics', message: `Failed to get usage metrics for ${asset.displayName}.` }),
+ );
dispatch(updateEditStatus({ editType: 'usageMetrics', status: RequestStatus.FAILED }));
}
};
diff --git a/src/files-and-videos/generic/DeleteConfirmationModal.jsx b/src/files-and-videos/generic/DeleteConfirmationModal.jsx
index c60d0a29a8..96d64d79c7 100644
--- a/src/files-and-videos/generic/DeleteConfirmationModal.jsx
+++ b/src/files-and-videos/generic/DeleteConfirmationModal.jsx
@@ -40,13 +40,13 @@ const DeleteConfirmationModal = ({
{original.displayName}
- )}
+ }
data-testid={`collapsible-${original.id}`}
>
@@ -75,7 +75,7 @@ const DeleteConfirmationModal = ({
)}
isOpen={isDeleteConfirmationOpen}
onClose={closeDeleteConfirmation}
- footerNode={(
+ footerNode={
{intl.formatMessage(messages.cancelButtonLabel)}
@@ -84,7 +84,7 @@ const DeleteConfirmationModal = ({
{intl.formatMessage(messages.deleteFileButtonLabel)}
- )}
+ }
>
{intl.formatMessage(
messages.deleteConfirmationMessage,
diff --git a/src/files-and-videos/generic/DeleteConfirmationModal.test.jsx b/src/files-and-videos/generic/DeleteConfirmationModal.test.jsx
index 669e497b70..1c4cf16efc 100644
--- a/src/files-and-videos/generic/DeleteConfirmationModal.test.jsx
+++ b/src/files-and-videos/generic/DeleteConfirmationModal.test.jsx
@@ -17,7 +17,8 @@ const defaultProps = {
activeStatus: 'active',
id: 'file-test',
usageLocations: [{
- displayLocation: 'unit', url: 'unit/url',
+ displayLocation: 'unit',
+ url: 'unit/url',
}],
},
}],
diff --git a/src/files-and-videos/generic/FileInput.tsx b/src/files-and-videos/generic/FileInput.tsx
index 4a4d5b7ff6..c6537308f3 100644
--- a/src/files-and-videos/generic/FileInput.tsx
+++ b/src/files-and-videos/generic/FileInput.tsx
@@ -4,15 +4,15 @@ import { getSupportedFormats } from '../videos-page/data/utils';
import messages from './messages';
declare interface UseFileInputArgs {
- onAddFile: (files: File[]) => void,
- setSelectedRows: (files: File[]) => void,
- setAddOpen: () => void,
+ onAddFile: (files: File[]) => void;
+ setSelectedRows: (files: File[]) => void;
+ setAddOpen: () => void;
}
declare interface FileInputVars {
- click: () => void,
- addFile: ChangeEventHandler,
- ref: MutableRefObject
+ click: () => void;
+ addFile: ChangeEventHandler;
+ ref: MutableRefObject;
}
export const useFileInput = ({
@@ -38,16 +38,19 @@ export const useFileInput = ({
declare interface FileInputArgs {
fileInput: {
- addFile: ChangeEventHandler,
- ref: MutableRefObject,
- },
- supportedFileFormats?: string | string[] | Record,
- allowMultiple?: boolean,
- id?: string,
+ addFile: ChangeEventHandler;
+ ref: MutableRefObject;
+ };
+ supportedFileFormats?: string | string[] | Record;
+ allowMultiple?: boolean;
+ id?: string;
}
const FileInput = ({
- fileInput: hook, supportedFileFormats, allowMultiple = true, id,
+ fileInput: hook,
+ supportedFileFormats,
+ allowMultiple = true,
+ id,
}: FileInputArgs) => {
const intl = useIntl();
return (
diff --git a/src/files-and-videos/generic/FileMenu.jsx b/src/files-and-videos/generic/FileMenu.jsx
index c0a4924aa2..070f6c3aba 100644
--- a/src/files-and-videos/generic/FileMenu.jsx
+++ b/src/files-and-videos/generic/FileMenu.jsx
@@ -32,29 +32,31 @@ const FileMenu = ({
alt="file-menu-toggle"
/>
- {fileType === 'video' ? (
- navigator.clipboard.writeText(id)}
- >
- {intl.formatMessage(messages.copyVideoIdTitle)}
-
- ) : (
- <>
+ {fileType === 'video' ?
+ (
navigator.clipboard.writeText(portableUrl)}
+ onClick={() => navigator.clipboard.writeText(id)}
>
- {intl.formatMessage(messages.copyStudioUrlTitle)}
+ {intl.formatMessage(messages.copyVideoIdTitle)}
- navigator.clipboard.writeText(externalUrl)}
- >
- {intl.formatMessage(messages.copyWebUrlTitle)}
-
-
- {locked ? intl.formatMessage(messages.unlockMenuTitle) : intl.formatMessage(messages.lockMenuTitle)}
-
- >
- )}
+ ) :
+ (
+ <>
+ navigator.clipboard.writeText(portableUrl)}
+ >
+ {intl.formatMessage(messages.copyStudioUrlTitle)}
+
+ navigator.clipboard.writeText(externalUrl)}
+ >
+ {intl.formatMessage(messages.copyWebUrlTitle)}
+
+
+ {locked ? intl.formatMessage(messages.unlockMenuTitle) : intl.formatMessage(messages.lockMenuTitle)}
+
+ >
+ )}
{intl.formatMessage(messages.downloadTitle)}
diff --git a/src/files-and-videos/generic/FileTable.jsx b/src/files-and-videos/generic/FileTable.jsx
index 78e676fa88..0dd632aacb 100644
--- a/src/files-and-videos/generic/FileTable.jsx
+++ b/src/files-and-videos/generic/FileTable.jsx
@@ -76,7 +76,8 @@ const FileTable = ({
supportedFileFormats,
fileType,
} = data;
- const defaultCurrentView = (fileType === 'video' && localStorage.getItem('videosCurrentView')) || (fileType === 'file' && localStorage.getItem('filesCurrentView')) || defaultView;
+ const defaultCurrentView = (fileType === 'video' && localStorage.getItem('videosCurrentView')) ||
+ (fileType === 'file' && localStorage.getItem('filesCurrentView')) || defaultView;
const [currentView, setCurrentView] = useState(defaultCurrentView);
useEffect(() => {
@@ -173,14 +174,15 @@ const FileTable = ({
const moreInfoColumn = {
id: 'moreInfo',
Header: '',
- Cell: ({ row }) => MoreInfoColumn({
- row,
- handleLock: handleLockFile,
- handleBulkDownload,
- handleOpenFileInfo,
- handleOpenDeleteConfirmation,
- fileType,
- }),
+ Cell: ({ row }) =>
+ MoreInfoColumn({
+ row,
+ handleLock: handleLockFile,
+ handleBulkDownload,
+ handleOpenFileInfo,
+ handleOpenDeleteConfirmation,
+ fileType,
+ }),
};
const hasMoreInfoColumn = tableColumns.filter(col => col.id === 'moreInfo').length === 1;
@@ -222,27 +224,36 @@ const FileTable = ({
FilterStatusComponent={FilterStatus}
RowStatusComponent={RowStatus}
>
- {isEmpty(files) && loadingStatus !== RequestStatus.IN_PROGRESS ? (
-
- ) : (
-
-
-
- { currentView === 'card' && }
- { currentView === 'list' && }
-
-
-
- )}
+ {isEmpty(files) && loadingStatus !== RequestStatus.IN_PROGRESS ?
+ (
+
+ ) :
+ (
+
+
+
+ {currentView === 'card' && (
+
+ )}
+ {currentView === 'list' && }
+
+
+
+ )}
)}
-
);
};
diff --git a/src/files-and-videos/generic/InfoModal.jsx b/src/files-and-videos/generic/InfoModal.jsx
index 662ffe55a0..f654783f6a 100644
--- a/src/files-and-videos/generic/InfoModal.jsx
+++ b/src/files-and-videos/generic/InfoModal.jsx
@@ -53,12 +53,12 @@ const InfoModal = ({
{showTranscriptionError && (
{intl.formatMessage(messages.transcriptionErrorMessage, { error: file.errorDescription })}
- )}
+ }
variant="danger"
/>
)}
diff --git a/src/files-and-videos/generic/UsageMetricsMessage.jsx b/src/files-and-videos/generic/UsageMetricsMessage.jsx
index 106bd08a48..d3387a27f4 100644
--- a/src/files-and-videos/generic/UsageMetricsMessage.jsx
+++ b/src/files-and-videos/generic/UsageMetricsMessage.jsx
@@ -20,19 +20,19 @@ const UsageMetricsMessage = ({
const intl = useIntl();
let usageMessage;
if (usagePathStatus === RequestStatus.SUCCESSFUL) {
- usageMessage = isEmpty(usageLocations) ? (
-
- ) : (
-
- {usageLocations.map(location => (
-
-
- {location.displayLocation}
-
-
- ))}
-
- );
+ usageMessage = isEmpty(usageLocations) ?
+
:
+ (
+
+ {usageLocations.map(location => (
+
+
+ {location.displayLocation}
+
+
+ ))}
+
+ );
} else if (usagePathStatus === RequestStatus.FAILED) {
usageMessage = (
diff --git a/src/files-and-videos/generic/constants.ts b/src/files-and-videos/generic/constants.ts
index 95a95e8f1f..ccdda7fbc9 100644
--- a/src/files-and-videos/generic/constants.ts
+++ b/src/files-and-videos/generic/constants.ts
@@ -1,6 +1,17 @@
const FILES_AND_UPLOAD_TYPE_FILTERS = {
- images: ['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/tiff', 'image/tif', 'image/x-icon',
- 'image/svg+xml', 'image/bmp', 'image/x-ms-bmp', 'image/vnd.microsoft.icon'],
+ images: [
+ 'image/png',
+ 'image/jpeg',
+ 'image/jpg',
+ 'image/gif',
+ 'image/tiff',
+ 'image/tif',
+ 'image/x-icon',
+ 'image/svg+xml',
+ 'image/bmp',
+ 'image/x-ms-bmp',
+ 'image/vnd.microsoft.icon',
+ ],
documents: [
'application/pdf',
'text/plain',
@@ -26,13 +37,42 @@ const FILES_AND_UPLOAD_TYPE_FILTERS = {
'text/x-sh',
'application/pdf',
],
- audio: ['audio/mpeg', 'audio/mp3', 'audio/x-wav', 'audio/ogg', 'audio/wav', 'audio/aac', 'audio/x-m4a',
- 'audio/mp4', 'audio/x-ms-wma'],
- code: ['application/json', 'text/html', 'text/javascript', 'application/javascript', 'text/css', 'text/x-python',
- 'application/x-java-jnlp-file', 'application/xml', 'application/postscript', 'application/x-javascript',
- 'application/java-vm', 'text/x-c++src', 'text/xml', 'text/x-scss', 'application/x-python-code',
- 'application/java-archive', 'text/x-python-script', 'application/x-ruby', 'application/mathematica',
- 'text/coffeescript', 'text/x-matlab', 'application/sql', 'text/php'],
+ audio: [
+ 'audio/mpeg',
+ 'audio/mp3',
+ 'audio/x-wav',
+ 'audio/ogg',
+ 'audio/wav',
+ 'audio/aac',
+ 'audio/x-m4a',
+ 'audio/mp4',
+ 'audio/x-ms-wma',
+ ],
+ code: [
+ 'application/json',
+ 'text/html',
+ 'text/javascript',
+ 'application/javascript',
+ 'text/css',
+ 'text/x-python',
+ 'application/x-java-jnlp-file',
+ 'application/xml',
+ 'application/postscript',
+ 'application/x-javascript',
+ 'application/java-vm',
+ 'text/x-c++src',
+ 'text/xml',
+ 'text/x-scss',
+ 'application/x-python-code',
+ 'application/java-archive',
+ 'text/x-python-script',
+ 'application/x-ruby',
+ 'application/mathematica',
+ 'text/coffeescript',
+ 'text/x-matlab',
+ 'application/sql',
+ 'text/php',
+ ],
video: ['.mp4', '.mov'],
};
diff --git a/src/files-and-videos/generic/index.ts b/src/files-and-videos/generic/index.ts
index a9dc9d93ec..5d942485d8 100644
--- a/src/files-and-videos/generic/index.ts
+++ b/src/files-and-videos/generic/index.ts
@@ -22,5 +22,5 @@ export {
useFileInput,
TranscriptColumn,
};
-export { default as FileTable } from './FileTable';
export { default as EditFileErrors } from './EditFileErrors';
+export { default as FileTable } from './FileTable';
diff --git a/src/files-and-videos/generic/table-components/FilterStatus.jsx b/src/files-and-videos/generic/table-components/FilterStatus.jsx
index e967e07944..3b95063892 100644
--- a/src/files-and-videos/generic/table-components/FilterStatus.jsx
+++ b/src/files-and-videos/generic/table-components/FilterStatus.jsx
@@ -2,17 +2,28 @@ import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import {
- DataTableContext, Button, Row, Chip,
+ DataTableContext,
+ Button,
+ Row,
+ Chip,
} from '@openedx/paragon';
import { Close } from '@openedx/paragon/icons';
import { getFilters, removeFilter } from './utils';
const FilterStatus = ({
- className, variant, size, clearFiltersText, buttonClassName,
+ className,
+ variant,
+ size,
+ clearFiltersText,
+ buttonClassName,
}) => {
const intl = useIntl();
const {
- state, setAllFilters, setFilter, RowStatusComponent, columns,
+ state,
+ setAllFilters,
+ setFilter,
+ RowStatusComponent,
+ columns,
} = useContext(DataTableContext);
if (!setAllFilters) {
diff --git a/src/files-and-videos/generic/table-components/Footer.jsx b/src/files-and-videos/generic/table-components/Footer.jsx
index 34b1932aa2..fe9f19b745 100644
--- a/src/files-and-videos/generic/table-components/Footer.jsx
+++ b/src/files-and-videos/generic/table-components/Footer.jsx
@@ -3,7 +3,10 @@ import { DataTableContext, Pagination, TableFooter } from '@openedx/paragon';
const Footer = () => {
const {
- pageOptions, pageCount, gotoPage, state,
+ pageOptions,
+ pageCount,
+ gotoPage,
+ state,
} = useContext(DataTableContext);
if (pageOptions.length < 2) {
diff --git a/src/files-and-videos/generic/table-components/GalleryCard.jsx b/src/files-and-videos/generic/table-components/GalleryCard.jsx
index c51820a96e..e17af8beda 100644
--- a/src/files-and-videos/generic/table-components/GalleryCard.jsx
+++ b/src/files-and-videos/generic/table-components/GalleryCard.jsx
@@ -30,7 +30,7 @@ const GalleryCard = ({
handleBulkDownload([{
- original: {
- id: original.id,
- displayName:
- original.displayName,
- downloadLink: original?.downloadLink,
- },
- }])}
+ onDownload={() =>
+ handleBulkDownload([{
+ original: {
+ id: original.id,
+ displayName: original.displayName,
+ downloadLink: original?.downloadLink,
+ },
+ }])}
openDeleteConfirmation={() => handleOpenDeleteConfirmation([{ original }])}
/>
- )}
+ }
/>
diff --git a/src/files-and-videos/generic/table-components/TableActions.jsx b/src/files-and-videos/generic/table-components/TableActions.jsx
index 8323aa3d8f..188de71315 100644
--- a/src/files-and-videos/generic/table-components/TableActions.jsx
+++ b/src/files-and-videos/generic/table-components/TableActions.jsx
@@ -51,14 +51,16 @@ const TableActions = ({
- {encodingsDownloadUrl ? (
-
-
-
- ) : null}
+ {encodingsDownloadUrl ?
+ (
+
+
+
+ ) :
+ null}
handleBulkDownload(selectedFlatRows)}
disabled={isEmpty(selectedFlatRows)}
diff --git a/src/files-and-videos/generic/table-components/TableActions.test.jsx b/src/files-and-videos/generic/table-components/TableActions.test.jsx
index 803987f36c..178aa96285 100644
--- a/src/files-and-videos/generic/table-components/TableActions.test.jsx
+++ b/src/files-and-videos/generic/table-components/TableActions.test.jsx
@@ -57,7 +57,9 @@ describe('TableActions', () => {
expect(screen.getByRole('button', { name: messages.sortButtonLabel.defaultMessage })).toBeInTheDocument();
expect(screen.getByRole('button', { name: messages.actionsButtonLabel.defaultMessage })).toBeInTheDocument();
- expect(screen.getByRole('button', { name: messages.addFilesButtonLabel.defaultMessage.replace('{fileType}', 'video') })).toBeInTheDocument();
+ expect(
+ screen.getByRole('button', { name: messages.addFilesButtonLabel.defaultMessage.replace('{fileType}', 'video') }),
+ ).toBeInTheDocument();
});
test('disables bulk and delete actions if no rows selected', () => {
@@ -90,7 +92,9 @@ describe('TableActions', () => {
const mockClear = jest.fn();
renderWithContext({ fileInputControl: { click: mockClick } }, {}, mockClear);
- fireEvent.click(screen.getByRole('button', { name: messages.addFilesButtonLabel.defaultMessage.replace('{fileType}', 'video') }));
+ fireEvent.click(
+ screen.getByRole('button', { name: messages.addFilesButtonLabel.defaultMessage.replace('{fileType}', 'video') }),
+ );
expect(mockClick).toHaveBeenCalled();
});
@@ -130,6 +134,9 @@ describe('TableActions', () => {
renderWithContext({ encodingsDownloadUrl });
fireEvent.click(screen.getByRole('button', { name: messages.actionsButtonLabel.defaultMessage }));
- expect(screen.getByRole('link', { name: messages.downloadEncodingsTitle.defaultMessage })).toHaveAttribute('href', expect.stringContaining(encodingsDownloadUrl));
+ expect(screen.getByRole('link', { name: messages.downloadEncodingsTitle.defaultMessage })).toHaveAttribute(
+ 'href',
+ expect.stringContaining(encodingsDownloadUrl),
+ );
});
});
diff --git a/src/files-and-videos/generic/table-components/sort-and-filter-modal/SortAndFilterModal.jsx b/src/files-and-videos/generic/table-components/sort-and-filter-modal/SortAndFilterModal.jsx
index 3c3e291cfb..2ee94bb31a 100644
--- a/src/files-and-videos/generic/table-components/sort-and-filter-modal/SortAndFilterModal.jsx
+++ b/src/files-and-videos/generic/table-components/sort-and-filter-modal/SortAndFilterModal.jsx
@@ -21,13 +21,19 @@ const SortAndFilterModal = ({
}) => {
const intl = useIntl();
const {
- state, setAllFilters, columns, gotoPage,
+ state,
+ setAllFilters,
+ columns,
+ gotoPage,
} = useContext(DataTableContext);
const filterOptions = getFilterOptions(columns);
const currentFilters = getCheckedFilters(state);
const [sortBy, setSortBy] = useState('dateAdded,desc');
const [filterBy, {
- add, remove, set, clear,
+ add,
+ remove,
+ set,
+ clear,
}] = useCheckboxSetValues(currentFilters);
useEffect(() => {
@@ -146,9 +152,7 @@ const SortAndFilterModal = ({
value={filterBy}
isInline
>
- {filterOptions.map(({ name, value }) => (
- {name}
- ))}
+ {filterOptions.map(({ name, value }) => {name} )}
diff --git a/src/files-and-videos/generic/table-components/table-custom-columns/AccessColumn.jsx b/src/files-and-videos/generic/table-components/table-custom-columns/AccessColumn.jsx
index 113b5da0e6..30af0f2254 100644
--- a/src/files-and-videos/generic/table-components/table-custom-columns/AccessColumn.jsx
+++ b/src/files-and-videos/generic/table-components/table-custom-columns/AccessColumn.jsx
@@ -11,17 +11,13 @@ const AccessColumn = ({ row }) => {
return (
{intl.formatMessage(messages.lockFileTooltipContent)}
- )}
+ }
>
- {locked ? (
-
- ) : (
-
- )}
+ {locked ? : }
);
};
diff --git a/src/files-and-videos/generic/table-components/table-custom-columns/MoreInfoColumn.jsx b/src/files-and-videos/generic/table-components/table-custom-columns/MoreInfoColumn.jsx
index c389ec5fd0..1c5206af70 100644
--- a/src/files-and-videos/generic/table-components/table-custom-columns/MoreInfoColumn.jsx
+++ b/src/files-and-videos/generic/table-components/table-custom-columns/MoreInfoColumn.jsx
@@ -50,60 +50,61 @@ const MoreInfoColumn = ({
onClose={close}
onEscapeKey={close}
>
-
- {fileType === 'video' ? (
- {
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- navigator.clipboard.writeText(id);
- close();
- }}
- >
- {intl.formatMessage(messages.copyVideoIdTitle)}
-
- ) : (
- <>
+
+ {fileType === 'video' ?
+ (
{
// eslint-disable-next-line @typescript-eslint/no-floating-promises
- navigator.clipboard.writeText(portableUrl);
+ navigator.clipboard.writeText(id);
close();
}}
>
- {intl.formatMessage(messages.copyStudioUrlTitle)}
+ {intl.formatMessage(messages.copyVideoIdTitle)}
- {
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- navigator.clipboard.writeText(externalUrl);
- close();
- }}
- >
- {intl.formatMessage(messages.copyWebUrlTitle)}
-
- handleLock(id, !locked)}
- >
- {locked ? intl.formatMessage(messages.unlockMenuTitle) : intl.formatMessage(messages.lockMenuTitle)}
-
- >
- )}
+ ) :
+ (
+ <>
+ {
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
+ navigator.clipboard.writeText(portableUrl);
+ close();
+ }}
+ >
+ {intl.formatMessage(messages.copyStudioUrlTitle)}
+
+ {
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
+ navigator.clipboard.writeText(externalUrl);
+ close();
+ }}
+ >
+ {intl.formatMessage(messages.copyWebUrlTitle)}
+
+ handleLock(id, !locked)}
+ >
+ {locked ? intl.formatMessage(messages.unlockMenuTitle) : intl.formatMessage(messages.lockMenuTitle)}
+
+ >
+ )}
handleBulkDownload(
- [{ original: { id, displayName, downloadLink } }],
- )}
+ onClick={() =>
+ handleBulkDownload(
+ [{ original: { id, displayName, downloadLink } }],
+ )}
>
{intl.formatMessage(messages.downloadTitle)}
diff --git a/src/files-and-videos/generic/table-components/table-custom-columns/index.ts b/src/files-and-videos/generic/table-components/table-custom-columns/index.ts
index 5c33cab8e6..437a099674 100644
--- a/src/files-and-videos/generic/table-components/table-custom-columns/index.ts
+++ b/src/files-and-videos/generic/table-components/table-custom-columns/index.ts
@@ -5,11 +5,4 @@ import StatusColumn from './StatusColumn';
import ThumbnailColumn from './ThumbnailColumn';
import TranscriptColumn from './TranscriptColumn';
-export {
- AccessColumn,
- ActiveColumn,
- MoreInfoColumn,
- StatusColumn,
- ThumbnailColumn,
- TranscriptColumn,
-};
+export { AccessColumn, ActiveColumn, MoreInfoColumn, StatusColumn, ThumbnailColumn, TranscriptColumn };
diff --git a/src/files-and-videos/videos-page/CourseVideosTable.tsx b/src/files-and-videos/videos-page/CourseVideosTable.tsx
index fe14b2645b..1aeb4c69a1 100644
--- a/src/files-and-videos/videos-page/CourseVideosTable.tsx
+++ b/src/files-and-videos/videos-page/CourseVideosTable.tsx
@@ -1,6 +1,9 @@
import { useIntl } from '@edx/frontend-platform/i18n';
import {
- ActionRow, Button, CheckboxFilter, useToggle,
+ ActionRow,
+ Button,
+ CheckboxFilter,
+ useToggle,
} from '@openedx/paragon';
import { AgreementGated } from '@src/constants';
import { RequestStatus } from '@src/data/constants';
@@ -39,7 +42,7 @@ import { useParams } from 'react-router-dom';
export const CourseVideosTable = () => {
const intl = useIntl();
- const { courseId } = useParams() as { courseId: string };
+ const { courseId } = useParams() as { courseId: string; };
const dispatch = useDispatch();
const [
isTranscriptSettingsOpen,
@@ -120,21 +123,23 @@ export const CourseVideosTable = () => {
dispatch(addVideoFile(courseId, files, videoIds, uploadingIdsRef));
};
const handleDeleteFile = (id) => dispatch(deleteVideoFile(courseId, id));
- const handleDownloadFile = (selectedRows) => dispatch(fetchVideoDownload({
- selectedRows,
- courseId,
- }));
+ const handleDownloadFile = (selectedRows) =>
+ dispatch(fetchVideoDownload({
+ selectedRows,
+ courseId,
+ }));
const handleUsagePaths = (video) => dispatch(getUsagePaths({ video, courseId }));
const handleFileOrder = ({ newFileIdOrder }) => {
dispatch(updateVideoOrder(courseId, newFileIdOrder));
};
- const handleAddThumbnail = (file, videoId) => resampleFile({
- file,
- dispatch,
- courseId,
- videoId,
- addVideoThumbnail,
- });
+ const handleAddThumbnail = (file, videoId) =>
+ resampleFile({
+ file,
+ dispatch,
+ courseId,
+ videoId,
+ addVideoThumbnail,
+ });
const videos = useModels('videos', videoIds);
@@ -147,12 +152,13 @@ export const CourseVideosTable = () => {
usageErrorMessages: errorMessages.usageMetrics,
fileType: 'video',
};
- const thumbnailPreview = (props) => VideoThumbnail({
- ...props,
- pageLoadStatus: loadingStatus,
- handleAddThumbnail,
- videoImageSettings,
- });
+ const thumbnailPreview = (props) =>
+ VideoThumbnail({
+ ...props,
+ pageLoadStatus: loadingStatus,
+ handleAddThumbnail,
+ videoImageSettings,
+ });
const infoModalSidebar = (video, activeTab, setActiveTab) => (
);
@@ -230,54 +236,54 @@ export const CourseVideosTable = () => {
<>
- {isVideoTranscriptEnabled ? (
- {
- openTranscriptSettings();
- handleErrorReset({ errorType: 'transcript' });
- }}
- >
- {intl.formatMessage(messages.transcriptSettingsButtonLabel)}
-
- ) : null}
+ {isVideoTranscriptEnabled ?
+ (
+ {
+ openTranscriptSettings();
+ handleErrorReset({ errorType: 'transcript' });
+ }}
+ >
+ {intl.formatMessage(messages.transcriptSettingsButtonLabel)}
+
+ ) :
+ null}
- {
- loadingStatus !== RequestStatus.FAILED && (
- <>
- {isVideoTranscriptEnabled && (
-
- )}
-
- >
- )
- }
+ {loadingStatus !== RequestStatus.FAILED && (
+ <>
+ {isVideoTranscriptEnabled && (
+
+ )}
+
+ >
+ )}
{allowThumbnailUpload && isUploaded &&
}
- {showThumbnail && !thumbnailError && pageLoadStatus === RequestStatus.SUCCESSFUL ? (
- <>
-
- { thumbnail ? (
-
setThumbnailError(true)}
- />
- ) : (
-
+
+ {thumbnail ?
+ (
+
setThumbnailError(true)}
+ />
+ ) :
+ (
+
+
+
+ )}
+
+
+
-
-
- )}
-
-
-
+
+ >
+ ) :
+ (
+ <>
+
- {addThumbnailMessage}
-
-
- >
- ) : (
- <>
-
-
-
-
- {!isUploaded && (
-
- {!isFailed ? status : failedMessage}
-
- )}
-
- >
- )}
+
+
+
+ {!isUploaded && (
+
+ {!isFailed ? status : failedMessage}
+
+ )}
+
+ >
+ )}
{allowThumbnailUpload && (
{
window.dispatchEvent(new Event('beforeunload'));
});
await waitFor(() => {
- expect(setFailedSpy).toHaveBeenCalledWith(courseId, expect.any(String), expect.any(String), 'upload_failed');
+ expect(setFailedSpy).toHaveBeenCalledWith(
+ courseId,
+ expect.any(String),
+ expect.any(String),
+ 'upload_failed',
+ );
});
uploadSpy.mockRestore();
setFailedSpy.mockRestore();
@@ -311,7 +316,12 @@ describe('Videos page', () => {
});
await waitFor(() => {
const addStatus = store.getState().videos.addingStatus;
- expect(setFailedSpy).toHaveBeenCalledWith(courseId, expect.any(String), expect.any(String), 'upload_failed');
+ expect(setFailedSpy).toHaveBeenCalledWith(
+ courseId,
+ expect.any(String),
+ expect.any(String),
+ 'upload_failed',
+ );
expect(addStatus).toEqual(RequestStatus.FAILED);
@@ -703,10 +713,13 @@ describe('Videos page', () => {
axiosMock.onGet(`${getVideosUrl(courseId)}/mOckID3/usage`).reply(404);
fireEvent.click(within(videoMenuButton).getByLabelText('file-menu-toggle'));
fireEvent.click(screen.getByText('Info'));
- await executeThunk(getUsagePaths({
- courseId,
- video: { id: 'mOckID3', displayName: 'mOckID3' },
- }), store.dispatch);
+ await executeThunk(
+ getUsagePaths({
+ courseId,
+ video: { id: 'mOckID3', displayName: 'mOckID3' },
+ }),
+ store.dispatch,
+ );
await waitFor(() => {
const { usageStatus } = store.getState().videos;
expect(usageStatus).toEqual(RequestStatus.FAILED);
@@ -729,8 +742,11 @@ describe('Videos page', () => {
axiosMock.onPut(`${getVideosUrl(courseId)}/download`).reply(404);
fireEvent.click(downloadButton!);
- // @ts-ignore
- await executeThunk(fetchVideoDownload([{ original: { displayName: 'mOckID1', id: '2', downloadLink: 'test' } }]), store.dispatch);
+ await executeThunk(
+ // @ts-ignore
+ fetchVideoDownload([{ original: { displayName: 'mOckID1', id: '2', downloadLink: 'test' } }]),
+ store.dispatch,
+ );
const updateStatus = store.getState().videos.updatingStatus;
expect(updateStatus).toEqual(RequestStatus.FAILED);
diff --git a/src/files-and-videos/videos-page/data/api.js b/src/files-and-videos/videos-page/data/api.js
index 19d7cd8d49..b6d1f41d82 100644
--- a/src/files-and-videos/videos-page/data/api.js
+++ b/src/files-and-videos/videos-page/data/api.js
@@ -34,8 +34,10 @@ export async function getVideos(courseId) {
export async function getAllUsagePaths({ courseId, videoIds }) {
// Hack: pass 'videoId' into the 'config' object; it will be ignored by axios
// but allows us to read it out later to easily get the videoId per result.
- const apiPromises = videoIds.map(id => getAuthenticatedHttpClient()
- .get(`${getVideosUrl(courseId)}/${id}/usage`, { videoId: id }));
+ const apiPromises = videoIds.map(id =>
+ getAuthenticatedHttpClient()
+ .get(`${getVideosUrl(courseId)}/${id}/usage`, { videoId: id })
+ );
const updatedUsageLocations = [];
const results = await Promise.allSettled(apiPromises);
@@ -142,7 +144,6 @@ export async function getDownload(selectedRows, courseId) {
/**
* Fetch where a video is used in a course.
* @param {blockId} courseId Course ID for the course to operate on
-
*/
export async function getVideoUsagePaths({ courseId, videoId }) {
const { data } = await getAuthenticatedHttpClient()
@@ -153,7 +154,6 @@ export async function getVideoUsagePaths({ courseId, videoId }) {
/**
* Delete video from course.
* @param {blockId} courseId Course ID for the course to operate on
-
*/
export async function deleteVideo(courseId, videoId) {
await getAuthenticatedHttpClient()
@@ -163,7 +163,6 @@ export async function deleteVideo(courseId, videoId) {
/**
* Add thumbnail to video.
* @param {blockId} courseId Course ID for the course to operate on
-
*/
export async function addThumbnail({ courseId, videoId, file }) {
const formData = new FormData();
@@ -176,7 +175,6 @@ export async function addThumbnail({ courseId, videoId, file }) {
/**
* Add video to course.
* @param {blockId} courseId Course ID for the course to operate on
-
*/
export async function addVideo(courseId, file, controller) {
const postJson = {
diff --git a/src/files-and-videos/videos-page/data/api.test.ts b/src/files-and-videos/videos-page/data/api.test.ts
index 310fe8637a..6edbe5bd00 100644
--- a/src/files-and-videos/videos-page/data/api.test.ts
+++ b/src/files-and-videos/videos-page/data/api.test.ts
@@ -4,7 +4,12 @@ import { initializeMockApp } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient, getHttpClient } from '@edx/frontend-platform/auth';
import {
- getDownload, getVideosUrl, getAllUsagePaths, getCourseVideosApiUrl, uploadVideo, sendVideoUploadStatus,
+ getDownload,
+ getVideosUrl,
+ getAllUsagePaths,
+ getCourseVideosApiUrl,
+ uploadVideo,
+ sendVideoUploadStatus,
} from './api';
jest.mock('file-saver');
@@ -133,7 +138,10 @@ describe('api.js', () => {
const loaded = total * progress;
if (config.onUploadProgress) {
config.onUploadProgress({
- loaded, total, bytes: loaded, lengthComputable: true,
+ loaded,
+ total,
+ bytes: loaded,
+ lengthComputable: true,
});
}
return [200, expectedResult];
diff --git a/src/files-and-videos/videos-page/data/thunks.js b/src/files-and-videos/videos-page/data/thunks.js
index d9e94ca160..9bbfcf0704 100644
--- a/src/files-and-videos/videos-page/data/thunks.js
+++ b/src/files-and-videos/videos-page/data/thunks.js
@@ -333,7 +333,12 @@ export function addVideoFile(
edxVideoId,
});
hasFailure = await uploadToBucket({
- courseId, uploadUrl, file, uploadingIdsRef, edxVideoId, dispatch,
+ courseId,
+ uploadUrl,
+ file,
+ uploadingIdsRef,
+ edxVideoId,
+ dispatch,
});
} else {
hasFailure = true;
diff --git a/src/files-and-videos/videos-page/data/utils.js b/src/files-and-videos/videos-page/data/utils.js
index 70b7f289b6..0d1bcad70a 100644
--- a/src/files-and-videos/videos-page/data/utils.js
+++ b/src/files-and-videos/videos-page/data/utils.js
@@ -278,7 +278,7 @@ export const validateForm = (cieloHasCredentials, threePlayHasCredentials, provi
case 'Cielo24':
if (cieloHasCredentials) {
return !isEmpty(cielo24Fidelity) && !isEmpty(cielo24Turnaround)
- && !isEmpty(preferredLanguages) && !isEmpty(videoSourceLanguage);
+ && !isEmpty(preferredLanguages) && !isEmpty(videoSourceLanguage);
}
return !isEmpty(apiKey) && !isEmpty(username);
case '3PlayMedia':
diff --git a/src/files-and-videos/videos-page/index.ts b/src/files-and-videos/videos-page/index.ts
index bb97e14716..6e1cae0782 100644
--- a/src/files-and-videos/videos-page/index.ts
+++ b/src/files-and-videos/videos-page/index.ts
@@ -5,9 +5,4 @@ import VideoThumbnail from './VideoThumbnail';
import VideoInfoModalSidebar from './info-sidebar';
export default VideosPage;
-export {
- TranscriptSettings,
- UploadModal,
- VideoThumbnail,
- VideoInfoModalSidebar,
-};
+export { TranscriptSettings, UploadModal, VideoThumbnail, VideoInfoModalSidebar };
diff --git a/src/files-and-videos/videos-page/info-sidebar/TranscriptTab.test.jsx b/src/files-and-videos/videos-page/info-sidebar/TranscriptTab.test.jsx
index 4ab3011d80..656214024d 100644
--- a/src/files-and-videos/videos-page/info-sidebar/TranscriptTab.test.jsx
+++ b/src/files-and-videos/videos-page/info-sidebar/TranscriptTab.test.jsx
@@ -91,15 +91,21 @@ describe('TranscriptTab', () => {
it('should delete empty transcript row', async () => {
renderComponent(defaultProps);
const addButton = screen.getByText(messages.uploadButtonLabel.defaultMessage);
- await act(async () => { fireEvent.click(addButton); });
+ await act(async () => {
+ fireEvent.click(addButton);
+ });
const deleteButton = screen.getByLabelText('delete empty transcript');
- await act(async () => { fireEvent.click(deleteButton); });
+ await act(async () => {
+ fireEvent.click(deleteButton);
+ });
expect(screen.getByText(transcriptRowMessages.deleteConfirmationHeader.defaultMessage)).toBeVisible();
const confirmButton = screen.getByText(transcriptRowMessages.confirmDeleteLabel.defaultMessage);
- await act(async () => { fireEvent.click(confirmButton); });
+ await act(async () => {
+ fireEvent.click(confirmButton);
+ });
expect(screen.queryByTestId('transcript-')).toBeNull();
});
@@ -111,7 +117,9 @@ describe('TranscriptTab', () => {
renderComponent(defaultProps);
addButton = screen.getByText(messages.uploadButtonLabel.defaultMessage);
- await act(async () => { fireEvent.click(addButton); });
+ await act(async () => {
+ fireEvent.click(addButton);
+ });
});
it('should upload new transcript', async () => {
@@ -196,12 +204,15 @@ describe('TranscriptTab', () => {
axiosMock.onDelete(`${getApiBaseUrl()}/transcript_delete/${courseId}/mOckID0/ar`).reply(204);
await act(async () => {
fireEvent.click(confirmButton);
- await executeThunk(deleteVideoTranscript({
- language: 'ar',
- videoId: updatedProps.id,
- transcripts: updatedProps.transcripts,
- apiUrl: `/transcript_delete/${courseId}`,
- }), store.dispatch);
+ await executeThunk(
+ deleteVideoTranscript({
+ language: 'ar',
+ videoId: updatedProps.id,
+ transcripts: updatedProps.transcripts,
+ apiUrl: `/transcript_delete/${courseId}`,
+ }),
+ store.dispatch,
+ );
});
const deleteStatus = store.getState().videos.transcriptStatus;
@@ -215,12 +226,15 @@ describe('TranscriptTab', () => {
axiosMock.onDelete(`${getApiBaseUrl()}/transcript_delete/${courseId}/mOckID0/ar`).reply(404);
await act(async () => {
fireEvent.click(confirmButton);
- await executeThunk(deleteVideoTranscript({
- language: 'ar',
- videoId: updatedProps.id,
- transcripts: updatedProps.transcripts,
- apiUrl: `/transcript_delete/${courseId}`,
- }), store.dispatch);
+ await executeThunk(
+ deleteVideoTranscript({
+ language: 'ar',
+ videoId: updatedProps.id,
+ transcripts: updatedProps.transcripts,
+ apiUrl: `/transcript_delete/${courseId}`,
+ }),
+ store.dispatch,
+ );
});
const deleteStatus = store.getState().videos.transcriptStatus;
diff --git a/src/files-and-videos/videos-page/info-sidebar/VideoInfoModalSidebar.jsx b/src/files-and-videos/videos-page/info-sidebar/VideoInfoModalSidebar.jsx
index d582cb6282..d567c54e3c 100644
--- a/src/files-and-videos/videos-page/info-sidebar/VideoInfoModalSidebar.jsx
+++ b/src/files-and-videos/videos-page/info-sidebar/VideoInfoModalSidebar.jsx
@@ -33,9 +33,9 @@ const VideoInfoModalSidebar = ({
{ transcriptCount: video.transcripts.length },
)}
notification={TRANSCRIPT_FAILURE_STATUSES.includes(video.transcriptionStatus) && (
-
- {intl.formatMessage(messages.notificationScreenReaderText)}
-
+
+ {intl.formatMessage(messages.notificationScreenReaderText)}
+
)}
>
diff --git a/src/files-and-videos/videos-page/info-sidebar/transcript-item/LanguageSelect.jsx b/src/files-and-videos/videos-page/info-sidebar/transcript-item/LanguageSelect.jsx
index e0ab163c63..e1a57cd9cf 100644
--- a/src/files-and-videos/videos-page/info-sidebar/transcript-item/LanguageSelect.jsx
+++ b/src/files-and-videos/videos-page/info-sidebar/transcript-item/LanguageSelect.jsx
@@ -48,9 +48,7 @@ const LanguageSelect = ({
onClose={close}
onEscapeKey={close}
>
-
+
{Object.entries(options).map(([valueKey, text]) => {
if (valueKey === value) {
diff --git a/src/files-and-videos/videos-page/info-sidebar/transcript-item/Transcript.jsx b/src/files-and-videos/videos-page/info-sidebar/transcript-item/Transcript.jsx
index ad5566df90..77301d7010 100644
--- a/src/files-and-videos/videos-page/info-sidebar/transcript-item/Transcript.jsx
+++ b/src/files-and-videos/videos-page/info-sidebar/transcript-item/Transcript.jsx
@@ -52,65 +52,69 @@ const Transcript = ({
return (
<>
- {isConfirmationOpen ? (
-
- )} />
-
-
-
-
-
-
-
-
- {
- handleTranscript({ language: transcript }, 'delete');
- closeConfirmation();
- }}
- >
-
-
-
-
-
- ) : (
-
-
- { transcript === '' ? (
-
+ } />
+
+
+
+
+
+
+
+
+ {
+ handleTranscript({ language: transcript }, 'delete');
+ closeConfirmation();
+ }}
+ >
+
+
+
+
+
+ ) :
+ (
+
+
- ) : (
-
- )}
-
- )}
+ {transcript === '' ?
+ (
+
+ ) :
+ (
+
+ )}
+
+ )}
>
);
diff --git a/src/files-and-videos/videos-page/info-sidebar/transcript-item/TranscriptMenu.jsx b/src/files-and-videos/videos-page/info-sidebar/transcript-item/TranscriptMenu.jsx
index bfc04f8fe8..5f321691e8 100644
--- a/src/files-and-videos/videos-page/info-sidebar/transcript-item/TranscriptMenu.jsx
+++ b/src/files-and-videos/videos-page/info-sidebar/transcript-item/TranscriptMenu.jsx
@@ -39,9 +39,7 @@ export const TranscriptActionMenu = ({
onClose={close}
onEscapeKey={close}
>
-
+
{
if (allowMultiple) {
return (
- handleSelect([valueKey, e.target.checked])} key={`${valueKey}-item`}>
+ handleSelect([valueKey, e.target.checked])}
+ key={`${valueKey}-item`}
+ >
{text}
);
@@ -43,7 +48,8 @@ const FormDropdown = ({
if (valueKey === value) {
return (
- {text}
+
+ {text}
);
}
diff --git a/src/files-and-videos/videos-page/transcript-settings/ThreePlayMediaForm.jsx b/src/files-and-videos/videos-page/transcript-settings/ThreePlayMediaForm.jsx
index dda5ba5f8a..bd5af68b34 100644
--- a/src/files-and-videos/videos-page/transcript-settings/ThreePlayMediaForm.jsx
+++ b/src/files-and-videos/videos-page/transcript-settings/ThreePlayMediaForm.jsx
@@ -57,41 +57,43 @@ const ThreePlayMediaForm = ({
/>
- {!isEmpty(data.videoSourceLanguage) ? (
-
-
-
-
- {
- if (!allowMultiple) {
- setData({ ...data, preferredLanguages: [value] });
- } else {
- const [lang, checked] = value;
- if (checked) {
- setData({ ...data, preferredLanguages: [...selectedLanguages, lang] });
+ {!isEmpty(data.videoSourceLanguage) ?
+ (
+
+
+
+
+ {
+ if (!allowMultiple) {
+ setData({ ...data, preferredLanguages: [value] });
} else {
- const updatedLangList = selectedLanguages.filter((selected) => selected !== lang);
- setData({ ...data, preferredLanguages: updatedLangList });
+ const [lang, checked] = value;
+ if (checked) {
+ setData({ ...data, preferredLanguages: [...selectedLanguages, lang] });
+ } else {
+ const updatedLangList = selectedLanguages.filter((selected) => selected !== lang);
+ setData({ ...data, preferredLanguages: updatedLangList });
+ }
}
- }
- }}
- placeholderText={intl.formatMessage(messages.threePlayMediaTranscriptLanguagePlaceholder)}
- />
-
-
- {selectedLanguages.map(language => (
-
- {languages[language]}
-
- ))}
-
-
-
- ) : null }
+ }}
+ placeholderText={intl.formatMessage(messages.threePlayMediaTranscriptLanguagePlaceholder)}
+ />
+
+
+ {selectedLanguages.map(language => (
+
+ {languages[language]}
+
+ ))}
+
+
+
+ ) :
+ null}
);
diff --git a/src/files-and-videos/videos-page/transcript-settings/TranscriptSettings.jsx b/src/files-and-videos/videos-page/transcript-settings/TranscriptSettings.jsx
index 2638508f1a..299b6929bc 100644
--- a/src/files-and-videos/videos-page/transcript-settings/TranscriptSettings.jsx
+++ b/src/files-and-videos/videos-page/transcript-settings/TranscriptSettings.jsx
@@ -6,7 +6,8 @@ import { FormattedMessage } from '@edx/frontend-platform/i18n';
import {
ActionRow,
Collapsible,
- Icon, IconButton,
+ Icon,
+ IconButton,
Sheet,
TransitionReplace,
} from '@openedx/paragon';
@@ -62,55 +63,57 @@ const TranscriptSettings = ({
<>
- {transcriptType ? (
- setTranscriptType(null)}
- alt="back button to main transcript settings view"
- />
- ) : (
-
-
-
- )}
+ {transcriptType ?
+ (
+ setTranscriptType(null)}
+ alt="back button to main transcript settings view"
+ />
+ ) :
+ (
+
+
+
+ )}
- { transcriptType ? (
-
-
-
- ) : (
-
- setTranscriptType('order')}
- >
-
+
+
+ ) :
+ (
+
+ setTranscriptType('order')}
>
-
-
-
-
-
- )}
+
+
+
+
+
+
+ )}
>
)}
diff --git a/src/files-and-videos/videos-page/transcript-settings/TranscriptSettings.test.jsx b/src/files-and-videos/videos-page/transcript-settings/TranscriptSettings.test.jsx
index 8912e52cce..85a40fa432 100644
--- a/src/files-and-videos/videos-page/transcript-settings/TranscriptSettings.test.jsx
+++ b/src/files-and-videos/videos-page/transcript-settings/TranscriptSettings.test.jsx
@@ -605,7 +605,9 @@ describe('TranscriptSettings', () => {
});
expect(updateButton).not.toHaveAttribute('disabled');
- axiosMock.onPost(`${getApiBaseUrl()}/transcript_preferences/${courseId}`).reply(404, { error: 'Invalid turnaround.' });
+ axiosMock.onPost(`${getApiBaseUrl()}/transcript_preferences/${courseId}`).reply(404, {
+ error: 'Invalid turnaround.',
+ });
fireEvent.click(updateButton);
await waitFor(() => {
const { transcriptStatus } = store.getState().videos;
diff --git a/src/files-and-videos/videos-page/upload-modal/UploadStatusIcon.jsx b/src/files-and-videos/videos-page/upload-modal/UploadStatusIcon.jsx
index b620372dd0..21b38316b3 100644
--- a/src/files-and-videos/videos-page/upload-modal/UploadStatusIcon.jsx
+++ b/src/files-and-videos/videos-page/upload-modal/UploadStatusIcon.jsx
@@ -7,9 +7,9 @@ import { RequestStatus } from '../../../data/constants';
const UploadStatusIcon = ({ status }) => {
switch (status) {
case RequestStatus.SUCCESSFUL:
- return ( );
+ return ;
case RequestStatus.FAILED:
- return ( );
+ return ;
case RequestStatus.IN_PROGRESS:
return (
{
/>
);
default:
- return (
);
+ return
;
}
};
diff --git a/src/frontend-platform.d.ts b/src/frontend-platform.d.ts
index d728a4fcc2..46baabf1a3 100644
--- a/src/frontend-platform.d.ts
+++ b/src/frontend-platform.d.ts
@@ -3,7 +3,6 @@
// (whichever comes first).
declare module '@edx/frontend-platform/i18n' {
-
// eslint-disable-next-line import/no-extraneous-dependencies
export {
createIntl,
diff --git a/src/generic/DraggableList/SortableItem.tsx b/src/generic/DraggableList/SortableItem.tsx
index 274fa1781c..373e08ece9 100644
--- a/src/generic/DraggableList/SortableItem.tsx
+++ b/src/generic/DraggableList/SortableItem.tsx
@@ -2,23 +2,26 @@ import React, { KeyboardEventHandler, MouseEventHandler } from 'react';
import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import {
- ActionRow, Card, Icon, IconButtonWithTooltip,
+ ActionRow,
+ Card,
+ Icon,
+ IconButtonWithTooltip,
} from '@openedx/paragon';
import { DragIndicator } from '@openedx/paragon/icons';
import { useIntl } from '@edx/frontend-platform/i18n';
import messages from './messages';
interface SortableItemProps {
- id: string,
- children?: React.ReactNode,
- actions: React.ReactNode,
- actionStyle?: {},
- componentStyle?: {},
- isClickable?: boolean,
- onClick?: MouseEventHandler,
- onKeyDown?: KeyboardEventHandler,
- disabled?: boolean,
- cardClassName?: string,
+ id: string;
+ children?: React.ReactNode;
+ actions: React.ReactNode;
+ actionStyle?: {};
+ componentStyle?: {};
+ isClickable?: boolean;
+ onClick?: MouseEventHandler;
+ onKeyDown?: KeyboardEventHandler;
+ disabled?: boolean;
+ cardClassName?: string;
}
const SortableItem = ({
@@ -71,16 +74,16 @@ const SortableItem = ({
{actions}
{!disabled && (
-
+
)}
{children}
diff --git a/src/generic/FieldFeedback.jsx b/src/generic/FieldFeedback.jsx
index 5a47a42e44..5f55b59197 100644
--- a/src/generic/FieldFeedback.jsx
+++ b/src/generic/FieldFeedback.jsx
@@ -12,23 +12,27 @@ const FieldFeedback = ({
}) => (
<>
- {feedbackCondition ? (
-
-
- {feedbackMessage}
-
-
- ) : }
+ {feedbackCondition ?
+ (
+
+
+ {feedbackMessage}
+
+
+ ) :
+ }
- {errorCondition ? (
-
-
- {errorMessage}
-
-
- ) : }
+ {errorCondition ?
+ (
+
+
+ {errorMessage}
+
+
+ ) :
+ }
>
);
diff --git a/src/generic/FormikControl.tsx b/src/generic/FormikControl.tsx
index 6ce65c1bc1..f902fd02be 100644
--- a/src/generic/FormikControl.tsx
+++ b/src/generic/FormikControl.tsx
@@ -30,9 +30,11 @@ const FormikControl: React.FC>
const fieldTouched = formikContext ? getIn(formikContext.touched, name) : false;
const fieldError = formikContext ? getIn(formikContext.errors, name) : undefined;
- const handleFocus = formikContext ? (
- e: { target: { name: any; } },
- ) => formikContext?.setFieldError(e.target.name, undefined) : undefined;
+ const handleFocus = formikContext ?
+ (
+ e: { target: { name: any; }; },
+ ) => formikContext?.setFieldError(e.target.name, undefined) :
+ undefined;
const handleBlur = formikContext ? formikContext.handleBlur : undefined;
const handleChange = formikContext ? formikContext.handleChange : undefined;
const formikSetFieldValue = formikContext ? formikContext.setFieldValue : undefined;
diff --git a/src/generic/Loading.tsx b/src/generic/Loading.tsx
index 10b5d1ae10..e2169f1d36 100644
--- a/src/generic/Loading.tsx
+++ b/src/generic/Loading.tsx
@@ -11,13 +11,13 @@ export const LoadingSpinner = ({ size }: LoadingSpinnerProps) => (
role="status"
variant="primary"
size={size}
- screenReaderText={(
+ screenReaderText={
- )}
+ }
/>
);
diff --git a/src/generic/WysiwygEditor.jsx b/src/generic/WysiwygEditor.jsx
index 812601bc1b..cd1c0d9e2b 100644
--- a/src/generic/WysiwygEditor.jsx
+++ b/src/generic/WysiwygEditor.jsx
@@ -10,7 +10,10 @@ export const SUPPORTED_TEXT_EDITORS = {
};
export const WysiwygEditor = ({
- initialValue, editorType, onChange, minHeight,
+ initialValue,
+ editorType,
+ onChange,
+ minHeight,
}) => {
const { editorRef, refReady, setEditorRef } = prepareEditorRef();
const { courseId } = useCourseAuthoringContext();
@@ -27,7 +30,8 @@ export const WysiwygEditor = ({
};
// default initial string returned onEditorChange if empty input
- const needToChange = (value) => !isEquivalentCodeQuotes(initialValue, value)
+ const needToChange = (value) =>
+ !isEquivalentCodeQuotes(initialValue, value)
&& !isEquivalentCodeExtraSpaces(initialValue, value)
&& (initialValue !== DEFAULT_EMPTY_WYSIWYG_VALUE || value !== '');
diff --git a/src/generic/agreement-gated-feature/AlertAgreementGatedFeature.tsx b/src/generic/agreement-gated-feature/AlertAgreementGatedFeature.tsx
index 8733369513..b9096844f2 100644
--- a/src/generic/agreement-gated-feature/AlertAgreementGatedFeature.tsx
+++ b/src/generic/agreement-gated-feature/AlertAgreementGatedFeature.tsx
@@ -10,7 +10,7 @@ import {
} from '@src/data/apiHooks';
import messages from './messages';
-const AlertAgreement = ({ agreementType }: { agreementType: string }) => {
+const AlertAgreement = ({ agreementType }: { agreementType: string; }) => {
const { data, isLoading, isError } = useUserAgreement(agreementType);
const mutation = useUserAgreementRecordUpdater(agreementType);
const showAlert = data && !isLoading && !isError;
@@ -29,8 +29,12 @@ const AlertAgreement = ({ agreementType }: { agreementType: string }) => {
variant="warning"
icon={Policy}
actions={[
- ,
- ,
+
+
+ ,
+
+
+ ,
]}
>
{name}
@@ -40,7 +44,7 @@ const AlertAgreement = ({ agreementType }: { agreementType: string }) => {
};
const AlertAgreementWrapper = (
- { agreementType }: { agreementType: string },
+ { agreementType }: { agreementType: string; },
) => {
const { data, isLoading, isError } = useUserAgreementRecord(agreementType);
const showAlert = !data?.isCurrent && !isLoading && !isError;
@@ -49,7 +53,7 @@ const AlertAgreementWrapper = (
};
export const AlertAgreementGatedFeature = (
- { gatingTypes }: { gatingTypes: AgreementGated[] },
+ { gatingTypes }: { gatingTypes: AgreementGated[]; },
) => {
const agreementTypes = getGatingAgreementTypes(gatingTypes);
return (
diff --git a/src/generic/alert-error/AlertError.test.tsx b/src/generic/alert-error/AlertError.test.tsx
index d162bf1bc9..28c0422175 100644
--- a/src/generic/alert-error/AlertError.test.tsx
+++ b/src/generic/alert-error/AlertError.test.tsx
@@ -4,7 +4,7 @@ import { IntlProvider } from '@edx/frontend-platform/i18n';
import AlertError from '.';
-const RootWrapper = ({ error }: { error: unknown }) => (
+const RootWrapper = ({ error }: { error: unknown; }) => (
diff --git a/src/generic/alert-message/index.tsx b/src/generic/alert-message/index.tsx
index 182b23efd1..fc3028d3e6 100644
--- a/src/generic/alert-message/index.tsx
+++ b/src/generic/alert-message/index.tsx
@@ -1,11 +1,12 @@
import React from 'react';
import { Alert } from '@openedx/paragon';
-interface Props
- extends Omit<
- React.ComponentPropsWithoutRef,
- 'title' | 'description'
- > {
+interface Props extends
+ Omit<
+ React.ComponentPropsWithoutRef,
+ 'title' | 'description'
+ >
+{
title?: string | React.ReactNode;
description?: string | React.ReactNode;
}
diff --git a/src/generic/block-type-utils/ComponentCountSnippet.test.tsx b/src/generic/block-type-utils/ComponentCountSnippet.test.tsx
index 958ce58379..b04d581688 100644
--- a/src/generic/block-type-utils/ComponentCountSnippet.test.tsx
+++ b/src/generic/block-type-utils/ComponentCountSnippet.test.tsx
@@ -1,5 +1,8 @@
import {
- initializeMocks, matchInnerText, render, screen,
+ initializeMocks,
+ matchInnerText,
+ render,
+ screen,
} from '@src/testUtils';
import { ComponentCountSnippet } from '.';
diff --git a/src/generic/clipboard/hooks/useClipboard.test.tsx b/src/generic/clipboard/hooks/useClipboard.test.tsx
index c24038493e..72390d341a 100644
--- a/src/generic/clipboard/hooks/useClipboard.test.tsx
+++ b/src/generic/clipboard/hooks/useClipboard.test.tsx
@@ -23,8 +23,12 @@ const xblockId = 'block-v1:edX+DemoX+Demo_Course+type@html+block@030e35c4756a4dd
let broadcastMockListener: (x: unknown) => void | undefined;
const clipboardBroadcastChannelMock = {
- postMessage: (message: unknown) => { broadcastMockListener(message); },
- addEventListener: (_eventName: string, handler: typeof broadcastMockListener) => { broadcastMockListener = handler; },
+ postMessage: (message: unknown) => {
+ broadcastMockListener(message);
+ },
+ addEventListener: (_eventName: string, handler: typeof broadcastMockListener) => {
+ broadcastMockListener = handler;
+ },
removeEventListener: jest.fn(),
};
_testingOverrideBroadcastChannel(clipboardBroadcastChannelMock as any);
diff --git a/src/generic/clipboard/hooks/useClipboard.ts b/src/generic/clipboard/hooks/useClipboard.ts
index bce2e02678..944ac24489 100644
--- a/src/generic/clipboard/hooks/useClipboard.ts
+++ b/src/generic/clipboard/hooks/useClipboard.ts
@@ -15,12 +15,14 @@ import messages from './messages';
const CLIPBOARD_QUERY_KEY = ['clipboard'];
// Global, shared broadcast channel for the clipboard. Disabled by default in test environment where it's not defined.
-let clipboardBroadcastChannel = (
- typeof BroadcastChannel !== 'undefined' ? new BroadcastChannel(STUDIO_CLIPBOARD_CHANNEL) : null
-);
+let clipboardBroadcastChannel = typeof BroadcastChannel !== 'undefined'
+ ? new BroadcastChannel(STUDIO_CLIPBOARD_CHANNEL)
+ : null;
/** To allow mocking the broadcast channel for testing */
// eslint-disable-next-line
-export const _testingOverrideBroadcastChannel = (x: BroadcastChannel) => { clipboardBroadcastChannel = x; };
+export const _testingOverrideBroadcastChannel = (x: BroadcastChannel) => {
+ clipboardBroadcastChannel = x;
+};
/**
* Custom React hook for managing clipboard functionality.
diff --git a/src/generic/clipboard/paste-component/components/PopoverContent.tsx b/src/generic/clipboard/paste-component/components/PopoverContent.tsx
index 70ac2808c9..60866f3eb1 100644
--- a/src/generic/clipboard/paste-component/components/PopoverContent.tsx
+++ b/src/generic/clipboard/paste-component/components/PopoverContent.tsx
@@ -7,10 +7,10 @@ import type { ClipboardStatus } from '../../../data/api';
import messages from '../messages';
interface PopoverContentProps {
- clipboardData: ClipboardStatus,
+ clipboardData: ClipboardStatus;
}
-const PopoverContent = ({ clipboardData } : PopoverContentProps) => {
+const PopoverContent = ({ clipboardData }: PopoverContentProps) => {
const intl = useIntl();
const { sourceEditUrl, content, sourceContextTitle } = clipboardData;
@@ -30,9 +30,7 @@ const PopoverContent = ({ clipboardData } : PopoverContentProps) => {
{content.displayName}
- {sourceEditUrl && (
-
- )}
+ {sourceEditUrl && }
diff --git a/src/generic/clipboard/paste-component/components/WhatsInClipboard.tsx b/src/generic/clipboard/paste-component/components/WhatsInClipboard.tsx
index 78fd3e17f8..c758c0b3e6 100644
--- a/src/generic/clipboard/paste-component/components/WhatsInClipboard.tsx
+++ b/src/generic/clipboard/paste-component/components/WhatsInClipboard.tsx
@@ -12,7 +12,9 @@ interface WhatsInClipboardProps {
}
const WhatsInClipboard = ({
- handlePopoverToggle, togglePopover, popoverElementRef,
+ handlePopoverToggle,
+ togglePopover,
+ popoverElementRef,
}: WhatsInClipboardProps) => {
const intl = useIntl();
const triggerElementRef = useRef(null);
diff --git a/src/generic/clipboard/paste-component/components/index.ts b/src/generic/clipboard/paste-component/components/index.ts
index 1336513b37..fb59acbecc 100644
--- a/src/generic/clipboard/paste-component/components/index.ts
+++ b/src/generic/clipboard/paste-component/components/index.ts
@@ -1,3 +1,3 @@
-export { default as WhatsInClipboard } from './WhatsInClipboard';
export { default as PasteButton } from './PasteButton';
export { default as PopoverContent } from './PopoverContent';
+export { default as WhatsInClipboard } from './WhatsInClipboard';
diff --git a/src/generic/clipboard/paste-component/index.tsx b/src/generic/clipboard/paste-component/index.tsx
index 47e177ce12..1d03d35fd4 100644
--- a/src/generic/clipboard/paste-component/index.tsx
+++ b/src/generic/clipboard/paste-component/index.tsx
@@ -12,7 +12,10 @@ interface PasteComponentProps {
}
const PasteComponent = ({
- onClick, clipboardData, text, className,
+ onClick,
+ clipboardData,
+ text,
+ className,
}: PasteComponentProps) => {
const [showPopover, togglePopover] = useState(false);
const popoverElementRef = useRef(null);
diff --git a/src/generic/clipboard/paste-component/messages.ts b/src/generic/clipboard/paste-component/messages.ts
index 77fbcba2b8..28138f19b0 100644
--- a/src/generic/clipboard/paste-component/messages.ts
+++ b/src/generic/clipboard/paste-component/messages.ts
@@ -8,7 +8,7 @@ const messages = defineMessages({
},
pasteButtonWhatsInClipboardText: {
id: 'course-authoring.generic.paste-component.paste-button.whats-in-clipboard.text',
- defaultMessage: "What's in my clipboard?",
+ defaultMessage: 'What\'s in my clipboard?',
description: 'The popover trigger button text of the info about copied content.',
},
});
diff --git a/src/generic/component-count/index.tsx b/src/generic/component-count/index.tsx
index 2856764072..9f8443bc06 100644
--- a/src/generic/component-count/index.tsx
+++ b/src/generic/component-count/index.tsx
@@ -7,12 +7,14 @@ type ComponentCountProps = {
};
const ComponentCount: React.FC = ({ count }) => (
- count !== undefined ? (
-
-
- {count}
-
- ) : null
+ count !== undefined ?
+ (
+
+
+ {count}
+
+ ) :
+ null
);
export default ComponentCount;
diff --git a/src/generic/configure-modal/AdvancedTab.test.jsx b/src/generic/configure-modal/AdvancedTab.test.jsx
index ed8150bc81..4cab894df2 100644
--- a/src/generic/configure-modal/AdvancedTab.test.jsx
+++ b/src/generic/configure-modal/AdvancedTab.test.jsx
@@ -31,13 +31,14 @@ const defaultProps = {
onlineProctoringRules: '',
};
-const renderComponent = (props = {}) => render(
-
- {}}>
-
-
- ,
-);
+const renderComponent = (props = {}) =>
+ render(
+
+ {}}>
+
+
+ ,
+ );
describe(' with enableTimedExams prop', () => {
beforeEach(() => {
@@ -672,7 +673,10 @@ describe(' with enableTimedExams prop', () => {
it('shows practice button and handles practice click', async () => {
const user = userEvent.setup();
renderComponent({
- useBtnGroup: true, enableProctoredExams: true, supportsOnboarding: false, setFieldValue: mockSetFieldValue,
+ useBtnGroup: true,
+ enableProctoredExams: true,
+ supportsOnboarding: false,
+ setFieldValue: mockSetFieldValue,
});
const practiceBtn = screen.getByRole('button', { name: 'Practice proctored' });
@@ -689,7 +693,10 @@ describe(' with enableTimedExams prop', () => {
it('handles onboarding button click', async () => {
const user = userEvent.setup();
renderComponent({
- useBtnGroup: true, enableProctoredExams: true, supportsOnboarding: true, setFieldValue: mockSetFieldValue,
+ useBtnGroup: true,
+ enableProctoredExams: true,
+ supportsOnboarding: true,
+ setFieldValue: mockSetFieldValue,
});
const onboardingBtn = screen.getByRole('button', { name: 'Onboarding' });
diff --git a/src/generic/configure-modal/AdvancedTab.tsx b/src/generic/configure-modal/AdvancedTab.tsx
index 21b451b71e..6dc45d5297 100644
--- a/src/generic/configure-modal/AdvancedTab.tsx
+++ b/src/generic/configure-modal/AdvancedTab.tsx
@@ -53,7 +53,7 @@ interface SelectorProps {
handleChange: (value: string) => void;
examTypeValue: string;
renderAlerts: () => React.ReactNode;
- enableTimedExams?: boolean,
+ enableTimedExams?: boolean;
enableProctoredExams?: boolean;
supportsOnboarding?: boolean;
}
@@ -89,34 +89,30 @@ const RadioForm = ({
<>
- }
+ description={ }
controlClassName="mw-1-25rem"
>
- {supportsOnboarding ? (
-
- }
- value="onboardingExam"
- controlClassName="mw-1-25rem"
- >
-
-
- ) : (
-
- }
- >
-
-
- )}
+ {supportsOnboarding ?
+ (
+ }
+ value="onboardingExam"
+ controlClassName="mw-1-25rem"
+ >
+
+
+ ) :
+ (
+ }
+ >
+
+
+ )}
>
)}
@@ -146,11 +142,11 @@ const ButtonGroupForm = ({
- )}
+ }
>
{enableProctoredExams && (
- <>
-
-
-
- )}
- >
- handleChange('proctoredExam')}
- >
-
-
-
- {supportsOnboarding ? (
-
-
-
- )}
- >
- handleChange('onboardingExam')}
- >
-
-
-
- ) : (
+ <>
-
+ overlay={
+
+
- )}
+ }
>
handleChange('practiceExam')}
+ variant={examTypeValue === 'proctoredExam' ? 'primary' : 'outline-primary'}
+ onClick={() => handleChange('proctoredExam')}
>
-
+
- )}
- >
+ {supportsOnboarding ?
+ (
+
+
+
+ }
+ >
+ handleChange('onboardingExam')}
+ >
+
+
+
+ ) :
+ (
+
+
+
+ }
+ >
+ handleChange('practiceExam')}
+ >
+
+
+
+ )}
+ >
)}
>
@@ -352,31 +350,31 @@ const AdvancedTab: React.FC = ({
<>
{(!hideTitle || !enableTimedExams)
&& (
- <>
-
- {!hideTitle && (
-
-
-
- )}
- {!enableTimedExams && (
-
-
-
- )}
- >
-
-
- )}
-
-
- >
+ <>
+
+ {!hideTitle && (
+
+
+
+ )}
+ {!enableTimedExams && (
+
+
+
+ }
+ >
+
+
+ )}
+
+
+ >
)}
{useBtnGroup
? (
@@ -431,26 +429,26 @@ const AdvancedTab: React.FC = ({
/>
- {onlineProctoringRules ? (
-
-
-
- ),
- }}
- />
- ) : (
-
- )}
+ {onlineProctoringRules ?
+ (
+
+
+
+ ),
+ }}
+ />
+ ) :
+ }
)}
diff --git a/src/generic/configure-modal/BasicTab.jsx b/src/generic/configure-modal/BasicTab.jsx
index 8b97bb6aed..74b3993c78 100644
--- a/src/generic/configure-modal/BasicTab.jsx
+++ b/src/generic/configure-modal/BasicTab.jsx
@@ -22,15 +22,15 @@ const BasicTab = ({
const onChangeGraderType = (e) => setFieldValue('graderType', e.target.value);
- const createOptions = () => courseGraders.map((option) => (
- {option}
- ));
+ const createOptions = () => courseGraders.map((option) => {option} );
return (
<>
{!isSelfPaced && (
<>
-
+
+
+
@@ -52,49 +52,51 @@ const BasicTab = ({
>
)}
- {
- isSubsection && (
-
-
-
-
-
-
-
- {intl.formatMessage(messages.notGradedTypeOption)}
-
- {createOptions()}
-
-
- {!isSelfPaced && (
-
-
- setFieldValue('dueDate', val)}
- data-testid="due-date-picker"
- />
- setFieldValue('dueDate', val)}
- />
-
-
- )}
-
- )
- }
+ {isSubsection && (
+
+
+
+
+
+
+
+
+
+
+
+ {intl.formatMessage(messages.notGradedTypeOption)}
+
+ {createOptions()}
+
+
+ {!isSelfPaced && (
+
+
+ setFieldValue('dueDate', val)}
+ data-testid="due-date-picker"
+ />
+ setFieldValue('dueDate', val)}
+ />
+
+
+ )}
+
+ )}
>
);
};
diff --git a/src/generic/configure-modal/ConfigureModal.test.tsx b/src/generic/configure-modal/ConfigureModal.test.tsx
index 6a4584a253..941f4350ad 100644
--- a/src/generic/configure-modal/ConfigureModal.test.tsx
+++ b/src/generic/configure-modal/ConfigureModal.test.tsx
@@ -33,19 +33,20 @@ jest.mock('react-router-dom', () => ({
const onCloseMock = jest.fn();
const onConfigureSubmitMock = jest.fn();
-const renderComponent = () => render(
-
-
-
- ,
- ,
-);
+const renderComponent = () =>
+ render(
+
+
+
+ ,
+ ,
+ );
describe(' for Section', () => {
beforeEach(() => {
@@ -83,20 +84,21 @@ describe(' for Section', () => {
});
});
-const renderSubsectionComponent = (props?: object) => render(
-
-
-
- ,
- ,
-);
+const renderSubsectionComponent = (props?: object) =>
+ render(
+
+
+
+ ,
+ ,
+ );
describe(' for Subsection', () => {
beforeEach(() => {
@@ -173,19 +175,20 @@ describe(' for Subsection', () => {
});
});
-const renderUnitComponent = (props?: object) => render(
-
-
-
- ,
- ,
-);
+const renderUnitComponent = (props?: object) =>
+ render(
+
+
+
+ ,
+ ,
+ );
describe(' for Unit', () => {
beforeEach(() => {
@@ -204,7 +207,10 @@ describe(' for Unit', () => {
it('renders unit ConfigureModal component correctly', async () => {
const user = userEvent.setup();
const {
- getByText, queryByText, getByRole, getByTestId,
+ getByText,
+ queryByText,
+ getByRole,
+ getByTestId,
} = renderUnitComponent();
expect(getByText(`${currentUnitMock.displayName} settings`)).toBeInTheDocument();
expect(getByText(messages.unitVisibility.defaultMessage)).toBeInTheDocument();
@@ -239,20 +245,21 @@ describe(' for Unit', () => {
});
});
-const renderXBlockComponent = (props?: object) => render(
-
-
-
- ,
- ,
-);
+const renderXBlockComponent = (props?: object) =>
+ render(
+
+
+
+ ,
+ ,
+ );
describe(' for XBlock', () => {
beforeEach(() => {
@@ -271,7 +278,10 @@ describe(' for XBlock', () => {
it('renders unit ConfigureModal component correctly', async () => {
const user = userEvent.setup();
const {
- getByText, queryByText, getByRole, getByTestId,
+ getByText,
+ queryByText,
+ getByRole,
+ getByTestId,
} = renderXBlockComponent();
expect(getByText(`Editing access for: ${currentUnitMock.displayName}`)).toBeInTheDocument();
expect(queryByText(messages.unitVisibility.defaultMessage)).not.toBeInTheDocument();
@@ -319,21 +329,22 @@ describe(' with enableTimedExams prop', () => {
store = initializeStore();
});
- const renderWithTimedExamsProps = (enableTimedExams = true) => render(
-
-
-
-
- ,
- ,
- );
+ const renderWithTimedExamsProps = (enableTimedExams = true) =>
+ render(
+
+
+
+
+ ,
+ ,
+ );
it('passes enableTimedExams=true to AdvancedTab', async () => {
const user = userEvent.setup();
diff --git a/src/generic/configure-modal/ConfigureModal.tsx b/src/generic/configure-modal/ConfigureModal.tsx
index 8134a4b27a..003374193b 100644
--- a/src/generic/configure-modal/ConfigureModal.tsx
+++ b/src/generic/configure-modal/ConfigureModal.tsx
@@ -20,15 +20,15 @@ import AdvancedTab from './AdvancedTab';
import { UnitTab } from './UnitTab';
interface Props {
- isOpen: boolean,
+ isOpen: boolean;
onClose: () => void;
- onConfigureSubmit: (args: object) => void,
- enableProctoredExams?: boolean,
- enableTimedExams?: boolean,
- currentItemData?: AccessManagedXBlockDataTypes,
- isXBlockComponent?: boolean,
- isSelfPaced?: boolean,
- isOverflowVisible?: boolean,
+ onConfigureSubmit: (args: object) => void;
+ enableProctoredExams?: boolean;
+ enableTimedExams?: boolean;
+ currentItemData?: AccessManagedXBlockDataTypes;
+ isXBlockComponent?: boolean;
+ isSelfPaced?: boolean;
+ isOverflowVisible?: boolean;
}
const ConfigureModal = ({
@@ -318,7 +318,9 @@ const ConfigureModal = ({
validateOnChange
>
{({
- values, handleSubmit, setFieldValue,
+ values,
+ handleSubmit,
+ setFieldValue,
}) => (
diff --git a/src/generic/configure-modal/PrereqSettings.jsx b/src/generic/configure-modal/PrereqSettings.jsx
index 98d129e4c4..d39720fa81 100644
--- a/src/generic/configure-modal/PrereqSettings.jsx
+++ b/src/generic/configure-modal/PrereqSettings.jsx
@@ -29,10 +29,14 @@ const PrereqSettings = ({
const prereqSelectionForm = () => (
<>
-
+
+
+
-
+
+
+
{intl.formatMessage(messages.prerequisiteSelectLabel)}
@@ -89,7 +93,9 @@ const PrereqSettings = ({
return (
<>
{prereqs.length > 0 && prereqSelectionForm()}
-
+
+
+
diff --git a/src/generic/configure-modal/UnitTab.tsx b/src/generic/configure-modal/UnitTab.tsx
index bec82080f7..852e9c9b99 100644
--- a/src/generic/configure-modal/UnitTab.tsx
+++ b/src/generic/configure-modal/UnitTab.tsx
@@ -1,6 +1,7 @@
import { Alert, Form } from '@openedx/paragon';
import {
- FormattedMessage, useIntl,
+ FormattedMessage,
+ useIntl,
} from '@edx/frontend-platform/i18n';
import { Field } from 'formik';
import classNames from 'classnames';
@@ -11,53 +12,55 @@ import messages from './messages';
export type UserPartitionInfo = {
selectablePartitions: {
groups: {
- deleted: boolean,
- id: number,
- name: string,
- selected: boolean,
- }[],
- id: number,
- name: string,
- scheme: string,
- }[],
- selectedGroupsLabel?: string,
- selectedPartitionIndex: number,
+ deleted: boolean;
+ id: number;
+ name: string;
+ selected: boolean;
+ }[];
+ id: number;
+ name: string;
+ scheme: string;
+ }[];
+ selectedGroupsLabel?: string;
+ selectedPartitionIndex: number;
};
export interface UnitTabProps {
- isXBlockComponent: boolean,
- category?: string,
+ isXBlockComponent: boolean;
+ category?: string;
values: {
- isVisibleToStaffOnly: boolean,
- discussionEnabled: boolean,
- selectedPartitionIndex: number,
- selectedGroups: string[],
- },
- setFieldValue: (key: string, value: any) => void,
- showWarning: boolean,
- userPartitionInfo?: UserPartitionInfo,
+ isVisibleToStaffOnly: boolean;
+ discussionEnabled: boolean;
+ selectedPartitionIndex: number;
+ selectedGroups: string[];
+ };
+ setFieldValue: (key: string, value: any) => void;
+ showWarning: boolean;
+ userPartitionInfo?: UserPartitionInfo;
}
export const DiscussionEditComponent = ({
discussionEnabled,
handleDiscussionChange,
}: {
- discussionEnabled: boolean,
- handleDiscussionChange: (e: any) => void,
+ discussionEnabled: boolean;
+ handleDiscussionChange: (e: any) => void;
}) => (
<>
-
+
+
+
>
);
export interface AccessEditComponentProps {
- selectedPartitionIndex?: number,
- setFieldValue: (key: string, value: any) => void,
- userPartitionInfo?: UserPartitionInfo,
- selectedGroups: string[],
+ selectedPartitionIndex?: number;
+ setFieldValue: (key: string, value: any) => void;
+ userPartitionInfo?: UserPartitionInfo;
+ selectedGroups: string[];
}
export const AccessEditComponent = ({
@@ -108,7 +111,9 @@ export const AccessEditComponent = ({
{selectedPartitionIndex !== undefined
&& selectedPartitionIndex >= 0 && userPartitionInfo?.selectablePartitions.length && (
-
+
+
+
{!isXBlockComponent && (
<>
-
+
+
+
-
+
{/* istanbul ignore next */ showWarning && (
@@ -216,7 +227,9 @@ export const UnitTab = ({
)}
{!isXBlockComponent && (
<>
-
+
+
+
- {
- isSubsection ? (
+ {isSubsection ?
+ (
<>
-
+
+
+
-
+
+
-
+
+
+
{showWarning && (
)}
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
@@ -120,12 +133,12 @@ const VisibilityTab = ({
>
- ) : (
+ ) :
+ (
- )
- }
+ )}
{showWarning && !isSubsection && (
diff --git a/src/generic/course-stepper/CourseStepper.test.tsx b/src/generic/course-stepper/CourseStepper.test.tsx
index 43f4f6a187..563c4dfcad 100644
--- a/src/generic/course-stepper/CourseStepper.test.tsx
+++ b/src/generic/course-stepper/CourseStepper.test.tsx
@@ -9,7 +9,8 @@ const stepsMock = [
},
{
title: 'Exporting',
- description: 'Creating the export data files (You can now leave this page safely, but avoid making drastic changes to content until this export is complete',
+ description:
+ 'Creating the export data files (You can now leave this page safely, but avoid making drastic changes to content until this export is complete',
},
{
title: 'Compressing',
@@ -21,9 +22,10 @@ const stepsMock = [
},
];
-const renderComponent = (props) => render(
- ,
-);
+const renderComponent = (props) =>
+ render(
+ ,
+ );
describe(' ', () => {
beforeEach(() => {
diff --git a/src/generic/course-stepper/index.tsx b/src/generic/course-stepper/index.tsx
index ef3cefe1e1..2450e0d557 100644
--- a/src/generic/course-stepper/index.tsx
+++ b/src/generic/course-stepper/index.tsx
@@ -64,46 +64,48 @@ const CourseStepper = ({
return (
- {steps.length ? steps.map(({ title, description, titleComponent }, index) => {
- const {
- stepIcon,
- isPercentShow,
- isErrorMessageShow,
- isActiveClass,
- isDoneClass,
- isErrorClass,
- } = getStepperSettings(index);
+ {steps.length ?
+ steps.map(({ title, description, titleComponent }, index) => {
+ const {
+ stepIcon,
+ isPercentShow,
+ isErrorMessageShow,
+ isActiveClass,
+ isDoneClass,
+ isErrorClass,
+ } = getStepperSettings(index);
- return (
-
-
-
-
-
-
{titleComponent ?? title}
- {isPercentShow && (
-
- {percent}%
+ return (
+
+
+
+
+
+
{titleComponent ?? title}
+ {isPercentShow && (
+
+ {percent}%
+
+ )}
+
+ {isErrorMessageShow ? errorMessage : description}
- )}
-
- {isErrorMessageShow ? errorMessage : description}
-
+
-
- );
- }) : null}
+ );
+ }) :
+ null}
);
};
diff --git a/src/generic/course-upload-image/data/api.js b/src/generic/course-upload-image/data/api.js
index 3d38c14467..5b1c1b1107 100644
--- a/src/generic/course-upload-image/data/api.js
+++ b/src/generic/course-upload-image/data/api.js
@@ -1,10 +1,11 @@
import { camelCaseObject, getConfig } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
-export const getUploadAssetsUrl = (courseId) => new URL(
- `/assets/${courseId}/`,
- getConfig().STUDIO_BASE_URL,
-);
+export const getUploadAssetsUrl = (courseId) =>
+ new URL(
+ `/assets/${courseId}/`,
+ getConfig().STUDIO_BASE_URL,
+ );
/**
* Upload assets.
diff --git a/src/generic/course-upload-image/index.jsx b/src/generic/course-upload-image/index.jsx
index d0cff97fb6..387b3ae1c2 100644
--- a/src/generic/course-upload-image/index.jsx
+++ b/src/generic/course-upload-image/index.jsx
@@ -56,53 +56,57 @@ const CourseUploadImage = ({
}
};
- const inputComponent = assetImagePath ? (
-
-
-
- ) : (
- <>
-
-
- {intl.formatMessage(messages.uploadImageDropzoneText, {
- identifierFieldText,
- })}
-
- >
- );
+ const inputComponent = assetImagePath ?
+ (
+
+
+
+ ) :
+ (
+ <>
+
+
+ {intl.formatMessage(messages.uploadImageDropzoneText, {
+ identifierFieldText,
+ })}
+
+ >
+ );
- const cardImageTextBody = assetImagePath ? (
-
-
- {intl.formatMessage(messages.uploadImageFilesAndUploads)}
-
- ),
- }}
- />
-
- ) : (
-
- {intl.formatMessage(messages.uploadImageEmpty)}
-
- );
+ const cardImageTextBody = assetImagePath ?
+ (
+
+
+ {intl.formatMessage(messages.uploadImageFilesAndUploads)}
+
+ ),
+ }}
+ />
+
+ ) :
+ (
+
+ {intl.formatMessage(messages.uploadImageEmpty)}
+
+ );
return (
@@ -123,12 +127,10 @@ const CourseUploadImage = ({
handleChangeImageAsset(e.target.value)}
- placeholder={
- customInputPlaceholder
+ placeholder={customInputPlaceholder
|| intl.formatMessage(messages.uploadImageInputPlaceholder, {
identifierFieldText,
- })
- }
+ })}
/>
diff --git a/src/generic/create-or-rerun-course/CreateOrRerunCourseForm.jsx b/src/generic/create-or-rerun-course/CreateOrRerunCourseForm.jsx
index 71f9f75773..f9d0f727e3 100644
--- a/src/generic/create-or-rerun-course/CreateOrRerunCourseForm.jsx
+++ b/src/generic/create-or-rerun-course/CreateOrRerunCourseForm.jsx
@@ -160,38 +160,40 @@ const CreateOrRerunCourseForm = ({
handleBlur(e);
};
- const renderOrgField = (field) => (allowToCreateNewOrg ? (
- setFieldValue(field.name, value)}
- noOptionsMessage={intl.formatMessage(messages.courseOrgNoOptions)}
- helpMessage=""
- errorMessage=""
- floatingLabel=""
- />
- ) : (
-
-
- {field.value || intl.formatMessage(messages.courseOrgNoOptions)}
-
-
- {field.options?.map((value) => (
- setFieldValue(field.name, value)}
- >
- {value}
-
- ))}
-
-
- ));
+ const renderOrgField = (field) => (allowToCreateNewOrg ?
+ (
+ setFieldValue(field.name, value)}
+ noOptionsMessage={intl.formatMessage(messages.courseOrgNoOptions)}
+ helpMessage=""
+ errorMessage=""
+ floatingLabel=""
+ />
+ ) :
+ (
+
+
+ {field.value || intl.formatMessage(messages.courseOrgNoOptions)}
+
+
+ {field.options?.map((value) => (
+ setFieldValue(field.name, value)}
+ >
+ {value}
+
+ ))}
+
+
+ ));
useEffect(() => {
// it needs to display the initial focus for the field depending on the current page
@@ -205,20 +207,22 @@ const CreateOrRerunCourseForm = ({
return (
- {(errors[TOTAL_LENGTH_KEY] || showErrorBanner) ? (
-
- ) : null}
+ {(errors[TOTAL_LENGTH_KEY] || showErrorBanner) ?
+ (
+
+ ) :
+ null}
{title}
@@ -230,18 +234,20 @@ const CreateOrRerunCourseForm = ({
key={field.label}
>
{field.label}
- {field.name !== 'org' ? (
-
- ) : renderOrgField(field)}
+ {field.name !== 'org' ?
+ (
+
+ ) :
+ renderOrgField(field)}
{field.helpText}
{hasErrorField(field.name) && (
diff --git a/src/generic/create-or-rerun-course/CreateOrRerunCourseForm.test.jsx b/src/generic/create-or-rerun-course/CreateOrRerunCourseForm.test.jsx
index 6d701fc5d0..982c5a4008 100644
--- a/src/generic/create-or-rerun-course/CreateOrRerunCourseForm.test.jsx
+++ b/src/generic/create-or-rerun-course/CreateOrRerunCourseForm.test.jsx
@@ -105,8 +105,11 @@ describe('
', () => {
render(
);
await mockStore();
expect(screen.getByText(messages.courseDisplayNameCreateHelpText.defaultMessage)).toBeInTheDocument();
- expect(screen.getByText('The name of the organization sponsoring the course.', { exact: false })).toBeInTheDocument();
- expect(screen.getByText('The unique number that identifies your course within your organization.', { exact: false })).toBeInTheDocument();
+ expect(screen.getByText('The name of the organization sponsoring the course.', { exact: false }))
+ .toBeInTheDocument();
+ expect(
+ screen.getByText('The unique number that identifies your course within your organization.', { exact: false }),
+ ).toBeInTheDocument();
expect(screen.getByText('The term in which your course will run.', { exact: false })).toBeInTheDocument();
expect(screen.getByRole('button', { name: messages.createButton.defaultMessage })).toBeInTheDocument();
});
@@ -117,9 +120,19 @@ describe('
', () => {
await mockStore();
expect(screen.getByText(messages.courseDisplayNameRerunHelpText.defaultMessage)).toBeInTheDocument();
- expect(screen.getByText('The name of the organization sponsoring the new course. (This name is often the same as the original organization name.)', { exact: false })).toBeInTheDocument();
+ expect(
+ screen.getByText(
+ 'The name of the organization sponsoring the new course. (This name is often the same as the original organization name.)',
+ { exact: false },
+ ),
+ ).toBeInTheDocument();
expect(screen.getByText(messages.courseNumberRerunHelpText.defaultMessage)).toBeInTheDocument();
- expect(screen.getByText('The term in which the new course will run. (This value is often different than the original course run value.)', { exact: false })).toBeInTheDocument();
+ expect(
+ screen.getByText(
+ 'The term in which the new course will run. (This value is often different than the original course run value.)',
+ { exact: false },
+ ),
+ ).toBeInTheDocument();
expect(screen.getByRole('button', { name: messages.rerunCreateButton.defaultMessage })).toBeInTheDocument();
});
@@ -208,7 +221,9 @@ describe('
', () => {
await mockStore();
const numberInput = screen.getByPlaceholderText(messages.courseNumberPlaceholder.defaultMessage);
- fireEvent.change(numberInput, { target: { value: 'long-name-which-is-longer-than-65-characters-to-check-for-errors' } });
+ fireEvent.change(numberInput, {
+ target: { value: 'long-name-which-is-longer-than-65-characters-to-check-for-errors' },
+ });
await waitFor(() => {
expect(screen.getByText(messages.totalLengthError.defaultMessage)).toBeInTheDocument();
diff --git a/src/generic/create-or-rerun-course/factories/mockApiResponses.jsx b/src/generic/create-or-rerun-course/factories/mockApiResponses.jsx
index db008301b0..ba4684965f 100644
--- a/src/generic/create-or-rerun-course/factories/mockApiResponses.jsx
+++ b/src/generic/create-or-rerun-course/factories/mockApiResponses.jsx
@@ -12,7 +12,8 @@ export const initialState = {
postErrors: {},
},
loadingStatuses: {
- organizationLoadingStatus: 'successful', courseRerunLoadingStatus: 'successful',
+ organizationLoadingStatus: 'successful',
+ courseRerunLoadingStatus: 'successful',
},
organizations: ['krisEdx', 'krisEd', 'DeveloperInc', 'importMit', 'testX', 'edX', 'developerInb'],
savingStatus: '',
diff --git a/src/generic/create-or-rerun-course/hooks.jsx b/src/generic/create-or-rerun-course/hooks.jsx
index 2f98d617e5..906fd485cc 100644
--- a/src/generic/create-or-rerun-course/hooks.jsx
+++ b/src/generic/create-or-rerun-course/hooks.jsx
@@ -69,7 +69,12 @@ const useCreateOrRerunCourse = (initialValues) => {
});
const {
- values, errors, touched, handleChange, handleBlur, setFieldValue,
+ values,
+ errors,
+ touched,
+ handleChange,
+ handleBlur,
+ setFieldValue,
} = useFormik({
initialValues,
enableReinitialize: true,
diff --git a/src/generic/data/api.mock.ts b/src/generic/data/api.mock.ts
index f162b7ae18..a3c8f20030 100644
--- a/src/generic/data/api.mock.ts
+++ b/src/generic/data/api.mock.ts
@@ -36,5 +36,6 @@ export async function mockClipboardHtml(blockType?: string): Promise
jest.spyOn(api, 'getClipboard').mockImplementation(() => mockClipboardHtml(blockType));
+mockClipboardHtml.applyMock = (blockType?: string) =>
+ jest.spyOn(api, 'getClipboard').mockImplementation(() => mockClipboardHtml(blockType));
mockClipboardHtml.applyMockOnce = () => jest.spyOn(api, 'getClipboard').mockImplementationOnce(mockClipboardHtml);
diff --git a/src/generic/data/api.ts b/src/generic/data/api.ts
index 8cd9d46685..6742b0482a 100644
--- a/src/generic/data/api.ts
+++ b/src/generic/data/api.ts
@@ -7,16 +7,18 @@ import { convertObjectToSnakeCase } from '@src/utils';
export const getApiBaseUrl = () => getConfig().STUDIO_BASE_URL;
export const getCreateOrRerunCourseUrl = () => new URL('course/', getApiBaseUrl()).href;
-export const getCourseRerunUrl = (courseId: string) => new URL(
- `/api/contentstore/v1/course_rerun/${courseId}`,
- getApiBaseUrl(),
-).href;
+export const getCourseRerunUrl = (courseId: string) =>
+ new URL(
+ `/api/contentstore/v1/course_rerun/${courseId}`,
+ getApiBaseUrl(),
+ ).href;
export const getOrganizationsUrl = () => new URL('organizations', getApiBaseUrl()).href;
export const getClipboardUrl = () => `${getApiBaseUrl()}/api/content-staging/v1/clipboard/`;
-export const getTagsCountApiUrl = (contentPattern: string) => new URL(
- `api/content_tagging/v1/object_tag_counts/${contentPattern}/?count_implicit`,
- getApiBaseUrl(),
-).href;
+export const getTagsCountApiUrl = (contentPattern: string) =>
+ new URL(
+ `api/content_tagging/v1/object_tag_counts/${contentPattern}/?count_implicit`,
+ getApiBaseUrl(),
+ ).href;
/**
* Get's organizations data. Returns list of organization names.
@@ -96,7 +98,7 @@ export async function updateClipboard(usageKey: string): Promise> {
if (!contentPattern) {
throw new Error('contentPattern is required');
diff --git a/src/generic/delete-modal/DeleteModal.test.jsx b/src/generic/delete-modal/DeleteModal.test.jsx
index 858cbf4a44..241cb1dc51 100644
--- a/src/generic/delete-modal/DeleteModal.test.jsx
+++ b/src/generic/delete-modal/DeleteModal.test.jsx
@@ -26,19 +26,20 @@ jest.mock('@edx/frontend-platform/i18n', () => ({
}),
}));
-const renderComponent = (props) => render(
-
-
-
- ,
- ,
-);
+const renderComponent = (props) =>
+ render(
+
+
+
+ ,
+ ,
+ );
describe(' ', () => {
beforeEach(() => {
diff --git a/src/generic/delete-modal/DeleteModal.tsx b/src/generic/delete-modal/DeleteModal.tsx
index c34425925a..1a0b041f4f 100644
--- a/src/generic/delete-modal/DeleteModal.tsx
+++ b/src/generic/delete-modal/DeleteModal.tsx
@@ -48,7 +48,7 @@ const DeleteModal = ({
onClose={close}
variant={variant}
icon={icon}
- footerNode={(
+ footerNode={
- )}
+ }
>
{modalDescription}
diff --git a/src/generic/divider/Divider.jsx b/src/generic/divider/Divider.jsx
index 6b75eff3df..03b05f0e6e 100644
--- a/src/generic/divider/Divider.jsx
+++ b/src/generic/divider/Divider.jsx
@@ -1,9 +1,7 @@
import PropTypes from 'prop-types';
import classNames from 'classnames';
-const Divider = ({ className, ...props }) => (
-
-);
+const Divider = ({ className, ...props }) =>
;
Divider.propTypes = {
className: PropTypes.string,
diff --git a/src/generic/help-sidebar/HelpSidebar.test.tsx b/src/generic/help-sidebar/HelpSidebar.test.tsx
index 64eb6d9345..3e24108909 100644
--- a/src/generic/help-sidebar/HelpSidebar.test.tsx
+++ b/src/generic/help-sidebar/HelpSidebar.test.tsx
@@ -13,12 +13,13 @@ jest.mock('@src/authz/data/apiHooks', () => ({
const mockPathname = '/foo-bar';
-const renderHelpSidebar = (props) => render(
-
- Test children
- ,
- { path: mockPathname },
-);
+const renderHelpSidebar = (props) =>
+ render(
+
+ Test children
+ ,
+ { path: mockPathname },
+ );
const props = {
courseId: 'course123',
diff --git a/src/generic/help-sidebar/index.ts b/src/generic/help-sidebar/index.ts
index 3b5b9d2463..f90bc71e88 100644
--- a/src/generic/help-sidebar/index.ts
+++ b/src/generic/help-sidebar/index.ts
@@ -1,4 +1,4 @@
+export { otherLinkURLParams } from './constants';
export { default as HelpSidebar } from './HelpSidebar';
export { default as HelpSidebarLink } from './HelpSidebarLink';
-export { otherLinkURLParams } from './constants';
export { default as messages } from './messages';
diff --git a/src/generic/hooks/context/hooks.test.tsx b/src/generic/hooks/context/hooks.test.tsx
index cbe43443c3..ff862a181e 100644
--- a/src/generic/hooks/context/hooks.test.tsx
+++ b/src/generic/hooks/context/hooks.test.tsx
@@ -6,11 +6,13 @@ import { IframeProvider } from './iFrameContext';
describe('useIframe hook', () => {
it('throws an error when used outside of IframeProvider', () => {
- expect(() => { renderHook(() => useIframe()); }).toThrow('useIframe must be used within an IframeProvider');
+ expect(() => {
+ renderHook(() => useIframe());
+ }).toThrow('useIframe must be used within an IframeProvider');
});
it('returns context value when used inside IframeProvider', () => {
- const wrapper = ({ children }: { children: ReactNode }) => (
+ const wrapper = ({ children }: { children: ReactNode; }) => (
{children}
diff --git a/src/generic/hooks/context/iFrameContext.tsx b/src/generic/hooks/context/iFrameContext.tsx
index 57448ee484..b5342bd7d3 100644
--- a/src/generic/hooks/context/iFrameContext.tsx
+++ b/src/generic/hooks/context/iFrameContext.tsx
@@ -1,5 +1,10 @@
import React, {
- createContext, MutableRefObject, useRef, useCallback, useMemo, ReactNode,
+ createContext,
+ MutableRefObject,
+ useRef,
+ useCallback,
+ useMemo,
+ ReactNode,
} from 'react';
import { logError } from '@edx/frontend-platform/logging';
@@ -11,7 +16,7 @@ export interface IframeContextType {
export const IframeContext = createContext(undefined);
-export const IframeProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
+export const IframeProvider: React.FC<{ children: ReactNode; }> = ({ children }) => {
const iframeRef = useRef(null);
const setIframeRef = useCallback((ref: MutableRefObject) => {
iframeRef.current = ref.current;
diff --git a/src/generic/hooks/tests/hooks.test.tsx b/src/generic/hooks/tests/hooks.test.tsx
index f44cf72ba2..6fc6eee3d8 100644
--- a/src/generic/hooks/tests/hooks.test.tsx
+++ b/src/generic/hooks/tests/hooks.test.tsx
@@ -43,7 +43,9 @@ describe('useIframeBehavior', () => {
it('scrolls to previous position on video fullscreen exit', () => {
const mockWindowTopOffset = 100;
- jest.spyOn(iframeBehaviorState, 'windowTopOffset').mockImplementation(() => [mockWindowTopOffset, setWindowTopOffset]);
+ jest.spyOn(iframeBehaviorState, 'windowTopOffset').mockImplementation(
+ () => [mockWindowTopOffset, setWindowTopOffset],
+ );
renderHook(() => useIframeBehavior({ id, iframeUrl, iframeRef }));
const message = {
@@ -81,9 +83,14 @@ describe('useIframeBehavior', () => {
it('handles xblock-event message correctly', () => {
const onBlockNotification = jest.fn();
- renderHook(() => useIframeBehavior({
- id, iframeUrl, iframeRef, onBlockNotification,
- }));
+ renderHook(() =>
+ useIframeBehavior({
+ id,
+ iframeUrl,
+ iframeRef,
+ onBlockNotification,
+ })
+ );
const messageEvent = new MessageEvent('message', {
data: {
@@ -154,7 +161,7 @@ describe('useIframeBehavior', () => {
});
expect(window.scrollY).toBe(
100 // Component offset
- + document.getElementsByName('xblock-iframe')[0].offsetTop, // iframe offset
+ + document.getElementsByName('xblock-iframe')[0].offsetTop, // iframe offset
);
});
diff --git a/src/generic/hooks/tests/useEventListener.test.tsx b/src/generic/hooks/tests/useEventListener.test.tsx
index a678cdb0ce..817675f7c3 100644
--- a/src/generic/hooks/tests/useEventListener.test.tsx
+++ b/src/generic/hooks/tests/useEventListener.test.tsx
@@ -35,7 +35,7 @@ describe('useEventListener', () => {
const handler1 = jest.fn();
const handler2 = jest.fn();
const { rerender } = renderHook(({ handler }: {
- handler: (event: Event) => void
+ handler: (event: Event) => void;
}) => useEventListener('click', handler), {
initialProps: { handler: handler1 },
});
@@ -49,7 +49,7 @@ describe('useEventListener', () => {
it('should update event listener when type changes', () => {
const handler = jest.fn();
const { rerender } = renderHook(({ type }: {
- type: keyof WindowEventMap
+ type: keyof WindowEventMap;
}) => useEventListener(type, handler), {
initialProps: { type: 'click' },
});
diff --git a/src/generic/inplace-text-editor/InplaceTextEditor.test.tsx b/src/generic/inplace-text-editor/InplaceTextEditor.test.tsx
index 9b7a55c281..f0d0b1e9bf 100644
--- a/src/generic/inplace-text-editor/InplaceTextEditor.test.tsx
+++ b/src/generic/inplace-text-editor/InplaceTextEditor.test.tsx
@@ -10,7 +10,7 @@ import { InplaceTextEditor } from '.';
const mockOnSave = jest.fn();
-const RootWrapper = ({ children }: { children: React.ReactNode }) => (
+const RootWrapper = ({ children }: { children: React.ReactNode; }) => (
{children}
@@ -102,7 +102,9 @@ describe(' ', () => {
const newText = screen.getByText('New text');
expect(newText).toBeInTheDocument();
- await act(async () => { rejecter(new Error('error')); });
+ await act(async () => {
+ rejecter(new Error('error'));
+ });
// Remove pending new text on error
expect(newText).not.toBeInTheDocument();
diff --git a/src/generic/internet-connection-alert/index.jsx b/src/generic/internet-connection-alert/index.jsx
index a4a8e271cd..511d12e6bb 100644
--- a/src/generic/internet-connection-alert/index.jsx
+++ b/src/generic/internet-connection-alert/index.jsx
@@ -7,7 +7,10 @@ import AlertMessage from '../alert-message';
import messages from './messages';
const InternetConnectionAlert = ({
- isFailed, isQueryPending, onQueryProcessing, onInternetConnectionFailed,
+ isFailed,
+ isQueryPending,
+ onQueryProcessing,
+ onInternetConnectionFailed,
}) => {
const intl = useIntl();
const [showAlert, setShowAlert] = useState(false);
diff --git a/src/generic/key-utils.test.ts b/src/generic/key-utils.test.ts
index 07ee9d6cd1..f9e12072a2 100644
--- a/src/generic/key-utils.test.ts
+++ b/src/generic/key-utils.test.ts
@@ -11,20 +11,22 @@ import {
describe('component utils', () => {
describe('getBlockType', () => {
- for (const [input, expected] of [
- ['lb:org:lib:html:id', 'html'],
- ['lb:OpenCraftX:ALPHA:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd', 'html'],
- ['lb:Axim:beta:problem:571fe018-f3ce-45c9-8f53-5dafcb422fdd', 'problem'],
- ['lct:org:lib:unit:my-unit-9284e2', 'unit'],
- ['lct:org:lib:section:my-section-9284e2', 'section'],
- ['lct:org:lib:subsection:my-section-9284e2', 'subsection'],
- ['block-v1:org+type@html+block@1', 'html'],
- ['block-v1:OpenCraftX+type@html+block@1571fe018-f3ce-45c9-8f53-5dafcb422fdd', 'html'],
- ['block-v1:Axim+type@problem+block@571fe018-f3ce-45c9-8f53-5dafcb422fdd', 'problem'],
- ['block-v1:org+type@unit+block@1', 'unit'],
- ['block-v1:org+type@section+block@1', 'section'],
- ['block-v1:org+type@subsection+block@1', 'subsection'],
- ]) {
+ for (
+ const [input, expected] of [
+ ['lb:org:lib:html:id', 'html'],
+ ['lb:OpenCraftX:ALPHA:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd', 'html'],
+ ['lb:Axim:beta:problem:571fe018-f3ce-45c9-8f53-5dafcb422fdd', 'problem'],
+ ['lct:org:lib:unit:my-unit-9284e2', 'unit'],
+ ['lct:org:lib:section:my-section-9284e2', 'section'],
+ ['lct:org:lib:subsection:my-section-9284e2', 'subsection'],
+ ['block-v1:org+type@html+block@1', 'html'],
+ ['block-v1:OpenCraftX+type@html+block@1571fe018-f3ce-45c9-8f53-5dafcb422fdd', 'html'],
+ ['block-v1:Axim+type@problem+block@571fe018-f3ce-45c9-8f53-5dafcb422fdd', 'problem'],
+ ['block-v1:org+type@unit+block@1', 'unit'],
+ ['block-v1:org+type@section+block@1', 'section'],
+ ['block-v1:org+type@subsection+block@1', 'subsection'],
+ ]
+ ) {
it(`returns '${expected}' for usage key '${input}'`, () => {
expect(getBlockType(input)).toStrictEqual(expected);
});
@@ -39,15 +41,17 @@ describe('component utils', () => {
});
describe('getLibraryId', () => {
- for (const [input, expected] of [
- ['lb:org:lib:html:id', 'lib:org:lib'],
- ['lb:OpenCraftX:ALPHA:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd', 'lib:OpenCraftX:ALPHA'],
- ['lb:Axim:beta:problem:571fe018-f3ce-45c9-8f53-5dafcb422fdd', 'lib:Axim:beta'],
- ['lib-collection:org:lib:coll', 'lib:org:lib'],
- ['lib-collection:OpenCraftX:ALPHA:coll', 'lib:OpenCraftX:ALPHA'],
- ['lct:org:lib:unit:my-unit-9284e2', 'lib:org:lib'],
- ['lct:OpenCraftX:ALPHA:my-unit-a3223f', 'lib:OpenCraftX:ALPHA'],
- ]) {
+ for (
+ const [input, expected] of [
+ ['lb:org:lib:html:id', 'lib:org:lib'],
+ ['lb:OpenCraftX:ALPHA:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd', 'lib:OpenCraftX:ALPHA'],
+ ['lb:Axim:beta:problem:571fe018-f3ce-45c9-8f53-5dafcb422fdd', 'lib:Axim:beta'],
+ ['lib-collection:org:lib:coll', 'lib:org:lib'],
+ ['lib-collection:OpenCraftX:ALPHA:coll', 'lib:OpenCraftX:ALPHA'],
+ ['lct:org:lib:unit:my-unit-9284e2', 'lib:org:lib'],
+ ['lct:OpenCraftX:ALPHA:my-unit-a3223f', 'lib:OpenCraftX:ALPHA'],
+ ]
+ ) {
it(`returns '${expected}' for usage key '${input}'`, () => {
expect(getLibraryId(input)).toStrictEqual(expected);
});
@@ -61,16 +65,18 @@ describe('component utils', () => {
});
describe('isLibraryKey', () => {
- for (const [input, expected] of [
- ['lib:org:lib', true],
- ['lib:OpenCraftX:ALPHA', true],
- ['lb:org:lib:html:id', false],
- ['lb:OpenCraftX:ALPHA:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd', false],
- ['library-v1:AximX+L1', false],
- ['course-v1:AximX+TS100+23', false],
- ['', false],
- [undefined, false],
- ] as const) {
+ for (
+ const [input, expected] of [
+ ['lib:org:lib', true],
+ ['lib:OpenCraftX:ALPHA', true],
+ ['lb:org:lib:html:id', false],
+ ['lb:OpenCraftX:ALPHA:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd', false],
+ ['library-v1:AximX+L1', false],
+ ['course-v1:AximX+TS100+23', false],
+ ['', false],
+ [undefined, false],
+ ] as const
+ ) {
it(`returns '${expected}' for learning context key '${input}'`, () => {
expect(isLibraryKey(input)).toStrictEqual(expected);
});
@@ -78,23 +84,27 @@ describe('component utils', () => {
});
describe('parseLibraryKey', () => {
- for (const [input, expected] of [
- ['lib:org:lib', { org: 'org', lib: 'lib' }],
- ['lib:OpenCraftX:ALPHA', { org: 'OpenCraftX', lib: 'ALPHA' }],
- ] as const) {
+ for (
+ const [input, expected] of [
+ ['lib:org:lib', { org: 'org', lib: 'lib' }],
+ ['lib:OpenCraftX:ALPHA', { org: 'OpenCraftX', lib: 'ALPHA' }],
+ ] as const
+ ) {
it(`returns '${JSON.stringify(expected)}' for learning context key '${input}'`, () => {
expect(parseLibraryKey(input)).toStrictEqual(expected);
});
}
- for (const input of [
- '',
- undefined,
- null,
- 'not a key',
- 'lb:foo',
- 'lb:org:lib:html:id',
- ]) {
+ for (
+ const input of [
+ '',
+ undefined,
+ null,
+ 'not a key',
+ 'lb:foo',
+ 'lb:org:lib:html:id',
+ ]
+ ) {
it(`throws an exception for library key '${input}'`, () => {
expect(() => parseLibraryKey(input as any)).toThrow(`Invalid libraryKey: ${input}`);
});
@@ -102,16 +112,18 @@ describe('component utils', () => {
});
describe('isLibraryV1Key', () => {
- for (const [input, expected] of [
- ['library-v1:AximX+L1', true],
- ['lib:org:lib', false],
- ['lib:OpenCraftX:ALPHA', false],
- ['lb:org:lib:html:id', false],
- ['lb:OpenCraftX:ALPHA:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd', false],
- ['course-v1:AximX+TS100+23', false],
- ['', false],
- [undefined, false],
- ] as const) {
+ for (
+ const [input, expected] of [
+ ['library-v1:AximX+L1', true],
+ ['lib:org:lib', false],
+ ['lib:OpenCraftX:ALPHA', false],
+ ['lb:org:lib:html:id', false],
+ ['lb:OpenCraftX:ALPHA:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd', false],
+ ['course-v1:AximX+TS100+23', false],
+ ['', false],
+ [undefined, false],
+ ] as const
+ ) {
it(`returns '${expected}' for learning context key '${input}'`, () => {
expect(isLibraryV1Key(input)).toStrictEqual(expected);
});
@@ -119,16 +131,18 @@ describe('component utils', () => {
});
describe('buildCollectionUsageKey', () => {
- for (const [libraryKey, collectionId, expected] of [
- ['lib:org:lib', 'coll', 'lib-collection:org:lib:coll'],
- ['lib:OpenCraftX:ALPHA', 'coll', 'lib-collection:OpenCraftX:ALPHA:coll'],
- ['lb:org:lib:html:id', 'coll', ''],
- ['lb:OpenCraftX:ALPHA:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd', 'coll', ''],
- ['library-v1:AximX+L1', 'coll', ''],
- ['course-v1:AximX+TS100+23', 'coll', ''],
- ['', 'coll', ''],
- ['', 'coll', ''],
- ] as const) {
+ for (
+ const [libraryKey, collectionId, expected] of [
+ ['lib:org:lib', 'coll', 'lib-collection:org:lib:coll'],
+ ['lib:OpenCraftX:ALPHA', 'coll', 'lib-collection:OpenCraftX:ALPHA:coll'],
+ ['lb:org:lib:html:id', 'coll', ''],
+ ['lb:OpenCraftX:ALPHA:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd', 'coll', ''],
+ ['library-v1:AximX+L1', 'coll', ''],
+ ['course-v1:AximX+TS100+23', 'coll', ''],
+ ['', 'coll', ''],
+ ['', 'coll', ''],
+ ] as const
+ ) {
it(`returns '${expected}' for learning context key '${libraryKey}' and collection Id '${collectionId}'`, () => {
expect(buildCollectionUsageKey(libraryKey, collectionId)).toStrictEqual(expected);
});
@@ -136,14 +150,16 @@ describe('component utils', () => {
});
describe('normalizeContainerType', () => {
- for (const [containerType, expected] of [
- [ContainerType.Vertical, ContainerType.Unit],
- [ContainerType.Sequential, ContainerType.Subsection],
- [ContainerType.Chapter, ContainerType.Section],
- [ContainerType.Unit, ContainerType.Unit],
- [ContainerType.Section, ContainerType.Section],
- [ContainerType.Subsection, ContainerType.Subsection],
- ] as const) {
+ for (
+ const [containerType, expected] of [
+ [ContainerType.Vertical, ContainerType.Unit],
+ [ContainerType.Sequential, ContainerType.Subsection],
+ [ContainerType.Chapter, ContainerType.Section],
+ [ContainerType.Unit, ContainerType.Unit],
+ [ContainerType.Section, ContainerType.Section],
+ [ContainerType.Subsection, ContainerType.Subsection],
+ ] as const
+ ) {
it(`returns '${expected}' for '${containerType}'`, () => {
expect(normalizeContainerType(containerType)).toStrictEqual(expected);
});
diff --git a/src/generic/key-utils.ts b/src/generic/key-utils.ts
index c787686120..beb8b283f7 100644
--- a/src/generic/key-utils.ts
+++ b/src/generic/key-utils.ts
@@ -31,7 +31,7 @@ export function getBlockType(
/**
* Parses a library key and returns the organization and library name as an object.
*/
-export function parseLibraryKey(libraryKey: string): { org: string, lib: string } {
+export function parseLibraryKey(libraryKey: string): { org: string; lib: string; } {
const splitKey = libraryKey?.split(':') || [];
if (splitKey.length !== 3) {
throw new Error(`Invalid libraryKey: ${libraryKey}`);
@@ -94,7 +94,7 @@ export function isBlockV1Key(usageKey: string | undefined | null): boolean {
/**
* Build a collection usage key from library V2 context key and collection Id.
* This Collection Usage Key is only used on tagging.
-*/
+ */
export const buildCollectionUsageKey = (learningContextKey: string, collectionId: string) => {
if (!isLibraryKey(learningContextKey)) {
return '';
diff --git a/src/generic/library-reference-card/LibraryReferenceCard.test.tsx b/src/generic/library-reference-card/LibraryReferenceCard.test.tsx
index 3774c3b1fd..02f015f9aa 100644
--- a/src/generic/library-reference-card/LibraryReferenceCard.test.tsx
+++ b/src/generic/library-reference-card/LibraryReferenceCard.test.tsx
@@ -96,9 +96,11 @@ describe('LibraryReferenceCard', () => {
goToParent={mockOpenContainerInfoSidebar}
/>,
);
- expect(await screen.findByText(
- `The link between ${itemData.displayName} and the library version has been broken. To edit or make changes, unlink component.`,
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ `The link between ${itemData.displayName} and the library version has been broken. To edit or make changes, unlink component.`,
+ ),
+ ).toBeInTheDocument();
await user.click(await screen.findByRole('button', { name: 'Unlink from library' }));
expect(mockUseCourseAuthoringContext().openUnlinkModal).toHaveBeenCalledWith({
@@ -126,9 +128,11 @@ describe('LibraryReferenceCard', () => {
goToParent={mockOpenContainerInfoSidebar}
/>,
);
- expect(await screen.findByText(
- `${itemData.displayName} has available updates`,
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ `${itemData.displayName} has available updates`,
+ ),
+ ).toBeInTheDocument();
await user.click(await screen.findByRole('button', { name: 'Review Updates' }));
expect(mockOpenSyncModal).toHaveBeenCalled();
@@ -152,9 +156,11 @@ describe('LibraryReferenceCard', () => {
goToParent={mockOpenContainerInfoSidebar}
/>,
);
- expect(await screen.findByText(
- `${itemData.displayName} has been modified in this course.`,
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ `${itemData.displayName} has been modified in this course.`,
+ ),
+ ).toBeInTheDocument();
});
it('renders the LibraryReferenceCard with top level error message', async () => {
@@ -177,9 +183,11 @@ describe('LibraryReferenceCard', () => {
goToParent={mockOpenContainerInfoSidebar}
/>,
);
- expect(await screen.findByText(
- `${itemData.displayName} was reused as part of a section which has a broken link. To receive library updates to this component, unlink the broken link.`,
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ `${itemData.displayName} was reused as part of a section which has a broken link. To receive library updates to this component, unlink the broken link.`,
+ ),
+ ).toBeInTheDocument();
await user.click(await screen.findByRole('button', { name: 'Unlink section' }));
// should call unlink with parent section data
@@ -218,9 +226,11 @@ describe('LibraryReferenceCard', () => {
goToParent={mockOpenContainerInfoSidebar}
/>,
);
- expect(await screen.findByText(
- `${itemData.displayName} was reused as part of a section which has updates available.`,
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ `${itemData.displayName} was reused as part of a section which has updates available.`,
+ ),
+ ).toBeInTheDocument();
await user.click(await screen.findByRole('button', { name: 'Review Updates' }));
expect(mockOpenSyncModal).toHaveBeenCalledWith(parentData);
@@ -245,9 +255,11 @@ describe('LibraryReferenceCard', () => {
goToParent={mockOpenContainerInfoSidebar}
/>,
);
- expect(await screen.findByText(
- `${itemData.displayName} was reused as part of a section.`,
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ `${itemData.displayName} was reused as part of a section.`,
+ ),
+ ).toBeInTheDocument();
await user.click(await screen.findByRole('button', { name: 'View section' }));
expect(mockOpenContainerInfoSidebar).toHaveBeenCalledWith(
diff --git a/src/generic/library-reference-card/LibraryReferenceCard.tsx b/src/generic/library-reference-card/LibraryReferenceCard.tsx
index c42a142ce8..a8378fb444 100644
--- a/src/generic/library-reference-card/LibraryReferenceCard.tsx
+++ b/src/generic/library-reference-card/LibraryReferenceCard.tsx
@@ -1,6 +1,9 @@
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import {
- Button, Card, Icon, Stack,
+ Button,
+ Card,
+ Icon,
+ Stack,
} from '@openedx/paragon';
import { Cached, LinkOff, Newsstand } from '@openedx/paragon/icons';
import { useCourseItemData } from '@src/course-outline/data/apiHooks';
@@ -179,9 +182,7 @@ const TopLevelTextAndButton = ({
}
if ((upstreamInfo?.downstreamCustomized?.length || 0) > 0) {
- return (
-
- );
+ return ;
}
return null;
@@ -190,7 +191,7 @@ const TopLevelTextAndButton = ({
interface Props {
itemId?: string;
sectionId?: string;
- postChange: (accept: boolean) => void,
+ postChange: (accept: boolean) => void;
goToParent: (containerId: string, subsectionId?: string, sectionId?: string) => void;
}
@@ -233,7 +234,9 @@ export const LibraryReferenceCard = ({
-
+
+
+
(Promise | void)) => (
-
-);
+const RootWrapper = (onClick?: () => Promise | void) => ;
describe(' ', () => {
it('renders the title and doesnt handle the spinner initially', () => {
- const { container, getByText } = render(RootWrapper(() => { }));
+ const { container, getByText } = render(RootWrapper(() => {}));
expect(getByText(buttonTitle)).toBeInTheDocument();
expect(container.getElementsByClassName('icon-spin').length).toBe(0);
@@ -31,9 +29,10 @@ describe(' ', () => {
it('renders the spinner correctly', async () => {
let resolver: () => void;
- const longFunction = () => new Promise((resolve) => {
- resolver = resolve;
- });
+ const longFunction = () =>
+ new Promise((resolve) => {
+ resolver = resolve;
+ });
const { container, getByRole, getByText } = render(RootWrapper(longFunction));
const buttonElement = getByRole('button');
fireEvent.click(buttonElement);
@@ -43,7 +42,9 @@ describe(' ', () => {
// expect(buttonElement).toBeDisabled();
expect(buttonElement).toHaveAttribute('aria-disabled', 'true');
- await act(async () => { resolver(); });
+ await act(async () => {
+ resolver();
+ });
expect(buttonElement).not.toHaveAttribute('aria-disabled', 'true');
expect(container.getElementsByClassName('icon-spin').length).toBe(0);
@@ -51,9 +52,10 @@ describe(' ', () => {
it('renders the spinner correctly even with error', async () => {
let rejecter: (err: Error) => void;
- const longFunction = () => new Promise((_resolve, reject) => {
- rejecter = reject;
- });
+ const longFunction = () =>
+ new Promise((_resolve, reject) => {
+ rejecter = reject;
+ });
const { container, getByRole, getByText } = render(RootWrapper(longFunction));
const buttonElement = getByRole('button');
@@ -65,7 +67,9 @@ describe(' ', () => {
// expect(buttonElement).toBeDisabled();
expect(buttonElement).toHaveAttribute('aria-disabled', 'true');
- await act(async () => { rejecter(new Error('error')); });
+ await act(async () => {
+ rejecter(new Error('error'));
+ });
// StatefulButton only sets aria-disabled (not disabled) when the state is pending
// expect(buttonElement).toBeEnabled();
@@ -87,7 +91,9 @@ describe(' ', () => {
fireEvent.click(buttonElement);
// Second click should not call the function, because the button is disabled
expect(longFunction).toHaveBeenCalledTimes(1);
- await act(async () => { resolver(); });
+ await act(async () => {
+ resolver();
+ });
// After the promise is resolved, the button should be enabled
fireEvent.click(buttonElement);
expect(longFunction).toHaveBeenCalledTimes(2);
diff --git a/src/generic/loading-button/index.tsx b/src/generic/loading-button/index.tsx
index e3ffaf76b8..c63a79f98f 100644
--- a/src/generic/loading-button/index.tsx
+++ b/src/generic/loading-button/index.tsx
@@ -10,15 +10,15 @@ import {
interface LoadingButtonProps extends React.ButtonHTMLAttributes {
label: string;
- onClick?: (e: any) => (Promise | void);
+ onClick?: (e: any) => Promise | void;
size?: string;
variant?: string;
isLoading?: boolean;
}
/**
- * A button that shows a loading spinner when clicked, if the onClick function returns a Promise.
- */
+ * A button that shows a loading spinner when clicked, if the onClick function returns a Promise.
+ */
const LoadingButton: React.FC = ({
label,
onClick,
diff --git a/src/generic/modal-dropzone/ModalDropzone.jsx b/src/generic/modal-dropzone/ModalDropzone.jsx
index eba0c0e78b..5107e6f357 100644
--- a/src/generic/modal-dropzone/ModalDropzone.jsx
+++ b/src/generic/modal-dropzone/ModalDropzone.jsx
@@ -43,7 +43,12 @@ const ModalDropzone = ({
handleCancel,
handleSelectFile,
} = useModalDropzone({
- onChange, onCancel, onClose, fileTypes, onSavingStatus, onSelectFile,
+ onChange,
+ onCancel,
+ onClose,
+ fileTypes,
+ onSavingStatus,
+ onSelectFile,
});
const invalidSizeMore = invalidFileSizeMore || intl.formatMessage(
@@ -51,30 +56,32 @@ const ModalDropzone = ({
{ maxSize: maxSize / (1000 * 1000) },
);
- const inputComponent = previewUrl ? (
-
- {previewComponent || (
-
+ {previewComponent || (
+
+ )}
+
+ ) :
+ (
+ <>
+
- )}
-
- ) : (
- <>
-
- {imageDropzoneText || intl.formatMessage(messages.uploadImageDropzoneText)}
- {imageHelpText}
- >
- );
+ {imageDropzoneText || intl.formatMessage(messages.uploadImageDropzoneText)}
+ {imageHelpText}
+ >
+ );
return (
- {uploadProgress > 0 ? (
-
- ) : (
-
- )}
+ {uploadProgress > 0 ?
+ :
+ (
+
+ )}
diff --git a/src/generic/modal-dropzone/data/api.js b/src/generic/modal-dropzone/data/api.js
index abcfaa760c..97af3d92f1 100644
--- a/src/generic/modal-dropzone/data/api.js
+++ b/src/generic/modal-dropzone/data/api.js
@@ -1,10 +1,11 @@
import { camelCaseObject, getConfig } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
-export const getUploadAssetsUrl = (courseId) => new URL(
- `/assets/${courseId}/`,
- getConfig().STUDIO_BASE_URL,
-);
+export const getUploadAssetsUrl = (courseId) =>
+ new URL(
+ `/assets/${courseId}/`,
+ getConfig().STUDIO_BASE_URL,
+ );
/**
* Upload assets.
diff --git a/src/generic/modal-dropzone/useModalDropzone.jsx b/src/generic/modal-dropzone/useModalDropzone.jsx
index 2eb4625613..19f2d7ae41 100644
--- a/src/generic/modal-dropzone/useModalDropzone.jsx
+++ b/src/generic/modal-dropzone/useModalDropzone.jsx
@@ -7,7 +7,12 @@ import { uploadAssets } from './data/api';
import messages from './messages';
const useModalDropzone = ({
- onChange, onCancel, onClose, fileTypes, onSavingStatus, onSelectFile,
+ onChange,
+ onCancel,
+ onClose,
+ fileTypes,
+ onSavingStatus,
+ onSelectFile,
}) => {
const { courseId } = useParams();
const intl = useIntl();
@@ -47,16 +52,17 @@ const useModalDropzone = ({
* "* /*": [".pdf", ".docx"]
* }
*/
- const constructAcceptObject = (types) => types
- .reduce((acc, type) => {
- // eslint-disable-next-line no-nested-ternary
- const mimeType = type === 'pdf' ? 'application/pdf' : VALID_IMAGE_TYPES.includes(type) ? 'image/*' : '*/*';
- if (!acc[mimeType]) {
- acc[mimeType] = [];
- }
- acc[mimeType].push(`.${type}`);
- return acc;
- }, {});
+ const constructAcceptObject = (types) =>
+ types
+ .reduce((acc, type) => {
+ // eslint-disable-next-line no-nested-ternary
+ const mimeType = type === 'pdf' ? 'application/pdf' : VALID_IMAGE_TYPES.includes(type) ? 'image/*' : '*/*';
+ if (!acc[mimeType]) {
+ acc[mimeType] = [];
+ }
+ acc[mimeType].push(`.${type}`);
+ return acc;
+ }, {});
const accept = useMemo(() => constructAcceptObject(fileTypes), [fileTypes]);
diff --git a/src/generic/modal-notification/index.jsx b/src/generic/modal-notification/index.jsx
index ae1dc2ba87..bf85f112e3 100644
--- a/src/generic/modal-notification/index.jsx
+++ b/src/generic/modal-notification/index.jsx
@@ -3,19 +3,27 @@ import PropTypes from 'prop-types';
import { ActionRow, AlertModal, Button } from '@openedx/paragon';
const ModalNotification = ({
- isOpen, title, message, handleCancel, handleAction, cancelButtonText, actionButtonText, variant, icon,
+ isOpen,
+ title,
+ message,
+ handleCancel,
+ handleAction,
+ cancelButtonText,
+ actionButtonText,
+ variant,
+ icon,
}) => (
{cancelButtonText}
{actionButtonText}
- )}
+ }
>
{message}
diff --git a/src/generic/model-store/hooks.js b/src/generic/model-store/hooks.js
index 8ee8b41e3e..e1c78314a2 100644
--- a/src/generic/model-store/hooks.js
+++ b/src/generic/model-store/hooks.js
@@ -9,9 +9,10 @@ export function useModel(type, id) {
export function useModels(type, ids) {
return useSelector(
- state => ids.map(
- id => (state.models[type] !== undefined ? state.models[type][id] : undefined),
- ),
+ state =>
+ ids.map(
+ id => (state.models[type] !== undefined ? state.models[type][id] : undefined),
+ ),
shallowEqual,
);
}
diff --git a/src/generic/model-store/index.ts b/src/generic/model-store/index.ts
index 954f5f3448..ba83377eca 100644
--- a/src/generic/model-store/index.ts
+++ b/src/generic/model-store/index.ts
@@ -10,7 +10,4 @@ export {
removeModels,
} from './slice';
-export {
- useModel,
- useModels,
-} from './hooks';
+export { useModel, useModels } from './hooks';
diff --git a/src/generic/processing-notification/index.tsx b/src/generic/processing-notification/index.tsx
index 9fa6aac247..5c71dd8918 100644
--- a/src/generic/processing-notification/index.tsx
+++ b/src/generic/processing-notification/index.tsx
@@ -1,5 +1,6 @@
import {
- Icon, Toast,
+ Icon,
+ Toast,
} from '@openedx/paragon';
import { Settings as IconSettings } from '@openedx/paragon/icons';
import classNames from 'classnames';
@@ -31,7 +32,7 @@ const ProcessingNotification = ({
onClose={close || (() => {})}
delay={delay}
>
- { /* @ts-ignore - Toast has a poor definition of children */ }
+ {/* @ts-ignore - Toast has a poor definition of children */}
{title}
diff --git a/src/generic/promptIfDirty/usePromptIfDirty.ts b/src/generic/promptIfDirty/usePromptIfDirty.ts
index c14be27632..01c64b6b01 100644
--- a/src/generic/promptIfDirty/usePromptIfDirty.ts
+++ b/src/generic/promptIfDirty/usePromptIfDirty.ts
@@ -1,6 +1,6 @@
import { useEffect } from 'react';
-const usePromptIfDirty = (checkIfDirty : () => boolean) => {
+const usePromptIfDirty = (checkIfDirty: () => boolean) => {
useEffect(() => {
// eslint-disable-next-line consistent-return
const handleBeforeUnload = (event) => {
diff --git a/src/generic/resizable/Resizable.tsx b/src/generic/resizable/Resizable.tsx
index cf96080375..adfe1606bb 100644
--- a/src/generic/resizable/Resizable.tsx
+++ b/src/generic/resizable/Resizable.tsx
@@ -1,6 +1,9 @@
import { useWindowSize } from '@openedx/paragon';
import React, {
- useRef, useState, useCallback, useMemo,
+ useRef,
+ useState,
+ useCallback,
+ useMemo,
} from 'react';
const MIN_WIDTH = 440; // px
@@ -8,7 +11,7 @@ const MIN_WIDTH = 440; // px
interface ResizableBoxProps {
children: React.ReactNode;
minWidth?: number;
- maxWidth?: number
+ maxWidth?: number;
}
/**
diff --git a/src/generic/saving-error-alert/SavingErrorAlert.jsx b/src/generic/saving-error-alert/SavingErrorAlert.jsx
index 8f5a78ef89..64f3358c7a 100644
--- a/src/generic/saving-error-alert/SavingErrorAlert.jsx
+++ b/src/generic/saving-error-alert/SavingErrorAlert.jsx
@@ -42,9 +42,7 @@ const SavingErrorAlert = ({
data-testid="saving-error-alert"
icon={WarningIcon}
title={intl.formatMessage(messages.warningTitle)}
- description={
- errorMessage || intl.formatMessage(messages.warningDescription)
- }
+ description={errorMessage || intl.formatMessage(messages.warningDescription)}
aria-hidden="true"
aria-labelledby={intl.formatMessage(
messages.warningTitleAriaLabelledBy,
diff --git a/src/generic/sidebar/BlockCardButton.tsx b/src/generic/sidebar/BlockCardButton.tsx
index bab788f83d..960e109d26 100644
--- a/src/generic/sidebar/BlockCardButton.tsx
+++ b/src/generic/sidebar/BlockCardButton.tsx
@@ -1,6 +1,10 @@
import React from 'react';
import {
- Button, Chip, Collapsible, Icon, Stack,
+ Button,
+ Chip,
+ Collapsible,
+ Icon,
+ Stack,
} from '@openedx/paragon';
import { getItemIcon } from '../block-type-utils';
diff --git a/src/generic/sidebar/InfoSidebarMenu.tsx b/src/generic/sidebar/InfoSidebarMenu.tsx
index 5275bfd0c6..7e678ccf8f 100644
--- a/src/generic/sidebar/InfoSidebarMenu.tsx
+++ b/src/generic/sidebar/InfoSidebarMenu.tsx
@@ -1,6 +1,9 @@
import { useIntl } from '@edx/frontend-platform/i18n';
import {
- Dropdown, Icon, IconButton, Stack,
+ Dropdown,
+ Icon,
+ IconButton,
+ Stack,
} from '@openedx/paragon';
import {
ArrowDownward,
@@ -55,7 +58,7 @@ export const InfoSidebarMenu = (props: InfoSidebarMenuProps) => {
return null;
}
- const { upstreamInfo } = item;
+ const { upstreamInfo } = item;
return (
diff --git a/src/generic/sidebar/Sidebar.test.tsx b/src/generic/sidebar/Sidebar.test.tsx
index 91554f9ddf..f742c8a810 100644
--- a/src/generic/sidebar/Sidebar.test.tsx
+++ b/src/generic/sidebar/Sidebar.test.tsx
@@ -1,6 +1,9 @@
import { useState } from 'react';
import {
- initializeMocks, render, screen, within,
+ initializeMocks,
+ render,
+ screen,
+ within,
} from '@src/testUtils';
import { userEvent } from '@testing-library/user-event';
diff --git a/src/generic/sidebar/Sidebar.tsx b/src/generic/sidebar/Sidebar.tsx
index 02de034933..82112b91cb 100644
--- a/src/generic/sidebar/Sidebar.tsx
+++ b/src/generic/sidebar/Sidebar.tsx
@@ -75,7 +75,7 @@ interface SidebarProps {
* isOpen={isOpen}
* toggle={toggle}
* />
- *);
+ * );
* ```
*/
// eslint-disable-next-line react/function-component-definition
@@ -97,40 +97,40 @@ export function Sidebar({
return (
- {(isOpen && !!currentPageKey) ? (
-
-
-
-
- {intl.formatMessage(title)}
-
-
-
- {Object.entries(pages).map(([key, page]) => (
- setCurrentPageKey(key)}
- disabled={page.disabled}
- >
-
-
- {intl.formatMessage(page.title)}
-
-
- ))}
-
-
-
-
-
- ) : (
-
- )}
+ {(isOpen && !!currentPageKey) ?
+ (
+
+
+
+
+ {intl.formatMessage(title)}
+
+
+
+ {Object.entries(pages).map(([key, page]) => (
+ setCurrentPageKey(key)}
+ disabled={page.disabled}
+ >
+
+
+ {intl.formatMessage(page.title)}
+
+
+ ))}
+
+
+
+
+
+ ) :
+
}
({
);
}
- return (
-
- );
+ return ;
})}
diff --git a/src/generic/sidebar/SidebarContent.tsx b/src/generic/sidebar/SidebarContent.tsx
index 312752f3c0..9a9b1cb01c 100644
--- a/src/generic/sidebar/SidebarContent.tsx
+++ b/src/generic/sidebar/SidebarContent.tsx
@@ -27,7 +27,7 @@ interface SidebarContentProps {
*
* ```
*/
-export const SidebarContent = ({ children } : SidebarContentProps) => {
+export const SidebarContent = ({ children }: SidebarContentProps) => {
// Flatten the array and filter out empty children to correctly render
// the hr element between each child.
const nonEmptyChildren = Array.isArray(children)
diff --git a/src/generic/sidebar/SidebarSection.tsx b/src/generic/sidebar/SidebarSection.tsx
index 1e7c1833b1..8413794af5 100644
--- a/src/generic/sidebar/SidebarSection.tsx
+++ b/src/generic/sidebar/SidebarSection.tsx
@@ -42,15 +42,18 @@ export interface SidebarSectionProps {
* ```
*/
export const SidebarSection = ({
- title, icon, actions, children,
+ title,
+ icon,
+ actions,
+ children,
}: SidebarSectionProps) => (
{icon && }
{title && (
-
- {title}
-
+
+ {title}
+
)}
{actions && (
diff --git a/src/generic/sidebar/SidebarTitle.tsx b/src/generic/sidebar/SidebarTitle.tsx
index 25629785f7..16c0ca4233 100644
--- a/src/generic/sidebar/SidebarTitle.tsx
+++ b/src/generic/sidebar/SidebarTitle.tsx
@@ -31,7 +31,7 @@ export const SidebarTitle = ({
const intl = useIntl();
return (
<>
-
+
{onBackBtnClick && (
{title}
- {menuProps && (
-
- )}
+ {menuProps && }
>
diff --git a/src/generic/sidebar/index.tsx b/src/generic/sidebar/index.tsx
index 2fccb9515f..edae53bc71 100644
--- a/src/generic/sidebar/index.tsx
+++ b/src/generic/sidebar/index.tsx
@@ -1,5 +1,5 @@
-export { SidebarContent } from './SidebarContent';
-export { SidebarTitle } from './SidebarTitle';
-export { SidebarSection } from './SidebarSection';
export { Sidebar } from './Sidebar';
export type { SidebarPage } from './Sidebar';
+export { SidebarContent } from './SidebarContent';
+export { SidebarSection } from './SidebarSection';
+export { SidebarTitle } from './SidebarTitle';
diff --git a/src/generic/sidebar/messages.ts b/src/generic/sidebar/messages.ts
index 9846fdf874..d947d35ce9 100644
--- a/src/generic/sidebar/messages.ts
+++ b/src/generic/sidebar/messages.ts
@@ -65,7 +65,7 @@ const messages = defineMessages({
id: 'course-authoring.sidebar.item-menu.move',
defaultMessage: 'Move',
description: 'Text for the Move button in the sidebar menu',
- },
+ },
});
export default messages;
diff --git a/src/generic/sub-header/SubHeader.tsx b/src/generic/sub-header/SubHeader.tsx
index d51d02fd30..95b1801fcc 100644
--- a/src/generic/sub-header/SubHeader.tsx
+++ b/src/generic/sub-header/SubHeader.tsx
@@ -7,7 +7,7 @@ interface SubHeaderProps {
breadcrumbs?: ReactElement | ReactElement[] | string | null;
contentTitle?: string;
description?: string;
- instruction?: ReactElement | string,
+ instruction?: ReactElement | string;
headerActions?: ReactElement | ReactElement[] | null;
titleActions?: ReactElement | ReactElement[] | null;
hideBorder?: boolean;
@@ -27,9 +27,7 @@ const SubHeader = ({
withSubHeaderContent = true,
}: SubHeaderProps) => (
- {breadcrumbs && (
-
{breadcrumbs}
- )}
+ {breadcrumbs &&
{breadcrumbs}
}
{subtitle}
@@ -52,9 +50,7 @@ const SubHeader = ({
{description}
)}
- {instruction && (
-
{instruction}
- )}
+ {instruction &&
{instruction}
}
);
diff --git a/src/generic/tag-count/index.tsx b/src/generic/tag-count/index.tsx
index 9d31639186..a3eff300d2 100644
--- a/src/generic/tag-count/index.tsx
+++ b/src/generic/tag-count/index.tsx
@@ -18,15 +18,13 @@ const TagCount: React.FC
= ({ count, onClick, size }: TagCountPro
);
return (
-
- { onClick ? (
-
- {renderContent()}
-
- )
+
+ {onClick ?
+ (
+
+ {renderContent()}
+
+ )
: renderContent()}
);
diff --git a/src/generic/toast-context/index.test.tsx b/src/generic/toast-context/index.test.tsx
index 58ebbb424c..e0f4402e7e 100644
--- a/src/generic/toast-context/index.test.tsx
+++ b/src/generic/toast-context/index.test.tsx
@@ -30,7 +30,7 @@ const TestComponentToClose = () => {
return
Content
;
};
-const TestComponentWithDelay = ({ delay }: { delay: number }) => {
+const TestComponentWithDelay = ({ delay }: { delay: number; }) => {
const { showToast } = React.useContext(ToastContext);
React.useEffect(() => {
@@ -68,25 +68,41 @@ describe('
', () => {
});
it('should show toast', async () => {
- render(
);
+ render(
+
+
+ ,
+ );
expect(await screen.findByText('This is the Toast!')).toBeInTheDocument();
});
it('should close toast after 5000ms', async () => {
- render(
);
+ render(
+
+
+ ,
+ );
expect(await screen.findByText('This is the Toast!')).toBeInTheDocument();
jest.advanceTimersByTime(6000);
expect(screen.queryByText('This is the Toast!')).not.toBeInTheDocument();
});
it('should close toast', async () => {
- render(
);
+ render(
+
+
+ ,
+ );
expect(await screen.findByText('Content')).toBeInTheDocument();
expect(screen.queryByText('This is the Toast!')).not.toBeInTheDocument();
});
it('should keep toast visible past default delay when custom delay is provided', async () => {
- render(
);
+ render(
+
+
+ ,
+ );
expect(await screen.findByText('This is the Toast!')).toBeInTheDocument();
// Still visible after the default 5000ms delay
jest.advanceTimersByTime(6000);
diff --git a/src/generic/toast-context/index.tsx b/src/generic/toast-context/index.tsx
index b855d2b967..6e2009c7b0 100644
--- a/src/generic/toast-context/index.tsx
+++ b/src/generic/toast-context/index.tsx
@@ -99,7 +99,7 @@ export const ToastProvider = (props: ToastProviderProps) => {
return (
{props.children}
- { toastMessage && (
+ {toastMessage && (
;
- onBlockNotification?: (event: { eventType: string; [key: string]: any }) => void;
+ onBlockNotification?: (event: { eventType: string; [key: string]: any; }) => void;
}
export interface UseIFrameBehaviorReturnTypes {
diff --git a/src/generic/unlink-modal/UnlinkModal.test.tsx b/src/generic/unlink-modal/UnlinkModal.test.tsx
index c070df511c..68bc43b000 100644
--- a/src/generic/unlink-modal/UnlinkModal.test.tsx
+++ b/src/generic/unlink-modal/UnlinkModal.test.tsx
@@ -12,28 +12,30 @@ import messages from './messages';
const onUnlinkSubmitMock = jest.fn();
const closeMock = jest.fn();
-const renderforContainer = () => defaultRender(
-
-
- ,
-);
+const renderforContainer = () =>
+ defaultRender(
+
+
+ ,
+ );
-const renderforComponent = () => defaultRender(
-
-
- ,
-);
+const renderforComponent = () =>
+ defaultRender(
+
+
+ ,
+ );
describe(' ', () => {
it('render UnlinkModal component correctly for containers', () => {
diff --git a/src/generic/unlink-modal/UnlinkModal.tsx b/src/generic/unlink-modal/UnlinkModal.tsx
index ca66e738f4..acbaf58781 100644
--- a/src/generic/unlink-modal/UnlinkModal.tsx
+++ b/src/generic/unlink-modal/UnlinkModal.tsx
@@ -23,7 +23,7 @@ type UnlinkModalPropsComponent = {
type UnlinkModalProps = {
isOpen: boolean;
close: () => void;
- onUnlinkSubmit: () => void | Promise,
+ onUnlinkSubmit: () => void | Promise;
} & (UnlinkModalPropsContainer | UnlinkModalPropsComponent);
export const UnlinkModal = ({
@@ -52,10 +52,12 @@ export const UnlinkModal = ({
categoryName,
b: BoldText,
});
- const modalDescriptionChildren = !isComponent ? intl.formatMessage(messages.descriptionChildren, {
- categoryName,
- childrenCategoryName,
- }) : null;
+ const modalDescriptionChildren = !isComponent ?
+ intl.formatMessage(messages.descriptionChildren, {
+ categoryName,
+ childrenCategoryName,
+ }) :
+ null;
return (
{
@@ -86,7 +88,7 @@ export const UnlinkModal = ({
label={intl.formatMessage(messages.unlinkButton)}
/>
- )}
+ }
>
{modalDescription}
diff --git a/src/generic/unlink-modal/data/apiHooks.ts b/src/generic/unlink-modal/data/apiHooks.ts
index 5718811d48..70bd4b0f74 100644
--- a/src/generic/unlink-modal/data/apiHooks.ts
+++ b/src/generic/unlink-modal/data/apiHooks.ts
@@ -9,9 +9,11 @@ import { unlinkDownstream } from './api';
export const useUnlinkDownstream = () => {
const queryClient = useQueryClient();
return useMutation({
- mutationFn: (variables: {
- downstreamBlockId: string;
- } & ParentIds) => unlinkDownstream(variables.downstreamBlockId),
+ mutationFn: (
+ variables: {
+ downstreamBlockId: string;
+ } & ParentIds,
+ ) => unlinkDownstream(variables.downstreamBlockId),
onSuccess: (_, variables) => {
const courseKey = getCourseKey(variables.downstreamBlockId);
queryClient.invalidateQueries({
diff --git a/src/generic/unlink-modal/index.tsx b/src/generic/unlink-modal/index.tsx
index 60faf24042..11c2d020b3 100644
--- a/src/generic/unlink-modal/index.tsx
+++ b/src/generic/unlink-modal/index.tsx
@@ -1,2 +1,2 @@
-export { UnlinkModal } from './UnlinkModal';
export { useUnlinkDownstream } from './data/apiHooks';
+export { UnlinkModal } from './UnlinkModal';
diff --git a/src/generic/upstream-info-icon/UpstreamInfoIcon.test.tsx b/src/generic/upstream-info-icon/UpstreamInfoIcon.test.tsx
index 06b4fa61db..126db5e311 100644
--- a/src/generic/upstream-info-icon/UpstreamInfoIcon.test.tsx
+++ b/src/generic/upstream-info-icon/UpstreamInfoIcon.test.tsx
@@ -1,5 +1,9 @@
import {
- render, screen, fireEvent, waitFor, initializeMocks,
+ render,
+ screen,
+ fireEvent,
+ waitFor,
+ initializeMocks,
} from '@src/testUtils';
import { UpstreamInfoIcon, UpstreamInfoIconProps } from '.';
diff --git a/src/generic/upstream-info-icon/index.tsx b/src/generic/upstream-info-icon/index.tsx
index 80173e5bdc..beb3b13319 100644
--- a/src/generic/upstream-info-icon/index.tsx
+++ b/src/generic/upstream-info-icon/index.tsx
@@ -1,10 +1,16 @@
/* eslint-disable react/prop-types */
import { useIntl } from '@edx/frontend-platform/i18n';
import {
- Button, Icon, OverlayTrigger, Tooltip,
+ Button,
+ Icon,
+ OverlayTrigger,
+ Tooltip,
} from '@openedx/paragon';
import {
- CallSplit, LinkOff, Newsstand, Sync,
+ CallSplit,
+ LinkOff,
+ Newsstand,
+ Sync,
} from '@openedx/paragon/icons';
import { BoldText } from '@src/utils';
@@ -83,16 +89,16 @@ const UpstreamInfoIconContent = ({
{tooltipMessage}
- )}
+ }
>
void }> = ({
+export const UpstreamInfoIcon: React.FC void; }> = ({
upstreamInfo,
size,
openSyncModal,
@@ -132,7 +138,5 @@ export const UpstreamInfoIcon: React.FC
- );
+ return ;
};
diff --git a/src/grading-settings/GradingSettings.jsx b/src/grading-settings/GradingSettings.jsx
index a1efc34a4f..5fc02a8588 100644
--- a/src/grading-settings/GradingSettings.jsx
+++ b/src/grading-settings/GradingSettings.jsx
@@ -1,6 +1,9 @@
import { useIntl } from '@edx/frontend-platform/i18n';
import {
- Button, Container, Layout, StatefulButton,
+ Button,
+ Container,
+ Layout,
+ StatefulButton,
} from '@openedx/paragon';
import { Add as IconAdd, CheckCircle, Warning } from '@openedx/paragon/icons';
import { useEffect, useState } from 'react';
diff --git a/src/grading-settings/GradingSettings.test.jsx b/src/grading-settings/GradingSettings.test.jsx
index 76a667de4c..c9ebc64ad0 100644
--- a/src/grading-settings/GradingSettings.test.jsx
+++ b/src/grading-settings/GradingSettings.test.jsx
@@ -1,5 +1,9 @@
import {
- act, fireEvent, render, screen, initializeMocks,
+ act,
+ fireEvent,
+ render,
+ screen,
+ initializeMocks,
} from '@src/testUtils';
import { CourseAuthoringProvider } from '@src/CourseAuthoringContext';
import { getCourseSettingsApiUrl } from '@src/data/api';
diff --git a/src/grading-settings/assignment-section/assignments/AssignmentItem.jsx b/src/grading-settings/assignment-section/assignments/AssignmentItem.jsx
index 68438c3adf..209877f62d 100644
--- a/src/grading-settings/assignment-section/assignments/AssignmentItem.jsx
+++ b/src/grading-settings/assignment-section/assignments/AssignmentItem.jsx
@@ -22,9 +22,10 @@ const AssignmentItem = ({
trailingElement,
}) => (
-
{title}
-
{intl.formatMessage(messages.assignmentTypeNameTitle)}
diff --git a/src/grading-settings/assignment-section/index.jsx b/src/grading-settings/assignment-section/index.jsx
index 20b3c65c62..487e8fc37a 100644
--- a/src/grading-settings/assignment-section/index.jsx
+++ b/src/grading-settings/assignment-section/index.jsx
@@ -26,7 +26,10 @@ const AssignmentSection = ({
const intl = useIntl();
const [errorList, setErrorList] = useState({});
const {
- type, weight, minCount, dropCount,
+ type,
+ weight,
+ minCount,
+ dropCount,
} = ASSIGNMENT_TYPES;
const isFieldsWithoutErrors = Object.values(errorList).every(field => field !== true);
@@ -74,7 +77,7 @@ const AssignmentSection = ({
{graders?.map((gradeField) => {
const courseAssignmentUsage = courseAssignmentLists[gradeField.type];
const showDefinedCaseAlert = gradeField.minCount !== courseAssignmentUsage?.length
- && Boolean(courseAssignmentUsage?.length);
+ && Boolean(courseAssignmentUsage?.length);
const showNotDefinedCaseAlert = !courseAssignmentUsage?.length && Boolean(gradeField.type);
return (
@@ -143,18 +146,16 @@ const AssignmentSection = ({
variant="warning"
icon={Warning}
title={intl.formatMessage(messages.assignmentAlertWarningUsageTitle, { type: gradeField.type })}
- description={(
+ description={
<>
{courseAssignmentUsage.length} Final assignment(s) found:
- {courseAssignmentUsage.map(assignmentItem => (
- {assignmentItem}
- ))}
+ {courseAssignmentUsage.map(assignmentItem => {assignmentItem} )}
>
- )}
+ }
aria-hidden="true"
/>
)}
@@ -164,11 +165,11 @@ const AssignmentSection = ({
variant="warning"
icon={Warning}
title={intl.formatMessage(messages.assignmentAlertWarningTitle, { type: gradeField.type })}
- description={(
+ description={
{intl.formatMessage(messages.assignmentAlertWarningDescription)}
- )}
+ }
aria-hidden="true"
/>
)}
diff --git a/src/grading-settings/assignment-section/messages.ts b/src/grading-settings/assignment-section/messages.ts
index 29d75447d7..7acf644a33 100644
--- a/src/grading-settings/assignment-section/messages.ts
+++ b/src/grading-settings/assignment-section/messages.ts
@@ -19,7 +19,7 @@ const messages = defineMessages({
},
assignmentTypeNameErrorMessage3: {
id: 'course-authoring.grading-settings.assignment.type-name.error.message-3',
- defaultMessage: "There's already another assignment type with this name.",
+ defaultMessage: 'There\'s already another assignment type with this name.',
},
abbreviationTitle: {
id: 'course-authoring.grading-settings.assignment.abbreviation.title',
@@ -27,7 +27,7 @@ const messages = defineMessages({
},
abbreviationDescription: {
id: 'course-authoring.grading-settings.assignment.abbreviation.description',
- defaultMessage: "This short name for the assignment type (for example, HW or Midterm) appears next to assignments on a learner's Progress page.",
+ defaultMessage: 'This short name for the assignment type (for example, HW or Midterm) appears next to assignments on a learner\'s Progress page.',
},
weightOfTotalGradeTitle: {
id: 'course-authoring.grading-settings.assignment.weight-of-total-grade.title',
diff --git a/src/grading-settings/data/api.js b/src/grading-settings/data/api.js
index d21b128f64..e83ca2c647 100644
--- a/src/grading-settings/data/api.js
+++ b/src/grading-settings/data/api.js
@@ -4,7 +4,8 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { deepConvertingKeysToCamelCase, deepConvertingKeysToSnakeCase } from '../../utils';
const getApiBaseUrl = () => getConfig().STUDIO_BASE_URL;
-export const getGradingSettingsApiUrl = (courseId) => `${getApiBaseUrl()}/api/contentstore/v1/course_grading/${courseId}`;
+export const getGradingSettingsApiUrl = (courseId) =>
+ `${getApiBaseUrl()}/api/contentstore/v1/course_grading/${courseId}`;
/**
* Get's grading setting for a course.
diff --git a/src/grading-settings/deadline-section/DeadlineSection.test.jsx b/src/grading-settings/deadline-section/DeadlineSection.test.jsx
index cb1986a8a4..19a90da532 100644
--- a/src/grading-settings/deadline-section/DeadlineSection.test.jsx
+++ b/src/grading-settings/deadline-section/DeadlineSection.test.jsx
@@ -13,7 +13,8 @@ const setGradingData = (fn) => {
};
const gracePeriodDefaultTime = {
- hours: 12, minutes: 12,
+ hours: 12,
+ minutes: 12,
};
const RootWrapper = (props = {}) => (
@@ -36,10 +37,12 @@ describe(' ', () => {
});
});
it('checking deadline input value', async () => {
- const { getByTestId } = render( );
+ const { getByTestId } = render(
+ ,
+ );
await waitFor(() => {
const inputElement = getByTestId('deadline-period-input');
expect(inputElement.value).toBe('12:12');
@@ -49,20 +52,24 @@ describe(' ', () => {
});
});
it('checking deadline input value if grace Period has no hours', async () => {
- const { getByTestId } = render( );
+ const { getByTestId } = render(
+ ,
+ );
await waitFor(() => {
const inputElement = getByTestId('deadline-period-input');
expect(inputElement.value).toBe('00:13');
});
});
it('checking deadline input value if grace Period has no minutes', async () => {
- const { getByTestId } = render( );
+ const { getByTestId } = render(
+ ,
+ );
await waitFor(() => {
const inputElement = getByTestId('deadline-period-input');
expect(inputElement.value).toBe('13:00');
@@ -76,10 +83,12 @@ describe(' ', () => {
});
});
it('checking deadline input validation error', async () => {
- const { getByPlaceholderText, getByText } = render( );
+ const { getByPlaceholderText, getByText } = render(
+ ,
+ );
await waitFor(() => {
const inputElement = getByPlaceholderText(TIME_FORMAT.toUpperCase());
fireEvent.change(inputElement, { target: { value: 'wrong:input format' } });
@@ -87,10 +96,12 @@ describe(' ', () => {
});
});
it('checking deadline input time format validation error', async () => {
- const { getByPlaceholderText, getByText } = render( );
+ const { getByPlaceholderText, getByText } = render(
+ ,
+ );
await waitFor(() => {
const inputElement = getByPlaceholderText(TIME_FORMAT.toUpperCase());
diff --git a/src/grading-settings/deadline-section/index.jsx b/src/grading-settings/deadline-section/index.jsx
index 31305fd5ea..60d95842ac 100644
--- a/src/grading-settings/deadline-section/index.jsx
+++ b/src/grading-settings/deadline-section/index.jsx
@@ -9,7 +9,10 @@ import { formatTime, timerValidation } from './utils';
import messages from './messages';
const DeadlineSection = ({
- setShowSavePrompt, gracePeriod, setGradingData, setShowSuccessAlert,
+ setShowSavePrompt,
+ gracePeriod,
+ setGradingData,
+ setShowSuccessAlert,
}) => {
const intl = useIntl();
const timeStampValue = gracePeriod
@@ -41,9 +44,10 @@ const DeadlineSection = ({
};
return (
-
{intl.formatMessage(messages.gracePeriodOnDeadlineLabel)}
diff --git a/src/grading-settings/grading-scale/GradingScale.jsx b/src/grading-settings/grading-scale/GradingScale.jsx
index d4d7d21dfb..0ae0f0aafa 100644
--- a/src/grading-settings/grading-scale/GradingScale.jsx
+++ b/src/grading-settings/grading-scale/GradingScale.jsx
@@ -95,7 +95,7 @@ const GradingScale = ({
return updatedGradingSegment;
});
- const nextIndex = (letters.length % defaultGradeDesignations.length);
+ const nextIndex = letters.length % defaultGradeDesignations.length;
if (gradingSegments.length === 2) {
setLetters([defaultGradeDesignations[0], defaultGradeDesignations[nextIndex]]);
@@ -109,16 +109,18 @@ const GradingScale = ({
const sortedSegments = newGradingSegmentData.sort((currentValue, previousValue) => currentValue - previousValue);
const newSegmentValue = sortedSegments[sortedSegments.length - 1 - activeHandleIndex];
const prevSegmentBoundary = (gradingSegments[activeHandleIndex + 1]
- && gradingSegments[activeHandleIndex + 1].current) || 0;
+ && gradingSegments[activeHandleIndex + 1].current) || 0;
const nextSegmentBoundary = gradingSegments[activeHandleIndex - 1].current;
showSavePrompt(true);
setGradingSegments(gradingSegments.map((gradingSegment, idx) => {
const upperBoundaryValue = (newSegmentValue < nextSegmentBoundary - gapToSegment)
- ? newSegmentValue : (nextSegmentBoundary - gapToSegment);
+ ? newSegmentValue :
+ (nextSegmentBoundary - gapToSegment);
const lowerBoundaryValue = (upperBoundaryValue > prevSegmentBoundary + gapToSegment)
- ? upperBoundaryValue : (prevSegmentBoundary + gapToSegment);
+ ? upperBoundaryValue :
+ (prevSegmentBoundary + gapToSegment);
if (idx === activeHandleIndex - 1) {
return {
diff --git a/src/grading-settings/grading-scale/components/GradingScaleHandle.jsx b/src/grading-settings/grading-scale/components/GradingScaleHandle.jsx
index d6ca20dfc7..c24879d9a1 100644
--- a/src/grading-settings/grading-scale/components/GradingScaleHandle.jsx
+++ b/src/grading-settings/grading-scale/components/GradingScaleHandle.jsx
@@ -4,7 +4,10 @@ import PropTypes from 'prop-types';
import { MAXIMUM_SCALE_LENGTH } from '../utils';
const GradingScaleHandle = ({
- idx, value, gradingSegments, getHandleProps,
+ idx,
+ value,
+ gradingSegments,
+ getHandleProps,
}) => (
);
diff --git a/src/grading-settings/grading-scale/components/GradingScaleSegment.tsx b/src/grading-settings/grading-scale/components/GradingScaleSegment.tsx
index 95d95b781a..e2054d8681 100644
--- a/src/grading-settings/grading-scale/components/GradingScaleSegment.tsx
+++ b/src/grading-settings/grading-scale/components/GradingScaleSegment.tsx
@@ -6,18 +6,18 @@ import messages from '../messages';
import { getLettersOnLongScale, getLettersOnShortScale } from '../utils';
interface RangeSegment {
- previous: number,
- current: number,
+ previous: number;
+ current: number;
}
interface GradingScaleSegmentProps {
- idx: number,
- value: number,
- getSegmentProps: () => { [key: string]: string },
- handleLetterChange: (event: ChangeEvent, idx: number) => void,
- letters: [string],
- gradingSegments: RangeSegment[],
- removeGradingSegment: (idx: number) => void,
+ idx: number;
+ value: number;
+ getSegmentProps: () => { [key: string]: string; };
+ handleLetterChange: (event: ChangeEvent, idx: number) => void;
+ letters: [string];
+ gradingSegments: RangeSegment[];
+ removeGradingSegment: (idx: number) => void;
}
const GradingScaleSegment = ({
@@ -46,22 +46,22 @@ const GradingScaleSegment = ({
}}
>
{gradingSegments.length === 2 && (
- handleLetterChange(e, idx)}
- disabled={idx === gradingSegments.length}
- />
+ handleLetterChange(e, idx)}
+ disabled={idx === gradingSegments.length}
+ />
)}
{gradingSegments.length > 2 && (
- handleLetterChange(e, idx)}
- disabled={idx === gradingSegments.length}
- />
+ handleLetterChange(e, idx)}
+ disabled={idx === gradingSegments.length}
+ />
)}
{gradingSegments[idx === 0 ? 0 : idx - 1]?.previous} - {value === 100 ? value : value - 1}
diff --git a/src/grading-settings/grading-scale/components/index.jsx b/src/grading-settings/grading-scale/components/index.jsx
index 6770055cf4..2a1a812717 100644
--- a/src/grading-settings/grading-scale/components/index.jsx
+++ b/src/grading-settings/grading-scale/components/index.jsx
@@ -1,3 +1,3 @@
export { default as GradingScaleHandle } from './GradingScaleHandle';
-export { default as GradingScaleTicks } from './GradingScaleTick';
export { default as GradingScaleSegment } from './GradingScaleSegment';
+export { default as GradingScaleTicks } from './GradingScaleTick';
diff --git a/src/grading-settings/grading-scale/react-ranger.js b/src/grading-settings/grading-scale/react-ranger.js
index 55895b34f0..bc73f63a1b 100644
--- a/src/grading-settings/grading-scale/react-ranger.js
+++ b/src/grading-settings/grading-scale/react-ranger.js
@@ -5,8 +5,8 @@ function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) { return {}; }
const target = {};
const sourceKeys = Object.keys(source);
- let key; let
- i;
+ let key;
+ let i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
@@ -160,7 +160,8 @@ function useRanger(_ref) {
const { values } = _getLatest2;
const _getLatest2$onChange = _getLatest2.onChange;
const onChange = _getLatest2$onChange === void 0
- ? function () {} : _getLatest2$onChange; // Left Arrow || Right Arrow
+ ? function() {} :
+ _getLatest2$onChange; // Left Arrow || Right Arrow
if (e.keyCode === 37 || e.keyCode === 39) {
setActiveHandleIndex(i);
@@ -179,9 +180,9 @@ function useRanger(_ref) {
const { tempValues } = _getLatest3;
const { values } = _getLatest3;
const _getLatest3$onChange = _getLatest3.onChange;
- const onChange = _getLatest3$onChange === void 0 ? function () {} : _getLatest3$onChange;
+ const onChange = _getLatest3$onChange === void 0 ? function() {} : _getLatest3$onChange;
const _getLatest3$onDrag = _getLatest3.onDrag;
- const onDrag = _getLatest3$onDrag === void 0 ? function () {} : _getLatest3$onDrag;
+ const onDrag = _getLatest3$onDrag === void 0 ? function() {} : _getLatest3$onDrag;
document.removeEventListener('mousemove', handleDrag);
document.removeEventListener('touchmove', handleDrag);
@@ -199,8 +200,11 @@ function useRanger(_ref) {
document.addEventListener('mouseup', handleRelease);
document.addEventListener('touchend', handleRelease);
}, [getLatest, handleDrag]);
- const getPercentageForValue = React.useCallback((val) =>
- interpolator.getPercentageForValue(val, min, max), [interpolator, max, min]); // Build the ticks
+ const getPercentageForValue = React.useCallback((val) => interpolator.getPercentageForValue(val, min, max), [
+ interpolator,
+ max,
+ min,
+ ]); // Build the ticks
const ticks = React.useMemo(() => {
let ticks = controlledTicks || steps;
@@ -230,7 +234,7 @@ function useRanger(_ref) {
style: {
position: 'absolute',
width: 0,
- left: `${getPercentageForValue(value) }%`,
+ left: `${getPercentageForValue(value)}%`,
transform: 'translateX(-50%)',
...style,
},
@@ -257,8 +261,8 @@ function useRanger(_ref) {
key,
style: {
position: 'absolute',
- left: `${left }%`,
- width: `${width }%`,
+ left: `${left}%`,
+ width: `${width}%`,
...style,
},
...rest,
@@ -266,57 +270,64 @@ function useRanger(_ref) {
},
}));
}, [getPercentageForValue, max, min, tempValues, values]);
- const handles = React.useMemo(() => (tempValues || values).map((value, i) => ({
- value,
- active: i === activeHandleIndex,
- getHandleProps: function getHandleProps(_temp3) {
- const _ref4 = _temp3 === void 0 ? {} : _temp3;
- const _ref4$key = _ref4.key;
- const key = _ref4$key === void 0 ? i : _ref4$key;
- const { ref } = _ref4;
- const _ref4$innerRef = _ref4.innerRef;
- const _onKeyDown = _ref4.onKeyDown;
- const _onMouseDown = _ref4.onMouseDown;
- const _onTouchStart = _ref4.onTouchStart;
- const _ref4$style = _ref4.style;
- const style = _ref4$style === void 0 ? {} : _ref4$style;
- const rest = _objectWithoutPropertiesLoose(_ref4, [
- 'key', 'ref', 'innerRef', 'onKeyDown', 'onMouseDown', 'onTouchStart', 'style',
- ]);
-
- return {
- key,
- onKeyDown: function onKeyDown(e) {
- e.persist();
- handleKeyDown(e, i);
- if (_onKeyDown) { _onKeyDown(e); }
- },
- onMouseDown: function onMouseDown(e) {
- e.persist();
- handlePress(e, i);
- if (_onMouseDown) { _onMouseDown(e); }
- },
- onTouchStart: function onTouchStart(e) {
- e.persist();
- handlePress(e, i);
- if (_onTouchStart) { _onTouchStart(e); }
- },
- role: 'slider',
- 'aria-valuemin': min,
- 'aria-valuemax': max,
- 'aria-valuenow': value,
- style: {
- position: 'absolute',
- top: '50%',
- left: `${getPercentageForValue(value) }%`,
- zIndex: i === activeHandleIndex ? '1' : '0',
- transform: 'translate(-50%, -50%)',
- ...style,
- },
- ...rest,
- };
- },
- })), [activeHandleIndex, getPercentageForValue, handleKeyDown, handlePress, min, max, tempValues, values]);
+ const handles = React.useMemo(() =>
+ (tempValues || values).map((value, i) => ({
+ value,
+ active: i === activeHandleIndex,
+ getHandleProps: function getHandleProps(_temp3) {
+ const _ref4 = _temp3 === void 0 ? {} : _temp3;
+ const _ref4$key = _ref4.key;
+ const key = _ref4$key === void 0 ? i : _ref4$key;
+ const { ref } = _ref4;
+ const _ref4$innerRef = _ref4.innerRef;
+ const _onKeyDown = _ref4.onKeyDown;
+ const _onMouseDown = _ref4.onMouseDown;
+ const _onTouchStart = _ref4.onTouchStart;
+ const _ref4$style = _ref4.style;
+ const style = _ref4$style === void 0 ? {} : _ref4$style;
+ const rest = _objectWithoutPropertiesLoose(_ref4, [
+ 'key',
+ 'ref',
+ 'innerRef',
+ 'onKeyDown',
+ 'onMouseDown',
+ 'onTouchStart',
+ 'style',
+ ]);
+
+ return {
+ key,
+ onKeyDown: function onKeyDown(e) {
+ e.persist();
+ handleKeyDown(e, i);
+ if (_onKeyDown) { _onKeyDown(e); }
+ },
+ onMouseDown: function onMouseDown(e) {
+ e.persist();
+ handlePress(e, i);
+ if (_onMouseDown) { _onMouseDown(e); }
+ },
+ onTouchStart: function onTouchStart(e) {
+ e.persist();
+ handlePress(e, i);
+ if (_onTouchStart) { _onTouchStart(e); }
+ },
+ role: 'slider',
+ 'aria-valuemin': min,
+ 'aria-valuemax': max,
+ 'aria-valuenow': value,
+ style: {
+ position: 'absolute',
+ top: '50%',
+ left: `${getPercentageForValue(value)}%`,
+ zIndex: i === activeHandleIndex ? '1' : '0',
+ transform: 'translate(-50%, -50%)',
+ ...style,
+ },
+ ...rest,
+ };
+ },
+ })), [activeHandleIndex, getPercentageForValue, handleKeyDown, handlePress, min, max, tempValues, values]);
const getTrackProps = function getTrackProps(_temp4) {
const _ref5 = _temp4 === void 0 ? {} : _temp4;
diff --git a/src/grading-settings/grading-scale/utils.js b/src/grading-settings/grading-scale/utils.js
index c395db3c8f..9e6b1b0e28 100644
--- a/src/grading-settings/grading-scale/utils.js
+++ b/src/grading-settings/grading-scale/utils.js
@@ -8,8 +8,9 @@ export const MAXIMUM_SCALE_LENGTH = 100;
* @param {object} cutoffs - The object containing the settings to grading cutoffs.
* @returns {array} - Converted grading cutoffs.
*/
-export const getGradingValues = (cutoffs) => Object.values(cutoffs)
- .map(number => Math.round(number * MAXIMUM_SCALE_LENGTH));
+export const getGradingValues = (cutoffs) =>
+ Object.values(cutoffs)
+ .map(number => Math.round(number * MAXIMUM_SCALE_LENGTH));
/**
* Initially, the data comes in the format { a: 0.8 },
@@ -18,19 +19,20 @@ export const getGradingValues = (cutoffs) => Object.values(cutoffs)
* @param {object} gradeValues - The object containing the settings to grading cutoffs.
* @returns {object} - New grading cutoffs.
*/
-export const getSortedGrades = (gradeValues) => gradeValues.reduce((sortedArray, current, idx) => {
- if (idx === (gradeValues.length - 1)) {
- sortedArray.push({ current: gradeValues[idx - 1] || MAXIMUM_SCALE_LENGTH, previous: gradeValues[idx] });
- sortedArray.push({ current: gradeValues[idx], previous: 0 });
- } else if (idx === 0) {
- sortedArray.push({ current: MAXIMUM_SCALE_LENGTH, previous: current });
- } else {
- const previous = gradeValues[idx - 1];
- sortedArray.push({ current: previous, previous: current });
- }
+export const getSortedGrades = (gradeValues) =>
+ gradeValues.reduce((sortedArray, current, idx) => {
+ if (idx === (gradeValues.length - 1)) {
+ sortedArray.push({ current: gradeValues[idx - 1] || MAXIMUM_SCALE_LENGTH, previous: gradeValues[idx] });
+ sortedArray.push({ current: gradeValues[idx], previous: 0 });
+ } else if (idx === 0) {
+ sortedArray.push({ current: MAXIMUM_SCALE_LENGTH, previous: current });
+ } else {
+ const previous = gradeValues[idx - 1];
+ sortedArray.push({ current: previous, previous: current });
+ }
- return sortedArray;
-}, []);
+ return sortedArray;
+ }, []);
/**
* Changes the start and end values of the segments when there are two segments.
diff --git a/src/grading-settings/grading-sidebar/GradingSidebar.test.jsx b/src/grading-settings/grading-sidebar/GradingSidebar.test.jsx
index e794ad64d8..a76e9bceea 100644
--- a/src/grading-settings/grading-sidebar/GradingSidebar.test.jsx
+++ b/src/grading-settings/grading-sidebar/GradingSidebar.test.jsx
@@ -1,5 +1,7 @@
import {
- initializeMocks, render, screen,
+ initializeMocks,
+ render,
+ screen,
} from '../../testUtils';
import messages from './messages';
import GradingSidebar from '.';
diff --git a/src/grading-settings/messages.ts b/src/grading-settings/messages.ts
index 80a55e952a..14488eb13b 100644
--- a/src/grading-settings/messages.ts
+++ b/src/grading-settings/messages.ts
@@ -19,7 +19,7 @@ const messages = defineMessages({
},
alertWarning: {
id: 'course-authoring.grading-settings.alert.warning',
- defaultMessage: "You've made some changes",
+ defaultMessage: 'You\'ve made some changes',
},
alertWarningDescriptions: {
id: 'course-authoring.grading-settings.alert.warning.descriptions',
diff --git a/src/group-configurations/GroupConfigurations.test.jsx b/src/group-configurations/GroupConfigurations.test.jsx
index 3cc4ace4f9..b32b687e65 100644
--- a/src/group-configurations/GroupConfigurations.test.jsx
+++ b/src/group-configurations/GroupConfigurations.test.jsx
@@ -22,11 +22,12 @@ const enrollmentTrackGroups = groupConfigurationResponseMock.allGroupConfigurati
const contentGroups = groupConfigurationResponseMock.allGroupConfigurations[1];
const teamGroups = groupConfigurationResponseMock.allGroupConfigurations[2];
-const renderComponent = () => render(
-
-
- ,
-);
+const renderComponent = () =>
+ render(
+
+
+ ,
+ );
describe(' ', () => {
beforeEach(async () => {
diff --git a/src/group-configurations/__mocks__/groupConfigurationResponseMock.js b/src/group-configurations/__mocks__/groupConfigurationResponseMock.js
index b35823be1d..0ad3a86daa 100644
--- a/src/group-configurations/__mocks__/groupConfigurationResponseMock.js
+++ b/src/group-configurations/__mocks__/groupConfigurationResponseMock.js
@@ -34,8 +34,7 @@ module.exports = {
},
{
active: true,
- description:
- 'The groups in this configuration can be mapped to cohorts in the Instructor Dashboard.',
+ description: 'The groups in this configuration can be mapped to cohorts in the Instructor Dashboard.',
groups: [
{
id: 593758473,
diff --git a/src/group-configurations/common/TitleButton.jsx b/src/group-configurations/common/TitleButton.jsx
index d6edfb0a06..4cd47f5e32 100644
--- a/src/group-configurations/common/TitleButton.jsx
+++ b/src/group-configurations/common/TitleButton.jsx
@@ -1,7 +1,10 @@
import PropTypes from 'prop-types';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
- Button, Stack, Badge, Truncate,
+ Button,
+ Stack,
+ Badge,
+ Truncate,
} from '@openedx/paragon';
import {
ArrowDropDown as ArrowDownIcon,
@@ -12,7 +15,10 @@ import { getCombinedBadgeList } from '../utils';
import messages from './messages';
const TitleButton = ({
- group, isExpanded, isExperiment, onTitleClick,
+ group,
+ isExpanded,
+ isExperiment,
+ onTitleClick,
}) => {
const { formatMessage } = useIntl();
const { id, name, usage } = group;
diff --git a/src/group-configurations/common/UsageList.test.jsx b/src/group-configurations/common/UsageList.test.jsx
index e4d4681279..9d8105cd0c 100644
--- a/src/group-configurations/common/UsageList.test.jsx
+++ b/src/group-configurations/common/UsageList.test.jsx
@@ -8,11 +8,12 @@ import messages from './messages';
const usages = contentGroupsMock.groups[1]?.usage;
-const renderComponent = (props = {}) => render(
-
-
- ,
-);
+const renderComponent = (props = {}) =>
+ render(
+
+
+ ,
+ );
describe(' ', () => {
it('renders component correctly', () => {
diff --git a/src/group-configurations/content-groups-section/ContentGroupCard.jsx b/src/group-configurations/content-groups-section/ContentGroupCard.jsx
index e56d4d4c4c..2121d3e993 100644
--- a/src/group-configurations/content-groups-section/ContentGroupCard.jsx
+++ b/src/group-configurations/content-groups-section/ContentGroupCard.jsx
@@ -68,68 +68,70 @@ const ContentGroupCard = ({
return (
<>
- {isEditMode ? (
- handleEditGroup(id, values, switchOffEditMode)}
- />
- ) : (
-
-
-
- {!readOnly && (
-
-
-
-
- )}
-
- {isExpanded && (
-
- {usage?.length ? (
-
- ) : (
- guideHowToAdd
+ {isEditMode ?
+ (
+
handleEditGroup(id, values, switchOffEditMode)}
+ />
+ ) :
+ (
+
+
+
+ {!readOnly && (
+
+
+
+
)}
- )}
-
- )}
+ {isExpanded && (
+
+ {usage?.length ?
+ (
+
+ ) :
+ guideHowToAdd}
+
+ )}
+
+ )}
render(
-
- group.name)}
- parentGroupId={contentGroupsMock.id}
- contentGroupActions={contentGroupActions}
- handleEditGroup={handleEditGroupMock}
- {...props}
- />
- ,
-);
+const renderComponent = (props = {}) =>
+ render(
+
+ group.name)}
+ parentGroupId={contentGroupsMock.id}
+ contentGroupActions={contentGroupActions}
+ handleEditGroup={handleEditGroupMock}
+ {...props}
+ />
+ ,
+ );
describe(' ', () => {
it('renders component correctly', () => {
@@ -51,7 +52,10 @@ describe(' ', () => {
it('expands/collapses the container group content on title click', async () => {
const user = userEvent.setup();
const {
- getByText, queryByTestId, getByTestId, queryByText,
+ getByText,
+ queryByTestId,
+ getByTestId,
+ queryByText,
} = renderComponent();
const cardTitle = getByTestId('configuration-card-header-button');
await user.click(cardTitle);
diff --git a/src/group-configurations/content-groups-section/ContentGroupForm.jsx b/src/group-configurations/content-groups-section/ContentGroupForm.jsx
index b4f7a76ba2..274ce12d31 100644
--- a/src/group-configurations/content-groups-section/ContentGroupForm.jsx
+++ b/src/group-configurations/content-groups-section/ContentGroupForm.jsx
@@ -51,7 +51,11 @@ const ContentGroupForm = ({
onSubmit={onSubmitForm}
>
{({
- values, errors, dirty, handleChange, handleSubmit,
+ values,
+ errors,
+ dirty,
+ handleChange,
+ handleSubmit,
}) => {
const isInvalid = !!errors.newGroupName;
diff --git a/src/group-configurations/content-groups-section/ContentGroupForm.test.jsx b/src/group-configurations/content-groups-section/ContentGroupForm.test.jsx
index e58b2bb112..b9599e3df3 100644
--- a/src/group-configurations/content-groups-section/ContentGroupForm.test.jsx
+++ b/src/group-configurations/content-groups-section/ContentGroupForm.test.jsx
@@ -10,17 +10,18 @@ const onCreateClickMock = jest.fn();
const onCancelClickMock = jest.fn();
const onEditClickMock = jest.fn();
-const renderComponent = (props = {}) => render(
-
- group.name)}
- onCreateClick={onCreateClickMock}
- onCancelClick={onCancelClickMock}
- onEditClick={onEditClickMock}
- {...props}
- />
- ,
-);
+const renderComponent = (props = {}) =>
+ render(
+
+ group.name)}
+ onCreateClick={onCreateClickMock}
+ onCancelClick={onCancelClickMock}
+ onEditClick={onEditClickMock}
+ {...props}
+ />
+ ,
+ );
describe(' ', () => {
it('renders component correctly', () => {
@@ -40,7 +41,10 @@ describe(' ', () => {
it('renders component in edit mode', () => {
const {
- getByText, queryByText, getByRole, getByPlaceholderText,
+ getByText,
+ queryByText,
+ getByRole,
+ getByPlaceholderText,
} = renderComponent({
isEditMode: true,
overrideValue: 'overrideValue',
@@ -75,7 +79,9 @@ describe(' ', () => {
it('calls onCreate when the "Create" button is clicked with a valid form', async () => {
const user = userEvent.setup();
const {
- getByRole, getByPlaceholderText, queryByText,
+ getByRole,
+ getByPlaceholderText,
+ queryByText,
} = renderComponent();
const newGroupNameText = 'New group name';
const newGroupInput = getByPlaceholderText(
diff --git a/src/group-configurations/content-groups-section/ContentGroupsSection.test.jsx b/src/group-configurations/content-groups-section/ContentGroupsSection.test.jsx
index 3bfceb5125..725e713420 100644
--- a/src/group-configurations/content-groups-section/ContentGroupsSection.test.jsx
+++ b/src/group-configurations/content-groups-section/ContentGroupsSection.test.jsx
@@ -16,15 +16,16 @@ const contentGroupActions = {
handleEdit: handleEditMock,
};
-const renderComponent = (props = {}) => render(
-
-
- ,
-);
+const renderComponent = (props = {}) =>
+ render(
+
+
+ ,
+ );
describe(' ', () => {
it('renders component correctly', () => {
diff --git a/src/group-configurations/content-groups-section/index.jsx b/src/group-configurations/content-groups-section/index.jsx
index de21e323f1..6f1edfd1ea 100644
--- a/src/group-configurations/content-groups-section/index.jsx
+++ b/src/group-configurations/content-groups-section/index.jsx
@@ -43,35 +43,35 @@ const ContentGroupsSection = ({
{name}
- {groups?.length ? (
- <>
- {groups.map((group) => (
-
- ))}
- {!isNewGroupVisible && (
-
- {formatMessage(messages.addNewGroup)}
-
- )}
- >
- ) : (
- !isNewGroupVisible && (
-
- )
- )}
+ {groups?.length ?
+ (
+ <>
+ {groups.map((group) => (
+
+ ))}
+ {!isNewGroupVisible && (
+
+ {formatMessage(messages.addNewGroup)}
+
+ )}
+ >
+ ) :
+ (
+ !isNewGroupVisible &&
+ )}
{isNewGroupVisible && (
getConfig().STUDIO_BASE_URL;
-export const getContentStoreApiUrl = (courseId) => `${getStudioBaseUrl()}/api/contentstore/v1/${API_PATH_PATTERN}/${courseId}`;
+export const getContentStoreApiUrl = (courseId) =>
+ `${getStudioBaseUrl()}/api/contentstore/v1/${API_PATH_PATTERN}/${courseId}`;
export const getLegacyApiUrl = (courseId, parentGroupId, groupId) => {
const parentUrlPath = `${getStudioBaseUrl()}/${API_PATH_PATTERN}/${courseId}`;
const parentGroupPath = `${parentGroupId ? `/${parentGroupId}` : ''}`;
diff --git a/src/group-configurations/empty-placeholder/EmptyPlaceholder.test.jsx b/src/group-configurations/empty-placeholder/EmptyPlaceholder.test.jsx
index 5d4ed0b5cb..592bb6ca18 100644
--- a/src/group-configurations/empty-placeholder/EmptyPlaceholder.test.jsx
+++ b/src/group-configurations/empty-placeholder/EmptyPlaceholder.test.jsx
@@ -6,11 +6,12 @@ import EmptyPlaceholder from '.';
const onCreateNewGroup = jest.fn();
-const renderComponent = () => render(
-
-
- ,
-);
+const renderComponent = () =>
+ render(
+
+
+ ,
+ );
describe(' ', () => {
it('renders EmptyPlaceholder component correctly', () => {
diff --git a/src/group-configurations/enrollment-track-groups-section/EnrollmentTrackGroupsSection.test.jsx b/src/group-configurations/enrollment-track-groups-section/EnrollmentTrackGroupsSection.test.jsx
index 84283ab689..c8bb2ccae9 100644
--- a/src/group-configurations/enrollment-track-groups-section/EnrollmentTrackGroupsSection.test.jsx
+++ b/src/group-configurations/enrollment-track-groups-section/EnrollmentTrackGroupsSection.test.jsx
@@ -4,14 +4,15 @@ import { IntlProvider } from '@edx/frontend-platform/i18n';
import { enrollmentTrackGroupsMock } from '../__mocks__';
import EnrollmentTrackGroupsSection from '.';
-const renderComponent = (props = {}) => render(
-
-
- ,
-);
+const renderComponent = (props = {}) =>
+ render(
+
+
+ ,
+ );
describe(' ', () => {
it('renders component correctly', () => {
diff --git a/src/group-configurations/experiment-configurations-section/ExperimentCard.jsx b/src/group-configurations/experiment-configurations-section/ExperimentCard.jsx
index 60a6d177d2..f5d26c1321 100644
--- a/src/group-configurations/experiment-configurations-section/ExperimentCard.jsx
+++ b/src/group-configurations/experiment-configurations-section/ExperimentCard.jsx
@@ -40,7 +40,10 @@ const ExperimentCard = ({
}, [isExpandedByDefault]);
const {
- id, groups: groupsControl, description, usage,
+ id,
+ groups: groupsControl,
+ description,
+ usage,
} = configuration;
const isUsedInLocation = !!usage?.length;
@@ -85,73 +88,75 @@ const ExperimentCard = ({
return (
<>
- {isEditMode ? (
-
- ) : (
-
-
-
setIsExpanded((prevState) => !prevState)}
- isExperiment
- />
-
-
+ ) :
+ (
+
+
+ setIsExpanded((prevState) => !prevState)}
+ isExperiment
/>
-
-
-
- {isExpanded && (
-
- {description}
-
- {usage?.length ? (
-
+
- ) : (
- guideHowToAdd
- )}
+
+
- )}
-
- )}
+ {isExpanded && (
+
+ {description}
+
+ {usage?.length ?
+ (
+
+ ) :
+ guideHowToAdd}
+
+ )}
+
+ )}
render(
-
-
- ,
-);
+const renderComponent = (props = {}) =>
+ render(
+
+
+ ,
+ );
describe(' ', () => {
it('renders component correctly', () => {
@@ -108,7 +109,7 @@ describe(' ', () => {
expect(usageBlock).toBeInTheDocument();
});
- it("user can't delete experiment configuration that is used in location", () => {
+ it('user can\'t delete experiment configuration that is used in location', () => {
const usageLocation = {
label: 'UnitName 2 / Content Experiment',
url: '/container/block-v1:2u+1+1+type@split_test+block@ccfae830ec9b406c835f8ce4520ae396',
diff --git a/src/group-configurations/experiment-configurations-section/ExperimentConfigurationsSection.test.jsx b/src/group-configurations/experiment-configurations-section/ExperimentConfigurationsSection.test.jsx
index 6fcd756567..731afbeaa6 100644
--- a/src/group-configurations/experiment-configurations-section/ExperimentConfigurationsSection.test.jsx
+++ b/src/group-configurations/experiment-configurations-section/ExperimentConfigurationsSection.test.jsx
@@ -22,15 +22,16 @@ jest.mock('react-router-dom', () => ({
}),
}));
-const renderComponent = (props) => render(
-
-
- ,
-);
+const renderComponent = (props) =>
+ render(
+
+
+ ,
+ );
describe(' ', () => {
it('renders component correctly', () => {
diff --git a/src/group-configurations/experiment-configurations-section/ExperimentForm.jsx b/src/group-configurations/experiment-configurations-section/ExperimentForm.jsx
index 83bd238323..1df605e430 100644
--- a/src/group-configurations/experiment-configurations-section/ExperimentForm.jsx
+++ b/src/group-configurations/experiment-configurations-section/ExperimentForm.jsx
@@ -48,7 +48,11 @@ const ExperimentForm = ({
onSubmit={onSubmitForm}
>
{({
- values, errors, dirty, handleChange, handleSubmit,
+ values,
+ errors,
+ dirty,
+ handleChange,
+ handleSubmit,
}) => (
<>
render(
-
-
- ,
-);
+const renderComponent = (props = {}) =>
+ render(
+
+
+ ,
+ );
describe(' ', () => {
it('renders component correctly', () => {
diff --git a/src/group-configurations/experiment-configurations-section/ExperimentFormGroups.jsx b/src/group-configurations/experiment-configurations-section/ExperimentFormGroups.jsx
index c20bfe93f1..b3c9f69104 100644
--- a/src/group-configurations/experiment-configurations-section/ExperimentFormGroups.jsx
+++ b/src/group-configurations/experiment-configurations-section/ExperimentFormGroups.jsx
@@ -3,7 +3,11 @@ import PropTypes from 'prop-types';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Close as CloseIcon, Add as AddIcon } from '@openedx/paragon/icons';
import {
- Form, Icon, IconButtonWithTooltip, Stack, Button,
+ Form,
+ Icon,
+ IconButtonWithTooltip,
+ Stack,
+ Button,
} from '@openedx/paragon';
import {
diff --git a/src/group-configurations/experiment-configurations-section/constants.ts b/src/group-configurations/experiment-configurations-section/constants.ts
index 70ed39bc88..2bd37441f8 100644
--- a/src/group-configurations/experiment-configurations-section/constants.ts
+++ b/src/group-configurations/experiment-configurations-section/constants.ts
@@ -4,10 +4,16 @@ export const initialExperimentConfiguration = {
description: '',
groups: [
{
- name: 'Group A', version: 1, usage: [], idx: 0,
+ name: 'Group A',
+ version: 1,
+ usage: [],
+ idx: 0,
},
{
- name: 'Group B', version: 1, usage: [], idx: 1,
+ name: 'Group B',
+ version: 1,
+ usage: [],
+ idx: 1,
},
],
scheme: 'random',
diff --git a/src/group-configurations/experiment-configurations-section/index.jsx b/src/group-configurations/experiment-configurations-section/index.jsx
index 1439d8f3fa..26ec0b518f 100644
--- a/src/group-configurations/experiment-configurations-section/index.jsx
+++ b/src/group-configurations/experiment-configurations-section/index.jsx
@@ -33,37 +33,39 @@ const ExperimentConfigurationsSection = ({
{formatMessage(messages.title)}
- {availableGroups.length ? (
- <>
- {availableGroups.map((configuration) => (
-
+ {availableGroups.map((configuration) => (
+
+ ))}
+ {!isNewConfigurationVisible && (
+
+ {formatMessage(messages.addNewGroup)}
+
+ )}
+ >
+ ) :
+ (
+ !isNewConfigurationVisible && (
+
- ))}
- {!isNewConfigurationVisible && (
-
- {formatMessage(messages.addNewGroup)}
-
- )}
- >
- ) : (
- !isNewConfigurationVisible && (
-
- )
- )}
+ )
+ )}
{isNewConfigurationVisible && (
{
} while (existingGroupNames.includes(`Group ${groupName}`));
return {
- [groupFieldName]: `Group ${groupName}`, version: 1, usage: [], idx: nextIndex,
+ [groupFieldName]: `Group ${groupName}`,
+ version: 1,
+ usage: [],
+ idx: nextIndex,
};
};
@@ -65,9 +68,4 @@ const getFormGroupErrors = (errors) => {
return { arrayErrors, stringError };
};
-export {
- allGroupNamesAreUnique,
- getNextGroupName,
- getGroupPercentage,
- getFormGroupErrors,
-};
+export { allGroupNamesAreUnique, getNextGroupName, getGroupPercentage, getFormGroupErrors };
diff --git a/src/group-configurations/experiment-configurations-section/utils.test.js b/src/group-configurations/experiment-configurations-section/utils.test.js
index 4e0e5f9272..4f48744dbb 100644
--- a/src/group-configurations/experiment-configurations-section/utils.test.js
+++ b/src/group-configurations/experiment-configurations-section/utils.test.js
@@ -9,10 +9,12 @@ describe('utils module', () => {
it('return correct next group name test-case-1', () => {
const groups = [
{
- name: 'Group A', idx: 0,
+ name: 'Group A',
+ idx: 0,
},
{
- name: 'Group B', idx: 1,
+ name: 'Group B',
+ idx: 1,
},
];
const nextGroup = getNextGroupName(groups);
@@ -30,10 +32,12 @@ describe('utils module', () => {
it('return correct next group name test-case-3', () => {
const groups = [
{
- name: 'Some group', idx: 0,
+ name: 'Some group',
+ idx: 0,
},
{
- name: 'Group B', idx: 1,
+ name: 'Group B',
+ idx: 1,
},
];
const nextGroup = getNextGroupName(groups);
@@ -44,10 +48,12 @@ describe('utils module', () => {
it('return correct next group name test-case-4', () => {
const groups = [
{
- name: 'Group A', idx: 0,
+ name: 'Group A',
+ idx: 0,
},
{
- name: 'Group A', idx: 1,
+ name: 'Group A',
+ idx: 1,
},
];
const nextGroup = getNextGroupName(groups);
@@ -58,13 +64,16 @@ describe('utils module', () => {
it('return correct next group name test-case-5', () => {
const groups = [
{
- name: 'Group A', idx: 0,
+ name: 'Group A',
+ idx: 0,
},
{
- name: 'Group C', idx: 1,
+ name: 'Group C',
+ idx: 1,
},
{
- name: 'Group B', idx: 2,
+ name: 'Group B',
+ idx: 2,
},
];
const nextGroup = getNextGroupName(groups);
@@ -75,10 +84,12 @@ describe('utils module', () => {
it('return correct next group name test-case-6', () => {
const groups = [
{
- name: '', idx: 0,
+ name: '',
+ idx: 0,
},
{
- name: '', idx: 1,
+ name: '',
+ idx: 1,
},
];
const nextGroup = getNextGroupName(groups);
@@ -89,10 +100,12 @@ describe('utils module', () => {
it('return correct next group name test-case-7', () => {
const groups = [
{
- name: 'Group A', idx: 0,
+ name: 'Group A',
+ idx: 0,
},
{
- name: 'Group C', idx: 1,
+ name: 'Group C',
+ idx: 1,
},
];
const nextGroup = getNextGroupName(groups);
@@ -103,7 +116,8 @@ describe('utils module', () => {
it('return correct next group name test-case-8', () => {
const groups = [
{
- name: 'Group D', idx: 0,
+ name: 'Group D',
+ idx: 0,
},
];
const nextGroup = getNextGroupName(groups);
@@ -114,7 +128,8 @@ describe('utils module', () => {
it('return correct next group name test-case-9', () => {
const groups = [
{
- name: 'Group E', idx: 4,
+ name: 'Group E',
+ idx: 4,
},
];
const nextGroup = getNextGroupName(groups);
@@ -124,7 +139,8 @@ describe('utils module', () => {
it('return correct next group name test-case-10', () => {
const groups = [
{
- name: 'Group E', idx: 0,
+ name: 'Group E',
+ idx: 0,
},
];
const nextGroup = getNextGroupName(groups);
diff --git a/src/group-configurations/experiment-configurations-section/validation.js b/src/group-configurations/experiment-configurations-section/validation.js
index 64ca594dc1..9947dc01b2 100644
--- a/src/group-configurations/experiment-configurations-section/validation.js
+++ b/src/group-configurations/experiment-configurations-section/validation.js
@@ -3,42 +3,43 @@ import * as Yup from 'yup';
import messages from './messages';
import { allGroupNamesAreUnique } from './utils';
-export const experimentFormValidationSchema = (formatMessage) => Yup.object().shape({
- id: Yup.number(),
- name: Yup.string()
- .trim()
- .required(formatMessage(messages.experimentConfigurationNameRequired)),
- description: Yup.string(),
- groups: Yup.array()
- .of(
- Yup.object().shape({
- id: Yup.number(),
- name: Yup.string()
- .trim()
- .required(
- formatMessage(messages.experimentConfigurationGroupsNameRequired),
- ),
- version: Yup.number(),
- usage: Yup.array().nullable(true),
- }),
- )
- .required()
- .min(1, formatMessage(messages.experimentConfigurationGroupsRequired))
- .test(
- 'unique-group-name-restriction',
- formatMessage(messages.experimentConfigurationGroupsNameUnique),
- (values) => allGroupNamesAreUnique(values),
- ),
- scheme: Yup.string(),
- version: Yup.number(),
- parameters: Yup.object(),
- usage: Yup.array()
- .of(
- Yup.object().shape({
- label: Yup.string(),
- url: Yup.string(),
- }),
- )
- .nullable(true),
- active: Yup.bool(),
-});
+export const experimentFormValidationSchema = (formatMessage) =>
+ Yup.object().shape({
+ id: Yup.number(),
+ name: Yup.string()
+ .trim()
+ .required(formatMessage(messages.experimentConfigurationNameRequired)),
+ description: Yup.string(),
+ groups: Yup.array()
+ .of(
+ Yup.object().shape({
+ id: Yup.number(),
+ name: Yup.string()
+ .trim()
+ .required(
+ formatMessage(messages.experimentConfigurationGroupsNameRequired),
+ ),
+ version: Yup.number(),
+ usage: Yup.array().nullable(true),
+ }),
+ )
+ .required()
+ .min(1, formatMessage(messages.experimentConfigurationGroupsRequired))
+ .test(
+ 'unique-group-name-restriction',
+ formatMessage(messages.experimentConfigurationGroupsNameUnique),
+ (values) => allGroupNamesAreUnique(values),
+ ),
+ scheme: Yup.string(),
+ version: Yup.number(),
+ parameters: Yup.object(),
+ usage: Yup.array()
+ .of(
+ Yup.object().shape({
+ label: Yup.string(),
+ url: Yup.string(),
+ }),
+ )
+ .nullable(true),
+ active: Yup.bool(),
+ });
diff --git a/src/group-configurations/group-configuration-sidebar/index.jsx b/src/group-configurations/group-configuration-sidebar/index.jsx
index 99dbf6bc4b..dc318b1d03 100644
--- a/src/group-configurations/group-configuration-sidebar/index.jsx
+++ b/src/group-configurations/group-configuration-sidebar/index.jsx
@@ -9,12 +9,19 @@ import { getSidebarData } from './utils';
import messages from './messages';
const GroupConfigurationSidebar = ({
- courseId, shouldShowExperimentGroups, shouldShowContentGroup, shouldShowEnrollmentTrackGroup,
+ courseId,
+ shouldShowExperimentGroups,
+ shouldShowContentGroup,
+ shouldShowEnrollmentTrackGroup,
}) => {
const intl = useIntl();
const urls = useHelpUrls(['groupConfigurations', 'enrollmentTracks', 'contentGroups']);
const sidebarData = getSidebarData({
- messages, intl, shouldShowExperimentGroups, shouldShowContentGroup, shouldShowEnrollmentTrackGroup,
+ messages,
+ intl,
+ shouldShowExperimentGroups,
+ shouldShowContentGroup,
+ shouldShowEnrollmentTrackGroup,
});
return (
diff --git a/src/group-configurations/group-configuration-sidebar/utils.jsx b/src/group-configurations/group-configuration-sidebar/utils.jsx
index 5719771a32..0d0cac6343 100644
--- a/src/group-configurations/group-configuration-sidebar/utils.jsx
+++ b/src/group-configurations/group-configuration-sidebar/utils.jsx
@@ -9,7 +9,11 @@
* @returns {Object[]} The array of sidebar data groups.
*/
const getSidebarData = ({
- messages, intl, shouldShowExperimentGroups, shouldShowContentGroup, shouldShowEnrollmentTrackGroup,
+ messages,
+ intl,
+ shouldShowExperimentGroups,
+ shouldShowContentGroup,
+ shouldShowEnrollmentTrackGroup,
}) => {
const groups = [];
diff --git a/src/group-configurations/index.tsx b/src/group-configurations/index.tsx
index 8b069d4047..b3a3971d8b 100644
--- a/src/group-configurations/index.tsx
+++ b/src/group-configurations/index.tsx
@@ -1,6 +1,9 @@
import { useIntl } from '@edx/frontend-platform/i18n';
import {
- Container, Layout, Stack, Row,
+ Container,
+ Layout,
+ Stack,
+ Row,
} from '@openedx/paragon';
import { useCourseAuthoringContext } from '@src/CourseAuthoringContext';
diff --git a/src/head/Head.test.jsx b/src/head/Head.test.jsx
index ac1a9cce8a..dfb298396b 100644
--- a/src/head/Head.test.jsx
+++ b/src/head/Head.test.jsx
@@ -8,7 +8,11 @@ import Head from './Head';
describe('Head', () => {
const props = {};
it('should match render title tag and favicon with the site configuration values', () => {
- render( );
+ render(
+
+
+ ,
+ );
const helmet = Helmet.peek();
expect(helmet.title).toEqual(`Course Authoring | ${getConfig().SITE_NAME}`);
expect(helmet.linkTags[0].rel).toEqual('shortcut icon');
diff --git a/src/header/Header.tsx b/src/header/Header.tsx
index 56768db2b3..2f2e307cf4 100644
--- a/src/header/Header.tsx
+++ b/src/header/Header.tsx
@@ -6,21 +6,25 @@ import { type Container, useToggle } from '@openedx/paragon';
import { useWaffleFlags } from '../data/apiHooks';
import { SearchModal } from '../search-modal';
import {
- useContentMenuItems, useLibrarySettingsMenuItems, useLibraryToolsMenuItems, useSettingMenuItems, useToolsMenuItems,
+ useContentMenuItems,
+ useLibrarySettingsMenuItems,
+ useLibraryToolsMenuItems,
+ useSettingMenuItems,
+ useToolsMenuItems,
} from './hooks';
import messages from './messages';
type ContainerPropsType = Omit, 'children'>;
interface HeaderProps {
- contextId?: string,
- number?: string,
- org?: string,
- title?: string,
- isHiddenMainMenu?: boolean,
- isLibrary?: boolean,
- containerProps?: ContainerPropsType,
- readOnly?: boolean,
+ contextId?: string;
+ number?: string;
+ org?: string;
+ title?: string;
+ isHiddenMainMenu?: boolean;
+ isLibrary?: boolean;
+ containerProps?: ContainerPropsType;
+ readOnly?: boolean;
}
const Header = ({
@@ -46,27 +50,29 @@ const Header = ({
const toolsMenuItems = useToolsMenuItems(contextId);
const libraryToolsMenuItems = useLibraryToolsMenuItems(contextId);
const libraryToolsSettingsItems = useLibrarySettingsMenuItems(contextId, readOnly);
- let mainMenuDropdowns = !isLibrary ? [
- {
- id: `${intl.formatMessage(messages['header.links.content'])}-dropdown-menu`,
- buttonTitle: intl.formatMessage(messages['header.links.content']),
- items: contentMenuItems,
- },
- {
- id: `${intl.formatMessage(messages['header.links.settings'])}-dropdown-menu`,
- buttonTitle: intl.formatMessage(messages['header.links.settings']),
- items: settingMenuItems,
- },
- {
+ let mainMenuDropdowns = !isLibrary ?
+ [
+ {
+ id: `${intl.formatMessage(messages['header.links.content'])}-dropdown-menu`,
+ buttonTitle: intl.formatMessage(messages['header.links.content']),
+ items: contentMenuItems,
+ },
+ {
+ id: `${intl.formatMessage(messages['header.links.settings'])}-dropdown-menu`,
+ buttonTitle: intl.formatMessage(messages['header.links.settings']),
+ items: settingMenuItems,
+ },
+ {
+ id: `${intl.formatMessage(messages['header.links.tools'])}-dropdown-menu`,
+ buttonTitle: intl.formatMessage(messages['header.links.tools']),
+ items: toolsMenuItems,
+ },
+ ] :
+ [{
id: `${intl.formatMessage(messages['header.links.tools'])}-dropdown-menu`,
buttonTitle: intl.formatMessage(messages['header.links.tools']),
- items: toolsMenuItems,
- },
- ] : [{
- id: `${intl.formatMessage(messages['header.links.tools'])}-dropdown-menu`,
- buttonTitle: intl.formatMessage(messages['header.links.tools']),
- items: libraryToolsMenuItems,
- }];
+ items: libraryToolsMenuItems,
+ }];
// Include settings menu only if user is allowed to see them.
if (isLibrary && libraryToolsSettingsItems.length > 0) {
diff --git a/src/header/hooks.test.tsx b/src/header/hooks.test.tsx
index b0a3de9ef5..f1db204b84 100644
--- a/src/header/hooks.test.tsx
+++ b/src/header/hooks.test.tsx
@@ -7,7 +7,11 @@ import { useUserPermissions } from '@src/authz/data/apiHooks';
import { mockWaffleFlags } from '@src/data/apiHooks.mock';
import messages from './messages';
import {
- useContentMenuItems, useToolsMenuItems, useSettingMenuItems, useLibrarySettingsMenuItems, useLibraryToolsMenuItems,
+ useContentMenuItems,
+ useToolsMenuItems,
+ useSettingMenuItems,
+ useLibrarySettingsMenuItems,
+ useLibraryToolsMenuItems,
} from './hooks';
jest.mock('@edx/frontend-platform/i18n', () => ({
@@ -43,7 +47,7 @@ const createWrapper = () => {
},
});
- const wrapper = ({ children }: { children: ReactNode }) => (
+ const wrapper = ({ children }: { children: ReactNode; }) => (
{children}
);
@@ -60,7 +64,8 @@ describe('header utils', () => {
...getConfig(),
ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN: 'true',
});
- const actualItems = renderHook(() => useContentMenuItems('course-123'), { wrapper: createWrapper() }).result.current;
+ const actualItems =
+ renderHook(() => useContentMenuItems('course-123'), { wrapper: createWrapper() }).result.current;
expect(actualItems).toHaveLength(5);
});
it('when video upload page disabled should not include Video Uploads option', () => {
@@ -71,14 +76,16 @@ describe('header utils', () => {
...getConfig(),
ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN: 'false',
});
- const actualItems = renderHook(() => useContentMenuItems('course-123'), { wrapper: createWrapper() }).result.current;
+ const actualItems =
+ renderHook(() => useContentMenuItems('course-123'), { wrapper: createWrapper() }).result.current;
expect(actualItems).toHaveLength(4);
});
it('adds course libraries link to content menu when libraries v2 is enabled', () => {
jest.mocked(useSelector).mockReturnValue({
librariesV2Enabled: true,
});
- const actualItems = renderHook(() => useContentMenuItems('course-123'), { wrapper: createWrapper() }).result.current;
+ const actualItems =
+ renderHook(() => useContentMenuItems('course-123'), { wrapper: createWrapper() }).result.current;
expect(actualItems[1]).toEqual({ href: '/course/course-123/libraries', title: 'Library Updates' });
});
});
@@ -99,7 +106,8 @@ describe('header utils', () => {
...getConfig(),
ENABLE_CERTIFICATE_PAGE: 'true',
});
- const actualItems = renderHook(() => useSettingMenuItems('course-123'), { wrapper: createWrapper() }).result.current;
+ const actualItems =
+ renderHook(() => useSettingMenuItems('course-123'), { wrapper: createWrapper() }).result.current;
expect(actualItems).toHaveLength(6);
});
it('when certificate page disabled should not include certificates option', () => {
@@ -107,16 +115,19 @@ describe('header utils', () => {
...getConfig(),
ENABLE_CERTIFICATE_PAGE: 'false',
});
- const actualItems = renderHook(() => useSettingMenuItems('course-123'), { wrapper: createWrapper() }).result.current;
+ const actualItems =
+ renderHook(() => useSettingMenuItems('course-123'), { wrapper: createWrapper() }).result.current;
expect(actualItems).toHaveLength(5);
});
it('when user has access to advanced settings should include advanced settings option', () => {
- const actualItemsTitle = renderHook(() => useSettingMenuItems('course-123'), { wrapper: createWrapper() }).result.current.map((item) => item.title);
+ const actualItemsTitle = renderHook(() => useSettingMenuItems('course-123'), { wrapper: createWrapper() }).result
+ .current.map((item) => item.title);
expect(actualItemsTitle).toContain('Advanced Settings');
});
it('when user has no access to advanced settings should not include advanced settings option', () => {
jest.mocked(useSelector).mockReturnValue({ canAccessAdvancedSettings: false });
- const actualItemsTitle = renderHook(() => useSettingMenuItems('course-123'), { wrapper: createWrapper() }).result.current.map((item) => item.title);
+ const actualItemsTitle = renderHook(() => useSettingMenuItems('course-123'), { wrapper: createWrapper() }).result
+ .current.map((item) => item.title);
expect(actualItemsTitle).not.toContain('Advanced Settings');
});
@@ -171,7 +182,8 @@ describe('header utils', () => {
...getConfig(),
ENABLE_TAGGING_TAXONOMY_PAGES: 'true',
});
- const actualItemsTitle = renderHook(() => useToolsMenuItems('course-123'), { wrapper: createWrapper() }).result.current.map((item) => item.title);
+ const actualItemsTitle = renderHook(() => useToolsMenuItems('course-123'), { wrapper: createWrapper() }).result
+ .current.map((item) => item.title);
expect(actualItemsTitle).toEqual([
'Import',
'Export Course',
@@ -184,7 +196,8 @@ describe('header utils', () => {
...getConfig(),
ENABLE_TAGGING_TAXONOMY_PAGES: 'false',
});
- const actualItemsTitle = renderHook(() => useToolsMenuItems('course-123'), { wrapper: createWrapper() }).result.current.map((item) => item.title);
+ const actualItemsTitle = renderHook(() => useToolsMenuItems('course-123'), { wrapper: createWrapper() }).result
+ .current.map((item) => item.title);
expect(actualItemsTitle).toEqual([
'Import',
'Export Course',
@@ -196,9 +209,10 @@ describe('header utils', () => {
mockWaffleFlags({
enableCourseOptimizer: true,
});
- const optimizerItem = renderHook(() => useToolsMenuItems('course-123'), { wrapper: createWrapper() }).result.current.find(
- item => item.href === '/course/course-123/optimizer',
- );
+ const optimizerItem = renderHook(() => useToolsMenuItems('course-123'), { wrapper: createWrapper() }).result
+ .current.find(
+ item => item.href === '/course/course-123/optimizer',
+ );
expect(optimizerItem).toBeDefined();
});
@@ -206,14 +220,17 @@ describe('header utils', () => {
mockWaffleFlags({
enableCourseOptimizer: false,
});
- const actualItemsTitle = renderHook(() => useToolsMenuItems('course-123'), { wrapper: createWrapper() }).result.current.map((item) => item.title);
+ const actualItemsTitle = renderHook(() => useToolsMenuItems('course-123'), { wrapper: createWrapper() }).result
+ .current.map((item) => item.title);
expect(actualItemsTitle).not.toContain(messages['header.links.optimizer'].defaultMessage);
});
});
describe('useLibrarySettingsMenuItems', () => {
it('should contain team access url', () => {
- const items = renderHook(() => useLibrarySettingsMenuItems('library-123', false), { wrapper: createWrapper() }).result.current;
+ const items =
+ renderHook(() => useLibrarySettingsMenuItems('library-123', false), { wrapper: createWrapper() }).result
+ .current;
expect(items).toContainEqual({ title: 'Library Team', href: 'http://localhost/?sa=manage-team' });
});
it('should contain admin console url if set', () => {
@@ -221,7 +238,9 @@ describe('header utils', () => {
...getConfig(),
ADMIN_CONSOLE_URL: 'http://admin-console.com',
});
- const items = renderHook(() => useLibrarySettingsMenuItems('library-123', false), { wrapper: createWrapper() }).result.current;
+ const items =
+ renderHook(() => useLibrarySettingsMenuItems('library-123', false), { wrapper: createWrapper() }).result
+ .current;
expect(items).toContainEqual({
title: 'Library Team',
href: 'http://admin-console.com/authz/libraries/library-123',
@@ -232,7 +251,8 @@ describe('header utils', () => {
...getConfig(),
ADMIN_CONSOLE_URL: 'http://admin-console.com',
});
- const items = renderHook(() => useLibrarySettingsMenuItems('library-123', true), { wrapper: createWrapper() }).result.current;
+ const items =
+ renderHook(() => useLibrarySettingsMenuItems('library-123', true), { wrapper: createWrapper() }).result.current;
expect(items).toContainEqual({
title: 'Library Team',
href: 'http://admin-console.com/authz/libraries/library-123',
@@ -242,7 +262,8 @@ describe('header utils', () => {
describe('useLibraryToolsMenuItems', () => {
it('should contain backup and import url', () => {
- const items = renderHook(() => useLibraryToolsMenuItems('course-123'), { wrapper: createWrapper() }).result.current;
+ const items =
+ renderHook(() => useLibraryToolsMenuItems('course-123'), { wrapper: createWrapper() }).result.current;
expect(items).toContainEqual({
href: '/library/course-123/backup',
title: 'Back up to local archive',
diff --git a/src/header/hooks.tsx b/src/header/hooks.tsx
index 6b8112b175..7997cb6566 100644
--- a/src/header/hooks.tsx
+++ b/src/header/hooks.tsx
@@ -26,7 +26,9 @@ export const useContentMenuItems = (courseId: string) => {
title: intl.formatMessage(messages['header.links.outline']),
},
{
- href: waffleFlags.useNewUpdatesPage ? `/course/${courseId}/course_info` : `${studioBaseUrl}/course_info/${courseId}`,
+ href: waffleFlags.useNewUpdatesPage
+ ? `/course/${courseId}/course_info`
+ : `${studioBaseUrl}/course_info/${courseId}`,
title: intl.formatMessage(messages['header.links.updates']),
},
{
@@ -102,8 +104,8 @@ export const useSettingMenuItems = (courseId: string) => {
? [{
href: `/course/${courseId}/settings/advanced`,
title: intl.formatMessage(messages['header.links.advancedSettings']),
- }] : []
- ),
+ }] :
+ []),
];
if (getConfig().ENABLE_CERTIFICATE_PAGE === 'true' || waffleFlags.useNewCertificatesPage) {
items.push({
@@ -132,21 +134,23 @@ export const useToolsMenuItems = (courseId: string) => {
? [{
href: `${studioBaseUrl}/course/${courseId}#export-tags`,
title: intl.formatMessage(messages['header.links.exportTags']),
- }] : []
- ),
+ }] :
+ []),
{
href: `/course/${courseId}/checklists`,
title: intl.formatMessage(messages['header.links.checklists']),
},
- ...(waffleFlags.enableCourseOptimizer ? [{
- href: `/course/${courseId}/optimizer`,
- title: (
- <>
- {intl.formatMessage(messages['header.links.optimizer'])}
- {intl.formatMessage(courseOptimizerMessages.new)}
- >
- ),
- }] : []),
+ ...(waffleFlags.enableCourseOptimizer ?
+ [{
+ href: `/course/${courseId}/optimizer`,
+ title: (
+ <>
+ {intl.formatMessage(messages['header.links.optimizer'])}
+ {intl.formatMessage(courseOptimizerMessages.new)}
+ >
+ ),
+ }] :
+ []),
];
return items;
@@ -194,7 +198,7 @@ export const useLibrarySettingsMenuItems = (itemId: string, readOnly: boolean) =
return null;
};
- const items: { title: string; href: string }[] = [];
+ const items: { title: string; href: string; }[] = [];
const teamAccessUrl = openTeamAccessModalUrl();
if (teamAccessUrl) {
diff --git a/src/help-urls/__mocks__/helpUrls.js b/src/help-urls/__mocks__/helpUrls.js
index cfde6b800f..f1900c5708 100644
--- a/src/help-urls/__mocks__/helpUrls.js
+++ b/src/help-urls/__mocks__/helpUrls.js
@@ -1,21 +1,27 @@
module.exports = {
advanced: 'https://docs.openedx.org/en/latest/educators/navigation/advanced_features.html',
- certificates: 'https://docs.openedx.org/en/latest/educators/navigation/creating_course.html#set-up-course-certificates',
+ certificates:
+ 'https://docs.openedx.org/en/latest/educators/navigation/creating_course.html#set-up-course-certificates',
checklist: 'https://docs.openedx.org/en/latest/educators/quickstarts/build_a_course.html#quick-start-build-a-course',
container: 'https://docs.openedx.org/en/latest/educators/references/course_development/parent_child_components.html',
contentGroups: 'https://docs.openedx.org/en/latest/educators/navigation/advanced_features.html#manage-course-cohorts',
- contentHighlights: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/manage_course_highlight_emails.html#set-course-section-highlights',
- contentLibraries: 'https://docs.openedx.org/en/latest/educators/navigation/content_creation_management.html#work-with-content-libraries',
+ contentHighlights:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/manage_course_highlight_emails.html#set-course-section-highlights',
+ contentLibraries:
+ 'https://docs.openedx.org/en/latest/educators/navigation/content_creation_management.html#work-with-content-libraries',
default: 'https://docs.openedx.org/en/latest/educators/index.html',
developCourse: 'https://docs.openedx.org/en/latest/educators/references/course_content_development.html',
- enrollmentTracks: 'https://docs.openedx.org/en/latest/educators/how-tos/advanced_features/create_content_for_specific_enrollment_tracks.html',
+ enrollmentTracks:
+ 'https://docs.openedx.org/en/latest/educators/how-tos/advanced_features/create_content_for_specific_enrollment_tracks.html',
exportCourse: 'https://docs.openedx.org/en/latest/educators/how-tos/releasing-course/export_course.html',
exportLibrary: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/export_import_library.html',
files: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/manage_course_files.html',
grading: 'https://docs.openedx.org/en/latest/educators/concepts/grading/about_graded_subsections.html',
- groupConfigurations: 'https://docs.openedx.org/en/latest/educators/concepts/advanced_features/about_group_configurations.html',
+ groupConfigurations:
+ 'https://docs.openedx.org/en/latest/educators/concepts/advanced_features/about_group_configurations.html',
home: 'https://docs.openedx.org/en/latest/educators/navigation/content_creation_management.html',
- imageAccessibility: 'https://docs.openedx.org/en/latest/educators/references/imageAccessibility/image_accessibility.html',
+ imageAccessibility:
+ 'https://docs.openedx.org/en/latest/educators/references/imageAccessibility/image_accessibility.html',
importCourse: 'https://docs.openedx.org/en/latest/educators/how-tos/releasing-course/import_course.html',
importLibrary: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/export_import_library.html',
login: 'https://docs.openedx.org/en/latest/educators/quickstarts/build_a_course.html#quick-start-build-a-course',
@@ -24,12 +30,14 @@ module.exports = {
register: 'https://docs.openedx.org/en/latest/educators/quickstarts/build_a_course.html#quick-start-build-a-course',
schedule: 'https://docs.openedx.org/en/latest/educators/references/course_development/about_page.html',
socialSharing: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html',
- teamCourse: 'https://docs.openedx.org/en/latest/educators/references/course_development/course_team_roles.html#guide-to-course-team-roles',
+ teamCourse:
+ 'https://docs.openedx.org/en/latest/educators/references/course_development/course_team_roles.html#guide-to-course-team-roles',
teamLibrary: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/library_access.html',
textbooks: 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/manage_textbooks.html',
unit: 'https://docs.openedx.org/en/latest/educators/concepts/open_edx_platform/about_course_units.html',
updates: 'https://docs.openedx.org/en/latest/educators/concepts/communication/about_course_updates_handouts.html',
- video: 'https://docs.openedx.org/en/latest/educators/navigation/content_creation_management.html#manage-video-components',
+ video:
+ 'https://docs.openedx.org/en/latest/educators/navigation/content_creation_management.html#manage-video-components',
visibility: 'https://docs.openedx.org/en/latest/educators/references/controlling_content_visibility.html',
welcome: 'https://docs.openedx.org/en/latest/educators/quickstarts/build_a_course.html#quick-start-build-a-course',
};
diff --git a/src/help-urls/hooks.tsx b/src/help-urls/hooks.tsx
index eaef5dd26d..762fb8516c 100644
--- a/src/help-urls/hooks.tsx
+++ b/src/help-urls/hooks.tsx
@@ -2,7 +2,7 @@ import { HelpUrls } from './data/api';
import { useAllHelpUrls } from './data/apiHooks';
const useHelpUrls = (tokenNames: T & (keyof HelpUrls)[]): {
- [K in T[number]]?: K extends keyof HelpUrls ? string : null
+ [K in T[number]]?: K extends keyof HelpUrls ? string : null;
} => {
const {
data: pages,
diff --git a/src/hooks.ts b/src/hooks.ts
index a1bdb11897..488a048e09 100644
--- a/src/hooks.ts
+++ b/src/hooks.ts
@@ -11,7 +11,7 @@ import { history } from '@edx/frontend-platform';
import { useLocation, useSearchParams } from 'react-router-dom';
import { isEqual } from 'lodash';
-export const useScrollToHashElement = ({ isLoading }: { isLoading: boolean }) => {
+export const useScrollToHashElement = ({ isLoading }: { isLoading: boolean; }) => {
const [elementWithHash, setElementWithHash] = useState(null);
const { pathname } = useLocation();
@@ -31,7 +31,7 @@ export const useScrollToHashElement = ({ isLoading }: { isLoading: boolean }) =>
return { elementWithHash };
};
-export const useEscapeClick = ({ onEscape, dependency }: { onEscape: () => void, dependency: any }) => {
+export const useEscapeClick = ({ onEscape, dependency }: { onEscape: () => void; dependency: any; }) => {
useEffect(() => {
const handleEscapeClick = (event: KeyboardEvent) => {
if (event.key === 'Escape') {
@@ -83,7 +83,7 @@ export const useLoadOnScroll = (
window.removeEventListener('scroll', onscroll);
};
}
- return () => { };
+ return () => {};
}, [hasNextPage, isFetchingNextPage, fetchNextPage]);
};
@@ -155,18 +155,18 @@ export function useStateWithUrlSearchParam(
// Update the url search parameter using:
type ReturnSetterParams = (
// a Type value
- value?: Type | Type[]
- // or a function that returns a Type from the previous returnValue
- | ((value: Type | Type[]) => Type | Type[])
+ value?:
+ | Type
+ | Type[]
+ // or a function that returns a Type from the previous returnValue
+ | ((value: Type | Type[]) => Type | Type[]),
) => void;
const returnSetter: Dispatch> = useCallback((value) => {
setSearchParams((/* previous -- see STATE WORKAROUND above */) => {
const useValue = value instanceof Function ? value(returnValue) : value;
- const paramValue: string | string[] | undefined = (
- useValue instanceof Array
- ? useValue.map(toString).filter((v) => v !== undefined) as string[]
- : toString(useValue)
- );
+ const paramValue: string | string[] | undefined = useValue instanceof Array
+ ? useValue.map(toString).filter((v) => v !== undefined) as string[]
+ : toString(useValue);
const newSearchParams = new URLSearchParams(locationRef.current.search);
if (paramValue === undefined || paramValue === defaultValue) {
@@ -217,7 +217,10 @@ export function useStickyState(
}
export function useToggleWithValue(defaultValue?: T): [
- isDefined: boolean, value: T | undefined, define: ((val: T) => void), undefine: () => void,
+ isDefined: boolean,
+ value: T | undefined,
+ define: ((val: T) => void),
+ undefine: () => void,
] {
const [value, setValue] = useState(defaultValue);
const define = useCallback((val: T) => {
diff --git a/src/import-page/CourseImportContext.tsx b/src/import-page/CourseImportContext.tsx
index 696dfb504a..66cf521438 100644
--- a/src/import-page/CourseImportContext.tsx
+++ b/src/import-page/CourseImportContext.tsx
@@ -1,5 +1,9 @@
import {
- createContext, useContext, useEffect, useMemo, useState,
+ createContext,
+ useContext,
+ useEffect,
+ useMemo,
+ useState,
} from 'react';
import moment from 'moment';
import Cookies from 'universal-cookie';
@@ -106,7 +110,9 @@ export const CourseImportProvider = ({ children }: CourseImportProviderProps) =>
const errorMessage = importStatusData?.message;
const anyRequestFailed = isErrorImportStatus || importMutation.isError || Boolean(errorMessage);
const anyRequestInProgress = isPendingImportStatus || importMutation.isPending;
- const formattedErrorMessage = anyRequestFailed ? errorMessage || intl.formatMessage(messages.defaultErrorMessage) : '';
+ const formattedErrorMessage = anyRequestFailed
+ ? errorMessage || intl.formatMessage(messages.defaultErrorMessage)
+ : '';
const isLoadingDenied = importStatusError?.response?.status === 403;
useEffect(() => {
diff --git a/src/import-page/CourseImportPage.test.tsx b/src/import-page/CourseImportPage.test.tsx
index 481d0e51b2..e4ad9dbb16 100644
--- a/src/import-page/CourseImportPage.test.tsx
+++ b/src/import-page/CourseImportPage.test.tsx
@@ -25,13 +25,14 @@ jest.mock('universal-cookie', () => {
return jest.fn(() => Cookie);
});
-const renderComponent = () => render(
-
-
-
-
- ,
-);
+const renderComponent = () =>
+ render(
+
+
+
+
+ ,
+ );
describe(' ', () => {
beforeEach(() => {
diff --git a/src/import-page/CourseImportPage.tsx b/src/import-page/CourseImportPage.tsx
index 0f9b75a367..a24d7b3d87 100644
--- a/src/import-page/CourseImportPage.tsx
+++ b/src/import-page/CourseImportPage.tsx
@@ -1,6 +1,7 @@
import { useIntl } from '@edx/frontend-platform/i18n';
import {
- Container, Layout,
+ Container,
+ Layout,
} from '@openedx/paragon';
import { Helmet } from 'react-helmet';
diff --git a/src/import-page/data/api.ts b/src/import-page/data/api.ts
index c2f24513b6..5e12edea3c 100644
--- a/src/import-page/data/api.ts
+++ b/src/import-page/data/api.ts
@@ -6,8 +6,8 @@ export const postImportCourseApiUrl = (courseId) => `${getApiBaseUrl()}/import/$
export const getImportStatusApiUrl = (courseId, fileName) => `${getApiBaseUrl()}/import_status/${courseId}/${fileName}`;
export interface ImportStatusData {
- importStatus: number,
- message?: string,
+ importStatus: number;
+ message?: string;
}
/**
diff --git a/src/import-page/file-section/FileSection.test.tsx b/src/import-page/file-section/FileSection.test.tsx
index acacd512d3..bd8de7b9a1 100644
--- a/src/import-page/file-section/FileSection.test.tsx
+++ b/src/import-page/file-section/FileSection.test.tsx
@@ -16,13 +16,14 @@ const courseId = '123';
let axiosMock;
-const renderComponent = () => render(
-
-
-
-
- ,
-);
+const renderComponent = () =>
+ render(
+
+
+
+
+ ,
+ );
describe(' ', () => {
beforeEach(() => {
diff --git a/src/import-page/import-stepper/ImportStepper.test.tsx b/src/import-page/import-stepper/ImportStepper.test.tsx
index a419269029..95e372309f 100644
--- a/src/import-page/import-stepper/ImportStepper.test.tsx
+++ b/src/import-page/import-stepper/ImportStepper.test.tsx
@@ -4,13 +4,14 @@ import messages from './messages';
import ImportStepper from './ImportStepper';
import { CourseImportProvider } from '../CourseImportContext';
-const renderComponent = () => render(
-
-
-
-
- ,
-);
+const renderComponent = () =>
+ render(
+
+
+
+
+ ,
+ );
describe(' ', () => {
beforeEach(() => {
diff --git a/src/import-page/import-stepper/ImportStepper.tsx b/src/import-page/import-stepper/ImportStepper.tsx
index fe72a3a369..9beafb2fb5 100644
--- a/src/import-page/import-stepper/ImportStepper.tsx
+++ b/src/import-page/import-stepper/ImportStepper.tsx
@@ -21,20 +21,23 @@ const ImportStepper = () => {
successDate,
} = useCourseImportContext();
- const handleRedirectCourseOutline = () => window.location.replace(`${getConfig().STUDIO_BASE_URL}/course/${courseId}`);
+ const handleRedirectCourseOutline = () =>
+ window.location.replace(`${getConfig().STUDIO_BASE_URL}/course/${courseId}`);
const successTitle = intl.formatMessage(messages.stepperSuccessTitle);
let successTitleComponent;
- const localizedSuccessDate = successDate ? (
-
- ) : null;
+ const localizedSuccessDate = successDate ?
+ (
+
+ ) :
+ null;
if (localizedSuccessDate && currentStage === IMPORT_STAGES.SUCCESS) {
successTitleComponent = (
<>
@@ -48,19 +51,23 @@ const ImportStepper = () => {
title: intl.formatMessage(messages.stepperUploadingTitle),
description: intl.formatMessage(messages.stepperUploadingDescription),
key: IMPORT_STAGES.UPLOADING,
- }, {
+ },
+ {
title: intl.formatMessage(messages.stepperUnpackingTitle),
description: intl.formatMessage(messages.stepperUnpackingDescription),
key: IMPORT_STAGES.UNPACKING,
- }, {
+ },
+ {
title: intl.formatMessage(messages.stepperVerifyingTitle),
description: intl.formatMessage(messages.stepperVerifyingDescription),
key: IMPORT_STAGES.VERIFYING,
- }, {
+ },
+ {
title: intl.formatMessage(messages.stepperUpdatingTitle),
description: intl.formatMessage(messages.stepperUpdatingDescription),
key: IMPORT_STAGES.UPDATING,
- }, {
+ },
+ {
title: successTitle,
description: intl.formatMessage(messages.stepperSuccessDescription),
key: IMPORT_STAGES.SUCCESS,
@@ -79,7 +86,9 @@ const ImportStepper = () => {
errorMessage={formattedErrorMessage}
/>
{currentStage === IMPORT_STAGES.SUCCESS && (
- {intl.formatMessage(messages.viewOutlineButton)}
+
+ {intl.formatMessage(messages.viewOutlineButton)}
+
)}
);
diff --git a/src/index.jsx b/src/index.jsx
index 671d627f57..b62a9e58cf 100755
--- a/src/index.jsx
+++ b/src/index.jsx
@@ -1,11 +1,20 @@
import {
- APP_INIT_ERROR, APP_READY, subscribe, initialize, mergeConfig, getConfig, getPath,
+ APP_INIT_ERROR,
+ APP_READY,
+ subscribe,
+ initialize,
+ mergeConfig,
+ getConfig,
+ getPath,
} from '@edx/frontend-platform';
import { AppProvider, ErrorPage } from '@edx/frontend-platform/react';
import React, { StrictMode, useEffect } from 'react';
import { createRoot } from 'react-dom/client';
import {
- Route, createRoutesFromElements, createBrowserRouter, RouterProvider,
+ Route,
+ createRoutesFromElements,
+ createBrowserRouter,
+ RouterProvider,
} from 'react-router-dom';
import {
QueryClient,
@@ -73,22 +82,22 @@ const App = () => {
} />
- )}
+ }
/>
- )}
+ }
/>
} />
} />
@@ -171,7 +180,8 @@ initialize({
NOTIFICATION_FEEDBACK_URL: process.env.NOTIFICATION_FEEDBACK_URL || null,
ENABLE_UNIT_PAGE: process.env.ENABLE_UNIT_PAGE || 'false',
ENABLE_ASSETS_PAGE: process.env.ENABLE_ASSETS_PAGE || 'false',
- ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN: process.env.ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN || 'false',
+ ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN:
+ process.env.ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN || 'false',
ENABLE_CERTIFICATE_PAGE: process.env.ENABLE_CERTIFICATE_PAGE || 'false',
ENABLE_COURSE_IMPORT_IN_LIBRARY: process.env.ENABLE_COURSE_IMPORT_IN_LIBRARY || 'false',
ENABLE_UNIT_PAGE_NEW_DESIGN: process.env.ENABLE_UNIT_PAGE_NEW_DESIGN || 'false',
@@ -179,7 +189,8 @@ initialize({
ENABLE_TAGGING_TAXONOMY_PAGES: process.env.ENABLE_TAGGING_TAXONOMY_PAGES || 'false',
ENABLE_CHECKLIST_QUALITY: process.env.ENABLE_CHECKLIST_QUALITY || 'true',
ENABLE_GRADING_METHOD_IN_PROBLEMS: process.env.ENABLE_GRADING_METHOD_IN_PROBLEMS === 'true',
- LIBRARY_UNSUPPORTED_BLOCKS: (process.env.LIBRARY_UNSUPPORTED_BLOCKS || 'conditional,step-builder,problem-builder').split(','),
+ LIBRARY_UNSUPPORTED_BLOCKS:
+ (process.env.LIBRARY_UNSUPPORTED_BLOCKS || 'conditional,step-builder,problem-builder').split(','),
COURSE_TEAM_SUPPORT_EMAIL: process.env.COURSE_TEAM_SUPPORT_EMAIL || null,
ADMIN_CONSOLE_URL: process.env.ADMIN_CONSOLE_URL || null,
}, 'CourseAuthoringConfig');
diff --git a/src/legacy-libraries-migration/ConfirmationView.tsx b/src/legacy-libraries-migration/ConfirmationView.tsx
index 99acf23c33..33a883bbf7 100644
--- a/src/legacy-libraries-migration/ConfirmationView.tsx
+++ b/src/legacy-libraries-migration/ConfirmationView.tsx
@@ -29,18 +29,18 @@ const ConfirmationCard = ({
}: ConfirmationCardProps) => (
{legacyLib.displayName}
- )}
- subtitle={(
+ }
+ subtitle={
{destinationName}
- )}
+ }
/>
{legacyLib.isMigrated && (
diff --git a/src/legacy-libraries-migration/LegacyLibMigrationPage.test.tsx b/src/legacy-libraries-migration/LegacyLibMigrationPage.test.tsx
index a18906652a..cc3bdd5918 100644
--- a/src/legacy-libraries-migration/LegacyLibMigrationPage.test.tsx
+++ b/src/legacy-libraries-migration/LegacyLibMigrationPage.test.tsx
@@ -244,9 +244,11 @@ describe(' ', () => {
await user.click(nextButton);
const alert = await screen.findByRole('alert');
- expect(await within(alert).findByText(
- /All content from the legacy library you selected will be migrated to/,
- )).toBeInTheDocument();
+ expect(
+ await within(alert).findByText(
+ /All content from the legacy library you selected will be migrated to/,
+ ),
+ ).toBeInTheDocument();
const backButton = screen.getByRole('button', { name: /back/i });
await user.click(backButton);
@@ -353,9 +355,11 @@ describe(' ', () => {
// Should show alert of ConfirmationView
const alert = await screen.findByRole('alert');
- expect(await within(alert).findByText(
- /All content from the 3 legacy libraries you selected will be migrated to/,
- )).toBeInTheDocument();
+ expect(
+ await within(alert).findByText(
+ /All content from the 3 legacy libraries you selected will be migrated to/,
+ ),
+ ).toBeInTheDocument();
expect(screen.getByText('MBA')).toBeInTheDocument();
expect(screen.getByText('Legacy library 1')).toBeInTheDocument();
expect(screen.getByText('MBA 1')).toBeInTheDocument();
@@ -410,10 +414,12 @@ describe(' ', () => {
// Should show alert of ConfirmationView
const alert = await screen.findByRole('alert');
- expect(await within(alert).findByText(
- /All content from the 3 legacy libraries you selected will be migrated to/,
- { exact: false },
- )).toBeInTheDocument();
+ expect(
+ await within(alert).findByText(
+ /All content from the 3 legacy libraries you selected will be migrated to/,
+ { exact: false },
+ ),
+ ).toBeInTheDocument();
expect(screen.getByText('MBA')).toBeInTheDocument();
expect(screen.getByText('Legacy library 1')).toBeInTheDocument();
expect(screen.getByText('MBA 1')).toBeInTheDocument();
diff --git a/src/legacy-libraries-migration/LegacyLibMigrationPage.tsx b/src/legacy-libraries-migration/LegacyLibMigrationPage.tsx
index ebd6637d89..c0777d004e 100644
--- a/src/legacy-libraries-migration/LegacyLibMigrationPage.tsx
+++ b/src/legacy-libraries-migration/LegacyLibMigrationPage.tsx
@@ -37,8 +37,8 @@ const ExitModal = ({
isExitModalOpen,
closeExitModal,
}: {
- isExitModalOpen: boolean,
- closeExitModal: () => void,
+ isExitModalOpen: boolean;
+ closeExitModal: () => void;
}) => {
const intl = useIntl();
const navigate = useNavigate();
@@ -229,22 +229,24 @@ export const LegacyLibMigrationPage = () => {
? intl.formatMessage(messages.cancel)
: intl.formatMessage(messages.back)}
- {currentStep !== 'confirmation-view' ? (
-
- {intl.formatMessage(messages.next)}
-
- ) : (
-
- )}
+ {currentStep !== 'confirmation-view' ?
+ (
+
+ {intl.formatMessage(messages.next)}
+
+ ) :
+ (
+
+ )}
diff --git a/src/library-authoring/EmptyStates.tsx b/src/library-authoring/EmptyStates.tsx
index 8fcc3c7ba4..36bc7c8ecf 100644
--- a/src/library-authoring/EmptyStates.tsx
+++ b/src/library-authoring/EmptyStates.tsx
@@ -1,7 +1,8 @@
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import type { MessageDescriptor } from 'react-intl';
import {
- Button, Stack,
+ Button,
+ Stack,
} from '@openedx/paragon';
import { Add } from '@openedx/paragon/icons';
import { ClearFiltersButton } from '../search-manager';
diff --git a/src/library-authoring/LibraryAuthoringPage.test.tsx b/src/library-authoring/LibraryAuthoringPage.test.tsx
index 9406cc7f02..53a75d6f6c 100644
--- a/src/library-authoring/LibraryAuthoringPage.test.tsx
+++ b/src/library-authoring/LibraryAuthoringPage.test.tsx
@@ -41,7 +41,7 @@ const searchEndpoint = 'http://mock.meilisearch.local/multi-search';
/**
* Returns 0 components from the search query.
-*/
+ */
const returnEmptyResult = (_url, req) => {
const requestData = JSON.parse(req.body?.toString() ?? '');
const query = requestData?.queries[0]?.q ?? '';
@@ -50,7 +50,9 @@ const returnEmptyResult = (_url, req) => {
mockEmptyResult.results[0].query = query;
// And fake the required '_formatted' fields; it contains the highlighting ... around matched words
// eslint-disable-next-line no-underscore-dangle, no-param-reassign
- mockEmptyResult.results[0]?.hits.forEach((hit) => { hit._formatted = { ...hit }; });
+ mockEmptyResult.results[0]?.hits.forEach((hit) => {
+ hit._formatted = { ...hit };
+ });
return mockEmptyResult;
};
@@ -80,7 +82,9 @@ describe(' ', () => {
newMockResult.results[0].query = query;
// And fake the required '_formatted' fields; it contains the highlighting ... around matched words
// eslint-disable-next-line no-underscore-dangle, no-param-reassign
- newMockResult.results[0]?.hits.forEach((hit) => { hit._formatted = { ...hit }; });
+ newMockResult.results[0]?.hits.forEach((hit) => {
+ hit._formatted = { ...hit };
+ });
return newMockResult;
});
});
@@ -94,7 +98,9 @@ describe(' ', () => {
// Ensure the search endpoint is called:
// Call 1: To fetch searchable/filterable/sortable library data
- await waitFor(() => { expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post'); });
+ await waitFor(() => {
+ expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post');
+ });
};
it('shows the spinner before the query is complete', () => {
@@ -192,7 +198,9 @@ describe(' ', () => {
// Update search mock so it returns no results:
fetchMock.post(searchEndpoint, returnEmptyResult, { overwriteRoutes: true });
render( , { path, params: { libraryId } });
- await waitFor(() => { expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post'); });
+ await waitFor(() => {
+ expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post');
+ });
expect(await screen.findByText('Content library')).toBeInTheDocument();
expect(screen.getByText('You have not added any content to this library yet.')).toBeInTheDocument();
@@ -208,13 +216,17 @@ describe(' ', () => {
expect(await screen.findByText('Content library')).toBeInTheDocument();
expect((await screen.findAllByText(libraryTitle))[0]).toBeInTheDocument();
- await waitFor(() => { expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post'); });
+ await waitFor(() => {
+ expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post');
+ });
fireEvent.change(screen.getByRole('searchbox'), { target: { value: 'noresults' } });
// Ensure the search endpoint is called again, only once more since the recently modified call
// should not be impacted by the search
- await waitFor(() => { expect(fetchMock).toHaveFetchedTimes(2, searchEndpoint, 'post'); });
+ await waitFor(() => {
+ expect(fetchMock).toHaveFetchedTimes(2, searchEndpoint, 'post');
+ });
expect(await screen.findByText('No matching components found in this library.')).toBeInTheDocument();
@@ -337,7 +349,7 @@ describe(' ', () => {
expect(await screen.findByTitle('Sort search results')).toBeInTheDocument();
- const testSortOption = (async (optionText, sortBy, isDefault) => {
+ const testSortOption = async (optionText, sortBy, isDefault) => {
// Open the drop-down menu
fireEvent.click(screen.getByTitle('Sort search results'));
@@ -372,7 +384,7 @@ describe(' ', () => {
// Is the selected sort option shown in the toggle button (if not default)
// as well as in the drop-down menu?
expect(screen.getAllByText(optionText).length).toEqual(isDefault ? 1 : 2);
- });
+ };
await testSortOption('Title, A-Z', 'display_name:asc', false);
await testSortOption('Title, Z-A', 'display_name:desc', false);
@@ -479,7 +491,7 @@ describe(' ', () => {
await renderLibraryPage();
// Click on the first collection
- fireEvent.click((await screen.findByText('Collection 1')));
+ fireEvent.click(await screen.findByText('Collection 1'));
const sidebar = screen.getByTestId('library-sidebar');
@@ -498,7 +510,7 @@ describe(' ', () => {
await renderLibraryPage();
// Click on the first unit
- fireEvent.click((await screen.findByText('Test Unit')));
+ fireEvent.click(await screen.findByText('Test Unit'));
const sidebar = screen.getByTestId('library-sidebar');
@@ -517,7 +529,7 @@ describe(' ', () => {
await renderLibraryPage();
// Click on the first collection
- fireEvent.click((await screen.findByText('Collection 1')));
+ fireEvent.click(await screen.findByText('Collection 1'));
// Click on the Details tab
fireEvent.click(screen.getByRole('tab', { name: 'Details' }));
@@ -532,7 +544,7 @@ describe(' ', () => {
fireEvent.click(screen.getByRole('tab', { name: 'Preview' }));
// Switch back to the collection
- fireEvent.click((await screen.findByText('Collection 1')));
+ fireEvent.click(await screen.findByText('Collection 1'));
// The Details (default) tab should be selected because the collection does not have a Preview tab
expect(screen.getByRole('tab', { name: 'Details' })).toHaveAttribute('aria-selected', 'true');
@@ -550,13 +562,17 @@ describe(' ', () => {
await renderLibraryPage();
// Ensure the search endpoint is called
- await waitFor(() => { expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post'); });
+ await waitFor(() => {
+ expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post');
+ });
const filterButton = screen.getByRole('button', { name: /type/i });
fireEvent.click(filterButton);
const problemFilterCheckbox = screen.getByRole('checkbox', { name: /problem/i });
const problemFilterMenuItem = problemFilterCheckbox.parentElement; // div.pgn__menu-item
- const showProbTypesSubmenuBtn = problemFilterMenuItem!.querySelector('button[aria-label="Open problem types filters"]');
+ const showProbTypesSubmenuBtn = problemFilterMenuItem!.querySelector(
+ 'button[aria-label="Open problem types filters"]',
+ );
expect(showProbTypesSubmenuBtn).not.toBeNull();
fireEvent.click(showProbTypesSubmenuBtn!);
@@ -586,7 +602,9 @@ describe(' ', () => {
await renderLibraryPage();
// Ensure the search endpoint is called
- await waitFor(() => { expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post'); });
+ await waitFor(() => {
+ expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post');
+ });
const filterButton = screen.getByRole('button', { name: /type/i });
fireEvent.click(filterButton);
@@ -817,7 +835,9 @@ describe(' ', () => {
expect(axiosMock.history.post[0].url).toBe(url);
expect(axiosMock.history.post[0].data).toContain(`"display_name":"${title}"`);
expect(axiosMock.history.post[0].data).toContain(`"container_type":"${containerType}"`);
- expect(mockShowToast).toHaveBeenCalledWith(expect.stringMatching(new RegExp(`${containerType} created successfully`, 'i')));
+ expect(mockShowToast).toHaveBeenCalledWith(
+ expect.stringMatching(new RegExp(`${containerType} created successfully`, 'i')),
+ );
});
test.each([
@@ -1076,7 +1096,9 @@ describe(' ', () => {
},
});
- await waitFor(() => expect(mockShowToast).toHaveBeenCalledWith('The migration of legacy libraries has been completed successfully.'));
+ await waitFor(() =>
+ expect(mockShowToast).toHaveBeenCalledWith('The migration of legacy libraries has been completed successfully.')
+ );
});
it('Should show fail in migration legacy libraries', async () => {
@@ -1115,6 +1137,8 @@ describe(' ', () => {
},
});
- await waitFor(() => expect(mockShowToast).toHaveBeenCalledWith('The legacy library with this key has failed: legacy-lib-1'));
+ await waitFor(() =>
+ expect(mockShowToast).toHaveBeenCalledWith('The legacy library with this key has failed: legacy-lib-1')
+ );
});
});
diff --git a/src/library-authoring/LibraryAuthoringPage.tsx b/src/library-authoring/LibraryAuthoringPage.tsx
index ffbbdbc290..29f71acfaf 100644
--- a/src/library-authoring/LibraryAuthoringPage.tsx
+++ b/src/library-authoring/LibraryAuthoringPage.tsx
@@ -107,7 +107,7 @@ const HeaderActions = () => {
);
};
-export const SubHeaderTitle = ({ title }: { title: ReactNode }) => {
+export const SubHeaderTitle = ({ title }: { title: ReactNode; }) => {
const intl = useIntl();
const { readOnly } = useOptionalLibraryContext();
@@ -281,17 +281,19 @@ const LibraryAuthoringPage = ({
return ;
}
- const breadcumbs = componentPickerMode && !restrictToLibrary ? (
-
- ) : undefined;
+ const breadcumbs = componentPickerMode && !restrictToLibrary ?
+ (
+
+ ) :
+ undefined;
const extraFilter: string[] = [];
if (libraryId) {
@@ -327,11 +329,9 @@ const LibraryAuthoringPage = ({
// Disable filtering by block/problem type when viewing the Collections/Units/Sections/Subsections tab,
// or when inside a specific Section or Subsection.
- const onlyOneType = (
- insideCollections || insideUnits || insideSections || insideSubsections
- || insideSection || insideSubsection
- || !([ContentType.home, ContentType.components].includes(activeKey))
- );
+ const onlyOneType = insideCollections || insideUnits || insideSections || insideSubsections
+ || insideSection || insideSubsection
+ || !([ContentType.home, ContentType.components].includes(activeKey));
const overrideTypesFilter = onlyOneType
? new TypesFilterData()
: undefined;
@@ -354,22 +354,24 @@ const LibraryAuthoringPage = ({
{libraryData
&& (
- <>
-
{libraryData.title} | {process.env.SITE_NAME}
- {!componentPickerMode && (
-
- )}
- >
+ <>
+
+ {libraryData.title} | {process.env.SITE_NAME}
+
+ {!componentPickerMode && (
+
+ )}
+ >
)}
{libraryData
&& (
- }
- subtitle={!componentPickerMode ? intl.formatMessage(messages.headingSubtitle) : undefined}
- breadcrumbs={breadcumbs}
- headerActions={ }
- hideBorder
- />
+ }
+ subtitle={!componentPickerMode ? intl.formatMessage(messages.headingSubtitle) : undefined}
+ breadcrumbs={breadcumbs}
+ headerActions={ }
+ hideBorder
+ />
)}
{visibleTabs.length > 1 && (
void;
+ onBlockNotification?: (event: { eventType: string; [key: string]: any; }) => void;
usageKey: string;
version?: VersionSpec;
view?: string;
scrolling?: string;
minHeight?: string;
scrollIntoView?: boolean;
- showTitle?: boolean,
+ showTitle?: boolean;
}
/**
* React component that displays an XBlock in a sandboxed IFrame.
@@ -91,7 +91,10 @@ export const LibraryBlock = ({
loading="lazy"
referrerPolicy="origin"
style={{
- width: '100%', height: iframeHeight, pointerEvents: 'auto', minHeight,
+ width: '100%',
+ height: iframeHeight,
+ pointerEvents: 'auto',
+ minHeight,
}}
allow={IFRAME_FEATURE_POLICY}
allowFullScreen
diff --git a/src/library-authoring/LibraryContent.test.tsx b/src/library-authoring/LibraryContent.test.tsx
index f9deb418c0..dd71aa53f1 100644
--- a/src/library-authoring/LibraryContent.test.tsx
+++ b/src/library-authoring/LibraryContent.test.tsx
@@ -42,7 +42,9 @@ const returnEmptyResult = (_url: string, req) => {
mockEmptyResult.results[0].query = query;
// And fake the required '_formatted' fields; it contains the highlighting ... around matched words
// eslint-disable-next-line no-underscore-dangle, no-param-reassign
- mockEmptyResult.results[0]?.hits.forEach((hit: any) => { hit._formatted = { ...hit }; });
+ mockEmptyResult.results[0]?.hits.forEach((hit: any) => {
+ hit._formatted = { ...hit };
+ });
return mockEmptyResult;
};
@@ -53,7 +55,7 @@ jest.mock('@src/search-manager', () => ({
}));
const withLibraryId = (libraryId: string) => ({
- extraWrapper: ({ children }: { children: React.ReactNode }) => (
+ extraWrapper: ({ children }: { children: React.ReactNode; }) => (
{children}
@@ -120,12 +122,14 @@ describe(' ', () => {
{
sourceKey: 'block-v1:UNIX+UX2+2025_T2+type@library_content+block@test_lib_content',
targetKey: null,
- unsupportedReason: 'The "library_content" XBlock (ID: "test_lib_content") has children, so it is not supported in content libraries. It has 2 children blocks.',
+ unsupportedReason:
+ 'The "library_content" XBlock (ID: "test_lib_content") has children, so it is not supported in content libraries. It has 2 children blocks.',
},
{
sourceKey: 'block-v1:UNIX+UX2+2025_T2+type@conditional+block@test_conditional',
targetKey: null,
- unsupportedReason: 'The "conditional" XBlock (ID: "test_conditional") has children, so it is not supported in content libraries. It has 2 children blocks.',
+ unsupportedReason:
+ 'The "conditional" XBlock (ID: "test_conditional") has children, so it is not supported in content libraries. It has 2 children blocks.',
},
]);
(useGetContentHits as jest.Mock).mockReturnValue({
diff --git a/src/library-authoring/LibraryContent.tsx b/src/library-authoring/LibraryContent.tsx
index fa20658e16..abf7b599c2 100644
--- a/src/library-authoring/LibraryContent.tsx
+++ b/src/library-authoring/LibraryContent.tsx
@@ -18,7 +18,7 @@ import PlaceholderCard from './import-course/PlaceholderCard';
*
* Use content to:
* - 'collections': Suggest to create a collection on empty state.
-* - Anything else to suggest to add content on empty state.
+ * - Anything else to suggest to add content on empty state.
*/
type LibraryContentProps = {
diff --git a/src/library-authoring/LibraryLayout.tsx b/src/library-authoring/LibraryLayout.tsx
index 5dee9176cf..1ec0d61bd7 100644
--- a/src/library-authoring/LibraryLayout.tsx
+++ b/src/library-authoring/LibraryLayout.tsx
@@ -25,7 +25,9 @@ import { ImportDetailsPage } from './import-course/ImportDetailsPage';
const LibraryLayoutWrapper: React.FC = ({ children }) => {
const {
- libraryId, collectionId, containerId,
+ libraryId,
+ collectionId,
+ containerId,
} = useParams();
if (libraryId === undefined) {
@@ -36,9 +38,9 @@ const LibraryLayoutWrapper: React.FC = ({ children }) =
return (
({ a11ycheckerCs
const { libraryId } = mockContentLibrary;
const render = (collectionId?: string) => {
- const params: { libraryId: string, collectionId?: string } = { libraryId, collectionId };
+ const params: { libraryId: string; collectionId?: string; } = { libraryId, collectionId };
return baseRender( , {
path: '/library/:libraryId/collection/:collectionId?',
params,
@@ -45,14 +45,14 @@ const render = (collectionId?: string) => {
- { children }
+ {children}
),
});
};
const renderWithContainer = (containerId: string, containerType: 'unit' | 'section' | 'subsection' = 'unit') => {
- const params: { libraryId: string, containerId?: string } = { libraryId, containerId };
+ const params: { libraryId: string; containerId?: string; } = { libraryId, containerId };
return baseRender( , {
path: `/library/:libraryId/${containerType}/:containerId?`,
params,
@@ -60,7 +60,7 @@ const renderWithContainer = (containerId: string, containerType: 'unit' | 'secti
- { children }
+ {children}
),
@@ -319,7 +319,10 @@ describe(' ', () => {
buttonName: /paste from clipboard/i,
},
])('$label', async ({
- mockUrl, mockResponse, buttonName, expectedError,
+ mockUrl,
+ mockResponse,
+ buttonName,
+ expectedError,
}) => {
userEvent.setup();
axiosMock.onPost(mockUrl).reply(400, mockResponse);
diff --git a/src/library-authoring/add-content/AddContent.tsx b/src/library-authoring/add-content/AddContent.tsx
index 73430997a8..dd6933f4d6 100644
--- a/src/library-authoring/add-content/AddContent.tsx
+++ b/src/library-authoring/add-content/AddContent.tsx
@@ -37,33 +37,33 @@ import { messages, getContentMessages } from './messages';
import type { BlockTypeMetadata } from '../data/api';
type ContentType = {
- name: string,
- disabled?: boolean,
- icon?: React.ComponentType,
- blockType: string,
+ name: string;
+ disabled?: boolean;
+ icon?: React.ComponentType;
+ blockType: string;
};
type AddContentButtonProps = {
- contentType: ContentType,
- onCreateContent: (blockType: string) => void,
+ contentType: ContentType;
+ onCreateContent: (blockType: string) => void;
};
type AddContentViewProps = {
- contentTypes: ContentType[],
- onCreateContent: (blockType: string) => void,
- isAddLibraryContentModalOpen: boolean,
- closeAddLibraryContentModal: () => void,
- isComponentPicker?: boolean,
+ contentTypes: ContentType[];
+ onCreateContent: (blockType: string) => void;
+ isAddLibraryContentModalOpen: boolean;
+ closeAddLibraryContentModal: () => void;
+ isComponentPicker?: boolean;
};
type AddAdvancedContentViewProps = {
- closeAdvancedList: () => void,
- onCreateContent: (blockType: string) => void,
- advancedBlocks: Record,
- isBlockTypeEnabled: (blockType: string) => boolean,
+ closeAdvancedList: () => void;
+ onCreateContent: (blockType: string) => void;
+ advancedBlocks: Record;
+ isBlockTypeEnabled: (blockType: string) => boolean;
};
-const AddContentButton = ({ contentType, onCreateContent } : AddContentButtonProps) => {
+const AddContentButton = ({ contentType, onCreateContent }: AddContentButtonProps) => {
const {
name,
disabled = false,
@@ -174,9 +174,7 @@ const AddContentView = ({
onCreateContent={onCreateContent}
/>
));
- const separator = (
-
- );
+ const separator = ;
// Extract the paste button for use on Section and Subsection
const pasteButton = componentButtons.find(ct => ct.key === 'add-content-paste');
@@ -261,18 +259,20 @@ const AddAdvancedContentView = ({
{sortedBlockTypes.map((blockType) => (
- isBlockTypeEnabled(blockType) ? (
-
- ) : null
+ isBlockTypeEnabled(blockType) ?
+ (
+
+ ) :
+ null
))}
>
);
@@ -341,10 +341,11 @@ const AddContent = () => {
// We use block types data from backend to verify the enabled basic and advanced blocks.
// Also, we use that data to get the translated display name of the block.
const { data: blockTypesDataList } = useBlockTypesMetadata(libraryId);
- const blockTypesData = useMemo(() => blockTypesDataList?.reduce((acc, block) => {
- acc[block.blockType] = block;
- return acc;
- }, {}), [blockTypesDataList]);
+ const blockTypesData = useMemo(() =>
+ blockTypesDataList?.reduce((acc, block) => {
+ acc[block.blockType] = block;
+ return acc;
+ }, {}), [blockTypesDataList]);
const isBlockTypeEnabled = (blockType: string) => !getConfig().LIBRARY_UNSUPPORTED_BLOCKS.includes(blockType);
@@ -376,13 +377,16 @@ const AddContent = () => {
},
];
- const isBasicBlock = (blockType: string) => contentTypes.some(
- content => content.blockType === blockType,
- );
+ const isBasicBlock = (blockType: string) =>
+ contentTypes.some(
+ content => content.blockType === blockType,
+ );
- const advancedBlocks = useMemo(() => (blockTypesData ? Object.fromEntries(
- Object.entries(blockTypesData).filter(([key]) => !isBasicBlock(key)),
- ) : {}), [blockTypesData]) as Record;
+ const advancedBlocks = useMemo(() => (blockTypesData ?
+ Object.fromEntries(
+ Object.entries(blockTypesData).filter(([key]) => !isBasicBlock(key)),
+ ) :
+ {}), [blockTypesData]) as Record;
// Include the 'Advanced / Other' button if there are enabled advanced Xblocks
if (Object.keys(advancedBlocks).length > 0) {
@@ -491,11 +495,13 @@ const AddContent = () => {
showAddLibraryContentModal();
} else if (blockType === 'advancedXBlock') {
showAdvancedList();
- } else if ([
- ContainerType.Unit,
- ContainerType.Subsection,
- ContainerType.Section,
- ].includes(blockType as ContainerType)) {
+ } else if (
+ [
+ ContainerType.Unit,
+ ContainerType.Subsection,
+ ContainerType.Section,
+ ].includes(blockType as ContainerType)
+ ) {
setCreateContainerModalType?.(blockType as ContainerType);
} else {
onCreateBlock(blockType);
@@ -509,22 +515,24 @@ const AddContent = () => {
return (
- {isAdvancedListOpen ? (
-
- ) : (
-
- )}
+ {isAdvancedListOpen ?
+ (
+
+ ) :
+ (
+
+ )}
);
};
diff --git a/src/library-authoring/add-content/AddContentWorkflow.test.tsx b/src/library-authoring/add-content/AddContentWorkflow.test.tsx
index dab4dee980..35d0f60a86 100644
--- a/src/library-authoring/add-content/AddContentWorkflow.test.tsx
+++ b/src/library-authoring/add-content/AddContentWorkflow.test.tsx
@@ -30,7 +30,7 @@ mockCreateLibraryBlock.applyMock();
mockSearchResult(mockResult);
// Mocking the redux APIs in the src/editors/ folder is a bit more involved:
jest.spyOn(editorCmsApi as any, 'fetchBlockById').mockImplementation(
- async (args: { blockId: string }) => (
+ async (args: { blockId: string; }) => (
{ status: 200, data: snakeCaseObject(await mockXBlockFields(args.blockId)) }
),
);
@@ -76,7 +76,8 @@ describe('AddContentWorkflow test', () => {
// Mock the save() REST API method:
saveSpy.mockReset().mockImplementationOnce(async () => ({
- status: 200, data: { id: mockXBlockFields.usageKeyNewHtml },
+ status: 200,
+ data: { id: mockXBlockFields.usageKeyNewHtml },
}));
// Click Save should create the component and then save the content
@@ -110,7 +111,8 @@ describe('AddContentWorkflow test', () => {
// Mock the save() REST API method:
saveSpy.mockReset().mockImplementationOnce(async () => ({
- status: 200, data: { id: mockXBlockFields.usageKeyNewProblem },
+ status: 200,
+ data: { id: mockXBlockFields.usageKeyNewProblem },
}));
// Click Save should create the component and then save the content
@@ -141,7 +143,8 @@ describe('AddContentWorkflow test', () => {
// Mock the save() REST API method:
saveSpy.mockReset().mockImplementationOnce(async () => ({
- status: 200, data: { id: mockXBlockFields.usageKeyNewVideo },
+ status: 200,
+ data: { id: mockXBlockFields.usageKeyNewVideo },
}));
// Click Save should create the component and then save the content
diff --git a/src/library-authoring/add-content/PickLibraryContentModal.test.tsx b/src/library-authoring/add-content/PickLibraryContentModal.test.tsx
index 0fed30629c..0344fd99af 100644
--- a/src/library-authoring/add-content/PickLibraryContentModal.test.tsx
+++ b/src/library-authoring/add-content/PickLibraryContentModal.test.tsx
@@ -50,27 +50,28 @@ const getIdFromContext = (context: ContextType) => {
}
};
-const render = (context: ContextType) => baseRender(
- ,
- {
- path: `/library/:libraryId/${context}/:${context === 'collection' ? context : 'container' }Id/*`,
- params: {
- libraryId,
- ...(context === 'collection' && { collectionId: 'collectionId' }),
- ...(context === 'unit' && { containerId: unitId }),
- ...(context === 'section' && { containerId: sectionId }),
- ...(context === 'subsection' && { containerId: subsectionId }),
+const render = (context: ContextType) =>
+ baseRender(
+ ,
+ {
+ path: `/library/:libraryId/${context}/:${context === 'collection' ? context : 'container'}Id/*`,
+ params: {
+ libraryId,
+ ...(context === 'collection' && { collectionId: 'collectionId' }),
+ ...(context === 'unit' && { containerId: unitId }),
+ ...(context === 'section' && { containerId: sectionId }),
+ ...(context === 'subsection' && { containerId: subsectionId }),
+ },
+ extraWrapper: ({ children }) => (
+
+ {children}
+
+ ),
},
- extraWrapper: ({ children }) => (
-
- {children}
-
- ),
- },
-);
+ );
describe(' ', () => {
beforeEach(async () => {
@@ -111,9 +112,11 @@ describe(' ', () => {
// Select and add the first item
fireEvent.click(screen.queryAllByRole('button', { name: 'Select' })[0]);
- expect(await screen.findByText(
- new RegExp(`1 selected ${addType}`, 'i'),
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ new RegExp(`1 selected ${addType}`, 'i'),
+ ),
+ ).toBeInTheDocument();
fireEvent.click(screen.getByRole('button', {
name: new RegExp(`add to ${context}`, 'i'),
}));
@@ -162,9 +165,11 @@ describe(' ', () => {
// Select and add the first item
fireEvent.click(screen.queryAllByRole('button', { name: 'Select' })[0]);
- expect(await screen.findByText(
- new RegExp(`1 selected ${addType}`, 'i'),
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ new RegExp(`1 selected ${addType}`, 'i'),
+ ),
+ ).toBeInTheDocument();
fireEvent.click(screen.getByRole('button', {
name: new RegExp(`add to ${context}`, 'i'),
diff --git a/src/library-authoring/add-content/PickLibraryContentModal.tsx b/src/library-authoring/add-content/PickLibraryContentModal.tsx
index f74460e471..b4b61ce51e 100644
--- a/src/library-authoring/add-content/PickLibraryContentModal.tsx
+++ b/src/library-authoring/add-content/PickLibraryContentModal.tsx
@@ -34,7 +34,10 @@ export const PickLibraryContentModal: React.FC = (
} = useLibraryContext();
const {
- insideCollection, insideUnit, insideSection, insideSubsection,
+ insideCollection,
+ insideUnit,
+ insideSection,
+ insideSubsection,
} = useLibraryRoutes();
const updateCollectionItemsMutation = useAddItemsToCollection(libraryId, collectionId);
@@ -110,7 +113,7 @@ export const PickLibraryContentModal: React.FC = (
size="xl"
isOpen={isOpen}
onClose={onClose}
- footerNode={(
+ footerNode={
= (
{intl.formatMessage(contentMessages.addToButton)}
- )}
+ }
>
baseRender( , {
- extraWrapper: ({ children }) => (
- {children}
- ),
-});
+const render = (libraryId: string = mockContentLibrary.libraryId) =>
+ baseRender( , {
+ extraWrapper: ({ children }) => {children} ,
+ });
// Mocking i18n to prevent having to generate all dynamic translations for this specific test file
// Other tests can still use the real implementation as needed
@@ -26,13 +25,14 @@ jest.mock('@edx/frontend-platform/i18n', () => ({
}),
}));
-const mockLibraryData:
-{ data: typeof mockContentLibrary.libraryData | undefined } = { data: mockContentLibrary.libraryData };
+const mockLibraryData: { data: typeof mockContentLibrary.libraryData | undefined; } = {
+ data: mockContentLibrary.libraryData,
+};
// TODO: consider using the usual mockContentLibrary.applyMocks pattern after figuring out
// why it doesn't work here as expected
jest.mock('@src/library-authoring/data/apiHooks', () => ({
- useContentLibrary: () => (mockLibraryData),
+ useContentLibrary: () => mockLibraryData,
}));
// Mutable mocks varied per test
@@ -138,7 +138,9 @@ describe(' ', () => {
const el = originalCreate(tagName);
if (tagName === 'a') {
// Force failure when click is invoked
- (el as any).click = () => { throw new Error('fail'); };
+ (el as any).click = () => {
+ throw new Error('fail');
+ };
}
return el;
});
diff --git a/src/library-authoring/backup-restore/LibraryBackupPage.tsx b/src/library-authoring/backup-restore/LibraryBackupPage.tsx
index 4767f7072e..b8dd1e5ec4 100644
--- a/src/library-authoring/backup-restore/LibraryBackupPage.tsx
+++ b/src/library-authoring/backup-restore/LibraryBackupPage.tsx
@@ -118,7 +118,8 @@ export const LibraryBackupPage = () => {
return intl.formatMessage(messages.backupPending);
}
return backupState === LibraryBackupStatus.Pending
- ? intl.formatMessage(messages.backupPending) : intl.formatMessage(messages.backupExporting);
+ ? intl.formatMessage(messages.backupPending) :
+ intl.formatMessage(messages.backupExporting);
}
if (hasBackupSucceeded && backupStatus.data?.url) {
return intl.formatMessage(messages.downloadReadyButton);
diff --git a/src/library-authoring/backup-restore/data/api.ts b/src/library-authoring/backup-restore/data/api.ts
index dd31db8173..c11e4a9345 100644
--- a/src/library-authoring/backup-restore/data/api.ts
+++ b/src/library-authoring/backup-restore/data/api.ts
@@ -1,5 +1,8 @@
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
-import { CreateLibraryBackupResponse, GetLibraryBackupStatusResponse } from '@src/library-authoring/backup-restore/data/constants';
+import {
+ CreateLibraryBackupResponse,
+ GetLibraryBackupStatusResponse,
+} from '@src/library-authoring/backup-restore/data/constants';
import { getLibraryBackupApiUrl, getLibraryBackupStatusApiUrl } from '@src/library-authoring/data/api';
export const createLibraryBackup = async (libraryId: string): Promise => {
@@ -7,8 +10,10 @@ export const createLibraryBackup = async (libraryId: string): Promise => {
+export const getLibraryBackupStatus = async (
+ libraryId: string,
+ taskId: string,
+): Promise => {
const { data } = await getAuthenticatedHttpClient().get(getLibraryBackupStatusApiUrl(libraryId, taskId));
return data;
};
diff --git a/src/library-authoring/backup-restore/data/hooks.test.tsx b/src/library-authoring/backup-restore/data/hooks.test.tsx
index ddde9bf7cf..755fc87d03 100644
--- a/src/library-authoring/backup-restore/data/hooks.test.tsx
+++ b/src/library-authoring/backup-restore/data/hooks.test.tsx
@@ -14,14 +14,16 @@ describe('backup-restore hooks', () => {
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false } },
});
- return function namingToMakeEslintHappy({ children }: { children: React.ReactNode }) {
+ return function namingToMakeEslintHappy({ children }: { children: React.ReactNode; }) {
return {children} ;
};
};
beforeEach(() => {
initializeMocks();
- createLibraryBackupSpy = jest.spyOn(api, 'createLibraryBackup').mockImplementation(async () => ({ task_id: 'task-abc' }));
+ createLibraryBackupSpy = jest.spyOn(api, 'createLibraryBackup').mockImplementation(async () => ({
+ task_id: 'task-abc',
+ }));
getLibraryBackupStatusSpy = jest.spyOn(api, 'getLibraryBackupStatus').mockImplementation(async () => ({
state: LibraryBackupStatus.Pending,
url: '',
diff --git a/src/library-authoring/backup-restore/data/hooks.ts b/src/library-authoring/backup-restore/data/hooks.ts
index 9f3b3d2554..2011b466dc 100644
--- a/src/library-authoring/backup-restore/data/hooks.ts
+++ b/src/library-authoring/backup-restore/data/hooks.ts
@@ -1,5 +1,9 @@
import { createLibraryBackup, getLibraryBackupStatus } from '@src/library-authoring/backup-restore/data/api';
-import { GetLibraryBackupStatusResponse, libraryBackupQueryKeys, LibraryBackupStatus } from '@src/library-authoring/backup-restore/data/constants';
+import {
+ GetLibraryBackupStatusResponse,
+ libraryBackupQueryKeys,
+ LibraryBackupStatus,
+} from '@src/library-authoring/backup-restore/data/constants';
import { useMutation, useQuery } from '@tanstack/react-query';
/**
@@ -14,17 +18,20 @@ import { useMutation, useQuery } from '@tanstack/react-query';
* const { data, isLoading, isError } = useGetLibraryBackupStatus('lib:123', 'task:456abc');
* ```
*/
-export const useGetLibraryBackupStatus = (libraryId: string, taskId: string) => useQuery({
- queryKey: libraryBackupQueryKeys.backupStatus(libraryId, taskId),
- queryFn: () => getLibraryBackupStatus(libraryId, taskId),
- enabled: !!taskId, // Only run the query if taskId is provided
- refetchInterval: (query) => (query.state.data?.state === LibraryBackupStatus.Pending
- || query.state.data?.state === LibraryBackupStatus.Exporting ? 2000 : false),
-});
+export const useGetLibraryBackupStatus = (libraryId: string, taskId: string) =>
+ useQuery({
+ queryKey: libraryBackupQueryKeys.backupStatus(libraryId, taskId),
+ queryFn: () => getLibraryBackupStatus(libraryId, taskId),
+ enabled: !!taskId, // Only run the query if taskId is provided
+ refetchInterval: (query) => (query.state.data?.state === LibraryBackupStatus.Pending
+ || query.state.data?.state === LibraryBackupStatus.Exporting ?
+ 2000 :
+ false),
+ });
-export const useCreateLibraryBackup = (libraryId: string) => useMutation({
- mutationKey: libraryBackupQueryKeys.backupMutation(libraryId),
- mutationFn: () => createLibraryBackup(libraryId),
- gcTime: 60, // Cache for 1 minute to prevent rapid re-creation of backups
-});
+export const useCreateLibraryBackup = (libraryId: string) =>
+ useMutation({
+ mutationKey: libraryBackupQueryKeys.backupMutation(libraryId),
+ mutationFn: () => createLibraryBackup(libraryId),
+ gcTime: 60, // Cache for 1 minute to prevent rapid re-creation of backups
+ });
diff --git a/src/library-authoring/collections/CollectionDetails.test.tsx b/src/library-authoring/collections/CollectionDetails.test.tsx
index 5b3fc71684..63757d724b 100644
--- a/src/library-authoring/collections/CollectionDetails.test.tsx
+++ b/src/library-authoring/collections/CollectionDetails.test.tsx
@@ -29,20 +29,21 @@ const { description: originalDescription } = mockGetCollectionMetadata.collectio
const library = mockContentLibrary.libraryData;
-const render = () => baseRender( , {
- extraWrapper: ({ children }) => (
-
-
- { children }
-
-
- ),
-});
+const render = () =>
+ baseRender( , {
+ extraWrapper: ({ children }) => (
+
+
+ {children}
+
+
+ ),
+ });
describe(' ', () => {
beforeEach(() => {
diff --git a/src/library-authoring/collections/CollectionDetails.tsx b/src/library-authoring/collections/CollectionDetails.tsx
index 13a85a4b74..1150a3b6f4 100644
--- a/src/library-authoring/collections/CollectionDetails.tsx
+++ b/src/library-authoring/collections/CollectionDetails.tsx
@@ -13,10 +13,10 @@ import HistoryWidget from '../generic/history-widget';
import messages from './messages';
interface BlockCountProps {
- count: number,
- blockType?: string,
- label: React.ReactNode,
- className?: string,
+ count: number;
+ blockType?: string;
+ label: React.ReactNode;
+ className?: string;
}
const BlockCount = ({
@@ -148,14 +148,16 @@ const CollectionDetails = () => {
{intl.formatMessage(messages.detailsTabDescriptionTitle)}
- {!readOnly ? (
- setDescription(e.target.value)}
- onBlur={onSubmit}
- />
- ) : collection.description}
+ {!readOnly ?
+ (
+ setDescription(e.target.value)}
+ onBlur={onSubmit}
+ />
+ ) :
+ collection.description}
diff --git a/src/library-authoring/collections/CollectionInfo.tsx b/src/library-authoring/collections/CollectionInfo.tsx
index fc0709fb73..bb6293f026 100644
--- a/src/library-authoring/collections/CollectionInfo.tsx
+++ b/src/library-authoring/collections/CollectionInfo.tsx
@@ -30,8 +30,10 @@ const CollectionInfo = () => {
const { sidebarItemInfo, sidebarTab, setSidebarTab } = useSidebarContext();
const tab: CollectionInfoTab = (
- sidebarTab && isCollectionInfoTab(sidebarTab)
- ) ? sidebarTab : COLLECTION_INFO_TABS.Details;
+ sidebarTab && isCollectionInfoTab(sidebarTab)
+ ) ?
+ sidebarTab :
+ COLLECTION_INFO_TABS.Details;
const collectionId = sidebarItemInfo?.id;
// istanbul ignore if: this should never happen
diff --git a/src/library-authoring/collections/CollectionInfoHeader.test.tsx b/src/library-authoring/collections/CollectionInfoHeader.test.tsx
index 5c868284ca..e3dc55cf57 100644
--- a/src/library-authoring/collections/CollectionInfoHeader.test.tsx
+++ b/src/library-authoring/collections/CollectionInfoHeader.test.tsx
@@ -27,20 +27,21 @@ const {
const { collectionId } = mockGetCollectionMetadata;
-const render = (libraryId: string = mockLibraryId) => baseRender( , {
- extraWrapper: ({ children }) => (
-
-
- { children }
-
-
- ),
-});
+const render = (libraryId: string = mockLibraryId) =>
+ baseRender( , {
+ extraWrapper: ({ children }) => (
+
+
+ {children}
+
+
+ ),
+ });
describe(' ', () => {
beforeEach(() => {
diff --git a/src/library-authoring/collections/LibraryCollectionPage.test.tsx b/src/library-authoring/collections/LibraryCollectionPage.test.tsx
index a5d846d1b7..3272f78c40 100644
--- a/src/library-authoring/collections/LibraryCollectionPage.test.tsx
+++ b/src/library-authoring/collections/LibraryCollectionPage.test.tsx
@@ -68,7 +68,9 @@ describe(' ', () => {
mockResultCopy.results[0].query = query;
// And fake the required '_formatted' fields; it contains the highlighting ... around matched words
// eslint-disable-next-line no-underscore-dangle, no-param-reassign
- mockResultCopy.results[0]?.hits.forEach((hit) => { hit._formatted = { ...hit }; });
+ mockResultCopy.results[0]?.hits.forEach((hit) => {
+ hit._formatted = { ...hit };
+ });
const collectionQueryId = requestData?.queries[0]?.filter?.[2]?.split('collections.key = "')[1].split('"')[0];
switch (collectionQueryId) {
case mockCollection.collectionNeverLoads:
@@ -100,7 +102,9 @@ describe(' ', () => {
});
if (![mockCollection.collectionNeverLoads, mockCollection.collectionEmpty].includes(colId)) {
- await waitFor(() => { expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post'); });
+ await waitFor(() => {
+ expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post');
+ });
}
};
@@ -183,7 +187,9 @@ describe(' ', () => {
// Ensure the search endpoint is called again, only once more since the recently modified call
// should not be impacted by the search
- await waitFor(() => { expect(fetchMock).toHaveFetchedTimes(2, searchEndpoint, 'post'); });
+ await waitFor(() => {
+ expect(fetchMock).toHaveFetchedTimes(2, searchEndpoint, 'post');
+ });
expect(screen.queryByText('No matching components found in this collection.')).toBeInTheDocument();
});
@@ -261,7 +267,7 @@ describe(' ', () => {
expect(await screen.findByTitle('Sort search results')).toBeInTheDocument();
- const testSortOption = (async (optionText, sortBy, isDefault) => {
+ const testSortOption = async (optionText, sortBy, isDefault) => {
// Open the drop-down menu
fireEvent.click(screen.getByTitle('Sort search results'));
@@ -296,7 +302,7 @@ describe(' ', () => {
// Is the selected sort option shown in the toggle button (if not default)
// as well as in the drop-down menu?
expect(screen.getAllByText(optionText).length).toEqual(isDefault ? 1 : 2);
- });
+ };
await testSortOption('Title, A-Z', 'display_name:asc', false);
await testSortOption('Title, Z-A', 'display_name:desc', false);
@@ -487,7 +493,9 @@ describe(' ', () => {
expect(axiosMock.history.post[0].url).toBe(containerUrl);
expect(axiosMock.history.post[0].data).toContain(`"display_name":"${containerTitle}"`);
expect(axiosMock.history.post[0].data).toContain(`"container_type":"${containerType}"`);
- expect(mockShowToast).toHaveBeenCalledWith(expect.stringMatching(new RegExp(`${containerType} created successfully`, 'i')));
+ expect(mockShowToast).toHaveBeenCalledWith(
+ expect.stringMatching(new RegExp(`${containerType} created successfully`, 'i')),
+ );
// Check that the unit was added to the collection
expect(axiosMock.history.patch.length).toBe(1);
diff --git a/src/library-authoring/collections/LibraryCollectionPage.tsx b/src/library-authoring/collections/LibraryCollectionPage.tsx
index 017d32e2b3..2b482a2a66 100644
--- a/src/library-authoring/collections/LibraryCollectionPage.tsx
+++ b/src/library-authoring/collections/LibraryCollectionPage.tsx
@@ -139,43 +139,47 @@ const LibraryCollectionPage = () => {
return ;
}
- const breadcrumbs = !componentPickerMode ? (
- ` spacer.
- {
- label: '',
- to: '',
- },
- ]}
- linkAs={Link}
- />
- ) : (
- { setCollectionId?.(undefined); },
- },
- ]}
- spacer={ }
- linkAs={Link}
- />
- );
+ const breadcrumbs = !componentPickerMode ?
+ (
+ ` spacer.
+ {
+ label: '',
+ to: '',
+ },
+ ]}
+ linkAs={Link}
+ />
+ ) :
+ (
+ {
+ setCollectionId?.(undefined);
+ },
+ },
+ ]}
+ spacer={ }
+ linkAs={Link}
+ />
+ );
const extraFilter = [`collections.key = "${collectionId}"`];
if (libraryId) {
@@ -192,7 +196,9 @@ const LibraryCollectionPage = () => {
return (
-
{libraryData.title} | {process.env.SITE_NAME}
+
+ {libraryData.title} | {process.env.SITE_NAME}
+
{!componentPickerMode && (
>;
};
@@ -65,7 +65,7 @@ const ComponentPickerContext = createContext void;
+ blockType?: string;
+ onClose?: (data?: any) => void;
}
export type LibraryContextData = {
@@ -47,8 +47,8 @@ export type LibraryContextData = {
/** If the editor is open and the user is editing some component, this is the component being edited. */
componentBeingEdited: ComponentEditorInfo | undefined;
/** If an onClose callback is provided, it will be called when the editor is closed. */
- openComponentEditor: (usageKey: string, onClose?: (data?:any) => void, blockType?:string) => void;
- closeComponentEditor: (data?:any) => void;
+ openComponentEditor: (usageKey: string, onClose?: (data?: any) => void, blockType?: string) => void;
+ closeComponentEditor: (data?: any) => void;
componentPicker?: typeof ComponentPicker;
blockTypesData?: Record;
};
@@ -66,7 +66,7 @@ const LibraryContext = createContext(undefined);
type LibraryProviderProps = {
libraryId: string;
children?: React.ReactNode;
- extraFilter?: string[]
+ extraFilter?: string[];
// If set, will initialize the current collection and/or component from the current URL
skipUrlUpdate?: boolean;
@@ -96,7 +96,7 @@ export const LibraryProvider = ({
return undefined;
});
}, []);
- const openComponentEditor = useCallback((usageKey: string, onClose?: () => void, blockType?:string) => {
+ const openComponentEditor = useCallback((usageKey: string, onClose?: () => void, blockType?: string) => {
setComponentBeingEdited({ usageKey, onClose, blockType });
}, []);
diff --git a/src/library-authoring/common/context/MultiLibraryContext.tsx b/src/library-authoring/common/context/MultiLibraryContext.tsx
index c2a310bb08..b1a2911d77 100644
--- a/src/library-authoring/common/context/MultiLibraryContext.tsx
+++ b/src/library-authoring/common/context/MultiLibraryContext.tsx
@@ -10,7 +10,7 @@ interface MultiLibraryContextProps {
const Context = React.createContext(undefined);
-export const MultiLibraryProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
+export const MultiLibraryProvider: React.FC<{ children: React.ReactNode; }> = ({ children }) => {
const [selectedLibraries, setSelectedLibraries] = useStickyState([], 'outline-library-filter');
const [selectedCollections, setSelectedCollections] = React.useState([]);
diff --git a/src/library-authoring/common/context/PublishedFilterContext.tsx b/src/library-authoring/common/context/PublishedFilterContext.tsx
index 443595ea3c..d296169ad4 100644
--- a/src/library-authoring/common/context/PublishedFilterContext.tsx
+++ b/src/library-authoring/common/context/PublishedFilterContext.tsx
@@ -6,7 +6,7 @@ interface PublishedFilterContextProps {
const Context = React.createContext(undefined);
-export const PublishedFilterContextProvider: React.FC = ({
+export const PublishedFilterContextProvider: React.FC = ({
showOnlyPublished,
children,
}) => {
diff --git a/src/library-authoring/common/context/SidebarContext.tsx b/src/library-authoring/common/context/SidebarContext.tsx
index 5e09985d7d..bf371042c9 100644
--- a/src/library-authoring/common/context/SidebarContext.tsx
+++ b/src/library-authoring/common/context/SidebarContext.tsx
@@ -60,7 +60,8 @@ const DEFAULT_TAB = {
type SidebarInfoTab = ComponentInfoTab | CollectionInfoTab | ContainerInfoTab;
const toSidebarInfoTab = (tab: string): SidebarInfoTab | undefined => (
isComponentInfoTab(tab) || isCollectionInfoTab(tab) || isContainerInfoTab(tab)
- ? tab : undefined
+ ? tab :
+ undefined
);
export interface DefaultTabs {
@@ -104,7 +105,6 @@ export type SidebarContextData = {
* Sidebar Context.
*
* Get this using `useSidebarContext()`
- *
*/
const SidebarContext = createContext(undefined);
diff --git a/src/library-authoring/component-info/ComponentAdvancedAssets.tsx b/src/library-authoring/component-info/ComponentAdvancedAssets.tsx
index 5e42fc63bd..6a87a799d9 100644
--- a/src/library-authoring/component-info/ComponentAdvancedAssets.tsx
+++ b/src/library-authoring/component-info/ComponentAdvancedAssets.tsx
@@ -33,8 +33,10 @@ export const ComponentAdvancedAssets: React.FC> = () => {
// For uploading assets:
const handleProcessUpload = React.useCallback(async ({
- fileData, requestConfig, handleError,
- }: { fileData: FormData, requestConfig: any, handleError: any }) => {
+ fileData,
+ requestConfig,
+ handleError,
+ }: { fileData: FormData; requestConfig: any; handleError: any; }) => {
const uploadData = new FormData();
const file = fileData.get('file') as File;
uploadData.set('content', file); // Paragon calls this 'file' but our API needs it called 'content'
@@ -67,18 +69,34 @@ export const ComponentAdvancedAssets: React.FC> = () => {
return (
<>
- { areAssetsLoading ? : null }
- { assets?.map(a => (
+ {areAssetsLoading
+ ? (
+
+
+
+ )
+ : null}
+ {assets?.map(a => (
{a.path} {' '}
( )
- { setConfirmDeleteAsset(a.path); }} title={intl.formatMessage(messages.advancedDetailsAssetsDeleteButton)}>
-
+ {
+ setConfirmDeleteAsset(a.path);
+ }}
+ title={intl.formatMessage(messages.advancedDetailsAssetsDeleteButton)}
+ >
+
+
+
- )) }
+ ))}
- { assets !== undefined && !readOnly // Wait until assets have loaded before displaying add button:
+ {assets !== undefined && !readOnly // Wait until assets have loaded before displaying add button:
? (
> = () => {
onUploadProgress={() => {}}
/>
)
- : null }
+ : null}
{ setConfirmDeleteAsset(''); }}
+ close={() => {
+ setConfirmDeleteAsset('');
+ }}
variant="warning"
title={intl.formatMessage(messages.advancedDetailsAssetsDeleteFileTitle)}
description={`Are you sure you want to delete ${filePathToDelete}?`}
diff --git a/src/library-authoring/component-info/ComponentAdvancedInfo.test.tsx b/src/library-authoring/component-info/ComponentAdvancedInfo.test.tsx
index 1ddf5707bf..b498a17a9c 100644
--- a/src/library-authoring/component-info/ComponentAdvancedInfo.test.tsx
+++ b/src/library-authoring/component-info/ComponentAdvancedInfo.test.tsx
@@ -29,25 +29,26 @@ const render = (
usageKey: string = mockLibraryBlockMetadata.usageKeyPublished,
libraryId: string = mockContentLibrary.libraryId,
showOnlyPublished: boolean = false,
-) => baseRender(
- ,
- {
- extraWrapper: ({ children }: { children: React.ReactNode }) => (
-
-
-
- {children}
-
-
-
- ),
- },
-);
+) =>
+ baseRender(
+ ,
+ {
+ extraWrapper: ({ children }: { children: React.ReactNode; }) => (
+
+
+
+ {children}
+
+
+
+ ),
+ },
+ );
describe(' ', () => {
beforeEach(() => {
@@ -84,7 +85,9 @@ describe(' ', () => {
render();
- const url = `${getXBlockAssetsApiUrl(mockLibraryBlockMetadata.usageKeyPublished)}${encodeURIComponent('static/image1.png')}`;
+ const url = `${getXBlockAssetsApiUrl(mockLibraryBlockMetadata.usageKeyPublished)}${
+ encodeURIComponent('static/image1.png')
+ }`;
axiosMock.onDelete(url).reply(200);
const expandButton = await screen.findByRole('button', { name: /Advanced details/ });
diff --git a/src/library-authoring/component-info/ComponentAdvancedInfo.tsx b/src/library-authoring/component-info/ComponentAdvancedInfo.tsx
index 2cdc3f4359..52cc1a9b7b 100644
--- a/src/library-authoring/component-info/ComponentAdvancedInfo.tsx
+++ b/src/library-authoring/component-info/ComponentAdvancedInfo.tsx
@@ -56,29 +56,41 @@ const ComponentAdvancedInfoInner: React.FC> = () => {
return (
<>
-
+
+
+
{usageKey}
-
+
+
+
{(() => {
if (isOLXLoading) { return ; }
if (!olx) { return ; }
return (
- {olxUpdater.error ? (
-
- <>
-
- {/*
+ {olxUpdater.error ?
+ (
+
+ <>
+
+
+
+
+
+ {
+ /*
TODO: fix the API so it returns 400 errors in a JSON object, not HTML 500 errors. Then display
a useful error message here like "parsing the XML failed on line 3".
(olxUpdater.error as Record)?.customAttributes?.httpErrorResponseData.errorMessage
- */}
- >
-
- ) : null}
+ */
+ }
+ >
+
+ ) :
+ null}
{olx}
- {
- isEditingOLX ? (
+ {isEditingOLX ?
+ (
<>
@@ -87,27 +99,31 @@ const ComponentAdvancedInfoInner: React.FC> = () => {
>
- ) : !readOnly ? (
+ ) :
+ !readOnly ?
+ (
- )}
+ }
>
setEditingOLX(true)}>
- ) : (
+ ) :
+ (
null
- )
- }
+ )}
);
})()}
-
+
+
+
>
);
diff --git a/src/library-authoring/component-info/ComponentDetails.test.tsx b/src/library-authoring/component-info/ComponentDetails.test.tsx
index c6a20d1ce2..127e3bc2ff 100644
--- a/src/library-authoring/component-info/ComponentDetails.test.tsx
+++ b/src/library-authoring/component-info/ComponentDetails.test.tsx
@@ -30,22 +30,23 @@ const {
libraryId,
} = mockContentLibrary;
-const render = (usageKey: string) => baseRender( , {
- path: `/library/${libraryId}/components/${usageKey}`,
- params: { libraryId, selectedItemId: usageKey },
- extraWrapper: ({ children }) => (
-
-
- {children}
-
-
- ),
-});
+const render = (usageKey: string) =>
+ baseRender( , {
+ path: `/library/${libraryId}/components/${usageKey}`,
+ params: { libraryId, selectedItemId: usageKey },
+ extraWrapper: ({ children }) => (
+
+
+ {children}
+
+
+ ),
+ });
describe(' ', () => {
beforeEach(() => {
diff --git a/src/library-authoring/component-info/ComponentInfo.test.tsx b/src/library-authoring/component-info/ComponentInfo.test.tsx
index 168fdc2a25..c551adbcb9 100644
--- a/src/library-authoring/component-info/ComponentInfo.test.tsx
+++ b/src/library-authoring/component-info/ComponentInfo.test.tsx
@@ -33,7 +33,7 @@ jest.mock('./ComponentManagement', () => ({
}));
const withLibraryId = (libraryId: string, sidebarComponentUsageKey: string) => ({
- extraWrapper: ({ children }: { children: React.ReactNode }) => (
+ extraWrapper: ({ children }: { children: React.ReactNode; }) => (
{
const intl = useIntl();
const { openComponentEditor } = useOptionalLibraryContext();
@@ -135,15 +135,17 @@ const ComponentActions = ({
{intl.formatMessage(messages.editComponentButtonTitle)}
- {!hasUnpublishedChanges ? (
-
- ) : (
-
- )}
+ {!hasUnpublishedChanges ?
+ (
+
+ ) :
+ (
+
+ )}
@@ -165,11 +167,9 @@ const ComponentInfo = () => {
resetSidebarAction,
} = useSidebarContext();
- const tab: ComponentInfoTab = (
- isComponentInfoTab(sidebarTab)
- ? sidebarTab
- : defaultTab.component
- );
+ const tab: ComponentInfoTab = isComponentInfoTab(sidebarTab)
+ ? sidebarTab
+ : defaultTab.component;
const handleTabChange = (newTab: ComponentInfoTab) => {
resetSidebarAction();
diff --git a/src/library-authoring/component-info/ComponentInfoHeader.test.tsx b/src/library-authoring/component-info/ComponentInfoHeader.test.tsx
index c5c3f6d7eb..13effa9588 100644
--- a/src/library-authoring/component-info/ComponentInfoHeader.test.tsx
+++ b/src/library-authoring/component-info/ComponentInfoHeader.test.tsx
@@ -23,20 +23,21 @@ const xBlockFields = {
},
};
-const render = (libraryId: string = mockLibraryId) => baseRender(
, {
- extraWrapper: ({ children }) => (
-
-
- {children}
-
-
- ),
-});
+const render = (libraryId: string = mockLibraryId) =>
+ baseRender(
, {
+ extraWrapper: ({ children }) => (
+
+
+ {children}
+
+
+ ),
+ });
let axiosMock: MockAdapter;
let mockShowToast: (message: string) => void;
diff --git a/src/library-authoring/component-info/ComponentManagement.test.tsx b/src/library-authoring/component-info/ComponentManagement.test.tsx
index 4d5051ff5a..e3ed7fc925 100644
--- a/src/library-authoring/component-info/ComponentManagement.test.tsx
+++ b/src/library-authoring/component-info/ComponentManagement.test.tsx
@@ -16,7 +16,7 @@ import ComponentManagement from './ComponentManagement';
jest.mock('../../content-tags-drawer', () => ({
...jest.requireActual('../../content-tags-drawer'),
- ContentTagsDrawer: ({ readOnly }: { readOnly: boolean }) => (
+ ContentTagsDrawer: ({ readOnly }: { readOnly: boolean; }) => (
Mocked {readOnly ? 'read-only' : 'editable'} ContentTagsDrawer
),
}));
@@ -35,20 +35,21 @@ mockContentLibrary.applyMock();
mockLibraryBlockMetadata.applyMock();
mockContentTaxonomyTagsData.applyMock();
-const render = (usageKey: string, libraryId?: string) => baseRender(
, {
- extraWrapper: ({ children }) => (
-
-
- {children}
-
-
- ),
-});
+const render = (usageKey: string, libraryId?: string) =>
+ baseRender(
, {
+ extraWrapper: ({ children }) => (
+
+
+ {children}
+
+
+ ),
+ });
describe('
', () => {
beforeEach(() => {
diff --git a/src/library-authoring/component-info/ComponentManagement.tsx b/src/library-authoring/component-info/ComponentManagement.tsx
index 6485fe28f9..5703f4de63 100644
--- a/src/library-authoring/component-info/ComponentManagement.tsx
+++ b/src/library-authoring/component-info/ComponentManagement.tsx
@@ -3,7 +3,10 @@ import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Collapsible, Icon, Stack } from '@openedx/paragon';
import {
- BookOpen, ExpandLess, ExpandMore, Tag,
+ BookOpen,
+ ExpandLess,
+ ExpandMore,
+ Tag,
} from '@openedx/paragon/icons';
import { useOptionalLibraryContext } from '../common/context/LibraryContext';
@@ -56,7 +59,7 @@ const ComponentManagement = () => {
}
let result = 0;
componentTags.taxonomies.forEach((taxonomy) => {
- const countedTags : string[] = [];
+ const countedTags: string[] = [];
taxonomy.tags.forEach((tagData) => {
tagData.lineage.forEach((tag) => {
if (!countedTags.includes(tag)) {
diff --git a/src/library-authoring/component-info/ComponentPreview.test.tsx b/src/library-authoring/component-info/ComponentPreview.test.tsx
index 2594ee347d..89ba2256ee 100644
--- a/src/library-authoring/component-info/ComponentPreview.test.tsx
+++ b/src/library-authoring/component-info/ComponentPreview.test.tsx
@@ -18,28 +18,29 @@ const {
const usageKey = mockLibraryBlockMetadata.usageKeyPublished;
-const render = () => baseRender(
, {
- path: `/library/${libraryId}/components/${usageKey}`,
- params: { libraryId, selectedItemId: usageKey },
- extraWrapper: ({ children }) => (
-
-
- {children}
-
-
- ),
-});
+const render = () =>
+ baseRender(
, {
+ path: `/library/${libraryId}/components/${usageKey}`,
+ params: { libraryId, selectedItemId: usageKey },
+ extraWrapper: ({ children }) => (
+
+
+ {children}
+
+
+ ),
+ });
describe('
', () => {
it('renders a preview of the component', async () => {
initializeMocks();
render();
- const iframe = (await screen.findByTitle
('Preview'));
+ const iframe = await screen.findByTitle('Preview');
expect(iframe.src).toEqual(`http://localhost:18010/xblocks/v2/${usageKey}/embed/student_view/`);
});
diff --git a/src/library-authoring/component-info/ComponentUsage.tsx b/src/library-authoring/component-info/ComponentUsage.tsx
index 9681bb4b1d..328c9eefe4 100644
--- a/src/library-authoring/component-info/ComponentUsage.tsx
+++ b/src/library-authoring/component-info/ComponentUsage.tsx
@@ -16,14 +16,14 @@ interface ComponentUsageProps {
}
type ComponentUsageTree = Record;
const getContainerUrl = (usageKey: string) => (
@@ -63,7 +63,7 @@ export const ComponentUsage = ({ usageKey }: ComponentUsageProps) => {
}
const componentUsage = downstreamHits.reduce((acc, hit) => {
- const link = hit.breadcrumbs.at(-1) as { displayName: string, usageKey: string };
+ const link = hit.breadcrumbs.at(-1) as { displayName: string; usageKey: string; };
// istanbul ignore if: this should never happen. it is a type guard for the breadcrumb last item
if (!link?.usageKey) {
return acc;
@@ -95,23 +95,21 @@ export const ComponentUsage = ({ usageKey }: ComponentUsageProps) => {
return (
<>
- {
- componentUsageList.map((context) => (
-
-
- {Object.keys(context.links).map((downstreamUsageKey: string) => (
-
- {context.links[downstreamUsageKey].displayName}
-
- ))}
-
-
- ))
- }
+ {componentUsageList.map((context) => (
+
+
+ {Object.keys(context.links).map((downstreamUsageKey: string) => (
+
+ {context.links[downstreamUsageKey].displayName}
+
+ ))}
+
+
+ ))}
>
);
};
diff --git a/src/library-authoring/component-info/ComponentUsageTab.test.tsx b/src/library-authoring/component-info/ComponentUsageTab.test.tsx
index 81ab374574..62674ba9ba 100644
--- a/src/library-authoring/component-info/ComponentUsageTab.test.tsx
+++ b/src/library-authoring/component-info/ComponentUsageTab.test.tsx
@@ -19,22 +19,23 @@ const {
libraryId,
} = mockContentLibrary;
-const render = (usageKey: string) => baseRender( , {
- path: `/library/${libraryId}/components/${usageKey}`,
- params: { libraryId, selectedItemId: usageKey },
- extraWrapper: ({ children }) => (
-
-
- {children}
-
-
- ),
-});
+const render = (usageKey: string) =>
+ baseRender( , {
+ path: `/library/${libraryId}/components/${usageKey}`,
+ params: { libraryId, selectedItemId: usageKey },
+ extraWrapper: ({ children }) => (
+
+
+ {children}
+
+
+ ),
+ });
describe(' ', () => {
beforeEach(() => {
diff --git a/src/library-authoring/component-picker/ComponentPicker.test.tsx b/src/library-authoring/component-picker/ComponentPicker.test.tsx
index 0cd84192fe..a5ee016777 100644
--- a/src/library-authoring/component-picker/ComponentPicker.test.tsx
+++ b/src/library-authoring/component-picker/ComponentPicker.test.tsx
@@ -160,7 +160,7 @@ describe(' ', () => {
expect(await screen.findByText('Test Library 1')).toBeInTheDocument();
// Click on the unit card to open the sidebar
- fireEvent.click((await screen.findByText('Published Test Unit')));
+ fireEvent.click(await screen.findByText('Published Test Unit'));
const sidebar = await screen.findByTestId('library-sidebar');
expect(sidebar).toBeInTheDocument();
@@ -302,38 +302,44 @@ describe(' ', () => {
// Select the first component
fireEvent.click(screen.queryAllByRole('button', { name: 'Select' })[0]);
- await waitFor(() => expect(onChange).toHaveBeenCalledWith([
- {
- usageKey: 'lb:Axim:TEST:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd',
- blockType: 'html',
- },
- ]));
+ await waitFor(() =>
+ expect(onChange).toHaveBeenCalledWith([
+ {
+ usageKey: 'lb:Axim:TEST:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd',
+ blockType: 'html',
+ },
+ ])
+ );
onChange.mockClear();
// Select another component
fireEvent.click(screen.queryAllByRole('button', { name: 'Select' })[1]);
- await waitFor(() => expect(onChange).toHaveBeenCalledWith([
- {
- usageKey: 'lb:Axim:TEST:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd',
- blockType: 'html',
- },
- {
- blockType: 'html',
- usageKey: 'lb:Axim:TEST:html:73a22298-bcd9-4f4c-ae34-0bc2b0612480',
- },
- ]));
+ await waitFor(() =>
+ expect(onChange).toHaveBeenCalledWith([
+ {
+ usageKey: 'lb:Axim:TEST:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd',
+ blockType: 'html',
+ },
+ {
+ blockType: 'html',
+ usageKey: 'lb:Axim:TEST:html:73a22298-bcd9-4f4c-ae34-0bc2b0612480',
+ },
+ ])
+ );
onChange.mockClear();
// Deselect the first component
fireEvent.click(screen.queryAllByRole('button', { name: 'Select' })[0]);
- await waitFor(() => expect(onChange).toHaveBeenCalledWith([
- {
- blockType: 'html',
- usageKey: 'lb:Axim:TEST:html:73a22298-bcd9-4f4c-ae34-0bc2b0612480',
- },
- ]));
+ await waitFor(() =>
+ expect(onChange).toHaveBeenCalledWith([
+ {
+ blockType: 'html',
+ usageKey: 'lb:Axim:TEST:html:73a22298-bcd9-4f4c-ae34-0bc2b0612480',
+ },
+ ])
+ );
});
it('should pick multilpe components using the component sidebar', async () => {
@@ -358,12 +364,14 @@ describe(' ', () => {
// Click the select component from the component sidebar
fireEvent.click(within(sidebar).getByRole('button', { name: 'Select' }));
- await waitFor(() => expect(onChange).toHaveBeenCalledWith([
- {
- usageKey: 'lb:Axim:TEST:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd',
- blockType: 'html',
- },
- ]));
+ await waitFor(() =>
+ expect(onChange).toHaveBeenCalledWith([
+ {
+ usageKey: 'lb:Axim:TEST:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd',
+ blockType: 'html',
+ },
+ ])
+ );
onChange.mockClear();
diff --git a/src/library-authoring/component-picker/ComponentPicker.tsx b/src/library-authoring/component-picker/ComponentPicker.tsx
index d8d56e28d6..906dd73d1c 100644
--- a/src/library-authoring/component-picker/ComponentPicker.tsx
+++ b/src/library-authoring/component-picker/ComponentPicker.tsx
@@ -20,7 +20,7 @@ import { ContentType, allLibraryPageTabs } from '../routes';
interface LibraryComponentPickerProps {
returnToLibrarySelection?: () => void;
- visibleTabs: ContentType[],
+ visibleTabs: ContentType[];
FiltersComponent?: React.ComponentType;
}
@@ -54,12 +54,12 @@ const defaultSelectionChangedCallback: ComponentSelectionChangedEvent = (selecti
};
type PickerProps = {
- showOnlyPublished?: boolean,
- extraFilter?: string[],
- visibleTabs?: ContentType[],
- componentPickerMode?: 'single' | 'multiple',
- onComponentSelected?: ComponentSelectedEvent,
- onChangeComponentSelection?: ComponentSelectionChangedEvent,
+ showOnlyPublished?: boolean;
+ extraFilter?: string[];
+ visibleTabs?: ContentType[];
+ componentPickerMode?: 'single' | 'multiple';
+ onComponentSelected?: ComponentSelectedEvent;
+ onChangeComponentSelection?: ComponentSelectionChangedEvent;
FiltersComponent?: React.ComponentType;
};
@@ -78,7 +78,7 @@ export const ComponentPicker = ({
onChangeComponentSelection = defaultSelectionChangedCallback,
FiltersComponent,
returnToLibrarySelection,
-}: PickerProps & LibraryComponentPickerProps & { libraryId?: string }) => {
+}: PickerProps & LibraryComponentPickerProps & { libraryId?: string; }) => {
const location = useLocation();
const queryParams = new URLSearchParams(location.search);
@@ -87,15 +87,17 @@ export const ComponentPicker = ({
const restrictToLibrary = !!libraryId;
- const componentPickerProviderProps = componentPickerMode === 'single' ? {
- componentPickerMode,
- onComponentSelected,
- restrictToLibrary,
- } : {
- componentPickerMode,
- onChangeComponentSelection,
- restrictToLibrary,
- };
+ const componentPickerProviderProps = componentPickerMode === 'single' ?
+ {
+ componentPickerMode,
+ onComponentSelected,
+ restrictToLibrary,
+ } :
+ {
+ componentPickerMode,
+ onChangeComponentSelection,
+ restrictToLibrary,
+ };
return (
@@ -104,7 +106,7 @@ export const ComponentPicker = ({
extraFilter={extraFilter}
>
- { calcShowOnlyPublished
+ {calcShowOnlyPublished
&& (
diff --git a/src/library-authoring/component-picker/SelectLibrary.tsx b/src/library-authoring/component-picker/SelectLibrary.tsx
index 59cfac6ddf..5348e17d9f 100644
--- a/src/library-authoring/component-picker/SelectLibrary.tsx
+++ b/src/library-authoring/component-picker/SelectLibrary.tsx
@@ -22,18 +22,14 @@ interface EmptyStateProps {
const EmptyState = ({ hasSearchQuery }: EmptyStateProps) => (
- {hasSearchQuery ? (
-
- ) : (
-
- )}
+ {hasSearchQuery ?
+ :
+ }
- {hasSearchQuery ? (
-
- ) : (
-
- )}
+ {hasSearchQuery ?
+ :
+ }
);
@@ -87,7 +83,7 @@ const SelectLibrary = ({ selectedLibrary, setSelectedLibrary, itemType }: Select
value={searchQuery}
placeholder={intl.formatMessage(messages.selectLibrarySearchPlaceholder)}
/>
- {data.results.length === 0 ? ( ) : (
+ {data.results.length === 0 ? : (
<>
{library.title}}
subtitle={`${library.org} / ${library.slug}`}
- actions={(
- {' '}
- )}
+ actions={{' '} }
/>
{library.description}
diff --git a/src/library-authoring/components/BaseCard.tsx b/src/library-authoring/components/BaseCard.tsx
index 52bd341fdd..8ac9b5e1b7 100644
--- a/src/library-authoring/components/BaseCard.tsx
+++ b/src/library-authoring/components/BaseCard.tsx
@@ -39,13 +39,13 @@ const BaseCard = ({
onSelect,
selected = false,
...props
-} : BaseCardProps) => {
+}: BaseCardProps) => {
const tagCount = useMemo(() => {
if (!tags) {
return 0;
}
return (tags.level0?.length || 0) + (tags.level1?.length || 0)
- + (tags.level2?.length || 0) + (tags.level3?.length || 0);
+ + (tags.level2?.length || 0) + (tags.level3?.length || 0);
}, [tags]);
const itemIcon = !props.isPlaceholder ? getItemIcon(itemType) : ExtensionOff;
@@ -66,16 +66,13 @@ const BaseCard = ({
>
- }
- actions={(
- {actions}
+ title={
}
+ actions={
+
+ {actions}
- )}
+ }
/>
@@ -95,10 +92,10 @@ const BaseCard = ({
{!props.isPlaceholder && (
- <>
-
-
- >
+ <>
+
+
+ >
)}
diff --git a/src/library-authoring/components/CollectionCard.test.tsx b/src/library-authoring/components/CollectionCard.test.tsx
index 259a01101e..3a998178f2 100644
--- a/src/library-authoring/components/CollectionCard.test.tsx
+++ b/src/library-authoring/components/CollectionCard.test.tsx
@@ -4,7 +4,12 @@ import type MockAdapter from 'axios-mock-adapter';
import { mockContentLibrary } from '@src/library-authoring/data/api.mocks';
import { PublishedFilterContextProvider } from '@src/library-authoring/common/context/PublishedFilterContext';
import {
- initializeMocks, render as baseRender, screen, waitFor, within, fireEvent,
+ initializeMocks,
+ render as baseRender,
+ screen,
+ waitFor,
+ within,
+ fireEvent,
} from '../../testUtils';
import { LibraryProvider } from '../common/context/LibraryContext';
import { type CollectionHit } from '../../search-manager';
@@ -51,17 +56,18 @@ const render = (
ui: React.ReactElement,
showOnlyPublished: boolean = false,
libId: string = libraryId,
-) => baseRender(ui, {
- path: '/library/:libraryId',
- params: { libraryId: libId },
- extraWrapper: ({ children }) => (
-
-
- {children}
-
-
- ),
-});
+) =>
+ baseRender(ui, {
+ path: '/library/:libraryId',
+ params: { libraryId: libId },
+ extraWrapper: ({ children }) => (
+
+
+ {children}
+
+
+ ),
+ });
describe('
', () => {
beforeEach(() => {
diff --git a/src/library-authoring/components/CollectionCard.tsx b/src/library-authoring/components/CollectionCard.tsx
index 0f35d047d4..d8febd24fe 100644
--- a/src/library-authoring/components/CollectionCard.tsx
+++ b/src/library-authoring/components/CollectionCard.tsx
@@ -22,10 +22,10 @@ import { useDeleteCollection, useRestoreCollection } from '../data/apiHooks';
import messages from './messages';
type CollectionMenuProps = {
- hit: CollectionHit,
+ hit: CollectionHit;
};
-const CollectionMenu = ({ hit } : CollectionMenuProps) => {
+const CollectionMenu = ({ hit }: CollectionMenuProps) => {
const intl = useIntl();
const { showToast } = useContext(ToastContext);
const { navigateTo } = useLibraryRoutes();
@@ -115,10 +115,10 @@ const CollectionMenu = ({ hit } : CollectionMenuProps) => {
};
type CollectionCardProps = {
- hit: CollectionHit,
+ hit: CollectionHit;
};
-const CollectionCard = ({ hit } : CollectionCardProps) => {
+const CollectionCard = ({ hit }: CollectionCardProps) => {
const { componentPickerMode } = useComponentPickerContext();
const { showOnlyPublished } = usePublishedFilterContext();
const { setCollectionId } = useOptionalLibraryContext();
@@ -133,9 +133,11 @@ const CollectionCard = ({ hit } : CollectionCardProps) => {
published,
} = hit;
- const numChildrenCount = showOnlyPublished ? (
- published?.numChildren || 0
- ) : numChildren;
+ const numChildrenCount = showOnlyPublished ?
+ (
+ published?.numChildren || 0
+ ) :
+ numChildren;
const { displayName = '', description = '' } = formatted;
diff --git a/src/library-authoring/components/ComponentCard.test.tsx b/src/library-authoring/components/ComponentCard.test.tsx
index 530b4f4c4f..5c29ad98fb 100644
--- a/src/library-authoring/components/ComponentCard.test.tsx
+++ b/src/library-authoring/components/ComponentCard.test.tsx
@@ -50,17 +50,18 @@ const contentHit: ContentHit = {
};
const { libraryId } = mockContentLibrary;
-const render = (libId: string = libraryId) => baseRender(
, {
- path: '/library/:libraryId',
- params: { libraryId: libId },
- extraWrapper: ({ children }) => (
-
-
- { children }
-
-
- ),
-});
+const render = (libId: string = libraryId) =>
+ baseRender(
, {
+ path: '/library/:libraryId',
+ params: { libraryId: libId },
+ extraWrapper: ({ children }) => (
+
+
+ {children}
+
+
+ ),
+ });
describe('
', () => {
beforeEach(() => {
diff --git a/src/library-authoring/components/ComponentCard.tsx b/src/library-authoring/components/ComponentCard.tsx
index 2317f33f3e..d7c3fd65b3 100644
--- a/src/library-authoring/components/ComponentCard.tsx
+++ b/src/library-authoring/components/ComponentCard.tsx
@@ -12,7 +12,7 @@ import BaseCard from './BaseCard';
import { ComponentMenu } from './ComponentMenu';
type ComponentCardProps = {
- hit: ContentHit,
+ hit: ContentHit;
};
const ComponentCard = ({ hit }: ComponentCardProps) => {
@@ -53,15 +53,13 @@ const ComponentCard = ({ hit }: ComponentCardProps) => {
displayName={displayName}
description={componentDescription}
tags={tags}
- actions={(
+ actions={
- {componentPickerMode ? (
-
- ) : (
-
- )}
+ {componentPickerMode ?
+ :
+ }
- )}
+ }
hasUnpublishedChanges={publishStatus !== PublishStatus.Published}
onSelect={selectComponent}
selected={selected}
diff --git a/src/library-authoring/components/ComponentDeleter.test.tsx b/src/library-authoring/components/ComponentDeleter.test.tsx
index 4d98547764..2c66753caa 100644
--- a/src/library-authoring/components/ComponentDeleter.test.tsx
+++ b/src/library-authoring/components/ComponentDeleter.test.tsx
@@ -10,7 +10,10 @@ import {
import { LibraryProvider } from '../common/context/LibraryContext';
import { SidebarProvider } from '../common/context/SidebarContext';
import {
- mockContentLibrary, mockDeleteLibraryBlock, mockLibraryBlockMetadata, mockRestoreLibraryBlock,
+ mockContentLibrary,
+ mockDeleteLibraryBlock,
+ mockLibraryBlockMetadata,
+ mockRestoreLibraryBlock,
} from '../data/api.mocks';
import ComponentDeleter from './ComponentDeleter';
@@ -29,7 +32,7 @@ const renderArgs = {
extraWrapper: ({ children }) => (
- { children }
+ {children}
),
@@ -105,9 +108,11 @@ describe('
', () => {
const modal = await screen.findByRole('dialog', { name: 'Delete Component' });
expect(modal).toBeVisible();
- expect(await screen.findByText(
- /by deleting this component, you will also be deleting it from in this library\./i,
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ /by deleting this component, you will also be deleting it from in this library\./i,
+ ),
+ ).toBeInTheDocument();
expect(screen.getByText(/unit 1/i)).toBeInTheDocument();
});
@@ -131,9 +136,11 @@ describe('
', () => {
const modal = await screen.findByRole('dialog', { name: 'Delete Component' });
expect(modal).toBeVisible();
- expect(await screen.findByText(
- /by deleting this component, you will also be deleting it from in this library\./i,
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ /by deleting this component, you will also be deleting it from in this library\./i,
+ ),
+ ).toBeInTheDocument();
expect(screen.getByText(/2 units/i)).toBeInTheDocument();
});
});
diff --git a/src/library-authoring/components/ComponentDeleter.tsx b/src/library-authoring/components/ComponentDeleter.tsx
index e3149ee18b..24e42d1418 100644
--- a/src/library-authoring/components/ComponentDeleter.tsx
+++ b/src/library-authoring/components/ComponentDeleter.tsx
@@ -29,7 +29,10 @@ const ComponentDeleter = ({ usageKey, close }: Props) => {
const sidebarComponentUsageKey = sidebarItemInfo?.id;
const restoreComponentMutation = useRestoreLibraryBlock();
- const { data: dataDownstreamLinks, isPending: isPendingLinks } = useEntityLinks({ upstreamKey: usageKey, contentType: 'components' });
+ const { data: dataDownstreamLinks, isPending: isPendingLinks } = useEntityLinks({
+ upstreamKey: usageKey,
+ contentType: 'components',
+ });
const downstreamCount = dataDownstreamLinks?.length ?? 0;
const restoreComponent = useCallback(async () => {
diff --git a/src/library-authoring/components/ComponentEditorModal.tsx b/src/library-authoring/components/ComponentEditorModal.tsx
index 3175db0d6a..51c77b1761 100644
--- a/src/library-authoring/components/ComponentEditorModal.tsx
+++ b/src/library-authoring/components/ComponentEditorModal.tsx
@@ -29,7 +29,7 @@ export const ComponentEditorModal: React.FC
> = () => {
}
const blockType = componentBeingEdited.blockType || getBlockType(componentBeingEdited.usageKey);
- const onClose = (data?:any) => {
+ const onClose = (data?: any) => {
closeComponentEditor(data);
invalidateComponentData(queryClient, libraryId, componentBeingEdited.usageKey);
};
diff --git a/src/library-authoring/components/ComponentMenu.tsx b/src/library-authoring/components/ComponentMenu.tsx
index 6e07dc6d73..44a974de61 100644
--- a/src/library-authoring/components/ComponentMenu.tsx
+++ b/src/library-authoring/components/ComponentMenu.tsx
@@ -13,7 +13,11 @@ import { getBlockType } from '@src/generic/key-utils';
import { ToastContext } from '@src/generic/toast-context';
import { useOptionalLibraryContext } from '@src/library-authoring/common/context/LibraryContext';
-import { SidebarActions, SidebarBodyItemId, useSidebarContext } from '@src/library-authoring/common/context/SidebarContext';
+import {
+ SidebarActions,
+ SidebarBodyItemId,
+ useSidebarContext,
+} from '@src/library-authoring/common/context/SidebarContext';
import { useRemoveItemsFromCollection } from '@src/library-authoring/data/apiHooks';
import containerMessages from '@src/library-authoring/containers/messages';
import { useLibraryRoutes } from '@src/library-authoring/routes';
diff --git a/src/library-authoring/components/PublicReadToggle.tsx b/src/library-authoring/components/PublicReadToggle.tsx
index 635a0a0902..2369f9f398 100644
--- a/src/library-authoring/components/PublicReadToggle.tsx
+++ b/src/library-authoring/components/PublicReadToggle.tsx
@@ -30,9 +30,7 @@ const PublicReadToggle = ({ libraryId, canEditToggle }: PublicReadToggleProps) =
checked={library?.allowPublicRead}
disabled={!canEditToggle || isPending}
onChange={onChangeToggle}
- helperText={
- {formatMessage(messages.publicReadToggleSubtext)}
- }
+ helperText={{formatMessage(messages.publicReadToggleSubtext)} }
>
{formatMessage(messages.publicReadToggleLabel)}
diff --git a/src/library-authoring/containers/ContainerCard.test.tsx b/src/library-authoring/containers/ContainerCard.test.tsx
index 3aa3f562d2..a9ae5135ea 100644
--- a/src/library-authoring/containers/ContainerCard.test.tsx
+++ b/src/library-authoring/containers/ContainerCard.test.tsx
@@ -3,7 +3,10 @@ import type MockAdapter from 'axios-mock-adapter';
import { mockContentSearchConfig, mockSearchResult, hydrateSearchResult } from '@src/search-manager/data/api.mock';
import {
- initializeMocks, render as baseRender, screen, waitFor,
+ initializeMocks,
+ render as baseRender,
+ screen,
+ waitFor,
fireEvent,
} from '@src/testUtils';
import { PublishedFilterContextProvider } from '@src/library-authoring/common/context/PublishedFilterContext';
@@ -61,7 +64,7 @@ jest.mock('react-router-dom', () => ({
const render = (
ui: React.ReactElement,
showOnlyPublished: boolean = false,
- containerContext?: { type: ContainerType, id: string },
+ containerContext?: { type: ContainerType; id: string; },
) => {
const path = containerContext
? `/library/:libraryId/${containerContext.type}/:containerId`
@@ -432,7 +435,10 @@ describe(' ', () => {
expectedRemoveText: 'Remove from section',
},
])('$label', async ({
- containerType, parentType, parentId, expectedRemoveText,
+ containerType,
+ parentType,
+ parentId,
+ expectedRemoveText,
}) => {
const containerHit = getContainerHitSample(containerType);
axiosMock.onDelete(getLibraryContainerChildrenApiUrl(parentId)).reply(200);
diff --git a/src/library-authoring/containers/ContainerCard.tsx b/src/library-authoring/containers/ContainerCard.tsx
index 14a224cdcb..ad8a555120 100644
--- a/src/library-authoring/containers/ContainerCard.tsx
+++ b/src/library-authoring/containers/ContainerCard.tsx
@@ -19,7 +19,11 @@ import { useRunOnNextRender } from '@src/utils';
import { useComponentPickerContext } from '@src/library-authoring/common/context/ComponentPickerContext';
import { useOptionalLibraryContext } from '@src/library-authoring/common/context/LibraryContext';
-import { SidebarActions, SidebarBodyItemId, useSidebarContext } from '@src/library-authoring/common/context/SidebarContext';
+import {
+ SidebarActions,
+ SidebarBodyItemId,
+ useSidebarContext,
+} from '@src/library-authoring/common/context/SidebarContext';
import { useRemoveItemsFromCollection } from '@src/library-authoring/data/apiHooks';
import { useLibraryRoutes } from '@src/library-authoring/routes';
import BaseCard from '@src/library-authoring/components/BaseCard';
@@ -35,10 +39,13 @@ type ContainerMenuProps = {
index?: number;
};
-export const ContainerMenu = ({ containerKey, displayName, index } : ContainerMenuProps) => {
+export const ContainerMenu = ({ containerKey, displayName, index }: ContainerMenuProps) => {
const intl = useIntl();
const {
- libraryId, collectionId, containerId, readOnly,
+ libraryId,
+ collectionId,
+ containerId,
+ readOnly,
} = useOptionalLibraryContext();
const {
sidebarItemInfo,
@@ -62,7 +69,7 @@ export const ContainerMenu = ({ containerKey, displayName, index } : ContainerMe
const handleRemoveFromCollection = () => {
removeComponentsMutation.mutateAsync([containerKey]).then(() => {
if (sidebarItemInfo?.id === containerKey) {
- // Close sidebar if current component is open
+ // Close sidebar if current component is open
closeLibrarySidebar();
}
showToast(intl.formatMessage(messages.removeComponentFromCollectionSuccess));
@@ -169,46 +176,44 @@ const UnitcardPreview = ({ childKeys, showMaxChildren = 5 }: UnitCardPreviewProp
const hiddenChildren = childKeys.length - showMaxChildren;
return (
- {
- childKeys.slice(0, showMaxChildren).map((usageKey, idx) => {
- const blockType = getBlockType(usageKey);
- let blockPreview: ReactNode;
-
- if (idx < showMaxChildren - 1 || hiddenChildren <= 0) {
- // Show the first N-1 blocks as item icons
- // (or all N blocks if no hidden children)
- blockPreview = (
-
- );
- } else {
- // Container has more blocks than can fit in the preview, so show "+N"
- blockPreview = (
-
- );
- }
- return (
-
- {blockPreview}
-
+ {childKeys.slice(0, showMaxChildren).map((usageKey, idx) => {
+ const blockType = getBlockType(usageKey);
+ let blockPreview: ReactNode;
+
+ if (idx < showMaxChildren - 1 || hiddenChildren <= 0) {
+ // Show the first N-1 blocks as item icons
+ // (or all N blocks if no hidden children)
+ blockPreview = (
+
);
- })
- }
+ } else {
+ // Container has more blocks than can fit in the preview, so show "+N"
+ blockPreview = (
+
+ );
+ }
+ return (
+
+ {blockPreview}
+
+ );
+ })}
);
};
type ContainerCardPreviewProps = {
- hit: ContainerHit,
+ hit: ContainerHit;
};
const ContainerCardPreview = ({ hit }: ContainerCardPreviewProps) => {
@@ -253,10 +258,10 @@ const ContainerCardPreview = ({ hit }: ContainerCardPreviewProps) => {
};
type ContainerCardProps = {
- hit: ContainerHit,
+ hit: ContainerHit;
};
-const ContainerCard = ({ hit } : ContainerCardProps) => {
+const ContainerCard = ({ hit }: ContainerCardProps) => {
const { componentPickerMode } = useComponentPickerContext();
const { showOnlyPublished } = usePublishedFilterContext();
const { openContainerInfoSidebar, openItemSidebar, sidebarItemInfo } = useSidebarContext();
@@ -271,9 +276,11 @@ const ContainerCard = ({ hit } : ContainerCardProps) => {
usageKey: containerKey,
} = hit;
- const numChildrenCount = showOnlyPublished ? (
- published?.numChildren || 0
- ) : numChildren;
+ const numChildrenCount = showOnlyPublished ?
+ (
+ published?.numChildren || 0
+ ) :
+ numChildren;
const displayName: string = (
showOnlyPublished ? formatted.published?.displayName : formatted.displayName
@@ -303,15 +310,13 @@ const ContainerCard = ({ hit } : ContainerCardProps) => {
preview={ }
tags={tags}
numChildren={numChildrenCount}
- actions={(
+ actions={
- {componentPickerMode ? (
-
- ) : (
-
- )}
+ {componentPickerMode ?
+ :
+ }
- )}
+ }
hasUnpublishedChanges={publishStatus !== PublishStatus.Published}
onSelect={selectContainer}
selected={selected}
diff --git a/src/library-authoring/containers/ContainerDeleter.test.tsx b/src/library-authoring/containers/ContainerDeleter.test.tsx
index 829df4f58d..5a2d7c058f 100644
--- a/src/library-authoring/containers/ContainerDeleter.test.tsx
+++ b/src/library-authoring/containers/ContainerDeleter.test.tsx
@@ -45,7 +45,7 @@ const renderArgs = {
extraWrapper: ({ children }) => (
- { children }
+ {children}
),
@@ -71,10 +71,13 @@ let mockShowToast: { (message: string, action?: ToastActionData): void; mock?: a
it(`<${context}> should show a confirmation prompt the card with title and description`, async () => {
const mockCancel = jest.fn();
const { containerId } = getContainerDetails(context);
- render( , renderArgs);
+ render(
+ ,
+ renderArgs,
+ );
const modal = await screen.findByRole('dialog', { name: new RegExp(`Delete ${context}`, 'i') });
expect(modal).toBeVisible();
@@ -137,8 +140,11 @@ let mockShowToast: { (message: string, action?: ToastActionData): void; mock?: a
const modal = await screen.findByRole('dialog', { name: new RegExp(`Delete ${context}`, 'i') });
expect(modal).toBeVisible();
- const textMatch = new RegExp(`By deleting this ${context}, you will also be deleting it from ${parent} 1 in this library.`);
- expect((await screen.findAllByText((_, element) => textMatch.test(element?.textContent || ''))).length).toBeGreaterThan(0);
+ const textMatch = new RegExp(
+ `By deleting this ${context}, you will also be deleting it from ${parent} 1 in this library.`,
+ );
+ expect((await screen.findAllByText((_, element) => textMatch.test(element?.textContent || ''))).length)
+ .toBeGreaterThan(0);
});
it(`<${context}> should show parents message if parents is set with multiple parents`, async () => {
@@ -165,8 +171,12 @@ let mockShowToast: { (message: string, action?: ToastActionData): void; mock?: a
const modal = await screen.findByRole('dialog', { name: new RegExp(`Delete ${context}`, 'i') });
expect(modal).toBeVisible();
- const textMatch = new RegExp(`By deleting this ${context}, you will also be deleting it from 2 ${parent}s in this library.`, 'i');
- expect((await screen.findAllByText((_, element) => textMatch.test(element?.textContent || ''))).length).toBeGreaterThan(0);
+ const textMatch = new RegExp(
+ `By deleting this ${context}, you will also be deleting it from 2 ${parent}s in this library.`,
+ 'i',
+ );
+ expect((await screen.findAllByText((_, element) => textMatch.test(element?.textContent || ''))).length)
+ .toBeGreaterThan(0);
});
});
});
diff --git a/src/library-authoring/containers/ContainerDeleter.tsx b/src/library-authoring/containers/ContainerDeleter.tsx
index 6538e05386..db32b4a225 100644
--- a/src/library-authoring/containers/ContainerDeleter.tsx
+++ b/src/library-authoring/containers/ContainerDeleter.tsx
@@ -15,13 +15,13 @@ import { useContentFromSearchIndex, useDeleteContainer, useRestoreContainer } fr
import messages from './messages';
type ContainerDeleterProps = {
- close: () => void,
- containerId: string,
+ close: () => void;
+ containerId: string;
};
type ContainerParents = {
- displayName?: string[],
- key?: string[],
+ displayName?: string[];
+ key?: string[];
};
const getOtherParentContainers = (containerParents?: ContainerParents, currentParentId?: string) => {
diff --git a/src/library-authoring/containers/ContainerInfo.test.tsx b/src/library-authoring/containers/ContainerInfo.test.tsx
index c274a753c4..3273ccb1a5 100644
--- a/src/library-authoring/containers/ContainerInfo.test.tsx
+++ b/src/library-authoring/containers/ContainerInfo.test.tsx
@@ -2,7 +2,10 @@ import userEvent from '@testing-library/user-event';
import type MockAdapter from 'axios-mock-adapter';
import {
- initializeMocks, render as baseRender, screen, waitFor,
+ initializeMocks,
+ render as baseRender,
+ screen,
+ waitFor,
fireEvent,
within,
} from '@src/testUtils';
@@ -103,7 +106,7 @@ const render = (
containerType: string = '', // renders container page
showOnlyPublished: boolean = false,
) => {
- const params: { libraryId: string, selectedItemId?: string } = { libraryId, selectedItemId: containerId };
+ const params: { libraryId: string; selectedItemId?: string; } = { libraryId, selectedItemId: containerId };
const path = containerType
? `/library/:libraryId/${containerType}/:selectedItemId?`
: '/library/:libraryId/:selectedItemId?';
@@ -187,7 +190,9 @@ let mockShowToast: { (message: string, action?: ToastActionData): void; mock?: a
fireEvent.click(deleteMenuItem);
// Confirm delete Modal is open
- const modal = await screen.findByRole('dialog', { name: `Delete ${containerType[0].toUpperCase()}${containerType.slice(1)}` });
+ const modal = await screen.findByRole('dialog', {
+ name: `Delete ${containerType[0].toUpperCase()}${containerType.slice(1)}`,
+ });
expect(modal).toBeInTheDocument();
const deleteButton = screen.getByRole('button', { name: /delete/i });
fireEvent.click(deleteButton);
@@ -239,15 +244,19 @@ let mockShowToast: { (message: string, action?: ToastActionData): void; mock?: a
// Reveals the confirmation box with warning text and publish hierarchy
expect(await screen.findByText('Confirm Publish')).toBeInTheDocument();
- expect(screen.getByText(new RegExp(
- `This ${containerType} and the ${childType}s it contains will all be`, // published
- 'i',
- ))).toBeInTheDocument();
- if (parentCount > 0) {
- expect(screen.getByText(new RegExp(
- `Its parent ${parentType}s will be`, // draft
+ expect(screen.getByText(
+ new RegExp(
+ `This ${containerType} and the ${childType}s it contains will all be`, // published
'i',
- ))).toBeInTheDocument();
+ ),
+ )).toBeInTheDocument();
+ if (parentCount > 0) {
+ expect(screen.getByText(
+ new RegExp(
+ `Its parent ${parentType}s will be`, // draft
+ 'i',
+ ),
+ )).toBeInTheDocument();
}
expect(screen.queryAllByText('Will Publish').length).toBe(willPublishCount);
expect(screen.queryAllByText('Draft').length).toBe(4 - willPublishCount);
@@ -308,15 +317,19 @@ let mockShowToast: { (message: string, action?: ToastActionData): void; mock?: a
expect(publishButton).not.toBeInTheDocument();
// Check warning text in the confirmation box
- expect(screen.getByText(new RegExp(
- `This ${containerType} and the ${childType} it contains will all be`, // published
- 'i',
- ))).toBeInTheDocument();
- if (parentCount) {
- expect(screen.getByText(new RegExp(
- `Its parent ${parentType} will be`, // draft
+ expect(screen.getByText(
+ new RegExp(
+ `This ${containerType} and the ${childType} it contains will all be`, // published
'i',
- ))).toBeInTheDocument();
+ ),
+ )).toBeInTheDocument();
+ if (parentCount) {
+ expect(screen.getByText(
+ new RegExp(
+ `Its parent ${parentType} will be`, // draft
+ 'i',
+ ),
+ )).toBeInTheDocument();
}
});
@@ -331,10 +344,14 @@ let mockShowToast: { (message: string, action?: ToastActionData): void; mock?: a
expect(publishButton).not.toBeInTheDocument();
// Check warning text in the confirmation box
- expect(await screen.findByText(new RegExp(
- `This ${containerType} will be`, // published
- 'i',
- ))).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ new RegExp(
+ `This ${containerType} will be`, // published
+ 'i',
+ ),
+ ),
+ ).toBeInTheDocument();
});
it(`show only published ${containerType} content`, async () => {
@@ -363,9 +380,11 @@ let mockShowToast: { (message: string, action?: ToastActionData): void; mock?: a
const child = await screen.findByText(`${childTypeDisplayName} block 0`);
// Check that there are no menu buttons for containers
- expect(within(
- child.parentElement!.parentElement!.parentElement!,
- ).queryAllByRole('button', { name: /container actions menu/i }).length).toBe(0);
+ expect(
+ within(
+ child.parentElement!.parentElement!.parentElement!,
+ ).queryAllByRole('button', { name: /container actions menu/i }).length,
+ ).toBe(0);
// Trigger double click. Find the child card as the parent element
await user.dblClick(child.parentElement!.parentElement!.parentElement!);
// Click should not do anything in preview
diff --git a/src/library-authoring/containers/ContainerInfo.tsx b/src/library-authoring/containers/ContainerInfo.tsx
index 07c245158e..04ef490a27 100644
--- a/src/library-authoring/containers/ContainerInfo.tsx
+++ b/src/library-authoring/containers/ContainerInfo.tsx
@@ -36,7 +36,7 @@ import { ContainerPublisher } from './ContainerPublisher';
import { PublishDraftButton, PublishedChip } from '../generic/publish-status-buttons';
type ContainerPreviewProps = {
- containerId: string,
+ containerId: string;
};
const ContainerMenu = ({ containerId }: ContainerPreviewProps) => {
@@ -81,7 +81,7 @@ const ContainerMenu = ({ containerId }: ContainerPreviewProps) => {
);
};
-const ContainerPreview = ({ containerId } : ContainerPreviewProps) => {
+const ContainerPreview = ({ containerId }: ContainerPreviewProps) => {
const containerType = getBlockType(containerId);
if (containerType === ContainerType.Unit) {
return ;
@@ -94,9 +94,9 @@ const ContainerActions = ({
containerType,
hasUnpublishedChanges,
}: {
- containerId: string,
- containerType: string,
- hasUnpublishedChanges: boolean,
+ containerId: string;
+ containerType: string;
+ hasUnpublishedChanges: boolean;
}) => {
const intl = useIntl();
const { libraryId } = useOptionalLibraryContext();
@@ -130,17 +130,19 @@ const ContainerActions = ({
)}
{!componentPickerMode && (
- !hasUnpublishedChanges ? (
-
- ) : (
-
- )
+ !hasUnpublishedChanges ?
+ (
+
+ ) :
+ (
+
+ )
)}
{showOpenButton && (
@@ -176,8 +178,10 @@ const ContainerInfo = () => {
const defaultContainerTab = defaultTab.container;
const tab: ContainerInfoTab = (
- sidebarTab && isContainerInfoTab(sidebarTab)
- ) ? sidebarTab : defaultContainerTab;
+ sidebarTab && isContainerInfoTab(sidebarTab)
+ ) ?
+ sidebarTab :
+ defaultContainerTab;
/* istanbul ignore next */
const handleTabChange = (newTab: ContainerInfoTab) => {
diff --git a/src/library-authoring/containers/ContainerInfoHeader.test.tsx b/src/library-authoring/containers/ContainerInfoHeader.test.tsx
index bf2e1d6b00..13a1d616be 100644
--- a/src/library-authoring/containers/ContainerInfoHeader.test.tsx
+++ b/src/library-authoring/containers/ContainerInfoHeader.test.tsx
@@ -27,20 +27,21 @@ const {
const { unitId: containerId } = mockGetContainerMetadata;
-const render = (libraryId: string = mockLibraryId) => baseRender(
, {
- extraWrapper: ({ children }) => (
-
-
- { children }
-
-
- ),
-});
+const render = (libraryId: string = mockLibraryId) =>
+ baseRender(
, {
+ extraWrapper: ({ children }) => (
+
+
+ {children}
+
+
+ ),
+ });
describe('
', () => {
beforeEach(() => {
diff --git a/src/library-authoring/containers/ContainerOrganize.test.tsx b/src/library-authoring/containers/ContainerOrganize.test.tsx
index 3e5c33f97e..91e97bc0d5 100644
--- a/src/library-authoring/containers/ContainerOrganize.test.tsx
+++ b/src/library-authoring/containers/ContainerOrganize.test.tsx
@@ -14,7 +14,7 @@ import ContainerOrganize from './ContainerOrganize';
jest.mock('../../content-tags-drawer', () => ({
...jest.requireActual('../../content-tags-drawer'),
- ContentTagsDrawer: ({ readOnly }: { readOnly: boolean }) => (
+ ContentTagsDrawer: ({ readOnly }: { readOnly: boolean; }) => (
Mocked {readOnly ? 'read-only' : 'editable'} ContentTagsDrawer
),
}));
@@ -29,20 +29,21 @@ const render = ({
}: {
libraryId?: string;
containerId?: string;
-}) => baseRender(
, {
- extraWrapper: ({ children }) => (
-
-
- {children}
-
-
- ),
-});
+}) =>
+ baseRender(
, {
+ extraWrapper: ({ children }) => (
+
+
+ {children}
+
+
+ ),
+ });
describe('
', () => {
beforeEach(() => {
diff --git a/src/library-authoring/containers/ContainerOrganize.tsx b/src/library-authoring/containers/ContainerOrganize.tsx
index c0d3502268..aebcb525f6 100644
--- a/src/library-authoring/containers/ContainerOrganize.tsx
+++ b/src/library-authoring/containers/ContainerOrganize.tsx
@@ -23,7 +23,7 @@ import messages from './messages';
const ContainerOrganize = () => {
const intl = useIntl();
- const [tagsCollapseIsOpen, ,setTagsCollapseClose, toggleTags] = useToggle(true);
+ const [tagsCollapseIsOpen, , setTagsCollapseClose, toggleTags] = useToggle(true);
const [collectionsCollapseIsOpen, setCollectionsCollapseOpen, , toggleCollections] = useToggle(true);
const { readOnly } = useOptionalLibraryContext();
@@ -53,7 +53,7 @@ const ContainerOrganize = () => {
}
let result = 0;
componentTags.taxonomies.forEach((taxonomy) => {
- const countedTags : string[] = [];
+ const countedTags: string[] = [];
taxonomy.tags.forEach((tagData) => {
tagData.lineage.forEach((tag) => {
if (!countedTags.includes(tag)) {
diff --git a/src/library-authoring/containers/ContainerRemover.test.tsx b/src/library-authoring/containers/ContainerRemover.test.tsx
index 7a4945238d..8f17f7eff6 100644
--- a/src/library-authoring/containers/ContainerRemover.test.tsx
+++ b/src/library-authoring/containers/ContainerRemover.test.tsx
@@ -54,12 +54,14 @@ describe('
', () => {
axiosMock.onPatch(url).reply(200);
const result = await mockGetContainerChildren(mockGetContainerChildren.unitIdWithDuplicate);
const resultIds = result.map((obj) => obj.id);
- renderModal(
);
+ renderModal(
+
,
+ );
const btn = await screen.findByRole('button', { name: 'Remove' });
await user.click(btn);
diff --git a/src/library-authoring/containers/ContainerRemover.tsx b/src/library-authoring/containers/ContainerRemover.tsx
index 54acea653a..326c2c4204 100644
--- a/src/library-authoring/containers/ContainerRemover.tsx
+++ b/src/library-authoring/containers/ContainerRemover.tsx
@@ -10,17 +10,20 @@ import { getBlockType } from '@src/generic/key-utils';
import { useSidebarContext } from '@src/library-authoring/common/context/SidebarContext';
import { useOptionalLibraryContext } from '@src/library-authoring/common/context/LibraryContext';
import {
- useContainer, useContainerChildren, useRemoveContainerChildren, useUpdateContainerChildren,
+ useContainer,
+ useContainerChildren,
+ useRemoveContainerChildren,
+ useUpdateContainerChildren,
} from '@src/library-authoring/data/apiHooks';
import messages from '@src/library-authoring/components/messages';
import { Container } from '@src/library-authoring/data/api';
import { usePublishedFilterContext } from '@src/library-authoring/common/context/PublishedFilterContext';
type ContainerRemoverProps = {
- close: () => void,
- containerKey: string,
- displayName: string,
- index?: number,
+ close: () => void;
+ containerKey: string;
+ displayName: string;
+ index?: number;
};
const ContainerRemover = ({
diff --git a/src/library-authoring/containers/index.tsx b/src/library-authoring/containers/index.tsx
index 69a1596f56..026ddedd1d 100644
--- a/src/library-authoring/containers/index.tsx
+++ b/src/library-authoring/containers/index.tsx
@@ -1,5 +1,5 @@
+export { ContainerEditableTitle } from './ContainerEditableTitle';
export { default as ContainerInfo } from './ContainerInfo';
export { default as ContainerInfoHeader } from './ContainerInfoHeader';
-export { ContainerEditableTitle } from './ContainerEditableTitle';
-export { HeaderActions } from './HeaderActions';
export { FooterActions } from './FooterActions';
+export { HeaderActions } from './HeaderActions';
diff --git a/src/library-authoring/create-collection/CreateCollectionModal.tsx b/src/library-authoring/create-collection/CreateCollectionModal.tsx
index 175b02ea85..6582115bf4 100644
--- a/src/library-authoring/create-collection/CreateCollectionModal.tsx
+++ b/src/library-authoring/create-collection/CreateCollectionModal.tsx
@@ -57,13 +57,11 @@ const CreateCollectionModal = () => {
title: '',
description: '',
}}
- validationSchema={
- Yup.object().shape({
- title: Yup.string()
- .required(intl.formatMessage(messages.createCollectionModalNameInvalid)),
- description: Yup.string(),
- })
- }
+ validationSchema={Yup.object().shape({
+ title: Yup.string()
+ .required(intl.formatMessage(messages.createCollectionModalNameInvalid)),
+ description: Yup.string(),
+ })}
onSubmit={handleCreate}
>
{(formikProps) => (
@@ -71,11 +69,11 @@ const CreateCollectionModal = () => {
{intl.formatMessage(messages.createCollectionModalNameLabel)}
- )}
+ }
value={formikProps.values.title}
placeholder={intl.formatMessage(messages.createCollectionModalNamePlaceholder)}
controlClasses="pb-2"
@@ -83,18 +81,18 @@ const CreateCollectionModal = () => {
{intl.formatMessage(messages.createCollectionModalDescriptionLabel)}
- )}
+ }
value={formikProps.values.description}
placeholder={intl.formatMessage(messages.createCollectionModalDescriptionPlaceholder)}
- help={(
+ help={
{intl.formatMessage(messages.createCollectionModalDescriptionDetails)}
- )}
+ }
controlClasses="pb-2"
rows="5"
/>
diff --git a/src/library-authoring/create-container/CreateContainerModal.test.tsx b/src/library-authoring/create-container/CreateContainerModal.test.tsx
index a6523bf124..e7c582d029 100644
--- a/src/library-authoring/create-container/CreateContainerModal.test.tsx
+++ b/src/library-authoring/create-container/CreateContainerModal.test.tsx
@@ -1,6 +1,9 @@
import userEvent from '@testing-library/user-event';
import {
- render, screen, waitFor, initializeMocks,
+ render,
+ screen,
+ waitFor,
+ initializeMocks,
} from '../../testUtils';
import { LibraryProvider } from '../common/context/LibraryContext';
import CreateContainerModal from './CreateContainerModal';
diff --git a/src/library-authoring/create-container/CreateContainerModal.tsx b/src/library-authoring/create-container/CreateContainerModal.tsx
index ffc6ef50f2..2d8a8a655a 100644
--- a/src/library-authoring/create-container/CreateContainerModal.tsx
+++ b/src/library-authoring/create-container/CreateContainerModal.tsx
@@ -127,12 +127,10 @@ const CreateContainerModal = () => {
initialValues={{
displayName: '',
}}
- validationSchema={
- Yup.object().shape({
- displayName: Yup.string()
- .required(labels.validationError),
- })
- }
+ validationSchema={Yup.object().shape({
+ displayName: Yup.string()
+ .required(labels.validationError),
+ })}
onSubmit={handleCreate}
>
{(formikProps) => (
@@ -140,11 +138,11 @@ const CreateContainerModal = () => {
{labels.nameLabel}
- )}
+ }
value={formikProps.values.displayName}
placeholder={labels.placeholder}
controlClasses="pb-2"
diff --git a/src/library-authoring/create-legacy-library/CreateLegacyLibrary.tsx b/src/library-authoring/create-legacy-library/CreateLegacyLibrary.tsx
index 260cab0cee..373c38f90a 100644
--- a/src/library-authoring/create-legacy-library/CreateLegacyLibrary.tsx
+++ b/src/library-authoring/create-legacy-library/CreateLegacyLibrary.tsx
@@ -41,9 +41,9 @@ export const CreateLegacyLibrary = ({
handleCancel,
handlePostCreate,
}: {
- showInModal?: boolean,
- handleCancel?: () => void,
- handlePostCreate?: (library: LibraryV1Data) => void,
+ showInModal?: boolean;
+ handleCancel?: () => void;
+ handlePostCreate?: (library: LibraryV1Data) => void;
}) => {
const intl = useIntl();
const navigate = useNavigate();
@@ -95,7 +95,7 @@ export const CreateLegacyLibrary = ({
return (
<>
- {!showInModal && ()}
+ {!showInModal && }
{!showInModal && (
mutate(values)}
>
{(formikProps) => (
@@ -159,17 +157,17 @@ export const CreateLegacyLibrary = ({
formikProps.setFieldValue(
- 'org',
- allowToCreateNewOrg
- ? (event.selectionId || event.userProvidedText)
- : event.selectionId,
- )}
+ onChange={(event) =>
+ formikProps.setFieldValue(
+ 'org',
+ allowToCreateNewOrg
+ ? (event.selectionId || event.userProvidedText)
+ : event.selectionId,
+ )}
placeholder={intl.formatMessage(messages.orgPlaceholder)}
>
- {organizations.map((org) => (
- {org}
- ))}
+ {organizations.map((org) => {org}
+ )}
{intl.formatMessage(messages.orgHelp)}
@@ -184,14 +182,13 @@ export const CreateLegacyLibrary = ({
className=""
controlClasses="pb-2"
/>
-
)}
- {isError && ( )}
+ {isError && }
- {!showInModal && ( )}
+ {!showInModal && }
>
);
};
diff --git a/src/library-authoring/create-legacy-library/data/api.ts b/src/library-authoring/create-legacy-library/data/api.ts
index 8652eb8a69..2ba9425fdb 100644
--- a/src/library-authoring/create-legacy-library/data/api.ts
+++ b/src/library-authoring/create-legacy-library/data/api.ts
@@ -9,9 +9,9 @@ import type { LibraryV1Data } from '@src/studio-home/data/api';
export const getContentLibraryV1CreateApiUrl = () => `${getConfig().STUDIO_BASE_URL}/library/`;
export interface CreateContentLibraryV1Args {
- displayName: string,
- org: string,
- number: string,
+ displayName: string;
+ org: string;
+ number: string;
}
/**
diff --git a/src/library-authoring/create-library/CreateLibrary.test.tsx b/src/library-authoring/create-library/CreateLibrary.test.tsx
index adbb823d75..c082d5ef58 100644
--- a/src/library-authoring/create-library/CreateLibrary.test.tsx
+++ b/src/library-authoring/create-library/CreateLibrary.test.tsx
@@ -281,7 +281,9 @@ describe(' ', () => {
render( );
- const createFromArchiveBtn = await screen.findByRole('button', { name: messages.createFromArchiveButton.defaultMessage });
+ const createFromArchiveBtn = await screen.findByRole('button', {
+ name: messages.createFromArchiveButton.defaultMessage,
+ });
expect(createFromArchiveBtn).toBeInTheDocument();
await user.click(createFromArchiveBtn);
@@ -301,7 +303,9 @@ describe(' ', () => {
render( );
// Switch to archive mode
- const createFromArchiveBtn = await screen.findByRole('button', { name: messages.createFromArchiveButton.defaultMessage });
+ const createFromArchiveBtn = await screen.findByRole('button', {
+ name: messages.createFromArchiveButton.defaultMessage,
+ });
await user.click(createFromArchiveBtn);
// Create a mock file
@@ -334,7 +338,7 @@ describe(' ', () => {
axiosMock.onGet(getStudioHomeApiUrl()).reply(200, studioHomeMock);
// Mock console.error to capture the call
- const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => { });
+ const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
// Mock the restore mutation to trigger onError callback immediately
mockRestoreMutate.mockImplementation((_file: File, { onError }: any) => {
@@ -346,7 +350,9 @@ describe(' ', () => {
render( );
// Switch to archive mode
- const createFromArchiveBtn = await screen.findByRole('button', { name: messages.createFromArchiveButton.defaultMessage });
+ const createFromArchiveBtn = await screen.findByRole('button', {
+ name: messages.createFromArchiveButton.defaultMessage,
+ });
await user.click(createFromArchiveBtn);
// Upload a valid file that will trigger the restore process and its onError callback
@@ -397,7 +403,9 @@ describe(' ', () => {
render( );
// Switch to archive mode
- const createFromArchiveBtn = await screen.findByRole('button', { name: messages.createFromArchiveButton.defaultMessage });
+ const createFromArchiveBtn = await screen.findByRole('button', {
+ name: messages.createFromArchiveButton.defaultMessage,
+ });
await user.click(createFromArchiveBtn);
// Upload a file to trigger the restore process
@@ -459,7 +467,9 @@ describe(' ', () => {
render( );
// Switch to archive mode
- const createFromArchiveBtn = await screen.findByRole('button', { name: messages.createFromArchiveButton.defaultMessage });
+ const createFromArchiveBtn = await screen.findByRole('button', {
+ name: messages.createFromArchiveButton.defaultMessage,
+ });
await user.click(createFromArchiveBtn);
// Upload a file to trigger the restore process
@@ -523,7 +533,9 @@ describe(' ', () => {
render( );
// Switch to archive mode
- const createFromArchiveBtn = await screen.findByRole('button', { name: messages.createFromArchiveButton.defaultMessage });
+ const createFromArchiveBtn = await screen.findByRole('button', {
+ name: messages.createFromArchiveButton.defaultMessage,
+ });
await user.click(createFromArchiveBtn);
// Upload a file to trigger the restore process
@@ -562,7 +574,9 @@ describe(' ', () => {
render( );
// Switch to archive mode
- const createFromArchiveBtn = await screen.findByRole('button', { name: messages.createFromArchiveButton.defaultMessage });
+ const createFromArchiveBtn = await screen.findByRole('button', {
+ name: messages.createFromArchiveButton.defaultMessage,
+ });
await user.click(createFromArchiveBtn);
// Upload a file to trigger the restore process
@@ -595,7 +609,9 @@ describe(' ', () => {
render( );
// Switch to archive mode
- const createFromArchiveBtn = await screen.findByRole('button', { name: messages.createFromArchiveButton.defaultMessage });
+ const createFromArchiveBtn = await screen.findByRole('button', {
+ name: messages.createFromArchiveButton.defaultMessage,
+ });
await user.click(createFromArchiveBtn);
// Try to upload a file with correct MIME type but wrong extension to trigger our custom validation
@@ -647,7 +663,9 @@ describe(' ', () => {
render( );
// Switch to archive mode
- const createFromArchiveBtn = await screen.findByRole('button', { name: messages.createFromArchiveButton.defaultMessage });
+ const createFromArchiveBtn = await screen.findByRole('button', {
+ name: messages.createFromArchiveButton.defaultMessage,
+ });
await user.click(createFromArchiveBtn);
// Initially no archive preview should be shown (no uploaded file)
@@ -722,7 +740,9 @@ describe(' ', () => {
render( );
// Switch to archive mode
- const createFromArchiveBtn = await screen.findByRole('button', { name: messages.createFromArchiveButton.defaultMessage });
+ const createFromArchiveBtn = await screen.findByRole('button', {
+ name: messages.createFromArchiveButton.defaultMessage,
+ });
await user.click(createFromArchiveBtn);
// Fill in form fields
@@ -765,7 +785,9 @@ describe(' ', () => {
render( );
// Switch to archive mode
- const createFromArchiveBtn = await screen.findByRole('button', { name: messages.createFromArchiveButton.defaultMessage });
+ const createFromArchiveBtn = await screen.findByRole('button', {
+ name: messages.createFromArchiveButton.defaultMessage,
+ });
await user.click(createFromArchiveBtn);
// Should show error alert with the specific error message
@@ -781,7 +803,9 @@ describe(' ', () => {
render( );
// Switch to archive mode
- const createFromArchiveBtn = await screen.findByRole('button', { name: messages.createFromArchiveButton.defaultMessage });
+ const createFromArchiveBtn = await screen.findByRole('button', {
+ name: messages.createFromArchiveButton.defaultMessage,
+ });
await user.click(createFromArchiveBtn);
// Should show generic error message
@@ -825,7 +849,9 @@ describe(' ', () => {
render( );
// Switch to archive mode
- const createFromArchiveBtn = await screen.findByRole('button', { name: messages.createFromArchiveButton.defaultMessage });
+ const createFromArchiveBtn = await screen.findByRole('button', {
+ name: messages.createFromArchiveButton.defaultMessage,
+ });
await user.click(createFromArchiveBtn);
// Fill in form fields
@@ -876,7 +902,9 @@ describe(' ', () => {
render( );
// Switch to archive mode
- const createFromArchiveBtn = await screen.findByRole('button', { name: messages.createFromArchiveButton.defaultMessage });
+ const createFromArchiveBtn = await screen.findByRole('button', {
+ name: messages.createFromArchiveButton.defaultMessage,
+ });
await user.click(createFromArchiveBtn);
// Fill in form fields
@@ -927,7 +955,9 @@ describe(' ', () => {
render( );
// Switch to archive mode
- const createFromArchiveBtn = await screen.findByRole('button', { name: messages.createFromArchiveButton.defaultMessage });
+ const createFromArchiveBtn = await screen.findByRole('button', {
+ name: messages.createFromArchiveButton.defaultMessage,
+ });
await user.click(createFromArchiveBtn);
// Fill in form fields
diff --git a/src/library-authoring/create-library/CreateLibrary.tsx b/src/library-authoring/create-library/CreateLibrary.tsx
index c9d67de91c..ecdc07fa4f 100644
--- a/src/library-authoring/create-library/CreateLibrary.tsx
+++ b/src/library-authoring/create-library/CreateLibrary.tsx
@@ -50,9 +50,9 @@ export const CreateLibrary = ({
handleCancel,
handlePostCreate,
}: {
- showInModal?: boolean,
- handleCancel?: () => void,
- handlePostCreate?: (library: ContentLibrary) => void,
+ showInModal?: boolean;
+ handleCancel?: () => void;
+ handlePostCreate?: (library: ContentLibrary) => void;
}) => {
const intl = useIntl();
const navigate = useNavigate();
@@ -152,19 +152,21 @@ export const CreateLibrary = ({
return (
<>
- {!showInModal && ()}
+ {!showInModal && }
{!showInModal && (
- {intl.formatMessage(messages.createFromArchiveButton)}
-
- ) : null}
+ headerActions={!isFromArchive ?
+ (
+
+ {intl.formatMessage(messages.createFromArchiveButton)}
+
+ ) :
+ null}
/>
)}
@@ -221,19 +223,17 @@ export const CreateLibrary = ({
})}
- {
- (restoreStatus.result.createdBy?.email && restoreStatus.result.createdOnServer) && (
-
-
-
- {intl.formatMessage(messages.archiveRestoredCreatedBy, {
- createdBy: restoreStatus.result.createdBy?.email,
- server: restoreStatus.result.createdOnServer,
- })}
-
-
- )
- }
+ {(restoreStatus.result.createdBy?.email && restoreStatus.result.createdOnServer) && (
+
+
+
+ {intl.formatMessage(messages.archiveRestoredCreatedBy, {
+ createdBy: restoreStatus.result.createdBy?.email,
+ server: restoreStatus.result.createdOnServer,
+ })}
+
+
+ )}
@@ -254,7 +254,7 @@ export const CreateLibrary = ({
{(restoreTaskId || isError || restoreMutation.isError) && (
{(restoreStatus?.state === LibraryRestoreStatus.Pending
- || restoreStatus?.state === LibraryRestoreStatus.InProgress) && (
+ || restoreStatus?.state === LibraryRestoreStatus.InProgress) && (
{intl.formatMessage(messages.restoreInProgress)}
@@ -290,25 +290,23 @@ export const CreateLibrary = ({
org: '',
slug: '',
}}
- validationSchema={
- Yup.object().shape({
- title: Yup.string()
- .required(intl.formatMessage(messages.requiredFieldError)),
- org: Yup.string()
- .required(intl.formatMessage(messages.requiredFieldError))
- .matches(
- specialCharsRule,
- intl.formatMessage(messages.disallowedCharsError),
- )
- .matches(noSpaceRule, intl.formatMessage(messages.noSpaceError)),
- slug: Yup.string()
- .required(intl.formatMessage(messages.requiredFieldError))
- .matches(
- validSlugIdRegex,
- intl.formatMessage(messages.invalidSlugError),
- ),
- })
- }
+ validationSchema={Yup.object().shape({
+ title: Yup.string()
+ .required(intl.formatMessage(messages.requiredFieldError)),
+ org: Yup.string()
+ .required(intl.formatMessage(messages.requiredFieldError))
+ .matches(
+ specialCharsRule,
+ intl.formatMessage(messages.disallowedCharsError),
+ )
+ .matches(noSpaceRule, intl.formatMessage(messages.noSpaceError)),
+ slug: Yup.string()
+ .required(intl.formatMessage(messages.requiredFieldError))
+ .matches(
+ validSlugIdRegex,
+ intl.formatMessage(messages.invalidSlugError),
+ ),
+ })}
onSubmit={(values) => {
const submitData = { ...values } as CreateContentLibraryArgs;
@@ -336,17 +334,17 @@ export const CreateLibrary = ({
formikProps.setFieldValue(
- 'org',
- allowToCreateNewOrg
- ? (event.selectionId || event.userProvidedText)
- : event.selectionId,
- )}
+ onChange={(event) =>
+ formikProps.setFieldValue(
+ 'org',
+ allowToCreateNewOrg
+ ? (event.selectionId || event.userProvidedText)
+ : event.selectionId,
+ )}
placeholder={intl.formatMessage(messages.orgPlaceholder)}
>
- {organizations.map((org) => (
- {org}
- ))}
+ {organizations.map((org) => {org}
+ )}
{intl.formatMessage(messages.orgHelp)}
@@ -361,14 +359,13 @@ export const CreateLibrary = ({
className=""
controlClasses="pb-2"
/>
-
)}
- {isError && ( )}
-
+ {isError && }
- {!showInModal && ( )}
+ {!showInModal && }
>
);
};
diff --git a/src/library-authoring/create-library/CreateLibraryModal.tsx b/src/library-authoring/create-library/CreateLibraryModal.tsx
index 436941049d..5c3e841b9d 100644
--- a/src/library-authoring/create-library/CreateLibraryModal.tsx
+++ b/src/library-authoring/create-library/CreateLibraryModal.tsx
@@ -8,7 +8,7 @@ import type { ContentLibrary } from '../data/api';
interface CreateLibraryModalProps {
isOpen: boolean;
onClose: () => void;
- handlePostCreate: (library: ContentLibrary) => void,
+ handlePostCreate: (library: ContentLibrary) => void;
}
export const CreateLibraryModal = ({
diff --git a/src/library-authoring/create-library/data/api.ts b/src/library-authoring/create-library/data/api.ts
index 392899b52d..e0b26ab582 100644
--- a/src/library-authoring/create-library/data/api.ts
+++ b/src/library-authoring/create-library/data/api.ts
@@ -13,10 +13,10 @@ const getApiBaseUrl = () => getConfig().STUDIO_BASE_URL;
export const getContentLibraryV2CreateApiUrl = () => `${getApiBaseUrl()}/api/libraries/v2/`;
export interface CreateContentLibraryArgs {
- title: string,
- org: string,
- slug: string,
- learning_package?: number,
+ title: string;
+ org: string;
+ slug: string;
+ learning_package?: number;
}
/**
diff --git a/src/library-authoring/create-library/data/apiHooks.test.tsx b/src/library-authoring/create-library/data/apiHooks.test.tsx
index 726cbee024..a767ac628b 100644
--- a/src/library-authoring/create-library/data/apiHooks.test.tsx
+++ b/src/library-authoring/create-library/data/apiHooks.test.tsx
@@ -16,7 +16,7 @@ import { LibraryRestoreStatus } from './restoreConstants';
mockContentLibrary.applyMock();
const { axiosMock, queryClient } = initializeMocks();
-const wrapper = ({ children }: { children: React.ReactNode }) => (
+const wrapper = ({ children }: { children: React.ReactNode; }) => (
{children}
@@ -134,7 +134,9 @@ describe('create library apiHooks', () => {
});
expect(result.current.data).toEqual(expectedResult);
- expect(axiosMock.history.get[0].url).toEqual(`http://localhost:18010/api/libraries/v2/restore/?task_id=${taskId}`);
+ expect(axiosMock.history.get[0].url).toEqual(
+ `http://localhost:18010/api/libraries/v2/restore/?task_id=${taskId}`,
+ );
});
it('should not make request when taskId is empty', async () => {
@@ -173,7 +175,9 @@ describe('create library apiHooks', () => {
});
expect(result.current.data).toEqual(expectedResult);
- expect(axiosMock.history.get[0].url).toEqual(`http://localhost:18010/api/libraries/v2/restore/?task_id=${taskId}`);
+ expect(axiosMock.history.get[0].url).toEqual(
+ `http://localhost:18010/api/libraries/v2/restore/?task_id=${taskId}`,
+ );
});
it('should handle in-progress status with refetch interval', async () => {
@@ -192,7 +196,10 @@ describe('create library apiHooks', () => {
errorLog: null,
};
- axiosMock.onGet(`http://localhost:18010/api/libraries/v2/restore/?task_id=${taskId}`).reply(200, inProgressResult);
+ axiosMock.onGet(`http://localhost:18010/api/libraries/v2/restore/?task_id=${taskId}`).reply(
+ 200,
+ inProgressResult,
+ );
const { result } = renderHook(() => useGetLibraryRestoreStatus(taskId), { wrapper });
@@ -201,7 +208,9 @@ describe('create library apiHooks', () => {
});
expect(result.current.data).toEqual(expectedResult);
- expect(axiosMock.history.get[0].url).toEqual(`http://localhost:18010/api/libraries/v2/restore/?task_id=${taskId}`);
+ expect(axiosMock.history.get[0].url).toEqual(
+ `http://localhost:18010/api/libraries/v2/restore/?task_id=${taskId}`,
+ );
});
it('should handle failed status', async () => {
@@ -229,7 +238,9 @@ describe('create library apiHooks', () => {
});
expect(result.current.data).toEqual(expectedResult);
- expect(axiosMock.history.get[0].url).toEqual(`http://localhost:18010/api/libraries/v2/restore/?task_id=${taskId}`);
+ expect(axiosMock.history.get[0].url).toEqual(
+ `http://localhost:18010/api/libraries/v2/restore/?task_id=${taskId}`,
+ );
});
it('should handle API error', async () => {
@@ -244,7 +255,9 @@ describe('create library apiHooks', () => {
});
expect(result.current.data).toBeUndefined();
- expect(axiosMock.history.get[0].url).toEqual(`http://localhost:18010/api/libraries/v2/restore/?task_id=${taskId}`);
+ expect(axiosMock.history.get[0].url).toEqual(
+ `http://localhost:18010/api/libraries/v2/restore/?task_id=${taskId}`,
+ );
});
});
});
diff --git a/src/library-authoring/create-library/data/apiHooks.ts b/src/library-authoring/create-library/data/apiHooks.ts
index 1a5880a5d3..f4bab3af9b 100644
--- a/src/library-authoring/create-library/data/apiHooks.ts
+++ b/src/library-authoring/create-library/data/apiHooks.ts
@@ -39,17 +39,21 @@ export const useCreateLibraryV2 = () => {
* const { data, isLoading, isError } = useGetLibraryRestoreStatus('task:456abc');
* ```
*/
-export const useGetLibraryRestoreStatus = (taskId: string) => useQuery({
- queryKey: libraryRestoreQueryKeys.restoreStatus(taskId),
- queryFn: () => getLibraryRestoreStatus(taskId),
- enabled: !!taskId, // Only run the query if taskId is provided
- refetchInterval: (query) => (
- (query.state.data?.state === LibraryRestoreStatus.Pending
- || query.state.data?.state === LibraryRestoreStatus.InProgress
- ) ? 2000 : false),
-});
+export const useGetLibraryRestoreStatus = (taskId: string) =>
+ useQuery({
+ queryKey: libraryRestoreQueryKeys.restoreStatus(taskId),
+ queryFn: () => getLibraryRestoreStatus(taskId),
+ enabled: !!taskId, // Only run the query if taskId is provided
+ refetchInterval: (query) => (
+ (query.state.data?.state === LibraryRestoreStatus.Pending
+ || query.state.data?.state === LibraryRestoreStatus.InProgress) ?
+ 2000 :
+ false
+ ),
+ });
-export const useCreateLibraryRestore = () => useMutation({
- mutationKey: libraryRestoreQueryKeys.restoreMutation(),
- mutationFn: createLibraryRestore,
-});
+export const useCreateLibraryRestore = () =>
+ useMutation({
+ mutationKey: libraryRestoreQueryKeys.restoreMutation(),
+ mutationFn: createLibraryRestore,
+ });
diff --git a/src/library-authoring/data/api.mocks.ts b/src/library-authoring/data/api.mocks.ts
index aac440005f..8842457a0f 100644
--- a/src/library-authoring/data/api.mocks.ts
+++ b/src/library-authoring/data/api.mocks.ts
@@ -14,74 +14,83 @@ import * as api from './api';
* Mock for `getContentLibraryV2List()`
*/
export const mockGetContentLibraryV2List = {
- applyMock: () => jest.spyOn(api, 'getContentLibraryV2List').mockResolvedValue(
- camelCaseObject(contentLibrariesListV2),
- ),
- applyMockNoPagination: () => jest.spyOn(api, 'getContentLibraryV2List').mockResolvedValue(
- camelCaseObject(contentLibrariesListV2.results),
- ),
- applyMockNoPaginationEmpty: () => jest.spyOn(api, 'getContentLibraryV2List').mockResolvedValue([] as api.ContentLibrary[]),
- applyMockError: () => jest.spyOn(api, 'getContentLibraryV2List').mockRejectedValue(
- createAxiosError({ code: 500, message: 'Internal Error.', path: api.getContentLibraryV2ListApiUrl() }),
- ),
- applyMockLoading: () => jest.spyOn(api, 'getContentLibraryV2List').mockResolvedValue(
- new Promise(() => {}),
- ),
- applyMockEmpty: () => jest.spyOn(api, 'getContentLibraryV2List').mockResolvedValue({
- next: null,
- previous: null,
- count: 0,
- numPages: 1,
- currentPage: 1,
- start: 0,
- results: [],
- }),
+ applyMock: () =>
+ jest.spyOn(api, 'getContentLibraryV2List').mockResolvedValue(
+ camelCaseObject(contentLibrariesListV2),
+ ),
+ applyMockNoPagination: () =>
+ jest.spyOn(api, 'getContentLibraryV2List').mockResolvedValue(
+ camelCaseObject(contentLibrariesListV2.results),
+ ),
+ applyMockNoPaginationEmpty: () =>
+ jest.spyOn(api, 'getContentLibraryV2List').mockResolvedValue([] as api.ContentLibrary[]),
+ applyMockError: () =>
+ jest.spyOn(api, 'getContentLibraryV2List').mockRejectedValue(
+ createAxiosError({ code: 500, message: 'Internal Error.', path: api.getContentLibraryV2ListApiUrl() }),
+ ),
+ applyMockLoading: () =>
+ jest.spyOn(api, 'getContentLibraryV2List').mockResolvedValue(
+ new Promise(() => {}),
+ ),
+ applyMockEmpty: () =>
+ jest.spyOn(api, 'getContentLibraryV2List').mockResolvedValue({
+ next: null,
+ previous: null,
+ count: 0,
+ numPages: 1,
+ currentPage: 1,
+ start: 0,
+ results: [],
+ }),
};
export const mockGetModulestoreMigratedBlocksInfo = {
- applyMockSuccess: () => jest.spyOn(api, 'getModulestoreMigrationBlocksInfo').mockResolvedValue(
- [
- {
- sourceKey: 'block-v1:UNIX+UX2+2025_T2+type@chapter+block@1',
- targetKey: '1',
- unsupportedReason: undefined,
- },
- {
- sourceKey: 'block-v1:UNIX+UX2+2025_T2+type@sequential+block@2',
- targetKey: '2',
- unsupportedReason: undefined,
- },
- {
- sourceKey: 'block-v1:UNIX+UX2+2025_T2+type@vertical+block@2',
- targetKey: '3',
- unsupportedReason: undefined,
- },
- {
- sourceKey: 'block-v1:UNIX+UX2+2025_T2+type@html+block@3',
- targetKey: '4',
- unsupportedReason: undefined,
- },
- ],
- ),
- applyMockPartial: () => jest.spyOn(api, 'getModulestoreMigrationBlocksInfo').mockResolvedValue(
- [
- {
- sourceKey: 'block-v1:UNIX+UX2+2025_T2+type@library_content+block@test_lib_content',
- targetKey: null,
- unsupportedReason: 'The "library_content" XBlock (ID: "test_lib_content") has children, so it is not supported in content libraries. It has 2 children blocks.',
- },
- {
- sourceKey: 'block-v1:UNIX+UX2+2025_T2+type@html+block@1',
- targetKey: '1',
- unsupportedReason: undefined,
- },
- {
- sourceKey: 'block-v1:UNIX+UX2+2025_T2+type@chapter+block@1',
- targetKey: '2',
- unsupportedReason: undefined,
- },
- ],
- ),
+ applyMockSuccess: () =>
+ jest.spyOn(api, 'getModulestoreMigrationBlocksInfo').mockResolvedValue(
+ [
+ {
+ sourceKey: 'block-v1:UNIX+UX2+2025_T2+type@chapter+block@1',
+ targetKey: '1',
+ unsupportedReason: undefined,
+ },
+ {
+ sourceKey: 'block-v1:UNIX+UX2+2025_T2+type@sequential+block@2',
+ targetKey: '2',
+ unsupportedReason: undefined,
+ },
+ {
+ sourceKey: 'block-v1:UNIX+UX2+2025_T2+type@vertical+block@2',
+ targetKey: '3',
+ unsupportedReason: undefined,
+ },
+ {
+ sourceKey: 'block-v1:UNIX+UX2+2025_T2+type@html+block@3',
+ targetKey: '4',
+ unsupportedReason: undefined,
+ },
+ ],
+ ),
+ applyMockPartial: () =>
+ jest.spyOn(api, 'getModulestoreMigrationBlocksInfo').mockResolvedValue(
+ [
+ {
+ sourceKey: 'block-v1:UNIX+UX2+2025_T2+type@library_content+block@test_lib_content',
+ targetKey: null,
+ unsupportedReason:
+ 'The "library_content" XBlock (ID: "test_lib_content") has children, so it is not supported in content libraries. It has 2 children blocks.',
+ },
+ {
+ sourceKey: 'block-v1:UNIX+UX2+2025_T2+type@html+block@1',
+ targetKey: '1',
+ unsupportedReason: undefined,
+ },
+ {
+ sourceKey: 'block-v1:UNIX+UX2+2025_T2+type@chapter+block@1',
+ targetKey: '2',
+ unsupportedReason: undefined,
+ },
+ ],
+ ),
};
/**
@@ -227,9 +236,12 @@ export async function mockCreateLibraryBlock(
): ReturnType {
if (args.libraryId === mockContentLibrary.libraryId) {
switch (args.blockType) {
- case 'html': return mockCreateLibraryBlock.newHtmlData;
- case 'problem': return mockCreateLibraryBlock.newProblemData;
- case 'video': return mockCreateLibraryBlock.newVideoData;
+ case 'html':
+ return mockCreateLibraryBlock.newHtmlData;
+ case 'problem':
+ return mockCreateLibraryBlock.newProblemData;
+ case 'video':
+ return mockCreateLibraryBlock.newVideoData;
default:
// Continue to error handling below.
}
@@ -340,13 +352,20 @@ mockRestoreContainer.applyMock = () => (
export async function mockXBlockFields(usageKey: string): Promise {
const thisMock = mockXBlockFields;
switch (usageKey) {
- case thisMock.usageKeyHtml: return thisMock.dataHtml;
- case thisMock.usageKeyNewHtml: return thisMock.dataNewHtml;
- case thisMock.usageKeyNewProblem: return thisMock.dataNewProblem;
- case thisMock.usageKeyNewVideo: return thisMock.dataNewVideo;
- case thisMock.usageKeyThirdParty: return thisMock.dataThirdParty;
- case thisMock.usageKey0: return thisMock.dataHtml0;
- default: throw new Error(`No mock has been set up for usageKey "${usageKey}"`);
+ case thisMock.usageKeyHtml:
+ return thisMock.dataHtml;
+ case thisMock.usageKeyNewHtml:
+ return thisMock.dataNewHtml;
+ case thisMock.usageKeyNewProblem:
+ return thisMock.dataNewProblem;
+ case thisMock.usageKeyNewVideo:
+ return thisMock.dataNewVideo;
+ case thisMock.usageKeyThirdParty:
+ return thisMock.dataThirdParty;
+ case thisMock.usageKey0:
+ return thisMock.dataHtml0;
+ default:
+ throw new Error(`No mock has been set up for usageKey "${usageKey}"`);
}
}
// Mock of a "regular" HTML (Text) block:
@@ -407,15 +426,24 @@ export async function mockLibraryBlockMetadata(usageKey: string): Promise(() => {});
case thisMock.usageKeyError404:
throw createAxiosError({ code: 404, message: 'Not found.', path: api.getLibraryBlockMetadataUrl(usageKey) });
- case thisMock.usageKeyNeverPublished: return thisMock.dataNeverPublished;
- case thisMock.usageKeyPublished: return thisMock.dataPublished;
- case thisMock.usageKeyWithCollections: return thisMock.dataWithCollections;
- case thisMock.usageKeyPublishDisabled: return thisMock.dataPublishDisabled;
- case thisMock.usageKeyUnsupportedXBlock: return thisMock.dataUnsupportedXBlock;
- case thisMock.usageKeyForTags: return thisMock.dataPublished;
- case thisMock.usageKeyPublishedWithChanges: return thisMock.dataPublishedWithChanges;
- case thisMock.usageKeyPublishedWithChangesV2: return thisMock.dataPublishedWithChanges;
- default: throw new Error(`No mock has been set up for usageKey "${usageKey}"`);
+ case thisMock.usageKeyNeverPublished:
+ return thisMock.dataNeverPublished;
+ case thisMock.usageKeyPublished:
+ return thisMock.dataPublished;
+ case thisMock.usageKeyWithCollections:
+ return thisMock.dataWithCollections;
+ case thisMock.usageKeyPublishDisabled:
+ return thisMock.dataPublishDisabled;
+ case thisMock.usageKeyUnsupportedXBlock:
+ return thisMock.dataUnsupportedXBlock;
+ case thisMock.usageKeyForTags:
+ return thisMock.dataPublished;
+ case thisMock.usageKeyPublishedWithChanges:
+ return thisMock.dataPublishedWithChanges;
+ case thisMock.usageKeyPublishedWithChangesV2:
+ return thisMock.dataPublishedWithChanges;
+ default:
+ throw new Error(`No mock has been set up for usageKey "${usageKey}"`);
}
}
mockLibraryBlockMetadata.usageKeyThatNeverLoads = 'lb:Axim:infiniteLoading:html:123';
@@ -499,7 +527,8 @@ mockLibraryBlockMetadata.dataPublishedWithChanges = {
collections: [],
} satisfies api.LibraryBlockMetadata;
/** Apply this mock. Returns a spy object that can tell you if it's been called. */
-mockLibraryBlockMetadata.applyMock = () => jest.spyOn(api, 'getLibraryBlockMetadata').mockImplementation(mockLibraryBlockMetadata);
+mockLibraryBlockMetadata.applyMock = () =>
+ jest.spyOn(api, 'getLibraryBlockMetadata').mockImplementation(mockLibraryBlockMetadata);
/**
* Mock for `getCollectionMetadata()`
@@ -557,7 +586,7 @@ export async function mockGetContainerMetadata(containerId: string): Promise { });
+ return new Promise(() => {});
case mockGetContainerMetadata.unitIdWithCollections:
return Promise.resolve(mockGetContainerMetadata.containerDataWithCollections);
case mockGetContainerMetadata.sectionId:
@@ -810,23 +839,23 @@ export async function mockGetContainerHierarchy(containerId: string): Promise (
{
...child,
- id: (
- childId === containerId
- ? childId
- // Generate a unique ID when multiple child blocks
- : `${typeNamespace}:org1:Demo_course_generated:${blockType}:${name}-${idx}`
- ),
+ id: childId === containerId
+ ? childId
+ // Generate a unique ID when multiple child blocks
+ : `${typeNamespace}:org1:Demo_course_generated:${blockType}:${name}-${idx}`,
displayName: `${name} block ${idx}`,
publishedDisplayName: `${name} block published ${idx}`,
hasUnpublishedChanges: true,
@@ -865,7 +894,8 @@ mockGetContainerHierarchy.applyMock = () => {
export async function mockXBlockOLX(usageKey: string): Promise {
const thisMock = mockXBlockOLX;
switch (usageKey) {
- case thisMock.usageKeyHtml: return thisMock.olxHtml;
+ case thisMock.usageKeyHtml:
+ return thisMock.olxHtml;
default: {
const blockType = getBlockType(usageKey);
return `<${blockType}>This is mock OLX for usageKey "${usageKey}"${blockType}>`;
@@ -954,7 +984,8 @@ mockGetLibraryTeam.applyMock = () => jest.spyOn(api, 'getLibraryTeam').mockImple
export async function mockBlockTypesMetadata(libraryId: string): Promise {
const thisMock = mockBlockTypesMetadata;
switch (libraryId) {
- case mockContentLibrary.libraryId: return thisMock.blockTypesMetadata;
+ case mockContentLibrary.libraryId:
+ return thisMock.blockTypesMetadata;
default: {
return [];
}
@@ -979,17 +1010,25 @@ export async function mockGetEntityLinks(
const thisMock = mockGetEntityLinks;
if (contentType === 'components') {
switch (upstreamKey) {
- case thisMock.upstreamContainerKey: return thisMock.componentResponse;
- case mockLibraryBlockMetadata.usageKeyPublishedWithChanges: return thisMock.componentResponse;
- case thisMock.emptyUsageKey: return thisMock.emptyComponentUsage;
- default: return [];
+ case thisMock.upstreamContainerKey:
+ return thisMock.componentResponse;
+ case mockLibraryBlockMetadata.usageKeyPublishedWithChanges:
+ return thisMock.componentResponse;
+ case thisMock.emptyUsageKey:
+ return thisMock.emptyComponentUsage;
+ default:
+ return [];
}
} else if (contentType === 'containers') {
switch (upstreamKey) {
- case thisMock.unitKey: return thisMock.unitResponse;
- case thisMock.subsectionKey: return thisMock.subsectionResponse;
- case thisMock.sectionKey: return thisMock.sectionResponse;
- default: return [];
+ case thisMock.unitKey:
+ return thisMock.unitResponse;
+ case thisMock.subsectionKey:
+ return thisMock.subsectionResponse;
+ case thisMock.sectionKey:
+ return thisMock.sectionResponse;
+ default:
+ return [];
}
}
return thisMock.allResponse;
@@ -1118,10 +1157,11 @@ mockGetEntityLinks.allResponse = [
...mockGetEntityLinks.subsectionResponse,
...mockGetEntityLinks.sectionResponse,
];
-mockGetEntityLinks.applyMock = () => jest.spyOn(
- courseLibApi,
- 'getEntityLinks',
-).mockImplementation(mockGetEntityLinks);
+mockGetEntityLinks.applyMock = () =>
+ jest.spyOn(
+ courseLibApi,
+ 'getEntityLinks',
+ ).mockImplementation(mockGetEntityLinks);
export async function mockGetCourseImports(libraryId: string): ReturnType {
switch (libraryId) {
@@ -1183,21 +1223,23 @@ mockGetCourseImports.inProgressImport = {
state: 'In Progress',
progress: 0.5012,
} satisfies api.CourseImport;
-mockGetCourseImports.applyMock = () => jest.spyOn(
- api,
- 'getCourseImports',
-).mockImplementation(mockGetCourseImports);
+mockGetCourseImports.applyMock = () =>
+ jest.spyOn(
+ api,
+ 'getCourseImports',
+ ).mockImplementation(mockGetCourseImports);
export const mockGetMigrationInfo = {
- applyMock: () => jest.spyOn(api, 'getMigrationInfo').mockResolvedValue(
- camelCaseObject({
- 'course-v1:HarvardX+123+2023': [{
- sourceKey: 'course-v1:HarvardX+123+2023',
- targetCollectionKey: 'ltc:org:coll-1',
- targetCollectionTitle: 'Collection 1',
- targetKey: mockContentLibrary.libraryId,
- targetTitle: 'Library 1',
- }],
- }),
- ),
+ applyMock: () =>
+ jest.spyOn(api, 'getMigrationInfo').mockResolvedValue(
+ camelCaseObject({
+ 'course-v1:HarvardX+123+2023': [{
+ sourceKey: 'course-v1:HarvardX+123+2023',
+ targetCollectionKey: 'ltc:org:coll-1',
+ targetCollectionTitle: 'Collection 1',
+ targetKey: mockContentLibrary.libraryId,
+ targetTitle: 'Library 1',
+ }],
+ }),
+ ),
};
diff --git a/src/library-authoring/data/api.ts b/src/library-authoring/data/api.ts
index b6dab5e716..72c880558e 100644
--- a/src/library-authoring/data/api.ts
+++ b/src/library-authoring/data/api.ts
@@ -13,7 +13,8 @@ export const getContentLibraryApiUrl = (libraryId: string) => `${getApiBaseUrl()
/**
* Get the URL for create content in library.
*/
-export const getCreateLibraryBlockUrl = (libraryId: string) => `${getApiBaseUrl()}/api/libraries/v2/${libraryId}/blocks/`;
+export const getCreateLibraryBlockUrl = (libraryId: string) =>
+ `${getApiBaseUrl()}/api/libraries/v2/${libraryId}/blocks/`;
/**
* Get the URL for the content library team API.
@@ -23,17 +24,20 @@ export const getLibraryTeamApiUrl = (libraryId: string) => `${getApiBaseUrl()}/a
/**
* Get the URL for updating/deleting a content library team member.
*/
-export const getLibraryTeamMemberApiUrl = (libraryId: string, username: string) => `${getApiBaseUrl()}/api/libraries/v2/${libraryId}/team/user/${username}/`;
+export const getLibraryTeamMemberApiUrl = (libraryId: string, username: string) =>
+ `${getApiBaseUrl()}/api/libraries/v2/${libraryId}/team/user/${username}/`;
/**
* Get the URL for block types metadata.
*/
-export const getBlockTypesMetaDataUrl = (libraryId: string) => `${getApiBaseUrl()}/api/libraries/v2/${libraryId}/block_types/`;
+export const getBlockTypesMetaDataUrl = (libraryId: string) =>
+ `${getApiBaseUrl()}/api/libraries/v2/${libraryId}/block_types/`;
/**
* Get the URL for library block metadata.
*/
-export const getLibraryBlockMetadataUrl = (usageKey: string) => `${getApiBaseUrl()}/api/libraries/v2/blocks/${usageKey}/`;
+export const getLibraryBlockMetadataUrl = (usageKey: string) =>
+ `${getApiBaseUrl()}/api/libraries/v2/blocks/${usageKey}/`;
/**
* Get the URL for restoring deleted library block.
@@ -43,7 +47,8 @@ export const getLibraryBlockRestoreUrl = (usageKey: string) => `${getLibraryBloc
/**
* Get the URL for library block collections.
*/
-export const getLibraryBlockCollectionsUrl = (usageKey: string) => `${getLibraryBlockMetadataUrl(usageKey)}collections/`;
+export const getLibraryBlockCollectionsUrl = (usageKey: string) =>
+ `${getLibraryBlockMetadataUrl(usageKey)}collections/`;
/**
* Get the URL for a single component hierarchy api.
@@ -58,49 +63,60 @@ export const getContentLibraryV2ListApiUrl = () => `${getApiBaseUrl()}/api/libra
/**
* Get the URL for commit/revert changes in library.
*/
-export const getCommitLibraryChangesUrl = (libraryId: string) => `${getApiBaseUrl()}/api/libraries/v2/${libraryId}/commit/`;
+export const getCommitLibraryChangesUrl = (libraryId: string) =>
+ `${getApiBaseUrl()}/api/libraries/v2/${libraryId}/commit/`;
/**
* Get the URL for paste clipboard content into library.
*/
-export const getLibraryPasteClipboardUrl = (libraryId: string) => `${getApiBaseUrl()}/api/libraries/v2/${libraryId}/paste_clipboard/`;
+export const getLibraryPasteClipboardUrl = (libraryId: string) =>
+ `${getApiBaseUrl()}/api/libraries/v2/${libraryId}/paste_clipboard/`;
/**
- * Get the URL for the xblock fields/metadata API.
- */
-export const getXBlockFieldsApiUrl = (usageKey: string) => `${getApiBaseUrl()}/api/xblock/v2/xblocks/${usageKey}/fields/`;
-export const getXBlockFieldsVersionApiUrl = (usageKey: string, version: VersionSpec) => `${getApiBaseUrl()}/api/xblock/v2/xblocks/${usageKey}@${version}/fields/`;
+ * Get the URL for the xblock fields/metadata API.
+ */
+export const getXBlockFieldsApiUrl = (usageKey: string) =>
+ `${getApiBaseUrl()}/api/xblock/v2/xblocks/${usageKey}/fields/`;
+export const getXBlockFieldsVersionApiUrl = (usageKey: string, version: VersionSpec) =>
+ `${getApiBaseUrl()}/api/xblock/v2/xblocks/${usageKey}@${version}/fields/`;
/**
- * Get the URL for the xblock OLX API
- */
+ * Get the URL for the xblock OLX API
+ */
export const getXBlockOLXApiUrl = (usageKey: string) => `${getLibraryBlockMetadataUrl(usageKey)}olx/`;
-export const getXBlockOLXVersionApiUrl = (usageKey: string, version: VersionSpec) => `${getApiBaseUrl()}/api/xblock/v2/xblocks/${usageKey}@${version}/olx/`;
+export const getXBlockOLXVersionApiUrl = (usageKey: string, version: VersionSpec) =>
+ `${getApiBaseUrl()}/api/xblock/v2/xblocks/${usageKey}@${version}/olx/`;
/**
* Get the URL for the xblock Publish API
*/
-export const getXBlockPublishApiUrl = (usageKey: string) => `${getApiBaseUrl()}/api/libraries/v2/blocks/${usageKey}/publish/`;
+export const getXBlockPublishApiUrl = (usageKey: string) =>
+ `${getApiBaseUrl()}/api/libraries/v2/blocks/${usageKey}/publish/`;
/**
- * Get the URL for the xblock Assets List API
- */
-export const getXBlockAssetsApiUrl = (usageKey: string) => `${getApiBaseUrl()}/api/libraries/v2/blocks/${usageKey}/assets/`;
+ * Get the URL for the xblock Assets List API
+ */
+export const getXBlockAssetsApiUrl = (usageKey: string) =>
+ `${getApiBaseUrl()}/api/libraries/v2/blocks/${usageKey}/assets/`;
/**
* Get the URL for the Library Collections API.
*/
-export const getLibraryCollectionsApiUrl = (libraryId: string) => `${getApiBaseUrl()}/api/libraries/v2/${libraryId}/collections/`;
+export const getLibraryCollectionsApiUrl = (libraryId: string) =>
+ `${getApiBaseUrl()}/api/libraries/v2/${libraryId}/collections/`;
/**
* Get the URL for the collection detail API.
*/
-export const getLibraryCollectionApiUrl = (libraryId: string, collectionId: string) => `${getLibraryCollectionsApiUrl(libraryId)}${collectionId}/`;
+export const getLibraryCollectionApiUrl = (libraryId: string, collectionId: string) =>
+ `${getLibraryCollectionsApiUrl(libraryId)}${collectionId}/`;
/**
* Get the URL for the collection items API.
*/
-export const getLibraryCollectionItemsApiUrl = (libraryId: string, collectionId: string) => `${getLibraryCollectionApiUrl(libraryId, collectionId)}items/`;
+export const getLibraryCollectionItemsApiUrl = (libraryId: string, collectionId: string) =>
+ `${getLibraryCollectionApiUrl(libraryId, collectionId)}items/`;
/**
* Get the API URL for restoring deleted collection.
*/
-export const getLibraryCollectionRestoreApiUrl = (libraryId: string, collectionId: string) => `${getLibraryCollectionApiUrl(libraryId, collectionId)}restore/`;
+export const getLibraryCollectionRestoreApiUrl = (libraryId: string, collectionId: string) =>
+ `${getLibraryCollectionApiUrl(libraryId, collectionId)}restore/`;
/**
* Get the URL for the xblock api.
*/
@@ -112,31 +128,38 @@ export const getContentStoreApiUrl = () => `${getApiBaseUrl()}/api/contentstore/
/**
* Get the URL for the library container api.
*/
-export const getLibraryContainersApiUrl = (libraryId: string) => `${getApiBaseUrl()}/api/libraries/v2/${libraryId}/containers/`;
+export const getLibraryContainersApiUrl = (libraryId: string) =>
+ `${getApiBaseUrl()}/api/libraries/v2/${libraryId}/containers/`;
/**
* Get the URL for the container detail api.
*/
-export const getLibraryContainerApiUrl = (containerId: string) => `${getApiBaseUrl()}/api/libraries/v2/containers/${containerId}/`;
+export const getLibraryContainerApiUrl = (containerId: string) =>
+ `${getApiBaseUrl()}/api/libraries/v2/containers/${containerId}/`;
/**
* Get the URL for restore a container
*/
-export const getLibraryContainerRestoreApiUrl = (containerId: string) => `${getLibraryContainerApiUrl(containerId)}restore/`;
+export const getLibraryContainerRestoreApiUrl = (containerId: string) =>
+ `${getLibraryContainerApiUrl(containerId)}restore/`;
/**
* Get the URL for a single container children api.
*/
-export const getLibraryContainerChildrenApiUrl = (containerId: string, published: boolean = false) => `${getLibraryContainerApiUrl(containerId)}children/?published=${published}`;
+export const getLibraryContainerChildrenApiUrl = (containerId: string, published: boolean = false) =>
+ `${getLibraryContainerApiUrl(containerId)}children/?published=${published}`;
/**
* Get the URL for a single container hierarchy api.
*/
-export const getLibraryContainerHierarchyApiUrl = (containerId: string) => `${getLibraryContainerApiUrl(containerId)}hierarchy/`;
+export const getLibraryContainerHierarchyApiUrl = (containerId: string) =>
+ `${getLibraryContainerApiUrl(containerId)}hierarchy/`;
/**
* Get the URL for library container collections.
*/
-export const getLibraryContainerCollectionsUrl = (containerId: string) => `${getLibraryContainerApiUrl(containerId)}collections/`;
+export const getLibraryContainerCollectionsUrl = (containerId: string) =>
+ `${getLibraryContainerApiUrl(containerId)}collections/`;
/**
* Get the URL for the API endpoint to publish a single container (+ children).
*/
-export const getLibraryContainerPublishApiUrl = (containerId: string) => `${getLibraryContainerApiUrl(containerId)}publish/`;
+export const getLibraryContainerPublishApiUrl = (containerId: string) =>
+ `${getLibraryContainerApiUrl(containerId)}publish/`;
/**
* Get the URL for the API endpoint to create a backup of a v2 library.
*/
@@ -144,7 +167,8 @@ export const getLibraryBackupApiUrl = (libraryId: string) => `${getApiBaseUrl()}
/**
* Get the URL for the API endpoint to get the status of a library backup task.
*/
-export const getLibraryBackupStatusApiUrl = (libraryId: string, taskId: string) => `${getApiBaseUrl()}/api/libraries/v2/${libraryId}/backup/?task_id=${taskId}`;
+export const getLibraryBackupStatusApiUrl = (libraryId: string, taskId: string) =>
+ `${getApiBaseUrl()}/api/libraries/v2/${libraryId}/backup/?task_id=${taskId}`;
/**
* Get the URL for the API endpoint to restore a library from an archive.
*/
@@ -152,7 +176,8 @@ export const getLibraryRestoreApiUrl = () => `${getApiBaseUrl()}/api/libraries/v
/**
* Get the URL for the API endpoint to get the status of a library restore task.
*/
-export const getLibraryRestoreStatusApiUrl = (taskId: string) => `${getApiBaseUrl()}/api/libraries/v2/restore/?task_id=${taskId}`;
+export const getLibraryRestoreStatusApiUrl = (taskId: string) =>
+ `${getApiBaseUrl()}/api/libraries/v2/restore/?task_id=${taskId}`;
/**
* Get the URL for the API endpoint to copy a single container.
*/
@@ -164,7 +189,8 @@ export const getBaseModuleStoreMigrationUrl = () => `${getApiBaseUrl()}/api/modu
/**
* Get the url for the API endpoint to list library course imports.
*/
-export const getCourseImportsApiUrl = (libraryId: string) => `${getBaseModuleStoreMigrationUrl()}library/${libraryId}/migrations/courses/`;
+export const getCourseImportsApiUrl = (libraryId: string) =>
+ `${getBaseModuleStoreMigrationUrl()}library/${libraryId}/migrations/courses/`;
/**
* Get the url for the API endpoint to get migration blocks info.
*/
@@ -199,22 +225,22 @@ export type LibraryAccessLevel = 'read' | 'author' | 'admin';
export interface LibraryTeamMember {
username: string;
email: string;
- accessLevel: LibraryAccessLevel,
+ accessLevel: LibraryAccessLevel;
}
export interface AddLibraryTeamMember {
- libraryId: string,
+ libraryId: string;
email: string;
- accessLevel: LibraryAccessLevel,
+ accessLevel: LibraryAccessLevel;
}
export interface DeleteLibraryTeamMember {
- libraryId: string,
+ libraryId: string;
username: string;
}
export interface UpdateLibraryTeamMember extends DeleteLibraryTeamMember {
- accessLevel: LibraryAccessLevel,
+ accessLevel: LibraryAccessLevel;
}
export interface Collection {
@@ -235,13 +261,13 @@ export interface LibraryBlockType {
}
export interface LibrariesV2Response {
- next: string | null,
- previous: string | null,
- count: number,
- numPages: number,
- currentPage: number,
- start: number,
- results: ContentLibrary[],
+ next: string | null;
+ previous: string | null;
+ count: number;
+ numPages: number;
+ currentPage: number;
+ start: number;
+ results: ContentLibrary[];
}
export interface XBlockFields {
@@ -253,31 +279,31 @@ export interface XBlockFields {
/* Additional custom parameters for the API request. */
export interface GetLibrariesV2CustomParams {
/* (optional) Library type, default `complex` */
- type?: string,
+ type?: string;
/* (optional) Page number of results */
- page?: number,
+ page?: number;
/* (optional) The number of results on each page, default `50` */
- pageSize?: number,
+ pageSize?: number;
/* (optional) Whether pagination is supported, default `true` */
- pagination?: boolean,
+ pagination?: boolean;
/* (optional) Library field to order results by. Prefix with '-' for descending */
- order?: string,
+ order?: string;
/* (optional) Search query to filter v2 Libraries by */
- search?: string,
+ search?: string;
}
export interface GetLibrariesV2CustomParamsNoPagination extends GetLibrariesV2CustomParams {
- pagination: false,
+ pagination: false;
}
export interface GetLibrariesV2CustomParamsPagination extends GetLibrariesV2CustomParams {
- pagination?: true,
+ pagination?: true;
}
export type LibraryAssetResponse = {
- path: string,
- size: number,
- url: string,
+ path: string;
+ size: number;
+ url: string;
};
export interface CreateBlockDataRequest {
@@ -303,7 +329,7 @@ export interface LibraryBlockMetadata {
lastPublished: string | null;
publishedBy: string | null;
lastDraftCreated: string | null;
- lastDraftCreatedBy: string | null,
+ lastDraftCreatedBy: string | null;
hasUnpublishedChanges: boolean;
created: string | null;
modified: string | null;
@@ -402,13 +428,13 @@ function isNoPagination(
* Get a list of content libraries.
*/
export async function getContentLibraryV2List(
- customParams: GetLibrariesV2CustomParamsNoPagination
+ customParams: GetLibrariesV2CustomParamsNoPagination,
): Promise;
export async function getContentLibraryV2List(
- customParams: GetLibrariesV2CustomParamsPagination
+ customParams: GetLibrariesV2CustomParamsPagination,
): Promise;
export async function getContentLibraryV2List(
- customParams: GetLibrariesV2CustomParams
+ customParams: GetLibrariesV2CustomParams,
): Promise;
export async function getContentLibraryV2List(
customParams: GetLibrariesV2CustomParams,
@@ -698,7 +724,7 @@ export interface Container {
publishedBy: string | null;
createdBy: string | null;
lastDraftCreated: string | null;
- lastDraftCreatedBy: string | null,
+ lastDraftCreatedBy: string | null;
hasUnpublishedChanges: boolean;
created: string;
modified: string;
diff --git a/src/library-authoring/data/apiHooks.ts b/src/library-authoring/data/apiHooks.ts
index b8f9774aa0..6a8d97c5cd 100644
--- a/src/library-authoring/data/apiHooks.ts
+++ b/src/library-authoring/data/apiHooks.ts
@@ -115,7 +115,10 @@ export const xblockQueryKeys = {
*/
xblock: (usageKey?: string) => [...xblockQueryKeys.all, usageKey],
/** Fields (i.e. the content, display name, etc.) of an XBlock */
- xblockFields: (usageKey: string, version: VersionSpec = 'draft') => [...xblockQueryKeys.xblock(usageKey), 'fields', version],
+ xblockFields: (
+ usageKey: string,
+ version: VersionSpec = 'draft',
+ ) => [...xblockQueryKeys.xblock(usageKey), 'fields', version],
/** OLX (XML representation of the fields/content) */
xblockOLX: (usageKey: string) => [...xblockQueryKeys.xblock(usageKey), 'OLX'],
/** assets (static files) */
@@ -245,13 +248,13 @@ export const useUpdateLibraryMetadata = () => {
* Builds the query to fetch list of V2 Libraries
*/
export function useContentLibraryV2List(
- customParams: api.GetLibrariesV2CustomParamsPagination
+ customParams: api.GetLibrariesV2CustomParamsPagination,
): UseQueryResult;
export function useContentLibraryV2List(
- customParams: api.GetLibrariesV2CustomParamsNoPagination
+ customParams: api.GetLibrariesV2CustomParamsNoPagination,
): UseQueryResult;
export function useContentLibraryV2List(
- customParams: api.GetLibrariesV2CustomParams
+ customParams: api.GetLibrariesV2CustomParams,
): UseQueryResult;
export function useContentLibraryV2List(
customParams: api.GetLibrariesV2CustomParams,
@@ -543,7 +546,7 @@ export const useCollection = (libraryId?: string, collectionId?: string) => (
export const useUpdateCollection = () => {
const queryClient = useQueryClient();
return useMutation({
- mutationFn: async ({ libraryId, collectionId, data }:{
+ mutationFn: async ({ libraryId, collectionId, data }: {
libraryId: string;
collectionId: string;
data: api.UpdateCollectionComponentsRequest;
@@ -708,9 +711,12 @@ export const useUpdateContainer = (containerId: string, affectedParentContainerI
const childrenQueryKey = libraryAuthoringQueryKeys.containerChildren(affectedParentContainerId);
childrenPreviousData = queryClient.getQueryData(childrenQueryKey) as api.Container[];
if (childrenPreviousData) {
- queryClient.setQueryData(childrenQueryKey, childrenPreviousData.map(item => (
- item.id === containerId ? { ...item, ...data } : item
- )));
+ queryClient.setQueryData(
+ childrenQueryKey,
+ childrenPreviousData.map(item => (
+ item.id === containerId ? { ...item, ...data } : item
+ )),
+ );
}
}
@@ -770,35 +776,37 @@ export const useRestoreContainer = (containerId: string) => {
/**
* Get the metadata and children for a container in a library
*/
-export const useContainerChildren = (
- containerId?: string,
- published: boolean = false,
- ) => (
- useQuery({
- enabled: !!containerId,
- queryKey: libraryAuthoringQueryKeys.containerChildren(containerId!),
- queryFn: () => api.getLibraryContainerChildren(containerId!, published),
- structuralSharing: (oldData: ChildType[], newData: ChildType[]) => {
+export const useContainerChildren = <
+ ChildType extends {
+ id: string;
+ isNew?: boolean;
+ } = api.LibraryBlockMetadata | api.Container,
+>(
+ containerId?: string,
+ published: boolean = false,
+) => (
+ useQuery({
+ enabled: !!containerId,
+ queryKey: libraryAuthoringQueryKeys.containerChildren(containerId!),
+ queryFn: () => api.getLibraryContainerChildren(containerId!, published),
+ structuralSharing: (oldData: ChildType[], newData: ChildType[]) => {
// This just sets `isNew` flag to new children components
- if (oldData) {
- const oldDataIds = oldData.map((obj) => obj.id);
- // eslint-disable-next-line no-param-reassign
- newData = newData.map((newObj) => {
- if (!oldDataIds.includes(newObj.id)) {
+ if (oldData) {
+ const oldDataIds = oldData.map((obj) => obj.id);
+ // eslint-disable-next-line no-param-reassign
+ newData = newData.map((newObj) => {
+ if (!oldDataIds.includes(newObj.id)) {
// Set isNew = true if we have new child on refetch
// eslint-disable-next-line no-param-reassign
- newObj.isNew = true;
- }
- return newObj;
- });
- }
- return replaceEqualDeep(oldData, newData);
- },
- })
- );
+ newObj.isNew = true;
+ }
+ return newObj;
+ });
+ }
+ return replaceEqualDeep(oldData, newData);
+ },
+ })
+);
/**
* If you work with `useContentFromSearchIndex`, you can use this
@@ -939,8 +947,8 @@ export const useRemoveContainerChildren = (containerId?: string) => {
};
/**
- * Use this mutation to publish changes to a container and any children within it
- */
+ * Use this mutation to publish changes to a container and any children within it
+ */
export const usePublishContainer = (containerId: string) => {
const queryClient = useQueryClient();
const libraryId = getLibraryId(containerId);
@@ -1018,11 +1026,14 @@ export const useMigrationBlocksInfo = (
) => (
useQuery({
queryKey: libraryAuthoringQueryKeys.migrationBlocksInfo(libraryId, collectionId, isFailed),
- queryFn: enabled ? () => api.getModulestoreMigrationBlocksInfo(
- libraryId,
- collectionId,
- isFailed,
- taskUuid,
- ) : skipToken,
+ queryFn: enabled ?
+ () =>
+ api.getModulestoreMigrationBlocksInfo(
+ libraryId,
+ collectionId,
+ isFailed,
+ taskUuid,
+ ) :
+ skipToken,
})
);
diff --git a/src/library-authoring/generic/filter-by-published/index.tsx b/src/library-authoring/generic/filter-by-published/index.tsx
index 8c0d4698a9..219ff67840 100644
--- a/src/library-authoring/generic/filter-by-published/index.tsx
+++ b/src/library-authoring/generic/filter-by-published/index.tsx
@@ -8,16 +8,11 @@ import { FilterByPublished, PublishStatus } from '../../../search-manager';
* never show results. This component removes that option from FilterByPublished
* when not relevant.
*/
-const LibraryFilterByPublished : React.FC> = () => {
+const LibraryFilterByPublished: React.FC> = () => {
const { showOnlyPublished } = usePublishedFilterContext();
if (showOnlyPublished) {
- return (
-
- );
+ return ;
}
return ;
diff --git a/src/library-authoring/generic/history-widget/index.tsx b/src/library-authoring/generic/history-widget/index.tsx
index 7f63b15842..749769b45e 100644
--- a/src/library-authoring/generic/history-widget/index.tsx
+++ b/src/library-authoring/generic/history-widget/index.tsx
@@ -3,7 +3,7 @@ import { Stack } from '@openedx/paragon';
import messages from './messages';
-const CustomFormattedDate = ({ date }: { date: string | Date }) => (
+const CustomFormattedDate = ({ date }: { date: string | Date; }) => (
;
- * ```
- */
+ * This component displays the history of an entity (Last Modified and Created dates)
+ *
+ * This component doesn't handle fetching the data or any other side effects. It only displays the dates.
+ *
+ * @example
+ * ```tsx
+ * const { data: componentMetadata } = useLibraryBlockMetadata(usageKey);
+ *
+ * return ;
+ * ```
+ */
const HistoryWidget = ({
modified,
created,
@@ -38,19 +38,25 @@ const HistoryWidget = ({
{lastPublished && (
)}
{modified && (
)}
{created && (
)}
diff --git a/src/library-authoring/generic/manage-collections/ManageCollections.test.tsx b/src/library-authoring/generic/manage-collections/ManageCollections.test.tsx
index 289d86fcbb..ab427220a4 100644
--- a/src/library-authoring/generic/manage-collections/ManageCollections.test.tsx
+++ b/src/library-authoring/generic/manage-collections/ManageCollections.test.tsx
@@ -25,15 +25,16 @@ mockLibraryBlockMetadata.applyMock();
mockGetContainerMetadata.applyMock();
mockContentSearchConfig.applyMock();
-const render = (ui: React.ReactElement) => baseRender(ui, {
- extraWrapper: ({ children }) => (
-
-
- {children}
-
-
- ),
-});
+const render = (ui: React.ReactElement) =>
+ baseRender(ui, {
+ extraWrapper: ({ children }) => (
+
+
+ {children}
+
+
+ ),
+ });
const searchEndpoint = 'http://mock.meilisearch.local/multi-search';
@@ -53,7 +54,9 @@ describe(' ', () => {
mockCollectionsResults.results[0].query = query;
// And fake the required '_formatted' fields; it contains the highlighting ... around matched words
// eslint-disable-next-line no-underscore-dangle, no-param-reassign
- mockCollectionsResults.results[0]?.hits.forEach((hit) => { hit._formatted = { ...hit }; });
+ mockCollectionsResults.results[0]?.hits.forEach((hit) => {
+ hit._formatted = { ...hit };
+ });
return mockCollectionsResults;
});
});
@@ -62,14 +65,18 @@ describe(' ', () => {
const user = userEvent.setup();
const url = getLibraryBlockCollectionsUrl(mockLibraryBlockMetadata.usageKeyWithCollections);
axiosMock.onPatch(url).reply(200);
- render( );
+ render(
+ ,
+ );
const manageBtn = await screen.findByRole('button', { name: 'Manage Collections' });
await user.click(manageBtn);
- await waitFor(() => { expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post'); });
+ await waitFor(() => {
+ expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post');
+ });
expect(screen.queryByRole('search')).toBeInTheDocument();
const secondCollection = await screen.findByRole('button', { name: 'My second collection' });
await user.click(secondCollection);
@@ -89,14 +96,18 @@ describe(' ', () => {
const user = userEvent.setup();
const url = getLibraryContainerCollectionsUrl(mockGetContainerMetadata.unitIdWithCollections);
axiosMock.onPatch(url).reply(200);
- render( );
+ render(
+ ,
+ );
const manageBtn = await screen.findByRole('button', { name: 'Manage Collections' });
await user.click(manageBtn);
- await waitFor(() => { expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post'); });
+ await waitFor(() => {
+ expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post');
+ });
expect(screen.queryByRole('search')).toBeInTheDocument();
const secondCollection = await screen.findByRole('button', { name: 'My second collection' });
await user.click(secondCollection);
@@ -116,14 +127,18 @@ describe(' ', () => {
const user = userEvent.setup();
const url = getLibraryBlockCollectionsUrl(mockLibraryBlockMetadata.usageKeyWithCollections);
axiosMock.onPatch(url).reply(400);
- render( );
+ render(
+ ,
+ );
const manageBtn = await screen.findByRole('button', { name: 'Add to Collection' });
await user.click(manageBtn);
- await waitFor(() => { expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post'); });
+ await waitFor(() => {
+ expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post');
+ });
expect(screen.queryByRole('search')).toBeInTheDocument();
const secondCollection = await screen.findByRole('button', { name: 'My second collection' });
await user.click(secondCollection);
@@ -143,14 +158,18 @@ describe(' ', () => {
const user = userEvent.setup();
const url = getLibraryBlockCollectionsUrl(mockLibraryBlockMetadata.usageKeyWithCollections);
axiosMock.onPatch(url).reply(400);
- render( );
+ render(
+ ,
+ );
const manageBtn = await screen.findByRole('button', { name: 'Add to Collection' });
await user.click(manageBtn);
- await waitFor(() => { expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post'); });
+ await waitFor(() => {
+ expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post');
+ });
expect(screen.queryByRole('search')).toBeInTheDocument();
const secondCollection = await screen.findByRole('button', { name: 'My second collection' });
await user.click(secondCollection);
diff --git a/src/library-authoring/generic/manage-collections/ManageCollections.tsx b/src/library-authoring/generic/manage-collections/ManageCollections.tsx
index 59672c09d8..d26ed4147c 100644
--- a/src/library-authoring/generic/manage-collections/ManageCollections.tsx
+++ b/src/library-authoring/generic/manage-collections/ManageCollections.tsx
@@ -2,7 +2,13 @@ import { useContext, useState } from 'react';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import type { UseMutationResult } from '@tanstack/react-query';
import {
- Button, Icon, Scrollable, SelectableBox, Stack, StatefulButton, useCheckboxSetValues,
+ Button,
+ Icon,
+ Scrollable,
+ SelectableBox,
+ Stack,
+ StatefulButton,
+ useCheckboxSetValues,
} from '@openedx/paragon';
import { Folder } from '@openedx/paragon/icons';
@@ -21,7 +27,7 @@ import messages from './messages';
interface ManageCollectionsProps {
opaqueKey: string;
- collections: CollectionMetadata[],
+ collections: CollectionMetadata[];
useUpdateCollectionsHook: (opaqueKey: string) => UseMutationResult;
}
@@ -218,7 +224,8 @@ const ManageCollections = ({ opaqueKey, collections, useUpdateCollectionsHook }:
useUpdateCollectionsHook={useUpdateCollectionsHook}
onClose={() => resetSidebarAction()}
/>
- ) : (
+ ) :
+ (
setSidebarAction(SidebarActions.JumpToManageCollections)}
diff --git a/src/library-authoring/generic/parent-breadcrumbs/ParentBreadcrumbs.test.tsx b/src/library-authoring/generic/parent-breadcrumbs/ParentBreadcrumbs.test.tsx
index a4b86e0254..640c1817da 100644
--- a/src/library-authoring/generic/parent-breadcrumbs/ParentBreadcrumbs.test.tsx
+++ b/src/library-authoring/generic/parent-breadcrumbs/ParentBreadcrumbs.test.tsx
@@ -65,10 +65,12 @@ describe(' ', () => {
});
it('should throw an error if displayName and key arrays are not the same length', async () => {
- expect(() => renderComponent(ContainerType.Unit, {
- displayName: ['Parent 1'],
- key: ['key1', 'key2'],
- })).toThrow('Parents key and displayName arrays must have the same length.');
+ expect(() =>
+ renderComponent(ContainerType.Unit, {
+ displayName: ['Parent 1'],
+ key: ['key1', 'key2'],
+ })
+ ).toThrow('Parents key and displayName arrays must have the same length.');
});
it('show breadcrumb with multiple parents', async () => {
@@ -91,9 +93,15 @@ describe(' ', () => {
expect(subsectionLinks).toHaveLength(2); // Library link only. Parents are displayed in a dropdown.
expect(subsectionLinks[0]).toHaveTextContent('Parent Subsection 1');
- expect(subsectionLinks[0]).toHaveProperty('href', 'http://localhost/library/library-id/subsection/subsection-key-1');
+ expect(subsectionLinks[0]).toHaveProperty(
+ 'href',
+ 'http://localhost/library/library-id/subsection/subsection-key-1',
+ );
expect(subsectionLinks[1]).toHaveTextContent('Parent Subsection 2');
- expect(subsectionLinks[1]).toHaveProperty('href', 'http://localhost/library/library-id/subsection/subsection-key-2');
+ expect(subsectionLinks[1]).toHaveProperty(
+ 'href',
+ 'http://localhost/library/library-id/subsection/subsection-key-2',
+ );
});
});
diff --git a/src/library-authoring/generic/parent-breadcrumbs/index.tsx b/src/library-authoring/generic/parent-breadcrumbs/index.tsx
index 3bde5562b9..500941ea10 100644
--- a/src/library-authoring/generic/parent-breadcrumbs/index.tsx
+++ b/src/library-authoring/generic/parent-breadcrumbs/index.tsx
@@ -2,7 +2,9 @@ import type { ReactNode } from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Link } from 'react-router-dom';
import {
- Breadcrumb, MenuItem, SelectMenu,
+ Breadcrumb,
+ MenuItem,
+ SelectMenu,
} from '@openedx/paragon';
import { ContainerType } from '@src/generic/key-utils';
import type { ContentLibrary } from '../../data/api';
@@ -69,7 +71,7 @@ export const ParentBreadcrumbs = ({ libraryData, parents, containerType }: Paren
const intl = useIntl();
const { id: libraryId, title: libraryTitle } = libraryData;
- const links: Array<{ label: string | string[], to: string | string[], containerType: ContainerType }> = [
+ const links: Array<{ label: string | string[]; to: string | string[]; containerType: ContainerType; }> = [
{
label: libraryTitle,
to: `/library/${libraryId}`,
diff --git a/src/library-authoring/generic/publish-status-buttons/PublishedChip.tsx b/src/library-authoring/generic/publish-status-buttons/PublishedChip.tsx
index e0ff404e03..f2d9ad0c74 100644
--- a/src/library-authoring/generic/publish-status-buttons/PublishedChip.tsx
+++ b/src/library-authoring/generic/publish-status-buttons/PublishedChip.tsx
@@ -10,9 +10,7 @@ import messages from './messages';
* It renders a localized message with consistent styling for status chips.
*/
export const PublishedChip = () => (
-
+
);
diff --git a/src/library-authoring/generic/publish-status-buttons/index.tsx b/src/library-authoring/generic/publish-status-buttons/index.tsx
index e93257c5ff..0df565a78b 100644
--- a/src/library-authoring/generic/publish-status-buttons/index.tsx
+++ b/src/library-authoring/generic/publish-status-buttons/index.tsx
@@ -1,2 +1,2 @@
-export { PublishedChip } from './PublishedChip';
export { PublishDraftButton } from './PublishDraftButton';
+export { PublishedChip } from './PublishedChip';
diff --git a/src/library-authoring/generic/status-widget/index.tsx b/src/library-authoring/generic/status-widget/index.tsx
index f2be49bbfd..887e1b23fc 100644
--- a/src/library-authoring/generic/status-widget/index.tsx
+++ b/src/library-authoring/generic/status-widget/index.tsx
@@ -15,7 +15,7 @@ import { SpinnerSimple } from '@openedx/paragon/icons';
import classNames from 'classnames';
import messages from './messages';
-const CustomFormattedDate = ({ date }: { date: string }) => (
+const CustomFormattedDate = ({ date }: { date: string; }) => (
(
);
-const CustomFormattedTime = ({ date }: { date: string }) => (
+const CustomFormattedTime = ({ date }: { date: string; }) => (
{ commitChanges(libraryId); };
- * const onRevert = () => { revertChanges(libraryId); };
- *
- * return ;
- * ```
- */
+ * This component displays the status of an entity (published, draft, etc.) and allows the user to publish
+ * or discard changes.
+ *
+ * This component doesn't handle fetching the data or any other side effects. It only displays the status
+ * and provides the buttons to commit or revert changes.
+ *
+ * @example
+ * ```tsx
+ * const { data: libraryData } = useContentLibrary(libraryId);
+ * const onCommit = () => { commitChanges(libraryId); };
+ * const onRevert = () => { revertChanges(libraryId); };
+ *
+ * return ;
+ * ```
+ */
const StatusWidget = ({
lastPublished,
hasUnpublishedChanges,
@@ -141,13 +141,13 @@ const StatusWidget = ({
isPublished = false;
statusMessage = intl.formatMessage(messages.draftStatusLabel);
extraStatusMessage = intl.formatMessage(messages.neverPublishedLabel);
- bodyMessage = ( );
+ bodyMessage = ;
} else if (hasUnpublishedChanges || hasUnpublishedDeletes) {
// Entity is on Draft state
isPublished = false;
statusMessage = intl.formatMessage(messages.draftStatusLabel);
extraStatusMessage = intl.formatMessage(messages.unpublishedStatusLabel);
- bodyMessage = ( );
+ bodyMessage = ;
} else {
// Entity is published
isPublished = true;
@@ -184,15 +184,16 @@ const StatusWidget = ({
return (
-
{statusMessage}
- { extraStatusMessage && (
+ {extraStatusMessage && (
{extraStatusMessage}
diff --git a/src/library-authoring/hierarchy/ItemHierarchy.tsx b/src/library-authoring/hierarchy/ItemHierarchy.tsx
index eccd2179fd..036f1be209 100644
--- a/src/library-authoring/hierarchy/ItemHierarchy.tsx
+++ b/src/library-authoring/hierarchy/ItemHierarchy.tsx
@@ -21,12 +21,12 @@ const HierarchyRow = ({
willPublish = false,
publishMessage = undefined,
}: {
- containerType: ContainerType,
- text: string,
- selected: boolean,
- showArrow: boolean,
- willPublish?: boolean,
- publishMessage?: MessageDescriptor,
+ containerType: ContainerType;
+ text: string;
+ selected: boolean;
+ showArrow: boolean;
+ willPublish?: boolean;
+ publishMessage?: MessageDescriptor;
}) => (
{
const intl = useIntl();
const { sidebarItemInfo } = useSidebarContext();
diff --git a/src/library-authoring/hierarchy/ItemHierarchyPublisher.tsx b/src/library-authoring/hierarchy/ItemHierarchyPublisher.tsx
index a70af3752e..aa39ba4228 100644
--- a/src/library-authoring/hierarchy/ItemHierarchyPublisher.tsx
+++ b/src/library-authoring/hierarchy/ItemHierarchyPublisher.tsx
@@ -105,9 +105,7 @@ export const ItemHierarchyPublisher = ({
};
return (
-
+
{intl.formatMessage(messages.publishConfirmHeading)}
{childWarningMessage()} {parentWarningMessage()}
diff --git a/src/library-authoring/hierarchy/messages.ts b/src/library-authoring/hierarchy/messages.ts
index 61e32597d0..7f0d4f1cb4 100644
--- a/src/library-authoring/hierarchy/messages.ts
+++ b/src/library-authoring/hierarchy/messages.ts
@@ -19,41 +19,31 @@ const messages = defineMessages({
hierarchySections: {
id: 'course-authoring.library-authoring.container-sidebar.hierarchy-sections',
defaultMessage: '{count, plural, one {{displayName}} other {{count} Sections}}',
- description: (
- 'Text used for the section part of the hierarchy: show the displayName when there is one, or '
- + 'the count when there is more than one.'
- ),
+ description: 'Text used for the section part of the hierarchy: show the displayName when there is one, or '
+ + 'the count when there is more than one.',
},
hierarchySubsections: {
id: 'course-authoring.library-authoring.container-sidebar.hierarchy-subsections',
defaultMessage: '{count, plural, one {{displayName}} other {{count} Subsections}}',
- description: (
- 'Text used for the subsection part of the hierarchy: show the displayName when there is one, or '
- + 'the count when there is more than one.'
- ),
+ description: 'Text used for the subsection part of the hierarchy: show the displayName when there is one, or '
+ + 'the count when there is more than one.',
},
hierarchyUnits: {
id: 'course-authoring.library-authoring.container-sidebar.hierarchy-units',
defaultMessage: '{count, plural, one {{displayName}} other {{count} Units}}',
- description: (
- 'Text used for the unit part of the hierarchy: show the displayName when there is one, or '
- + 'the count when there is more than one.'
- ),
+ description: 'Text used for the unit part of the hierarchy: show the displayName when there is one, or '
+ + 'the count when there is more than one.',
},
hierarchyComponents: {
id: 'course-authoring.library-authoring.container-sidebar.hierarchy-components',
defaultMessage: '{count, plural, one {{displayName}} other {{count} Components}}',
- description: (
- 'Text used for the components part of the hierarchy: show the displayName when there is one, or '
- + 'the count when there is more than one.'
- ),
+ description: 'Text used for the components part of the hierarchy: show the displayName when there is one, or '
+ + 'the count when there is more than one.',
},
publishSectionWithChildrenWarning: {
id: 'course-authoring.library-authoring.section-sidebar.hierarchy-publisher.publish-warning',
- defaultMessage: (
- 'This section and the {childCount, plural, one {subsection} other {subsections}}'
- + ' it contains will all be published .'
- ),
+ defaultMessage: 'This section and the {childCount, plural, one {subsection} other {subsections}}'
+ + ' it contains will all be published .',
description: 'Content details shown before publishing a section that contains subsections',
},
publishSectionWarning: {
@@ -63,10 +53,8 @@ const messages = defineMessages({
},
publishSubsectionWithChildrenWarning: {
id: 'course-authoring.library-authoring.subsection-sidebar.hierarchy-publisher.publish-warning',
- defaultMessage: (
- 'This subsection and the {childCount, plural, one {unit} other {units}}'
- + ' it contains will all be published .'
- ),
+ defaultMessage: 'This subsection and the {childCount, plural, one {unit} other {units}}'
+ + ' it contains will all be published .',
description: 'Content details shown before publishing a subsection that contains units',
},
publishSubsectionWarning: {
@@ -76,10 +64,8 @@ const messages = defineMessages({
},
publishUnitWithChildrenWarning: {
id: 'course-authoring.library-authoring.unit-sidebar.hierarchy-publisher.publish-warning',
- defaultMessage: (
- 'This unit and the {childCount, plural, one {component} other {components}}'
- + ' it contains will all be published .'
- ),
+ defaultMessage: 'This unit and the {childCount, plural, one {component} other {components}}'
+ + ' it contains will all be published .',
description: 'Content details shown before publishing a unit that contains components',
},
publishUnitWarning: {
@@ -89,18 +75,14 @@ const messages = defineMessages({
},
publishSubsectionWithParentWarning: {
id: 'course-authoring.library-authoring.subsection-sidebar.hierarchy-publisher.publish-parent-warning',
- defaultMessage: (
- 'Its {parentCount, plural, one {parent section} other {parent sections}}'
- + ' will be draft .'
- ),
+ defaultMessage: 'Its {parentCount, plural, one {parent section} other {parent sections}}'
+ + ' will be draft .',
description: 'Parent details shown before publishing a unit that has one or more parent subsections',
},
publishUnitWithParentWarning: {
id: 'course-authoring.library-authoring.unit-sidebar.hierarchy-publisher.publish-parent-warning',
- defaultMessage: (
- 'Its {parentCount, plural, one {parent subsection} other {parent subsections}}'
- + ' will be draft .'
- ),
+ defaultMessage: 'Its {parentCount, plural, one {parent subsection} other {parent subsections}}'
+ + ' will be draft .',
description: 'Parent details shown before publishing a unit that has one or more parent subsections',
},
publishConfirmHeading: {
@@ -130,10 +112,8 @@ const messages = defineMessages({
},
publishComponentsWithParentWarning: {
id: 'course-authoring.library-authoring.component-sidebar.hierarchy-publisher.publish-parent-warning',
- defaultMessage: (
- 'Its {parentCount, plural, one {parent unit} other {parent units}}'
- + ' will be draft .'
- ),
+ defaultMessage: 'Its {parentCount, plural, one {parent unit} other {parent units}}'
+ + ' will be draft .',
description: 'Parent details shown before publishing a component that has one or more parent units',
},
});
diff --git a/src/library-authoring/import-course/CourseImportHomePage.test.tsx b/src/library-authoring/import-course/CourseImportHomePage.test.tsx
index 2e2ddcaa23..6e44173964 100644
--- a/src/library-authoring/import-course/CourseImportHomePage.test.tsx
+++ b/src/library-authoring/import-course/CourseImportHomePage.test.tsx
@@ -24,7 +24,7 @@ const render = (libraryId: string) => (
testRender(
,
{
- extraWrapper: ({ children }: { children: React.ReactNode }) => (
+ extraWrapper: ({ children }: { children: React.ReactNode; }) => (
{children}
diff --git a/src/library-authoring/import-course/CourseImportHomePage.tsx b/src/library-authoring/import-course/CourseImportHomePage.tsx
index c27dda9383..9754cc2b6c 100644
--- a/src/library-authoring/import-course/CourseImportHomePage.tsx
+++ b/src/library-authoring/import-course/CourseImportHomePage.tsx
@@ -81,19 +81,21 @@ export const CourseImportHomePage = () => {
- {courseImports.length ? (
-
-
-
-
- {courseImports.map((courseImport) => (
-
- ))}
-
- ) : ( )}
+ {courseImports.length ?
+ (
+
+
+
+
+ {courseImports.map((courseImport) => (
+
+ ))}
+
+ ) :
+ }
diff --git a/src/library-authoring/import-course/ImportDetailsPage.test.tsx b/src/library-authoring/import-course/ImportDetailsPage.test.tsx
index 1c05ab3601..99975c7d67 100644
--- a/src/library-authoring/import-course/ImportDetailsPage.test.tsx
+++ b/src/library-authoring/import-course/ImportDetailsPage.test.tsx
@@ -41,7 +41,7 @@ const render = (migrationTaskId: string) => (
testRender(
,
{
- extraWrapper: ({ children }: { children: React.ReactNode }) => (
+ extraWrapper: ({ children }: { children: React.ReactNode; }) => (
{children}
@@ -94,9 +94,11 @@ describe(' ', () => {
it('should render Succeeded state', async () => {
mockGetModulestoreMigratedBlocksInfo.applyMockSuccess();
render(mockGetMigrationStatus.migrationId);
- expect(await screen.findByText(
- /test course has been imported to your library in a collection called test collection/i,
- ));
+ expect(
+ await screen.findByText(
+ /test course has been imported to your library in a collection called test collection/i,
+ ),
+ );
expect(await screen.findByText(/Total Blocks/i)).toBeInTheDocument();
expect(await screen.findByText('4')).toBeInTheDocument();
@@ -148,19 +150,27 @@ describe(' ', () => {
expect(await screen.findByText(/Components/i)).toBeInTheDocument();
expect(await screen.findByText('1/2')).toBeInTheDocument();
- expect(await screen.findByText(
- /66% of course test course has been imported successfully/i,
- )).toBeInTheDocument();
-
- expect(await screen.findByRole('cell', {
- name: /randomized content block/i,
- })).toBeInTheDocument();
- expect(await screen.findByRole('cell', {
- name: 'library_content',
- })).toBeInTheDocument();
- expect(await screen.findByRole('cell', {
- name: /has children, so it is not supported in content libraries/i,
- })).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ /66% of course test course has been imported successfully/i,
+ ),
+ ).toBeInTheDocument();
+
+ expect(
+ await screen.findByRole('cell', {
+ name: /randomized content block/i,
+ }),
+ ).toBeInTheDocument();
+ expect(
+ await screen.findByRole('cell', {
+ name: 'library_content',
+ }),
+ ).toBeInTheDocument();
+ expect(
+ await screen.findByRole('cell', {
+ name: /has children, so it is not supported in content libraries/i,
+ }),
+ ).toBeInTheDocument();
const viewImportedContentBtn = screen.getByRole('button', {
name: /view imported content/i,
diff --git a/src/library-authoring/import-course/ImportDetailsPage.tsx b/src/library-authoring/import-course/ImportDetailsPage.tsx
index fdb8d1d1f9..8816ada742 100644
--- a/src/library-authoring/import-course/ImportDetailsPage.tsx
+++ b/src/library-authoring/import-course/ImportDetailsPage.tsx
@@ -3,7 +3,11 @@ import { Helmet } from 'react-helmet';
import { useNavigate, useParams } from 'react-router-dom';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import {
- Stack, Container, Alert, Layout, Button,
+ Stack,
+ Container,
+ Alert,
+ Layout,
+ Button,
DataTable,
} from '@openedx/paragon';
@@ -11,7 +15,10 @@ import Header from '@src/header';
import { useCourseDetails } from '@src/course-outline/data/apiHooks';
import SubHeader from '@src/generic/sub-header/SubHeader';
import {
- ArrowForward, CheckCircle, Info, WarningFilled,
+ ArrowForward,
+ CheckCircle,
+ Info,
+ WarningFilled,
} from '@openedx/paragon/icons';
import Loading from '@src/generic/Loading';
import { ToastContext } from '@src/generic/toast-context';
@@ -225,7 +232,8 @@ const ImportDetailsContent = () => {
- {libraryData?.title || ''} | {intl.formatMessage(messages.importSuccessfulAlertTitle)} | {process.env.SITE_NAME}
+ {libraryData?.title || ''} | {intl.formatMessage(messages.importSuccessfulAlertTitle)} |{' '}
+ {process.env.SITE_NAME}
{
/>
-
+
+
+
{
);
- } if (migrationStatus === 'Failed') {
+ }
+ if (migrationStatus === 'Failed') {
return (
@@ -312,18 +323,22 @@ const ImportDetailsContent = () => {
/>
-
+
+
+
);
- } if (migrationStatus === 'Partial Succeeded') {
+ }
+ if (migrationStatus === 'Partial Succeeded') {
return (
- {libraryData?.title || ''} | {intl.formatMessage(messages.importPartialAlertTitle)} | {process.env.SITE_NAME}
+ {libraryData?.title || ''} | {intl.formatMessage(messages.importPartialAlertTitle)} |{' '}
+ {process.env.SITE_NAME}
{
/>
-
+
+
+
{
{
Header: intl.formatMessage(messages.importPartialReasonTableBlockName),
accessor: 'blockName',
-
},
{
Header: intl.formatMessage(messages.importPartialReasonTableBlockType),
@@ -411,7 +427,9 @@ const ImportDetailsContent = () => {
return (
// In Progress
-
+
+
+
{
}}
/>
-
+
+
+
(
testRender(
,
{
- extraWrapper: ({ children }: { children: React.ReactNode }) => (
+ extraWrapper: ({ children }: { children: React.ReactNode; }) => (
{children}
diff --git a/src/library-authoring/import-course/ImportedCourseCard.tsx b/src/library-authoring/import-course/ImportedCourseCard.tsx
index d2670c5a10..ef1818f175 100644
--- a/src/library-authoring/import-course/ImportedCourseCard.tsx
+++ b/src/library-authoring/import-course/ImportedCourseCard.tsx
@@ -44,7 +44,7 @@ const STATE_ICON_COLOR_CLASS = {
'In Progress': undefined,
};
-const StateIcon = ({ state }: { state: CourseImport['state'] }) => (
+const StateIcon = ({ state }: { state: CourseImport['state']; }) => (
- {courseImport.state === 'Failed' ? (
-
- ) : (
+ {courseImport.state === 'Failed' ?
: (
<>
{Math.round(courseImport.progress * 100)}
diff --git a/src/library-authoring/import-course/PlaceholderCard.tsx b/src/library-authoring/import-course/PlaceholderCard.tsx
index 561c8a3eba..0150aa5320 100644
--- a/src/library-authoring/import-course/PlaceholderCard.tsx
+++ b/src/library-authoring/import-course/PlaceholderCard.tsx
@@ -11,7 +11,7 @@ interface PlaceHolderCardProps {
const PlaceholderCard = ({ blockType, displayName, description }: PlaceHolderCardProps) => {
const intl = useIntl();
const defaultDescription = intl.formatMessage(messages.placeholderCardDescription);
- const truncatedDescription = description ? `${description.substring(0, 40) }...` : defaultDescription;
+ const truncatedDescription = description ? `${description.substring(0, 40)}...` : defaultDescription;
/* istanbul ignore next */
return (
You can import existing courses into a library in order to reference '
- + 'course content across courses.'
- + 'Courses with content you or others may want to reuse or reference in the future are '
- + 'excellent candidates for import.
',
+ + 'course content across courses.'
+ + 'Courses with content you or others may want to reuse or reference in the future are '
+ + 'excellent candidates for import.
',
description: 'Body of the first question in the Help & Support sidebar',
},
helpAndSupportSecondQuestionTitle: {
@@ -67,10 +67,10 @@ const messages = defineMessages({
helpAndSupportSecondQuestionBody: {
id: 'course-authoring.library-authoring.import-course.help-and-support.q2.body',
defaultMessage: 'You can select a course to import and decide whether to import all sections, '
- + 'subsections, units, or blocks from this course.
'
- + 'Not all courses content types can be imported, but this page will convey the status of imports '
- + 'and share any import errors found while importing your course.
'
- + 'For additional details you can review the Library Import documentation.
',
+ + 'subsections, units, or blocks from this course.'
+ + 'Not all courses content types can be imported, but this page will convey the status of imports '
+ + 'and share any import errors found while importing your course.
'
+ + 'For additional details you can review the Library Import documentation.
',
description: 'Body of the second question in the Help & Support sidebar',
},
importCourseStepperTitle: {
@@ -116,7 +116,7 @@ const messages = defineMessages({
importCourseInProgressStatusBody: {
id: 'course-authoring.library-authoring.import-course.review-details.in-progress.body',
defaultMessage: '{courseName} is being analyzed for review prior to import. For large courses, this may take some time.'
- + ' Please remain on this page.',
+ + ' Please remain on this page.',
description: 'Body of the info card with the in-progress status in the course import modal.',
},
importCourseAnalysisSummary: {
@@ -232,7 +232,7 @@ const messages = defineMessages({
importSuccessfulBody: {
id: 'library-authoring.import-course.import-details.import-successful.body',
defaultMessage: 'Course {courseName} has been imported successfully.'
- + ' Imported Course content can be edited and remixed in your Library, and reused in Courses',
+ + ' Imported Course content can be edited and remixed in your Library, and reused in Courses',
description: 'Body of the import successful card in the import details page',
},
importSummaryTitle: {
@@ -288,14 +288,14 @@ const messages = defineMessages({
importPartialAlertBody: {
id: 'library-authoring.import-course.import-details.import-partial.alert.title',
defaultMessage: '{courseName} has been imported to your library in a collection called {collectionName}.'
- + ' Some content was not added to your course. See details below.',
+ + ' Some content was not added to your course. See details below.',
description: 'Body of the alert in the import details page when the migration is in partial import.',
},
importPartialBody: {
id: 'library-authoring.import-course.import-details.import-partial.alert.title',
defaultMessage: '{percentage}% of Course {courseName} has been imported successfully.'
- + ' Imported Course content can be edited and remixed in your Library, and reused in Courses.
'
- + 'Details of the import, including reasons some content was not imported are described below
',
+ + ' Imported Course content can be edited and remixed in your Library, and reused in Courses.'
+ + 'Details of the import, including reasons some content was not imported are described below
',
description: 'Body of the import details page when the migration is in partial import.',
},
importPartialReasonTableBlockName: {
@@ -321,8 +321,8 @@ const messages = defineMessages({
importBlockedBody: {
id: 'library-authoring.import-course.review-details.import-blocked.body',
defaultMessage: 'This import would exceed the Content Library limit of {limitNumber} items.'
- + ' To prevent incomplete or lost content, the import has been blocked. For more information,'
- + ' view the Content Library documentation.',
+ + ' To prevent incomplete or lost content, the import has been blocked. For more information,'
+ + ' view the Content Library documentation.',
description: 'Body for the alert in review details when the import is blocked',
},
importNotPossibleTooltip: {
diff --git a/src/library-authoring/import-course/stepper/ImportStepperPage.test.tsx b/src/library-authoring/import-course/stepper/ImportStepperPage.test.tsx
index 3b6d7f2048..478e4dd4e7 100644
--- a/src/library-authoring/import-course/stepper/ImportStepperPage.test.tsx
+++ b/src/library-authoring/import-course/stepper/ImportStepperPage.test.tsx
@@ -30,7 +30,8 @@ const courses = [
{
courseKey: mockGetPreviewModulestoreMigration.sourceKeyGood,
displayName: 'Managing Risk in the Information Age',
- lmsLink: '//localhost:18000/courses/course-v1:HarvardX+123+2023/jump_to/block-v1:HarvardX+123+2023+type@course+block@course',
+ lmsLink:
+ '//localhost:18000/courses/course-v1:HarvardX+123+2023/jump_to/block-v1:HarvardX+123+2023+type@course+block@course',
number: '123',
org: 'HarvardX',
rerunLink: '/course_rerun/course-v1:HarvardX+123+2023',
@@ -40,7 +41,8 @@ const courses = [
{
courseKey: mockGetPreviewModulestoreMigration.sourceKeyBlockLimit,
displayName: 'Course with a lot of components',
- lmsLink: '//localhost:18000/courses/course-v1:HarvardX+123+2023/jump_to/block-v1:HarvardX+123+2023+type@course+block@course',
+ lmsLink:
+ '//localhost:18000/courses/course-v1:HarvardX+123+2023/jump_to/block-v1:HarvardX+123+2023+type@course+block@course',
number: '3',
org: 'HarvardX',
rerunLink: '/course_rerun/course-v1:HarvardX+123+2023',
@@ -50,7 +52,8 @@ const courses = [
{
courseKey: mockGetPreviewModulestoreMigration.sourceKeyBlockLoading,
displayName: 'Course with a loading',
- lmsLink: '//localhost:18000/courses/course-v1:HarvardX+123+2023/jump_to/block-v1:HarvardX+123+2023+type@course+block@course',
+ lmsLink:
+ '//localhost:18000/courses/course-v1:HarvardX+123+2023/jump_to/block-v1:HarvardX+123+2023+type@course+block@course',
number: '4',
org: 'HarvardX',
rerunLink: '/course_rerun/course-v1:HarvardX+123+2023',
@@ -99,7 +102,7 @@ const renderComponent = (studioHomeState: Partial = {}) => {
...render(
,
{
- extraWrapper: ({ children }: { children: React.ReactNode }) => (
+ extraWrapper: ({ children }: { children: React.ReactNode; }) => (
{children}
@@ -177,9 +180,13 @@ describe(' ', () => {
expect(nextButton).toBeEnabled();
await user.click(nextButton);
- await waitFor(async () => expect(await screen.findByText(
- /managing risk in the information age is being analyzed for review prior to import/i,
- )).toBeInTheDocument());
+ await waitFor(async () =>
+ expect(
+ await screen.findByText(
+ /managing risk in the information age is being analyzed for review prior to import/i,
+ ),
+ ).toBeInTheDocument()
+ );
expect(await screen.findByText('Analysis Summary')).toBeInTheDocument();
// The import details is loading
@@ -211,9 +218,11 @@ describe(' ', () => {
await user.click(nextButton);
expect(await screen.findByText(/Import Blocked/i)).toBeInTheDocument();
- expect(await screen.findByText(
- /This import would exceed the Content Library limit of 1000 items/i,
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ /This import would exceed the Content Library limit of 1000 items/i,
+ ),
+ ).toBeInTheDocument();
expect(screen.getByRole('button', { name: /import course/i })).toBeDisabled();
});
diff --git a/src/library-authoring/import-course/stepper/ImportStepperPage.tsx b/src/library-authoring/import-course/stepper/ImportStepperPage.tsx
index 79990d0377..343a8f171d 100644
--- a/src/library-authoring/import-course/stepper/ImportStepperPage.tsx
+++ b/src/library-authoring/import-course/stepper/ImportStepperPage.tsx
@@ -3,7 +3,13 @@ import { Helmet } from 'react-helmet';
import { useNavigate } from 'react-router-dom';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import {
- ActionRow, Button, Chip, Container, Layout, OverlayTrigger, Stepper,
+ ActionRow,
+ Button,
+ Chip,
+ Container,
+ Layout,
+ OverlayTrigger,
+ Stepper,
Tooltip,
} from '@openedx/paragon';
@@ -149,46 +155,50 @@ export const ImportStepperPage = () => {
- {currentStep === 'select-course' ? (
-
- navigate('../import')}>
-
-
- setCurrentStep('review-details')}
- disabled={!selectedCourseId}
- >
-
-
-
- ) : (
-
- setCurrentStep('select-course')}>
-
-
- {importIsBlocked ? (
-
-
-
- )}
+ {currentStep === 'select-course' ?
+ (
+
+ navigate('../import')}>
+
+
+ setCurrentStep('review-details')}
+ disabled={!selectedCourseId}
>
-
-
-
-
- ) : (
-
- )}
-
- )}
+
+
+
+ ) :
+ (
+
+ setCurrentStep('select-course')}>
+
+
+ {importIsBlocked ?
+ (
+
+
+
+ }
+ >
+
+
+
+
+ ) :
+ (
+
+ )}
+
+ )}
diff --git a/src/library-authoring/import-course/stepper/ReviewImportDetails.test.tsx b/src/library-authoring/import-course/stepper/ReviewImportDetails.test.tsx
index f87509601a..3ee54380ac 100644
--- a/src/library-authoring/import-course/stepper/ReviewImportDetails.test.tsx
+++ b/src/library-authoring/import-course/stepper/ReviewImportDetails.test.tsx
@@ -23,7 +23,7 @@ jest.mock('@src/library-authoring/data/apiHooks', () => ({
}));
const render = (element: React.ReactElement) => {
- const params: { libraryId: string } = { libraryId };
+ const params: { libraryId: string; } = { libraryId };
return baseRender(element, {
path: '/libraries/:libraryId/import/course',
params,
@@ -31,7 +31,7 @@ const render = (element: React.ReactElement) => {
- { children }
+ {children}
),
});
@@ -79,11 +79,13 @@ describe('ReviewImportDetails', () => {
expect(await screen.findByRole('alert')).toBeInTheDocument();
expect(await screen.findByText(/Import Analysis Completed: Reimport/i)).toBeInTheDocument();
- expect(await screen.findByText(
- messages.importCourseAnalysisCompleteReimportBody.defaultMessage
- .replace('{courseName}', 'Test Course')
- .replace('{libraryName}', 'Library title'),
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ messages.importCourseAnalysisCompleteReimportBody.defaultMessage
+ .replace('{courseName}', 'Test Course')
+ .replace('{libraryName}', 'Library title'),
+ ),
+ ).toBeInTheDocument();
});
it('renders warning when unsupportedBlockPercentage > 0', async () => {
@@ -93,15 +95,19 @@ describe('ReviewImportDetails', () => {
data: null,
});
- render( );
+ render(
+ ,
+ );
expect(await screen.findByRole('alert')).toBeInTheDocument();
expect(await screen.findByText(/Import Analysis Complete/i)).toBeInTheDocument();
- expect(await screen.findByText(
- /75% of course content will be imported into a collection in your library called Test Course. Some content will not be imported. For details see below./i,
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ /75% of course content will be imported into a collection in your library called Test Course. Some content will not be imported. For details see below./i,
+ ),
+ ).toBeInTheDocument();
expect(await screen.findByText(/Total Blocks/i)).toBeInTheDocument();
expect(await screen.findByText('15/20')).toBeInTheDocument();
expect(await screen.findByText('Sections')).toBeInTheDocument();
@@ -121,15 +127,19 @@ describe('ReviewImportDetails', () => {
data: null,
});
- render( );
+ render(
+ ,
+ );
expect(await screen.findByRole('alert')).toBeInTheDocument();
expect(await screen.findByText(/Import Blocked/i)).toBeInTheDocument();
- expect(await screen.findByText(
- /This import would exceed the Content Library limit of 1000 items/i,
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ /This import would exceed the Content Library limit of 1000 items/i,
+ ),
+ ).toBeInTheDocument();
});
it('renders success alert when no unsupported blocks', async () => {
@@ -139,15 +149,19 @@ describe('ReviewImportDetails', () => {
data: null,
});
- render( );
+ render(
+ ,
+ );
expect(await screen.findByRole('alert')).toBeInTheDocument();
- expect(await screen.findByText(
- messages.importCourseAnalysisCompleteAllContentBody.defaultMessage
- .replace('{courseName}', 'Test Course'),
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ messages.importCourseAnalysisCompleteAllContentBody.defaultMessage
+ .replace('{courseName}', 'Test Course'),
+ ),
+ ).toBeInTheDocument();
expect(await screen.findByText(/Total Blocks/i)).toBeInTheDocument();
expect(await screen.findByText('10')).toBeInTheDocument();
expect(await screen.findByText('Sections')).toBeInTheDocument();
diff --git a/src/library-authoring/import-course/stepper/ReviewImportDetails.tsx b/src/library-authoring/import-course/stepper/ReviewImportDetails.tsx
index 903f0cd2a6..369b1b4b07 100644
--- a/src/library-authoring/import-course/stepper/ReviewImportDetails.tsx
+++ b/src/library-authoring/import-course/stepper/ReviewImportDetails.tsx
@@ -30,7 +30,7 @@ const Banner = ({
const { libraryId } = useLibraryContext();
const { data: migrationInfoData, isPending: migrationInfoIsPending } = useMigrationInfo(
[courseId!],
- (courseId !== undefined && libraryId !== undefined),
+ courseId !== undefined && libraryId !== undefined,
);
const currentMigrationInfo = useMemo(() => {
@@ -53,7 +53,9 @@ const Banner = ({
if (isBlockDataPending || migrationInfoIsPending) {
return (
-
+
+
+
-
+
+
+
0) {
return (
-
+
+
+
-
+
+
+
{
+export const ReviewImportDetails = ({ courseId }: { courseId: string; }) => {
const { libraryId } = useLibraryContext();
const {
@@ -157,7 +165,9 @@ export const ReviewImportDetails = ({ courseId }: { courseId: string }) => {
/>
{!limitIsExceeded && (
<>
-
+
+
+
{
/>
{!isPreviewMigrationPending && unssuportedBlocks > 0
&& (
- <>
-
-
-
-
- >
+ <>
+
+
+
+
+
+
+ >
)}
>
)}
diff --git a/src/library-authoring/import-course/stepper/SummaryCard.tsx b/src/library-authoring/import-course/stepper/SummaryCard.tsx
index c7a2ecc50a..65ab23852b 100644
--- a/src/library-authoring/import-course/stepper/SummaryCard.tsx
+++ b/src/library-authoring/import-course/stepper/SummaryCard.tsx
@@ -1,7 +1,12 @@
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import type { MessageDescriptor } from 'react-intl';
import {
- Bubble, Card, Icon, OverlayTrigger, Stack, Tooltip,
+ Bubble,
+ Card,
+ Icon,
+ OverlayTrigger,
+ Stack,
+ Tooltip,
} from '@openedx/paragon';
import { Info, Widgets } from '@openedx/paragon/icons';
@@ -19,9 +24,7 @@ const DisplayNumber = ({ count, isPending }: DisplayNumberProps) => {
if (isPending) {
return ;
}
- return (
- {count}
- );
+ return {count} ;
};
interface DisplayNumberComponentProps {
@@ -34,26 +37,31 @@ interface DisplayNumberComponentProps {
}
const DisplayNumberComponent = ({
- count, isPending, icon, typeId, title, info,
+ count,
+ isPending,
+ icon,
+ typeId,
+ title,
+ info,
}: DisplayNumberComponentProps) => (
<>
{info
- && (
+ && (
{info}
- )}
+ }
>
- )}
+ )}
{icon
? (
@@ -139,14 +147,16 @@ export const SummaryCard = ({
icon={Widgets}
typeId="unsupported"
title={messages.importCourseComponents}
- info={unsupportedBlocks ? (
-
- ) : null}
+ info={unsupportedBlocks ?
+ (
+
+ ) :
+ null}
/>
diff --git a/src/library-authoring/index.tsx b/src/library-authoring/index.tsx
index 7b0553e307..6c9ecd97bd 100644
--- a/src/library-authoring/index.tsx
+++ b/src/library-authoring/index.tsx
@@ -1,7 +1,7 @@
-export { default as LibraryLayout } from './LibraryLayout';
-export { LibraryAndComponentPicker, ComponentPicker } from './component-picker';
export { type SelectedComponent } from './common/context/ComponentPickerContext';
-export { CreateLibrary, CreateLibraryModal } from './create-library';
+export { LibraryAndComponentPicker, ComponentPicker } from './component-picker';
export { CreateLegacyLibrary } from './create-legacy-library';
+export { CreateLibrary, CreateLibraryModal } from './create-library';
export { libraryAuthoringQueryKeys, useContentLibraryV2List } from './data/apiHooks';
export { default as PreviewChangesEmbed } from './legacy-integration/PreviewChangesEmbed';
+export { default as LibraryLayout } from './LibraryLayout';
diff --git a/src/library-authoring/legacy-integration/PreviewChangesEmbed.tsx b/src/library-authoring/legacy-integration/PreviewChangesEmbed.tsx
index c1fa8c90c5..f164d3802c 100644
--- a/src/library-authoring/legacy-integration/PreviewChangesEmbed.tsx
+++ b/src/library-authoring/legacy-integration/PreviewChangesEmbed.tsx
@@ -30,9 +30,15 @@ const PreviewChangesEmbed = () => {
return (
<>
- {/* It's not necessary since this will usually be in an
)}
{shouldShowAdminConsoleLink && (
-
+
{intl.formatMessage(messages.libraryTeamButtonTitle)}
)}
diff --git a/src/library-authoring/library-info/LibraryInfoHeader.test.tsx b/src/library-authoring/library-info/LibraryInfoHeader.test.tsx
index f939756437..8507df4b45 100644
--- a/src/library-authoring/library-info/LibraryInfoHeader.test.tsx
+++ b/src/library-authoring/library-info/LibraryInfoHeader.test.tsx
@@ -15,9 +15,10 @@ import LibraryInfoHeader from './LibraryInfoHeader';
const { libraryId: mockLibraryId, libraryIdReadOnly, libraryData } = mockContentLibrary;
-const render = (libraryId: string = mockLibraryId) => baseRender( , {
- extraWrapper: ({ children }) => { children } ,
-});
+const render = (libraryId: string = mockLibraryId) =>
+ baseRender( , {
+ extraWrapper: ({ children }) => {children} ,
+ });
let axiosMock: MockAdapter;
let mockShowToast: (message: string) => void;
diff --git a/src/library-authoring/library-info/LibraryInfoHeader.tsx b/src/library-authoring/library-info/LibraryInfoHeader.tsx
index 00d5b304ad..b24ff3f263 100644
--- a/src/library-authoring/library-info/LibraryInfoHeader.tsx
+++ b/src/library-authoring/library-info/LibraryInfoHeader.tsx
@@ -53,7 +53,7 @@ const LibraryInfoHeader = () => {
return (
- { inputIsActive
+ {inputIsActive
? (
{
unknown: null,
};
- const buildBody = () : React.ReactNode => bodyComponentMap[sidebarItemInfo?.type || 'unknown'];
+ const buildBody = (): React.ReactNode => bodyComponentMap[sidebarItemInfo?.type || 'unknown'];
const buildHeader = (): React.ReactNode => headerComponentMap[sidebarItemInfo?.type || 'unknown'];
return (
diff --git a/src/library-authoring/library-team/AddLibraryTeamMember.tsx b/src/library-authoring/library-team/AddLibraryTeamMember.tsx
index baabcd32a8..63c70e9d37 100644
--- a/src/library-authoring/library-team/AddLibraryTeamMember.tsx
+++ b/src/library-authoring/library-team/AddLibraryTeamMember.tsx
@@ -12,8 +12,8 @@ import FormikControl from '../../generic/FormikControl';
import { EXAMPLE_USER_EMAIL } from './constants';
const AddLibraryTeamMember = ({ onSubmit, onCancel }: {
- onSubmit: ({ email } : { email: string }) => void,
- onCancel: () => void,
+ onSubmit: ({ email }: { email: string; }) => void;
+ onCancel: () => void;
}) => {
const intl = useIntl();
@@ -22,11 +22,9 @@ const AddLibraryTeamMember = ({ onSubmit, onCancel }: {
{({ handleSubmit, values }) => (
diff --git a/src/library-authoring/library-team/LibraryTeam.test.tsx b/src/library-authoring/library-team/LibraryTeam.test.tsx
index c851ac59ba..9e94beb0f0 100644
--- a/src/library-authoring/library-team/LibraryTeam.test.tsx
+++ b/src/library-authoring/library-team/LibraryTeam.test.tsx
@@ -118,7 +118,8 @@ describe(' ', () => {
}
// Single Admin user cannot be demoted or deleted.
- expect(screen.getByText('Promote another member to Admin to change this user\'s access rights.')).toBeInTheDocument();
+ expect(screen.getByText('Promote another member to Admin to change this user\'s access rights.'))
+ .toBeInTheDocument();
// Author + Reader can be made Admin
expect(screen.getAllByRole('button', { name: 'Make Admin' }).length).toBe(2);
@@ -206,9 +207,11 @@ describe(' ', () => {
expect(axiosMock.history.post.length).toEqual(1);
});
- expect(await screen.findByText(
- 'Error adding Team Member. This is a specific error.',
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ 'Error adding Team Member. This is a specific error.',
+ ),
+ ).toBeInTheDocument();
});
it('shows error when specific error (Array)', async () => {
@@ -232,9 +235,11 @@ describe(' ', () => {
expect(axiosMock.history.post.length).toEqual(1);
});
- expect(await screen.findByText(
- 'Error adding Team Member. This is a specific error.',
- )).toBeInTheDocument();
+ expect(
+ await screen.findByText(
+ 'Error adding Team Member. This is a specific error.',
+ ),
+ ).toBeInTheDocument();
});
it('shows error', async () => {
diff --git a/src/library-authoring/library-team/LibraryTeam.tsx b/src/library-authoring/library-team/LibraryTeam.tsx
index d7f14cbc8f..a506f4c50e 100644
--- a/src/library-authoring/library-team/LibraryTeam.tsx
+++ b/src/library-authoring/library-team/LibraryTeam.tsx
@@ -56,7 +56,7 @@ const LibraryTeam: React.FC> = () => {
const addMember = useAddLibraryTeamMember(libraryId);
const onAddMember = useCallback(
- (data: { email: string }) => {
+ (data: { email: string; }) => {
const { email } = data;
addMember.mutateAsync({
libraryId,
@@ -141,21 +141,25 @@ const LibraryTeam: React.FC> = () => {
}
const { email: currentUserEmail, administrator: isGlobalStaff } = getAuthenticatedUser();
- const isLibraryAdmin = libraryTeamMembers ? (
- libraryTeamMembers.filter(
- ({ email, accessLevel }) => (
- accessLevel === LibraryRole.Admin.toString() && email === currentUserEmail
- ),
- ).length === 1
- ) : false;
+ const isLibraryAdmin = libraryTeamMembers ?
+ (
+ libraryTeamMembers.filter(
+ ({ email, accessLevel }) => (
+ accessLevel === LibraryRole.Admin.toString() && email === currentUserEmail
+ ),
+ ).length === 1
+ ) :
+ false;
const canChangeRoles = libraryData ? libraryData.canEditLibrary && (isLibraryAdmin || isGlobalStaff) : false;
// Is there only one Admin member in the Team? We'll prevent that user from being demoted/deleted.
- const singleAdmin = libraryTeamMembers ? (
- libraryTeamMembers.filter(
- ({ accessLevel }) => accessLevel === LibraryRole.Admin.toString(),
- ).length === 1
- ) : false;
+ const singleAdmin = libraryTeamMembers ?
+ (
+ libraryTeamMembers.filter(
+ ({ accessLevel }) => accessLevel === LibraryRole.Admin.toString(),
+ ).length === 1
+ ) :
+ false;
return (
@@ -204,21 +208,23 @@ const LibraryTeam: React.FC> = () => {
)}
- {libraryTeamMembers && libraryTeamMembers.length ? (
- libraryTeamMembers.map(({ username, accessLevel, email }) => (
-
- ))
- ) : }
+ {libraryTeamMembers && libraryTeamMembers.length ?
+ (
+ libraryTeamMembers.map(({ username, accessLevel, email }) => (
+
+ ))
+ ) :
+ }
{isError && }
diff --git a/src/library-authoring/library-team/LibraryTeamMember.tsx b/src/library-authoring/library-team/LibraryTeamMember.tsx
index 115d5f32b7..39cea11c69 100644
--- a/src/library-authoring/library-team/LibraryTeamMember.tsx
+++ b/src/library-authoring/library-team/LibraryTeamMember.tsx
@@ -22,8 +22,8 @@ const MemberBadge = ({
role,
isCurrentUser,
}: {
- role: LibraryRole,
- isCurrentUser: boolean,
+ role: LibraryRole;
+ isCurrentUser: boolean;
}) => {
const roleMessage = ROLE_LABEL[role] ?? ROLE_LABEL[LibraryRole.Unknown];
const variant = ROLE_BADGE_VARIANT[role] ?? ROLE_BADGE_VARIANT[LibraryRole.Unknown];
@@ -50,14 +50,14 @@ const LibraryTeamMember = ({
onChangeRole,
onDeleteRole,
}: {
- username: string,
- email: string,
- accessLevel: string,
- canChangeRoles: boolean,
- isCurrentUser: boolean,
- isSingleAdmin: boolean,
- onChangeRole: (username: string, role: LibraryRole) => void,
- onDeleteRole: (username: string) => void,
+ username: string;
+ email: string;
+ accessLevel: string;
+ canChangeRoles: boolean;
+ isCurrentUser: boolean;
+ isSingleAdmin: boolean;
+ onChangeRole: (username: string, role: LibraryRole) => void;
+ onDeleteRole: (username: string) => void;
}) => {
const intl = useIntl();
@@ -77,38 +77,40 @@ const LibraryTeamMember = ({
{username}
{email}
- {canChangeThisMember ? (
-
- {availableRoles && availableRoles.length && availableRoles.map((newRole) => (
-
onChangeRole(username, newRole)}
- >
- {intl.formatMessage(CHANGE_ROLE_LABEL[newRole])}
-
- ))}
+ {canChangeThisMember ?
+ (
+
+ {availableRoles && availableRoles.length && availableRoles.map((newRole) => (
+ onChangeRole(username, newRole)}
+ >
+ {intl.formatMessage(CHANGE_ROLE_LABEL[newRole])}
+
+ ))}
- onDeleteRole(username)}
- iconAs={Icon}
- alt={intl.formatMessage(messages.deleteMember)}
- title={intl.formatMessage(messages.deleteMember)}
- />
-
- ) : (
- // We prevent the user from removing the last remaining Admin
- // user so that someone can still administrate this Library,
- // so show a message explaining why.
- canChangeRoles && (
-
-
+ onDeleteRole(username)}
+ iconAs={Icon}
+ alt={intl.formatMessage(messages.deleteMember)}
+ title={intl.formatMessage(messages.deleteMember)}
+ />
- )
- )}
+ ) :
+ (
+ // We prevent the user from removing the last remaining Admin
+ // user so that someone can still administrate this Library,
+ // so show a message explaining why.
+ canChangeRoles && (
+
+
+
+ )
+ )}
);
};
diff --git a/src/library-authoring/library-team/LibraryTeamModal.tsx b/src/library-authoring/library-team/LibraryTeamModal.tsx
index 87eab3a2a3..f227294870 100644
--- a/src/library-authoring/library-team/LibraryTeamModal.tsx
+++ b/src/library-authoring/library-team/LibraryTeamModal.tsx
@@ -10,7 +10,7 @@ export const LibraryTeamModal = () => {
const intl = useIntl();
const { sidebarAction, resetSidebarAction } = useSidebarContext();
// Open the library team modal only when Manage Team sidebar action is set
- const isOpen = (sidebarAction === SidebarActions.ManageTeam);
+ const isOpen = sidebarAction === SidebarActions.ManageTeam;
const onClose = useCallback(() => {
resetSidebarAction();
}, [resetSidebarAction]);
diff --git a/src/library-authoring/library-team/messages.ts b/src/library-authoring/library-team/messages.ts
index 32623b237a..3124df2977 100644
--- a/src/library-authoring/library-team/messages.ts
+++ b/src/library-authoring/library-team/messages.ts
@@ -69,10 +69,8 @@ const messages = defineMessages({
cannotChangeRoleSingleAdmin: {
id: 'course-authoring.library-authoring.library-team.cannot-changerole-single-admin',
defaultMessage: 'Promote another member to Admin to change this user\'s access rights.',
- description: (
- 'Shown to Library Admins if there\'s only one Admin in the Team,'
- + ' explaining why this member cannot be changed yet.'
- ),
+ description: 'Shown to Library Admins if there\'s only one Admin in the Team,'
+ + ' explaining why this member cannot be changed yet.',
},
makeMemberAdmin: {
id: 'course-authoring.library-authoring.library-team.make-member-admin',
diff --git a/src/library-authoring/routes.test.tsx b/src/library-authoring/routes.test.tsx
index 39c3695b4d..999974187c 100644
--- a/src/library-authoring/routes.test.tsx
+++ b/src/library-authoring/routes.test.tsx
@@ -44,7 +44,9 @@ describe('Library Authoring routes', () => {
newMockResult.results[0].query = query;
// And fake the required '_formatted' fields; it contains the highlighting ... around matched words
// eslint-disable-next-line no-underscore-dangle, no-param-reassign
- newMockResult.results[0]?.hits.forEach((hit) => { hit._formatted = { ...hit }; });
+ newMockResult.results[0]?.hits.forEach((hit) => {
+ hit._formatted = { ...hit };
+ });
return newMockResult;
});
});
diff --git a/src/library-authoring/routes.ts b/src/library-authoring/routes.ts
index cca3c9b262..9d67f7c990 100644
--- a/src/library-authoring/routes.ts
+++ b/src/library-authoring/routes.ts
@@ -67,11 +67,11 @@ export enum ContentType {
export const allLibraryPageTabs: ContentType[] = Object.values(ContentType);
export type NavigateToData = {
- selectedItemId?: string,
- collectionId?: string,
- containerId?: string,
- contentType?: ContentType,
- index?: number,
+ selectedItemId?: string;
+ collectionId?: string;
+ containerId?: string;
+ contentType?: ContentType;
+ index?: number;
};
export type LibraryRoutesData = {
@@ -123,7 +123,8 @@ export const useLibraryRoutes = (): LibraryRoutesData => {
insideSubsection,
insideUnits,
insideUnit,
- ].filter((match) => match).length > 1) {
+ ].filter((match) => match).length > 1
+ ) {
throw new Error('Cannot be inside more than one route at the same time.');
}
@@ -146,8 +147,10 @@ export const useLibraryRoutes = (): LibraryRoutesData => {
};
let route: string;
- if (routeParams.selectedItemId
- && (['components', 'units', 'sections', 'subsections'].includes(routeParams.selectedItemId || ''))) {
+ if (
+ routeParams.selectedItemId
+ && (['components', 'units', 'sections', 'subsections'].includes(routeParams.selectedItemId || ''))
+ ) {
// These are not valid selectedItemIds, but routes
routeParams.selectedItemId = undefined;
}
@@ -184,8 +187,10 @@ export const useLibraryRoutes = (): LibraryRoutesData => {
// FIXME: We are using the Collection key, not the full OpaqueKey. So we
// can't directly use the selectedItemId to determine if it's a collection.
// We need to change this to use the full OpaqueKey in the future.
- if (routeParams.selectedItemId?.startsWith('lct:')
- || routeParams.selectedItemId?.startsWith('lb:')) {
+ if (
+ routeParams.selectedItemId?.startsWith('lct:')
+ || routeParams.selectedItemId?.startsWith('lb:')
+ ) {
routeParams.selectedItemId = undefined;
}
route = ROUTES.COLLECTIONS;
diff --git a/src/library-authoring/section-subsections/LibraryContainerChildren.tsx b/src/library-authoring/section-subsections/LibraryContainerChildren.tsx
index 94922cc858..49308ad82e 100644
--- a/src/library-authoring/section-subsections/LibraryContainerChildren.tsx
+++ b/src/library-authoring/section-subsections/LibraryContainerChildren.tsx
@@ -1,9 +1,15 @@
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import {
- useCallback, useContext, useEffect, useState,
+ useCallback,
+ useContext,
+ useEffect,
+ useState,
} from 'react';
import {
- ActionRow, Badge, Icon, Stack,
+ ActionRow,
+ Badge,
+ Icon,
+ Stack,
} from '@openedx/paragon';
import { Description } from '@openedx/paragon/icons';
import { InplaceTextEditor } from '@src/generic/inplace-text-editor';
@@ -44,7 +50,10 @@ interface ContainerRowProps extends LibraryContainerChildrenProps {
}
const ContainerRow = ({
- containerKey, container, readOnly, index,
+ containerKey,
+ container,
+ readOnly,
+ index,
}: ContainerRowProps) => {
const intl = useIntl();
const { showToast } = useContext(ToastContext);
@@ -78,10 +87,8 @@ const ContainerRow = ({
return (
<>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
-
+
{
- const style: { marginBottom: string, borderRadius: string, outline?: string } = {
+ const style: { marginBottom: string; borderRadius: string; outline?: string; } = {
marginBottom: '1rem',
borderRadius: '8px',
};
@@ -211,11 +218,9 @@ export const LibraryContainerChildren = ({ containerKey, readOnly }: LibraryCont
{children?.length === 0 && (
- {containerType === ContainerType.Section ? (
-
- ) : (
-
- )}
+ {containerType === ContainerType.Section ?
+ :
+ }
)}
- )}
+ }
/>
-
))}
diff --git a/src/library-authoring/section-subsections/LibrarySectionPage.tsx b/src/library-authoring/section-subsections/LibrarySectionPage.tsx
index 40035ca2e3..bb2b488d5b 100644
--- a/src/library-authoring/section-subsections/LibrarySectionPage.tsx
+++ b/src/library-authoring/section-subsections/LibrarySectionPage.tsx
@@ -94,13 +94,13 @@ export const LibrarySectionPage = () => {
} />}
breadcrumbs={breadcrumbs}
- headerActions={(
+ headerActions={
- )}
+ }
hideBorder
/>
diff --git a/src/library-authoring/section-subsections/LibrarySectionSubsectionPage.test.tsx b/src/library-authoring/section-subsections/LibrarySectionSubsectionPage.test.tsx
index d95919a6ea..b701d28109 100644
--- a/src/library-authoring/section-subsections/LibrarySectionSubsectionPage.test.tsx
+++ b/src/library-authoring/section-subsections/LibrarySectionSubsectionPage.test.tsx
@@ -92,9 +92,10 @@ describe('
', () => {
render(
, {
path,
routerProps: {
- initialEntries: [childId
- ? `/library/${libId}/${cType}/${cId}/${childId}`
- : `/library/${libId}/${cType}/${cId}`,
+ initialEntries: [
+ childId
+ ? `/library/${libId}/${cType}/${cId}/${childId}`
+ : `/library/${libId}/${cType}/${cId}`,
],
},
});
diff --git a/src/library-authoring/section-subsections/LibrarySubsectionPage.tsx b/src/library-authoring/section-subsections/LibrarySubsectionPage.tsx
index 64116a6cc2..de5e525c5d 100644
--- a/src/library-authoring/section-subsections/LibrarySubsectionPage.tsx
+++ b/src/library-authoring/section-subsections/LibrarySubsectionPage.tsx
@@ -28,7 +28,10 @@ export const LibrarySubsectionPage = () => {
const { data: libraryData, isPending: isLibPending } = useContentLibrary(libraryId);
// fetch subsectionData from index as it includes its parent sections as well.
const {
- hits, isPending, isError, error,
+ hits,
+ isPending,
+ isError,
+ error,
} = useContentFromSearchIndex(containerId ? [containerId] : []);
const subsectionData = (hits as ContainerHit[])?.[0];
@@ -74,20 +77,20 @@ export const LibrarySubsectionPage = () => {
} />}
- breadcrumbs={(
+ breadcrumbs={
- )}
- headerActions={(
+ }
+ headerActions={
- )}
+ }
hideBorder
/>
diff --git a/src/library-authoring/units/LibraryUnitBlocks.tsx b/src/library-authoring/units/LibraryUnitBlocks.tsx
index e486bd8b5e..cce759d0ba 100644
--- a/src/library-authoring/units/LibraryUnitBlocks.tsx
+++ b/src/library-authoring/units/LibraryUnitBlocks.tsx
@@ -1,11 +1,17 @@
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import {
- ActionRow, Badge, Icon, Stack,
+ ActionRow,
+ Badge,
+ Icon,
+ Stack,
} from '@openedx/paragon';
import { Description } from '@openedx/paragon/icons';
import classNames from 'classnames';
import {
- useCallback, useContext, useEffect, useState,
+ useCallback,
+ useContext,
+ useEffect,
+ useState,
} from 'react';
import { blockTypes } from '@src/editors/data/constants/app';
import DraggableList, { SortableItem } from '@src/generic/DraggableList';
@@ -128,7 +134,10 @@ const BlockHeader = ({ block, index, readOnly }: ComponentBlockProps) => {
/** ComponentBlock to render preview of given component under Unit */
const ComponentBlock = ({
- block, readOnly, isDragging, index,
+ block,
+ readOnly,
+ isDragging,
+ index,
}: ComponentBlockProps) => {
const { openComponentEditor } = useOptionalLibraryContext();
const { showOnlyPublished } = usePublishedFilterContext();
@@ -197,7 +206,9 @@ const ComponentBlock = ({
}
}}
disabled={readOnly}
- cardClassName={sidebarItemInfo?.id === block.originalId && sidebarItemInfo?.index === index ? 'selected' : undefined}
+ cardClassName={sidebarItemInfo?.id === block.originalId && sidebarItemInfo?.index === index
+ ? 'selected'
+ : undefined}
>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
', () => {
it('shows empty unit', async () => {
renderLibraryUnitPage(mockGetContainerMetadata.unitIdEmpty);
- expect((await screen.findAllByText('Test Unit'))).toHaveLength(2); // Header + Sidebar
+ expect(await screen.findAllByText('Test Unit')).toHaveLength(2); // Header + Sidebar
expect(await screen.findByText('This unit is empty')).toBeInTheDocument();
});
it('can rename unit', async () => {
renderLibraryUnitPage();
- expect((await screen.findAllByText('Test Unit'))).toHaveLength(2); // Header + Sidebar
+ expect(await screen.findAllByText('Test Unit')).toHaveLength(2); // Header + Sidebar
const editUnitTitleButton = screen.getAllByRole(
'button',
@@ -159,7 +159,7 @@ describe('
', () => {
it('show error if renaming unit fails', async () => {
renderLibraryUnitPage();
- expect((await screen.findAllByText('Test Unit'))).toHaveLength(2); // Header + Sidebar
+ expect(await screen.findAllByText('Test Unit')).toHaveLength(2); // Header + Sidebar
const editUnitTitleButton = screen.getAllByRole(
'button',
@@ -213,7 +213,7 @@ describe('
', () => {
it('should open and close component sidebar on component selection', async () => {
const user = userEvent.setup();
renderLibraryUnitPage();
- expect((await screen.findAllByText('Test Unit'))).toHaveLength(2); // Header + Sidebar
+ expect(await screen.findAllByText('Test Unit')).toHaveLength(2); // Header + Sidebar
// No Preview tab shown in sidebar
expect(screen.queryByText('Preview')).not.toBeInTheDocument();
@@ -238,7 +238,7 @@ describe('
', () => {
const url = getXBlockFieldsApiUrl('lb:org1:Demo_course_generated:html:text-0');
axiosMock.onPost(url).reply(200);
renderLibraryUnitPage();
- expect((await screen.findAllByText('Test Unit'))).toHaveLength(2); // Header + Sidebar
+ expect(await screen.findAllByText('Test Unit')).toHaveLength(2); // Header + Sidebar
// Wait loading of the component
await screen.findByText('text block 0');
@@ -273,7 +273,7 @@ describe('
', () => {
const url = getXBlockFieldsApiUrl('lb:org1:Demo_course_generated:html:text-0');
axiosMock.onPost(url).reply(400);
renderLibraryUnitPage();
- expect((await screen.findAllByText('Test Unit'))).toHaveLength(2); // Header + Sidebar
+ expect(await screen.findAllByText('Test Unit')).toHaveLength(2); // Header + Sidebar
// Wait loading of the component
await screen.findByText('text block 0');
diff --git a/src/library-authoring/units/LibraryUnitPage.tsx b/src/library-authoring/units/LibraryUnitPage.tsx
index 9d447ef547..83de6f55a6 100644
--- a/src/library-authoring/units/LibraryUnitPage.tsx
+++ b/src/library-authoring/units/LibraryUnitPage.tsx
@@ -35,7 +35,10 @@ export const LibraryUnitPage = () => {
const { data: libraryData, isPending: isLibPending } = useContentLibrary(libraryId);
// fetch unitData from index as it includes its parent subsections as well.
const {
- hits, isPending, isError, error,
+ hits,
+ isPending,
+ isError,
+ error,
} = useContentFromSearchIndex(containerId ? [containerId] : []);
const unitData = (hits as ContainerHit[])?.[0];
@@ -61,7 +64,9 @@ export const LibraryUnitPage = () => {
return (
-
{libraryData.title} | {process.env.SITE_NAME}
+
+ {libraryData.title} | {process.env.SITE_NAME}
+
{
} />}
- headerActions={(
+ headerActions={
- )}
- breadcrumbs={(
+ }
+ breadcrumbs={
- )}
+ }
hideBorder
/>
diff --git a/src/optimizer-page/CourseOptimizerPage.test.js b/src/optimizer-page/CourseOptimizerPage.test.js
index 80a95d2cb2..89051cc72b 100644
--- a/src/optimizer-page/CourseOptimizerPage.test.js
+++ b/src/optimizer-page/CourseOptimizerPage.test.js
@@ -1,14 +1,21 @@
/* eslint-disable @typescript-eslint/no-shadow */
/* eslint-disable react/jsx-filename-extension */
import {
- fireEvent, render, waitFor, screen,
+ fireEvent,
+ render,
+ waitFor,
+ screen,
initializeMocks,
} from '@src/testUtils';
import { CourseAuthoringProvider } from '@src/CourseAuthoringContext';
import messages from './messages';
import generalMessages from '../messages';
import scanResultsMessages from './scan-results/messages';
-import CourseOptimizerPage, { pollLinkCheckDuringScan, pollRerunLinkUpdateDuringUpdate, pollRerunLinkUpdateStatus } from './CourseOptimizerPage';
+import CourseOptimizerPage, {
+ pollLinkCheckDuringScan,
+ pollRerunLinkUpdateDuringUpdate,
+ pollRerunLinkUpdateStatus,
+} from './CourseOptimizerPage';
import { postLinkCheckCourseApiUrl, getLinkCheckStatusApiUrl } from './data/api';
import {
mockApiResponse,
@@ -61,7 +68,10 @@ describe('CourseOptimizerPage', () => {
mockFetchLinkCheckStatus = jest.fn();
jest.spyOn(thunks, 'fetchLinkCheckStatus').mockImplementation(mockFetchLinkCheckStatus);
jest.useFakeTimers();
- jest.spyOn(global, 'setInterval').mockImplementation((cb) => { cb(); return true; });
+ jest.spyOn(global, 'setInterval').mockImplementation((cb) => {
+ cb();
+ return true;
+ });
});
afterEach(() => {
diff --git a/src/optimizer-page/CourseOptimizerPage.tsx b/src/optimizer-page/CourseOptimizerPage.tsx
index 19f33fcf3f..0da9c6fe6b 100644
--- a/src/optimizer-page/CourseOptimizerPage.tsx
+++ b/src/optimizer-page/CourseOptimizerPage.tsx
@@ -1,11 +1,19 @@
/* eslint-disable no-param-reassign */
import {
- useEffect, useState, useRef, MutableRefObject,
+ useEffect,
+ useState,
+ useRef,
+ MutableRefObject,
} from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
- Badge, Container, Layout, Card, Icon, StatefulButton,
+ Badge,
+ Container,
+ Layout,
+ Card,
+ Icon,
+ StatefulButton,
} from '@openedx/paragon';
import { SpinnerSimple } from '@openedx/paragon/icons';
import { Helmet } from 'react-helmet';
@@ -19,8 +27,15 @@ import { RERUN_LINK_UPDATE_STATUSES } from './data/constants';
import { STATEFUL_BUTTON_STATES } from '../constants';
import messages from './messages';
import {
- getCurrentStage, getError, getLinkCheckInProgress, getLoadingStatus, getSavingStatus, getLinkCheckResult,
- getLastScannedAt, getRerunLinkUpdateInProgress, getRerunLinkUpdateResult,
+ getCurrentStage,
+ getError,
+ getLinkCheckInProgress,
+ getLoadingStatus,
+ getSavingStatus,
+ getLinkCheckResult,
+ getLastScannedAt,
+ getRerunLinkUpdateInProgress,
+ getRerunLinkUpdateResult,
} from './data/selectors';
import { startLinkCheck, fetchLinkCheckStatus, fetchRerunLinkUpdateStatus } from './data/thunks';
import ScanResults from './scan-results';
@@ -168,9 +183,9 @@ const CourseOptimizerPage = () => {
if (rerunUpdateInterval.current) { clearInterval(rerunUpdateInterval.current); }
return (
- //
+ //
- //
+ //
);
}
@@ -223,7 +238,7 @@ const CourseOptimizerPage = () => {
}}
state={getScanButtonState()}
onClick={() => dispatch(startLinkCheck(courseId))}
- disabled={!!(linkCheckInProgress) && !errorMessage}
+ disabled={!!linkCheckInProgress && !errorMessage}
variant="primary"
data-testid="scan-course"
/>
@@ -250,7 +265,12 @@ const CourseOptimizerPage = () => {
title={intl.formatMessage(messages.scanHeader)}
/>
- {lastScannedAt && `${intl.formatMessage(messages.lastScannedOn)} ${intl.formatDate(lastScannedAt, { year: 'numeric', month: 'long', day: 'numeric' })}`}
+
+ {lastScannedAt &&
+ `${intl.formatMessage(messages.lastScannedOn)} ${
+ intl.formatDate(lastScannedAt, { year: 'numeric', month: 'long', day: 'numeric' })
+ }`}
+
{
const url = api.postRerunLinkUpdateApiUrl(courseId);
axiosMock.onPost(url).networkError();
- await expect(api.postRerunLinkUpdateSingle(courseId, 'https://test.com', 'block-1')).rejects.toThrow('Network Error');
+ await expect(api.postRerunLinkUpdateSingle(courseId, 'https://test.com', 'block-1')).rejects.toThrow(
+ 'Network Error',
+ );
});
it('should handle server errors', async () => {
@@ -245,9 +247,15 @@ describe('Course Optimizer API', () => {
const courseId = 'test-course-123';
expect(api.postLinkCheckCourseApiUrl(courseId)).toMatch(/\/api\/contentstore\/v0\/link_check\/test-course-123$/);
- expect(api.getLinkCheckStatusApiUrl(courseId)).toMatch(/\/api\/contentstore\/v0\/link_check_status\/test-course-123$/);
- expect(api.postRerunLinkUpdateApiUrl(courseId)).toMatch(/\/api\/contentstore\/v0\/rerun_link_update\/test-course-123$/);
- expect(api.getRerunLinkUpdateStatusApiUrl(courseId)).toMatch(/\/api\/contentstore\/v0\/rerun_link_update_status\/test-course-123$/);
+ expect(api.getLinkCheckStatusApiUrl(courseId)).toMatch(
+ /\/api\/contentstore\/v0\/link_check_status\/test-course-123$/,
+ );
+ expect(api.postRerunLinkUpdateApiUrl(courseId)).toMatch(
+ /\/api\/contentstore\/v0\/rerun_link_update\/test-course-123$/,
+ );
+ expect(api.getRerunLinkUpdateStatusApiUrl(courseId)).toMatch(
+ /\/api\/contentstore\/v0\/rerun_link_update_status\/test-course-123$/,
+ );
});
});
});
diff --git a/src/optimizer-page/data/api.ts b/src/optimizer-page/data/api.ts
index e09749fa50..4114ef3984 100644
--- a/src/optimizer-page/data/api.ts
+++ b/src/optimizer-page/data/api.ts
@@ -31,12 +31,16 @@ export interface RerunLinkUpdateStatusApiResponseBody {
}
const getApiBaseUrl = () => getConfig().STUDIO_BASE_URL;
-export const postLinkCheckCourseApiUrl = (courseId) => new URL(`api/contentstore/v0/link_check/${courseId}`, getApiBaseUrl()).href;
-export const getLinkCheckStatusApiUrl = (courseId) => new URL(`api/contentstore/v0/link_check_status/${courseId}`, getApiBaseUrl()).href;
-export const postRerunLinkUpdateApiUrl = (courseId) => new URL(`api/contentstore/v0/rerun_link_update/${courseId}`, getApiBaseUrl()).href;
-export const getRerunLinkUpdateStatusApiUrl = (courseId) => new URL(`api/contentstore/v0/rerun_link_update_status/${courseId}`, getApiBaseUrl()).href;
+export const postLinkCheckCourseApiUrl = (courseId) =>
+ new URL(`api/contentstore/v0/link_check/${courseId}`, getApiBaseUrl()).href;
+export const getLinkCheckStatusApiUrl = (courseId) =>
+ new URL(`api/contentstore/v0/link_check_status/${courseId}`, getApiBaseUrl()).href;
+export const postRerunLinkUpdateApiUrl = (courseId) =>
+ new URL(`api/contentstore/v0/rerun_link_update/${courseId}`, getApiBaseUrl()).href;
+export const getRerunLinkUpdateStatusApiUrl = (courseId) =>
+ new URL(`api/contentstore/v0/rerun_link_update_status/${courseId}`, getApiBaseUrl()).href;
-export async function postLinkCheck(courseId: string): Promise<{ linkCheckStatus: LinkCheckStatusTypes }> {
+export async function postLinkCheck(courseId: string): Promise<{ linkCheckStatus: LinkCheckStatusTypes; }> {
const { data } = await getAuthenticatedHttpClient()
.post(postLinkCheckCourseApiUrl(courseId));
return camelCaseObject(data);
@@ -56,7 +60,12 @@ export async function postRerunLinkUpdateAll(courseId: string): Promise {
+export async function postRerunLinkUpdateSingle(
+ courseId: string,
+ linkUrl: string,
+ blockId: string,
+ contentType: string = 'course_updates',
+): Promise {
const { data } = await getAuthenticatedHttpClient()
.post(postRerunLinkUpdateApiUrl(courseId), {
action: 'single',
diff --git a/src/optimizer-page/data/slice.test.ts b/src/optimizer-page/data/slice.test.ts
index 78bbdce497..7a710c5df0 100644
--- a/src/optimizer-page/data/slice.test.ts
+++ b/src/optimizer-page/data/slice.test.ts
@@ -25,9 +25,16 @@ import {
} from './slice';
describe('courseOptimizer slice', () => {
- let store: EnhancedStore;
- }>, StoreEnhancer]>>;
+ let store: EnhancedStore<
+ CourseOptimizerState,
+ UnknownAction,
+ Tuple<[
+ StoreEnhancer<{
+ dispatch: ThunkDispatch;
+ }>,
+ StoreEnhancer,
+ ]>
+ >;
beforeEach(() => {
store = configureStore({ reducer });
diff --git a/src/optimizer-page/data/slice.ts b/src/optimizer-page/data/slice.ts
index dea8bf472c..f05d03b7e6 100644
--- a/src/optimizer-page/data/slice.ts
+++ b/src/optimizer-page/data/slice.ts
@@ -7,7 +7,7 @@ export interface CourseOptimizerState {
linkCheckResult: LinkCheckResult | null;
lastScannedAt: string | null;
currentStage: number | null;
- error: { msg: string | null; unitUrl: string | null };
+ error: { msg: string | null; unitUrl: string | null; };
downloadPath: string | null;
successDate: string | null;
isErrorModalOpen: boolean;
diff --git a/src/optimizer-page/data/thunks.ts b/src/optimizer-page/data/thunks.ts
index 72fb073fe8..1ecafcd9bc 100644
--- a/src/optimizer-page/data/thunks.ts
+++ b/src/optimizer-page/data/thunks.ts
@@ -110,7 +110,12 @@ export function updateAllPreviousRunLinks(courseId: string) {
};
}
-export function updateSinglePreviousRunLink(courseId: string, linkUrl: string, blockId: string, contentType: string = 'course_updates') {
+export function updateSinglePreviousRunLink(
+ courseId: string,
+ linkUrl: string,
+ blockId: string,
+ contentType: string = 'course_updates',
+) {
return async (dispatch) => {
dispatch(updateSavingStatus({ status: RequestStatus.PENDING }));
try {
diff --git a/src/optimizer-page/mocks/mockApiResponse.js b/src/optimizer-page/mocks/mockApiResponse.js
index ad0e8d99ea..3bd6d82778 100644
--- a/src/optimizer-page/mocks/mockApiResponse.js
+++ b/src/optimizer-page/mocks/mockApiResponse.js
@@ -213,7 +213,11 @@ export const mockApiResponseWithPreviousRunLinks = {
externalForbiddenLinks: [],
previousRunLinks: [
{ originalLink: 'https://example.com/old-course-run/content', isUpdated: false },
- { originalLink: 'https://example.com/old-course-run/content2', isUpdated: true, updatedLink: 'https://example.com/new-course-run/content2' },
+ {
+ originalLink: 'https://example.com/old-course-run/content2',
+ isUpdated: true,
+ updatedLink: 'https://example.com/new-course-run/content2',
+ },
],
},
],
@@ -232,7 +236,11 @@ export const mockApiResponseWithPreviousRunLinks = {
lockedLinks: [],
externalForbiddenLinks: [],
previousRunLinks: [
- { originalLink: 'https://example.com/old-course-run/update', isUpdated: true, updatedLink: 'https://example.com/new-course-run/update' },
+ {
+ originalLink: 'https://example.com/old-course-run/update',
+ isUpdated: true,
+ updatedLink: 'https://example.com/new-course-run/update',
+ },
],
},
],
diff --git a/src/optimizer-page/scan-results/BrokenLinkTable.test.tsx b/src/optimizer-page/scan-results/BrokenLinkTable.test.tsx
index aa0561bd12..884cc04439 100644
--- a/src/optimizer-page/scan-results/BrokenLinkTable.test.tsx
+++ b/src/optimizer-page/scan-results/BrokenLinkTable.test.tsx
@@ -1,6 +1,9 @@
import React from 'react';
import {
- render, screen, fireEvent, waitFor,
+ render,
+ screen,
+ fireEvent,
+ waitFor,
} from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { AppProvider } from '@edx/frontend-platform/react';
@@ -60,7 +63,10 @@ interface BrokenLinkTableWrapperProps {
}
const BrokenLinkTableWrapper: React.FC = ({
- unit, onUpdateLink, filters = { brokenLinks: true, lockedLinks: false, externalForbiddenLinks: false }, ...props
+ unit,
+ onUpdateLink,
+ filters = { brokenLinks: true, lockedLinks: false, externalForbiddenLinks: false },
+ ...props
}) => (
@@ -74,11 +80,12 @@ const BrokenLinkTableWrapper: React.FC = ({
);
-const intlWrapper = (ui: React.ReactElement) => render(
-
- {ui}
- ,
-);
+const intlWrapper = (ui: React.ReactElement) =>
+ render(
+
+ {ui}
+ ,
+ );
describe('BrokenLinkTable', () => {
beforeEach(() => {
@@ -216,7 +223,9 @@ describe('BrokenLinkTable', () => {
},
]);
- render( );
+ render(
+ ,
+ );
const updateButton = findUpdateButton();
fireEvent.click(updateButton);
@@ -244,7 +253,14 @@ describe('BrokenLinkTable', () => {
},
]);
- render( );
+ render(
+ ,
+ );
const updateButton = findUpdateButton();
fireEvent.click(updateButton);
@@ -272,7 +288,9 @@ describe('BrokenLinkTable', () => {
},
]);
- render( );
+ render(
+ ,
+ );
const updateButton = findUpdateButton();
fireEvent.click(updateButton);
@@ -289,9 +307,10 @@ describe('BrokenLinkTable', () => {
describe('Loading States', () => {
it('should show loading state during update', async () => {
const mockUpdateHandler = jest.fn().mockImplementation(
- () => new Promise(resolve => {
- setTimeout(() => resolve(true), 100);
- }),
+ () =>
+ new Promise(resolve => {
+ setTimeout(() => resolve(true), 100);
+ }),
);
const unitWithPreviousRunLinks = createMockUnit([
{
@@ -305,7 +324,9 @@ describe('BrokenLinkTable', () => {
},
]);
- render( );
+ render(
+ ,
+ );
const updateButton = findUpdateButton();
fireEvent.click(updateButton);
@@ -346,7 +367,8 @@ describe('BrokenLinkTable', () => {
render( );
- expect(screen.getByText('https://example.com/path with spaces/file.pdf?param=value&other=123')).toBeInTheDocument();
+ expect(screen.getByText('https://example.com/path with spaces/file.pdf?param=value&other=123'))
+ .toBeInTheDocument();
});
it('should handle very long URLs', () => {
diff --git a/src/optimizer-page/scan-results/BrokenLinkTable.tsx b/src/optimizer-page/scan-results/BrokenLinkTable.tsx
index 3a463b81ad..70c967a988 100644
--- a/src/optimizer-page/scan-results/BrokenLinkTable.tsx
+++ b/src/optimizer-page/scan-results/BrokenLinkTable.tsx
@@ -1,5 +1,8 @@
import {
- Card, Icon, DataTable, StatefulButton,
+ Card,
+ Icon,
+ DataTable,
+ StatefulButton,
} from '@openedx/paragon';
import {
SpinnerSimple,
@@ -15,10 +18,13 @@ import CustomIcon from './CustomIcon';
import lockedIcon from './lockedIcon';
import ManualIcon from './manualIcon';
import {
- STATEFUL_BUTTON_STATES, BROKEN, LOCKED, MANUAL,
+ STATEFUL_BUTTON_STATES,
+ BROKEN,
+ LOCKED,
+ MANUAL,
} from '../../constants';
-const BrokenLinkHref: FC<{ href: string }> = ({ href }) => {
+const BrokenLinkHref: FC<{ href: string; }> = ({ href }) => {
const handleClick = (event: React.MouseEvent) => {
event.preventDefault();
window.open(href, '_blank');
@@ -33,7 +39,7 @@ const BrokenLinkHref: FC<{ href: string }> = ({ href }) => {
);
};
-const GoToBlock: FC<{ block: { url: string, displayName?: string } }> = ({ block }) => {
+const GoToBlock: FC<{ block: { url: string; displayName?: string; }; }> = ({ block }) => {
const handleClick = (event: React.MouseEvent) => {
event.preventDefault();
window.open(block.url, '_blank');
@@ -67,15 +73,15 @@ const iconsMap = {
};
const LinksCol: FC<{
- block: { url: string, displayName: string, id?: string },
- href: string,
- linkType?: string,
- showIcon?: boolean,
- showUpdateButton?: boolean,
- isUpdated?: boolean,
- onUpdate?: (link: string, blockId: string, sectionId?: string) => void,
- sectionId?: string,
- originalLink?: string,
+ block: { url: string; displayName: string; id?: string; };
+ href: string;
+ linkType?: string;
+ showIcon?: boolean;
+ showUpdateButton?: boolean;
+ isUpdated?: boolean;
+ onUpdate?: (link: string, blockId: string, sectionId?: string) => void;
+ sectionId?: string;
+ originalLink?: string;
updatedLinkMap?: Record;
updatedLinkInProgress?: Record;
}> = ({
@@ -120,30 +126,30 @@ const LinksCol: FC<{
/>
)}
{showUpdateButton && (
- isUpdated ? (
-
- {intl.formatMessage(messages.updated)}
-
-
- ) : (
- }}
- state={isUpdating ? STATEFUL_BUTTON_STATES.pending : STATEFUL_BUTTON_STATES.default}
- onClick={handleUpdate}
- disabled={isUpdating}
- disabledStates={['pending']}
- variant="outline-primary"
- size="sm"
- data-testid={`update-link-${uid}`}
- />
- )
+ isUpdated ?
+ (
+
+ {intl.formatMessage(messages.updated)}
+
+
+ ) :
+ (
+ }}
+ state={isUpdating ? STATEFUL_BUTTON_STATES.pending : STATEFUL_BUTTON_STATES.default}
+ onClick={handleUpdate}
+ disabled={isUpdating}
+ disabledStates={['pending']}
+ variant="outline-primary"
+ size="sm"
+ data-testid={`update-link-${uid}`}
+ />
+ )
)}
@@ -226,7 +232,7 @@ const BrokenLinkTable: FC
= ({
if (
filters.brokenLinks
- || (!filters.brokenLinks && !filters.externalForbiddenLinks && !filters.lockedLinks)
+ || (!filters.brokenLinks && !filters.externalForbiddenLinks && !filters.lockedLinks)
) {
const blockBrokenLinks = block.brokenLinks.map((link) => ({
Links: (
@@ -242,7 +248,7 @@ const BrokenLinkTable: FC = ({
if (
filters.lockedLinks
- || (!filters.brokenLinks && !filters.externalForbiddenLinks && !filters.lockedLinks)
+ || (!filters.brokenLinks && !filters.externalForbiddenLinks && !filters.lockedLinks)
) {
const blockLockedLinks = block.lockedLinks.map((link) => ({
Links: (
@@ -259,7 +265,7 @@ const BrokenLinkTable: FC = ({
if (
filters.externalForbiddenLinks
- || (!filters.brokenLinks && !filters.externalForbiddenLinks && !filters.lockedLinks)
+ || (!filters.brokenLinks && !filters.externalForbiddenLinks && !filters.lockedLinks)
) {
const externalForbiddenLinks = block.externalForbiddenLinks.map((link) => ({
Links: (
diff --git a/src/optimizer-page/scan-results/CustomIcon.jsx b/src/optimizer-page/scan-results/CustomIcon.jsx
index 7c53d840d8..b1cd056f87 100644
--- a/src/optimizer-page/scan-results/CustomIcon.jsx
+++ b/src/optimizer-page/scan-results/CustomIcon.jsx
@@ -18,13 +18,13 @@ const CustomIcon = ({
{intl.formatMessage(message1)}
{message1 && }
{intl.formatMessage(message2)}
- )}
+ }
>
diff --git a/src/optimizer-page/scan-results/ScanResults.test.js b/src/optimizer-page/scan-results/ScanResults.test.js
index 569a37d5bb..d9b3443334 100644
--- a/src/optimizer-page/scan-results/ScanResults.test.js
+++ b/src/optimizer-page/scan-results/ScanResults.test.js
@@ -1,7 +1,11 @@
/* eslint-disable @typescript-eslint/no-shadow */
/* eslint-disable react/jsx-filename-extension */
import {
- fireEvent, render, waitFor, screen, act,
+ fireEvent,
+ render,
+ waitFor,
+ screen,
+ act,
} from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { AppProvider } from '@edx/frontend-platform/react';
@@ -172,10 +176,12 @@ jest.mock('../../data/apiHooks', () => ({
jest.mock('../data/thunks', () => ({
updateSinglePreviousRunLink: jest.fn(() => () => Promise.resolve({ status: 'Succeeded' })),
updateAllPreviousRunLinks: jest.fn(() => () => Promise.resolve({ status: 'Succeeded' })),
- fetchRerunLinkUpdateStatus: jest.fn(() => () => Promise.resolve({
- status: 'Succeeded',
- results: [{ id: 'course-update-with-prev-links', success: true }],
- })),
+ fetchRerunLinkUpdateStatus: jest.fn(() => () =>
+ Promise.resolve({
+ status: 'Succeeded',
+ results: [{ id: 'course-update-with-prev-links', success: true }],
+ })
+ ),
fetchLinkCheckStatus: jest.fn(() => () => Promise.resolve({})),
}));
@@ -414,23 +420,25 @@ describe('ScanResults', () => {
const mockOnErrorStateChange = jest.fn();
thunks.updateSinglePreviousRunLink.mockReturnValue(() => Promise.resolve({ status: 'Succeeded' }));
- thunks.fetchRerunLinkUpdateStatus.mockReturnValue(() => Promise.resolve({
- status: 'Succeeded',
- results: [
- {
- id: 'course-update-with-prev-links',
- original_url: 'https://previous.run/link1',
- success: true,
- new_url: 'https://updated.run/link1',
- },
- {
- id: 'course-update-with-prev-links',
- original_url: 'https://previous.run/link2',
- success: true,
- new_url: 'https://updated.run/link2',
- },
- ],
- }));
+ thunks.fetchRerunLinkUpdateStatus.mockReturnValue(() =>
+ Promise.resolve({
+ status: 'Succeeded',
+ results: [
+ {
+ id: 'course-update-with-prev-links',
+ original_url: 'https://previous.run/link1',
+ success: true,
+ new_url: 'https://updated.run/link1',
+ },
+ {
+ id: 'course-update-with-prev-links',
+ original_url: 'https://previous.run/link2',
+ success: true,
+ new_url: 'https://updated.run/link2',
+ },
+ ],
+ })
+ );
render( );
@@ -457,10 +465,12 @@ describe('ScanResults', () => {
// Mock failed response - the thunk should still resolve but with failed status
thunks.updateSinglePreviousRunLink.mockReturnValue(() => Promise.resolve({ status: 'Succeeded' }));
- thunks.fetchRerunLinkUpdateStatus.mockReturnValue(() => Promise.resolve({
- status: 'Succeeded',
- results: [{ id: 'course-update-with-prev-links', success: false }], // success: false indicates failure
- }));
+ thunks.fetchRerunLinkUpdateStatus.mockReturnValue(() =>
+ Promise.resolve({
+ status: 'Succeeded',
+ results: [{ id: 'course-update-with-prev-links', success: false }], // success: false indicates failure
+ })
+ );
render( );
@@ -481,23 +491,25 @@ describe('ScanResults', () => {
const mockOnErrorStateChange = jest.fn();
thunks.updateAllPreviousRunLinks.mockReturnValue(() => Promise.resolve({ status: 'Succeeded' }));
- thunks.fetchRerunLinkUpdateStatus.mockReturnValue(() => Promise.resolve({
- status: 'Succeeded',
- results: [
- {
- id: 'course-update-with-prev-links',
- original_url: 'https://previous.run/link1',
- success: true,
- new_url: 'https://updated.run/link1',
- },
- {
- id: 'course-update-with-prev-links',
- original_url: 'https://previous.run/link2',
- success: true,
- new_url: 'https://updated.run/link2',
- },
- ],
- }));
+ thunks.fetchRerunLinkUpdateStatus.mockReturnValue(() =>
+ Promise.resolve({
+ status: 'Succeeded',
+ results: [
+ {
+ id: 'course-update-with-prev-links',
+ original_url: 'https://previous.run/link1',
+ success: true,
+ new_url: 'https://updated.run/link1',
+ },
+ {
+ id: 'course-update-with-prev-links',
+ original_url: 'https://previous.run/link2',
+ success: true,
+ new_url: 'https://updated.run/link2',
+ },
+ ],
+ })
+ );
render( );
@@ -522,23 +534,25 @@ describe('ScanResults', () => {
// Mock partial failure response
thunks.updateAllPreviousRunLinks.mockReturnValue(() => Promise.resolve({ status: 'Succeeded' }));
- thunks.fetchRerunLinkUpdateStatus.mockReturnValue(() => Promise.resolve({
- status: 'Succeeded',
- results: [
- {
- id: 'course-update-with-prev-links',
- original_url: 'https://previous.run/link1',
- success: true,
- new_url: 'https://updated.run/link1',
- },
- {
- id: 'course-update-with-prev-links',
- original_url: 'https://previous.run/link2',
- success: false,
- new_url: null,
- },
- ],
- }));
+ thunks.fetchRerunLinkUpdateStatus.mockReturnValue(() =>
+ Promise.resolve({
+ status: 'Succeeded',
+ results: [
+ {
+ id: 'course-update-with-prev-links',
+ original_url: 'https://previous.run/link1',
+ success: true,
+ new_url: 'https://updated.run/link1',
+ },
+ {
+ id: 'course-update-with-prev-links',
+ original_url: 'https://previous.run/link2',
+ success: false,
+ new_url: null,
+ },
+ ],
+ })
+ );
render( );
@@ -601,24 +615,45 @@ describe('ScanResults', () => {
const bulkResults = [
{
- id: 'api-1', type: 'course_updates', original_url: 'https://previous.run/link1', success: true, new_url: 'https://updated.run/link1',
+ id: 'api-1',
+ type: 'course_updates',
+ original_url: 'https://previous.run/link1',
+ success: true,
+ new_url: 'https://updated.run/link1',
},
{
- id: 'api-2', type: 'course_updates', original_url: 'https://previous.run/link2', success: true, new_url: 'https://updated.run/link2',
+ id: 'api-2',
+ type: 'course_updates',
+ original_url: 'https://previous.run/link2',
+ success: true,
+ new_url: 'https://updated.run/link2',
},
{
- id: 'api-3', type: 'custom_pages', original_url: 'https://previous.run/link3', success: false, new_url: null,
+ id: 'api-3',
+ type: 'custom_pages',
+ original_url: 'https://previous.run/link3',
+ success: false,
+ new_url: null,
},
{
- id: 'api-4', type: 'custom_pages', original_url: 'https://previous.run/link4', success: true, new_url: 'https://updated.run/link4',
+ id: 'api-4',
+ type: 'custom_pages',
+ original_url: 'https://previous.run/link4',
+ success: true,
+ new_url: 'https://updated.run/link4',
},
{
- id: 'course-update-with-prev-links', original_url: 'https://previous.run/link1', success: true, new_url: 'https://updated.run/link1',
+ id: 'course-update-with-prev-links',
+ original_url: 'https://previous.run/link1',
+ success: true,
+ new_url: 'https://updated.run/link1',
},
];
thunks.updateAllPreviousRunLinks.mockReturnValue(() => Promise.resolve({ status: 'Succeeded' }));
- thunks.fetchRerunLinkUpdateStatus.mockReturnValue(() => Promise.resolve({ status: 'Succeeded', results: bulkResults }));
+ thunks.fetchRerunLinkUpdateStatus.mockReturnValue(() =>
+ Promise.resolve({ status: 'Succeeded', results: bulkResults })
+ );
render( );
@@ -684,15 +719,24 @@ describe('ScanResults', () => {
const bulkResults = [
{
- id: 'api-unknown', type: 'unknown_type', original_url: 'https://previous.run/unk', success: true, new_url: 'https://updated.run/unk',
+ id: 'api-unknown',
+ type: 'unknown_type',
+ original_url: 'https://previous.run/unk',
+ success: true,
+ new_url: 'https://updated.run/unk',
},
{
- id: 'course-update-with-prev-links', original_url: 'https://previous.run/link1', success: true, new_url: 'https://updated.run/link1',
+ id: 'course-update-with-prev-links',
+ original_url: 'https://previous.run/link1',
+ success: true,
+ new_url: 'https://updated.run/link1',
},
];
thunks.updateAllPreviousRunLinks.mockReturnValue(() => Promise.resolve({ status: 'Succeeded' }));
- thunks.fetchRerunLinkUpdateStatus.mockReturnValue(() => Promise.resolve({ status: 'Succeeded', results: bulkResults }));
+ thunks.fetchRerunLinkUpdateStatus.mockReturnValue(() =>
+ Promise.resolve({ status: 'Succeeded', results: bulkResults })
+ );
const { rerender } = render(
{
const mockOnErrorStateChange = jest.fn();
thunks.updateAllPreviousRunLinks.mockReturnValue(() => Promise.resolve({ status: 'Succeeded' }));
- thunks.fetchRerunLinkUpdateStatus.mockReturnValue(() => Promise.resolve({ status: 'Succeeded', results: [{ id: 'course-update-with-prev-links', success: false }] }));
+ thunks.fetchRerunLinkUpdateStatus.mockReturnValue(() =>
+ Promise.resolve({ status: 'Succeeded', results: [{ id: 'course-update-with-prev-links', success: false }] })
+ );
window.scrollTo = jest.fn();
@@ -1199,7 +1245,11 @@ describe('ScanResults', () => {
brokenLinks: [],
lockedLinks: ['https://locked2.com'],
externalForbiddenLinks: [],
- previousRunLinks: [{ originalLink: 'https://prev2.com', isUpdated: true, updatedLink: 'https://updated2.com' }],
+ previousRunLinks: [{
+ originalLink: 'https://prev2.com',
+ isUpdated: true,
+ updatedLink: 'https://updated2.com',
+ }],
},
],
},
@@ -1613,16 +1663,32 @@ describe('ScanResults', () => {
new_url: 'https://updated.run/link2-v2',
},
{
- id: 'api-1', type: 'course_updates', original_url: 'https://previous.run/link1', success: true, new_url: 'https://updated.run/link1',
+ id: 'api-1',
+ type: 'course_updates',
+ original_url: 'https://previous.run/link1',
+ success: true,
+ new_url: 'https://updated.run/link1',
},
{
- id: 'api-2', type: 'custom_pages', original_url: 'https://previous.run/link3', success: false, new_url: null,
+ id: 'api-2',
+ type: 'custom_pages',
+ original_url: 'https://previous.run/link3',
+ success: false,
+ new_url: null,
},
{
- id: 'api-3', type: 'custom_pages', original_url: 'https://previous.run/link4', success: false, new_url: null,
+ id: 'api-3',
+ type: 'custom_pages',
+ original_url: 'https://previous.run/link4',
+ success: false,
+ new_url: null,
},
{
- id: 'api-4', type: 'course_updates', original_url: 'https://previous.run/link5', success: false, new_url: null,
+ id: 'api-4',
+ type: 'course_updates',
+ original_url: 'https://previous.run/link5',
+ success: false,
+ new_url: null,
},
],
};
@@ -1651,12 +1717,14 @@ describe('ScanResults', () => {
useWaffleFlags.mockReturnValue({ enableCourseOptimizerCheckPrevRunLinks: true });
thunks.updateSinglePreviousRunLink.mockReturnValue(() => Promise.resolve({ status: 'Succeeded' }));
- thunks.fetchRerunLinkUpdateStatus.mockReturnValue(() => Promise.resolve({
- status: 'Succeeded',
- results: [
- { id: 'course-update-with-prev-links', success: false },
- ],
- }));
+ thunks.fetchRerunLinkUpdateStatus.mockReturnValue(() =>
+ Promise.resolve({
+ status: 'Succeeded',
+ results: [
+ { id: 'course-update-with-prev-links', success: false },
+ ],
+ })
+ );
window.scrollTo = jest.fn();
@@ -1750,7 +1818,9 @@ describe('ScanResults', () => {
const mockOnErrorStateChange = jest.fn();
useWaffleFlags.mockReturnValue({ enableCourseOptimizerCheckPrevRunLinks: true });
- thunks.updateAllPreviousRunLinks.mockReturnValue(() => { throw new Error('Sync error'); });
+ thunks.updateAllPreviousRunLinks.mockReturnValue(() => {
+ throw new Error('Sync error');
+ });
window.scrollTo = jest.fn();
render(
diff --git a/src/optimizer-page/scan-results/ScanResults.tsx b/src/optimizer-page/scan-results/ScanResults.tsx
index 068019d86c..4692f368e1 100644
--- a/src/optimizer-page/scan-results/ScanResults.tsx
+++ b/src/optimizer-page/scan-results/ScanResults.tsx
@@ -28,7 +28,9 @@ import { countBrokenLinks, isDataEmpty } from '../utils';
import FilterModal from './filterModal';
import { useWaffleFlags } from '../../data/apiHooks';
import {
- updateAllPreviousRunLinks, updateSinglePreviousRunLink, fetchRerunLinkUpdateStatus,
+ updateAllPreviousRunLinks,
+ updateSinglePreviousRunLink,
+ fetchRerunLinkUpdateStatus,
} from '../data/thunks';
import { STATEFUL_BUTTON_STATES } from '../../constants';
import { RERUN_LINK_UPDATE_IN_PROGRESS_STATUSES } from '../data/constants';
@@ -42,7 +44,11 @@ interface Props {
}
const ScanResults: FC = ({
- data, courseId, onErrorStateChange, rerunLinkUpdateInProgress, rerunLinkUpdateResult,
+ data,
+ courseId,
+ onErrorStateChange,
+ rerunLinkUpdateInProgress,
+ rerunLinkUpdateResult,
}) => {
const intl = useIntl();
const waffleFlags = useWaffleFlags();
@@ -72,10 +78,12 @@ const ScanResults: FC = ({
sectionId: string,
messageKey: keyof typeof messages,
) => {
- const itemsWithLinks = items.filter(item => (item.brokenLinks && item.brokenLinks.length > 0)
+ const itemsWithLinks = items.filter(item =>
+ (item.brokenLinks && item.brokenLinks.length > 0)
|| (item.lockedLinks && item.lockedLinks.length > 0)
|| (item.externalForbiddenLinks && item.externalForbiddenLinks.length > 0)
- || (item.previousRunLinks && item.previousRunLinks.length > 0));
+ || (item.previousRunLinks && item.previousRunLinks.length > 0)
+ );
if (itemsWithLinks.length === 0) { return null; }
@@ -144,10 +152,14 @@ const ScanResults: FC = ({
// Calculate if there are any previous run links across all sections
const hasPreviousRunLinks = useMemo(
- () => allSections.some(section => (
- section.subsections.some(subsection => subsection.units.some(unit => (
- unit.blocks.some(block => block.previousRunLinks && block.previousRunLinks.length > 0)
- ))))),
+ () =>
+ allSections.some(section => (
+ section.subsections.some(subsection =>
+ subsection.units.some(unit => (
+ unit.blocks.some(block => block.previousRunLinks && block.previousRunLinks.length > 0)
+ ))
+ )
+ )),
[allSections],
);
@@ -175,7 +187,10 @@ const ScanResults: FC = ({
const activeFilters = Object.keys(filters).filter(key => filters[key]);
const [filterBy, {
- add, remove, set, clear,
+ add,
+ remove,
+ set,
+ clear,
}] = useCheckboxSetValues(activeFilters);
useEffect(() => {
@@ -207,9 +222,13 @@ const ScanResults: FC = ({
const addBlocksWithPrevLinks = (sectionId: string) => {
const section = allSections.find(s => s.id === sectionId);
if (!section) { return; }
- section.subsections.forEach(sub => sub.units.forEach(unit => unit.blocks.forEach(b => {
- if (b.previousRunLinks?.length) { blocksWithResults.add(b.id); }
- })));
+ section.subsections.forEach(sub =>
+ sub.units.forEach(unit =>
+ unit.blocks.forEach(b => {
+ if (b.previousRunLinks?.length) { blocksWithResults.add(b.id); }
+ })
+ )
+ );
};
if (Array.isArray(response.results)) {
@@ -414,10 +433,11 @@ const ScanResults: FC = ({
if (
rerunLinkUpdateResult
&& (rerunLinkUpdateResult.status === 'Succeeded'
- || (rerunLinkUpdateResult.results && rerunLinkUpdateResult.results.length > 0))
+ || (rerunLinkUpdateResult.results && rerunLinkUpdateResult.results.length > 0))
) {
const allResultIds = rerunLinkUpdateResult.results?.map(r => r.id).sort().join(',') || '';
- const responseId = `${rerunLinkUpdateResult.status}-${rerunLinkUpdateResult.results?.length}-${allResultIds}-${isUpdateAllInProgress}`;
+ const responseId =
+ `${rerunLinkUpdateResult.status}-${rerunLinkUpdateResult.results?.length}-${allResultIds}-${isUpdateAllInProgress}`;
if (processedResponseIds.has(responseId)) {
return;
@@ -446,7 +466,8 @@ const ScanResults: FC = ({
}
}
}
- }, [rerunLinkUpdateResult,
+ }, [
+ rerunLinkUpdateResult,
rerunLinkUpdateInProgress,
isUpdateAllInProgress,
intl,
@@ -509,7 +530,8 @@ const ScanResults: FC = ({
// eslint-disable-next-line @typescript-eslint/no-floating-promises
handleUpdateCompletion();
- }, [rerunLinkUpdateInProgress,
+ }, [
+ rerunLinkUpdateInProgress,
isUpdateAllInProgress,
dispatch,
courseId,
@@ -552,7 +574,7 @@ const ScanResults: FC = ({
if (allLinksUpdatedInAPI) { return true; }
- const allPreviousRunLinks: { linkId: string; isUpdatedInAPI: boolean }[] = [];
+ const allPreviousRunLinks: { linkId: string; isUpdatedInAPI: boolean; }[] = [];
allSections.forEach(section => {
section.subsections.forEach(subsection => {
subsection.units.forEach(unit => {
@@ -573,11 +595,14 @@ const ScanResults: FC = ({
if (allPreviousRunLinks.length === 0) { return false; }
- const allUpdated = allPreviousRunLinks.every(({ linkId, isUpdatedInAPI }) => isUpdatedInAPI
- || updatedLinkIds.includes(linkId));
+ const allUpdated = allPreviousRunLinks.every(({ linkId, isUpdatedInAPI }) =>
+ isUpdatedInAPI
+ || updatedLinkIds.includes(linkId)
+ );
return allUpdated;
- }, [allSections,
+ }, [
+ allSections,
hasPreviousRunLinks,
updatedLinkIds,
updateAllTrigger,
@@ -619,8 +644,8 @@ const ScanResults: FC = ({
exactMatch = updateStatusResponse.results.find(
(result: any) => {
const matches = result.id === blockId
- && result.original_url === link
- && result.success === true;
+ && result.original_url === link
+ && result.success === true;
return matches;
},
@@ -667,8 +692,8 @@ const ScanResults: FC = ({
(result: any) => {
if (hasOriginalUrlField) {
return result.id === blockId
- && result.original_url === link
- && result.success === false;
+ && result.original_url === link
+ && result.success === false;
}
return result.id === blockId && result.success === false;
},
@@ -818,26 +843,29 @@ const ScanResults: FC = ({
const shouldSectionRender = (sectionIndex: number): boolean => {
const section = allSections[sectionIndex];
const hasVisibleUnit = section.subsections.some(
- (subsection) => subsection.units.some((unit) => unit.blocks.some((block) => {
- const hasBroken = block.brokenLinks?.length > 0;
- const hasLocked = block.lockedLinks?.length > 0;
- const hasExternal = block.externalForbiddenLinks?.length > 0;
+ (subsection) =>
+ subsection.units.some((unit) =>
+ unit.blocks.some((block) => {
+ const hasBroken = block.brokenLinks?.length > 0;
+ const hasLocked = block.lockedLinks?.length > 0;
+ const hasExternal = block.externalForbiddenLinks?.length > 0;
- const noFilters = !filters.brokenLinks
- && !filters.lockedLinks
- && !filters.externalForbiddenLinks;
+ const noFilters = !filters.brokenLinks
+ && !filters.lockedLinks
+ && !filters.externalForbiddenLinks;
- const showBroken = filters.brokenLinks && hasBroken;
- const showLocked = filters.lockedLinks && hasLocked;
- const showExternal = filters.externalForbiddenLinks && hasExternal;
+ const showBroken = filters.brokenLinks && hasBroken;
+ const showLocked = filters.lockedLinks && hasLocked;
+ const showExternal = filters.externalForbiddenLinks && hasExternal;
- return (
- showBroken
+ return (
+ showBroken
|| showLocked
|| showExternal
|| (noFilters && (hasBroken || hasLocked || hasExternal))
- );
- })),
+ );
+ })
+ ),
);
return hasVisibleUnit;
};
@@ -885,8 +913,8 @@ const ScanResults: FC = ({
= ({
/>
{activeFilters.length > 0 &&
}
{activeFilters.length > 0 && (
-
-
- {activeFilters.map(filter => (
- {
- remove(filter);
- const updatedFilters = { ...filters, [filter]: false };
- setFilters(updatedFilters);
- }}
- >
- {(() => {
- const foundOption = filterOptions.filter(option => option.value === filter)[0];
- return foundOption ? foundOption.name : filter;
- })()}
-
- ))}
-
- {
- clear();
- setFilters(initialFilters);
- }}
- >
- {intl.formatMessage(messages.clearFilters)}
-
-
+
+
+ {activeFilters.map(filter => (
+ {
+ remove(filter);
+ const updatedFilters = { ...filters, [filter]: false };
+ setFilters(updatedFilters);
+ }}
+ >
+ {(() => {
+ const foundOption = filterOptions.filter(option => option.value === filter)[0];
+ return foundOption ? foundOption.name : filter;
+ })()}
+
+ ))}
+
+ {
+ clear();
+ setFilters(initialFilters);
+ }}
+ >
+ {intl.formatMessage(messages.clearFilters)}
+
+
)}
{(() => {
@@ -958,14 +986,18 @@ const ScanResults: FC = ({
index={index}
handleToggle={handleToggle}
isOpen={openStates[index]}
- hasPrevAndIsOpen={index > 0 ? (() => {
- const prevVisibleIndex = findPreviousVisibleSection(index);
- return prevVisibleIndex >= 0 && openStates[prevVisibleIndex];
- })() : true}
- hasNextAndIsOpen={index < allSections.length - 1 ? (() => {
- const nextVisibleIndex = findNextVisibleSection(index);
- return nextVisibleIndex >= 1 && openStates[nextVisibleIndex];
- })() : true}
+ hasPrevAndIsOpen={index > 0 ?
+ (() => {
+ const prevVisibleIndex = findPreviousVisibleSection(index);
+ return prevVisibleIndex >= 0 && openStates[prevVisibleIndex];
+ })() :
+ true}
+ hasNextAndIsOpen={index < allSections.length - 1 ?
+ (() => {
+ const nextVisibleIndex = findNextVisibleSection(index);
+ return nextVisibleIndex >= 1 && openStates[nextVisibleIndex];
+ })() :
+ true}
key={section.id}
title={section.displayName}
brokenNumber={brokenLinksCounts[index]}
@@ -991,9 +1023,9 @@ const ScanResults: FC = ({
&& !filters.externalForbiddenLinks;
return showBroken
- || showLocked
- || showExternal
- || (noFilters && (hasBroken || hasLocked || hasExternal));
+ || showLocked
+ || showExternal
+ || (noFilters && (hasBroken || hasLocked || hasExternal));
});
if (hasVisibleBlock) {
@@ -1017,107 +1049,107 @@ const ScanResults: FC = ({
&& allSections
&& allSections.length > 0
&& hasPreviousRunLinks && (() => {
- // Filter out sections/subsections/units that have no previous run links
- const filteredSections = allSections.map((section) => {
- // Filter subsections
- const filteredSubsections = section.subsections.map(subsection => {
- // Filter units
- const filteredUnits = subsection.units.filter(unit => unit.blocks.some(block => {
- const hasPreviousLinks = block.previousRunLinks?.length > 0;
- return hasPreviousLinks;
- }));
+ // Filter out sections/subsections/units that have no previous run links
+ const filteredSections = allSections.map((section) => {
+ // Filter subsections
+ const filteredSubsections = section.subsections.map(subsection => {
+ // Filter units
+ const filteredUnits = subsection.units.filter(unit =>
+ unit.blocks.some(block => {
+ const hasPreviousLinks = block.previousRunLinks?.length > 0;
+ return hasPreviousLinks;
+ })
+ );
+ return {
+ ...subsection,
+ units: filteredUnits,
+ };
+ }).filter(subsection => subsection.units.length > 0);
return {
- ...subsection,
- units: filteredUnits,
+ ...section,
+ subsections: filteredSubsections,
};
- }).filter(subsection => subsection.units.length > 0);
- return {
- ...section,
- subsections: filteredSubsections,
- };
- }).filter(section => section.subsections.length > 0);
-
- if (filteredSections.length === 0) {
- return null;
- }
+ }).filter(section => section.subsections.length > 0);
- return (
-
-
-
- {intl.formatMessage(messages.linkToPrevCourseRun)}
- ,
- }}
- state={
- Object.keys(updatingLinkIds).length > 0
- ? STATEFUL_BUTTON_STATES.disable
- : getUpdateAllButtonState()
- }
- onClick={handleUpdateAllCourseLinks}
- disabled={areAllLinksUpdated}
- disabledStates={['disable', 'pending']}
- variant="primary"
- data-testid="update-all-course"
- />
-
+ if (filteredSections.length === 0) {
+ return null;
+ }
+
+ return (
+
+
+
+ {intl.formatMessage(messages.linkToPrevCourseRun)}
+ ,
+ }}
+ state={Object.keys(updatingLinkIds).length > 0
+ ? STATEFUL_BUTTON_STATES.disable
+ : getUpdateAllButtonState()}
+ onClick={handleUpdateAllCourseLinks}
+ disabled={areAllLinksUpdated}
+ disabledStates={['disable', 'pending']}
+ variant="primary"
+ data-testid="update-all-course"
+ />
+
+
+ {filteredSections.map((section, index) => (
+
0 ? prevRunOpenStates[index - 1] : true}
+ hasNextAndIsOpen={index < filteredSections.length - 1 ? prevRunOpenStates[index + 1] : true}
+ key={section.id}
+ title={section.displayName}
+ previousRunLinksCount={previousRunLinksCounts[section.id] || 0}
+ isPreviousRunLinks
+ className="section-collapsible-header"
+ >
+ {section.subsections.map((subsection) => (
+ <>
+ {subsection.units.map((unit) => (
+
+
+
+ ))}
+ >
+ ))}
+
+ ))}
- {filteredSections.map((section, index) => (
-
0 ? prevRunOpenStates[index - 1] : true}
- hasNextAndIsOpen={index < filteredSections.length - 1 ? prevRunOpenStates[index + 1] : true}
- key={section.id}
- title={section.displayName}
- previousRunLinksCount={previousRunLinksCounts[section.id] || 0}
- isPreviousRunLinks
- className="section-collapsible-header"
- >
- {section.subsections.map((subsection) => (
- <>
- {subsection.units.map((unit) => (
-
-
-
- ))}
- >
- ))}
-
- ))}
-
- );
- })()}
+ );
+ })()}
{waffleFlags.enableCourseOptimizerCheckPrevRunLinks && !hasPreviousRunLinks && (
-
-
-
- {intl.formatMessage(messages.linkToPrevCourseRun)}
-
-
-
-
{intl.formatMessage(messages.noResultsFound)}
+
+
+
+ {intl.formatMessage(messages.linkToPrevCourseRun)}
+
+
+
+
{intl.formatMessage(messages.noResultsFound)}
+
-
)}
>
);
diff --git a/src/optimizer-page/scan-results/SectionCollapsible.test.tsx b/src/optimizer-page/scan-results/SectionCollapsible.test.tsx
index e0cbf9296a..8ff8895ba9 100644
--- a/src/optimizer-page/scan-results/SectionCollapsible.test.tsx
+++ b/src/optimizer-page/scan-results/SectionCollapsible.test.tsx
@@ -2,11 +2,12 @@ import { render, screen, fireEvent } from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import SectionCollapsible from './SectionCollapsible';
-const intlWrapper = (ui: React.ReactElement) => render(
-
- {ui}
- ,
-);
+const intlWrapper = (ui: React.ReactElement) =>
+ render(
+
+ {ui}
+ ,
+ );
describe('SectionCollapsible', () => {
const defaultProps = {
diff --git a/src/optimizer-page/scan-results/SectionCollapsible.tsx b/src/optimizer-page/scan-results/SectionCollapsible.tsx
index a28c033ff3..8ffc536371 100644
--- a/src/optimizer-page/scan-results/SectionCollapsible.tsx
+++ b/src/optimizer-page/scan-results/SectionCollapsible.tsx
@@ -44,7 +44,9 @@ const SectionCollapsible: FC
= ({
isPreviousRunLinks = false,
className,
}) => {
- const styling = `card-lg open-section-rounded ${hasPrevAndIsOpen ? 'closed-section-rounded-top' : ''} ${hasNextAndIsOpen ? 'closed-section-rounded-bottom' : ''}`;
+ const styling = `card-lg open-section-rounded ${hasPrevAndIsOpen ? 'closed-section-rounded-top' : ''} ${
+ hasNextAndIsOpen ? 'closed-section-rounded-bottom' : ''
+ }`;
const collapsibleTitle = (
@@ -52,26 +54,28 @@ const SectionCollapsible: FC
= ({
{title}
- {isPreviousRunLinks ? (
-
-
{previousRunLinksCount > 0 ? previousRunLinksCount : '-'}
-
- ) : (
- <>
+ {isPreviousRunLinks ?
+ (
-
-
{brokenNumber}
+
{previousRunLinksCount > 0 ? previousRunLinksCount : '-'}
-
-
- >
- )}
+ ) :
+ (
+ <>
+
+
+
+ >
+ )}
);
@@ -81,11 +85,11 @@ const SectionCollapsible: FC = ({
{collapsibleTitle}
- )}
+ }
iconWhenClosed=""
iconWhenOpen=""
open={isOpen}
diff --git a/src/optimizer-page/scan-results/filterModal.jsx b/src/optimizer-page/scan-results/filterModal.jsx
index 0a68ac80a6..ae30d19761 100644
--- a/src/optimizer-page/scan-results/filterModal.jsx
+++ b/src/optimizer-page/scan-results/filterModal.jsx
@@ -53,9 +53,30 @@ const FilterModal = ({
{name}
- { value === 'brokenLinks' && }
- { value === 'externalForbiddenLinks' && }
- { value === 'lockedLinks' && }
+ {value === 'brokenLinks' && (
+
+ )}
+ {value === 'externalForbiddenLinks' && (
+
+ )}
+ {value === 'lockedLinks' && (
+
+ )}
))}
diff --git a/src/optimizer-page/scan-results/manualIcon.tsx b/src/optimizer-page/scan-results/manualIcon.tsx
index 673139d378..68132485b7 100644
--- a/src/optimizer-page/scan-results/manualIcon.tsx
+++ b/src/optimizer-page/scan-results/manualIcon.tsx
@@ -8,7 +8,7 @@ const ManualIcon: React.FC> = (props) => (
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
- {...props} // This allows passing additional props like className, style, etc.
+ {...props /* This allows passing additional props like className, style, etc.*/}
>
{
// Check sections
if (data.sections && data.sections.length > 0) {
const hasAnyLinks = data.sections.some(
- (section) => section.subsections.some(
- (subsection) => subsection.units.some(
- (unit) => unit.blocks.some(
- (block) => {
- const hasBrokenLinks = block.brokenLinks && block.brokenLinks.length > 0;
- const hasLockedLinks = block.lockedLinks && block.lockedLinks.length > 0;
- const hasExternalForbiddenLinks = block.externalForbiddenLinks
+ (section) =>
+ section.subsections.some(
+ (subsection) =>
+ subsection.units.some(
+ (unit) =>
+ unit.blocks.some(
+ (block) => {
+ const hasBrokenLinks = block.brokenLinks && block.brokenLinks.length > 0;
+ const hasLockedLinks = block.lockedLinks && block.lockedLinks.length > 0;
+ const hasExternalForbiddenLinks = block.externalForbiddenLinks
&& block.externalForbiddenLinks.length > 0;
- const hasPreviousRunLinks = block.previousRunLinks
+ const hasPreviousRunLinks = block.previousRunLinks
&& block.previousRunLinks.length > 0;
- return (
- hasBrokenLinks
+ return (
+ hasBrokenLinks
|| hasLockedLinks
|| hasExternalForbiddenLinks
|| hasPreviousRunLinks
- );
- },
- ),
+ );
+ },
+ ),
+ ),
),
- ),
);
if (hasAnyLinks) {
@@ -76,10 +79,12 @@ export const isDataEmpty = (data: LinkCheckResult | null): boolean => {
// Check course updates
if (data.courseUpdates && data.courseUpdates.length > 0) {
- const hasAnyLinks = data.courseUpdates.some((update) => (update.brokenLinks && update.brokenLinks.length > 0)
+ const hasAnyLinks = data.courseUpdates.some((update) =>
+ (update.brokenLinks && update.brokenLinks.length > 0)
|| (update.lockedLinks && update.lockedLinks.length > 0)
|| (update.externalForbiddenLinks && update.externalForbiddenLinks.length > 0)
- || (update.previousRunLinks && update.previousRunLinks.length > 0));
+ || (update.previousRunLinks && update.previousRunLinks.length > 0)
+ );
if (hasAnyLinks) {
return false;
}
@@ -87,10 +92,12 @@ export const isDataEmpty = (data: LinkCheckResult | null): boolean => {
// Check custom pages
if (data.customPages && data.customPages.length > 0) {
- const hasAnyLinks = data.customPages.some((page) => (page.brokenLinks && page.brokenLinks.length > 0)
+ const hasAnyLinks = data.customPages.some((page) =>
+ (page.brokenLinks && page.brokenLinks.length > 0)
|| (page.lockedLinks && page.lockedLinks.length > 0)
|| (page.externalForbiddenLinks && page.externalForbiddenLinks.length > 0)
- || (page.previousRunLinks && page.previousRunLinks.length > 0));
+ || (page.previousRunLinks && page.previousRunLinks.length > 0)
+ );
if (hasAnyLinks) {
return false;
}
diff --git a/src/pages-and-resources/PagesAndResources.test.tsx b/src/pages-and-resources/PagesAndResources.test.tsx
index 2b6ce340ca..7196f19db2 100644
--- a/src/pages-and-resources/PagesAndResources.test.tsx
+++ b/src/pages-and-resources/PagesAndResources.test.tsx
@@ -1,5 +1,8 @@
import {
- screen, waitFor, initializeMocks, render,
+ screen,
+ waitFor,
+ initializeMocks,
+ render,
} from '@src/testUtils';
import { getConfig, setConfig } from '@edx/frontend-platform';
@@ -23,11 +26,12 @@ const mockPlugin = (identifier) => ({
const courseId = 'course-v1:edX+TestX+Test_Course';
-const renderComponent = () => render(
-
-
- ,
-);
+const renderComponent = () =>
+ render(
+
+
+ ,
+ );
describe('PagesAndResources', () => {
beforeEach(() => {
@@ -36,7 +40,9 @@ describe('PagesAndResources', () => {
...getConfig(),
pluginSlots: {
'org.openedx.frontend.authoring.additional_course_plugin.v1': mockPlugin('additional_course_plugin'),
- 'org.openedx.frontend.authoring.additional_course_content_plugin.v1': mockPlugin('additional_course_content_plugin'),
+ 'org.openedx.frontend.authoring.additional_course_content_plugin.v1': mockPlugin(
+ 'additional_course_content_plugin',
+ ),
},
});
});
diff --git a/src/pages-and-resources/PagesAndResources.tsx b/src/pages-and-resources/PagesAndResources.tsx
index a89142b1a3..6f4d94cbc8 100644
--- a/src/pages-and-resources/PagesAndResources.tsx
+++ b/src/pages-and-resources/PagesAndResources.tsx
@@ -64,9 +64,7 @@ const PagesAndResources = () => {
}
if (courseAppsApiStatus === RequestStatus.DENIED) {
- return (
-
- );
+ return ;
}
const hasAdditionalCoursePlugin = getConfig()?.pluginSlots?.additional_course_plugin != null;
@@ -82,29 +80,55 @@ const PagesAndResources = () => {
rel="noopener noreferrer"
showLaunchIcon={false}
>
- {intl.formatMessage(messages.viewLiveButton)}
+ {intl.formatMessage(messages.viewLiveButton)}
- } />
- } />
- } />
- } />
+
+
+
+ }
+ />
+
+
+
+ }
+ />
+
+
+
+ }
+ />
+
+
+
+ }
+ />
} courseId={courseId} />
- {
- (contentPermissionsPages.length > 0 || hasAdditionalCoursePlugin)
- && (
- <>
-
-
{intl.formatMessage(messages.contentPermissions)}
-
-
} />
- >
- )
- }
+ {(contentPermissionsPages.length > 0 || hasAdditionalCoursePlugin)
+ && (
+ <>
+
+
{intl.formatMessage(messages.contentPermissions)}
+
+
} />
+ >
+ )}
);
diff --git a/src/pages-and-resources/PagesAndResourcesProvider.tsx b/src/pages-and-resources/PagesAndResourcesProvider.tsx
index ae7e2d0ef5..9184fce86d 100644
--- a/src/pages-and-resources/PagesAndResourcesProvider.tsx
+++ b/src/pages-and-resources/PagesAndResourcesProvider.tsx
@@ -8,7 +8,7 @@ export const PagesAndResourcesContext = React.createContext
{
diff --git a/src/pages-and-resources/SettingsComponent.jsx b/src/pages-and-resources/SettingsComponent.jsx
index c612565e15..44fe16b09e 100644
--- a/src/pages-and-resources/SettingsComponent.jsx
+++ b/src/pages-and-resources/SettingsComponent.jsx
@@ -16,12 +16,14 @@ const SettingsComponent = ({ url }) => {
const navigate = useNavigate();
const LazyLoadedComponent = React.useMemo(
- () => React.lazy(() =>
- import(`@openedx-plugins/course-app-${appId}/Settings`).catch((err) => { // eslint-disable-line
- // If we couldn't load this plugin, log the details to the console.
- console.trace(err); // eslint-disable-line no-console
- return { default: PluginLoadFailedError };
- })),
+ () =>
+ React.lazy(() =>
+ import(`@openedx-plugins/course-app-${appId}/Settings`).catch((err) => { // eslint-disable-line
+ // If we couldn't load this plugin, log the details to the console.
+ console.trace(err); // eslint-disable-line no-console
+ return { default: PluginLoadFailedError };
+ })
+ ),
[appId],
);
diff --git a/src/pages-and-resources/app-settings-modal/AppSettingsModal.jsx b/src/pages-and-resources/app-settings-modal/AppSettingsModal.jsx
index 1251394e1f..001b8a254c 100644
--- a/src/pages-and-resources/app-settings-modal/AppSettingsModal.jsx
+++ b/src/pages-and-resources/app-settings-modal/AppSettingsModal.jsx
@@ -12,7 +12,10 @@ import { Info } from '@openedx/paragon/icons';
import { Formik } from 'formik';
import PropTypes from 'prop-types';
import React, {
- useContext, useEffect, useRef, useState,
+ useContext,
+ useEffect,
+ useRef,
+ useState,
} from 'react';
import { useDispatch, useSelector } from 'react-redux';
import * as Yup from 'yup';
@@ -111,13 +114,11 @@ const AppSettingsModal = ({
enabled: !!appInfo?.enabled,
...initialValues,
}}
- validationSchema={
- Yup.object()
- .shape({
- enabled: Yup.boolean(),
- ...validationSchema,
- })
- }
+ validationSchema={Yup.object()
+ .shape({
+ enabled: Yup.boolean(),
+ ...validationSchema,
+ })}
onSubmit={handleFormSubmit}
enableReinitialize={enableReinitialize}
>
@@ -129,7 +130,7 @@ const AppSettingsModal = ({
onClose={onClose}
variant={modalVariant}
isMobile={isMobile}
- footer={(
+ footer={
- )}
+ }
>
{saveError && (
@@ -156,7 +157,7 @@ const AppSettingsModal = ({
onChange={(event) => formikProps.handleChange(event)}
onBlur={formikProps.handleBlur}
checked={formikProps.values.enabled}
- label={(
+ label={
{enableAppLabel}
{formikProps.values.enabled && (
@@ -165,31 +166,29 @@ const AppSettingsModal = ({
)}
- )}
- helpText={(
+ }
+ helpText={
{enableAppHelp}
{learnMoreLink}
- )}
+ }
/>
)}
{bodyChildren}
{(formikProps.values.enabled || configureBeforeEnable) && children
&& }
- {
- children && (
-
- {formikProps.values.enabled || configureBeforeEnable ? (
+ {children && (
+
+ {formikProps.values.enabled || configureBeforeEnable ?
+ (
{children(formikProps)}
- ) : (
-
- )}
-
- )
- }
+ ) :
+ }
+
+ )}
)}
diff --git a/src/pages-and-resources/data/thunks.js b/src/pages-and-resources/data/thunks.js
index 9434b329b3..9b77eb0e22 100644
--- a/src/pages-and-resources/data/thunks.js
+++ b/src/pages-and-resources/data/thunks.js
@@ -2,13 +2,15 @@ import { RequestStatus } from '../../data/constants';
import { addModels, updateModel } from '../../generic/model-store';
import {
getCourseAdvancedSettings,
- getCourseApps, updateCourseAdvancedSettings,
+ getCourseApps,
+ updateCourseAdvancedSettings,
updateCourseApp,
} from './api';
import {
fetchCourseAppsSettingsSuccess,
fetchCourseAppsSuccess,
- updateCourseAppsApiStatus, updateCourseAppsSettingsSuccess,
+ updateCourseAppsApiStatus,
+ updateCourseAppsSettingsSuccess,
updateLoadingStatus,
updateSavingStatus,
} from './slice';
@@ -35,7 +37,8 @@ export function fetchCourseApps(courseId) {
const courseApps = await getCourseApps(courseId);
courseApps.sort((firstEl, secondEl) => (
- COURSE_APPS_ORDER.indexOf(firstEl.id) - COURSE_APPS_ORDER.indexOf(secondEl.id)));
+ COURSE_APPS_ORDER.indexOf(firstEl.id) - COURSE_APPS_ORDER.indexOf(secondEl.id)
+ ));
dispatch(addModels({ modelType: 'courseApps', models: courseApps }));
dispatch(fetchCourseAppsSuccess({
diff --git a/src/pages-and-resources/discussions/DiscussionsSettings.jsx b/src/pages-and-resources/discussions/DiscussionsSettings.jsx
index 3b9ec906af..23a34b0773 100644
--- a/src/pages-and-resources/discussions/DiscussionsSettings.jsx
+++ b/src/pages-and-resources/discussions/DiscussionsSettings.jsx
@@ -1,11 +1,17 @@
import React, {
- useCallback, useContext, useEffect, useState,
+ useCallback,
+ useContext,
+ useEffect,
+ useState,
} from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
- Alert, Button, FullscreenModal, Stepper,
+ Alert,
+ Button,
+ FullscreenModal,
+ Stepper,
} from '@openedx/paragon';
import { useCourseAuthoringContext } from '@src/CourseAuthoringContext';
@@ -96,7 +102,7 @@ const DiscussionsSettings = () => {
isOpen
beforeBodyNode={ }
isOverflowVisible={false}
- footerNode={(
+ footerNode={
<>
@@ -113,19 +119,17 @@ const DiscussionsSettings = () => {
>
- )}
+ }
>
- {
- !canChangeProviders && (
-
- {intl.formatMessage(messages.noProviderSwitchAfterCourseStarted)}
-
- )
- }
+ {!canChangeProviders && (
+
+ {intl.formatMessage(messages.noProviderSwitchAfterCourseStarted)}
+
+ )}
}
+ element={
+
+
+
+ }
/>
}
+ element={
+
+
+
+ }
/>
@@ -223,7 +243,10 @@ describe('DiscussionsSettings', () => {
});
test('requires confirmation if changing provider', async () => {
- axiosMock.onGet(`${getConfig().LMS_BASE_URL}/api/courses/v1/courses/${courseId}?username=abc123`).reply(200, courseDetailResponse);
+ axiosMock.onGet(`${getConfig().LMS_BASE_URL}/api/courses/v1/courses/${courseId}?username=abc123`).reply(
+ 200,
+ courseDetailResponse,
+ );
renderComponent(`/course/${courseId}/pages-and-resources/discussion`);
// This is an important line that ensures the spinner has been removed - and thus our main
@@ -243,7 +266,10 @@ describe('DiscussionsSettings', () => {
});
test('can cancel confirmation', async () => {
- axiosMock.onGet(`${getConfig().LMS_BASE_URL}/api/courses/v1/courses/${courseId}?username=abc123`).reply(200, courseDetailResponse);
+ axiosMock.onGet(`${getConfig().LMS_BASE_URL}/api/courses/v1/courses/${courseId}?username=abc123`).reply(
+ 200,
+ courseDetailResponse,
+ );
renderComponent(`/course/${courseId}/pages-and-resources/discussion`);
// This is an important line that ensures the spinner has been removed - and thus our main
@@ -293,7 +319,9 @@ describe('DiscussionsSettings', () => {
const alert = queryByRole(container, 'alert');
expect(alert).toBeInTheDocument();
- expect(alert.textContent).toEqual(expect.stringContaining('We encountered a technical error when loading this page.'));
+ expect(alert.textContent).toEqual(
+ expect.stringContaining('We encountered a technical error when loading this page.'),
+ );
expect(alert.innerHTML).toEqual(expect.stringContaining(getConfig().SUPPORT_URL));
});
});
@@ -326,7 +354,9 @@ describe('DiscussionsSettings', () => {
expect(queryByTestId(container, 'appConfigForm')).toBeInTheDocument();
const alert = await findByRole(container, 'alert');
expect(alert).toBeInTheDocument();
- expect(alert.textContent).toEqual(expect.stringContaining('We encountered a technical error when applying changes.'));
+ expect(alert.textContent).toEqual(
+ expect.stringContaining('We encountered a technical error when applying changes.'),
+ );
expect(alert.innerHTML).toEqual(expect.stringContaining(getConfig().SUPPORT_URL));
});
});
@@ -373,7 +403,11 @@ describe('DiscussionsSettings', () => {
// Confirm route is correct
// We don't technically leave the route in this case, though the modal is hidden.
const locationDisplay = await screen.findByTestId('location-display');
- await waitFor(() => expect(locationDisplay.textContent).toEqual(`/course/${courseId}/pages-and-resources/discussion/configure/piazza`));
+ await waitFor(() =>
+ expect(locationDisplay.textContent).toEqual(
+ `/course/${courseId}/pages-and-resources/discussion/configure/piazza`,
+ )
+ );
const alert = await findByRole(container, 'alert');
expect(alert).toBeInTheDocument();
@@ -466,28 +500,34 @@ describe.each([
.reply(200, { courseId, name: 'Course Test' });
});
- test(`${piiSharingAllowed ? 'shows PII share username/email field when piiSharingAllowed is true'
- : 'hides PII share username/email field when piiSharingAllowed is false'}`, async () => {
- const user = userEvent.setup();
- renderComponent(`/course/${courseId}/pages-and-resources/discussion`);
+ test(
+ `${
+ piiSharingAllowed ?
+ 'shows PII share username/email field when piiSharingAllowed is true'
+ : 'hides PII share username/email field when piiSharingAllowed is false'
+ }`,
+ async () => {
+ const user = userEvent.setup();
+ renderComponent(`/course/${courseId}/pages-and-resources/discussion`);
- let spinner = await screen.findByRole('status');
- await waitFor(() => {
- expect(spinner).not.toBeInTheDocument();
- });
+ let spinner = await screen.findByRole('status');
+ await waitFor(() => {
+ expect(spinner).not.toBeInTheDocument();
+ });
- await user.click(screen.getByLabelText('Select Piazza'));
- await user.click(screen.getByText(messages.nextButton.defaultMessage));
+ await user.click(screen.getByLabelText('Select Piazza'));
+ await user.click(screen.getByText(messages.nextButton.defaultMessage));
- await waitFor(() => {
- spinner = screen.queryByRole('status');
- expect(spinner).not.toBeInTheDocument();
- });
+ await waitFor(() => {
+ spinner = screen.queryByRole('status');
+ expect(spinner).not.toBeInTheDocument();
+ });
- if (enablePIISharing) {
- expect(queryByTestId(container, 'piiSharingFields')).toBeInTheDocument();
- } else {
- expect(queryByTestId(container, 'piiSharingFields')).not.toBeInTheDocument();
- }
- });
+ if (enablePIISharing) {
+ expect(queryByTestId(container, 'piiSharingFields')).toBeInTheDocument();
+ } else {
+ expect(queryByTestId(container, 'piiSharingFields')).not.toBeInTheDocument();
+ }
+ },
+ );
});
diff --git a/src/pages-and-resources/discussions/app-config-form/AppConfigForm.jsx b/src/pages-and-resources/discussions/app-config-form/AppConfigForm.jsx
index 1358f997ae..b498eef689 100644
--- a/src/pages-and-resources/discussions/app-config-form/AppConfigForm.jsx
+++ b/src/pages-and-resources/discussions/app-config-form/AppConfigForm.jsx
@@ -1,5 +1,8 @@
import React, {
- useCallback, useContext, useEffect, useState,
+ useCallback,
+ useContext,
+ useEffect,
+ useState,
} from 'react';
import PropTypes from 'prop-types';
@@ -19,7 +22,10 @@ import SaveFormConnectionErrorAlert from '../../../generic/SaveFormConnectionErr
import { PagesAndResourcesContext } from '../../PagesAndResourcesProvider';
import {
DENIED,
- FAILED, LOADED, LOADING, selectApp,
+ FAILED,
+ LOADED,
+ LOADING,
+ selectApp,
} from '../data/slice';
import { fetchDiscussionSettings, saveProviderConfig } from '../data/thunks';
import OpenedXConfigForm from './apps/openedx';
@@ -40,7 +46,10 @@ const AppConfigForm = ({
const { appId: routeAppId } = useParams();
const [isLoading, setLoading] = useState(true);
const {
- activeAppId, selectedAppId, status, saveStatus,
+ activeAppId,
+ selectedAppId,
+ status,
+ saveStatus,
} = useSelector(state => state.discussions);
const [confirmationDialogVisible, setConfirmationDialogVisible] = useState(false);
@@ -64,7 +73,7 @@ const AppConfigForm = ({
// This is a callback that gets called after the form has been submitted successfully.
const handleSubmit = useCallback((values) => {
- const needsConfirmation = (activeAppId !== selectedAppId);
+ const needsConfirmation = activeAppId !== selectedAppId;
if (needsConfirmation && !confirmationDialogVisible) {
setConfirmationDialogVisible(true);
} else {
@@ -75,16 +84,12 @@ const AppConfigForm = ({
}, [activeAppId, confirmationDialogVisible, courseId, selectedAppId]);
if (!selectedAppId || status === LOADING || isLoading) {
- return (
-
- );
+ return ;
}
let alert = null;
if (saveStatus === FAILED) {
- alert = (
-
- );
+ alert = ;
}
if (saveStatus === DENIED) {
alert = ;
diff --git a/src/pages-and-resources/discussions/app-config-form/AppConfigFormSaveButton.jsx b/src/pages-and-resources/discussions/app-config-form/AppConfigFormSaveButton.jsx
index dcf28aa32b..ced3101670 100644
--- a/src/pages-and-resources/discussions/app-config-form/AppConfigFormSaveButton.jsx
+++ b/src/pages-and-resources/discussions/app-config-form/AppConfigFormSaveButton.jsx
@@ -27,9 +27,12 @@ const AppConfigFormSaveButton = ({ labelText }) => {
// https://developer.mozilla.org/en-US/docs/Web/API/Event/Event
// cancelable: (optional) a Boolean indicating whether the event can be canceled. The default is false.
// cancelable: true cancels the untrusted event and safari, chrome cancel the untrusted event by default
- formRef.current.dispatchEvent(new Event('submit', {
- cancelable: true, bubbles: true,
- }));
+ formRef.current.dispatchEvent(
+ new Event('submit', {
+ cancelable: true,
+ bubbles: true,
+ }),
+ );
}, [formRef]);
return (
diff --git a/src/pages-and-resources/discussions/app-config-form/apps/lti/LtiConfigForm.jsx b/src/pages-and-resources/discussions/app-config-form/apps/lti/LtiConfigForm.jsx
index 02bcbb2422..b0e2c37b84 100644
--- a/src/pages-and-resources/discussions/app-config-form/apps/lti/LtiConfigForm.jsx
+++ b/src/pages-and-resources/discussions/app-config-form/apps/lti/LtiConfigForm.jsx
@@ -36,7 +36,12 @@ const LtiConfigForm = ({ onSubmit, formRef }) => {
const user = getAuthenticatedUser();
const { externalLinks } = app;
const {
- handleSubmit, handleChange, handleBlur, values, touched, errors,
+ handleSubmit,
+ handleChange,
+ handleBlur,
+ values,
+ touched,
+ errors,
} = useFormik({
initialValues: ltiAppConfig,
validationSchema: Yup.object().shape({
@@ -73,11 +78,11 @@ const LtiConfigForm = ({ onSubmit, formRef }) => {
{...messages.staffOnlyConfigInfo}
values={{
providerName,
- supportEmail: supportEmails[providerName] ? (
- {supportEmails[providerName]}
- ) : (
- 'support'
- ),
+ supportEmail: supportEmails[providerName] ?
+ {supportEmails[providerName]} :
+ (
+ 'support'
+ ),
}}
/>
@@ -86,11 +91,11 @@ const LtiConfigForm = ({ onSubmit, formRef }) => {
{...messages.staffOnlyConfigGuide}
values={{
providerName,
- supportEmail: supportEmails[providerName] ? (
- {supportEmails[providerName]}
- ) : (
- 'support'
- ),
+ supportEmail: supportEmails[providerName] ?
+ {supportEmails[providerName]} :
+ (
+ 'support'
+ ),
}}
/>
@@ -147,7 +152,7 @@ const LtiConfigForm = ({ onSubmit, formRef }) => {
>
)}
- {(enablePIISharing) && (
+ {enablePIISharing && (
{intl.formatMessage(messages.piiSharing)}
diff --git a/src/pages-and-resources/discussions/app-config-form/apps/openedx/OpenedXConfigForm.jsx b/src/pages-and-resources/discussions/app-config-form/apps/openedx/OpenedXConfigForm.jsx
index f6f8454f24..ccc1cbe6a8 100644
--- a/src/pages-and-resources/discussions/app-config-form/apps/openedx/OpenedXConfigForm.jsx
+++ b/src/pages-and-resources/discussions/app-config-form/apps/openedx/OpenedXConfigForm.jsx
@@ -22,11 +22,17 @@ import OpenedXConfigFormProvider from './OpenedXConfigFormProvider';
setupYupExtensions();
const OpenedXConfigForm = ({
- onSubmit, formRef, legacy,
+ onSubmit,
+ formRef,
+ legacy,
}) => {
const intl = useIntl();
const {
- selectedAppId, enableGradedUnits, discussionTopicIds, divideDiscussionIds, postingRestrictions,
+ selectedAppId,
+ enableGradedUnits,
+ discussionTopicIds,
+ divideDiscussionIds,
+ postingRestrictions,
} = useSelector(state => state.discussions);
const appConfigObj = useModel('appConfigs', selectedAppId);
const discussionTopicsModel = useModels('discussionTopics', discussionTopicIds);
@@ -97,12 +103,20 @@ const OpenedXConfigForm = ({
onSubmit={(values) => onSubmit(values)}
>
{({
- handleSubmit, handleChange, handleBlur, values, errors, touched,
+ handleSubmit,
+ handleChange,
+ handleBlur,
+ values,
+ errors,
+ touched,
}) => {
const { discussionTopics, restrictedDates } = values;
- const discussionTopicErrors = discussionTopics.map((value, index) => checkFieldErrors(touched, errors, `discussionTopics.${index}`, 'name'));
+ const discussionTopicErrors = discussionTopics.map((value, index) =>
+ checkFieldErrors(touched, errors, `discussionTopics.${index}`, 'name')
+ );
const restrictedDatesErrors = restrictedDates.map(
- (value, index) => checkFieldErrors(touched, errors, `restrictedDates.${index}`, 'startDate')
+ (value, index) =>
+ checkFieldErrors(touched, errors, `restrictedDates.${index}`, 'startDate')
|| checkFieldErrors(touched, errors, `restrictedDates.${index}`, 'endDate')
|| checkFieldErrors(touched, errors, `restrictedDates.${index}`, 'startTime')
|| checkFieldErrors(touched, errors, `restrictedDates.${index}`, 'endTime'),
@@ -114,8 +128,7 @@ const OpenedXConfigForm = ({
discussionTopicErrors,
postingRestrictions,
restrictedDatesErrors,
- isFormInvalid:
- discussionTopicErrors.some((error) => error)
+ isFormInvalid: discussionTopicErrors.some((error) => error)
|| restrictedDatesErrors.some((error) => error),
};
diff --git a/src/pages-and-resources/discussions/app-config-form/apps/openedx/OpenedXConfigForm.test.jsx b/src/pages-and-resources/discussions/app-config-form/apps/openedx/OpenedXConfigForm.test.jsx
index c9648827ae..945952d262 100644
--- a/src/pages-and-resources/discussions/app-config-form/apps/openedx/OpenedXConfigForm.test.jsx
+++ b/src/pages-and-resources/discussions/app-config-form/apps/openedx/OpenedXConfigForm.test.jsx
@@ -157,9 +157,11 @@ describe('OpenedXConfigForm', () => {
expect(container.querySelector('#divideByCohorts')).toBeDisabled();
expect(container.querySelector('#divideCourseTopicsByCohorts')).not.toBeInTheDocument();
- divideDiscussionIds.forEach(id => expect(
- container.querySelector(`#checkbox-${id}`),
- ).not.toBeInTheDocument());
+ divideDiscussionIds.forEach(id =>
+ expect(
+ container.querySelector(`#checkbox-${id}`),
+ ).not.toBeInTheDocument()
+ );
// AnonymousPostingFields
expect(
@@ -196,9 +198,11 @@ describe('OpenedXConfigForm', () => {
expect(
container.querySelector('#divideCourseTopicsByCohorts'),
).not.toBeInTheDocument();
- divideDiscussionIds.forEach(id => expect(
- container.querySelector(`#checkbox-${id}`),
- ).not.toBeInTheDocument());
+ divideDiscussionIds.forEach(id =>
+ expect(
+ container.querySelector(`#checkbox-${id}`),
+ ).not.toBeInTheDocument()
+ );
// AnonymousPostingFields
expect(
@@ -242,10 +246,14 @@ describe('OpenedXConfigForm', () => {
const updateTopicName = async (topicId, topicName) => {
const topicCard = queryByTestId(container, topicId);
- await act(async () => { await user.click(queryByLabelText(topicCard, 'Expand')); });
+ await act(async () => {
+ await user.click(queryByLabelText(topicCard, 'Expand'));
+ });
const topicInput = topicCard.querySelector('input');
topicInput.focus();
- await act(async () => { fireEvent.change(topicInput, { target: { value: topicName } }); });
+ await act(async () => {
+ fireEvent.change(topicInput, { target: { value: topicName } });
+ });
topicInput.blur();
return topicCard;
@@ -253,12 +261,14 @@ describe('OpenedXConfigForm', () => {
const assertTopicNameRequiredValidation = (topicCard, expectExists = true) => {
const error = queryByText(topicCard, messages.discussionTopicRequired.defaultMessage);
- if (expectExists) { expect(error).toBeInTheDocument(); } else { expect(error).not.toBeInTheDocument(); }
+ if (expectExists) { expect(error).toBeInTheDocument(); }
+ else { expect(error).not.toBeInTheDocument(); }
};
const assertDuplicateTopicNameValidation = async (topicCard, expectExists = true) => {
const error = queryByText(topicCard, messages.discussionTopicNameAlreadyExist.defaultMessage);
- if (expectExists) { expect(error).toBeInTheDocument(); } else { expect(error).not.toBeInTheDocument(); }
+ if (expectExists) { expect(error).toBeInTheDocument(); }
+ else { expect(error).not.toBeInTheDocument(); }
};
const assertHasErrorValidation = (expectExists = true) => {
@@ -310,7 +320,9 @@ describe('OpenedXConfigForm', () => {
test('check duplicate error is removed on fields when name is fixed', async () => {
const duplicateTopicInput = duplicateTopicCard.querySelector('input');
duplicateTopicInput.focus();
- await act(async () => { await user.type(duplicateTopicInput, 'valid'); });
+ await act(async () => {
+ await user.type(duplicateTopicInput, 'valid');
+ });
duplicateTopicInput.blur();
await waitForElementToBeRemoved(
diff --git a/src/pages-and-resources/discussions/app-config-form/apps/shared/AppExternalLinks.jsx b/src/pages-and-resources/discussions/app-config-form/apps/shared/AppExternalLinks.jsx
index 3acbb6e48b..505ac565bd 100644
--- a/src/pages-and-resources/discussions/app-config-form/apps/shared/AppExternalLinks.jsx
+++ b/src/pages-and-resources/discussions/app-config-form/apps/shared/AppExternalLinks.jsx
@@ -2,7 +2,8 @@ import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import {
- Hyperlink, MailtoLink,
+ Hyperlink,
+ MailtoLink,
} from '@openedx/paragon';
import AppConfigFormDivider from './AppConfigFormDivider';
@@ -34,12 +35,13 @@ const AppExternalLinks = ({
showLaunchIcon={showLaunchIcon}
className={customClasses}
>
- { intl.formatMessage(messages[type], { providerName }) }
+ {intl.formatMessage(messages[type], { providerName })}
))}
>
- ) : null}
+ ) :
+ null}
{contactEmail && (
@@ -51,7 +53,7 @@ const AppExternalLinks = ({
to={contactEmail}
rel="noopener noreferrer"
>
- { contactEmail }
+ {contactEmail}
),
}}
diff --git a/src/pages-and-resources/discussions/app-config-form/apps/shared/DiscussionRestriction.jsx b/src/pages-and-resources/discussions/app-config-form/apps/shared/DiscussionRestriction.jsx
index 66691d0f1d..70b147ab16 100644
--- a/src/pages-and-resources/discussions/app-config-form/apps/shared/DiscussionRestriction.jsx
+++ b/src/pages-and-resources/discussions/app-config-form/apps/shared/DiscussionRestriction.jsx
@@ -39,19 +39,23 @@ const DiscussionRestriction = () => {
setSelectedRestrictionOption(postingRestrictions);
}, [postingRestrictions]);
- const discussionRestrictionButtons = useMemo(() => discussionRestrictionOptions.map((restriction) => (
- handleClick(restriction.value)}
- >
- {restriction.label}
-
- )), [selectedRestrictionOption]);
+ const discussionRestrictionButtons = useMemo(() =>
+ discussionRestrictionOptions.map((restriction) => (
+ handleClick(restriction.value)}
+ >
+ {restriction.label}
+
+ )), [selectedRestrictionOption]);
const selectedRestrictionMessage = useMemo(() => (
discussionRestrictionOptions.find(option => option.value === selectedRestrictionOption).message
@@ -69,8 +73,7 @@ const DiscussionRestriction = () => {
{intl.formatMessage(selectedRestrictionMessage)}
{(postingRestrictions !== discussionRestriction.ENABLED
- && selectedRestrictionOption === discussionRestriction.ENABLED
- ) && (
+ && selectedRestrictionOption === discussionRestriction.ENABLED) && (
{
const onButton = screen.queryByTestId('enabled');
- await act(async () => { fireEvent.click(onButton); });
+ await act(async () => {
+ fireEvent.click(onButton);
+ });
const eventButton = await screen.findByText(eventType);
- await act(async () => { fireEvent.click(eventButton); });
+ await act(async () => {
+ fireEvent.click(eventButton);
+ });
await waitFor(() => {
expect(container.querySelector(`[data-testid= ${selectedOption}].selected-button`)).toBeInTheDocument();
@@ -111,11 +120,15 @@ describe('Discussion Restriction', () => {
const scheduledButton = screen.queryByTestId('scheduled');
- await act(async () => { fireEvent.click(scheduledButton); });
+ await act(async () => {
+ fireEvent.click(scheduledButton);
+ });
const addDatesButton = screen.queryByText('Add restricted dates');
- await act(async () => { fireEvent.click(addDatesButton); });
+ await act(async () => {
+ fireEvent.click(addDatesButton);
+ });
await waitFor(async () => {
const startDate = screen.getByTestId('startDate');
const startTime = screen.getByTestId('startTime');
@@ -136,11 +149,15 @@ describe('Discussion Restriction', () => {
const deleteButton = screen.getByLabelText('Delete Topic');
- await act(async () => { fireEvent.click(deleteButton); });
+ await act(async () => {
+ fireEvent.click(deleteButton);
+ });
const eventButton = screen.getByText(eventType);
- await act(async () => { fireEvent.click(eventButton); });
+ await act(async () => {
+ fireEvent.click(eventButton);
+ });
await waitFor(() => {
const configureLabel = screen.queryByText('Configure restricted date range');
@@ -178,7 +195,9 @@ describe('Discussion Restriction', () => {
const restrictionSchedules = screen.queryByTestId('restriction-schedules');
const expandBtn = within(restrictionSchedules).getByRole('button', { name: 'Expand' });
- await act(async () => { fireEvent.click(expandBtn); });
+ await act(async () => {
+ fireEvent.click(expandBtn);
+ });
let configureLabel = screen.queryByText('Configure restricted date range');
@@ -186,7 +205,9 @@ describe('Discussion Restriction', () => {
const collapseBtn = within(restrictionSchedules).getByRole('button', { name: 'Collapse' });
- await act(async () => { fireEvent.click(collapseBtn); });
+ await act(async () => {
+ fireEvent.click(collapseBtn);
+ });
configureLabel = screen.queryByText('Configure restricted date range');
diff --git a/src/pages-and-resources/discussions/app-config-form/apps/shared/DivisionByGroupFields.jsx b/src/pages-and-resources/discussions/app-config-form/apps/shared/DivisionByGroupFields.jsx
index cb39ff67b8..291214cfc6 100644
--- a/src/pages-and-resources/discussions/app-config-form/apps/shared/DivisionByGroupFields.jsx
+++ b/src/pages-and-resources/discussions/app-config-form/apps/shared/DivisionByGroupFields.jsx
@@ -1,7 +1,10 @@
import React, { useEffect, useContext } from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
- Form, TransitionReplace, Hyperlink, Alert,
+ Form,
+ TransitionReplace,
+ Hyperlink,
+ Alert,
} from '@openedx/paragon';
import { AppContext } from '@edx/frontend-platform/react';
import { FieldArray, useFormikContext } from 'formik';
@@ -74,14 +77,14 @@ const DivisionByGroupFields = () => {
{intl.formatMessage(messages.divisionByGroup)}
{!cohortsEnabled
- && (
-
- {intl.formatMessage(messages.cohortsEnabled)}
-
- {intl.formatMessage(messages.instructorDashboard)}
-
-
- )}
+ && (
+
+ {intl.formatMessage(messages.cohortsEnabled)}
+
+ {intl.formatMessage(messages.instructorDashboard)}
+
+
+ )}
{
disabled={!cohortsEnabled}
/>
- {(divideByCohorts && cohortsEnabled) ? (
-
-
- handleDivideCourseTopicsByCohortsToggle(event)}
- onBlur={handleBlur}
- className="ml-4 mt-3"
- id="divideCourseTopicsByCohorts"
- checked={divideCourseTopicsByCohorts}
- label={intl.formatMessage(messages.divideCourseTopicsByCohortsLabel)}
- helpText={intl.formatMessage(messages.divideCourseTopicsByCohortsHelp)}
- />
-
- {divideCourseTopicsByCohorts ? (
-
- (
-
- handleCheckBoxToggle(event, push, remove)}
- onBlur={handleBlur}
- defaultValue={divideDiscussionIds}
- >
- {validDiscussionTopics.map((topic) => (
- topic.name ? (
-
- {topic.name}
-
- ) : null
- ))}
-
-
- )}
- />
-
- ) : (
-
- )}
-
-
- ) : (
-
- )}
+ {(divideByCohorts && cohortsEnabled) ?
+ (
+
+
+ handleDivideCourseTopicsByCohortsToggle(event)}
+ onBlur={handleBlur}
+ className="ml-4 mt-3"
+ id="divideCourseTopicsByCohorts"
+ checked={divideCourseTopicsByCohorts}
+ label={intl.formatMessage(messages.divideCourseTopicsByCohortsLabel)}
+ helpText={intl.formatMessage(messages.divideCourseTopicsByCohortsHelp)}
+ />
+
+ {divideCourseTopicsByCohorts ?
+ (
+
+ (
+
+ handleCheckBoxToggle(event, push, remove)}
+ onBlur={handleBlur}
+ defaultValue={divideDiscussionIds}
+ >
+ {validDiscussionTopics.map((topic) => (
+ topic.name ?
+ (
+
+ {topic.name}
+
+ ) :
+ null
+ ))}
+
+
+ )}
+ />
+
+ ) :
+ }
+
+
+ ) :
+ }
>
);
diff --git a/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-restrictions/RestrictDatesInput.jsx b/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-restrictions/RestrictDatesInput.jsx
index 26d35d454e..cca8c90412 100644
--- a/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-restrictions/RestrictDatesInput.jsx
+++ b/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-restrictions/RestrictDatesInput.jsx
@@ -18,7 +18,10 @@ const RestrictDatesInput = ({
dataTestId,
}) => {
const {
- handleChange, handleBlur, errors, touched,
+ handleChange,
+ handleBlur,
+ errors,
+ touched,
} = useFormikContext();
const [inFocus, setInFocus] = useState(false);
diff --git a/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-topics/DiscussionTopics.test.jsx b/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-topics/DiscussionTopics.test.jsx
index d60dff70b4..0a2ce305b8 100644
--- a/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-topics/DiscussionTopics.test.jsx
+++ b/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-topics/DiscussionTopics.test.jsx
@@ -1,7 +1,14 @@
import React from 'react';
import {
- act, fireEvent, queryAllByTestId, queryByTestId, queryByText, render, waitFor, queryByLabelText,
+ act,
+ fireEvent,
+ queryAllByTestId,
+ queryByTestId,
+ queryByText,
+ render,
+ waitFor,
+ queryByLabelText,
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import MockAdapter from 'axios-mock-adapter';
diff --git a/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-topics/TopicItem.jsx b/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-topics/TopicItem.jsx
index 7db11c7ef2..0dfac758a0 100644
--- a/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-topics/TopicItem.jsx
+++ b/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-topics/TopicItem.jsx
@@ -5,7 +5,9 @@ import { useFormikContext } from 'formik';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
- Button, Card, Form,
+ Button,
+ Card,
+ Form,
} from '@openedx/paragon';
import CollapsableEditor from '../../../../../../generic/CollapsableEditor';
@@ -22,7 +24,9 @@ const TopicItem = ({
}) => {
const intl = useIntl();
const {
- handleChange, handleBlur, errors,
+ handleChange,
+ handleBlur,
+ errors,
} = useFormikContext();
const [inFocus, setInFocus] = useState(false);
const [showDeletePopup, setShowDeletePopup] = useState(false);
@@ -43,7 +47,8 @@ const TopicItem = ({
);
- } if (isOpen) {
+ }
+ if (isOpen) {
return (
{intl.formatMessage(messages.configureAdditionalTopic)}
diff --git a/src/pages-and-resources/discussions/app-config-form/messages.ts b/src/pages-and-resources/discussions/app-config-form/messages.ts
index 38165f6516..c23a19497e 100644
--- a/src/pages-and-resources/discussions/app-config-form/messages.ts
+++ b/src/pages-and-resources/discussions/app-config-form/messages.ts
@@ -3,11 +3,9 @@ import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
configurationChangeConsequence: {
id: 'authoring.discussions.configurationChangeConsequences',
- defaultMessage:
- 'Students will lose access to any active or previous'
+ defaultMessage: 'Students will lose access to any active or previous'
+ ' discussion posts for your course.',
- description:
- 'Describes that, as a consequence of changing configuration,'
+ description: 'Describes that, as a consequence of changing configuration,'
+ ' students will lose access posts on the course.',
},
configureApp: {
diff --git a/src/pages-and-resources/discussions/app-config-form/utils.js b/src/pages-and-resources/discussions/app-config-form/utils.js
index 90a71d58d2..36358cd27d 100644
--- a/src/pages-and-resources/discussions/app-config-form/utils.js
+++ b/src/pages-and-resources/discussions/app-config-form/utils.js
@@ -15,7 +15,8 @@ export const checkFieldErrors = (touched, errors, fieldPath, propertyName) => {
export const errorExists = (errors, fieldPath, propertyName) => getIn(errors, `${fieldPath}.${propertyName}`);
export const checkStatus = ([startDate, endDate]) => {
- const today = moment(); let status;
+ const today = moment();
+ let status;
if (moment(endDate).isBefore(today, 'days')) {
status = constants.COMPLETE;
@@ -38,7 +39,8 @@ export const hasValidTimeFormat = (time) => time && moment(time, validTimeFormat
export const startOfDayTime = (time) => time || moment().startOf('day').format('HH:mm');
export const endOfDayTime = (time) => time || moment().endOf('day').format('HH:mm');
export const normalizeTime = (time) => time && moment(time, validTimeFormats, true).format('HH:mm');
-export const normalizeDate = (date) => moment(date, ['MM/DD/YYYY', 'YYYY-MM-DDTHH:mm', 'YYYY-MM-DD'], true).format('YYYY-MM-DD');
+export const normalizeDate = (date) =>
+ moment(date, ['MM/DD/YYYY', 'YYYY-MM-DDTHH:mm', 'YYYY-MM-DD'], true).format('YYYY-MM-DD');
export const decodeDateTime = (date, time) => {
const nDate = normalizeDate(date);
@@ -56,7 +58,10 @@ export const sortRestrictedDatesByStatus = (data, status, order) => (
);
export const formatRestrictedDates = ({
- startDate, startTime, endDate, endTime,
+ startDate,
+ startTime,
+ endDate,
+ endTime,
}) => {
let formattedDate;
const hasSameDay = isSameDay(startDate, endDate);
diff --git a/src/pages-and-resources/discussions/app-list/AppCard.jsx b/src/pages-and-resources/discussions/app-list/AppCard.jsx
index 31cc9a0ccd..5e5f1fe1e2 100644
--- a/src/pages-and-resources/discussions/app-list/AppCard.jsx
+++ b/src/pages-and-resources/discussions/app-list/AppCard.jsx
@@ -3,7 +3,9 @@ import classNames from 'classnames';
import { useIntl } from '@edx/frontend-platform/i18n';
import Responsive from 'react-responsive';
import {
- Card, CheckboxControl, breakpoints,
+ Card,
+ CheckboxControl,
+ breakpoints,
} from '@openedx/paragon';
import { useCourseAuthoringContext } from '@src/CourseAuthoringContext';
import messages from './messages';
@@ -11,7 +13,10 @@ import appMessages from '../app-config-form/messages';
import FeaturesList from './FeaturesList';
const AppCard = ({
- app, onClick, selected, features,
+ app,
+ onClick,
+ selected,
+ features,
}) => {
const intl = useIntl();
const { canChangeProviders } = useCourseAuthoringContext();
@@ -33,7 +38,7 @@ const AppCard = ({
{intl.formatMessage(appMessages[`appName-${app.id}`])} }
subtitle={{supportText}
}
- actions={(
+ actions={
- )}
+ }
size="sm"
/>
diff --git a/src/pages-and-resources/discussions/app-list/AppCard.test.jsx b/src/pages-and-resources/discussions/app-list/AppCard.test.jsx
index 1abf950bbd..f2c5279599 100644
--- a/src/pages-and-resources/discussions/app-list/AppCard.test.jsx
+++ b/src/pages-and-resources/discussions/app-list/AppCard.test.jsx
@@ -1,5 +1,8 @@
import {
- render, queryByLabelText, queryByTestId, initializeMocks,
+ render,
+ queryByLabelText,
+ queryByTestId,
+ initializeMocks,
} from '@src/testUtils';
import { executeThunk } from '@src/utils';
diff --git a/src/pages-and-resources/discussions/app-list/AppList.jsx b/src/pages-and-resources/discussions/app-list/AppList.jsx
index 571683b755..8e060b10cf 100644
--- a/src/pages-and-resources/discussions/app-list/AppList.jsx
+++ b/src/pages-and-resources/discussions/app-list/AppList.jsx
@@ -1,16 +1,31 @@
import React, {
- useCallback, useEffect, useMemo, useState, useContext,
+ useCallback,
+ useEffect,
+ useMemo,
+ useState,
+ useContext,
} from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
- CardGrid, Container, breakpoints, Form, ActionRow, AlertModal, Button, StatefulButton,
+ CardGrid,
+ Container,
+ breakpoints,
+ Form,
+ ActionRow,
+ AlertModal,
+ Button,
+ StatefulButton,
} from '@openedx/paragon';
import { useDispatch, useSelector } from 'react-redux';
import Responsive from 'react-responsive';
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
import { useModels } from '../../../generic/model-store';
import {
- selectApp, LOADED, LOADING, SAVING, updateValidationStatus,
+ selectApp,
+ LOADED,
+ LOADING,
+ SAVING,
+ updateValidationStatus,
} from '../data/slice';
import AppCard from './AppCard';
import messages from './messages';
@@ -27,7 +42,14 @@ const AppList = () => {
const dispatch = useDispatch();
const { courseId } = useContext(PagesAndResourcesContext);
const {
- appIds, featureIds, status, saveStatus, activeAppId, selectedAppId, enabled, postingRestrictions,
+ appIds,
+ featureIds,
+ status,
+ saveStatus,
+ activeAppId,
+ selectedAppId,
+ enabled,
+ postingRestrictions,
} = useSelector(state => state.discussions);
const [discussionTabToggle, setDiscussionTabToggle] = useState(enabled);
const apps = useModels('apps', appIds);
@@ -36,9 +58,10 @@ const AppList = () => {
const ltiProvider = !['openedx', 'legacy'].includes(activeAppId);
const isOnSmallScreen = useIsOnSmallScreen();
- const showOneEdxProvider = useMemo(() => apps.filter(app => (
- activeAppId === 'openedx' ? app.id !== 'legacy' : app.id !== 'openedx'
- )), [activeAppId]);
+ const showOneEdxProvider = useMemo(() =>
+ apps.filter(app => (
+ activeAppId === 'openedx' ? app.id !== 'legacy' : app.id !== 'openedx'
+ )), [activeAppId]);
// This could be a bit confusing. activeAppId is the ID of the app that is currently configured
// according to the server. selectedAppId is the ID of the app that we _want_ to configure here
@@ -73,8 +96,7 @@ const AppList = () => {
selectedAppId,
{
enabled: enabledDiscussion,
- postingRestrictions:
- enabledDiscussion ? postingRestrictions : discussionRestriction.ENABLED,
+ postingRestrictions: enabledDiscussion ? postingRestrictions : discussionRestriction.ENABLED,
},
));
}, [courseId, selectedAppId, postingRestrictions]);
@@ -98,9 +120,7 @@ const AppList = () => {
}, [updateSettings]);
if (!selectedAppId || status === LOADING) {
- return (
-
- );
+ return ;
}
if (status === LOADED && apps.length === 0) {
@@ -111,15 +131,16 @@ const AppList = () => {
);
}
- const showAppCard = (filteredApps) => filteredApps.map(app => (
-
- ));
+ const showAppCard = (filteredApps) =>
+ filteredApps.map(app => (
+
+ ));
return (
@@ -166,7 +187,7 @@ const AppList = () => {
onClose={handleClose}
isBlocking
className="hide-discussion-modal"
- footerNode={(
+ footerNode={
{intl.formatMessage(messages.hideDiscussionCancelButton)}
@@ -181,7 +202,7 @@ const AppList = () => {
onClick={handleOk}
/>
- )}
+ }
>
{intl.formatMessage(messages.hideDiscussionTabMessage)}
diff --git a/src/pages-and-resources/discussions/app-list/AppList.test.jsx b/src/pages-and-resources/discussions/app-list/AppList.test.jsx
index 1fa13dd356..84beda4786 100644
--- a/src/pages-and-resources/discussions/app-list/AppList.test.jsx
+++ b/src/pages-and-resources/discussions/app-list/AppList.test.jsx
@@ -1,6 +1,11 @@
/* eslint-disable react/jsx-no-constructed-context-values */
import {
- render, screen, within, queryAllByRole, waitFor, fireEvent,
+ render,
+ screen,
+ within,
+ queryAllByRole,
+ waitFor,
+ fireEvent,
initializeMocks,
} from '@src/testUtils';
import { act } from 'react-dom/test-utils';
@@ -114,8 +119,10 @@ describe('AppList', () => {
test('hides the FeaturesList at desktop sizes', async () => {
renderComponent();
- await waitFor(() => expect(screen.queryByText(messages['supportedFeatureList-mobile-show'].defaultMessage))
- .not.toBeInTheDocument());
+ await waitFor(() =>
+ expect(screen.queryByText(messages['supportedFeatureList-mobile-show'].defaultMessage))
+ .not.toBeInTheDocument()
+ );
});
test('displays the FeaturesList at mobile sizes', async () => {
diff --git a/src/pages-and-resources/discussions/app-list/FeatureList.test.jsx b/src/pages-and-resources/discussions/app-list/FeatureList.test.jsx
index e021160e72..18ce0323dc 100644
--- a/src/pages-and-resources/discussions/app-list/FeatureList.test.jsx
+++ b/src/pages-and-resources/discussions/app-list/FeatureList.test.jsx
@@ -1,7 +1,10 @@
import React from 'react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import {
- render, queryAllByText, queryByText, getByRole,
+ render,
+ queryAllByText,
+ queryByText,
+ getByRole,
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import FeaturesList from './FeaturesList';
diff --git a/src/pages-and-resources/discussions/app-list/FeaturesList.jsx b/src/pages-and-resources/discussions/app-list/FeaturesList.jsx
index e28a1e3ff8..4307ea7677 100644
--- a/src/pages-and-resources/discussions/app-list/FeaturesList.jsx
+++ b/src/pages-and-resources/discussions/app-list/FeaturesList.jsx
@@ -11,7 +11,7 @@ const FeaturesList = ({ app }) => {
return (
event.stopPropagation()}
- title={(
+ title={
<>
{intl.formatMessage(messages['supportedFeatureList-mobile-show'])}
@@ -20,7 +20,7 @@ const FeaturesList = ({ app }) => {
{intl.formatMessage(messages['supportedFeatureList-mobile-hide'])}
>
- )}
+ }
styling="basic"
>
{app.featureIds.map((id) => (
diff --git a/src/pages-and-resources/discussions/app-list/FeaturesTable.jsx b/src/pages-and-resources/discussions/app-list/FeaturesTable.jsx
index 2ad081fca9..dfc7daab46 100644
--- a/src/pages-and-resources/discussions/app-list/FeaturesTable.jsx
+++ b/src/pages-and-resources/discussions/app-list/FeaturesTable.jsx
@@ -13,7 +13,10 @@ import './FeaturesTable.scss';
const FeaturesTable = ({ apps, features }) => {
const intl = useIntl();
const {
- basic, partial, full, common,
+ basic,
+ partial,
+ full,
+ common,
} = groupBy(features, (feature) => feature.featureSupportType);
const createRow = (feature) => {
@@ -32,22 +35,21 @@ const FeaturesTable = ({ apps, features }) => {
key={`${app.id}&${feature.id}`}
data-testid={`${app.id}-${feature.id.replaceAll('.', '-')}`}
>
- {
- app.featureIds.includes(feature.id)
- ?
- :
- }
+ {app.featureIds.includes(feature.id)
+ ?
+ : }
);
}
});
return {
- feature: FEATURE_TYPES.includes(feature) ? (
-
- {intl.formatMessage(messages[`featureType-${feature}`])}
-
- )
+ feature: FEATURE_TYPES.includes(feature) ?
+ (
+
+ {intl.formatMessage(messages[`featureType-${feature}`])}
+
+ )
: intl.formatMessage(messages[`featureName-${feature.id}`]),
// 'feature' is the identifier for cells in the first column.
// This is spreading the app IDs from appCheckmarkCells into the return array, creating
@@ -60,18 +62,16 @@ const FeaturesTable = ({ apps, features }) => {
return (
createRow(feature)),
- { ...createRow('partial') },
- ...partial.map((feature) => createRow(feature)),
- { ...createRow('full') },
- ...full.map((feature) => createRow(feature)),
- { ...createRow('common') },
- ...common.map((feature) => createRow(feature)),
- ]
- }
+ data={[
+ { ...createRow('basic') },
+ ...basic.map((feature) => createRow(feature)),
+ { ...createRow('partial') },
+ ...partial.map((feature) => createRow(feature)),
+ { ...createRow('full') },
+ ...full.map((feature) => createRow(feature)),
+ { ...createRow('common') },
+ ...common.map((feature) => createRow(feature)),
+ ]}
columns={[
{
Header: '',
diff --git a/src/pages-and-resources/discussions/app-list/FeaturesTable.test.jsx b/src/pages-and-resources/discussions/app-list/FeaturesTable.test.jsx
index 68a32f901d..e5b232bc3a 100644
--- a/src/pages-and-resources/discussions/app-list/FeaturesTable.test.jsx
+++ b/src/pages-and-resources/discussions/app-list/FeaturesTable.test.jsx
@@ -22,7 +22,8 @@ describe('FeaturesTable', () => {
featureIds: ['discussion-page', 'basic-configuration'],
hasFullSupport: false,
id: 'piazza',
- }];
+ },
+ ];
features = [
{ id: 'discussion-page', featureSupportType: 'basic' },
diff --git a/src/pages-and-resources/discussions/data/api.js b/src/pages-and-resources/discussions/data/api.js
index 706ae44094..669a503747 100644
--- a/src/pages-and-resources/discussions/data/api.js
+++ b/src/pages-and-resources/discussions/data/api.js
@@ -203,7 +203,8 @@ function denormalizeData(courseId, appId, data) {
}
if ('divideCourseTopicsByCohorts' in data) {
pluginConfiguration.divided_course_wide_discussions = data.divideCourseTopicsByCohorts
- ? data.divideDiscussionIds : [];
+ ? data.divideDiscussionIds :
+ [];
}
const ltiConfiguration = {};
diff --git a/src/pages-and-resources/discussions/data/constants.ts b/src/pages-and-resources/discussions/data/constants.ts
index 2a1bf010e6..ede453caf3 100644
--- a/src/pages-and-resources/discussions/data/constants.ts
+++ b/src/pages-and-resources/discussions/data/constants.ts
@@ -53,6 +53,9 @@ export const discussionRestrictionOptions = [
export const today = moment();
export const active = [today.format('YYYY-MM-DDTHH:mm'), today.add(5, 'hours').format('YYYY-MM-DDTHH:mm')];
export const upcoming = [today.add(2, 'days').format('YYYY-MM-DD'), today.add(5, 'days').format('YYYY-MM-DD')];
-export const complete = [today.subtract(7, 'days').format('YYYY-MM-DD'), today.subtract(5, 'days').format('YYYY-MM-DD')];
+export const complete = [
+ today.subtract(7, 'days').format('YYYY-MM-DD'),
+ today.subtract(5, 'days').format('YYYY-MM-DD'),
+];
export const FEATURE_TYPES = ['basic', 'partial', 'full', 'common'];
diff --git a/src/pages-and-resources/discussions/data/redux.test.js b/src/pages-and-resources/discussions/data/redux.test.js
index 4c4753101d..eda89138c4 100644
--- a/src/pages-and-resources/discussions/data/redux.test.js
+++ b/src/pages-and-resources/discussions/data/redux.test.js
@@ -8,7 +8,12 @@ import { executeThunk } from '../../../utils';
import { generateProvidersApiResponse, legacyApiResponse, piazzaApiResponse } from '../factories/mockApiResponses';
import { getDiscussionsProvidersUrl, getDiscussionsSettingsUrl } from './api';
import {
- DENIED, FAILED, SAVED, LOADED, selectApp, updateValidationStatus,
+ DENIED,
+ FAILED,
+ SAVED,
+ LOADED,
+ selectApp,
+ updateValidationStatus,
} from './slice';
import { fetchDiscussionSettings, fetchProviders, saveProviderConfig } from './thunks';
@@ -28,12 +33,10 @@ const featuresState = {
'wcag-2.1': {
id: 'wcag-2.1',
featureSupportType: 'partial',
-
},
'basic-configuration': {
id: 'basic-configuration',
featureSupportType: 'common',
-
},
};
@@ -284,7 +287,10 @@ describe('Data layer integration tests', () => {
await executeThunk(fetchProviders(courseId), store.dispatch);
await executeThunk(fetchDiscussionSettings(courseId), store.dispatch);
store.dispatch(selectApp({ appId: 'piazza' }));
- await executeThunk(saveProviderConfig(courseId, 'piazza', {}, pagesAndResourcesPath, mockedNavigator), store.dispatch);
+ await executeThunk(
+ saveProviderConfig(courseId, 'piazza', {}, pagesAndResourcesPath, mockedNavigator),
+ store.dispatch,
+ );
expect(store.getState().discussions).toEqual(
expect.objectContaining({
@@ -307,7 +313,10 @@ describe('Data layer integration tests', () => {
// We call fetchProviders and selectApp here too just to get us into a real state.
await executeThunk(fetchProviders(courseId), store.dispatch);
store.dispatch(selectApp({ appId: 'piazza' }));
- await executeThunk(saveProviderConfig(courseId, 'piazza', {}, pagesAndResourcesPath, mockedNavigator), store.dispatch);
+ await executeThunk(
+ saveProviderConfig(courseId, 'piazza', {}, pagesAndResourcesPath, mockedNavigator),
+ store.dispatch,
+ );
expect(store.getState().discussions).toEqual(
expect.objectContaining({
@@ -351,17 +360,20 @@ describe('Data layer integration tests', () => {
// We call fetchProviders and selectApp here too just to get us into a real state.
await executeThunk(fetchProviders(courseId), store.dispatch);
store.dispatch(selectApp({ appId: 'piazza' }));
- await executeThunk(saveProviderConfig(
- courseId,
- 'piazza',
- {
- consumerKey: 'new_consumer_key',
- consumerSecret: 'new_consumer_secret',
- launchUrl: 'http://localhost/new_launch_url',
- },
- pagesAndResourcesPath,
- mockedNavigator,
- ), store.dispatch);
+ await executeThunk(
+ saveProviderConfig(
+ courseId,
+ 'piazza',
+ {
+ consumerKey: 'new_consumer_key',
+ consumerSecret: 'new_consumer_secret',
+ launchUrl: 'http://localhost/new_launch_url',
+ },
+ pagesAndResourcesPath,
+ mockedNavigator,
+ ),
+ store.dispatch,
+ );
await waitFor(() => {
expect(mockedNavigator).toHaveBeenCalledWith(pagesAndResourcesPath);
@@ -435,30 +447,33 @@ describe('Data layer integration tests', () => {
await executeThunk(fetchProviders(courseId), store.dispatch);
await executeThunk(fetchDiscussionSettings(courseId), store.dispatch);
store.dispatch(selectApp({ appId: 'legacy' }));
- await executeThunk(saveProviderConfig(
- courseId,
- 'legacy',
- {
- allowAnonymousPosts: true,
- allowAnonymousPostsPeers: true,
- reportedContentEmailNotifications: true,
- restrictedDates: [],
- // TODO: Note! As of this writing, all the data below this line is NOT returned in the API
- // but we technically send it to the thunk, so here it is.
- divideByCohorts: true,
- allowDivisionsByUnit: true,
- alwaysDivideInlineDiscussions: true,
- divideCourseTopicsByCohorts: true,
- divisionScheme: DivisionSchemes.COHORT,
- divideDiscussionIds,
- discussionTopics: [
- { name: 'Edx', id: '13f106c6-6735-4e84-b097-0456cff55960' },
- { name: 'General', id: 'course' },
- ],
- },
- pagesAndResourcesPath,
- mockedNavigator,
- ), store.dispatch);
+ await executeThunk(
+ saveProviderConfig(
+ courseId,
+ 'legacy',
+ {
+ allowAnonymousPosts: true,
+ allowAnonymousPostsPeers: true,
+ reportedContentEmailNotifications: true,
+ restrictedDates: [],
+ // TODO: Note! As of this writing, all the data below this line is NOT returned in the API
+ // but we technically send it to the thunk, so here it is.
+ divideByCohorts: true,
+ allowDivisionsByUnit: true,
+ alwaysDivideInlineDiscussions: true,
+ divideCourseTopicsByCohorts: true,
+ divisionScheme: DivisionSchemes.COHORT,
+ divideDiscussionIds,
+ discussionTopics: [
+ { name: 'Edx', id: '13f106c6-6735-4e84-b097-0456cff55960' },
+ { name: 'General', id: 'course' },
+ ],
+ },
+ pagesAndResourcesPath,
+ mockedNavigator,
+ ),
+ store.dispatch,
+ );
await waitFor(() => {
expect(mockedNavigator).toHaveBeenCalledWith(pagesAndResourcesPath);
expect(store.getState().discussions).toEqual(
diff --git a/src/pages-and-resources/discussions/data/thunks.js b/src/pages-and-resources/discussions/data/thunks.js
index 4e0fc189ce..568bcec037 100644
--- a/src/pages-and-resources/discussions/data/thunks.js
+++ b/src/pages-and-resources/discussions/data/thunks.js
@@ -1,7 +1,14 @@
import { addModel, addModels } from '../../../generic/model-store';
import { getDiscussionsProviders, getDiscussionsSettings, postDiscussionsSettings } from './api';
import {
- DENIED, FAILED, loadApps, LOADING, SAVED, SAVING, updateSaveStatus, updateStatus,
+ DENIED,
+ FAILED,
+ loadApps,
+ LOADING,
+ SAVED,
+ SAVING,
+ updateSaveStatus,
+ updateStatus,
} from './slice';
function updateDiscussionSettingsState({
diff --git a/src/pages-and-resources/discussions/factories/mockApiResponses.js b/src/pages-and-resources/discussions/factories/mockApiResponses.js
index 093d74824c..8b1ccbdd68 100644
--- a/src/pages-and-resources/discussions/factories/mockApiResponses.js
+++ b/src/pages-and-resources/discussions/factories/mockApiResponses.js
@@ -173,8 +173,7 @@ export const emptyAppApiResponse = {
plugin_configuration: {},
providers: {
active: 'legacy',
- available: {
- },
+ available: {},
},
};
@@ -211,7 +210,8 @@ export const courseDetailResponse = {
name: 'Demonstration Course',
number: 'DemoX',
org: 'edX',
- overview: '\n About This Course \n Include your long course description here. The long course description should contain 150-400 words.
\n\n This is paragraph 2 of the long course description. Add more paragraphs as needed. Make sure to enclose them in paragraph tags.
\n \n\n \n Prerequisites \n Add information about course prerequisites here.
\n \n\n \n Course Staff \n \n \n
\n
\n\n Staff Member #1 \n Biography of instructor/staff member #1
\n \n\n \n \n
\n
\n\n Staff Member #2 \n Biography of instructor/staff member #2
\n \n \n\n \n \n Frequently Asked Questions \n \n What web browser should I use? \n The Open edX platform works best with current versions of Chrome, Firefox or Safari, or with Internet Explorer version 9 and above.
\n\n See our list of supported browsers for the most up-to-date information.
\n \n\n \n Question #2 \n Your answer would be displayed here.
\n \n \n \n',
+ overview:
+ '\n About This Course \n Include your long course description here. The long course description should contain 150-400 words.
\n\n This is paragraph 2 of the long course description. Add more paragraphs as needed. Make sure to enclose them in paragraph tags.
\n \n\n \n Prerequisites \n Add information about course prerequisites here.
\n \n\n \n Course Staff \n \n \n
\n
\n\n Staff Member #1 \n Biography of instructor/staff member #1
\n \n\n \n \n
\n
\n\n Staff Member #2 \n Biography of instructor/staff member #2
\n \n \n\n \n \n Frequently Asked Questions \n \n What web browser should I use? \n The Open edX platform works best with current versions of Chrome, Firefox or Safari, or with Internet Explorer version 9 and above.
\n\n See our list of supported browsers for the most up-to-date information.
\n \n\n \n Question #2 \n Your answer would be displayed here.
\n \n \n \n',
pacing: 'instructor',
short_description: null,
start: '2013-02-05T05:00:00Z',
diff --git a/src/pages-and-resources/discussions/index.ts b/src/pages-and-resources/discussions/index.ts
index aac60e6dbe..51d2940d40 100644
--- a/src/pages-and-resources/discussions/index.ts
+++ b/src/pages-and-resources/discussions/index.ts
@@ -1,2 +1,2 @@
-export { default } from './DiscussionsSettings';
export { reducer } from './data/slice';
+export { default } from './DiscussionsSettings';
diff --git a/src/pages-and-resources/discussions/messages.ts b/src/pages-and-resources/discussions/messages.ts
index eb165c7b59..7dd42fefe4 100644
--- a/src/pages-and-resources/discussions/messages.ts
+++ b/src/pages-and-resources/discussions/messages.ts
@@ -36,8 +36,8 @@ const messages = defineMessages({
},
noProviderSwitchAfterCourseStarted: {
id: 'authoring.discussions.noProviderSwitchAfterCourseStarted',
- defaultMessage: "Discussion provider can't be changed after course has started, please reach out to partner support.",
- description: "Informs the user that the provider can't be changed after the course has started.",
+ defaultMessage: 'Discussion provider can\'t be changed after course has started, please reach out to partner support.',
+ description: 'Informs the user that the provider can\'t be changed after the course has started.',
},
providerSelection: {
id: 'authoring.discussions.providerSelection',
diff --git a/src/pages-and-resources/pages/PageGrid.jsx b/src/pages-and-resources/pages/PageGrid.jsx
index 0d7445fd4f..fda21275be 100644
--- a/src/pages-and-resources/pages/PageGrid.jsx
+++ b/src/pages-and-resources/pages/PageGrid.jsx
@@ -4,16 +4,15 @@ import { CardGrid } from '@openedx/paragon';
import PageCard, { CoursePageShape } from './PageCard';
const PageGrid = ({ pages, pluginSlotComponent, courseId }) => (
-
- {pages.map((page) => (
-
- ))}
+ {pages.map((page) => )}
{pluginSlotComponent}
);
diff --git a/src/plugin-slots/AdditionalCourseContentPluginSlot/README.md b/src/plugin-slots/AdditionalCourseContentPluginSlot/README.md
index e132e646ca..95435f9b9c 100644
--- a/src/plugin-slots/AdditionalCourseContentPluginSlot/README.md
+++ b/src/plugin-slots/AdditionalCourseContentPluginSlot/README.md
@@ -3,4 +3,5 @@
### Slot ID: `org.openedx.frontend.authoring.additional_course_content_plugin.v1`
### Slot ID Aliases
-* `additional_course_content_plugin`
\ No newline at end of file
+
+- `additional_course_content_plugin`
diff --git a/src/plugin-slots/AdditionalCoursePluginSlot/README.md b/src/plugin-slots/AdditionalCoursePluginSlot/README.md
index 5e6c286a33..5a6b96efc9 100644
--- a/src/plugin-slots/AdditionalCoursePluginSlot/README.md
+++ b/src/plugin-slots/AdditionalCoursePluginSlot/README.md
@@ -3,7 +3,8 @@
### Slot ID: `org.openedx.frontend.authoring.additional_course_plugin.v1`
### Slot ID Aliases
-* `additional_course_plugin`
+
+- `additional_course_plugin`
## Description
@@ -34,31 +35,30 @@ const config = {
id: 'custom_additional_course',
type: DIRECT_PLUGIN,
RenderWidget: () => (
-
-
- slot props course
-
- )}
- actions={ }
- size="sm"
- />
-
-
- Additional course from slot props description.
- Or anything else.
-
-
-
+
+
+ slot props course
+
+ }
+ actions={ }
+ size="sm"
+ />
+
+
+ Additional course from slot props description. Or anything else.
+
+
+
),
},
},
- ]
- }
+ ],
+ },
},
-}
+};
export default config;
-```
\ No newline at end of file
+```
diff --git a/src/plugin-slots/AdditionalTranslationsComponentSlot/README.md b/src/plugin-slots/AdditionalTranslationsComponentSlot/README.md
index 7d1677de5d..fd01d7e44d 100644
--- a/src/plugin-slots/AdditionalTranslationsComponentSlot/README.md
+++ b/src/plugin-slots/AdditionalTranslationsComponentSlot/README.md
@@ -3,18 +3,19 @@
### Slot ID: `org.openedx.frontend.authoring.video_transcript_additional_translations_component.v1`
### Slot ID Aliases
-* `additonal_translations_component_slot` (original misspelling)
-* `additional_translations_component_slot`
+
+- `additonal_translations_component_slot` (original misspelling)
+- `additional_translations_component_slot`
### Plugin Props:
-* `setIsAiTranslations` - Function (React SetState)
-* `closeTranscriptSettings` - Function (Paragon useToggle)
-* `courseId` - String
-* `additionalProps` - Object
- * `transcriptType` - String
- * `isAiTranslationsEnabled` - Boolean
-
+- `setIsAiTranslations` - Function (React SetState)
+- `closeTranscriptSettings` - Function (Paragon useToggle)
+- `courseId` - String
+- `additionalProps` - Object
+ - `transcriptType` - String
+ - `isAiTranslationsEnabled` - Boolean
+
## Description
This slot is used to add a custom block in the **Video Transcription Settings** drawer.
@@ -35,9 +36,7 @@ const TranslationsBlock = ({ setIsAiTranslations, courseId }) => (
setIsAiTranslations(courseId === 'anyId')}
>
-
+
Custom transcript 💬
@@ -60,7 +59,7 @@ const config = {
],
},
},
-}
+};
export default config;
```
diff --git a/src/plugin-slots/CourseAuthoringOutlineSidebarSlot/README.md b/src/plugin-slots/CourseAuthoringOutlineSidebarSlot/README.md
index ee11b7975e..3ac27900b6 100644
--- a/src/plugin-slots/CourseAuthoringOutlineSidebarSlot/README.md
+++ b/src/plugin-slots/CourseAuthoringOutlineSidebarSlot/README.md
@@ -3,13 +3,14 @@
### Slot ID: `org.openedx.frontend.authoring.course_outline_sidebar.v1`
### Slot ID Aliases
-* `course_authoring_outline_sidebar_slot`
+
+- `course_authoring_outline_sidebar_slot`
### Plugin Props:
-* `courseId` - String.
-* `courseName` - String.
-* `sections` - Array of Objects. Object structure defined in `index.tsx`.
+- `courseId` - String.
+- `courseName` - String.
+- `sections` - Array of Objects. Object structure defined in `index.tsx`.
## Description
@@ -33,13 +34,11 @@ const config = {
{
op: PLUGIN_OPERATIONS.Wrap,
widgetId: 'default_contents',
- wrapper: ({ component }) => (
- {component}
- ),
+ wrapper: ({ component }) => {component}
,
},
],
},
- }
+ },
};
export default config;
```
diff --git a/src/plugin-slots/CourseAuthoringOutlineSidebarSlot/index.tsx b/src/plugin-slots/CourseAuthoringOutlineSidebarSlot/index.tsx
index 1386d7aebc..da5c54e1cc 100644
--- a/src/plugin-slots/CourseAuthoringOutlineSidebarSlot/index.tsx
+++ b/src/plugin-slots/CourseAuthoringOutlineSidebarSlot/index.tsx
@@ -21,10 +21,10 @@ export const CourseAuthoringOutlineSidebarSlot = ({
);
type Section = {
- id: string,
- displayName: string,
- graded: boolean,
- category: string,
+ id: string;
+ displayName: string;
+ graded: boolean;
+ category: string;
};
interface CourseAuthoringOutlineSidebarSlotProps {
diff --git a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md
index 091af0d8df..20bc9cc305 100644
--- a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md
+++ b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md
@@ -6,13 +6,13 @@
### Plugin Props:
-* `courseId` - String.
-* `blockId` - String. The usage id of the current unit being viewed / edited.
-* `unitTitle` - String. The name of the current unit being viewed / edited.
-* `xBlocks` - Array of Objects. List of XBlocks in the Unit. Object structure defined in `index.tsx`.
-* `readOnly` - Boolean. True if the user should not be able to edit the contents of the unit.
-* `isUnitVerticalType` - Boolean. If the unit category is `vertical`.
-* `isSplitTestType` - Boolean. If the unit category is `split_test`.
+- `courseId` - String.
+- `blockId` - String. The usage id of the current unit being viewed / edited.
+- `unitTitle` - String. The name of the current unit being viewed / edited.
+- `xBlocks` - Array of Objects. List of XBlocks in the Unit. Object structure defined in `index.tsx`.
+- `readOnly` - Boolean. True if the user should not be able to edit the contents of the unit.
+- `isUnitVerticalType` - Boolean. If the unit category is `vertical`.
+- `isSplitTestType` - Boolean. If the unit category is `split_test`.
## Description
@@ -36,13 +36,11 @@ const config = {
{
op: PLUGIN_OPERATIONS.Wrap,
widgetId: 'default_contents',
- wrapper: ({ component }) => (
- {component}
- ),
+ wrapper: ({ component }) => {component}
,
},
],
},
- }
+ },
};
export default config;
```
@@ -52,16 +50,15 @@ export default config;

```js
-import { PLUGIN_OPERATIONS, DIRECT_PLUGIN } from '@openedx/frontend-plugin-framework';
+import { PLUGIN_OPERATIONS, DIRECT_PLUGIN } from '@openedx/frontend-plugin-framework';
-const ProblemBlocks = ({unitTitle, xBlocks}) => (
+const ProblemBlocks = ({ unitTitle, xBlocks }) => (
<>
{unitTitle}: Problem Blocks
{xBlocks
- .filter(block => block.blockType === "problem")
- .map(block => {block.displayName} )
- }
+ .filter(block => block.blockType === 'problem')
+ .map(block => {block.displayName} )}
>
);
@@ -73,16 +70,16 @@ const config = {
plugins: [
{
op: PLUGIN_OPERATIONS.Insert,
- widget:{
+ widget: {
id: 'problem-blocks-list',
priority: 1,
type: DIRECT_PLUGIN,
RenderWidget: ProblemBlocks,
- }
+ },
},
],
},
- }
+ },
};
export default config;
```
diff --git a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.v1.md b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.v1.md
index aafccfb461..0cb842e311 100644
--- a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.v1.md
+++ b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.v1.md
@@ -6,11 +6,11 @@
### Plugin Props:
-* `courseId` - String.
-* `blockId` - String. The usage id of the current unit being viewed / edited.
-* `unitTitle` - String. The name of the current unit being viewed / edited.
-* `xBlocks` - Array of Objects. List of XBlocks in the Unit. Object structure defined in `index.tsx`.
-* `readOnly` - Boolean. True if the user should not be able to edit the contents of the unit.
+- `courseId` - String.
+- `blockId` - String. The usage id of the current unit being viewed / edited.
+- `unitTitle` - String. The name of the current unit being viewed / edited.
+- `xBlocks` - Array of Objects. List of XBlocks in the Unit. Object structure defined in `index.tsx`.
+- `readOnly` - Boolean. True if the user should not be able to edit the contents of the unit.
### Description
@@ -22,9 +22,10 @@ be used to add additional sidebar components or modify the existing sidebar.
> It is recommended to use the `org.openedx.frontend.authoring.course_unit_sidebar.v2` slot ID for new plugins.
The `v1` slot has the following limitations compared to the `v2` version:
-* It renders conditionally based on the `isUnitVerticalType` prop, which means the plugins won't be rendered in other scenarios like unit with library blocks.
-* It does **not** wrap the `SplitTestSidebarInfo` component. So it can't be hidden from the sidebar by overriding the components in the slot.
-* As it is not the primary child component of the sidebar, CSS styling for inserted components face limitations, such as an inability to be `sticky` or achieve 100% height.
+
+- It renders conditionally based on the `isUnitVerticalType` prop, which means the plugins won't be rendered in other scenarios like unit with library blocks.
+- It does **not** wrap the `SplitTestSidebarInfo` component. So it can't be hidden from the sidebar by overriding the components in the slot.
+- As it is not the primary child component of the sidebar, CSS styling for inserted components face limitations, such as an inability to be `sticky` or achieve 100% height.
## Example 1
@@ -43,13 +44,11 @@ const config = {
{
op: PLUGIN_OPERATIONS.Wrap,
widgetId: 'default_contents',
- wrapper: ({ component }) => (
- {component}
- ),
+ wrapper: ({ component }) => {component}
,
},
],
},
- }
+ },
};
export default config;
```
@@ -59,16 +58,15 @@ export default config;

```js
-import { PLUGIN_OPERATIONS, DIRECT_PLUGIN } from '@openedx/frontend-plugin-framework';
+import { PLUGIN_OPERATIONS, DIRECT_PLUGIN } from '@openedx/frontend-plugin-framework';
-const ProblemBlocks = ({unitTitle, xBlocks}) => (
+const ProblemBlocks = ({ unitTitle, xBlocks }) => (
<>
{unitTitle}: Problem Blocks
{xBlocks
- .filter(block => block.blockType === "problem")
- .map(block => {block.displayName} )
- }
+ .filter(block => block.blockType === 'problem')
+ .map(block => {block.displayName} )}
>
);
@@ -80,16 +78,16 @@ const config = {
plugins: [
{
op: PLUGIN_OPERATIONS.Insert,
- widget:{
+ widget: {
id: 'problem-blocks-list',
priority: 1,
type: DIRECT_PLUGIN,
RenderWidget: ProblemBlocks,
- }
+ },
},
],
},
- }
+ },
};
export default config;
```
diff --git a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/index.tsx b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/index.tsx
index 6c16a58336..67575020ca 100644
--- a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/index.tsx
+++ b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/index.tsx
@@ -15,7 +15,13 @@ export const CourseAuthoringUnitSidebarSlot = (