Compare commits
3 Commits
7f93925f74
...
05152cd5a4
Author | SHA1 | Date | |
---|---|---|---|
|
05152cd5a4 | ||
|
cf3289aac6 | ||
|
acf72ca67e |
@ -13,6 +13,7 @@
|
||||
<script>
|
||||
|
||||
// import io from 'socket.io-client'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -50,7 +51,6 @@ export default {
|
||||
|
||||
},
|
||||
mounted: function(){
|
||||
|
||||
},
|
||||
computed: {
|
||||
loggedIn () {
|
||||
|
@ -28,7 +28,7 @@
|
||||
}
|
||||
|
||||
html {
|
||||
scrollbar-width: none;
|
||||
/*scrollbar-width: none;*/
|
||||
}
|
||||
|
||||
div.ui.basic.segment.no-fluf-segment {
|
||||
|
@ -105,13 +105,13 @@
|
||||
|
||||
<!-- Buttons -->
|
||||
<div class="ui small compact basic button" v-on:click="openNote">
|
||||
<i class="file icon"></i>
|
||||
<i class="file outline icon"></i>
|
||||
Open Note
|
||||
</div>
|
||||
<div class="ui small compact basic button" v-on:click="openEditAttachments"
|
||||
:class="{ 'disabled':this.searchParams.noteId }">
|
||||
<i class="folder icon"></i>
|
||||
Note Attachments
|
||||
<i class="folder open outline icon"></i>
|
||||
Note Files
|
||||
</div>
|
||||
<div class="ui small compact basic icon button" v-on:click="deleteAttachment">
|
||||
<i v-if="!working" class="trash alternate outline icon"></i>
|
||||
@ -192,6 +192,7 @@
|
||||
this.unfolded = false
|
||||
setTimeout( () => {
|
||||
this.visible = false
|
||||
this.$store.dispatch('fetchAndUpdateUserTotals')
|
||||
}, 600)
|
||||
}
|
||||
})
|
||||
|
@ -68,6 +68,7 @@
|
||||
const imageCode = `<img alt="image" src="/api/static/thumb_${location}">`
|
||||
|
||||
this.$bus.$emit('new_file_upload', {noteId: this.noteId, imageCode})
|
||||
this.$store.dispatch('fetchAndUpdateUserTotals')
|
||||
}
|
||||
})
|
||||
.catch(results => {
|
||||
|
@ -153,7 +153,8 @@
|
||||
|
||||
<div class="menu-section" v-if="loggedIn">
|
||||
<router-link exact-active-class="active" class="menu-item menu-button" to="/notes" v-on:click.native="emitReloadEvent()">
|
||||
<i class="file icon"></i>Notes
|
||||
<i class="file outline icon"></i>Notes
|
||||
<!-- <span v-if="$store.getters.totals">{{ $store.getters.totals['totalNotes'] }}</span> -->
|
||||
</router-link>
|
||||
<div>
|
||||
<!-- <div class="menu-item sub">Show Only <i class="caret down icon"></i></div> -->
|
||||
@ -163,27 +164,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="menu-section" v-if="loggedIn">
|
||||
<div v-on:click="updateFastFilters(3)" class="menu-item menu-button">
|
||||
<i class="mail icon"></i>Inbox
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="menu-section" v-if="loggedIn">
|
||||
<div v-on:click="updateFastFilters(2)" class="menu-item menu-button">
|
||||
<i class="archive icon"></i>Archived
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="menu-section" v-if="loggedIn">
|
||||
<div class="menu-section" v-if="loggedIn && $store.getters.totals && $store.getters.totals['totalFiles']">
|
||||
<router-link class="menu-item menu-button" exact-active-class="active" to="/attachments">
|
||||
<i class="folder icon"></i>Files
|
||||
<i class="folder open outline icon"></i>Files
|
||||
<!-- <span>{{ $store.getters.totals['totalFiles'] }}</span> -->
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
<div class="menu-section" v-if="loggedIn">
|
||||
<router-link v-if="loggedIn" exact-active-class="active" class="menu-item menu-button" to="/quick">
|
||||
<i class="coffee icon"></i>Quick
|
||||
<i class="paper plane outline icon"></i>Quick
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
@ -208,7 +198,7 @@
|
||||
|
||||
<div class="menu-section" v-if="loggedIn">
|
||||
<div v-if="loggedIn" v-on:click="destroyLoginToken" class="menu-item menu-button">
|
||||
<i class="user icon"></i>{{ucWords($store.getters.getUsername)}}
|
||||
<i class="user outline icon"></i>{{ucWords($store.getters.getUsername)}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -242,6 +232,8 @@
|
||||
this.mobile = this.$store.getters.getIsUserOnMobile
|
||||
this.collapsed = this.$store.getters.getIsUserOnMobile
|
||||
|
||||
// {{ totals['totalNotes'] }}
|
||||
|
||||
if(this.mobile){
|
||||
this.menuOpen = false
|
||||
}
|
||||
|
@ -30,6 +30,7 @@
|
||||
axios.post('/api/note/delete', {'noteId':this.noteId}).then(response => {
|
||||
if(response.data == true){
|
||||
this.$bus.$emit('note_deleted', this.noteId)
|
||||
this.$store.dispatch('fetchAndUpdateUserTotals')
|
||||
}
|
||||
})
|
||||
},
|
||||
|
@ -118,13 +118,13 @@
|
||||
/>
|
||||
</side-slide-menu>
|
||||
|
||||
<side-slide-menu v-if="showTagSlideMenu" v-on:close="showTagSlideMenu = false" name="tags">
|
||||
<side-slide-menu v-if="showTagSlideMenu" v-on:close="showTagSlideMenu = false" name="tags" :style-object="styleObject">
|
||||
<div class="ui basic segment">
|
||||
<note-tag-edit :noteId="noteid" :key="'tags-for-note-'+noteid"/>
|
||||
</div>
|
||||
</side-slide-menu>
|
||||
|
||||
<side-slide-menu v-if="showFilesSideMenu" v-on:close="showFilesSideMenu = false" name="images">
|
||||
<side-slide-menu v-if="showFilesSideMenu" v-on:close="showFilesSideMenu = false" name="images" :style-object="styleObject">
|
||||
<div class="ui basic segment">
|
||||
<simple-attachment-note
|
||||
v-on:close="showFilesSideMenu = false"
|
||||
@ -134,7 +134,7 @@
|
||||
</div>
|
||||
</side-slide-menu>
|
||||
|
||||
<side-slide-menu v-if="showNoteOptions" v-on:close="showNoteOptions = false" name="note-options">
|
||||
<side-slide-menu v-if="showNoteOptions" v-on:close="showNoteOptions = false" name="note-options" :style-object="styleObject">
|
||||
<div class="ui basic padded segment">
|
||||
<div class="ui grid">
|
||||
<div class="sixteen wide column">
|
||||
@ -202,6 +202,7 @@
|
||||
loading: true,
|
||||
loadingMessage: 'Loading Note',
|
||||
currentNoteId: 0,
|
||||
modified: false,
|
||||
noteText: '',
|
||||
rawTextId: 0,
|
||||
shareUsername: null,
|
||||
@ -873,21 +874,16 @@
|
||||
'archived':this.archived,
|
||||
}
|
||||
|
||||
let vm = this
|
||||
//Debounce save to prevent spamming
|
||||
// clearTimeout(this.saveDebounce)
|
||||
// this.saveDebounce = setTimeout(() => {
|
||||
//Only notify user if saving - may help with debugging in the future
|
||||
vm.statusText = 'Saving'
|
||||
axios.post('/api/note/update', postData).then( response => {
|
||||
vm.statusText = 'Saved'
|
||||
vm.updated = Math.round((+new Date)/1000)
|
||||
this.statusText = 'Saving'
|
||||
axios.post('/api/note/update', postData).then( response => {
|
||||
this.statusText = 'Saved'
|
||||
this.updated = Math.round((+new Date)/1000)
|
||||
this.modified = true
|
||||
|
||||
//Update last saved note hash
|
||||
vm.lastNoteHash = vm.hashString( currentNoteText )
|
||||
return resolve(true)
|
||||
})
|
||||
// }, 300)
|
||||
//Update last saved note hash
|
||||
this.lastNoteHash = this.hashString( currentNoteText )
|
||||
return resolve(true)
|
||||
})
|
||||
})
|
||||
},
|
||||
checkForUpdatedNote(){
|
||||
@ -949,7 +945,9 @@
|
||||
this.sizeDown = true
|
||||
//This timeout allows animation to play before closing
|
||||
setTimeout(() => {
|
||||
this.$bus.$emit('close_active_note', {position: this.position, noteId: this.noteid})
|
||||
this.$bus.$emit('close_active_note', {
|
||||
position: this.position, noteId: this.noteid, modified: this.modified
|
||||
})
|
||||
return
|
||||
}, 300)
|
||||
})
|
||||
|
@ -12,8 +12,9 @@
|
||||
|
||||
<div class="sixteen wide column">
|
||||
<h3>All Tags</h3>
|
||||
<h4 v-if="allTags.length == 0">No tags yet, add a tag.</h4>
|
||||
<div v-if="allTags.length > 0">
|
||||
<div class="ui icon large label" v-for="tag in allTags" :class="{ 'green':isTagOnNote(tag.id) }">
|
||||
<div class="ui icon large label clickable" v-for="tag in allTags" :class="{ 'green':isTagOnNote(tag.id) }" v-on:click="toggleTag(tag.text, tag.id, tag.entryId)">
|
||||
{{ ucWords(tag.text) }}
|
||||
</div>
|
||||
</div>
|
||||
@ -42,7 +43,7 @@
|
||||
v-on:focus="onFocus"
|
||||
/>
|
||||
<div class="suggestion-box" v-if="suggestions.length > 0">
|
||||
<div class="suggestion-item" v-for="(item, index) in suggestions" :class="{ 'active':(index == selection) }" v-on:click="onClickTag(index)">
|
||||
<div class="suggestion-item" v-for="(item, index) in suggestions" :class="{ 'active':(index == selection) }" v-on:click="onSuggestionClick(index)">
|
||||
{{ucWords(item.text)}} <span class="suggestion-tip" v-if="index == selection">Press Enter to add</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -98,6 +99,7 @@
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
},
|
||||
getTagTextById(id){
|
||||
let tag = this.getTagById(id)
|
||||
@ -171,9 +173,38 @@
|
||||
}
|
||||
}, 300)
|
||||
},
|
||||
onClickTag(index){
|
||||
onSuggestionClick(index){
|
||||
this.newTagInput = this.suggestions[index].text
|
||||
this.addTag()
|
||||
},
|
||||
toggleTag(tagText, id){
|
||||
|
||||
//remove tag
|
||||
if(this.isTagOnNote(id)){
|
||||
|
||||
//Find database ID for tag
|
||||
let entryId = null
|
||||
this.noteTagIds.forEach(tag => {
|
||||
if(tag.tagId == id){
|
||||
entryId = tag.entryId
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
//Submit database entry to be removed
|
||||
if(entryId){
|
||||
this.removeTag(entryId)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//Add Tag
|
||||
this.newTagInput = tagText
|
||||
this.addTag()
|
||||
return
|
||||
|
||||
|
||||
|
||||
},
|
||||
addTag(){
|
||||
|
||||
@ -228,6 +259,8 @@
|
||||
},
|
||||
removeTag(tagId){
|
||||
|
||||
console.log(tagId)
|
||||
|
||||
let postData = {
|
||||
'tagId':tagId,
|
||||
'noteId':this.noteId
|
||||
@ -255,9 +288,6 @@
|
||||
|
||||
/* note tag edit area */
|
||||
.full-tag-area {
|
||||
|
||||
color: var(--text_color);
|
||||
background-color: var(--background_color);
|
||||
/*padding: 15px;*/
|
||||
/*border: 1px solid;*/
|
||||
border-color: var(--border_color);
|
||||
|
@ -1,9 +1,8 @@
|
||||
<template>
|
||||
<div class="ui form">
|
||||
<div class="fields">
|
||||
<div class="sixteen wide field">
|
||||
<input v-model="searchTerm" @keyup="searchKeyUp" @:keyup.enter="search" placeholder="Search Notes and Files" />
|
||||
</div>
|
||||
<div class="ui left icon fluid input">
|
||||
<input v-model="searchTerm" @keyup="searchKeyUp" @:keyup.enter="search" placeholder="Search Notes and Files" />
|
||||
<i class="search icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -8,13 +8,16 @@
|
||||
z-index: 400;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
|
||||
color: var(--text_color);
|
||||
background-color: var(--background_color);
|
||||
}
|
||||
.slide-content {
|
||||
box-sizing: border-box;
|
||||
/*padding: 1em 1.5em;*/
|
||||
height: calc(100% - 43px);
|
||||
border-right: 1px solid var(--menu-border);
|
||||
background-color: var(--background_color);
|
||||
/*background-color: var(--background_color);*/
|
||||
overflow-x: scroll;
|
||||
}
|
||||
.slide-shadow {
|
||||
@ -71,7 +74,7 @@
|
||||
<transition name="modal-fade">
|
||||
<div>
|
||||
|
||||
<div class="slide-container">
|
||||
<div class="slide-container" :style="{ 'background-color':bgColor, 'color':textColor}">
|
||||
|
||||
<!-- content of the editor -->
|
||||
<div class="slide-content">
|
||||
@ -94,13 +97,15 @@
|
||||
<script>
|
||||
export default {
|
||||
name: 'SideSlideMenu',
|
||||
props: [ 'name' ],
|
||||
props: [ 'name', 'styleObject' ],
|
||||
components: {
|
||||
'nm-button':require('@/components/NoteMenuButtonComponent.vue').default
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
items: []
|
||||
items: [],
|
||||
bgColor: null,
|
||||
textColor: null,
|
||||
}
|
||||
},
|
||||
beforeMount(){
|
||||
@ -116,6 +121,16 @@
|
||||
},
|
||||
mounted(){
|
||||
|
||||
//If note style object is set, use that on the slide menu
|
||||
if(this.styleObject && this.styleObject.noteText){
|
||||
this.textColor = this.styleObject.noteText
|
||||
}
|
||||
|
||||
if(this.styleObject && this.styleObject.noteBackground){
|
||||
this.bgColor = this.styleObject.noteBackground
|
||||
}
|
||||
|
||||
|
||||
//Close all other panels that are not this one
|
||||
this.$nextTick( () => {
|
||||
this.$bus.$emit('destroy_all_other_side_panels', this.name)
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
<div class="ui sixteen wide column">
|
||||
<h2 class="ui header">
|
||||
<i class="folder icon"></i>
|
||||
<i class="folder open outline icon"></i>
|
||||
<div class="content">
|
||||
Files
|
||||
<div class="sub header">Uploaded Files and Websites from notes.</div>
|
||||
@ -18,7 +18,7 @@
|
||||
Show All Attachments
|
||||
</div>
|
||||
<div class="ui green button" v-on:click="openNote">
|
||||
<i class="file icon"></i>
|
||||
<i class="file outline icon"></i>
|
||||
Open Note
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3,33 +3,48 @@
|
||||
|
||||
<div class="ui grid" :class="{ 'mush-it-up':showOneColumn() }" ref="content">
|
||||
|
||||
<!-- Note filter options -->
|
||||
<div class="row" v-if="!$store.getters.getIsUserOnMobile">
|
||||
<div v-if="!$store.getters.getIsUserOnMobile" class="sixteen wide column">
|
||||
<!-- :class="{ 'sixteen wide column':showOneColumn(), 'sixteen wide column':!showOneColumn() }" -->
|
||||
|
||||
<div :class="{ 'sixteen wide column':showOneColumn(), 'eight wide column':!showOneColumn() }">
|
||||
<div class="ui form">
|
||||
<div class="fields">
|
||||
<div class="ten wide field">
|
||||
<search-input></search-input>
|
||||
</div>
|
||||
<div class="six wide field">
|
||||
<span class="ui fluid green button"
|
||||
v-if="showClear"
|
||||
@click="reset">
|
||||
<i class="undo icon"></i>Back to All Notes
|
||||
</span>
|
||||
<!-- <fast-filters /> -->
|
||||
</div>
|
||||
<div class="ui grid">
|
||||
|
||||
<div class="eight wide column">
|
||||
<search-input></search-input>
|
||||
</div>
|
||||
|
||||
<div class="eight wide column">
|
||||
|
||||
<div class="ui basic button" v-on:click="updateFastFilters(3)" v-if="$store.getters.totals && $store.getters.totals['sharedToNotes'] > 0" style="position: relative;">
|
||||
<i class="green mail icon"></i>Inbox
|
||||
<span class="floating ui green label" v-if="$store.getters.totals['unreadNotes'] > 0">
|
||||
{{ $store.getters.totals['unreadNotes'] }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="ui basic button" v-on:click="updateFastFilters(2)" v-if="$store.getters.totals && $store.getters.totals['archivedNotes'] > 0">
|
||||
<i class="green archive icon"></i>Archived
|
||||
<!-- <span>{{ $store.getters.totals['archivedNotes'] }}</span> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="eight wide column" v-if="showClear">
|
||||
<!-- <fast-filters /> -->
|
||||
<span class="ui fluid green button"
|
||||
|
||||
@click="reset">
|
||||
<i class="arrow circle left icon"></i>Back to All Notes
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div v-if="$store.getters.getIsUserOnMobile && showClear" class="row">
|
||||
<div class="sixteen wide column">
|
||||
<span class="ui fluid green button"
|
||||
@click="reset">
|
||||
<i class="undo icon"></i>Reset Filters
|
||||
<span class="ui fluid green button" @click="reset">
|
||||
<i class="arrow circle left icon"></i>Back to All Notes
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -67,7 +82,7 @@
|
||||
<!-- pinned notes -->
|
||||
<div v-if="containsPinnednotes > 0" class="note-card-section">
|
||||
<!-- ({{containsPinnednotes}}) -->
|
||||
<h4><i class="green pin icon"></i>Pinned <span v-if="!working"></span></h4>
|
||||
<h4><i class="green pin icon"></i>Pinned</h4>
|
||||
<div class="note-card-display-area">
|
||||
<note-title-display-card
|
||||
v-for="note in notes"
|
||||
@ -83,7 +98,7 @@
|
||||
<!-- normal notes -->
|
||||
<div v-if="containsNormalNotes > 0" class="note-card-section">
|
||||
<!-- ({{containsNormalNotes}}) -->
|
||||
<h4><i class="green file icon"></i>Notes <span v-if="!working"></span></h4>
|
||||
<h4><i class="green file icon"></i>Notes</h4>
|
||||
<div class="note-card-display-area">
|
||||
<note-title-display-card
|
||||
v-for="note in notes"
|
||||
@ -118,7 +133,7 @@
|
||||
|
||||
<!-- found attachments -->
|
||||
<div class="sixteen wide column" v-if="foundAttachments.length > 0">
|
||||
<h4><i class="green folder icon"></i> Found in Files ({{ foundAttachments.length }})</h4>
|
||||
<h4><i class="folder open outline icon"></i> Found in Files ({{ foundAttachments.length }})</h4>
|
||||
<attachment-display
|
||||
v-for="item in foundAttachments"
|
||||
:item="item"
|
||||
@ -197,9 +212,16 @@
|
||||
|
||||
this.$parent.loginGateway()
|
||||
|
||||
this.$bus.$on('close_active_note', ({position, noteId}) => {
|
||||
//Update totals for app
|
||||
this.$store.dispatch('fetchAndUpdateUserTotals')
|
||||
|
||||
this.$bus.$on('close_active_note', ({position, noteId, modified}) => {
|
||||
this.closeNote(position)
|
||||
this.updateSingleNote(noteId)
|
||||
this.$store.dispatch('fetchAndUpdateUserTotals')
|
||||
if(modified){
|
||||
this.updateSingleNote(noteId)
|
||||
}
|
||||
|
||||
})
|
||||
this.$bus.$on('note_deleted', (noteId) => {
|
||||
//Remove deleted note from set, its deleted
|
||||
@ -268,6 +290,7 @@
|
||||
// this.$bus.$off()
|
||||
},
|
||||
mounted() {
|
||||
|
||||
//Loads initial batch and tags
|
||||
this.reset()
|
||||
},
|
||||
@ -637,6 +660,31 @@
|
||||
resolve(data)
|
||||
})
|
||||
})
|
||||
},
|
||||
updateFastFilters(index){
|
||||
|
||||
//clear out tags
|
||||
this.searchTags = []
|
||||
|
||||
//A little hacky, brings user to notes page then filters on click
|
||||
if(this.$route.name != 'NotesPage'){
|
||||
this.$router.push('/notes')
|
||||
setTimeout( () => {
|
||||
this.updateFastFilters(index)
|
||||
}, 500 )
|
||||
}
|
||||
|
||||
const options = [
|
||||
'withLinks', // 'Only Show Notes with Links'
|
||||
'withTags', // 'Only Show Notes with Tags'
|
||||
'onlyArchived', //'Only Show Archived Notes'
|
||||
'onlyShowSharedNotes', //Only show shared notes
|
||||
]
|
||||
|
||||
let filter = {}
|
||||
filter[options[index]] = 1
|
||||
|
||||
this.$bus.$emit('update_fast_filters', filter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
<div class="ui sixteen wide column">
|
||||
<h2 class="ui header">
|
||||
<i class="coffee icon"></i>
|
||||
<i class="paper plane outline icon"></i>
|
||||
<div class="content">
|
||||
Quick
|
||||
<div class="sub header">Add new information with great speed</div>
|
||||
@ -26,7 +26,14 @@
|
||||
</div>
|
||||
<div class="field">
|
||||
<div v-on:click="appendQuickNote" class="ui green button">Save (CRTL + Enter)</div>
|
||||
<div v-if="quickNoteId" v-on:click="openNoteEdit" class="ui right floated basic button">Edit</div>
|
||||
<div v-if="quickNoteId" class="ui right floated basic button" v-on:click="$router.push('/attachments/note/'+quickNoteId)">
|
||||
<i class="folder open outline icon"></i>
|
||||
Quick Files + Links
|
||||
</div>
|
||||
<div v-if="quickNoteId" v-on:click="openNoteEdit" class="ui right floated basic button">
|
||||
<i class="file outline icon"></i>
|
||||
Edit
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -98,7 +105,7 @@
|
||||
//Don't submit empty note
|
||||
if(this.newText.trim() == ''){ return }
|
||||
|
||||
axios.post('/api/quick-note/update', { 'pushText':this.newText } )
|
||||
axios.post('/api/quick-note/update', { 'pushText':this.newText.trim() } )
|
||||
.then( results => {
|
||||
|
||||
this.newText = '' //Clear text area
|
||||
|
@ -12,6 +12,7 @@ export default new Vuex.Store({
|
||||
isUserOnMobile: false,
|
||||
isNoteSettingsOpen: false, //Little note settings pane
|
||||
socket: null,
|
||||
userTotals: null,
|
||||
},
|
||||
mutations: {
|
||||
setLoginToken(state, userData){
|
||||
@ -88,6 +89,14 @@ export default new Vuex.Store({
|
||||
//Put socket id in axios headers
|
||||
axios.defaults.headers.common['socketId'] = socket
|
||||
state.socket = socket
|
||||
},
|
||||
setUserTotals(state, totalsObject){
|
||||
//Save all the totals for the user
|
||||
state.userTotals = totalsObject
|
||||
|
||||
// Object.keys(totalsObject).forEach( key => {
|
||||
// console.log(key + ' -- ' + totalsObject[key])
|
||||
// })
|
||||
}
|
||||
|
||||
},
|
||||
@ -114,5 +123,16 @@ export default new Vuex.Store({
|
||||
getSocket: state => {
|
||||
return state.socket
|
||||
},
|
||||
totals: state => {
|
||||
return state.userTotals
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
fetchAndUpdateUserTotals ({ commit }) {
|
||||
axios.post('/api/user/totals')
|
||||
.then( ({data}) => {
|
||||
commit('setUserTotals', data)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
@ -105,7 +105,7 @@ Note.create = (userId, noteText, quickNote = 0) => {
|
||||
const created = Math.round((+new Date)/1000)
|
||||
|
||||
db.promise()
|
||||
.query(`INSERT INTO note_raw_text (text) VALUE ('')`)
|
||||
.query(`INSERT INTO note_raw_text (text) VALUE (?)`, [noteText])
|
||||
.then( (rows, fields) => {
|
||||
|
||||
const rawTextId = rows[0].insertId
|
||||
@ -334,6 +334,10 @@ Note.get = (userId, noteId) => {
|
||||
WHERE note.user_id = ? AND note.id = ? LIMIT 1`, [userId,noteId])
|
||||
.then((rows, fields) => {
|
||||
|
||||
const created = Math.round((+new Date)/1000)
|
||||
|
||||
db.promise().query(`UPDATE note SET opened = ? WHERE (id = ?)`, [created, noteId])
|
||||
|
||||
//Return note data
|
||||
resolve(rows[0][0])
|
||||
|
||||
|
@ -10,7 +10,9 @@ QuickNote.get = (userId) => {
|
||||
|
||||
db.promise()
|
||||
.query(`
|
||||
SELECT id, text FROM note WHERE quick_note = 1 AND user_id = ? LIMIT 1
|
||||
SELECT note.id, text FROM note
|
||||
JOIN note_raw_text ON (note_raw_text.id = note.note_raw_text_id)
|
||||
WHERE quick_note = 1 AND user_id = ? LIMIT 1
|
||||
`, [userId])
|
||||
.then((rows, fields) => {
|
||||
|
||||
@ -53,8 +55,10 @@ QuickNote.update = (userId, pushText) => {
|
||||
|
||||
db.promise()
|
||||
.query(`
|
||||
SELECT id, text, color, pinned, archived
|
||||
FROM note WHERE quick_note = 1 AND user_id = ? LIMIT 1
|
||||
SELECT note.id, text, color, pinned, archived
|
||||
FROM note
|
||||
JOIN note_raw_text ON (note_raw_text.id = note.note_raw_text_id)
|
||||
WHERE quick_note = 1 AND user_id = ? LIMIT 1
|
||||
`, [userId])
|
||||
.then((rows, fields) => {
|
||||
|
||||
@ -95,19 +99,3 @@ QuickNote.update = (userId, pushText) => {
|
||||
//Note.create(userId, 'Quick Note', 1)
|
||||
|
||||
}
|
||||
|
||||
QuickNote.create = (userId, noteText) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
if(userId == null || userId < 10){ reject('User Id required to create note') }
|
||||
|
||||
const created = Math.round((+new Date)/1000)
|
||||
|
||||
db.promise()
|
||||
.query('INSERT INTO note (user_id, text, created) VALUES (?,?,?)', [userId, noteText, created])
|
||||
.then((rows, fields) => {
|
||||
resolve(rows[0].insertId) //Only return the new note ID when creating a new note
|
||||
})
|
||||
.catch(console.log)
|
||||
})
|
||||
}
|
@ -113,3 +113,56 @@ User.create = (username, password) => {
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
//Counts notes, pinned notes, archived notes, shared notes, unread notes, total files and types
|
||||
User.getCounts = (userId) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
let countTotals = {}
|
||||
|
||||
db.promise().query(
|
||||
`SELECT
|
||||
SUM(pinned = 1 && archived = 0 && share_user_id IS NULL) AS pinnedNotes,
|
||||
SUM(pinned = 0 && archived = 1 && share_user_id IS NULL) AS archivedNotes,
|
||||
SUM(share_user_id IS NULL) AS totalNotes,
|
||||
SUM(share_user_id != ?) AS sharedToNotes,
|
||||
SUM( (share_user_id != ? && opened IS null) || (share_user_id != ? && updated > opened) ) AS unreadNotes
|
||||
FROM note
|
||||
WHERE user_id = ?`, [userId, userId, userId, userId])
|
||||
.then( (rows, fields) => {
|
||||
|
||||
Object.assign(countTotals, rows[0][0]) //combine results
|
||||
|
||||
return db.promise().query(
|
||||
`SELECT count(id) AS sharedFromNotes
|
||||
FROM note WHERE share_user_id = ?`, [userId]
|
||||
)
|
||||
})
|
||||
.then( (rows, fields) => {
|
||||
|
||||
Object.assign(countTotals, rows[0][0]) //combine results
|
||||
|
||||
return db.promise().query(
|
||||
`SELECT
|
||||
SUM(attachment_type = 1) as linkFiles,
|
||||
SUM(attachment_type != 1) as otherFiles,
|
||||
COUNT(id) as totalFiles
|
||||
FROM attachment WHERE visible = 1
|
||||
AND user_id = ?
|
||||
`, [userId]
|
||||
)
|
||||
}).then( (rows, fields) => {
|
||||
|
||||
Object.assign(countTotals, rows[0][0]) //combine results
|
||||
|
||||
//Convert everything to an int or 0
|
||||
Object.keys(countTotals).forEach( key => {
|
||||
const count = parseInt(countTotals[key])
|
||||
countTotals[key] = count ? count : 0
|
||||
})
|
||||
|
||||
resolve(countTotals)
|
||||
})
|
||||
|
||||
})
|
||||
}
|
@ -46,4 +46,11 @@ router.post('/login', function (req, res) {
|
||||
})
|
||||
})
|
||||
|
||||
// fetch counts of users notes
|
||||
router.post('/totals', function (req, res) {
|
||||
User.getCounts(req.headers.userId)
|
||||
.then( countsObject => res.send( countsObject ))
|
||||
})
|
||||
|
||||
|
||||
module.exports = router
|
Loading…
Reference in New Issue
Block a user