Skip to content
This repository was archived by the owner on Feb 14, 2025. It is now read-only.

Commit 4a5eaaf

Browse files
authored
feat: setup game editor work (#363)
1 parent 7939af4 commit 4a5eaaf

File tree

8 files changed

+160
-0
lines changed

8 files changed

+160
-0
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/* eslint-disable import/extensions */
2+
/* eslint-disable import/no-unresolved */
3+
/**
4+
* This is an example component for an xblock Editor
5+
* It uses pre-existing components to handle the saving of a the result of a function into the xblock's data.
6+
* To use run npm run-script addXblock <your>
7+
*/
8+
9+
/* eslint-disable no-unused-vars */
10+
11+
import React from 'react';
12+
import { connect } from 'react-redux';
13+
import PropTypes from 'prop-types';
14+
15+
import { Spinner } from '@edx/paragon';
16+
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
17+
18+
import EditorContainer from '../EditorContainer';
19+
import * as module from '.';
20+
import { actions, selectors } from '../../data/redux';
21+
import { RequestKeys } from '../../data/constants/requests';
22+
23+
export const hooks = {
24+
getContent: () => ({
25+
some: 'content',
26+
}),
27+
};
28+
29+
export const thumbEditor = ({
30+
onClose,
31+
// redux
32+
blockValue,
33+
lmsEndpointUrl,
34+
blockFailed,
35+
blockFinished,
36+
initializeEditor,
37+
exampleValue,
38+
// inject
39+
intl,
40+
}) => (
41+
<EditorContainer
42+
getContent={module.hooks.getContent}
43+
onClose={onClose}
44+
>
45+
<div>
46+
{exampleValue}
47+
</div>
48+
<div className="editor-body h-75 overflow-auto">
49+
{!blockFinished
50+
? (
51+
<div className="text-center p-6">
52+
<Spinner
53+
animation="border"
54+
className="m-3"
55+
// Use a messages.js file for intl messages.
56+
screenreadertext={intl.formatMessage('Loading Spinner')}
57+
/>
58+
</div>
59+
)
60+
: (
61+
<p>
62+
Your Editor Goes here.
63+
You can get at the xblock data with the blockValue field.
64+
here is what is in your xblock: {JSON.stringify(blockValue)}
65+
</p>
66+
)}
67+
</div>
68+
</EditorContainer>
69+
);
70+
thumbEditor.defaultProps = {
71+
blockValue: null,
72+
lmsEndpointUrl: null,
73+
};
74+
thumbEditor.propTypes = {
75+
onClose: PropTypes.func.isRequired,
76+
// redux
77+
blockValue: PropTypes.shape({
78+
data: PropTypes.shape({ data: PropTypes.string }),
79+
}),
80+
lmsEndpointUrl: PropTypes.string,
81+
blockFailed: PropTypes.bool.isRequired,
82+
blockFinished: PropTypes.bool.isRequired,
83+
initializeEditor: PropTypes.func.isRequired,
84+
// inject
85+
intl: intlShape.isRequired,
86+
};
87+
88+
export const mapStateToProps = (state) => ({
89+
blockValue: selectors.app.blockValue(state),
90+
lmsEndpointUrl: selectors.app.lmsEndpointUrl(state),
91+
blockFailed: selectors.requests.isFailed(state, { requestKey: RequestKeys.fetchBlock }),
92+
blockFinished: selectors.requests.isFinished(state, { requestKey: RequestKeys.fetchBlock }),
93+
// TODO fill with redux state here if needed
94+
exampleValue: selectors.game.exampleValue(state),
95+
});
96+
97+
export const mapDispatchToProps = {
98+
initializeEditor: actions.app.initializeEditor,
99+
// TODO fill with dispatches here if needed
100+
};
101+
102+
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(thumbEditor));

src/editors/data/constants/app.js

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

src/editors/data/redux/game/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { actions, reducer } from './reducers';
2+
export { default as selectors } from './selectors';
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { createSlice } from '@reduxjs/toolkit';
2+
import { StrictDict } from '../../../utils';
3+
4+
const initialState = {
5+
settings: {},
6+
// TODO fill in with mock state
7+
exampleValue: 'this is an example value from the redux state',
8+
};
9+
10+
// eslint-disable-next-line no-unused-vars
11+
const game = createSlice({
12+
name: 'game',
13+
initialState,
14+
reducers: {
15+
updateField: (state, { payload }) => ({
16+
...state,
17+
...payload,
18+
}),
19+
// TODO fill in reducers
20+
},
21+
});
22+
23+
const actions = StrictDict(game.actions);
24+
25+
const { reducer } = game;
26+
27+
export {
28+
actions,
29+
initialState,
30+
reducer,
31+
};
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { createSelector } from 'reselect';
2+
import * as module from './selectors';
3+
4+
export const gameState = (state) => state.game;
5+
const mkSimpleSelector = (cb) => createSelector([module.gameState], cb);
6+
export const simpleSelectors = {
7+
exampleValue: mkSimpleSelector(gameData => gameData.exampleValue),
8+
settings: mkSimpleSelector(gameData => gameData.settings),
9+
completeState: mkSimpleSelector(gameData => gameData),
10+
// TODO fill in with selectors as needed
11+
};
12+
13+
export default {
14+
...simpleSelectors,
15+
};

src/editors/data/redux/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import * as app from './app';
66
import * as requests from './requests';
77
import * as video from './video';
88
import * as problem from './problem';
9+
import * as game from './game';
910

1011
/* eslint-disable import/no-cycle */
1112
export { default as thunkActions } from './thunkActions';
@@ -15,6 +16,7 @@ const modules = {
1516
requests,
1617
video,
1718
problem,
19+
game,
1820
};
1921

2022
const moduleProps = (propName) => Object.keys(modules).reduce(

src/editors/data/services/cms/mockApi.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ export const fetchBlockById = ({ blockId, studioEndpointUrl }) => {
5454
weight: 29,
5555
},
5656
};
57+
} else if (blockId === 'game-block-id') {
58+
data = {
59+
display_name: 'Game Block',
60+
// TODO: insert mock data from backend here
61+
};
5762
}
5863
return mockPromise({ data: { ...data } });
5964
};

src/editors/supportedEditors.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import TextEditor from './containers/TextEditor';
22
import VideoEditor from './containers/VideoEditor';
33
import ProblemEditor from './containers/ProblemEditor';
44
import VideoUploadEditor from './containers/VideoUploadEditor';
5+
import GameEditor from './containers/GameEditor';
56

67
// ADDED_EDITOR_IMPORTS GO HERE
78

@@ -13,6 +14,7 @@ const supportedEditors = {
1314
[blockTypes.problem]: ProblemEditor,
1415
[blockTypes.video_upload]: VideoUploadEditor,
1516
// ADDED_EDITORS GO BELOW
17+
[blockTypes.game]: GameEditor,
1618
};
1719

1820
export default supportedEditors;

0 commit comments

Comments
 (0)