Skip to content

Commit

Permalink
Create /login page
Browse files Browse the repository at this point in the history
- Add `Login.vue` file in `src/pages/` directory

- Register `/login` route with `Login.vue`

- Add `<Trash>` icon component
  Create `Trash.vue` file in `src/components/Icon/` directory

- Install firebase & vuexfire
  ``` bash
  npm add firebase vuexfire
  ```

- Configure  firebase
  • Loading branch information
znck committed Feb 3, 2018
1 parent b43729a commit 37bb23b
Show file tree
Hide file tree
Showing 9 changed files with 1,308 additions and 223 deletions.
1,372 changes: 1,161 additions & 211 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion package.json
Expand Up @@ -5,10 +5,12 @@
"private": true,
"main": "src/index.js",
"dependencies": {
"firebase": "^4.9.0",
"marked": "^0.3.12",
"vue": "^2.5.13",
"vue-router": "^3.0.1",
"vuex": "^3.0.1"
"vuex": "^3.0.1",
"vuexfire": "^2.3.0"
},
"devDependencies": {
"@vue/cli": "^3.0.0-alpha.5",
Expand Down
7 changes: 7 additions & 0 deletions src/components/Icon/Trash.vue
@@ -0,0 +1,7 @@
<template>
<svg class="icon" 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">
<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>
</template>

<style scoped src="./icon.css"></style>
4 changes: 3 additions & 1 deletion src/components/Icon/index.js
Expand Up @@ -2,10 +2,12 @@ import Back from './Back.vue'
import Edit from './Edit.vue'
import Preview from './Preview.vue'
import Save from './Save.vue'
import Trash from './Trash.vue'

export {
Back,
Edit,
Preview,
Save
Save,
Trash
}
21 changes: 21 additions & 0 deletions src/firebase.js
@@ -0,0 +1,21 @@
import firebase from 'firebase/app'

import 'firebase/auth'
import 'firebase/database'

// Initialize Firebase
const config = {
apiKey: "AIzaSyD1uFXoNtk4tK4HIX3ikgg7EoFCphAWRaE",
authDomain: "begin-again-workshop.firebaseapp.com",
databaseURL: "https://begin-again-workshop.firebaseio.com",
projectId: "begin-again-workshop",
storageBucket: "begin-again-workshop.appspot.com",
messagingSenderId: "436845609512"
}

firebase.initializeApp(config)
firebase.auth().setPersistence(firebase.auth.Auth.Persistence.LOCAL)

export const db = firebase.database()
export const auth = firebase.auth()
export const authProvider = new firebase.auth.GoogleAuthProvider()
16 changes: 15 additions & 1 deletion src/pages/Home.vue
Expand Up @@ -3,6 +3,7 @@
<header class="header">
<h1>Markdown Notebook</h1>
<router-link tag="button" class="button" :to="{ name: 'create' }">Add New Note</router-link>
<button class="button logout" @click.prevent="logout">Logout</button>
</header>
<main class="notes">
<Note v-for="note in notes"
Expand All @@ -19,6 +20,7 @@
<script>
import { mapGetters } from 'vuex';
import Note from '../components/Note.vue'
import { auth } from '../firebase'
export default {
Expand All @@ -28,7 +30,15 @@ export default {
...mapGetters({ notes: 'notesSortedByLastUpdated' })
},
components: { Note }
components: { Note },
methods: {
async logout () {
await auth.signOut()
this.$router.replace({ name: 'login' })
}
}
}
</script>

Expand All @@ -55,6 +65,10 @@ export default {
cursor: pointer;
}
.logout {
background: #aaa;
}
.notes {
flex: 1;
padding: 45px;
Expand Down
61 changes: 61 additions & 0 deletions src/pages/Login.vue
@@ -0,0 +1,61 @@
<template>
<div class="login-page">
<div>
<h1>Markdown Notebook</h1>
<button class="login" @click.prevent="login">Login</button>

<div class="error" v-if="error">{{ error }}</div>
</div>
</div>
</template>

<script>
import { auth, authProvider } from '../firebase'
export default {
data: () => ({ error: null }),
beforeRouteEnter: (to, from, next) => {
if (auth.currentUser) next({ path: '/' })
else next()
},
methods: {
async login () {
try {
await auth.signInWithPopup(authProvider)
this.$router.push({ path: '/' })
} catch (error) {
this.error = error.message
}
}
}
}
</script>

<style scoped>
.login-page {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
height: 100vh;
}
.login {
background: #768;
border: transparent;
border-radius: 4px;
color: white;
font-size: 1.5rem;
padding: 8px 32px;
cursor: pointer;
}
.error {
margin: 8px 16px;
color: red;
}
</style>

35 changes: 31 additions & 4 deletions src/pages/View.vue
Expand Up @@ -8,19 +8,22 @@
<router-link :to="{ name: 'edit', params: { id } }">
<EditIcon />
</router-link>
<a href="#" @click.prevent="removeNote">
<DeleteIcon />
</a>
</header>
<article class="main">
<Markdown class="preview" :content="note.body" />
</article>
<footer class="footer">
<small>Created: {{ note.createdAt.toDateString() }} {{ note.createdAt.toTimeString() }}</small>
<small style="text-align: right">Last Updated: {{ note.createdAt.toDateString() }} {{ note.createdAt.toTimeString() }}</small>
<small>Created: {{ note.createdAt | formatDate }}</small>
<small style="text-align: right">Last Updated: {{ note.createdAt | formatDate }}</small>
</footer>
</section>
</template>

<script>
import { mapGetters } from 'vuex'
import { mapActions, mapGetters } from 'vuex'
import Markdown from '../components/Markdown.vue'
import * as Icons from '../components/Icon'
Expand Down Expand Up @@ -50,8 +53,32 @@ export default {
components: {
Markdown,
BackIcon: Icons.Back,
EditIcon: Icons.Edit
EditIcon: Icons.Edit,
DeleteIcon: Icons.Trash
},
filters: {
formatDate (date) {
if (!date) return ''
if (typeof date === 'number') date = new Date(date)
return date.toDateString() + ' ' + date.toTimeString()
}
},
methods: {
...mapActions(['remove']),
async removeNote() {
const confirm = window.confirm('Do you want to delete this note?')
if (!confirm) return
await this.remove(this.note)
this.$router.push({ path: '/' })
}
}
}
</script>

Expand Down
11 changes: 6 additions & 5 deletions src/router.js
Expand Up @@ -4,11 +4,12 @@ import Router from 'vue-router'
Vue.use(Router)

const routes = [
{ name: 'home', path: '/notes', component: () => import('./pages/Home.vue') },
{ name: 'create', path: '/notes/create', component: () => import('./pages/Create.vue') },
{ name: 'view', path: '/notes/:id', component: () => import('./pages/View.vue'), props: true },
{ name: 'edit', path: '/notes/:id/edit', component: () => import('./pages/Edit.vue'), props: true },
{ path: '/', redirect: '/notes' }
{ name: 'home', path: '/notes', component: () => import('./pages/Home.vue'), meta: { needsAuth: true } },
{ name: 'create', path: '/notes/create', component: () => import('./pages/Create.vue'), meta: { needsAuth: true } },
{ name: 'view', path: '/notes/:id', component: () => import('./pages/View.vue'), props: true, meta: { needsAuth: true } },
{ name: 'edit', path: '/notes/:id/edit', component: () => import('./pages/Edit.vue'), props: true, meta: { needsAuth: true } },
{ path: '/', redirect: '/notes', meta: { needsAuth: true } },
{ name: 'login', path: '/login', component: () => import('./pages/Login.vue') }
]

export default new Router({ mode: 'history', routes })

0 comments on commit 37bb23b

Please sign in to comment.