├── .gitignore
├── config
├── environments
│ ├── production.js
│ └── development.js
└── index.js
├── public
├── favicon.ico
└── fonts
│ ├── aileron-thin-webfont.woff
│ ├── aileron-thin-webfont.woff2
│ ├── aileron-ultralight-webfont.woff
│ ├── aileron-ultralight-webfont.woff2
│ └── aileron.css
├── webpackConfig
├── common.config.js
├── webpack.server.babel.js
├── webpack.base.js
├── webpack.server.prod.babel.js
├── webpack.client.prod.babel.js
├── webpack.server.dev.babel.js
└── webpack.hot.js
├── .eslintignore
├── .eslintrc
├── src
├── vuex
│ ├── getters.js
│ ├── store.js
│ └── actions.js
├── clientEntry.js
├── containers
│ ├── App.vue
│ ├── Landing
│ │ ├── Landing.vue
│ │ └── Landing.js
│ ├── ServerApp.js
│ ├── ClientApp.js
│ └── sharedAttr.js
├── scss
│ ├── mixins.scss
│ ├── gradients.scss
│ ├── main.scss
│ ├── transitions.scss
│ ├── helpers.scss
│ ├── normalize.css
│ └── grid12.scss
├── components
│ ├── LoadingScreen
│ │ ├── LoadingScreen.js
│ │ └── LoadingScreen.vue
│ └── Todos
│ │ ├── TodoInput
│ │ ├── TodoInput.js
│ │ └── TodoInput.vue
│ │ ├── Todos.js
│ │ ├── TodoItem
│ │ ├── EditTodo
│ │ │ ├── EditTodo.js
│ │ │ └── EditTodo.vue
│ │ ├── TodoItem.vue
│ │ └── TodoItem.js
│ │ └── Todos.vue
├── routes
│ ├── serverRoutes.js
│ └── clientRoutes.js
└── serverEntry.js
├── .babelrc
├── serverRoutes
├── catchAll.js
└── index.js
├── data
└── todos.js
├── views
├── helpers
│ ├── generateInitialState.js
│ ├── getProductionBundle.js
│ ├── getManifest.js
│ ├── generateClosingTags.js
│ ├── getDevBundle.js
│ └── generateHead.js
└── index.js
├── server.js
├── README.md
├── package.json
└── controllers
└── todos.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | public/dist/
3 | dist/
4 | *.swp
5 | .DS_Store
6 |
--------------------------------------------------------------------------------
/config/environments/production.js:
--------------------------------------------------------------------------------
1 | export default {
2 | 'port': '8080',
3 | };
4 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Slegrib/vue-todo/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/webpackConfig/common.config.js:
--------------------------------------------------------------------------------
1 | export default [
2 | 'vue',
3 | 'vue-router',
4 | ];
5 |
--------------------------------------------------------------------------------
/config/environments/development.js:
--------------------------------------------------------------------------------
1 | export default {
2 | 'port': '8080',
3 | 'hot': '3000',
4 | };
5 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | webpack.base.js
2 | webpack.client.prod.js
3 | webpack.server.dev.js
4 | webpack.server.prod.js
5 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "parser": "babel-eslint",
4 | "rules": {
5 |
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/vuex/getters.js:
--------------------------------------------------------------------------------
1 | // get the current state of the todos
2 | export const getTodos = state => state.todos;
3 |
--------------------------------------------------------------------------------
/public/fonts/aileron-thin-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Slegrib/vue-todo/HEAD/public/fonts/aileron-thin-webfont.woff
--------------------------------------------------------------------------------
/public/fonts/aileron-thin-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Slegrib/vue-todo/HEAD/public/fonts/aileron-thin-webfont.woff2
--------------------------------------------------------------------------------
/public/fonts/aileron-ultralight-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Slegrib/vue-todo/HEAD/public/fonts/aileron-ultralight-webfont.woff
--------------------------------------------------------------------------------
/public/fonts/aileron-ultralight-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Slegrib/vue-todo/HEAD/public/fonts/aileron-ultralight-webfont.woff2
--------------------------------------------------------------------------------
/src/clientEntry.js:
--------------------------------------------------------------------------------
1 | import App from './containers/ClientApp';
2 | import css from './scss/main.scss';
3 |
4 |
5 | App.$mount('#root');
6 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015",
4 | "stage-0"
5 | ],
6 | "plugins": ["transform-runtime"],
7 | "comments": false
8 | }
9 |
--------------------------------------------------------------------------------
/src/containers/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/serverRoutes/catchAll.js:
--------------------------------------------------------------------------------
1 | // catch all route for the single page application
2 | import renderApp from '../views';
3 |
4 | export default (server) => {
5 | server.get('*', renderApp);
6 | };
7 |
--------------------------------------------------------------------------------
/data/todos.js:
--------------------------------------------------------------------------------
1 | module.exports = [
2 | { id: 1, done: true, description: 'Create the best todo app ever' },
3 | { id: 2, done: false, description: 'Get Interview' },
4 | { id: 3, done: false, description: 'Get Hired' },
5 | ];
6 |
--------------------------------------------------------------------------------
/views/helpers/generateInitialState.js:
--------------------------------------------------------------------------------
1 | export default (context) => {
2 | const initialState = context.initialState || 'initial state';
3 | return ``;
4 | };
5 |
--------------------------------------------------------------------------------
/src/scss/mixins.scss:
--------------------------------------------------------------------------------
1 | @mixin transform($transforms) {
2 | -moz-transform: $transforms;
3 | -o-transform: $transforms;
4 | -ms-transform: $transforms;
5 | -webkit-transform: $transforms;
6 | transform: $transforms;
7 | }
8 |
--------------------------------------------------------------------------------
/src/components/LoadingScreen/LoadingScreen.js:
--------------------------------------------------------------------------------
1 | /*
2 | This is a loading screen for the app. When the app finishes mounting then the
3 | top level component sets its state to loading = false. Then unmounts this
4 | component.
5 | */
6 | export default {
7 | props: {
8 | loading: Boolean,
9 | required: true,
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/src/components/LoadingScreen/LoadingScreen.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/config/index.js:
--------------------------------------------------------------------------------
1 | import development from './environments/development';
2 | import production from './environments/production';
3 |
4 | const config = {
5 | 'development': development,
6 | 'production': production,
7 | };
8 |
9 | // export the right config settings depending on the node environment
10 | export default config[process.env.NODE_ENV];
11 |
--------------------------------------------------------------------------------
/src/components/Todos/TodoInput/TodoInput.js:
--------------------------------------------------------------------------------
1 | export default {
2 | data() {
3 | return {
4 | value: '',
5 | };
6 | },
7 | methods: {
8 | handleSubmit() {
9 | if (this.value.length > 0) {
10 | this.$store.dispatch('createTodo', { description: this.value, component: this });
11 | }
12 | },
13 | },
14 | };
15 |
--------------------------------------------------------------------------------
/src/containers/Landing/Landing.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/components/Todos/Todos.js:
--------------------------------------------------------------------------------
1 | import { mapGetters } from 'vuex';
2 | import TodoInput from './TodoInput/TodoInput.vue';
3 | import TodoItem from './TodoItem/TodoItem.vue';
4 |
5 | export default {
6 | components: {
7 | 'todo-input': TodoInput,
8 | 'todo-item': TodoItem,
9 | },
10 | computed: {
11 | // map the todos from vuex
12 | ...mapGetters({
13 | todos: 'getTodos',
14 | }),
15 | },
16 | };
17 |
--------------------------------------------------------------------------------
/views/helpers/getProductionBundle.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import path from 'path';
3 | import { createBundleRenderer } from 'vue-server-renderer';
4 |
5 | export default ()=> {
6 | const projectRoot = path.resolve(__dirname, '../../');
7 | const filePath = path.join(projectRoot, 'dist/bundle.server.js');
8 | const code = fs.readFileSync(filePath, 'utf8');
9 |
10 | const bundleRenderer = createBundleRenderer(code);
11 | return bundleRenderer;
12 | };
13 |
--------------------------------------------------------------------------------
/views/helpers/getManifest.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import path from 'path';
3 | // root of the project folder
4 | const projectRoot = path.resolve(__dirname, '../../');
5 | const manifestPath = path.join(projectRoot, 'public/dist/manifest.json');
6 | // read the file using node's built in file system
7 | const manifestJSON = fs.readFileSync(manifestPath, 'utf8');
8 | // parse the manifest to use when importing client side javascript files
9 | const manifest = JSON.parse(manifestJSON);
10 |
11 | export default manifest;
12 |
--------------------------------------------------------------------------------
/views/helpers/generateClosingTags.js:
--------------------------------------------------------------------------------
1 | import manifest from './getManifest.js';
2 | import config from '../../config';
3 | const hotPort = config.hot;
4 | const NODE_ENV = process.env.NODE_ENV;
5 | const isProd = NODE_ENV === 'production';
6 |
7 | const bundlePath = isProd ? manifest['/dist/bundle.js'] : `http://localhost:${hotPort}/dist/bundle.js`;
8 |
9 | const closingTags =
10 | `
11 |