Skip to content
Browse files

Tabbed Editor and Custom Code Mirror sizes implemented. Misc tab has …

…the odd behaviour of having all the un-rendered code mirrors instead of the ones that aren't defined in the layout. These should be avoided as they won't update the seed data on a save. Also added a nice font to the other elements
  • Loading branch information...
1 parent 76e0ea2 commit ea26946ff81386d78c76810895b5cc21c95c9115 @benmcmahon100 benmcmahon100 committed
Showing with 157 additions and 53 deletions.
  1. +73 −4 src/Components/Editor.js
  2. +66 −49 src/Components/GrandCentralStation.js
  3. +17 −0 src/style.css
  4. +1 −0 views/layout.jade
View
77 src/Components/Editor.js
@@ -3,6 +3,7 @@ import './../../node_modules/codemirror/theme/monokai.css';
import './../../node_modules/codemirror/addon/scroll/simplescrollbars.css';
import React, {Component} from 'react';
+import $ from 'jquery';
import {updateChallenge} from './../actions/editorActions';
@@ -57,6 +58,18 @@ class Editor extends Component {
return (field[0] !== 'id');
});
+ this.editorLayout = this.props.editorLayout;
+
+ let layout = {
+
+ };
+
+ for(var header in this.editorLayout){
+ layout[header] = [];
+ }
+
+ let finalHTML = [];
+
unrenderedCodeMirrors = codeMirrorData.map(function(data) {
if (Array.isArray(data[1])) {
if (data[0] === 'tests') {
@@ -75,18 +88,48 @@ class Editor extends Component {
);
});
+ for(var i = 0; i < unrenderedCodeMirrors.length; i++){
+ let unrenderedCodeMirror = unrenderedCodeMirrors[i];
+ for(var j in this.editorLayout){
+ if(this.editorLayout[j].map((head) => {return(head.name)}).indexOf(unrenderedCodeMirror.key) > -1){
+ if(layout[j].indexOf(unrenderedCodeMirror) < 0) {
+ layout[j].push(unrenderedCodeMirror);
+ }
+ }
+ else {
+ if(layout['misc'].indexOf(unrenderedCodeMirror) < 0 && layout[j].indexOf(unrenderedCodeMirror) < 0) {
+ layout['misc'].push(unrenderedCodeMirror);
+ }
+ }
+ }
+ }
+
+ for(var k in layout){
+ finalHTML.push(
+ <div className = {"tab " + k} data-tab = {k} key = {k}>
+ {layout[k]}
+ </div>
+ );
+ }
+
this.state = {
codeMirrorData: codeMirrorData,
- unrenderedCodeMirrors: unrenderedCodeMirrors
+ unrenderedCodeMirrors: finalHTML
};
}
+ toggleTabs(e) {
+ $('.tab').hide();
+ $('.' + e.target.dataset.tab).show();
+ }
+
componentDidMount() {
let codeMirrors = [];
const dispatch = this.props.dispatch;
const challengeId = this.props.challenge.id;
const activeFile = this.props.activeFile;
const challengeType = this.props.challenge.challengeType;
+ const editorLayout = this.editorLayout;
this.state.codeMirrorData.map(function(codeMirror) {
// Determine mode
@@ -108,7 +151,15 @@ class Editor extends Component {
mode = 'htmlmixed';
break;
}
+
+ let cHeader = "";
+
/* eslint-enable no-fallthrough */
+ for(var header in editorLayout){
+ if(editorLayout[header].map((field) => {return(field.name);}).indexOf(codeMirror[0]) > -1){
+ cHeader = header;
+ }
+ }
let editor = CodeMirror.fromTextArea(
document.getElementById(codeMirror[0]),
@@ -125,6 +176,10 @@ class Editor extends Component {
}
);
+ let cData = editorLayout[cHeader].filter((data) => {return(data.name === codeMirror[0]);})[0];
+
+ editor.setSize(cData.dimens[1], cData.dimens[0]);
+
editor.on('change', function(instance) {
updateChallenge(dispatch,
{
@@ -137,15 +192,29 @@ class Editor extends Component {
}
);
});
-
codeMirrors.push(editor);
});
+ $('.tab').hide();
+ $('.meta').show();
}
render() {
+ let tabButtons = [];
+ for(var tab in this.editorLayout){
+ tabButtons.push(
+ <div key = {tab} onClick = {this.toggleTabs} data-tab = {tab} className = "tabSelector">
+ {tab.split("_").join(" ")}
+ </div>
+ );
+ }
return (
- <div>
- {this.state.unrenderedCodeMirrors}
+ <div className = "editorContainer">
+ <div className = "selectors">
+ {tabButtons}
+ </div>
+ <div className = "tabContainer">
+ {this.state.unrenderedCodeMirrors}
+ </div>
</div>
);
}
View
115 src/Components/GrandCentralStation.js
@@ -57,6 +57,67 @@ class GrandCentralStation extends Component {
this.forceOpenNav = this.forceOpenNav.bind(this);
this.handleSnackbar = this.handleSnackbar.bind(this);
this.handleKeyboardSave = this.handleKeyboardSave.bind(this);
+
+ this.challengeSkeleton = {
+ id: "",
+ title: "",
+ description: [],
+ head: [],
+ challengeSeed: [],
+ tail: [],
+ solutions: [],
+ tests: [],
+ releasedOn: "",
+ type: "",
+ challengeType: 0,
+ nameCn: "",
+ descriptionCn: "",
+ nameFr: "",
+ descriptionFr: "",
+ nameRu: "",
+ descriptionRu: "",
+ nameEs: "",
+ descriptionEs: "",
+ namePt: "",
+ descriptionPt: ""
+ };
+
+ // Dimensions are given as [ Height, Width ]
+
+ this.editorLayout = {
+ meta: [
+ {name: "title", dimens: ['30px', 'auto']},
+ {name: "description", dimens: ['180px', 'auto']},
+ {name: "releasedOn", dimens: ['30px', 'auto']},
+ {name: "type", dimens: ['30px', 'auto']},
+ {name: "challengeType", dimens: ['30px', 'auto']}
+ ],
+ code: [
+ {name: "head", dimens: ['180px', 'auto']},
+ {name: "challengeSeed", dimens: ['360px', 'auto']},
+ {name: "tail", dimens: ['180px', 'auto']}
+ ],
+ test_solutions: [
+ {name: "solutions", dimens: ['240px', 'auto']},
+ {name: "tests", dimens: ['240px', 'auto']}
+ ],
+ localization: [
+ {name: "nameCn", dimens: ['30px', 'auto']},
+ {name: "descriptionCn", dimens: ['180px', 'auto']},
+ {name: "nameFr", dimens: ['30px', 'auto']},
+ {name: "descriptionFr", dimens: ['180px', 'auto']},
+ {name: "nameRu", dimens: ['30px', 'auto']},
+ {name: "descriptionRu", dimens: ['180px', 'auto']},
+ {name: "nameEs", dimens: ['30px', 'auto']},
+ {name: "descriptionEs", dimens: ['180px', 'auto']},
+ {name: "namePt", dimens: ['30px', 'auto']},
+ {name: "descriptionPt", dimens: ['180px', 'auto']}
+ ],
+ misc: [
+
+ ]
+ };
+
this.state = {
modalIsOpen: false
};
@@ -152,24 +213,7 @@ class GrandCentralStation extends Component {
newFileStoreObject = file;
newFileStoreObject.challenges = newFileStoreObject.challenges.map((challenge) => {
- return Object.assign({}, {
- id: "",
- title: "",
- description: [],
- head: [],
- challengeSeed: [],
- tail: [],
- solutions: [],
- tests: [],
- releasedOn: "",
- type: "",
- challengeType: "",
- nameCn: "",
- nameFr: "",
- nameRu: "",
- nameEs: "",
- namePt: ""
- }, challenge);
+ return Object.assign({}, this.challengeSkeleton, challenge);
});
loadFile(dispatch, {
@@ -201,37 +245,10 @@ class GrandCentralStation extends Component {
if (id === 'new') {
$.getJSON('/mongoid', function(mongoid) {
mongoid = mongoid.objectId;
- oldFileStore.challenges.push({
+ oldFileStore.challenges.push(Object.assign({}, this.challengeSkeleton, {
'id': mongoid,
- 'title': mongoid,
- 'description': [
- ''
- ],
- 'tests': [
- ''
- ],
- 'challengeSeed': [
- ''
- ],
- 'MDNlinks': [
- ''
- ],
- 'solutions': [
- ''
- ],
- 'type': '',
- 'challengeType': 0,
- 'nameCn': '',
- 'descriptionCn': [],
- 'nameFr': '',
- 'descriptionFr': [],
- 'nameRu': '',
- 'descriptionRu': [],
- 'nameEs': '',
- 'descriptionEs': [],
- 'namePt': '',
- 'descriptionPt': []
- });
+ 'title': mongoid
+ }));
let AddedChallenge = {fileStore: oldFileStore};
@@ -381,7 +398,7 @@ class GrandCentralStation extends Component {
{leftNav}
{menu}
<div style = {{ 'marginTop': '70px' }}>
- <Editor id={this.props.activeChallenge.id} />
+ <Editor editorLayout = {this.editorLayout} id={this.props.activeChallenge.id} />
</div>
</div>
{snackBar}
View
17 src/style.css
@@ -0,0 +1,17 @@
+body {
+ font-family: 'Ubuntu';
+}
+
+.selectors {
+ display: flex;
+ width: 100%;
+}
+
+.selectors > .tabSelector {
+ flex: 1 0 auto;
+ background-color: rgb(51, 51, 51);
+ color: white;
+ text-align: center;
+ margin: 4px;
+ padding: 4px;
+}
View
1 views/layout.jade
@@ -2,6 +2,7 @@ doctype html
html
head
title= title
+ link(href='https://fonts.googleapis.com/css?family=Ubuntu' rel='stylesheet' type='text/css')
body
#root
script(src = "/dist/bundle.js")

0 comments on commit ea26946

Please sign in to comment.
Something went wrong with that request. Please try again.