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'
 | 
			
		||||
					this.statusText = 'Saving'
 | 
			
		||||
					axios.post('/api/note/update', postData).then( response => {
 | 
			
		||||
							vm.statusText = 'Saved'
 | 
			
		||||
							vm.updated = Math.round((+new Date)/1000)
 | 
			
		||||
						this.statusText = 'Saved'
 | 
			
		||||
						this.updated = Math.round((+new Date)/1000)
 | 
			
		||||
						this.modified = true
 | 
			
		||||
 | 
			
		||||
						//Update last saved note hash
 | 
			
		||||
							vm.lastNoteHash = vm.hashString( currentNoteText )
 | 
			
		||||
						this.lastNoteHash = this.hashString( currentNoteText )
 | 
			
		||||
						return resolve(true)
 | 
			
		||||
					})
 | 
			
		||||
					// }, 300)
 | 
			
		||||
				})
 | 
			
		||||
			},
 | 
			
		||||
			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">
 | 
			
		||||
		<div class="ui left icon fluid input">
 | 
			
		||||
			<input v-model="searchTerm" @keyup="searchKeyUp" @:keyup.enter="search" placeholder="Search Notes and Files" />
 | 
			
		||||
			</div>
 | 
			
		||||
			<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">
 | 
			
		||||
				<div class="ui grid">
 | 
			
		||||
 | 
			
		||||
					<div class="eight wide column">
 | 
			
		||||
						<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
 | 
			
		||||
					
 | 
			
		||||
					<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>
 | 
			
		||||
			</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.$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
 | 
			
		||||
		Reference in New Issue
	
	Block a user