Skip to content

Commit 804b206

Browse files
authored
Merge pull request #20 from Robinsstudio/studentView
Répondre à un QCM
2 parents 510f8ec + 8d70849 commit 804b206

9 files changed

Lines changed: 4509 additions & 7269 deletions

File tree

package-lock.json

Lines changed: 4105 additions & 7139 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
"react": "^16.7.0",
99
"react-codemirror": "^1.0.0",
1010
"react-dom": "^16.7.0",
11-
"react-scripts": "^2.1.5",
11+
"react-markdown": "^4.0.8",
12+
"react-router-dom": "^5.0.0",
13+
"react-scripts": "^3.0.1",
14+
"react-syntax-highlighter": "^10.2.1",
1215
"reactstrap": "^7.1.0"
1316
},
1417
"scripts": {

src/AdminView.js

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import React, { Component } from 'react';
2+
import ExplorerView from './ExplorerView';
3+
import Editor from './Editor';
4+
import request from './request';
5+
6+
class AdminView extends Component {
7+
constructor(props) {
8+
super(props);
9+
this.state = {
10+
tags: [],
11+
files: [],
12+
folder: {
13+
path: [],
14+
active: {}
15+
},
16+
editor: {
17+
visible: false,
18+
questions: [],
19+
model: {
20+
questions: []
21+
}
22+
}
23+
};
24+
25+
this.requestFolder = this.requestFolder.bind(this);
26+
this.searchByTags = this.searchByTags.bind(this);
27+
this.create = this.create.bind(this);
28+
this.edit = this.edit.bind(this);
29+
this.save = this.save.bind(this);
30+
this.closeEditor = this.closeEditor.bind(this);
31+
this.updateEditor = this.updateEditor.bind(this);
32+
this.refreshEditor = this.refreshEditor.bind(this);
33+
this.refresh = this.refresh.bind(this);
34+
}
35+
36+
requestFolder(_id) {
37+
this.setState({ tags: [] });
38+
request('ListFolder', { _id }).then(res => res.json()).then(({folder, files}) => {
39+
this.setState({ folder, files });
40+
});
41+
}
42+
43+
searchByTags(tags) {
44+
if (tags.length) {
45+
this.setState({ tags });
46+
request('GetQuestionsByTags', { tags, idParent: this.state.folder.active._id }).then(res => res.json()).then(files => {
47+
this.setState({ files });
48+
});
49+
} else {
50+
this.refresh();
51+
}
52+
}
53+
54+
create() {
55+
this.setState({
56+
editor: {
57+
visible: true,
58+
questions: [],
59+
model: {
60+
questions: []
61+
}
62+
}
63+
});
64+
}
65+
66+
edit(model) {
67+
request('GetQuestionsByIds', { _ids: model.questions.map(quest => quest.idQuestion) }).then(res => res.json()).then(questions => {
68+
this.setState({
69+
editor: {
70+
visible: true,
71+
model,
72+
questions
73+
}
74+
});
75+
});
76+
}
77+
78+
updateEditor(editor) {
79+
this.setState({ editor });
80+
}
81+
82+
save(name) {
83+
const { editor, folder } = this.state;
84+
const idParent = editor.model.idParent || folder.active._id;
85+
86+
request('SaveMultipleChoice', { ...editor.model, idParent, name, questions: editor.questions.map(quest => {
87+
return { idQuestion: quest._id };
88+
}) }).then(this.closeEditor).then(this.refresh);
89+
}
90+
91+
closeEditor() {
92+
this.setState((state) => {
93+
return { editor: { ...state.editor, visible: false } };
94+
});
95+
}
96+
97+
refreshEditor() {
98+
const { editor } = this.state;
99+
request('GetQuestionsByIds', { _ids: editor.questions.map(quest => quest._id) }).then(res => res.json()).then(questions => {
100+
this.setState(state => {
101+
return {
102+
editor: {
103+
...state.editor,
104+
questions
105+
}
106+
};
107+
});
108+
});
109+
}
110+
111+
refresh() {
112+
const { editor, folder } = this.state;
113+
if (editor.visible) {
114+
this.refreshEditor();
115+
}
116+
this.requestFolder(folder.active._id);
117+
}
118+
119+
render() {
120+
const { folder, files, tags, editor } = this.state;
121+
return (
122+
<div id="app">
123+
<ExplorerView editing={editor.visible} folder={folder} files={files} tags={tags}
124+
requestFolder={this.requestFolder} searchByTags={this.searchByTags}
125+
create={this.create} edit={this.edit} refresh={this.refresh}/>
126+
127+
<Editor editor={editor} folder={folder} update={this.updateEditor} save={this.save} closeEditor={this.closeEditor}/>
128+
</div>
129+
);
130+
}
131+
}
132+
133+
export default AdminView;

src/App.js

Lines changed: 12 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,133 +1,21 @@
1-
import React, { Component } from 'react';
2-
import ExplorerView from './ExplorerView';
3-
import Editor from './Editor';
1+
import React, { Component, Fragment } from 'react';
2+
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
3+
import AdminView from './AdminView';
4+
import StudentView from './StudentView';
45
import Modals from './Modals';
5-
import request from './request';
66

77
class App extends Component {
8-
constructor(props) {
9-
super(props);
10-
this.state = {
11-
tags: [],
12-
files: [],
13-
folder: {
14-
path: [],
15-
active: {}
16-
},
17-
editor: {
18-
visible: false,
19-
questions: [],
20-
model: {
21-
questions: []
22-
}
23-
}
24-
};
25-
26-
this.requestFolder = this.requestFolder.bind(this);
27-
this.searchByTags = this.searchByTags.bind(this);
28-
this.create = this.create.bind(this);
29-
this.edit = this.edit.bind(this);
30-
this.save = this.save.bind(this);
31-
this.closeEditor = this.closeEditor.bind(this);
32-
this.updateEditor = this.updateEditor.bind(this);
33-
this.refreshEditor = this.refreshEditor.bind(this);
34-
this.refresh = this.refresh.bind(this);
35-
}
36-
37-
requestFolder(_id) {
38-
this.setState({ tags: [] });
39-
request('ListFolder', { _id }).then(res => res.json()).then(({folder, files}) => {
40-
this.setState({ folder, files });
41-
});
42-
}
43-
44-
searchByTags(tags) {
45-
if (tags.length) {
46-
this.setState({ tags });
47-
request('GetQuestionsByTags', { tags, idParent: this.state.folder.active._id }).then(res => res.json()).then(files => {
48-
this.setState({ files });
49-
});
50-
} else {
51-
this.refresh();
52-
}
53-
}
54-
55-
create() {
56-
this.setState({
57-
editor: {
58-
visible: true,
59-
questions: [],
60-
model: {
61-
questions: []
62-
}
63-
}
64-
});
65-
}
66-
67-
edit(model) {
68-
request('GetQuestionsByIds', { _ids: model.questions.map(quest => quest.idQuestion) }).then(res => res.json()).then(questions => {
69-
this.setState({
70-
editor: {
71-
visible: true,
72-
model,
73-
questions
74-
}
75-
});
76-
});
77-
}
78-
79-
updateEditor(editor) {
80-
this.setState({ editor });
81-
}
82-
83-
save(name) {
84-
const { editor, folder } = this.state;
85-
const idParent = editor.model.idParent || folder.active._id;
86-
87-
request('SaveMultipleChoice', { ...editor.model, idParent, name, questions: editor.questions.map(quest => {
88-
return { idQuestion: quest._id };
89-
}) }).then(this.closeEditor).then(this.refresh);
90-
}
91-
92-
closeEditor() {
93-
this.setState((state) => {
94-
return { editor: { ...state.editor, visible: false } };
95-
});
96-
}
97-
98-
refreshEditor() {
99-
const { editor } = this.state;
100-
request('GetQuestionsByIds', { _ids: editor.questions.map(quest => quest._id) }).then(res => res.json()).then(questions => {
101-
this.setState(state => {
102-
return {
103-
editor: {
104-
...state.editor,
105-
questions
106-
}
107-
};
108-
});
109-
});
110-
}
111-
112-
refresh() {
113-
const { editor, folder } = this.state;
114-
if (editor.visible) {
115-
this.refreshEditor();
116-
}
117-
this.requestFolder(folder.active._id);
118-
}
119-
1208
render() {
121-
const { folder, files, tags, editor } = this.state;
1229
return (
123-
<div id="app">
124-
<ExplorerView editing={editor.visible} folder={folder} files={files} tags={tags}
125-
requestFolder={this.requestFolder} searchByTags={this.searchByTags}
126-
create={this.create} edit={this.edit} refresh={this.refresh}/>
127-
128-
<Editor editor={editor} folder={folder} update={this.updateEditor} save={this.save} closeEditor={this.closeEditor}/>
10+
<Fragment>
11+
<Router>
12+
<Switch>
13+
<Route path="/qcm/:url" component={StudentView}/>
14+
<Route path="/" component={AdminView}/>
15+
</Switch>
16+
</Router>
12917
{Modals.get()}
130-
</div>
18+
</Fragment>
13119
);
13220
}
13321
}

src/CodeRenderer.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React, { PureComponent } from 'react';
2+
import SyntaxHighlighter from 'react-syntax-highlighter';
3+
import { googlecode } from 'react-syntax-highlighter/dist/styles/hljs';
4+
5+
class CodeRenderer extends PureComponent {
6+
render() {
7+
const { language, value } = this.props;
8+
return (
9+
<SyntaxHighlighter language={language} style={googlecode}>
10+
{value}
11+
</SyntaxHighlighter>
12+
);
13+
}
14+
}
15+
16+
export default CodeRenderer;

src/File.js

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,39 @@ class File extends Component {
5151
this.setState({ renaming: false });
5252
}
5353

54+
copyToClipboard(value) {
55+
const hiddenElement = document.createElement('input');
56+
hiddenElement.style.background = 'transparent';
57+
hiddenElement.value = value;
58+
59+
document.body.appendChild(hiddenElement);
60+
hiddenElement.select();
61+
document.execCommand('copy');
62+
document.body.removeChild(hiddenElement);
63+
}
64+
5465
handleContextMenu(event) {
55-
const { name } = this.props.file;
56-
this.props.handleContextMenu(event, [
66+
const { file: { name, type, url, _id }, refresh } = this.props;
67+
68+
const multipleChoiceItem = url ? {
69+
label: 'Copier le lien partageable',
70+
onClick: () => this.copyToClipboard(`${window.location.href}qcm/${url}`)
71+
} : {
72+
label: 'Générer un lien partageable',
73+
onClick: () => request('/GenerateLink', { _id }).then(() => refresh())
74+
};
75+
76+
const menuItems = [
5777
{ label: 'Ouvrir', onClick: this.open },
5878
{ label: 'Renommer', onClick: this.startRenaming },
59-
{ label: 'Supprimer', onClick: () => Modals.showConfirmModal('Supprimer', `Voulez-vous vraiment supprimer ${name} ?`).then(this.remove).catch(() => {}) }
60-
]);
79+
{
80+
label: 'Supprimer',
81+
onClick: () => Modals.showConfirmModal('Supprimer', `Voulez-vous vraiment supprimer ${name} ?`)
82+
.then(this.remove).catch(() => {})
83+
}
84+
].concat(type === 'qcm' ? multipleChoiceItem : []);
85+
86+
this.props.handleContextMenu(event, menuItems);
6187
}
6288

6389
handleDragStart(event) {

0 commit comments

Comments
 (0)