diff --git a/client/constants.js b/client/constants.js
index 145819a3..ce5960c3 100644
--- a/client/constants.js
+++ b/client/constants.js
@@ -30,6 +30,8 @@ export const PROJECT_SAVE_SUCCESS = 'PROJECT_SAVE_SUCCESS';
export const PROJECT_SAVE_FAIL = 'PROJECT_SAVE_FAIL';
export const NEW_PROJECT = 'NEW_PROJECT';
export const RESET_PROJECT = 'RESET_PROJECT';
+export const SHOW_EDIT_PROJECT_NAME = 'SHOW_EDIT_PROJECT_NAME';
+export const HIDE_EDIT_PROJECT_NAME = 'HIDE_EDIT_PROJECT_NAME';
export const SET_PROJECT = 'SET_PROJECT';
export const SET_PROJECTS = 'SET_PROJECTS';
diff --git a/client/modules/App/components/Overlay.js b/client/modules/App/components/Overlay.js
new file mode 100644
index 00000000..31a451c4
--- /dev/null
+++ b/client/modules/App/components/Overlay.js
@@ -0,0 +1,17 @@
+import React, { PropTypes } from 'react';
+
+function Overlay(props) {
+ return (
+
+ );
+}
+
+Overlay.propTypes = {
+ children: PropTypes.object
+};
+
+export default Overlay;
diff --git a/client/modules/IDE/actions/project.js b/client/modules/IDE/actions/project.js
index d541a49f..926b88b9 100644
--- a/client/modules/IDE/actions/project.js
+++ b/client/modules/IDE/actions/project.js
@@ -41,8 +41,7 @@ export function getProject(id) {
};
}
-export function setProjectName(event) {
- const name = event.target.textContent;
+export function setProjectName(name) {
return {
type: ActionTypes.SET_PROJECT_NAME,
name
@@ -171,3 +170,15 @@ export function cloneProject() {
};
}
+export function showEditProjectName() {
+ return {
+ type: ActionTypes.SHOW_EDIT_PROJECT_NAME
+ };
+}
+
+export function hideEditProjectName() {
+ return {
+ type: ActionTypes.HIDE_EDIT_PROJECT_NAME
+ };
+}
+
diff --git a/client/modules/IDE/actions/projects.js b/client/modules/IDE/actions/projects.js
new file mode 100644
index 00000000..d1898d77
--- /dev/null
+++ b/client/modules/IDE/actions/projects.js
@@ -0,0 +1,25 @@
+import * as ActionTypes from '../../../constants';
+import { browserHistory } from 'react-router';
+import axios from 'axios';
+
+const ROOT_URL = location.href.indexOf('localhost') > 0 ? 'http://localhost:8000/api' : '/api';
+
+export function getProjects() {
+ return (dispatch) => {
+ axios.get(`${ROOT_URL}/projects`, { withCredentials: true })
+ .then(response => {
+ dispatch({
+ type: ActionTypes.SET_PROJECTS,
+ projects: response.data
+ });
+ })
+ .catch(response => dispatch({
+ type: ActionTypes.ERROR,
+ error: response.data
+ }));
+ };
+}
+
+export function closeSketchList() {
+ browserHistory.push('/');
+}
diff --git a/client/modules/IDE/components/SidebarItem.js b/client/modules/IDE/components/SidebarItem.js
index 4d58377a..f68e0706 100644
--- a/client/modules/IDE/components/SidebarItem.js
+++ b/client/modules/IDE/components/SidebarItem.js
@@ -16,7 +16,6 @@ class SidebarItem extends React.Component {
}
handleKeyPress(event) {
- console.log(event.key);
if (event.key === 'Enter') {
this.props.hideEditFileName(this.props.file.id);
}
diff --git a/client/modules/IDE/components/SketchList.js b/client/modules/IDE/components/SketchList.js
new file mode 100644
index 00000000..5d2a759e
--- /dev/null
+++ b/client/modules/IDE/components/SketchList.js
@@ -0,0 +1,68 @@
+import React, { PropTypes } from 'react';
+import { connect } from 'react-redux';
+import { bindActionCreators } from 'redux';
+import moment from 'moment';
+import { Link } from 'react-router';
+import * as SketchActions from '../actions/projects';
+import * as ProjectActions from '../actions/project';
+import InlineSVG from 'react-inlinesvg';
+const exitUrl = require('../../../images/exit.svg');
+
+class SketchList extends React.Component {
+ componentDidMount() {
+ this.props.getProjects();
+ }
+
+ render() {
+ return (
+
+
+
+
+
+
+ Name |
+ Created |
+ Last Updated |
+
+
+
+ {this.props.sketches.map(sketch =>
+
+ {sketch.name} |
+ {moment(sketch.createdAt).format('MMM D, YYYY h:mm:ss A')} |
+ {moment(sketch.updatedAt).format('MMM D, YYYY h:mm:ss A')} |
+
+ )}
+
+
+
+
+ );
+ }
+}
+
+SketchList.propTypes = {
+ user: PropTypes.object.isRequired,
+ getProjects: PropTypes.func.isRequired,
+ sketches: PropTypes.array.isRequired,
+ closeSketchList: PropTypes.func.isRequired
+};
+
+function mapStateToProps(state) {
+ return {
+ user: state.user,
+ sketches: state.sketches
+ };
+}
+
+function mapDispatchToProps(dispatch) {
+ return bindActionCreators(Object.assign({}, SketchActions, ProjectActions), dispatch);
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(SketchList);
diff --git a/client/modules/IDE/components/TextOutput.js b/client/modules/IDE/components/TextOutput.js
index 9efee01d..949215d6 100644
--- a/client/modules/IDE/components/TextOutput.js
+++ b/client/modules/IDE/components/TextOutput.js
@@ -10,7 +10,6 @@ class TextOutput extends React.Component {
className="text-output"
id="canvas-sub"
tabIndex="0"
- role="main"
aria-label="text-output"
title="canvas text output"
>
@@ -18,23 +17,17 @@ class TextOutput extends React.Component {
-
-
-
);
diff --git a/client/modules/IDE/components/Toolbar.js b/client/modules/IDE/components/Toolbar.js
index 67400db8..0bdde6b0 100644
--- a/client/modules/IDE/components/Toolbar.js
+++ b/client/modules/IDE/components/Toolbar.js
@@ -6,67 +6,106 @@ const stopUrl = require('../../../images/stop.svg');
const preferencesUrl = require('../../../images/preferences.svg');
import classNames from 'classnames';
-function Toolbar(props) {
- let playButtonClass = classNames({
- 'toolbar__play-button': true,
- 'toolbar__play-button--selected': props.isPlaying
- });
- let stopButtonClass = classNames({
- 'toolbar__stop-button': true,
- 'toolbar__stop-button--selected': !props.isPlaying
- });
- let preferencesButtonClass = classNames({
- 'toolbar__preferences-button': true,
- 'toolbar__preferences-button--selected': props.preferencesIsVisible
- });
+class Toolbar extends React.Component {
+ constructor(props) {
+ super(props);
+ this.handleKeyPress = this.handleKeyPress.bind(this);
+ this.handleProjectNameChange = this.handleProjectNameChange.bind(this);
+ }
- return (
-
-
-
-
-
-
-
+
+
+
- {(() => { // eslint-disable-line
- if (props.owner) {
- return (
-
by {props.owner.username}
- );
- }
- })()}
+
+
+
+
+
-
-
- );
+ );
+ }
}
Toolbar.propTypes = {
@@ -77,11 +116,16 @@ Toolbar.propTypes = {
startTextOutput: PropTypes.func.isRequired,
stopTextOutput: PropTypes.func.isRequired,
setProjectName: PropTypes.func.isRequired,
- projectName: PropTypes.string.isRequired,
openPreferences: PropTypes.func.isRequired,
owner: PropTypes.shape({
username: PropTypes.string
- })
+ }),
+ project: PropTypes.shape({
+ name: PropTypes.string.isRequired,
+ isEditingName: PropTypes.bool
+ }).isRequired,
+ showEditProjectName: PropTypes.func.isRequired,
+ hideEditProjectName: PropTypes.func.isRequired
};
export default Toolbar;
diff --git a/client/modules/IDE/pages/IDEView.js b/client/modules/IDE/pages/IDEView.js
index 49489b4b..a9a6d93d 100644
--- a/client/modules/IDE/pages/IDEView.js
+++ b/client/modules/IDE/pages/IDEView.js
@@ -17,9 +17,12 @@ import * as EditorAccessibilityActions from '../actions/editorAccessibility';
import * as PreferencesActions from '../actions/preferences';
import { getFile, getHTMLFile, getJSFiles, getCSSFiles, setSelectedFile } from '../reducers/files';
import SplitPane from 'react-split-pane';
+import Overlay from '../../App/components/Overlay';
+import SketchList from '../components/SketchList';
class IDEView extends React.Component {
constructor(props) {
+ console.log(props);
super(props);
this._handleConsolePaneOnDragFinished = this._handleConsolePaneOnDragFinished.bind(this);
this._handleSidebarPaneOnDragFinished = this._handleSidebarPaneOnDragFinished.bind(this);
@@ -51,6 +54,10 @@ class IDEView extends React.Component {
if (this.props.ide.sidebarIsExpanded !== nextProps.ide.sidebarIsExpanded) {
this.sidebarSize = nextProps.ide.sidebarIsExpanded ? 180 : 20;
}
+
+ if (nextProps.params.project_id && !this.props.params.project_id) {
+ this.props.getProject(nextProps.params.project_id);
+ }
}
componentDidUpdate(prevProps) {
@@ -118,10 +125,13 @@ class IDEView extends React.Component {
stopTextOutput={this.props.stopTextOutput}
projectName={this.props.project.name}
setProjectName={this.props.setProjectName}
+ showEditProjectName={this.props.showEditProjectName}
+ hideEditProjectName={this.props.hideEditProjectName}
openPreferences={this.props.openPreferences}
preferencesIsVisible={this.props.ide.preferencesIsVisible}
setTextOutput={this.props.setTextOutput}
owner={this.props.project.owner}
+ project={this.props.project}
/>
{ // eslint-disable-line
+ if (this.props.location.pathname === '/sketches') {
+ return (
+
+
+
+ );
+ }
+ })()}
);
@@ -253,6 +272,9 @@ IDEView.propTypes = {
params: PropTypes.shape({
project_id: PropTypes.string
}),
+ location: PropTypes.shape({
+ pathname: PropTypes.string
+ }),
getProject: PropTypes.func.isRequired,
user: PropTypes.shape({
authenticated: PropTypes.bool.isRequired,
@@ -330,7 +352,9 @@ IDEView.propTypes = {
deleteFile: PropTypes.func.isRequired,
showEditFileName: PropTypes.func.isRequired,
hideEditFileName: PropTypes.func.isRequired,
- updateFileName: PropTypes.func.isRequired
+ updateFileName: PropTypes.func.isRequired,
+ showEditProjectName: PropTypes.func.isRequired,
+ hideEditProjectName: PropTypes.func.isRequired
};
function mapStateToProps(state) {
diff --git a/client/modules/IDE/reducers/project.js b/client/modules/IDE/reducers/project.js
index d50e1485..efca305b 100644
--- a/client/modules/IDE/reducers/project.js
+++ b/client/modules/IDE/reducers/project.js
@@ -22,6 +22,10 @@ const project = (state = initialState, action) => {
};
case ActionTypes.RESET_PROJECT:
return initialState;
+ case ActionTypes.SHOW_EDIT_PROJECT_NAME:
+ return Object.assign({}, state, { isEditingName: true });
+ case ActionTypes.HIDE_EDIT_PROJECT_NAME:
+ return Object.assign({}, state, { isEditingName: false });
default:
return state;
}
diff --git a/client/modules/IDE/reducers/projects.js b/client/modules/IDE/reducers/projects.js
new file mode 100644
index 00000000..b973bccc
--- /dev/null
+++ b/client/modules/IDE/reducers/projects.js
@@ -0,0 +1,12 @@
+import * as ActionTypes from '../../../constants';
+
+const sketches = (state = [], action) => {
+ switch (action.type) {
+ case ActionTypes.SET_PROJECTS:
+ return action.projects;
+ default:
+ return state;
+ }
+};
+
+export default sketches;
diff --git a/client/modules/Sketch/pages/SketchListView.js b/client/modules/Sketch/pages/SketchListView.js
index e46cab23..1f775429 100644
--- a/client/modules/Sketch/pages/SketchListView.js
+++ b/client/modules/Sketch/pages/SketchListView.js
@@ -22,24 +22,26 @@ class SketchListView extends React.Component {
exportProjectAsZip={this.props.exportProjectAsZip}
cloneProject={this.props.cloneProject}
/>
-
-
-
- Name |
- Created |
- Last Updated |
-
-
-
- {this.props.sketches.map(sketch =>
-
- {sketch.name} |
- {moment(sketch.createdAt).format('MMM D, YYYY')} |
- {moment(sketch.updatedAt).format('MMM D, YYYY')} |
+
+
+
+
+ Name |
+ Created |
+ Last Updated |
- )}
-
-
+
+
+ {this.props.sketches.map(sketch =>
+
+ {sketch.name} |
+ {moment(sketch.createdAt).format('MMM D, YYYY')} |
+ {moment(sketch.updatedAt).format('MMM D, YYYY')} |
+
+ )}
+
+
+
);
}
diff --git a/client/routes.js b/client/routes.js
index e071eb7f..356a27da 100644
--- a/client/routes.js
+++ b/client/routes.js
@@ -4,7 +4,7 @@ import App from './modules/App/App';
import IDEView from './modules/IDE/pages/IDEView';
import LoginView from './modules/User/pages/LoginView';
import SignupView from './modules/User/pages/SignupView';
-import SketchListView from './modules/Sketch/pages/SketchListView';
+// import SketchListView from './modules/Sketch/pages/SketchListView';
import { getUser } from './modules/User/actions';
const checkAuth = (store) => {
@@ -18,7 +18,7 @@ const routes = (store) =>
-
+
);
diff --git a/client/styles/components/_overlay.scss b/client/styles/components/_overlay.scss
new file mode 100644
index 00000000..3ece1be1
--- /dev/null
+++ b/client/styles/components/_overlay.scss
@@ -0,0 +1,17 @@
+.overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 9999;
+ background-color: rgba(0, 0, 0, 0.1);
+}
+
+.overlay-content {
+ height: 100%;
+ width: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
\ No newline at end of file
diff --git a/client/styles/components/_sketch-list.scss b/client/styles/components/_sketch-list.scss
index 9ef6a786..4780b12a 100644
--- a/client/styles/components/_sketch-list.scss
+++ b/client/styles/components/_sketch-list.scss
@@ -1,9 +1,25 @@
+.sketch-list__header {
+ display: flex;
+ justify-content: space-between;
+ padding: #{20 / $base-font-size}rem;
+}
+
+.sketches-table-container {
+ flex: 1 0 0%;
+ overflow-y: scroll;
+}
+
.sketches-table {
width: 100%;
padding: #{10 / $base-font-size}rem 0;
- padding-left: #{170 / $base-font-size}rem;
+ padding-left: #{20 / $base-font-size}rem;
+ height: 100%;
}
.sketches-table__row {
margin: #{10 / $base-font-size}rem;
+}
+
+.sketch-list__exit-button {
+ @extend %icon;
}
\ No newline at end of file
diff --git a/client/styles/components/_toolbar.scss b/client/styles/components/_toolbar.scss
index 2855509d..00f9e33d 100644
--- a/client/styles/components/_toolbar.scss
+++ b/client/styles/components/_toolbar.scss
@@ -57,6 +57,18 @@
&:focus {
color: $light-inactive-text-color;
}
+
+ .toolbar__project-name-container--editing & {
+ display: none;
+ }
+}
+
+.toolbar__project-name-input {
+ display: none;
+ border: 0px;
+ .toolbar__project-name-container--editing & {
+ display: block;
+ }
}
.toolbar__project-owner {
diff --git a/client/styles/layout/_sketch-list.scss b/client/styles/layout/_sketch-list.scss
index 979c48d4..7587262d 100644
--- a/client/styles/layout/_sketch-list.scss
+++ b/client/styles/layout/_sketch-list.scss
@@ -1,6 +1,8 @@
.sketch-list {
+ @extend %modal;
display: flex;
flex-wrap: wrap;
- height: 100%;
flex-flow: column;
-}
\ No newline at end of file
+ width: #{1000 / $base-font-size}rem;
+ height: #{700 / $base-font-size}rem;
+}
diff --git a/client/styles/main.scss b/client/styles/main.scss
index 7a565c25..3b3a79a3 100644
--- a/client/styles/main.scss
+++ b/client/styles/main.scss
@@ -20,6 +20,7 @@
@import 'components/modal';
@import 'components/console';
@import 'components/resizer';
+@import 'components/overlay';
@import 'layout/ide';
@import 'layout/sketch-list';
diff --git a/static/interceptor-functions.js b/static/interceptor-functions.js
index b20330a0..3c4d52fe 100644
--- a/static/interceptor-functions.js
+++ b/static/interceptor-functions.js
@@ -188,7 +188,7 @@ var Interceptor = {
if(!(typeof(arguments[i])).localeCompare('number')){
arguments[i] = round(arguments[i]);
}
- objectArray[objectCount][x.params[i].description]=arguments[i];
+ objectArray[objectCount][x.params[i].description.slice(3,-5)]=arguments[i];
}
if(objectTypeCount[x.name]) {
objectTypeCount[x.name]++;
@@ -215,7 +215,7 @@ var Interceptor = {
var tempCol = row.children.length;
var properties = Object.keys(objectArray[j]);
- if(tempCol