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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useDispatch, useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import { useNavigate } from 'react-router-dom';
import { Button } from '@openedx/paragon';
import { Button, ButtonGroup } from '@openedx/paragon';
import { Plus as PlusIcon, ContentPasteGo as ContentPasteGoIcon } from '@openedx/paragon/icons';
import { useIntl } from '@edx/frontend-platform/i18n';

Expand Down Expand Up @@ -49,7 +49,7 @@ const SequenceNavigationTabs = ({
return (
<div className="sequence-navigation-tabs-wrapper">
<div className="sequence-navigation-tabs-container d-flex" ref={containerRef}>
<div
<ButtonGroup
className="sequence-navigation-tabs d-flex flex-grow-1"
style={shouldDisplayDropdown ? invisibleStyle : null}
>
Expand Down Expand Up @@ -80,7 +80,7 @@ const SequenceNavigationTabs = ({
{intl.formatMessage(messages.pasteAsNewUnitLink)}
</Button>
)}
</div>
</ButtonGroup>
</div>
{shouldDisplayDropdown && (
<SequenceNavigationDropdown
Expand Down
6 changes: 2 additions & 4 deletions src/editors/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import React from 'react';
import { useDispatch } from 'react-redux';

import * as hooks from './hooks';
import { useEditorContext } from './EditorContext';

import supportedEditors from './supportedEditors';
import type { EditorComponent } from './EditorComponent';
Expand All @@ -13,20 +14,17 @@ export interface Props extends EditorComponent {
blockType: string;
blockId: string | null;
learningContextId: string | null;
lmsEndpointUrl: string | null;
studioEndpointUrl: string | null;
}

const Editor: React.FC<Props> = ({
learningContextId,
blockType,
blockId,
lmsEndpointUrl,
studioEndpointUrl,
onClose = null,
returnFunction = null,
}) => {
const dispatch = useDispatch();
const { lmsEndpointUrl, studioEndpointUrl } = useEditorContext();
const loading = hooks.useInitializeApp({
dispatch,
data: {
Expand Down
12 changes: 12 additions & 0 deletions src/editors/EditorContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,16 @@ export interface EditorContext {
learningContextId: string;
/** Is the so-called "Markdown" problem editor available in this learning context? */
isMarkdownEditorEnabledForContext: boolean;
/** e.g. "http://studio.local.openedx.io:8001" */
studioEndpointUrl?: string | null;
/** e.g. "http://local.openedx.io:8000" */
lmsEndpointUrl?: string | null;
}

export type EditorContextInit = {
learningContextId: string;
studioEndpointUrl?: string | null;
lmsEndpointUrl?: string | null;
};

const context = React.createContext<EditorContext | undefined>(undefined);
Expand All @@ -36,17 +42,23 @@ export function useEditorContext() {
export const EditorContextProvider: React.FC<{ children: React.ReactNode; } & EditorContextInit> = ({
children,
learningContextId,
studioEndpointUrl,
lmsEndpointUrl,
}) => {
const courseIdIfCourse = isCourseKey(learningContextId) ? learningContextId : undefined;
const isMarkdownEditorEnabledForContext = useWaffleFlags(courseIdIfCourse).useReactMarkdownEditor;

const ctx: EditorContext = React.useMemo(() => ({
learningContextId,
isMarkdownEditorEnabledForContext,
studioEndpointUrl,
lmsEndpointUrl,
}), [
// Dependencies - make sure we update the context object if any of these values change:
learningContextId,
isMarkdownEditorEnabledForContext,
studioEndpointUrl,
lmsEndpointUrl,
]);
return <context.Provider value={ctx}>{children}</context.Provider>;
};
8 changes: 5 additions & 3 deletions src/editors/EditorPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,17 @@ const EditorPage: React.FC<Props> = ({
studioEndpointUrl,
}}
>
<EditorContextProvider learningContextId={courseId}>
<EditorContextProvider
learningContextId={courseId}
studioEndpointUrl={studioEndpointUrl}
lmsEndpointUrl={lmsEndpointUrl}
>
<Editor
{...{
onClose,
learningContextId: courseId,
blockType,
blockId,
lmsEndpointUrl,
studioEndpointUrl,
returnFunction,
}}
/>
Expand Down
29 changes: 29 additions & 0 deletions src/editors/PluggableEditors.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import supportedEditors, { registerEditor } from './supportedEditors';

describe('Pluggable Editors', () => {
it('should allow registering a new editor', () => {

Check failure on line 4 in src/editors/PluggableEditors.test.tsx

View workflow job for this annotation

GitHub Actions / tests

Expected indentation of 2 spaces but found 4
const MockEditor = () => <div>Mock Editor</div>;

Check failure on line 5 in src/editors/PluggableEditors.test.tsx

View workflow job for this annotation

GitHub Actions / tests

Expected indentation of 4 spaces but found 8
const newBlockType = 'test-block-type';

Check failure on line 6 in src/editors/PluggableEditors.test.tsx

View workflow job for this annotation

GitHub Actions / tests

Expected indentation of 4 spaces but found 8

expect(supportedEditors[newBlockType]).toBeUndefined();

Check failure on line 8 in src/editors/PluggableEditors.test.tsx

View workflow job for this annotation

GitHub Actions / tests

Expected indentation of 4 spaces but found 8

registerEditor(newBlockType, MockEditor);

Check failure on line 10 in src/editors/PluggableEditors.test.tsx

View workflow job for this annotation

GitHub Actions / tests

Expected indentation of 4 spaces but found 8

expect(supportedEditors[newBlockType]).toBe(MockEditor);

Check failure on line 12 in src/editors/PluggableEditors.test.tsx

View workflow job for this annotation

GitHub Actions / tests

Expected indentation of 4 spaces but found 8
});

Check failure on line 13 in src/editors/PluggableEditors.test.tsx

View workflow job for this annotation

GitHub Actions / tests

Expected indentation of 2 spaces but found 4

it('should allow overwriting an existing editor', () => {

Check failure on line 15 in src/editors/PluggableEditors.test.tsx

View workflow job for this annotation

GitHub Actions / tests

Expected indentation of 2 spaces but found 4
const MockEditor = () => <div>New Mock Editor</div>;

Check failure on line 16 in src/editors/PluggableEditors.test.tsx

View workflow job for this annotation

GitHub Actions / tests

Expected indentation of 4 spaces but found 8
const existingBlockType = 'html'; // Assuming 'html' exists

Check failure on line 17 in src/editors/PluggableEditors.test.tsx

View workflow job for this annotation

GitHub Actions / tests

Expected indentation of 4 spaces but found 8

const originalEditor = supportedEditors[existingBlockType];
expect(originalEditor).toBeDefined();

registerEditor(existingBlockType, MockEditor);

expect(supportedEditors[existingBlockType]).toBe(MockEditor);

// Restore original editor for other tests
registerEditor(existingBlockType, originalEditor);
});
});
8 changes: 6 additions & 2 deletions src/editors/supportedEditors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@ import GameEditor from './containers/GameEditor';

import { blockTypes } from './data/constants/app';

const supportedEditors = {
const supportedEditors: Record<string, any> = {
[blockTypes.html]: TextEditor,
[blockTypes.video]: VideoEditor,
[blockTypes.problem]: ProblemEditor,
[blockTypes.video_upload]: VideoUploadEditor,
// ADDED_EDITORS GO BELOW
[blockTypes.game]: GameEditor,
} as const;
};

export const registerEditor = (blockType: string, editorComponent: any) => {
supportedEditors[blockType] = editorComponent;
};

export default supportedEditors;
Loading