From e3704a729b25db24a2f6773a82577f432bd6cd84 Mon Sep 17 00:00:00 2001 From: Chris Kobrzak Date: Tue, 8 Sep 2015 00:41:28 +0100 Subject: [PATCH 1/2] Integrate simple TODO list powered by Alt Flux library It's very much a WIP as the code has been ported from another project and uses different conventions: no semicolons as line delimiters and file names with CamelCase. --- index.html | 4 ++ package.json | 6 +- src/app.js | 3 + src/flux/actions/NoteActions.js | 3 + src/flux/libs/alt.js | 5 ++ src/flux/stores/NoteStore.js | 4 ++ src/flux/stores/NoteStoreModel.js | 54 ++++++++++++++++++ src/todos/App.jsx | 53 ++++++++++++++++++ src/todos/Button.jsx | 13 +++++ src/todos/EditableTextBox.jsx | 15 +++++ src/todos/Note.jsx | 92 +++++++++++++++++++++++++++++++ src/todos/Notes.jsx | 38 +++++++++++++ src/todos/Todos.css | 31 +++++++++++ 13 files changed, 320 insertions(+), 1 deletion(-) create mode 100644 src/flux/actions/NoteActions.js create mode 100644 src/flux/libs/alt.js create mode 100644 src/flux/stores/NoteStore.js create mode 100644 src/flux/stores/NoteStoreModel.js create mode 100644 src/todos/App.jsx create mode 100644 src/todos/Button.jsx create mode 100644 src/todos/EditableTextBox.jsx create mode 100644 src/todos/Note.jsx create mode 100644 src/todos/Notes.jsx create mode 100644 src/todos/Todos.css diff --git a/index.html b/index.html index df9680c..c45b9bb 100644 --- a/index.html +++ b/index.html @@ -8,9 +8,13 @@
+
+ Page #1 Page #2 + + diff --git a/package.json b/package.json index fbdb4ed..a7cc31c 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,11 @@ "name": "webpack-react-workflow", "version": "0.1.0", "description": "A dummy project on how to integrate React and Webpack in a Web project", + "dependencies": { + "alt": "^0.17.3", + "node-uuid": "^1.4.3", + "react": "^0.13.3" + }, "devDependencies": { "autoprefixer": "^5.2.0", "babel-core": "^5.8.22", @@ -22,7 +27,6 @@ "mocha": "^2.2.5", "node-sass": "3.2.0", "postcss-loader": "^0.6.0", - "react": "^0.13.3", "react-hot-loader": "^1.2.8", "sass-loader": "^2.0.0", "style-loader": "^0.12.3", diff --git a/src/app.js b/src/app.js index 2424c01..f725d7b 100644 --- a/src/app.js +++ b/src/app.js @@ -7,5 +7,8 @@ import Book from './book/book.js'; import Section from './book/section.jsx'; // eslint-disable-line no-unused-vars React.render(
, document.getElementById( 'heading-container' ) ); +import Todos from './todos/App.jsx'; // eslint-disable-line no-unused-vars +React.render( , document.getElementById( 'notes-container' ) ); + var book = new Book(); book.logSomething(); diff --git a/src/flux/actions/NoteActions.js b/src/flux/actions/NoteActions.js new file mode 100644 index 0000000..a97f7c3 --- /dev/null +++ b/src/flux/actions/NoteActions.js @@ -0,0 +1,3 @@ +import alt from "../libs/alt" + +export default alt.generateActions("create", "update", "delete") diff --git a/src/flux/libs/alt.js b/src/flux/libs/alt.js new file mode 100644 index 0000000..2faeca7 --- /dev/null +++ b/src/flux/libs/alt.js @@ -0,0 +1,5 @@ +import Alt from "alt" + +let alt = new Alt() + +export default alt diff --git a/src/flux/stores/NoteStore.js b/src/flux/stores/NoteStore.js new file mode 100644 index 0000000..8227469 --- /dev/null +++ b/src/flux/stores/NoteStore.js @@ -0,0 +1,4 @@ +import alt from "../libs/alt" +import NoteStoreModel from "./NoteStoreModel" + +export default alt.createStore( NoteStoreModel, "NoteStore" ) diff --git a/src/flux/stores/NoteStoreModel.js b/src/flux/stores/NoteStoreModel.js new file mode 100644 index 0000000..45599fc --- /dev/null +++ b/src/flux/stores/NoteStoreModel.js @@ -0,0 +1,54 @@ +import uuid from "node-uuid" +import NoteActions from "../actions/NoteActions" + +export default class { + + constructor() { + this.bindActions( NoteActions ) + + this.notes = [] + } + + create( note ) { + let notes = this.notes + + note.id = uuid.v4() + + this.setState({ + notes: notes.concat( note ) + }) + } + + update( {id, task} ) { + let noteIndex = this.findNoteIndexById( id ) + if ( noteIndex < 0 ) { + return + } + + let notes = this.notes + notes[ noteIndex ].task = task + this.setState({ notes }) + } + + findNoteIndexById( id ) { + let notes = this.notes + let noteIndex = notes.findIndex( ( note ) => note.id === id ) + + if ( noteIndex < 0 ) { + console.warn( "Could not find note", id, notes ) + } + + return noteIndex + } + + delete( id ) { + let noteIndex = this.findNoteIndexById( id ) + if ( noteIndex < 0 ) { + return + } + + let notes = this.notes + notes.splice( noteIndex, 1 ) + this.setState({ notes }) + } +} diff --git a/src/todos/App.jsx b/src/todos/App.jsx new file mode 100644 index 0000000..4ad0bc0 --- /dev/null +++ b/src/todos/App.jsx @@ -0,0 +1,53 @@ +import React from "react" +import Button from "./Button.jsx" +import Notes from "./Notes.jsx" +import NoteActions from "../flux/actions/NoteActions.js" +import NoteStore from "../flux/stores/NoteStore.js" +import "./Todos.css" + +export default class extends React.Component { + constructor(props) { + super(props) + this.bindInstanceMethods() + + this.state = NoteStore.getState() + } + + bindInstanceMethods() { + this.setState = this.setState.bind( this ) + } + + componentDidMount() { + NoteStore.listen( this.setState ) + } + + componentWillUnmount() { + NoteStore.unlisten( this.setState ) + } + + render() { + let notes = this.state.notes + + return ( +
+
+ ) + } + + addNote() { + NoteActions.create( {task: "New task"} ) + } + + editNote( id, task ) { + NoteActions.update( {id, task} ) + } + + deleteNote( id ) { + NoteActions.delete( id ) + } +} diff --git a/src/todos/Button.jsx b/src/todos/Button.jsx new file mode 100644 index 0000000..0a86803 --- /dev/null +++ b/src/todos/Button.jsx @@ -0,0 +1,13 @@ +import React from "react" + +export default class extends React.Component { + + render() { + let text = this.props.text || "OK", + className = this.props.className || null + + return () + } +} diff --git a/src/todos/EditableTextBox.jsx b/src/todos/EditableTextBox.jsx new file mode 100644 index 0000000..b993332 --- /dev/null +++ b/src/todos/EditableTextBox.jsx @@ -0,0 +1,15 @@ +import React from "react" + +export default class extends React.Component { + + render() { + let autoFocus = this.props.autoFocus || true + + return () + } +} diff --git a/src/todos/Note.jsx b/src/todos/Note.jsx new file mode 100644 index 0000000..a2e7765 --- /dev/null +++ b/src/todos/Note.jsx @@ -0,0 +1,92 @@ +import React from "react" +import Button from "./Button.jsx" +import EditableTextBox from "./EditableTextBox.jsx" + +export default class extends React.Component { + constructor(props) { + super( props ) + this.bindInstanceMethods() + + this.state = { + editing: false + } + } + + bindInstanceMethods() { + let methods = [ + "startEditing", + "handleInputBlur", + "handleKeyPress", + "renderDelete", + "renderInput", + "renderTask" + ] + for ( let method of methods ) { + this[ method ] = this[ method ].bind( this ) + } + } + + render() { + let editing = this.state.editing + let renderedElement + if ( editing ) { + renderedElement = this.renderInput() + } else { + renderedElement = this.renderTask() + } + + return renderedElement + } + + renderTask() { + let renderedDelete + if ( this.props.onDeleteCompleted ) { + renderedDelete = this.renderDelete() + } + + return (
+ {this.props.task} + {renderedDelete} +
) + } + + renderDelete() { + return (