es6 classes for React; closes #112
This commit is contained in:
parent
b57bc76edd
commit
c3896a3598
6
.babelrc
6
.babelrc
|
@ -1,3 +1,7 @@
|
||||||
{
|
{
|
||||||
"presets": [ "react", "es2015" ]
|
"presets": [
|
||||||
|
"react",
|
||||||
|
"es2015",
|
||||||
|
"stage-0"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "burnchart",
|
"name": "burnchart",
|
||||||
"version": "3.2.1",
|
"version": "3.2.2",
|
||||||
"description": "GitHub Burndown Chart as a Service",
|
"description": "GitHub Burndown Chart as a Service",
|
||||||
"author": "Radek Stepan <dev@radekstepan.com> (http://radekstepan.com)",
|
"author": "Radek Stepan <dev@radekstepan.com> (http://radekstepan.com)",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
|
@ -21,6 +21,7 @@
|
||||||
"babel": "^6.3.26",
|
"babel": "^6.3.26",
|
||||||
"babel-preset-es2015": "^6.3.13",
|
"babel-preset-es2015": "^6.3.13",
|
||||||
"babel-preset-react": "^6.3.13",
|
"babel-preset-react": "^6.3.13",
|
||||||
|
"babel-preset-stage-0": "^6.5.0",
|
||||||
"babel-register": "^6.4.3",
|
"babel-register": "^6.4.3",
|
||||||
"babelify": "^7.2.0",
|
"babelify": "^7.2.0",
|
||||||
"browserify": "^13.0.0",
|
"browserify": "^13.0.0",
|
||||||
|
|
|
@ -1060,5 +1060,5 @@ ul li {
|
||||||
color: #C1041C;
|
color: #C1041C;
|
||||||
}
|
}
|
||||||
#app.theme--monza #page #content #projects table tr td.action {
|
#app.theme--monza #page #content #projects table tr td.action {
|
||||||
background: #760211;
|
color: #760211;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -27,8 +27,8 @@ export default {
|
||||||
},
|
},
|
||||||
// Request pertaining.
|
// Request pertaining.
|
||||||
"request": {
|
"request": {
|
||||||
// Default timeout of 5s.
|
// Default timeout of 10s.
|
||||||
"timeout": 5e3
|
"timeout": 1e4
|
||||||
},
|
},
|
||||||
// The app theme; 'monza' is the default red theme.
|
// The app theme; 'monza' is the default red theme.
|
||||||
"theme": "monza"
|
"theme": "monza"
|
||||||
|
|
|
@ -8,33 +8,42 @@ import actions from '../actions/appActions.js';
|
||||||
import Icon from './Icon.jsx';
|
import Icon from './Icon.jsx';
|
||||||
import S from './Space.jsx';
|
import S from './Space.jsx';
|
||||||
|
|
||||||
export default React.createClass({
|
export default class AddProjectForm extends React.Component {
|
||||||
|
|
||||||
displayName: 'AddProjectForm.jsx',
|
displayName: 'AddProjectForm.jsx'
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
// Blank input.
|
||||||
|
this.state = { 'val': '' };
|
||||||
|
// Bindings.
|
||||||
|
this._onChange = this._onChange.bind(this);
|
||||||
|
this._onAdd = this._onAdd.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
// Sign user in.
|
// Sign user in.
|
||||||
_onSignIn() {
|
_onSignIn() {
|
||||||
actions.emit('user.signin');
|
actions.emit('user.signin');
|
||||||
},
|
}
|
||||||
|
|
||||||
_onChange(evt, { newValue }) {
|
_onChange(evt, { newValue }) {
|
||||||
this.setState({ 'val': newValue });
|
this.setState({ 'val': newValue });
|
||||||
},
|
}
|
||||||
|
|
||||||
// Get a list of repo suggestions.
|
// Get a list of repo suggestions.
|
||||||
_onGetList({ value }) {
|
_onGetList({ value }) {
|
||||||
actions.emit('projects.search', value);
|
actions.emit('projects.search', value);
|
||||||
},
|
}
|
||||||
|
|
||||||
// What should be the value of the suggestion.
|
// What should be the value of the suggestion.
|
||||||
_getListValue(value) {
|
_getListValue(value) {
|
||||||
return value;
|
return value;
|
||||||
},
|
}
|
||||||
|
|
||||||
// How do we render the repo?
|
// How do we render the repo?
|
||||||
_renderListValue(value) {
|
_renderListValue(value) {
|
||||||
return value;
|
return value;
|
||||||
},
|
}
|
||||||
|
|
||||||
// Add the project.
|
// Add the project.
|
||||||
_onAdd() {
|
_onAdd() {
|
||||||
|
@ -46,12 +55,7 @@ export default React.createClass({
|
||||||
actions.emit('projects.add', { owner, name });
|
actions.emit('projects.add', { owner, name });
|
||||||
// Redirect to the dashboard.
|
// Redirect to the dashboard.
|
||||||
App.navigate({ 'to': 'projects' });
|
App.navigate({ 'to': 'projects' });
|
||||||
},
|
}
|
||||||
|
|
||||||
// Blank input.
|
|
||||||
getInitialState() {
|
|
||||||
return { 'val': '' };
|
|
||||||
},
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let user;
|
let user;
|
||||||
|
@ -106,11 +110,6 @@ export default React.createClass({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
|
||||||
|
|
||||||
// Focus input field on mount.
|
|
||||||
componentDidMount() {
|
|
||||||
if ('el' in this.refs) this.refs.el.focus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
|
|
@ -7,13 +7,17 @@ d3Tip(d3);
|
||||||
import lines from '../modules/chart/lines.js';
|
import lines from '../modules/chart/lines.js';
|
||||||
import axes from '../modules/chart/axes.js';
|
import axes from '../modules/chart/axes.js';
|
||||||
|
|
||||||
export default React.createClass({
|
export default class Chart extends React.Component {
|
||||||
|
|
||||||
displayName: 'Chart.jsx',
|
displayName: 'Chart.jsx'
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <div id="chart" ref="el" style={this.props.style} />;
|
return <div id="chart" ref="el" style={this.props.style} />;
|
||||||
},
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
let { data } = this.props;
|
let { data } = this.props;
|
||||||
|
@ -154,4 +158,4 @@ export default React.createClass({
|
||||||
.on('mouseout', tooltip.hide);
|
.on('mouseout', tooltip.hide);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
|
|
@ -7,13 +7,17 @@ import actions from '../actions/appActions.js';
|
||||||
import Icon from './Icon.jsx';
|
import Icon from './Icon.jsx';
|
||||||
import Link from './Link.jsx';
|
import Link from './Link.jsx';
|
||||||
|
|
||||||
export default React.createClass({
|
export default class EditProjects extends React.Component {
|
||||||
|
|
||||||
displayName: 'EditProjects.jsx',
|
displayName: 'EditProjects.jsx'
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
_onDelete(project) {
|
_onDelete(project) {
|
||||||
actions.emit('projects.delete', project);
|
actions.emit('projects.delete', project);
|
||||||
},
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let { projects } = this.props;
|
let { projects } = this.props;
|
||||||
|
@ -55,4 +59,4 @@ export default React.createClass({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
export default React.createClass({
|
export default class Footer extends React.Component {
|
||||||
|
|
||||||
displayName: 'Footer.jsx',
|
displayName: 'Footer.jsx'
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
|
@ -14,4 +18,4 @@ export default React.createClass({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
|
|
@ -6,24 +6,28 @@ import Notify from './Notify.jsx';
|
||||||
import Icon from './Icon.jsx';
|
import Icon from './Icon.jsx';
|
||||||
import Link from './Link.jsx';
|
import Link from './Link.jsx';
|
||||||
|
|
||||||
export default React.createClass({
|
export default class Header extends React.Component {
|
||||||
|
|
||||||
displayName: 'Header.jsx',
|
displayName: 'Header.jsx'
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
// Sign user in.
|
// Sign user in.
|
||||||
_onSignIn() {
|
_onSignIn() {
|
||||||
actions.emit('user.signin');
|
actions.emit('user.signin');
|
||||||
},
|
}
|
||||||
|
|
||||||
// Sign user out.
|
// Sign user out.
|
||||||
_onSignOut() {
|
_onSignOut() {
|
||||||
actions.emit('user.signout');
|
actions.emit('user.signout');
|
||||||
},
|
}
|
||||||
|
|
||||||
// Add example projects.
|
// Add example projects.
|
||||||
_onDemo() {
|
_onDemo() {
|
||||||
actions.emit('projects.demo');
|
actions.emit('projects.demo');
|
||||||
},
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
// From app store.
|
// From app store.
|
||||||
|
@ -79,4 +83,4 @@ export default React.createClass({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
|
|
@ -5,14 +5,18 @@ import actions from '../actions/appActions.js';
|
||||||
import Icon from './Icon.jsx';
|
import Icon from './Icon.jsx';
|
||||||
import Link from './Link.jsx';
|
import Link from './Link.jsx';
|
||||||
|
|
||||||
export default React.createClass({
|
export default class Hero extends React.Component {
|
||||||
|
|
||||||
displayName: 'Hero.jsx',
|
displayName: 'Hero.jsx'
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
// Add example projects.
|
// Add example projects.
|
||||||
_onDemo() {
|
_onDemo() {
|
||||||
actions.emit('projects.demo');
|
actions.emit('projects.demo');
|
||||||
},
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
|
@ -35,4 +39,4 @@ export default React.createClass({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import React from 'react';
|
||||||
import format from '../modules/format.js';
|
import format from '../modules/format.js';
|
||||||
|
|
||||||
// Fontello icon hex codes.
|
// Fontello icon hex codes.
|
||||||
let codes = {
|
const codes = {
|
||||||
'delete': '\e800', // Font Awesome - trash-empty
|
'delete': '\e800', // Font Awesome - trash-empty
|
||||||
'settings': '\e801', // Font Awesome - cog
|
'settings': '\e801', // Font Awesome - cog
|
||||||
'pencil': '\e802', // Font Awesome - pencil
|
'pencil': '\e802', // Font Awesome - pencil
|
||||||
|
@ -23,15 +23,19 @@ let codes = {
|
||||||
'fire': '\e810' // Maki - fire-station
|
'fire': '\e810' // Maki - fire-station
|
||||||
};
|
};
|
||||||
|
|
||||||
export default React.createClass({
|
export default class Icon extends React.Component {
|
||||||
|
|
||||||
displayName: 'Icon.jsx',
|
displayName: 'Icon.jsx'
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let name = this.props.name;
|
const name = this.props.name;
|
||||||
|
|
||||||
if (name && name in codes) {
|
if (name && name in codes) {
|
||||||
let code = format.hexToDec(codes[name]);
|
const code = format.hexToDec(codes[name]);
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
className={`icon ${name}`}
|
className={`icon ${name}`}
|
||||||
|
@ -43,4 +47,4 @@ export default React.createClass({
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
|
|
@ -2,15 +2,19 @@ import React from 'react';
|
||||||
|
|
||||||
import App from '../App.jsx';
|
import App from '../App.jsx';
|
||||||
|
|
||||||
export default React.createClass({
|
export default class Link extends React.Component {
|
||||||
|
|
||||||
displayName: 'Link.jsx',
|
displayName: 'Link.jsx'
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
// Navigate to a route.
|
// Navigate to a route.
|
||||||
_navigate(link, evt) {
|
_navigate(link, evt) {
|
||||||
App.navigate(link);
|
App.navigate(link);
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
},
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let route = this.props.route;
|
let route = this.props.route;
|
||||||
|
@ -27,4 +31,4 @@ export default React.createClass({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
|
|
@ -9,14 +9,18 @@ import actions from '../actions/appActions.js';
|
||||||
import Icon from './Icon.jsx';
|
import Icon from './Icon.jsx';
|
||||||
import Link from './Link.jsx';
|
import Link from './Link.jsx';
|
||||||
|
|
||||||
export default React.createClass({
|
export default class Milestones extends React.Component {
|
||||||
|
|
||||||
displayName: 'Milestones.jsx',
|
displayName: 'Milestones.jsx'
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
// Cycle through milestones sort order.
|
// Cycle through milestones sort order.
|
||||||
_onSort() {
|
_onSort() {
|
||||||
actions.emit('projects.sort');
|
actions.emit('projects.sort');
|
||||||
},
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let { projects, project } = this.props;
|
let { projects, project } = this.props;
|
||||||
|
@ -119,4 +123,4 @@ export default React.createClass({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
|
|
@ -5,17 +5,14 @@ import actions from '../actions/appActions.js';
|
||||||
|
|
||||||
import Icon from './Icon.jsx';
|
import Icon from './Icon.jsx';
|
||||||
|
|
||||||
let Notify = React.createClass({
|
class Notify extends React.Component {
|
||||||
|
|
||||||
displayName: 'Notify.jsx',
|
displayName: 'Notify.jsx'
|
||||||
|
|
||||||
// Close notification.
|
constructor(props) {
|
||||||
_onClose() {
|
super(props);
|
||||||
actions.emit('system.notify');
|
|
||||||
},
|
|
||||||
|
|
||||||
getDefaultProps() {
|
this.props = {
|
||||||
return {
|
|
||||||
// No text.
|
// No text.
|
||||||
'text': null,
|
'text': null,
|
||||||
// Grey style.
|
// Grey style.
|
||||||
|
@ -25,7 +22,12 @@ let Notify = React.createClass({
|
||||||
// Just announcing.
|
// Just announcing.
|
||||||
'icon': 'megaphone'
|
'icon': 'megaphone'
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
|
|
||||||
|
// Close notification.
|
||||||
|
_onClose() {
|
||||||
|
actions.emit('system.notify');
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let { text, system, type, icon, ttl } = this.props;
|
let { text, system, type, icon, ttl } = this.props;
|
||||||
|
@ -51,9 +53,9 @@ let Notify = React.createClass({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
|
||||||
export default React.createClass({
|
export default class NotifyWrapper extends React.Component {
|
||||||
|
|
||||||
// TODO: animate in
|
// TODO: animate in
|
||||||
render() {
|
render() {
|
||||||
|
@ -73,4 +75,4 @@ export default React.createClass({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
// Inserts a space before rendering text.
|
// Inserts a space before rendering text.
|
||||||
export default React.createClass({
|
export default class Space extends React.Component {
|
||||||
|
|
||||||
displayName: 'Space.jsx',
|
displayName: 'Space.jsx'
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <span> </span>;
|
return <span> </span>;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
|
|
@ -2,18 +2,20 @@ import React from 'react';
|
||||||
|
|
||||||
import actions from '../../actions/appActions.js';
|
import actions from '../../actions/appActions.js';
|
||||||
|
|
||||||
import Page from '../../lib/PageMixin.js';
|
import Page from '../../lib/PageClass.js';
|
||||||
|
|
||||||
import Notify from '../Notify.jsx';
|
import Notify from '../Notify.jsx';
|
||||||
import Header from '../Header.jsx';
|
import Header from '../Header.jsx';
|
||||||
import Footer from '../Footer.jsx';
|
import Footer from '../Footer.jsx';
|
||||||
import AddProjectForm from '../AddProjectForm.jsx';
|
import AddProjectForm from '../AddProjectForm.jsx';
|
||||||
|
|
||||||
export default React.createClass({
|
export default class AddProjectPage extends Page {
|
||||||
|
|
||||||
displayName: 'AddProjectPage.jsx',
|
displayName: 'AddProjectPage.jsx'
|
||||||
|
|
||||||
mixins: [ Page ],
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
|
@ -35,4 +37,4 @@ export default React.createClass({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
import Page from '../../lib/PageMixin.js';
|
import Page from '../../lib/PageClass.js';
|
||||||
|
|
||||||
import format from '../../modules/format.js';
|
import format from '../../modules/format.js';
|
||||||
|
|
||||||
|
@ -10,11 +10,13 @@ import Header from '../Header.jsx';
|
||||||
import Footer from '../Footer.jsx';
|
import Footer from '../Footer.jsx';
|
||||||
import Chart from '../Chart.jsx';
|
import Chart from '../Chart.jsx';
|
||||||
|
|
||||||
export default React.createClass({
|
export default class ChartPage extends Page {
|
||||||
|
|
||||||
displayName: 'ChartPage.jsx',
|
displayName: 'ChartPage.jsx'
|
||||||
|
|
||||||
mixins: [ Page ],
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let content;
|
let content;
|
||||||
|
@ -70,4 +72,4 @@ export default React.createClass({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
import Page from '../../lib/PageMixin.js';
|
import Page from '../../lib/PageClass.js';
|
||||||
|
|
||||||
import Notify from '../Notify.jsx';
|
import Notify from '../Notify.jsx';
|
||||||
import Header from '../Header.jsx';
|
import Header from '../Header.jsx';
|
||||||
|
@ -9,17 +9,18 @@ import Footer from '../Footer.jsx';
|
||||||
import Milestones from '../Milestones.jsx';
|
import Milestones from '../Milestones.jsx';
|
||||||
import Chart from '../Chart.jsx';
|
import Chart from '../Chart.jsx';
|
||||||
|
|
||||||
export default React.createClass({
|
export default class MilestonePage extends Page {
|
||||||
|
|
||||||
displayName: 'MilestonesPage.jsx',
|
displayName: 'MilestonesPage.jsx'
|
||||||
|
|
||||||
mixins: [ Page ],
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let content;
|
let content;
|
||||||
if (!this.state.app.system.loading) {
|
if (!this.state.app.system.loading) {
|
||||||
let projects = this.state.projects;
|
let projects = this.state.projects;
|
||||||
|
|
||||||
// Create the all milestones payload.
|
// Create the all milestones payload.
|
||||||
let data;
|
let data;
|
||||||
_.find(projects.list, (obj) => {
|
_.find(projects.list, (obj) => {
|
||||||
|
@ -83,4 +84,4 @@ export default React.createClass({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import Page from '../../lib/PageMixin.js';
|
import Page from '../../lib/PageClass.js';
|
||||||
|
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
export default React.createClass({
|
export default class NotFoundPage extends Page {
|
||||||
|
|
||||||
displayName: 'NotFoundPage.jsx',
|
displayName: 'NotFoundPage.jsx'
|
||||||
|
|
||||||
mixins: [ Page ],
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <div>Page {this.props.path} not found</div>;
|
return <div>Page {this.props.path} not found</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
import Page from '../../lib/PageMixin.js';
|
import Page from '../../lib/PageClass.js';
|
||||||
|
|
||||||
import Notify from '../Notify.jsx';
|
import Notify from '../Notify.jsx';
|
||||||
import Header from '../Header.jsx';
|
import Header from '../Header.jsx';
|
||||||
|
@ -9,23 +10,23 @@ import Milestones from '../Milestones.jsx';
|
||||||
import EditProjects from '../EditProjects.jsx';
|
import EditProjects from '../EditProjects.jsx';
|
||||||
import Hero from '../Hero.jsx';
|
import Hero from '../Hero.jsx';
|
||||||
|
|
||||||
export default React.createClass({
|
export default class ProjectsPage extends Page {
|
||||||
|
|
||||||
displayName: 'ProjectsPage.jsx',
|
displayName: 'ProjectsPage.jsx'
|
||||||
|
|
||||||
mixins: [ Page ],
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
// Start the page in a view mode.
|
||||||
|
// NOTE probably move into its own component so we don't merge state.
|
||||||
|
_.merge(this.state, { 'edit': false });
|
||||||
|
// Bindings.
|
||||||
|
this._onToggleMode = this._onToggleMode.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
// Toggle between edit and view mode.
|
// Toggle between edit and view mode.
|
||||||
_onToggleMode() {
|
_onToggleMode() {
|
||||||
this.setState({ 'edit': !this.state.edit });
|
this.setState({ 'edit': !this.state.edit });
|
||||||
},
|
}
|
||||||
|
|
||||||
getInitialState() {
|
|
||||||
return {
|
|
||||||
// Start the page in a view mode.
|
|
||||||
'edit': false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let content;
|
let content;
|
||||||
|
@ -66,4 +67,4 @@ export default React.createClass({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
|
|
@ -21,12 +21,12 @@ export default class EventEmitter {
|
||||||
// Add a listener on this path/regex.
|
// Add a listener on this path/regex.
|
||||||
on(path, cb) {
|
on(path, cb) {
|
||||||
if (!_.isRegExp(path)) path = new RegExp(`^${path}$`);
|
if (!_.isRegExp(path)) path = new RegExp(`^${path}$`);
|
||||||
this.list.push({ pattern: path, cb: cb });
|
this.list.push({ 'pattern': path, cb: cb });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a listener to all events.
|
// Add a listener to all events.
|
||||||
onAny(cb) {
|
onAny(cb) {
|
||||||
this.list.push({ pattern: /./, cb: cb });
|
this.list.push({ 'pattern': /./, cb: cb });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assume we can have multiple.
|
// Assume we can have multiple.
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
import React from 'react';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
import stores from '../stores';
|
||||||
|
|
||||||
|
export default class Page extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
// State contains our store data.
|
||||||
|
// NOTE top-level page components shouldn't modify the state.
|
||||||
|
this.state = this._getData();
|
||||||
|
// Bindings.
|
||||||
|
this._onChange = this._onChange.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the POJO of the store.
|
||||||
|
_getData(store) {
|
||||||
|
let obj = {};
|
||||||
|
if (store) {
|
||||||
|
obj[store] = stores[store].get();
|
||||||
|
} else {
|
||||||
|
// Get all stores.
|
||||||
|
for (let key in stores) {
|
||||||
|
obj[key] = stores[key].get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the state when store changes.
|
||||||
|
_onChange(store, val, key) {
|
||||||
|
if (!this._isMounted) return;
|
||||||
|
this.setState(this._getData(store));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen to all events (data changes).
|
||||||
|
componentDidMount() {
|
||||||
|
this._isMounted = true;
|
||||||
|
|
||||||
|
for (let key in stores) {
|
||||||
|
stores[key].onAny(_.partial(this._onChange, key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop listening to store changes.
|
||||||
|
componentWillUnmount() {
|
||||||
|
this._isMounted = false;
|
||||||
|
|
||||||
|
for (let key in stores) {
|
||||||
|
stores[key].clean(this._onChange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,48 +0,0 @@
|
||||||
import _ from 'lodash';
|
|
||||||
|
|
||||||
import stores from '../stores';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
|
|
||||||
// Get the POJO of the store.
|
|
||||||
_getData(store) {
|
|
||||||
let obj = {};
|
|
||||||
if (store) {
|
|
||||||
obj[store] = stores[store].get();
|
|
||||||
} else {
|
|
||||||
// Get all stores.
|
|
||||||
let key;
|
|
||||||
for (key in stores) {
|
|
||||||
obj[key] = stores[key].get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
},
|
|
||||||
|
|
||||||
_onChange(store, val, key) {
|
|
||||||
if (this.isMounted()) { // not ideal
|
|
||||||
this.setState(this._getData(store));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
getInitialState() {
|
|
||||||
return this._getData();
|
|
||||||
},
|
|
||||||
|
|
||||||
// Listen to all events (data changes).
|
|
||||||
componentDidMount() {
|
|
||||||
let key;
|
|
||||||
for (key in stores) {
|
|
||||||
stores[key].onAny(_.partial(this._onChange, key));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
let key;
|
|
||||||
for (key in stores) {
|
|
||||||
stores[key].clean(this._onChange);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
|
@ -73,7 +73,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.action {
|
&.action {
|
||||||
background: darken(@strong_color, 15%);
|
color: darken(@strong_color, 15%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue