├── .eslintrc ├── .firebaserc ├── .gitignore ├── LICENSE ├── README.md ├── database-rules.json ├── dist ├── 52a05e731e61db85e7d96bf3f10d919c.png ├── 80527ac68a7bc8cd3fed705fb73a7174.png ├── 9523da15d21a8526f31920a99994a44b.png ├── index.html └── main.js ├── docs └── screen-shot.jpg ├── firebase.json ├── package.json ├── settings.js.org ├── src ├── index.html └── js │ ├── App.vue │ ├── api │ ├── firebase.js │ └── localstrage.js │ ├── assets │ ├── btn_google_signin_light_focus_web@2x.png │ ├── btn_google_signin_light_normal_web@2x.png │ └── btn_google_signin_light_pressed_web@2x.png │ ├── components │ ├── AppHeader.vue │ ├── Editor.vue │ ├── Index.vue │ ├── Memo.vue │ └── Viewer.vue │ ├── main.js │ ├── router │ └── index.js │ └── vuex │ └── index.js └── webpack.config.js /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "babel-eslint", 4 | "extends": "vue", 5 | "plugins": ["flow-vars"], 6 | "globals": { 7 | "$": true, 8 | "_App": true, 9 | "Env": true, 10 | "Materialize": true 11 | }, 12 | "rules": { 13 | "flow-vars/define-flow-type": 1, 14 | "flow-vars/use-flow-type": 1 15 | } 16 | } -------------------------------------------------------------------------------- /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "production": "vue-memo" 4 | } 5 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | .sass-cache 4 | settings.js 5 | *.log -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2017 Akiho Nagao 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Dependencies 2 | 3 | - Vue.js(>2.x.) 4 | - vue-router(>2.x.) 5 | - vuex(>2.x.) 6 | - vuex-router-sync(>3.x.) @next 7 | - Firebase(>3.6.x) 8 | - marked(>0.3.x) 9 | - webpack(>1.13.x) 10 | - babel-core(>6.18.x) 11 | - babel-presett-es2015 12 | - babel-presett-stage-2 13 | 14 | ## Introduction 15 | Vue-memo is a personal project created to deepen the understanding of Vue.js. 16 | I will wait for Pull Request. 17 | 18 | ![App Screen Shop](https://github.com/akifo/vue-memo/raw/dev/docs/screen-shot.jpg) 19 | 20 | ## Before Start 21 | 22 | 1. Create Firebase Project 23 | 2. To enable Google Authentication Sign-In 24 | 3. Entry Environment Variables 25 | 26 | ``` bash 27 | # create settings.js 28 | cp settings.js.org settings.js 29 | # paste from Firebase config 30 | vim settings.js 31 | ``` 32 | 33 | ## Development Setup 34 | 35 | ``` bash 36 | # install deps: 37 | npm install 38 | # serve examples at localhost:8080: 39 | npm run dev 40 | # build dist files: 41 | npm run build 42 | ``` 43 | 44 | ## Deploy to Firebase 45 | 46 | ```bash 47 | firebase login 48 | firebase use --add 49 | # select your project, and then... 50 | npm run deploy 51 | ``` 52 | 53 | ## Demo 54 | 55 | [demo site](https://vue-memo.firebaseapp.com/) 56 | -------------------------------------------------------------------------------- /database-rules.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | ".read": true, 4 | "users": { 5 | "$uid": { 6 | ".write": "auth !== null && auth.uid === $uid", 7 | "name": { 8 | ".validate": "newData.isString() && 2 <= newData.val().length && newData.val().length <= 100" 9 | } 10 | } 11 | }, 12 | "memos": { 13 | "$uid": { 14 | ".write": "auth !== null && auth.uid === $uid", 15 | "$mid": { 16 | "title": { 17 | ".validate": "newData.isString() && newData.val().length <= 200" 18 | }, 19 | "body": { 20 | ".validate": "newData.isString() && newData.val().length <= 4000" 21 | }, 22 | "created": { 23 | ".validate": "newData.isNumber() && newData.val() < now + 5000" 24 | }, 25 | "modified": { 26 | ".validate": "newData.isNumber() && newData.val() < now + 5000" 27 | } 28 | }, 29 | ".indexOn": ["created"] 30 | } 31 | }, 32 | "publicMemos": { 33 | "$mid": { 34 | ".write": "root.child('memos/' + auth.uid ).hasChild($mid)", 35 | "title": { 36 | ".validate": "newData.isString() && newData.val().length <= 200" 37 | }, 38 | "body": { 39 | ".validate": "newData.isString() && newData.val().length <= 4000" 40 | }, 41 | "created": { 42 | ".validate": "newData.isNumber() && newData.val() < now + 5000" 43 | }, 44 | "modified": { 45 | ".validate": "newData.isNumber() && newData.val() < now + 5000" 46 | }, 47 | "author": { 48 | "uid": { 49 | ".validate": "newData.val() == auth.uid" 50 | }, 51 | "name": { 52 | ".validate": "newData.isString() && 2 <= newData.val().length && newData.val().length <= 100" 53 | } 54 | } 55 | }, 56 | ".indexOn": ["created"] 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /dist/52a05e731e61db85e7d96bf3f10d919c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akifo/vue-memo/a1dfb8a20c73901f6dc9b9379875391da7e63857/dist/52a05e731e61db85e7d96bf3f10d919c.png -------------------------------------------------------------------------------- /dist/80527ac68a7bc8cd3fed705fb73a7174.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akifo/vue-memo/a1dfb8a20c73901f6dc9b9379875391da7e63857/dist/80527ac68a7bc8cd3fed705fb73a7174.png -------------------------------------------------------------------------------- /dist/9523da15d21a8526f31920a99994a44b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akifo/vue-memo/a1dfb8a20c73901f6dc9b9379875391da7e63857/dist/9523da15d21a8526f31920a99994a44b.png -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Vue-memo 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/screen-shot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akifo/vue-memo/a1dfb8a20c73901f6dc9b9379875391da7e63857/docs/screen-shot.jpg -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "database": { 3 | "rules": "database-rules.json" 4 | }, 5 | "hosting": { 6 | "public": "dist", 7 | "ignore": [ 8 | "firebase.json", 9 | "database-rules.json", 10 | "**/.*", 11 | "package.json", 12 | "**/node_modules/**" 13 | ] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-memo", 3 | "repository": "https://github.com/akifo/vue-memo", 4 | "license": "MIT", 5 | "version": "2.0.0", 6 | "description": "Vue-memo is a personal project created to deepen the understanding of Vue.js.", 7 | "author": "Akiho Nagao", 8 | "main": "dist/main.js", 9 | "scripts": { 10 | "build": "webpack --progress --hide-modules --content-base dist", 11 | "dev": "webpack-dev-server --open --inline --hot --content-base dist", 12 | "deploy": "firebase deploy" 13 | }, 14 | "devDependencies": { 15 | "babel-core": "^6.18.2", 16 | "babel-eslint": "^7.1.1", 17 | "babel-loader": "^6.2.7", 18 | "babel-plugin-transform-runtime": "^6.15.0", 19 | "babel-polyfill": "^6.16.0", 20 | "babel-preset-es2015": "^6.18.0", 21 | "babel-preset-stage-2": "^6.18.0", 22 | "babel-runtime": "^6.18.0", 23 | "copy-webpack-plugin": "^4.0.1", 24 | "css-loader": "^0.28.1", 25 | "eslint": "^3.11.1", 26 | "eslint-config-vue": "^2.0.1", 27 | "eslint-plugin-flow-vars": "^0.5.0", 28 | "eslint-plugin-html": "^1.7.0", 29 | "eslint-plugin-vue": "^1.0.0", 30 | "file-loader": "^0.9.0", 31 | "stylus": "^0.54.5", 32 | "stylus-loader": "^2.4.0", 33 | "vue-hot-reload-api": "^2.0.6", 34 | "vue-loader": "^9.9.0", 35 | "webpack": "^1.13.3", 36 | "webpack-dev-server": "^1.16.2" 37 | }, 38 | "dependencies": { 39 | "firebase": "^3.6.2", 40 | "lodash": "^4.17.2", 41 | "marked": "^0.3.6", 42 | "moment": "^2.17.0", 43 | "vue": "^2.1.3", 44 | "vue-router": "^2.0.3", 45 | "vuex": "^2.0.0", 46 | "vuex-router-sync": "^3.0.0" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /settings.js.org: -------------------------------------------------------------------------------- 1 | const Env = { 2 | firebase: { 3 | apiKey: "", 4 | authDomain: "", 5 | databaseURL: "", 6 | storageBucket: "", 7 | messagingSenderId: "" 8 | } 9 | } 10 | 11 | export default Env 12 | global.Env = Env 13 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Vue-memo 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/js/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 21 | 22 | 27 | -------------------------------------------------------------------------------- /src/js/api/firebase.js: -------------------------------------------------------------------------------- 1 | import firebase from 'firebase' 2 | import moment from 'moment' 3 | 4 | // initialize Firebase 5 | firebase.initializeApp(Env.firebase) 6 | var auth = firebase.auth() 7 | var database = firebase.database() 8 | 9 | // variable 10 | var _userInfo = {} 11 | var _memos = {} 12 | var _userRef = null 13 | var _publicMemosRef = null 14 | var _myMemosRef = null 15 | var _fetchedPublicCount = 0 16 | var _fetchedMyselfCount = 0 17 | 18 | export default { 19 | 20 | // Sets up shortcuts to Firebase features and initiate firebase auth. 21 | initFirebase () { 22 | // Initiates Firebase auth and listen to auth state changes. 23 | auth.onAuthStateChanged(this.onAuthStateChanged.bind(this)) 24 | }, 25 | 26 | getAuth () { 27 | return auth.currentUser || {} 28 | }, 29 | 30 | // Signs-in 31 | signIn () { 32 | // Sign in Firebase using popup auth and Google as the identity provider. 33 | var provider = new firebase.auth.GoogleAuthProvider() 34 | auth.signInWithPopup(provider) 35 | }, 36 | 37 | // Signs-out 38 | signOut () { 39 | // Sign out of Firebase. 40 | auth.signOut() 41 | }, 42 | 43 | // Triggers when the auth state change for instance when the user signs-in or signs-out. 44 | onAuthStateChanged (user) { 45 | if (user) { // User is signed in! 46 | this.fetchUserInfo(user.uid) 47 | .then(val => { 48 | _userInfo = { 49 | loggedIn: true, 50 | uid: user.uid, 51 | name: val.name || user.displayName, 52 | profilePicUrl: user.photoURL 53 | } 54 | _App.$store.dispatch('onAuthStateChanged', Object.assign({}, _userInfo)) 55 | }).catch(() => { 56 | _userInfo = { 57 | loggedIn: true, 58 | uid: user.uid, 59 | name: user.displayName, 60 | profilePicUrl: user.photoURL 61 | } 62 | _App.$store.dispatch('onAuthStateChanged', Object.assign({}, _userInfo)) 63 | }) 64 | } else { 65 | _userInfo = { 66 | loggedIn: false, 67 | uid: '', 68 | name: 'guest', 69 | profilePicUrl: '' 70 | } 71 | _App.$store.dispatch('onAuthStateChanged', Object.assign({}, _userInfo)) 72 | } 73 | }, 74 | 75 | fetchUserInfo (uid) { 76 | return new Promise((resolve, reject) => { 77 | _userRef = database.ref('users') 78 | _userRef.child(uid).once('value') 79 | .then(snapshot => { 80 | const user = snapshot.val() 81 | resolve(user) 82 | }).catch(reject) 83 | }) 84 | }, 85 | 86 | setUserInfo (key, val) { 87 | return new Promise((resolve, reject) => { 88 | if (key && val && this.checkSignedInWithMessage()) { 89 | _userRef = database.ref('users').child(_userInfo.uid).child(key) 90 | _userRef.set(val) 91 | .then(() => { 92 | _userInfo[key] = val 93 | resolve() 94 | }).catch(reject) 95 | } 96 | }) 97 | }, 98 | 99 | checkSignedInWithMessage () { 100 | if (auth.currentUser) return true 101 | return false 102 | }, 103 | 104 | fetchMemo (key) { 105 | return new Promise((resolve, reject) => { 106 | _publicMemosRef = database.ref('publicMemos').child(key) 107 | _publicMemosRef.once('value') 108 | .then(snapshot => { 109 | const memo = snapshot.val() 110 | _memos[key] = memo 111 | resolve({ 112 | memo: Object.assign({}, memo), 113 | key: key 114 | }) 115 | }).catch(reject) 116 | }) 117 | }, 118 | 119 | fetchMemos (count, type) { 120 | return new Promise((resolve, reject) => { 121 | if (type === 'public') { 122 | _fetchedPublicCount += count 123 | _publicMemosRef = database.ref('publicMemos') 124 | _publicMemosRef.orderByChild('created').limitToLast(_fetchedPublicCount).once('value') 125 | .then(snapshot => { 126 | const memo = snapshot.val() || {} 127 | Object.keys(memo).forEach(key => { 128 | _memos[key] = memo[key] 129 | }) 130 | resolve(Object.assign({}, _memos)) 131 | }).catch(reject) 132 | } else if (type === 'myself' && this.checkSignedInWithMessage()) { 133 | _fetchedMyselfCount += count 134 | _myMemosRef = database.ref('memos').child(_userInfo.uid) 135 | _myMemosRef.orderByChild('created').limitToLast(_fetchedMyselfCount).once('value') 136 | .then(snapshot => { 137 | const memo = snapshot.val() || {} 138 | Object.keys(memo).forEach(key => { 139 | _memos[key] = memo[key] 140 | _memos[key].author = { 141 | uid: _userInfo.uid, 142 | name: _userInfo.name 143 | } 144 | }) 145 | resolve(Object.assign({}, _memos)) 146 | }).catch(reject) 147 | } else reject('required login for myself timeline') 148 | }) 149 | }, 150 | 151 | addMemo (memo) { 152 | return new Promise((resolve, reject) => { 153 | // Check that the user entered a message and is signed in. 154 | if (memo && this.checkSignedInWithMessage()) { 155 | _myMemosRef = database.ref('memos').child(_userInfo.uid) 156 | var key = '' 157 | const now = parseInt(moment().format('x')) 158 | _myMemosRef.push({ 159 | title: memo.title, 160 | body: memo.body, 161 | created: now, 162 | modified: now 163 | }).then(val => { 164 | key = val.key 165 | _publicMemosRef = database.ref('publicMemos').child(key) 166 | return _publicMemosRef.set({ 167 | title: memo.title, 168 | body: memo.body, 169 | created: now, 170 | modified: now, 171 | author: { 172 | uid: _userInfo.uid, 173 | name: _userInfo.name 174 | } 175 | }) 176 | }).then(() => { 177 | _memos[key] = memo 178 | resolve({ 179 | memo: Object.assign({}, { 180 | created: now, 181 | modified: now, 182 | author: { 183 | uid: _userInfo.uid, 184 | name: _userInfo.name 185 | } 186 | }, memo), 187 | key: key 188 | }) 189 | }).catch(reject) 190 | } 191 | }) 192 | }, 193 | 194 | deleteMemo (key) { 195 | return new Promise((resolve, reject) => { 196 | if (key && this.checkSignedInWithMessage()) { 197 | _publicMemosRef = database.ref('publicMemos').child(key) 198 | _publicMemosRef.remove() 199 | .then(() => { 200 | _myMemosRef = database.ref('memos').child(_userInfo.uid).child(key) 201 | return _myMemosRef.remove() 202 | }).then(() => { 203 | resolve(key) 204 | delete _memos[key] 205 | }).catch(reject) 206 | } 207 | }) 208 | }, 209 | 210 | updateMemo (key, memo) { 211 | return new Promise((resolve, reject) => { 212 | if (memo && this.checkSignedInWithMessage()) { 213 | _myMemosRef = database.ref('memos').child(memo.author.uid).child(key) 214 | const now = parseInt(moment().format('x')) 215 | _myMemosRef.set({ 216 | title: memo.title, 217 | body: memo.body, 218 | created: memo.created, 219 | modified: now 220 | }).then(() => { 221 | _publicMemosRef = database.ref('publicMemos').child(key) 222 | return _publicMemosRef.set({ 223 | title: memo.title, 224 | body: memo.body, 225 | created: memo.created, 226 | modified: now, 227 | author: { 228 | uid: memo.author.uid, 229 | name: memo.author.name 230 | } 231 | }) 232 | }).then(() => { 233 | _memos[key] = memo 234 | resolve() 235 | }).catch(reject) 236 | } 237 | }) 238 | } 239 | 240 | } 241 | -------------------------------------------------------------------------------- /src/js/api/localstrage.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /src/js/assets/btn_google_signin_light_focus_web@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akifo/vue-memo/a1dfb8a20c73901f6dc9b9379875391da7e63857/src/js/assets/btn_google_signin_light_focus_web@2x.png -------------------------------------------------------------------------------- /src/js/assets/btn_google_signin_light_normal_web@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akifo/vue-memo/a1dfb8a20c73901f6dc9b9379875391da7e63857/src/js/assets/btn_google_signin_light_normal_web@2x.png -------------------------------------------------------------------------------- /src/js/assets/btn_google_signin_light_pressed_web@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akifo/vue-memo/a1dfb8a20c73901f6dc9b9379875391da7e63857/src/js/assets/btn_google_signin_light_pressed_web@2x.png -------------------------------------------------------------------------------- /src/js/components/AppHeader.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 61 | 62 | 108 | -------------------------------------------------------------------------------- /src/js/components/Editor.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 83 | 84 | -------------------------------------------------------------------------------- /src/js/components/Index.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 63 | 64 | 75 | -------------------------------------------------------------------------------- /src/js/components/Memo.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 16 | 17 | 38 | -------------------------------------------------------------------------------- /src/js/components/Viewer.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 57 | 58 | -------------------------------------------------------------------------------- /src/js/main.js: -------------------------------------------------------------------------------- 1 | import 'babel-polyfill' 2 | import './../../settings' 3 | import Vue from 'vue' 4 | import App from './App' 5 | import { sync } from 'vuex-router-sync' 6 | import store from './vuex' 7 | import router from './router' 8 | import Firebase from './api/firebase' 9 | import moment from 'moment' 10 | 11 | // for debugging 12 | if (process.env.NODE_ENV !== 'production') Vue.config.debug = true 13 | 14 | sync(store, router) 15 | Firebase.initFirebase() 16 | 17 | Vue.filter('formatDate', function (value, format) { 18 | return moment(value).format('YYYY.MM.DD hh:mm:ss') 19 | }) 20 | 21 | const app = new Vue({ 22 | router, 23 | store, 24 | el: '#app', 25 | render: h => h(App) 26 | }) 27 | 28 | global._App = app 29 | -------------------------------------------------------------------------------- /src/js/router/index.js: -------------------------------------------------------------------------------- 1 | import VueRouter from 'vue-router' 2 | import Vue from 'vue' 3 | import Index from '../components/Index' 4 | import Editor from '../components/Editor' 5 | import Viewer from '../components/Viewer' 6 | 7 | Vue.use(VueRouter) 8 | 9 | var router = new VueRouter({ 10 | routes: [ 11 | { 12 | path: '/', 13 | name: 'index', 14 | component: Index 15 | }, { 16 | path: '/editor', 17 | name: 'newEditor', 18 | component: Editor 19 | }, { 20 | path: '/editor/:id', 21 | name: 'updateEditor', 22 | component: Editor 23 | }, { 24 | path: '/viewer/:id', 25 | name: 'viewer', 26 | component: Viewer 27 | } 28 | ] 29 | }) 30 | 31 | export default router 32 | -------------------------------------------------------------------------------- /src/js/vuex/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import Firebase from './../api/firebase' 4 | // import LocalStrage from './../api/localstrage' 5 | 6 | Vue.use(Vuex) 7 | 8 | const debug = process.env.NODE_ENV !== 'production' 9 | 10 | const state = { 11 | user: { 12 | loggedIn: false, 13 | uid: '', 14 | name: '', 15 | profilePicUrl: '' 16 | }, 17 | memos: {} 18 | // route: {} // vue-router has created state.route 19 | } 20 | 21 | const mutations = { 22 | 23 | onAuthStateChanged (state, { user }) { 24 | state.user = user 25 | }, 26 | 27 | setUser (state, { key, val }) { 28 | Vue.set(state.user, key, val) 29 | }, 30 | 31 | setMemo (state, { key, memo }) { 32 | Vue.set(state.memos, key, memo) 33 | }, 34 | 35 | setMemos (state, { memos }) { 36 | state.memos = memos || {} 37 | }, 38 | 39 | deleteMemo (state, { key }) { 40 | Vue.delete(state.memos, key) 41 | } 42 | 43 | } 44 | 45 | const actions = { 46 | 47 | onAuthStateChanged ({ commit }, user) { 48 | commit('onAuthStateChanged', { user }) 49 | }, 50 | 51 | signIn () { 52 | Firebase.signIn() 53 | }, 54 | 55 | signOut () { 56 | Firebase.signOut() 57 | }, 58 | 59 | setUserInfo ({ commit, state }, { key, val }) { 60 | return new Promise((resolve, reject) => { 61 | if (state.user.loggedIn) { // is signed in. Firebase 62 | Firebase.setUserInfo(key, val) 63 | .then(() => { 64 | commit('setUser', { key, val }) 65 | resolve() 66 | }).catch(reject) 67 | } else { // is signed out. Localstrage 68 | reject('still dev for guest') 69 | } 70 | }) 71 | }, 72 | 73 | fetchMemo ({ commit, state }) { 74 | Firebase.fetchMemo(state.route.params.id) 75 | .then(obj => { 76 | commit('setMemo', { 77 | key: obj.key, 78 | memo: obj.memo 79 | }) 80 | }) 81 | }, 82 | 83 | fetchMemos ({ commit }, { count, type }) { 84 | if (state.user.loggedIn || type === 'public') { // is signed in. Firebase 85 | Firebase.fetchMemos(count, type) 86 | .then(memos => { 87 | commit('setMemos', { memos }) 88 | }) 89 | } else { // is signed out. Localstrage 90 | } 91 | }, 92 | 93 | addMemo ({ commit, state }, memo) { 94 | return new Promise((resolve, reject) => { 95 | if (state.user.loggedIn) { // is signed in. Firebase 96 | Firebase.addMemo(memo) 97 | .then(obj => { 98 | commit('setMemo', { 99 | key: obj.key, 100 | memo: obj.memo 101 | }) 102 | resolve(obj.key) 103 | }).catch(err => { 104 | reject() 105 | }) 106 | } else { // is signed out. Localstrage 107 | reject('still dev for guest') 108 | } 109 | }) 110 | }, 111 | 112 | deleteMemo ({ commit, state }) { 113 | return new Promise((resolve, reject) => { 114 | if (state.user.loggedIn) { // is signed in. Firebase 115 | Firebase.deleteMemo(state.route.params.id) 116 | .then(key => { 117 | commit('deleteMemo', { key }) 118 | resolve() 119 | }).catch(reject) 120 | } else { // is signed out. Localstrage 121 | reject('still dev for guest') 122 | } 123 | }) 124 | }, 125 | 126 | updateMemo ({ commit, state }, memo) { 127 | return new Promise((resolve, reject) => { 128 | if (state.user.loggedIn) { // is signed in. Firebase 129 | const key = state.route.params.id 130 | Firebase.updateMemo(key, memo) 131 | .then(() => { 132 | commit('setMemo', { key, memo }) 133 | resolve(key) 134 | }).catch(reject) 135 | } else { // is signed out. Localstrage 136 | reject('still dev for guest') 137 | } 138 | }) 139 | } 140 | 141 | } 142 | 143 | const getters = { 144 | memos: state => state.memos, 145 | currentMemoID: ({ route }) => route.params.id, 146 | currentMemo: state => { 147 | return state.route.params.id 148 | ? state.memos[state.route.params.id] 149 | : {} 150 | }, 151 | user: state => state.user, 152 | currentUserName: state => state.user.name, 153 | currentUserId: state => state.user.uid 154 | } 155 | 156 | export default new Vuex.Store({ 157 | state, 158 | getters, 159 | actions, 160 | mutations, 161 | strict: debug 162 | }) 163 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | const path = require('path') 3 | const CopyWebpackPlugin = require('copy-webpack-plugin') 4 | 5 | module.exports = { 6 | context: path.join(__dirname, '/src'), 7 | entry: { 8 | main: './js/main.js' 9 | }, 10 | output: { 11 | path: path.join(__dirname, 'dist'), 12 | filename: '[name].js' 13 | }, 14 | devtool: 'inline-source-map', 15 | resolve: { 16 | extensions: ['', '.js', '.vue'] 17 | }, 18 | module: { 19 | loaders: [ 20 | { 21 | test: /\.js$/, 22 | exclude: /node_modules/, 23 | loader: 'babel' 24 | }, { 25 | test: /\.vue$/, 26 | loader: 'vue' 27 | }, 28 | { 29 | test: /\.(png|jpg|gif|svg)$/, 30 | loader: 'file-loader', 31 | options: { 32 | name: '[name].[ext]?[hash]' 33 | } 34 | } 35 | ] 36 | }, 37 | babel: { 38 | presets: ['es2015', 'stage-2'], 39 | plugins: ['transform-runtime'], 40 | comments: false 41 | }, 42 | plugins: [ 43 | new webpack.DefinePlugin({ 44 | 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development') 45 | }), 46 | new webpack.HotModuleReplacementPlugin(), 47 | new CopyWebpackPlugin([ 48 | { from: './index.html' } 49 | ]) 50 | ] 51 | } 52 | --------------------------------------------------------------------------------