Skip to content

Commit 1926631

Browse files
committed
feat: wip pdf authoring
1 parent af204c7 commit 1926631

15 files changed

Lines changed: 132 additions & 2 deletions

File tree

src/course-unit/add-component/AddComponent.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,25 @@ const AddComponent = ({
170170
showAddLibraryContentModal();
171171
break;
172172
case COMPONENT_TYPES.advanced:
173-
handleCreateNewCourseXBlock({ type: moduleName, category: moduleName, parentLocator: blockId });
173+
// TODO: The 'advanced components' concept warrants examination.
174+
// 'Advanced' is a bucket where we chuck all the blocks that are
175+
// uncommon, or third-party installs. Until now, none of these have
176+
// had special editors in this MFE. This is the first.
177+
// The fact that advanced modules are handled as a special category
178+
// *in code* and not just in UI seems like a mistake in retrospect.
179+
//
180+
// There will be more of these, and soon.
181+
switch (moduleName) {
182+
case COMPONENT_TYPES.pdf:
183+
handleCreateNewCourseXBlock({ type: moduleName, parentLocator: blockId }, ({ courseKey, locator }) => {
184+
setCourseId(courseKey);
185+
setBlockType(moduleName);
186+
setNewBlockId(locator);
187+
showXBlockEditorModal();
188+
});
189+
break;
190+
default: handleCreateNewCourseXBlock({ type: moduleName, category: moduleName, parentLocator: blockId });
191+
}
174192
break;
175193
case COMPONENT_TYPES.openassessment:
176194
handleCreateNewCourseXBlock({ boilerplate: moduleName, category: type, parentLocator: blockId });

src/editors/Editor.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const Editor: React.FC<Props> = ({
4040
});
4141

4242
const EditorComponent = supportedEditors[blockType];
43+
console.log("Component is", EditorComponent)
4344

4445
// Do not load editor until everything is initialized.
4546
if (loading) {
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import React, {useRef} from 'react';
2+
import { EditorComponent } from '@src/editors/EditorComponent';
3+
import { useIntl } from '@edx/frontend-platform/i18n';
4+
import { useDispatch, useSelector } from 'react-redux';
5+
import { EditorState, selectors } from '@src/editors/data/redux';
6+
import { RequestKeys } from '@src/editors/data/constants/requests';
7+
import {Spinner} from "@openedx/paragon";
8+
import EditorContainer from "@src/editors/containers/EditorContainer";
9+
import { ProblemEditorContextProvider } from "../ProblemEditor/components/EditProblemView/ProblemEditorContext";
10+
11+
export interface Props extends EditorComponent {}
12+
13+
/**
14+
* Renders the form with all fields to embed a PDF.
15+
*/
16+
const PdfEditor: React.FC<Props> = (props) => {
17+
const intl = useIntl();
18+
const dispatch = useDispatch();
19+
const blockFinished = useSelector((state: EditorState) => selectors.app.shouldCreateBlock(state)
20+
|| selectors.requests.isFinished(state, { requestKey: RequestKeys.fetchBlock }));
21+
22+
const blockFailed = useSelector(
23+
(state: EditorState) => selectors.requests.isFailed(state, { requestKey: RequestKeys.fetchBlock }),
24+
);
25+
// TODO: Is this necessary?
26+
const editorRef = useRef(null);
27+
if (!blockFinished) {
28+
return (
29+
<div className="text-center p-6">
30+
<Spinner
31+
animation="border"
32+
className="m-3"
33+
screenReaderText="Loading Problem Editor"
34+
/>
35+
</div>
36+
);
37+
}
38+
return (
39+
<ProblemEditorContextProvider editorRef={editorRef}>
40+
<EditorContainer {...props} isDirty={() => true} getContent={() => console.log("Content get!")}>
41+
<h1>I am the PDF Editor</h1>
42+
</EditorContainer>
43+
</ProblemEditorContextProvider>
44+
)
45+
};
46+
47+
export default PdfEditor;

src/editors/data/constants/app.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ export const blockTypes = StrictDict({
77
// ADDED_EDITORS GO BELOW
88
video_upload: 'video_upload',
99
game: 'game',
10+
pdf: 'pdf',
1011
});

src/editors/data/redux/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import * as requests from './requests';
88
import * as video from './video';
99
import * as problem from './problem';
1010
import * as game from './game';
11+
import * as pdf from './pdf';
1112
import type { RequestKeys, RequestStates } from '../constants/requests';
1213
import { AdvancedProblemType, type GradingMethodKey, ProblemType } from '../constants/problem';
1314

@@ -35,6 +36,7 @@ const actions = StrictDict({
3536
video: video.actions,
3637
problem: problem.actions,
3738
game: game.actions,
39+
pdf: pdf.selectors,
3840
});
3941

4042
const selectors = StrictDict({
@@ -43,6 +45,7 @@ const selectors = StrictDict({
4345
video: video.selectors,
4446
problem: problem.selectors,
4547
game: game.selectors,
48+
pdf: pdf.selectors,
4649
});
4750

4851
export interface EditorState {
@@ -192,6 +195,7 @@ export interface EditorState {
192195
}
193196
}
194197
},
198+
pdf: pdf.PdfState,
195199
game: {
196200
settings: Record<string, any>;
197201
exampleValue: 'this is an example value from the redux state';
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export { actions, reducer } from './reducers';
2+
export { default as selectors } from './selectors';
3+
export type { PdfState } from './types';
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { PdfState } from '@src/editors/data/redux/pdf/types';
2+
import { createSlice } from '@reduxjs/toolkit';
3+
4+
export const initialPdfState: () => PdfState = () => ({
5+
displayName: 'pdf',
6+
url: '',
7+
allowDownload: true,
8+
source_text: '',
9+
source_url: '',
10+
});
11+
12+
const pdf = createSlice({
13+
name: 'pdf',
14+
initialState: initialPdfState(),
15+
reducers: {},
16+
});
17+
18+
export const { reducer, actions } = pdf;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { pdfState } from '@src/editors/data/redux/pdf/selectors';
2+
import { initialPdfState } from '@src/editors/data/redux/pdf/reducers';
3+
import { EditorState } from '@src/editors/data/redux';
4+
5+
describe('PDF Selectors', () => {
6+
it('Selects the PDF State', () => {
7+
const state = initialPdfState();
8+
expect(pdfState({ otherValue: 'wat', pdf: state } as unknown as EditorState)).toEqual(state);
9+
});
10+
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { createSelector } from 'reselect';
2+
import type { EditorState } from '..';
3+
import { PdfState } from './types';
4+
5+
export const pdfState: (state: EditorState) => PdfState = (state: EditorState) => state.pdf;
6+
7+
const mkSimpleSelector = <T>(cb: (pdfState: EditorState['pdf']) => T) => createSelector([pdfState], cb);
8+
9+
const simpleSelectors: { [Property in keyof PdfState]: (state: EditorState) => PdfState[Property] } = {
10+
displayName: mkSimpleSelector(pdfState => pdfState.displayName),
11+
url: mkSimpleSelector(pdfState => pdfState.url),
12+
allowDownload: mkSimpleSelector(pdfState => pdfState.allowDownload),
13+
source_text: mkSimpleSelector(pdfState => pdfState.source_text),
14+
source_url: mkSimpleSelector(pdfState => pdfState.source_url),
15+
};
16+
17+
export default simpleSelectors;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export interface PdfState {
2+
displayName: string,
3+
url: string,
4+
allowDownload: boolean,
5+
source_text: string,
6+
source_url: string,
7+
}

0 commit comments

Comments
 (0)