Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolashery committed Dec 3, 2014
0 parents commit 1136554
Show file tree
Hide file tree
Showing 12 changed files with 288 additions and 0 deletions.
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Folder view configuration files
.DS_Store
Desktop.ini

# Thumbnail cache files
._*
Thumbs.db

# Files that might appear on external disks
.Spotlight-V100
.Trashes

# Application specific files
node_modules
npm-debug.log
tmp
dist
14 changes: 14 additions & 0 deletions .jshintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"esnext": true,
"browser": true,
"node": true,
"bitwise": true,
"eqeqeq": true,
"immed": true,
"indent": 2,
"latedef": "nofunc",
"noarg": true,
"undef": true,
"unused": "vars",
"trailing": true
}
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# UI as data
28 changes: 28 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
var gulp = require('gulp');
var react = require('gulp-react');
var jshint = require('gulp-jshint');

var jsFiles = [
'src/**/*.js',
'*.js'
];

gulp.task('jshint', function() {
var stream = gulp.src(jsFiles)
.pipe(react())
.pipe(jshint())
.pipe(jshint.reporter('jshint-stylish'));

if (process.env.CI) {
stream = stream.pipe(jshint.reporter('fail'));
}

return stream;
});

gulp.task('jshint-watch', ['jshint'], function(cb){
console.log('Watching files for changes...');
gulp.watch(jsFiles, ['jshint']);
});

gulp.task('default', ['jshint']);
15 changes: 15 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>

<head>
<title>UI as data</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
</head>

<body>
<p>Loading app...</p>
<script type="text/javascript" src="bundle.js"></script>
</body>

</html>
29 changes: 29 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "example-ui-as-data",
"version": "0.1.0",
"dependencies": {
"immutable": "3.3.0",
"react": "0.12.1"
},
"devDependencies": {
"css-loader": "0.9.0",
"gulp": "3.8.10",
"gulp-jshint": "1.9.0",
"gulp-react": "2.0.0",
"jshint-stylish": "1.0.0",
"jsx-loader": "0.12.2",
"style-loader": "0.8.2",
"webpack": "1.4.13",
"webpack-dev-server": "1.6.6"
},
"engines": {
"node": "0.10.x"
},
"private": true,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server --devtool eval-source-map --cache --colors --progress",
"jshint": "gulp jshint",
"jshint-watch": "gulp jshint-watch"
}
}
94 changes: 94 additions & 0 deletions src/actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
var Immutable = require('immutable');

var actions = {};

actions.addTodo = function(state, title) {
var todo = Immutable.Map({
id: this._nextTodoId(state),
title: title,
completed: false
});
return state.update('todos', function(todos) {
return todos.push(todo);
});
};

actions._nextTodoId = function(state) {
var lastTodo = this._lastTodo(state);
if (!lastTodo) {
return 1;
}
else {
return lastTodo.get('id') + 1;
}
};

actions._lastTodo = function(state) {
return state.get('todos', Immutable.List()).last();
};

actions.toggleAll = function(state, checked) {
return state.update('todos', function(todos) {
return todos.map(function(todo) {
return todo.set('completed', checked);
});
});
};

actions.toggle = function(state, id) {
return this._updateTodo(state, id, function(todo) {
return todo.update('completed', function(checked) {
return !checked;
});
});
};

actions._updateTodo = function(state, id, updateFn) {
return state.update('todos', function(todos) {
return todos.map(function(todo) {
if (todo.get('id') === id) {
return updateFn(todo);
}
else {
return todo;
}
});
});
};

actions.destroy = function(state, id) {
return state.update('todos', function(todos) {
return todos.filter(function(todo) {
return todo.get('id') !== id;
});
});
};

actions.save = function(state, id, text) {
state = this.closeEdit(state);
return this._updateTodo(state, id, function(todo) {
return todo.set('title', text);
});
};

actions.clearCompleted = function(state) {
return state.update('todos', function(todos) {
return todos.filter(function(todo) {
return !todo.get('completed');
});
});
};

actions.show = function(state, showing) {
return state.set('nowShowing', showing);
};

actions.openEdit = function(state, id) {
return state.set('editing', id);
};

actions.closeEdit = function(state) {
return state.set('editing', null);
};

module.exports = actions;
9 changes: 9 additions & 0 deletions src/components/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
var React = require('react');

var App = React.createClass({
render: function() {
return <p>Hello world!</p>;
}
});

module.exports = App;
17 changes: 17 additions & 0 deletions src/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
var React = require('react');
window.React = React;
var App = require('./components/App.jsx');

window.Immutable = require('immutable');
var app = window.app = {};
app.state = require('./state');
app.actions = require('./actions');
app.projections = require('./projections');

var state = app.state.initial();
state = app.actions.addTodo(state, 'Groceries');
state = app.actions.addTodo(state, 'Cleaning');
state = app.actions.toggle(state, 1);
window.state = state;

React.render(React.createElement(App), document.body);
34 changes: 34 additions & 0 deletions src/projections.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
var projections = {};

projections.shownTodos = function(state) {
return state.get('todos').filter(function(todo) {
switch (state.get('nowShowing')) {
case 'active':
return !todo.get('completed');
case 'completed':
return todo.get('completed');
default:
return true;
}
});
};

projections.activeTodoCount = function(state) {
return state.get('todos').reduce(function(accum, todo) {
return todo.get('completed') ? accum : accum + 1;
}, 0);
};

projections.completedTodoCount = function(state) {
return state.get('todos').size - this.activeTodoCount(state);
};

projections.isShowingFooter = function(state) {
return Boolean(this.activeTodoCount(state) || this.completedTodoCount(state));
};

projections.isShowingTodoList = function(state) {
return Boolean(state.get('todos').size);
};

module.exports = projections;
13 changes: 13 additions & 0 deletions src/state.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
var Immutable = require('immutable');

var state = {};

state.initial = function() {
return Immutable.fromJS({
todos: [],
nowShowing: 'all',
editing: null
});
};

module.exports = state;
17 changes: 17 additions & 0 deletions webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
var path = require('path');

var config = {
entry: './src/main.js',
output: {
path: path.join(__dirname, '/dist'),
filename: 'bundle.js'
},
module: {
loaders: [
{test: /\.jsx$/, loader: 'jsx'},
{test: /\.css$/, loader: 'style!css'}
]
}
};

module.exports = config;

0 comments on commit 1136554

Please sign in to comment.