├── .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 | 
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 |
2 |
6 |
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 |
2 |
18 |
19 |
20 |
61 |
62 |
108 |
--------------------------------------------------------------------------------
/src/js/components/Editor.vue:
--------------------------------------------------------------------------------
1 |
2 |
22 |
23 |
24 |
83 |
84 |
--------------------------------------------------------------------------------
/src/js/components/Index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
12 |
15 |
16 | add
17 |
18 |
19 |
20 |
21 |
63 |
64 |
75 |
--------------------------------------------------------------------------------
/src/js/components/Memo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{memo.title}}
5 | {{memo.author.name}} | {{memo.created | formatDate }}
6 |
7 |
8 |
9 |
10 |
16 |
17 |
38 |
--------------------------------------------------------------------------------
/src/js/components/Viewer.vue:
--------------------------------------------------------------------------------
1 |
2 |
14 |
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 |
--------------------------------------------------------------------------------