forked from boranton/testcafe-workshop
WIP: setup code splitting
This commit is contained in:
parent
ead26ccab6
commit
6abc8c04cb
3
.babelrc
3
.babelrc
@ -2,7 +2,8 @@
|
||||
"presets": [
|
||||
["es2015", {"modules": false}],
|
||||
"es2016",
|
||||
"stage-2"
|
||||
"stage-2",
|
||||
"react"
|
||||
],
|
||||
"env": {
|
||||
"test": {
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
"kentcdodds/import/possible-errors",
|
||||
"kentcdodds/mocha",
|
||||
"kentcdodds/webpack",
|
||||
"kentcdodds/react",
|
||||
],
|
||||
"rules": {
|
||||
// these are only here because I did not
|
||||
|
||||
@ -18,6 +18,11 @@
|
||||
</section>
|
||||
<footer class="footer">
|
||||
<span class="todo-count"></span>
|
||||
<button class="toggle-graph">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32">
|
||||
<path d="M14 18v-14c-7.732 0-14 6.268-14 14s6.268 14 14 14 14-6.268 14-14c0-2.251-0.532-4.378-1.476-6.262l-12.524 6.262zM28.524 7.738c-2.299-4.588-7.043-7.738-12.524-7.738v14l12.524-6.262z"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<ul class="filters">
|
||||
<li>
|
||||
<a href="#/" class="selected">All</a>
|
||||
@ -32,6 +37,7 @@
|
||||
<button class="clear-completed">Clear completed</button>
|
||||
</footer>
|
||||
</section>
|
||||
<section class="graph-area-container"></section>
|
||||
<footer class="info">
|
||||
<p>Double-click to edit a todo</p>
|
||||
<p>Created by <a href="http://twitter.com/oscargodson">Oscar Godson</a></p>
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
{
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"d3": "3.5.17",
|
||||
"lodash": "4.14.1",
|
||||
"rd3": "0.7.0",
|
||||
"react": "15.3.0",
|
||||
"react-dom": "15.3.0",
|
||||
"todomvc-app-css": "2.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -9,6 +14,7 @@
|
||||
"babel-plugin-__coverage__": "11.0.0",
|
||||
"babel-preset-es2015": "6.13.2",
|
||||
"babel-preset-es2016": "6.11.3",
|
||||
"babel-preset-react": "6.11.1",
|
||||
"babel-preset-stage-2": "6.13.0",
|
||||
"chai": "3.5.0",
|
||||
"css-loader": "0.23.1",
|
||||
@ -25,6 +31,7 @@
|
||||
"mocha": "3.0.1",
|
||||
"npm-run-all": "2.3.0",
|
||||
"opt-cli": "1.5.1",
|
||||
"progress-bar-webpack-plugin": "1.9.0",
|
||||
"rimraf": "2.5.4",
|
||||
"style-loader": "0.13.1",
|
||||
"webpack": "2.1.0-beta.20",
|
||||
|
||||
20
src/app.css
Normal file
20
src/app.css
Normal file
@ -0,0 +1,20 @@
|
||||
.toggle-graph {
|
||||
float: left;
|
||||
margin-left: 16px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.toggle-graph svg {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
}
|
||||
.toggle-graph svg path {
|
||||
fill: #777;
|
||||
}
|
||||
|
||||
.toggle-graph.active svg path,
|
||||
.toggle-graph:hover svg path,
|
||||
.toggle-graph:focus svg path {
|
||||
fill: black;
|
||||
}
|
||||
38
src/app.js
38
src/app.js
@ -1,25 +1,23 @@
|
||||
import 'todomvc-app-css/index.css'
|
||||
import './app.css'
|
||||
|
||||
import View from './view'
|
||||
import Controller from './controller'
|
||||
import Model from './model'
|
||||
import Store from './store'
|
||||
import Template from './template'
|
||||
|
||||
/**
|
||||
* Sets up a brand new Todo list.
|
||||
*
|
||||
* @param {string} name The name of your new to do list.
|
||||
*/
|
||||
function Todo(name) {
|
||||
this.storage = new Store(name)
|
||||
this.model = new Model(this.storage)
|
||||
this.template = new Template()
|
||||
this.view = new View(this.template)
|
||||
this.controller = new Controller(this.model, this.view)
|
||||
}
|
||||
import {$on} from './helpers'
|
||||
import {updateTodo} from './todo'
|
||||
import toggleGraph from './graph'
|
||||
|
||||
export function onLoad() { // eslint-disable-line import/prefer-default-export
|
||||
const todo = new Todo('todos-vanillajs')
|
||||
todo.controller.setView(document.location.hash)
|
||||
updateTodo()
|
||||
const toggleGraphButton = document.querySelector('.toggle-graph')
|
||||
$on(
|
||||
toggleGraphButton,
|
||||
'click',
|
||||
() => {
|
||||
const active = toggleGraph()
|
||||
if (active) {
|
||||
toggleGraphButton.classList.add('active')
|
||||
} else {
|
||||
toggleGraphButton.classList.remove('active')
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@ -250,6 +250,7 @@ Controller.prototype._filter = function(force) {
|
||||
Controller.prototype._updateFilterState = function(currentPage) {
|
||||
// Store a reference to the active route, allowing us to re-filter todo
|
||||
// items as they are marked complete or incomplete.
|
||||
currentPage = currentPage.split('?')[0]
|
||||
this._activeRoute = currentPage
|
||||
|
||||
if (currentPage === '') {
|
||||
|
||||
48
src/graph/index.js
Normal file
48
src/graph/index.js
Normal file
@ -0,0 +1,48 @@
|
||||
import {subscribe, getTodo} from '../todo'
|
||||
import renderGraph from './render'
|
||||
|
||||
let graphArea
|
||||
const unsubscribe = {
|
||||
store: null,
|
||||
todo: null,
|
||||
}
|
||||
|
||||
export default toggleGraph
|
||||
|
||||
function toggleGraph() {
|
||||
if (graphArea) {
|
||||
graphArea.remove()
|
||||
graphArea = null
|
||||
unsubscribe.store()
|
||||
unsubscribe.todo()
|
||||
return false
|
||||
} else {
|
||||
graphArea = document.createElement('div')
|
||||
document.body.querySelector('.graph-area-container').appendChild(graphArea)
|
||||
const {storage} = getTodo()
|
||||
renderGraph(graphArea, storage)
|
||||
updateTodoSubscription()
|
||||
updateStoreSubscription(storage)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
function updateTodoSubscription() {
|
||||
if (unsubscribe.todo) {
|
||||
unsubscribe.todo()
|
||||
}
|
||||
unsubscribe.todo = subscribe(function onTodoUpdate() {
|
||||
const {storage} = getTodo()
|
||||
updateStoreSubscription(storage)
|
||||
renderGraph(graphArea, storage)
|
||||
})
|
||||
}
|
||||
|
||||
function updateStoreSubscription(store) {
|
||||
if (unsubscribe.store) {
|
||||
unsubscribe.store()
|
||||
}
|
||||
unsubscribe.store = store.subscribe(function onStoreUpdate() {
|
||||
renderGraph(graphArea, store)
|
||||
})
|
||||
}
|
||||
44
src/graph/render.js
Normal file
44
src/graph/render.js
Normal file
@ -0,0 +1,44 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import {PieChart} from 'rd3'
|
||||
import {chain} from 'lodash'
|
||||
|
||||
export default updateGraph
|
||||
|
||||
function updateGraph(node, store) {
|
||||
store.findAll(todos => {
|
||||
ReactDOM.render(
|
||||
<Graph todos={todos} />,
|
||||
node,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
function Graph({todos}) {
|
||||
const data = chain(todos)
|
||||
.groupBy('completed')
|
||||
.map((group, complete) => ({
|
||||
label: complete === 'true' ? 'Complete' : 'Incomplete',
|
||||
value: Math.round(group.length / todos.length * 10000) / 100
|
||||
}))
|
||||
.value()
|
||||
return (
|
||||
<div>
|
||||
There are {todos.length} total todos
|
||||
<div>
|
||||
<PieChart
|
||||
data={data}
|
||||
width={450}
|
||||
height={310}
|
||||
radius={110}
|
||||
innerRadius={20}
|
||||
sectorBorderColor="white"
|
||||
title="Todo Data"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Graph.propTypes = {
|
||||
todos: React.PropTypes.array,
|
||||
}
|
||||
14
src/store.js
14
src/store.js
@ -1,3 +1,4 @@
|
||||
import {remove} from './helpers'
|
||||
export default Store
|
||||
|
||||
/**
|
||||
@ -23,6 +24,16 @@ function Store(name, callback) {
|
||||
}
|
||||
|
||||
callback.call(this, JSON.parse(localStorage[name]))
|
||||
this.subscribers = []
|
||||
}
|
||||
|
||||
Store.prototype.subscribe = function(subscriber) {
|
||||
this.subscribers.push(subscriber)
|
||||
return () => remove(this.subscribers, subscriber)
|
||||
}
|
||||
|
||||
Store.prototype._notify = function() {
|
||||
this.subscribers.forEach(s => s())
|
||||
}
|
||||
|
||||
/**
|
||||
@ -102,6 +113,7 @@ Store.prototype.save = function(updateData, callback, id) {
|
||||
localStorage[this._dbName] = JSON.stringify(data)
|
||||
callback.call(this, [updateData])
|
||||
}
|
||||
this._notify()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -123,6 +135,7 @@ Store.prototype.remove = function(id, callback) {
|
||||
|
||||
localStorage[this._dbName] = JSON.stringify(data)
|
||||
callback.call(this, JSON.parse(localStorage[this._dbName]).todos)
|
||||
this._notify()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -133,4 +146,5 @@ Store.prototype.remove = function(id, callback) {
|
||||
Store.prototype.drop = function(callback) {
|
||||
localStorage[this._dbName] = JSON.stringify({todos: []})
|
||||
callback.call(this, JSON.parse(localStorage[this._dbName]).todos)
|
||||
this._notify()
|
||||
}
|
||||
|
||||
41
src/todo.js
Normal file
41
src/todo.js
Normal file
@ -0,0 +1,41 @@
|
||||
import View from './view'
|
||||
import Controller from './controller'
|
||||
import Model from './model'
|
||||
import Store from './store'
|
||||
import Template from './template'
|
||||
import {remove} from './helpers'
|
||||
|
||||
export {updateTodo, getTodo, subscribe}
|
||||
|
||||
let todo
|
||||
const subscribers = []
|
||||
|
||||
/**
|
||||
* Sets up a brand new Todo list.
|
||||
*
|
||||
* @param {string} name The name of your new to do list.
|
||||
*/
|
||||
function Todo(name) {
|
||||
this.storage = new Store(name)
|
||||
this.model = new Model(this.storage)
|
||||
this.template = new Template()
|
||||
this.view = new View(this.template)
|
||||
this.controller = new Controller(this.model, this.view)
|
||||
}
|
||||
|
||||
function updateTodo() {
|
||||
todo = new Todo('todos-vanillajs')
|
||||
todo.controller.setView(document.location.hash)
|
||||
subscribers.forEach(s => s())
|
||||
}
|
||||
|
||||
function getTodo() {
|
||||
return todo
|
||||
}
|
||||
|
||||
function subscribe(cb) {
|
||||
subscribers.push(cb)
|
||||
return function unsubscribe() {
|
||||
remove(subscribers, cb)
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
/* eslint no-console:"off" */
|
||||
const {resolve} = require('path')
|
||||
const ProgressBarPlugin = require('progress-bar-webpack-plugin')
|
||||
const webpackValidator = require('webpack-validator')
|
||||
const {getIfUtils} = require('webpack-config-utils')
|
||||
|
||||
@ -21,6 +22,9 @@ module.exports = env => {
|
||||
{test: /\.css$/, loaders: ['style', 'css']},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new ProgressBarPlugin()
|
||||
],
|
||||
})
|
||||
if (env.debug) {
|
||||
console.log(config)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user