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
2454
public/js/bundle.js
2454
public/js/bundle.js
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"
|
||||||
|
|
|
@ -39,13 +39,13 @@ let find = ({ to, params, query }) => {
|
||||||
_.find(routes, (name, url) => {
|
_.find(routes, (name, url) => {
|
||||||
if (name != to) return;
|
if (name != to) return;
|
||||||
let matches = url.match(re);
|
let matches = url.match(re);
|
||||||
|
|
||||||
// Do not match on the number of params.
|
// Do not match on the number of params.
|
||||||
if (_.keys(params).length != (matches || []).length) return;
|
if (_.keys(params).length != (matches || []).length) return;
|
||||||
|
|
||||||
// Do not match on the name of params.
|
// Do not match on the name of params.
|
||||||
if (!_.every(matches, m => m.slice(1) in params)) return;
|
if (!_.every(matches, m => m.slice(1) in params)) return;
|
||||||
|
|
||||||
// Fill in the params.
|
// Fill in the params.
|
||||||
$url = url.replace(re, m => params[m.slice(1)]);
|
$url = url.replace(re, m => params[m.slice(1)]);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
@ -20,18 +20,22 @@ let codes = {
|
||||||
'megaphone': '\e80d', // Entypo - megaphone
|
'megaphone': '\e80d', // Entypo - megaphone
|
||||||
'sort': '\e80e', // Typicons - sort-alphabet
|
'sort': '\e80e', // Typicons - sort-alphabet
|
||||||
'spinner': '\e80f', // MFG Labs - spinner1
|
'spinner': '\e80f', // MFG Labs - spinner1
|
||||||
'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