├── .gitignore ├── README.md ├── assets ├── README.md └── scss │ └── main.scss ├── assignments.txt ├── components ├── Logo.vue ├── Navbar.vue ├── PostCreate.vue ├── PostItem.vue ├── PostManage.vue ├── README.md └── shared │ └── Modal.vue ├── layouts ├── README.md └── default.vue ├── middleware └── README.md ├── nuxt.config.js ├── package-lock.json ├── package.json ├── pages ├── README.md ├── index.vue ├── manage.vue └── posts │ └── _id.vue ├── plugins ├── README.md └── filters.js ├── resources ├── 1_Index-page.html ├── 2_Checkbox.html ├── 3_manage.html ├── 4_Modal.html ├── 5_Modal_Form.html ├── 6_Post_Update.html ├── 7_delete_button.html └── 8_PostDetail.html ├── server ├── index.js └── routes │ └── index.js ├── static ├── README.md └── favicon.ico └── store ├── README.md ├── index.js ├── initial_data.json └── post.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Node template 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | 10 | # Runtime data 11 | pids 12 | *.pid 13 | *.seed 14 | *.pid.lock 15 | 16 | # Directory for instrumented libs generated by jscoverage/JSCover 17 | lib-cov 18 | 19 | # Coverage directory used by tools like istanbul 20 | coverage 21 | 22 | # nyc test coverage 23 | .nyc_output 24 | 25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 26 | .grunt 27 | 28 | # Bower dependency directory (https://bower.io/) 29 | bower_components 30 | 31 | # node-waf configuration 32 | .lock-wscript 33 | 34 | # Compiled binary addons (https://nodejs.org/api/addons.html) 35 | build/Release 36 | 37 | # Dependency directories 38 | node_modules/ 39 | jspm_packages/ 40 | 41 | # TypeScript v1 declaration files 42 | typings/ 43 | 44 | # Optional npm cache directory 45 | .npm 46 | 47 | # Optional eslint cache 48 | .eslintcache 49 | 50 | # Optional REPL history 51 | .node_repl_history 52 | 53 | # Output of 'npm pack' 54 | *.tgz 55 | 56 | # Yarn Integrity file 57 | .yarn-integrity 58 | 59 | # dotenv environment variables file 60 | .env 61 | 62 | # parcel-bundler cache (https://parceljs.org/) 63 | .cache 64 | 65 | # next.js build output 66 | .next 67 | 68 | # nuxt.js build output 69 | .nuxt 70 | 71 | # Nuxt generate 72 | dist 73 | 74 | # vuepress build output 75 | .vuepress/dist 76 | 77 | # Serverless directories 78 | .serverless 79 | 80 | # IDE / Editor 81 | .idea 82 | .editorconfig 83 | 84 | # Service worker 85 | sw.* 86 | 87 | # Mac OSX 88 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nuxt-posts 2 | 3 | > My awe-inspiring Nuxt.js project 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | $ npm run install 10 | 11 | # serve with hot reload at localhost:3000 12 | $ npm run dev 13 | 14 | # build for production and launch server 15 | $ npm run build 16 | $ npm run start 17 | 18 | # generate static project 19 | $ npm run generate 20 | ``` 21 | 22 | For detailed explanation on how things work, checkout [Nuxt.js docs](https://nuxtjs.org). 23 | -------------------------------------------------------------------------------- /assets/README.md: -------------------------------------------------------------------------------- 1 | # ASSETS 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your un-compiled assets such as LESS, SASS, or JavaScript. 6 | 7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#webpacked). 8 | -------------------------------------------------------------------------------- /assets/scss/main.scss: -------------------------------------------------------------------------------- 1 | 2 | 3 | .markdown { 4 | p { 5 | margin: 5px 0; 6 | } 7 | 8 | h1, h2, h3 { 9 | font-weight: bold; 10 | } 11 | 12 | h1 { 13 | font-size: 23px; 14 | } 15 | 16 | h2 { 17 | font-size: 20px; 18 | } 19 | 20 | h3 { 21 | font-size: 17px; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /assignments.txt: -------------------------------------------------------------------------------- 1 | 2 | --------------SERVER---------------- 3 | 4 | 1. Update server endpoint to remove post 5 | HINT: is very similiar to patch endpoint, you don't need to send any data 6 | just provide post "id" in request params. 7 | 2. find index of post in array and remove post 8 | 3. to remove post from array you can use funtion "splice" 9 | 4. write file with initialData... 10 | 11 | --------------CLIENT---------------- 12 | 13 | 1. Create new action "deletePost" expect to receive "id" of post in arguments of this function. 14 | 2. Find post index in array and if index is found send request to delete post 15 | HINT: this.$axios.$delete('endpoint') 16 | 3. In "then" block after promise is resolved commit mutation to remove post from list, use "splice" once more 17 | 4. after delete button is clicked dispatch action "deletePost" 18 | 19 | NOTE: One issue is expected. After post will be deleted, activePost will have still old value of deleted post. 20 | Don't worry about this issue right now. Bonus points if you can resolve it. In any case we will fix it in next lecture. 21 | -------------------------------------------------------------------------------- /components/Logo.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 80 | -------------------------------------------------------------------------------- /components/Navbar.vue: -------------------------------------------------------------------------------- 1 | 2 | 47 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /components/PostCreate.vue: -------------------------------------------------------------------------------- 1 | 47 | 48 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /components/PostItem.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 26 | 27 | 69 | 70 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /components/PostManage.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /components/README.md: -------------------------------------------------------------------------------- 1 | # COMPONENTS 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | The components directory contains your Vue.js Components. 6 | 7 | _Nuxt.js doesn't supercharge these components._ 8 | -------------------------------------------------------------------------------- /components/shared/Modal.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 34 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /layouts/README.md: -------------------------------------------------------------------------------- 1 | # LAYOUTS 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your Application Layouts. 6 | 7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/views#layouts). 8 | -------------------------------------------------------------------------------- /layouts/default.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 56 | -------------------------------------------------------------------------------- /middleware/README.md: -------------------------------------------------------------------------------- 1 | # MIDDLEWARE 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your application middleware. 6 | Middleware let you define custom functions that can be run before rendering either a page or a group of pages. 7 | 8 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing#middleware). 9 | -------------------------------------------------------------------------------- /nuxt.config.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = { 3 | mode: 'universal', 4 | /* 5 | ** Headers of the page 6 | */ 7 | head: { 8 | title: process.env.npm_package_name || '', 9 | meta: [ 10 | { charset: 'utf-8' }, 11 | { name: 'viewport', content: 'width=device-width, initial-scale=1' }, 12 | { hid: 'description', name: 'description', content: process.env.npm_package_description || '' } 13 | ], 14 | link: [ 15 | { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' } 16 | ], 17 | script: [ 18 | { src: 'https://cdn.jsdelivr.net/npm/marked/marked.min.js'} 19 | ] 20 | }, 21 | /* 22 | ** Customize the progress-bar color 23 | */ 24 | loading: { color: '#fff' }, 25 | /* 26 | ** Global CSS 27 | */ 28 | css: [ 29 | '@/assets/scss/main.scss' 30 | ], 31 | /* 32 | ** Plugins to load before mounting the App 33 | */ 34 | plugins: [ 35 | {src: '~/plugins/filters.js'} 36 | ], 37 | /* 38 | ** Nuxt.js modules 39 | */ 40 | modules: [ 41 | // Doc:https://github.com/nuxt-community/modules/tree/master/packages/bulma 42 | '@nuxtjs/bulma', 43 | // Doc: https://axios.nuxtjs.org/usage 44 | '@nuxtjs/axios', 45 | ], 46 | /* 47 | ** Axios module configuration 48 | ** See https://axios.nuxtjs.org/options 49 | */ 50 | axios: { 51 | }, 52 | /* 53 | ** Build configuration 54 | */ 55 | serverMiddleware: [ 56 | '~/server/routes/index' 57 | ], 58 | build: { 59 | postcss: { 60 | preset: { 61 | features: { 62 | customProperties: false 63 | } 64 | } 65 | }, 66 | /* 67 | ** You can extend webpack config here 68 | */ 69 | extend(config, ctx) { 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-posts", 3 | "version": "1.0.0", 4 | "description": "My awe-inspiring Nuxt.js project", 5 | "author": "Filip Jerga", 6 | "private": true, 7 | "scripts": { 8 | "dev": "cross-env NODE_ENV=development nodemon server/index.js --watch server", 9 | "build": "nuxt build", 10 | "start": "cross-env NODE_ENV=production node server/index.js", 11 | "generate": "nuxt generate" 12 | }, 13 | "dependencies": { 14 | "@nuxtjs/axios": "^5.3.6", 15 | "@nuxtjs/bulma": "^1.2.1", 16 | "body-parser": "^1.19.0", 17 | "cross-env": "^5.2.0", 18 | "express": "^4.16.4", 19 | "moment": "^2.24.0", 20 | "node-sass": "^4.12.0", 21 | "nuxt": "^2.0.0", 22 | "sass-loader": "^7.1.0" 23 | }, 24 | "devDependencies": { 25 | "nodemon": "^1.18.9" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /pages/README.md: -------------------------------------------------------------------------------- 1 | # PAGES 2 | 3 | This directory contains your Application Views and Routes. 4 | The framework reads all the `*.vue` files inside this directory and creates the router of your application. 5 | 6 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing). 7 | -------------------------------------------------------------------------------- /pages/index.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | 88 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /pages/manage.vue: -------------------------------------------------------------------------------- 1 | 63 | 114 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /pages/posts/_id.vue: -------------------------------------------------------------------------------- 1 | 31 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /plugins/README.md: -------------------------------------------------------------------------------- 1 | # PLUGINS 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains Javascript plugins that you want to run before mounting the root Vue.js application. 6 | 7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/plugins). 8 | -------------------------------------------------------------------------------- /plugins/filters.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import moment from 'moment' 3 | 4 | 5 | Vue.filter('formatDate', (date, dateFormat = 'LL') => { 6 | if (!date) { 7 | return '' 8 | } 9 | 10 | return moment(date).format(dateFormat) 11 | }) 12 | -------------------------------------------------------------------------------- /resources/1_Index-page.html: -------------------------------------------------------------------------------- 1 |
2 | 43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |

Newest Posts

51 |
52 |
53 |
54 | 55 |

Some Title

56 |
Some Subtitle
57 |
58 |
59 | by Filip Jerga, 27th Jan, 2019 60 |
61 |
62 |
63 | 64 |

Some Title

65 |
Some Subtitle
66 |
67 |
68 | by Filip Jerga, 27th Jan, 2019 69 |
70 |
71 |
72 | 73 |
74 | 75 |
76 |
77 |
78 |
79 |
80 | 81 | 82 | .post-content { 83 | font-style: italic; 84 | } 85 | 86 | .post { 87 | margin-bottom: 20px; 88 | padding: 5px; 89 | border-bottom: 2px solid transparent; 90 | } 91 | 92 | .post:hover { 93 | border-bottom: 2px solid #e8e8e8; 94 | } 95 | -------------------------------------------------------------------------------- /resources/2_Checkbox.html: -------------------------------------------------------------------------------- 1 |
2 | 6 |
7 | 8 | 9 | 10 | .post-footer { 11 | font-style: italic; 12 | } 13 | .post { 14 | margin-bottom: 20px; 15 | padding: 5px; 16 | border-bottom: 2px solid transparent; 17 | display: flex; 18 | flex-direction: row; 19 | } 20 | .post-content { 21 | flex: 1; 22 | } 23 | .post-right { 24 | float: right; 25 | justify-content: flex-end; 26 | align-self: center; 27 | } 28 | -------------------------------------------------------------------------------- /resources/3_manage.html: -------------------------------------------------------------------------------- 1 | 124 | 125 | 128 | 129 | 143 | -------------------------------------------------------------------------------- /resources/4_Modal.html: -------------------------------------------------------------------------------- 1 | 2 | 25 | -------------------------------------------------------------------------------- /resources/5_Modal_Form.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 | 6 |
7 |
8 | 9 |
10 | 11 |
12 | 13 |
14 |
15 |
16 | 17 |
18 | 19 |
20 |
21 |
22 | -------------------------------------------------------------------------------- /resources/6_Post_Update.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 | 9 |
10 |
11 |
12 | 13 |
14 | 18 |
19 |
20 |
21 | 22 |
23 | 26 |
27 |
28 | 29 |
30 | -------------------------------------------------------------------------------- /resources/7_delete_button.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | .delete-button { 5 | display: block; 6 | width: 100px; 7 | margin-left: auto; 8 | margin-right: 0; 9 | } 10 | -------------------------------------------------------------------------------- /resources/8_PostDetail.html: -------------------------------------------------------------------------------- 1 | 31 | -------------------------------------------------------------------------------- /server/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const consola = require('consola') 3 | const { Nuxt, Builder } = require('nuxt') 4 | const app = express() 5 | 6 | // Import and Set Nuxt.js options 7 | const config = require('../nuxt.config.js') 8 | config.dev = !(process.env.NODE_ENV === 'production') 9 | 10 | async function start() { 11 | // Init Nuxt.js 12 | const nuxt = new Nuxt(config) 13 | 14 | const { host, port } = nuxt.options.server 15 | 16 | // Build only in dev mode 17 | if (config.dev) { 18 | const builder = new Builder(nuxt) 19 | await builder.build() 20 | } else { 21 | await nuxt.ready() 22 | } 23 | 24 | // Give nuxt middleware to express 25 | app.use(nuxt.render) 26 | 27 | // Listen the server 28 | app.listen(port, host) 29 | consola.ready({ 30 | message: `Server listening on http://${host}:${port}`, 31 | badge: true 32 | }) 33 | } 34 | start() 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /server/routes/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const app = express() 3 | const bodyParser = require('body-parser') 4 | 5 | const fs = require('fs') 6 | const path = require('path') 7 | const filePath = '../../store/initial_data.json' 8 | const initialData = require(filePath) 9 | 10 | app.use(bodyParser.json()) 11 | 12 | app.get('/posts', function(req, res) { 13 | return res.json(initialData.posts) 14 | }) 15 | 16 | app.post('/posts', function(req, res) { 17 | const post = req.body 18 | initialData.posts.push(post) 19 | 20 | fs.writeFile(path.join(__dirname, filePath), JSON.stringify(initialData, null, 2), function(err) { 21 | if (err) { 22 | return res.status(422).send(err) 23 | } 24 | 25 | return res.json('File Sucesfully updated') 26 | }) 27 | }) 28 | 29 | app.patch('/posts/:id', function(req, res) { 30 | const id = req.params.id 31 | const post = req.body 32 | const index = initialData.posts.findIndex(p => p._id === post._id) 33 | initialData.posts[index] = post 34 | 35 | if (index !== -1) { 36 | fs.writeFile(path.join(__dirname, filePath), JSON.stringify(initialData, null, 2), function(err) { 37 | if (err) { 38 | return res.status(422).send(err) 39 | } 40 | 41 | return res.json('File Sucesfully Updated') 42 | }) 43 | } else { 44 | return res.status(422).send({error: 'Post cannot be updated!'}) 45 | } 46 | }) 47 | 48 | // 49 | app.delete('/posts/:id', function(req, res) { 50 | const id = req.params.id 51 | const index = initialData.posts.findIndex(p => p._id === id) 52 | 53 | if (index !== -1) { 54 | initialData.posts.splice(index, 1) 55 | 56 | fs.writeFile(path.join(__dirname, filePath), JSON.stringify(initialData, null, 2), function(err) { 57 | if (err) { 58 | return res.status(422).send(err) 59 | } 60 | 61 | return res.json({message: 'File Sucesfully Updated'}) 62 | }) 63 | } else { 64 | return res.status(422).send({error: 'Post cannot be updated!'}) 65 | } 66 | }) 67 | 68 | 69 | 70 | 71 | module.exports = { 72 | path: '/api', 73 | handler: app 74 | } 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /static/README.md: -------------------------------------------------------------------------------- 1 | # STATIC 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your static files. 6 | Each file inside this directory is mapped to `/`. 7 | Thus you'd want to delete this README.md before deploying to production. 8 | 9 | Example: `/static/robots.txt` is mapped as `/robots.txt`. 10 | 11 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#static). 12 | -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jerga99/nuxt-posts/232ada0ce60800fe9aa91a909f4c28890d59c8ac/static/favicon.ico -------------------------------------------------------------------------------- /store/README.md: -------------------------------------------------------------------------------- 1 | # STORE 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your Vuex Store files. 6 | Vuex Store option is implemented in the Nuxt.js framework. 7 | 8 | Creating a file in this directory automatically activates the option in the framework. 9 | 10 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/vuex-store). 11 | -------------------------------------------------------------------------------- /store/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jerga99/nuxt-posts/232ada0ce60800fe9aa91a909f4c28890d59c8ac/store/index.js -------------------------------------------------------------------------------- /store/initial_data.json: -------------------------------------------------------------------------------- 1 | { 2 | "posts": [ 3 | { 4 | "title": "sdasdasdadasd", 5 | "subtitle": "adadadad", 6 | "content": "adadadda", 7 | "_id": "jg4stma", 8 | "createdAt": 1563560226848 9 | }, 10 | { 11 | "title": "asdada", 12 | "subtitle": "dadada", 13 | "content": "dasdadd", 14 | "_id": "jgx0htk", 15 | "createdAt": 1563560230288 16 | }, 17 | { 18 | "title": "New Post", 19 | "subtitle": "New post with markdown", 20 | "content": "# h1 Heading 8-)\n## h2 Heading\n### h3 Heading\n#### h4 Heading\n##### h5 Heading\n", 21 | "_id": "m9cafnc", 22 | "createdAt": 1563567352609 23 | }, 24 | { 25 | "title": "Amazing New Post! UPDATED", 26 | "subtitle": "Amazing new post subtitle", 27 | "content": "---\n__Advertisement :)__\n\n- __[pica](https://nodeca.github.io/pica/demo/)__ - high quality and fast image\n resize in browser.\n- __[babelfish](https://github.com/nodeca/babelfish/)__ - developer friendly\n i18n with plurals support and easy syntax.\n\nYou will like those projects!\n\n---\n\n# h1 Heading 8-)\n## h2 Heading\n### h3 Heading\n#### h4 Heading\n##### h5 Heading\n###### h6 Heading\n\n\n## Horizontal Rules\n\n___\n\n---\n\n***\n\n\n## Typographic replacements\n\nEnable typographer option to see result.\n\n(c) (C) (r) (R) (tm) (TM) (p) (P) +-\n\ntest.. test... test..... test?..... test!....\n\n!!!!!! ???? ,, -- ---\n\n\"Smartypants, double quotes\" and 'single quotes'", 28 | "_id": "vidi2j3", 29 | "createdAt": 1563612079853 30 | } 31 | ] 32 | } -------------------------------------------------------------------------------- /store/post.js: -------------------------------------------------------------------------------- 1 | 2 | import INITIAL_DATA from './initial_data.json' 3 | import Vue from 'vue' 4 | 5 | 6 | export function fetchPostsAPI() { 7 | return new Promise((resolve, reject) => { 8 | setTimeout(() => { 9 | resolve(INITIAL_DATA.posts) 10 | }, 0) 11 | }) 12 | } 13 | 14 | 15 | export const state = () => { 16 | return { 17 | items: [], 18 | archivedItems: [], 19 | item: {} 20 | } 21 | } 22 | 23 | // Getters are like computed properties but for Vuex 24 | export const getters = { 25 | hasEmptyItems(state) { 26 | return state.items.length === 0 27 | } 28 | } 29 | 30 | // Very good spot to send a request to a server. Usualy Actions resolve into some data 31 | export const actions = { 32 | getArchivedPosts({commit}) { 33 | const archivedPosts = localStorage.getItem('archived_posts') 34 | if (archivedPosts) { 35 | commit('setArchivedPosts', JSON.parse(archivedPosts)) 36 | return archivedPosts 37 | } else { 38 | localStorage.setItem('archived_posts', JSON.stringify([])) 39 | return [] 40 | } 41 | }, 42 | togglePost({state, commit, dispatch}, postId) { 43 | if (state.archivedItems.includes(postId)) { 44 | // remove post id 45 | const index = state.archivedItems.findIndex(pId => pId === postId) 46 | commit('removeArchivedPost', index) 47 | dispatch('persistArchivedPosts') 48 | return postId 49 | } else { 50 | // add Post id 51 | commit('addArchivedPost', postId) 52 | dispatch('persistArchivedPosts') 53 | return postId 54 | } 55 | }, 56 | persistArchivedPosts({state}) { 57 | localStorage.setItem('archived_posts', JSON.stringify(state.archivedItems)) 58 | }, 59 | fetchPosts({commit}) { 60 | return this.$axios.$get('/api/posts') 61 | .then((posts) => { 62 | commit('setPosts', posts) 63 | return posts 64 | }) 65 | }, 66 | fetchPostById({commit}, postId) { 67 | return this.$axios.$get('/api/posts') 68 | .then((posts) => { 69 | const selectedPost = posts.find((p) => p._id === postId) 70 | commit('setPost', selectedPost) 71 | return selectedPost 72 | }) 73 | }, 74 | createPost({commit}, postData) { 75 | postData._id = Math.random().toString(36).substr(2, 7) 76 | postData.createdAt = (new Date()).getTime() 77 | 78 | return this.$axios.$post('/api/posts', postData) 79 | .then((res) => { 80 | commit('addPost', postData) 81 | return postData 82 | }) 83 | }, 84 | updatePost({commit, state}, postData) { 85 | const index = state.items.findIndex((post) => { 86 | return post._id === postData._id 87 | }) 88 | 89 | if (index !== -1) { 90 | return this.$axios.$patch(`/api/posts/${postData._id}`, postData) 91 | .then((res) => { 92 | commit('replacePost', {post: postData, index}) 93 | return postData 94 | }) 95 | } 96 | }, 97 | deletePost({commit, state}, postId) { 98 | const index = state.items.findIndex((post) => { 99 | return post._id === postId 100 | }) 101 | 102 | if (index !== -1) { 103 | return this.$axios.$delete(`/api/posts/${postId}`) 104 | .then((res) => { 105 | commit('deletePost', index) 106 | return postId 107 | }) 108 | } 109 | } 110 | } 111 | 112 | // Mutations are simple functions that have access to a state. 113 | // Mutations are used to assign values to a state 114 | export const mutations = { 115 | setArchivedPosts(state, archivedPosts) { 116 | state.archivedItems = archivedPosts 117 | }, 118 | addArchivedPost(state, postId) { 119 | state.archivedItems.push(postId) 120 | }, 121 | removeArchivedPost(state, index) { 122 | state.archivedItems.splice(index, 1) 123 | }, 124 | setPosts(state, posts) { 125 | state.items = posts 126 | }, 127 | setPost(state, post) { 128 | state.item = post 129 | }, 130 | addPost(state, post) { 131 | state.items.push(post) 132 | }, 133 | replacePost(state, {post, index}) { 134 | Vue.set(state.items, index, post) 135 | }, 136 | deletePost(state, postIndex) { 137 | state.items.splice(postIndex, 1) 138 | } 139 | } 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | --------------------------------------------------------------------------------