Skip to content

Commit

Permalink
Add firebase auth and database support
Browse files Browse the repository at this point in the history
- Add router navigation guard to redirect unauthenticated user to `/login` page

- Use **vuexfire** to integrate firebase database with vuex

- Initialize firebase and vuex state when `<App>` is created
  • Loading branch information
znck committed Feb 3, 2018
1 parent 37bb23b commit 39498fb
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 63 deletions.
6 changes: 5 additions & 1 deletion src/App.vue
Expand Up @@ -6,7 +6,11 @@

<script>
export default {
name: 'MarkdownNotebook'
name: 'MarkdownNotebook',
created () {
this.$store.dispatch('init')
}
}
</script>

Expand Down
9 changes: 9 additions & 0 deletions src/index.js
Expand Up @@ -2,6 +2,15 @@ import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import { auth } from './firebase'

router.beforeEach(async (to, from, next) => {
if (to.matched.some(record => record.meta.needsAuth) && !auth.currentUser) {
return next({ name: 'login' })
} else {
return next()
}
})

new Vue({
el: '#app',
Expand Down
92 changes: 30 additions & 62 deletions src/store.js
@@ -1,102 +1,70 @@
import Vue from 'vue'
import Vuex, { Store } from 'vuex'
import { desc, uuid } from './utils'
import { firebaseMutations, firebaseAction } from 'vuexfire'

Vue.use(Vuex)

const CREATE = 'CREATE'
const UPDATE = 'UPDATE'

function readFromLocalStorage(key, defaultValue) {
const dateFormat = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z$/

function reviver(key, value) {
if (typeof value === 'string' && dateFormat.test(value)) {
return new Date(value)
}

return value
}

const value = localStorage.getItem(key)

if (!value) return defaultValue
import { db } from './firebase'
import { uuid, desc } from './utils'

try {
return JSON.parse(value, reviver)
} catch (e) {
localStorage.removeItem(key)
}
Vue.use(Vuex)

return defaultValue
}
const notesRef = db.ref('notes')

const getters = {
noteById: ({ notes }) => id => notes.find(it => it.id === id),
notesSortedByLastUpdated: ({ notes }) => notes.slice().sort((a, b) => desc(a.updatedAt, b.updatedAt))
}

const state = () => ({
notes: readFromLocalStorage('notebook', [])
notes: []
})

const mutations = {
[CREATE]: (state, note) => { state.notes.push(note) },
[UPDATE]: (state, [old, note]) => { state.notes.splice(state.notes.indexOf(old), 1, note) }
}

const actions = {
async save({ dispatch }, payload) {
if (payload.id) return dispatch('update', payload)
init: firebaseAction(({ bindFirebaseRef }) => bindFirebaseRef('notes', notesRef)),

return dispatch('create', payload)
async save({ dispatch }, payload) {
return await dispatch(payload.id ? 'update' : 'create', payload)
},

async create({ commit }, { title, body }) {
const timestamp = new Date()
const note = {
async create(_, { title, body }) {
const newNoteRef = notesRef.push()
const timestamp = Date.now()
const payload = {
id: uuid(),
title,
body,
createdAt: timestamp,
updatedAt: timestamp
}

commit(CREATE, note)
await newNoteRef.set(payload)

return note
return payload
},

async update({ commit, getters }, { id, title, body }) {
const note = getters.noteById(id)
async update(_, item) {
const note = getters.noteById(item.id)

if (!note) throw Error('Cannot update non-existing note.')
await notesRef.child(note['.key']).update({
updatedAt: Date.now(),
...item
})

const payload = {
...note,
id,
title,
body,
updatedAt: new Date()
}

commit(UPDATE, [note, payload])
return note
},

return payload
async remove(_, item) {
await notesRef.child(item['.key']).remove()
}
}

const store = new Store({
const mutations = {
...firebaseMutations
}

export default new Store({
getters,
state,
mutations,
actions
})

store.subscribe((mutation, state) => {
if (mutation.type === CREATE || mutation.type === UPDATE) {
localStorage.setItem('notebook', JSON.stringify(state.notes))
}
})

export default store
24 changes: 24 additions & 0 deletions src/utils.js
Expand Up @@ -20,4 +20,28 @@ export function asc(a, b) {

export function desc(a, b) {
return - asc(a, b)
}

export function readFromLocalStorage(key, defaultValue) {
const dateFormat = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z$/

function reviver(key, value) {
if (typeof value === 'string' && dateFormat.test(value)) {
return new Date(value)
}

return value
}

const value = localStorage.getItem(key)

if (!value) return defaultValue

try {
return JSON.parse(value, reviver)
} catch (e) {
localStorage.removeItem(key)
}

return defaultValue
}
6 changes: 6 additions & 0 deletions test/components/Icon/__snapshots__/index.spec.js.snap
Expand Up @@ -23,3 +23,9 @@ exports[`<SaveIcon> snapshot 1`] = `
<path d="M3 12h6v-3h-6v3zM10 12h1v-7q0-0.109-0.078-0.301t-0.156-0.27l-2.195-2.195q-0.078-0.078-0.266-0.156t-0.305-0.078v3.25q0 0.312-0.219 0.531t-0.531 0.219h-4.5q-0.312 0-0.531-0.219t-0.219-0.531v-3.25h-1v10h1v-3.25q0-0.312 0.219-0.531t0.531-0.219h6.5q0.312 0 0.531 0.219t0.219 0.531v3.25zM7 4.75v-2.5q0-0.102-0.074-0.176t-0.176-0.074h-1.5q-0.102 0-0.176 0.074t-0.074 0.176v2.5q0 0.102 0.074 0.176t0.176 0.074h1.5q0.102 0 0.176-0.074t0.074-0.176zM12 5v7.25q0 0.312-0.219 0.531t-0.531 0.219h-10.5q-0.312 0-0.531-0.219t-0.219-0.531v-10.5q0-0.312 0.219-0.531t0.531-0.219h7.25q0.312 0 0.688 0.156t0.594 0.375l2.188 2.187q0.219 0.219 0.375 0.594t0.156 0.688z"></path>
</svg>
`;
exports[`<TrashIcon> snapshot 1`] = `
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="11" height="14" viewBox="0 0 11 14" class="icon">
<path d="M4 5.75v4.5q0 0.109-0.070 0.18t-0.18 0.070h-0.5q-0.109 0-0.18-0.070t-0.070-0.18v-4.5q0-0.109 0.070-0.18t0.18-0.070h0.5q0.109 0 0.18 0.070t0.070 0.18zM6 5.75v4.5q0 0.109-0.070 0.18t-0.18 0.070h-0.5q-0.109 0-0.18-0.070t-0.070-0.18v-4.5q0-0.109 0.070-0.18t0.18-0.070h0.5q0.109 0 0.18 0.070t0.070 0.18zM8 5.75v4.5q0 0.109-0.070 0.18t-0.18 0.070h-0.5q-0.109 0-0.18-0.070t-0.070-0.18v-4.5q0-0.109 0.070-0.18t0.18-0.070h0.5q0.109 0 0.18 0.070t0.070 0.18zM9 11.406v-7.406h-7v7.406q0 0.172 0.055 0.316t0.113 0.211 0.082 0.066h6.5q0.023 0 0.082-0.066t0.113-0.211 0.055-0.316zM3.75 3h3.5l-0.375-0.914q-0.055-0.070-0.133-0.086h-2.477q-0.078 0.016-0.133 0.086zM11 3.25v0.5q0 0.109-0.070 0.18t-0.18 0.070h-0.75v7.406q0 0.648-0.367 1.121t-0.883 0.473h-6.5q-0.516 0-0.883-0.457t-0.367-1.105v-7.438h-0.75q-0.109 0-0.18-0.070t-0.070-0.18v-0.5q0-0.109 0.070-0.18t0.18-0.070h2.414l0.547-1.305q0.117-0.289 0.422-0.492t0.617-0.203h2.5q0.312 0 0.617 0.203t0.422 0.492l0.547 1.305h2.414q0.109 0 0.18 0.070t0.070 0.18z"></path>
</svg>
`;

0 comments on commit 39498fb

Please sign in to comment.