Large refactor on the front end

Created pages directory
Added night mode
This commit is contained in:
Max G 2019-07-30 19:10:31 +00:00
parent fcee24a61d
commit 7806a206b2
14 changed files with 98 additions and 79 deletions

View File

@ -37,6 +37,11 @@ export default {
}, },
beforeCreate: function(){ beforeCreate: function(){
//Set color theme based on local storage
if(localStorage.getItem('nightMode') == 'true'){
this.$store.commit('toggleNightMode')
}
//Puts token into state on page load //Puts token into state on page load
let token = localStorage.getItem('loginToken') let token = localStorage.getItem('loginToken')
let username = localStorage.getItem('username') let username = localStorage.getItem('username')

View File

@ -1,24 +1,10 @@
:root { :root {
--primary_color: #1C84DA;
--secondary_color: #1EAEDB;
--element_background_color: #FFF;
--background_color: #fff; --background_color: #fff;
--text_color: #3d3d3d; --text_color: #3d3d3d;
--outline_color: rgba(34,36,38,.15); --outline_color: rgba(34,36,38,.15);
} }
/* Night mode colors */
:root {
--background_color: #000;
--text_color: #a98457;
--outline_color: #a98457;
}
/* OVERWRITE DEFAULT SEMANTIC STYLES FOR CUSTOM/NIGHT MODES*/ /* OVERWRITE DEFAULT SEMANTIC STYLES FOR CUSTOM/NIGHT MODES*/
body{ body{
color: var(--text_color); color: var(--text_color);

View File

@ -63,7 +63,7 @@
name: 'InputNotes', name: 'InputNotes',
props: [ 'noteid', 'position' ], props: [ 'noteid', 'position' ],
components:{ components:{
'note-tag-edit': require('./NoteTagEdit.vue').default 'note-tag-edit': require('@/components/NoteTagEdit.vue').default
}, },
data(){ data(){
return { return {

View File

@ -54,7 +54,7 @@
name: 'NoteTitleDisplayCard', name: 'NoteTitleDisplayCard',
props: [ 'onClick', 'data' ], props: [ 'onClick', 'data' ],
components: { components: {
'delete-button': require('./DeleteButtonComponent.vue').default, 'delete-button': require('@/components/NoteDeleteButtonComponent.vue').default,
}, },
data () { data () {
return { return {
@ -108,7 +108,9 @@
} }
.overflow-hidden { .overflow-hidden {
overflow: hidden; overflow: hidden;
word-break: break-all; }
.overflow-hidden p, .overflow-hidden h3 {
word-break: break-word;
} }
.max-height { .max-height {
height: calc(100% + 30px); height: calc(100% + 30px);

View File

@ -1,38 +0,0 @@
<template>
<div id="NotesPage">
<div class="ui basic segment">
<search-bar />
</div>
</div>
</template>
<script>
//ajax calls
import axios from 'axios';
// import { mapGetters } from 'vuex'
export default {
name: 'Notes',
components:{
'search-bar': require('./SearchBar.vue').default
},
data () {
return {
notes: null,
activeNoteId: null
}
},
beforeMount(){
},
mounted: function() {
//this.getLatest()
},
methods: {
}
}
</script>

View File

@ -2,8 +2,11 @@
<div class="ui basic segment"> <div class="ui basic segment">
<div class="ui container"> <div class="ui container">
CTRL + SHIFT + V - paste without formatting <h2>Note Editing - Keyboard Shortcuts</h2>
CTRL + Z - Undo in note, <b>Undo youtube video player embed.</b>
<p>CTRL + SHIFT + V - paste without formatting</p>
<p>CTRL + Z - Undo in note, <b>Undo youtube video player embed.</b></p>
<p>ESC - Close note editor</p>
<h2>Block formatting</h2> <h2>Block formatting</h2>

View File

@ -1,5 +1,5 @@
<template> <template>
<div> <div class="ui basic segment">
<div class="ui equal width grid"> <div class="ui equal width grid">
@ -40,6 +40,12 @@
<router-link class="ui basic button" to="/help">Help</router-link> <router-link class="ui basic button" to="/help">Help</router-link>
<div v-on:click="toggleNightMode" class="ui basic button">
Dark Theme:
<span v-if="$store.getters.getIsNightMode">On</span>
<span v-else>Off</span>
</div>
<div class="ui right floated basic button" <div class="ui right floated basic button"
data-tooltip="Log Out" data-position="left center" data-tooltip="Log Out" data-position="left center"
v-on:click="destroyLoginToken">{{username}}</div> v-on:click="destroyLoginToken">{{username}}</div>
@ -52,21 +58,26 @@
<div class="ui two wide large screen only column"> <div class="ui two wide large screen only column">
<div class="ui basic fluid button" @click="reset"><i class="undo icon"></i>All Notes</div> <div class="ui basic fluid button" @click="reset"><i class="undo icon"></i>All Notes</div>
<div class="ui divider"></div> <div class="ui divider"></div>
<div class="ui clickable basic fluid large label" v-for="tag in commonTags" @click="toggleTagFilter(tag.id)" <div class="ui section list">
:class="{ 'green':(searchTags.includes(tag.id)) }"> <div class="item" v-for="tag in commonTags" @click="toggleTagFilter(tag.id)">
{{ucWords(tag.text)}} <div class="detail">{{tag.usages}}</div> <div class="ui clickable basic fluid large label" :class="{ 'green':(searchTags.includes(tag.id)) }">
{{ucWords(tag.text)}} <div class="detail">{{tag.usages}}</div>
</div>
</div>
</div> </div>
</div> </div>
<!-- Note title cards --> <!-- Note title cards -->
<div class="ui fourteen wide computer sixteen wide mobile column"> <div class="ui fourteen wide computer sixteen wide mobile column">
<h2>Notes ({{notes.length}})</h2> <h2>
Notes ({{notes.length}})
</h2>
<div v-if="notes !== null" class="note-card-display-area" :class="{'one-column':(activeNoteId1 != null || activeNoteId2 != null )}"> <div v-if="notes !== null" class="note-card-display-area" :class="{'one-column':(activeNoteId1 != null || activeNoteId2 != null )}">
<note-title-display-card <note-title-display-card
v-for="note in notes" v-for="note in notes"
:onClick="openNote" :onClick="openNote"
:data="note" :data="note"
:key="note.id + note.color + searchTerm + note.note_highlights.length + note.attachment_highlights.length + note.tag_highlights.length" :key="note.id + note.color + searchTerm + note.note_highlights.length + note.attachment_highlights.length + ' -' + note.tag_highlights.length + '-' +note.title.length + '-' +note.subtext.length"
/> />
</div> </div>
@ -88,8 +99,8 @@
export default { export default {
name: 'SearchBar', name: 'SearchBar',
components: { components: {
'input-notes': require('./InputNotes.vue').default, 'input-notes': require('@/components/NoteInputPanel.vue').default,
'note-title-display-card': require('./NoteTitleDisplayCard.vue').default, 'note-title-display-card': require('@/components/NoteTitleDisplayCard.vue').default,
}, },
data () { data () {
return { return {
@ -110,6 +121,10 @@
} }
}, },
beforeMount(){ beforeMount(){
let username = this.$store.getters.getUsername
this.username = this.ucWords(username)
this.$bus.$on('close_active_note', position => { this.$bus.$on('close_active_note', position => {
this.closeNote(position) this.closeNote(position)
}) })
@ -119,8 +134,6 @@
}, },
mounted() { mounted() {
let username = this.$store.getters.getUsername
this.username = this.ucWords(username)
this.search() this.search()
@ -226,6 +239,9 @@
destroyLoginToken() { destroyLoginToken() {
this.$store.commit('destroyLoginToken') this.$store.commit('destroyLoginToken')
this.$router.push('/') this.$router.push('/')
},
toggleNightMode(){
this.$store.commit('toggleNightMode')
} }
} }
} }

View File

@ -1,10 +1,10 @@
import Vue from 'vue' import Vue from 'vue'
import Router from 'vue-router' import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld' import HomePage from '@/pages/HomePage'
import Login from '@/components/Login' import LoginPage from '@/pages/LoginPage'
import Notes from '@/components/Notes' import NotesPage from '@/pages/NotesPage'
import HelpPage from '@/components/HelpPage' import HelpPage from '@/pages/HelpPage'
Vue.use(Router) Vue.use(Router)
@ -12,21 +12,21 @@ export default new Router({
routes: [ routes: [
{ {
path: '/', path: '/',
name: 'HelloWorld', name: 'HomePage',
meta: {title:'Home'}, meta: {title:'Home'},
component: HelloWorld component: HomePage
}, },
{ {
path: '/login', path: '/login',
name: 'Login', name: 'LoginPage',
meta: {title:'Login'}, meta: {title:'Login'},
component: Login component: LoginPage
}, },
{ {
path: '/notes', path: '/notes',
name: 'Notes', name: 'NotesPage',
meta: {title:'Notes'}, meta: {title:'Notes'},
component: Notes component: NotesPage
}, },
{ {
path: '/help', path: '/help',

View File

@ -9,7 +9,8 @@ export default new Vuex.Store({
count: 0, count: 0,
message: 'Get out me yard ya wankers', message: 'Get out me yard ya wankers',
token: null, token: null,
username: null username: null,
nightMode: false,
}, },
mutations: { mutations: {
increment (state) { increment (state) {
@ -40,6 +41,33 @@ export default new Vuex.Store({
delete axios.defaults.headers.common['Authorization'] delete axios.defaults.headers.common['Authorization']
state.token = null state.token = null
state.username = null state.username = null
},
toggleNightMode(state){
//Toggle state and save to local storage
state.nightMode = !(state.nightMode)
localStorage.setItem('nightMode', state.nightMode)
//Default theme colors
let themeColors = {
'background_color': '#fff',
'text_color': '#3d3d3d',
'outline_color': 'rgba(34,36,38,.15)',
}
//Night mode colors
if(state.nightMode){
themeColors = {
'background_color': '#000',
'text_color': '#a98457',
'outline_color': '#a98457',
}
}
//Go through each color and set CSS variable
let root = document.documentElement
Object.keys(themeColors).forEach( attribute => {
root.style.setProperty('--'+attribute, themeColors[attribute])
})
} }
}, },
getters: { getters: {
@ -55,6 +83,9 @@ export default new Vuex.Store({
getLoggedIn: state => { getLoggedIn: state => {
let weIn = (state.token !== null && state.token != undefined && state.token.length > 0) let weIn = (state.token !== null && state.token != undefined && state.token.length > 0)
return weIn return weIn
} },
getIsNightMode: state => {
return state.nightMode
},
} }
}) })

View File

@ -222,6 +222,7 @@ Notes.search = (userId, searchQuery, searchTags) => {
.replace(/<[^>]+>/g, '') //Rip out all HTML tags .replace(/<[^>]+>/g, '') //Rip out all HTML tags
//Generate Subtext //Generate Subtext
note.subtext = ''
if(note.text != '' && note.title != ''){ if(note.text != '' && note.title != ''){
note.subtext = note.text note.subtext = note.text
.replace(/&[#A-Za-z0-9]+;/g,' ') //Rip out all HTML entities .replace(/&[#A-Za-z0-9]+;/g,' ') //Rip out all HTML entities
@ -245,6 +246,9 @@ Notes.search = (userId, searchQuery, searchTags) => {
if(highlights && highlights[note.id] && highlights[note.id].notes_tags){ if(highlights && highlights[note.id] && highlights[note.id].notes_tags){
note['tag_highlights'] = highlights[note.id].notes_tags note['tag_highlights'] = highlights[note.id].notes_tags
} }
//Clear out note.text before sending it to front end
delete note.text
}) })
//If no notes are returned, there are no tags, return empty //If no notes are returned, there are no tags, return empty

10
startDevServerAndClient.sh Executable file
View File

@ -0,0 +1,10 @@
#!/bin/bash
echo 'Make sure this is being run from root folder of project'
echo 'Starting API server (/api), watching for file changes...'
pm2 start server/index.js --watch
echo 'Starting Client webpack dev server (/app), in a screen, watching for file changes...'
screen -dm bash -c "cd client/; npm run watch"