2019-07-19 20:51:57 +00:00
|
|
|
<template>
|
2019-12-20 05:50:50 +00:00
|
|
|
<div class="ui basic segment no-fluf-segment">
|
2019-07-19 20:51:57 +00:00
|
|
|
|
2019-12-20 05:50:50 +00:00
|
|
|
<div class="ui grid" :class="{ 'mush-it-up':showOneColumn() }" ref="content">
|
2019-07-21 16:28:07 +00:00
|
|
|
|
2020-02-12 05:29:56 +00:00
|
|
|
<div class="sixteen wide column">
|
2020-02-11 21:11:14 +00:00
|
|
|
<!-- :class="{ 'sixteen wide column':showOneColumn(), 'sixteen wide column':!showOneColumn() }" -->
|
2019-12-20 05:50:50 +00:00
|
|
|
|
2020-02-11 06:05:28 +00:00
|
|
|
<div class="ui grid">
|
2020-02-11 21:11:14 +00:00
|
|
|
|
2020-02-12 05:29:56 +00:00
|
|
|
<div class="six wide column" v-if="!$store.getters.getIsUserOnMobile">
|
2020-02-11 06:05:28 +00:00
|
|
|
<search-input></search-input>
|
|
|
|
</div>
|
2020-02-11 21:11:14 +00:00
|
|
|
|
2020-02-12 05:29:56 +00:00
|
|
|
<div class="ten wide column" :class="{ 'sixteen wide column':$store.getters.getIsUserOnMobile }">
|
2020-02-11 21:11:14 +00:00
|
|
|
|
2020-02-14 01:08:46 +00:00
|
|
|
<div class="ui basic button"
|
|
|
|
v-on:click="updateFastFilters(3)"
|
|
|
|
v-if="$store.getters.totals && ($store.getters.totals['sharedToNotes'] > 0 || $store.getters.totals['sharedFromNotes'] > 0)"
|
|
|
|
style="position: relative;">
|
|
|
|
<i class="green mail icon"></i>Shared Notes
|
2020-02-11 21:11:14 +00:00
|
|
|
<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>
|
2020-02-14 05:31:38 +00:00
|
|
|
|
2020-02-11 21:11:14 +00:00
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="eight wide column" v-if="showClear">
|
2020-02-11 06:05:28 +00:00
|
|
|
<!-- <fast-filters /> -->
|
|
|
|
<span class="ui fluid green button"
|
2020-02-11 21:11:14 +00:00
|
|
|
|
2020-02-11 06:05:28 +00:00
|
|
|
@click="reset">
|
|
|
|
<i class="arrow circle left icon"></i>Back to All Notes
|
|
|
|
</span>
|
2019-07-24 18:06:50 +00:00
|
|
|
</div>
|
2020-02-11 21:11:14 +00:00
|
|
|
|
2019-07-21 16:28:07 +00:00
|
|
|
</div>
|
2020-02-11 06:05:28 +00:00
|
|
|
|
2020-01-03 01:26:55 +00:00
|
|
|
</div>
|
|
|
|
|
2020-02-14 01:08:46 +00:00
|
|
|
<h2 v-if="fastFilters['withLinks'] == 1">Notes with Links</h2>
|
|
|
|
<h2 v-if="fastFilters['withTags'] == 1">Notes with Tags</h2>
|
|
|
|
<h2 v-if="fastFilters['onlyArchived'] == 1">Archived Notes</h2>
|
|
|
|
<h2 v-if="fastFilters['onlyShowSharedNotes'] == 1">Shared Notes</h2>
|
|
|
|
|
2020-02-11 06:05:28 +00:00
|
|
|
|
2019-12-20 05:50:50 +00:00
|
|
|
<div v-if="commonTags.length > 0" class="sixteen wide column">
|
2020-02-10 17:44:43 +00:00
|
|
|
<h4><i class="green tags icon"></i>Tags</h4>
|
2019-12-20 05:50:50 +00:00
|
|
|
<span v-for="tag in commonTags" @click="toggleTagFilter(tag.id)">
|
|
|
|
<span class="ui clickable basic label" :class="{ 'green':(searchTags.includes(tag.id)) }">
|
|
|
|
{{ucWords(tag.text)}} <span class="detail">{{tag.usages}}</span>
|
|
|
|
</span>
|
|
|
|
</span>
|
|
|
|
</div>
|
2019-07-24 18:06:50 +00:00
|
|
|
|
2019-12-20 05:50:50 +00:00
|
|
|
<!-- Note title card display -->
|
|
|
|
<div class="sixteen wide column">
|
|
|
|
<h3 v-if="searchTerm.length > 0 && notes.length == 0">No notes found. Check your spelling, try completing the word or using a different phrase.</h3>
|
2019-07-30 19:10:31 +00:00
|
|
|
|
2020-02-14 01:08:46 +00:00
|
|
|
<h3 v-if="$store.getters.totals && $store.getters.totals['totalNotes'] == 0">
|
|
|
|
No Notes Yet. Create one when you feel ready.
|
|
|
|
</h3>
|
2019-09-10 18:10:11 +00:00
|
|
|
|
2020-02-14 01:08:46 +00:00
|
|
|
<!-- <div v-if="working">
|
2019-12-20 05:50:50 +00:00
|
|
|
<div class="ui active inline loader"></div> Working...
|
2020-02-14 01:08:46 +00:00
|
|
|
</div> -->
|
2019-07-21 16:28:07 +00:00
|
|
|
|
2019-12-20 05:50:50 +00:00
|
|
|
<!-- Go to one wide column, do not do this on mobile interface -->
|
|
|
|
<div v-if="notes !== null && notes.length > 0"
|
|
|
|
:class="{'one-column':(
|
|
|
|
(activeNoteId1 != null || activeNoteId2 != null) &&
|
|
|
|
!$store.getters.getIsUserOnMobile
|
|
|
|
)}">
|
|
|
|
|
|
|
|
<!-- pinned notes -->
|
|
|
|
<div v-if="containsPinnednotes > 0" class="note-card-section">
|
2020-01-03 01:26:55 +00:00
|
|
|
<!-- ({{containsPinnednotes}}) -->
|
2020-02-11 21:11:14 +00:00
|
|
|
<h4><i class="green pin icon"></i>Pinned</h4>
|
2019-12-20 05:50:50 +00:00
|
|
|
<div class="note-card-display-area">
|
|
|
|
<note-title-display-card
|
|
|
|
v-for="note in notes"
|
|
|
|
v-if="note.pinned"
|
|
|
|
:onClick="openNote"
|
|
|
|
:data="note"
|
|
|
|
:currently-open="(activeNoteId1 == note.id || activeNoteId2 == note.id)"
|
|
|
|
:key="note.id + note.color + note.note_highlights.length + note.attachment_highlights.length + ' -' + note.tag_highlights.length + '-' +note.title.length + '-' +note.subtext.length"
|
|
|
|
/>
|
2019-07-30 19:10:31 +00:00
|
|
|
</div>
|
2019-07-19 20:51:57 +00:00
|
|
|
</div>
|
2019-07-21 16:28:07 +00:00
|
|
|
|
2019-12-20 05:50:50 +00:00
|
|
|
<!-- normal notes -->
|
|
|
|
<div v-if="containsNormalNotes > 0" class="note-card-section">
|
2020-01-03 01:26:55 +00:00
|
|
|
<!-- ({{containsNormalNotes}}) -->
|
2020-02-11 21:11:14 +00:00
|
|
|
<h4><i class="green file icon"></i>Notes</h4>
|
2019-12-20 05:50:50 +00:00
|
|
|
<div class="note-card-display-area">
|
|
|
|
<note-title-display-card
|
|
|
|
v-for="note in notes"
|
|
|
|
v-if="note.note_highlights && !note.pinned"
|
|
|
|
:onClick="openNote"
|
|
|
|
:data="note"
|
|
|
|
:currently-open="(activeNoteId1 == note.id || activeNoteId2 == note.id)"
|
|
|
|
:key="note.id + note.color + note.note_highlights.length + note.attachment_highlights.length + ' -' + note.tag_highlights.length + '-' +note.title.length + '-' +note.subtext.length"
|
|
|
|
/>
|
|
|
|
</div>
|
2019-07-19 20:51:57 +00:00
|
|
|
</div>
|
2019-07-24 18:06:50 +00:00
|
|
|
|
2019-12-20 05:50:50 +00:00
|
|
|
<!-- found in text -->
|
|
|
|
<div v-if="containsTextResults" class="note-card-section">
|
|
|
|
<h4><i class="green paragraph icon"></i> Found in Text ({{containsTextResults}})</h4>
|
|
|
|
<div class="note-card-display-area">
|
|
|
|
<note-title-display-card
|
|
|
|
v-for="note in notes"
|
|
|
|
v-if="note.note_highlights && note.note_highlights.length"
|
|
|
|
:textResults="true"
|
|
|
|
:onClick="openNote"
|
|
|
|
:data="note"
|
|
|
|
:currently-open="(activeNoteId1 == note.id || activeNoteId2 == note.id)"
|
|
|
|
:key="note.id + note.color + note.note_highlights.length + note.attachment_highlights.length + ' -' + note.tag_highlights.length + '-' +note.title.length + '-' +note.subtext.length"
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
2019-07-19 20:51:57 +00:00
|
|
|
</div>
|
2019-12-20 05:50:50 +00:00
|
|
|
|
2019-07-19 20:51:57 +00:00
|
|
|
</div>
|
2019-12-20 05:50:50 +00:00
|
|
|
|
2020-02-01 22:21:22 +00:00
|
|
|
|
|
|
|
<!-- found attachments -->
|
|
|
|
<div class="sixteen wide column" v-if="foundAttachments.length > 0">
|
2020-02-11 06:05:28 +00:00
|
|
|
<h4><i class="folder open outline icon"></i> Found in Files ({{ foundAttachments.length }})</h4>
|
2020-02-01 22:21:22 +00:00
|
|
|
<attachment-display
|
|
|
|
v-for="item in foundAttachments"
|
|
|
|
:item="item"
|
|
|
|
:key="item.id"
|
|
|
|
:search-params="{}"
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
|
2019-07-19 20:51:57 +00:00
|
|
|
</div>
|
|
|
|
|
2019-07-20 23:07:22 +00:00
|
|
|
|
2020-01-03 01:26:55 +00:00
|
|
|
<input-notes v-if="activeNoteId1 != null" :noteid="activeNoteId1" :position="activeNote1Position" ref="note1" />
|
|
|
|
<input-notes v-if="activeNoteId2 != null" :noteid="activeNoteId2" :position="activeNote2Position" ref="note2" />
|
2019-12-20 05:50:50 +00:00
|
|
|
|
2019-07-19 20:51:57 +00:00
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
2019-12-20 05:50:50 +00:00
|
|
|
import axios from 'axios'
|
2019-07-19 20:51:57 +00:00
|
|
|
|
|
|
|
export default {
|
|
|
|
name: 'SearchBar',
|
2019-07-20 23:07:22 +00:00
|
|
|
components: {
|
2019-07-30 19:10:31 +00:00
|
|
|
'input-notes': require('@/components/NoteInputPanel.vue').default,
|
|
|
|
'note-title-display-card': require('@/components/NoteTitleDisplayCard.vue').default,
|
2019-09-10 18:10:11 +00:00
|
|
|
'fast-filters': require('@/components/FastFilters.vue').default,
|
2020-01-03 01:26:55 +00:00
|
|
|
'search-input': require('@/components/SearchInput.vue').default,
|
2020-02-01 22:21:22 +00:00
|
|
|
'attachment-display': require('@/components/AttachmentDisplayCard').default,
|
2020-02-14 01:08:46 +00:00
|
|
|
'counter':require('@/components/AnimatedCounterComponent.vue').default
|
2019-07-20 23:07:22 +00:00
|
|
|
},
|
2019-07-19 20:51:57 +00:00
|
|
|
data () {
|
|
|
|
return {
|
|
|
|
initComponent: true,
|
|
|
|
commonTags: [],
|
|
|
|
searchTerm: '',
|
|
|
|
searchTags: [],
|
2019-07-20 23:07:22 +00:00
|
|
|
notes: [],
|
2019-12-20 05:50:50 +00:00
|
|
|
highlights: [],
|
2019-07-20 23:07:22 +00:00
|
|
|
searchDebounce: null,
|
2019-09-10 18:10:11 +00:00
|
|
|
fastFilters: {},
|
|
|
|
working: false,
|
2019-12-20 05:50:50 +00:00
|
|
|
//Load up notes in batches
|
|
|
|
firstLoadBatchSize: 30, //First set of rapidly loaded notes
|
|
|
|
batchSize: 100, //Size of batch loaded when user scrolls through current batch
|
|
|
|
batchOffset: 0, //Tracks the current batch that has been loaded
|
|
|
|
loadingBatchTimeout: null, //Limit how quickly batches can be loaded
|
|
|
|
loadingInProgress: false,
|
2020-01-03 01:26:55 +00:00
|
|
|
fetchTags: false,
|
2019-12-20 05:50:50 +00:00
|
|
|
|
|
|
|
//Clear button is not visible
|
|
|
|
showClear: false,
|
|
|
|
initialPostData: null,
|
|
|
|
currentPostData: null,
|
|
|
|
|
|
|
|
containsNormalNotes: 0,
|
|
|
|
containsPinnednotes: 0,
|
|
|
|
containsTextResults: 0,
|
2020-01-03 01:26:55 +00:00
|
|
|
// containsTagResults: 0,
|
|
|
|
// containsAttachmentResults: 0,
|
2019-07-20 23:07:22 +00:00
|
|
|
|
|
|
|
//Currently open notes in app
|
|
|
|
activeNoteId1: null,
|
|
|
|
activeNoteId2: null,
|
2019-12-20 05:50:50 +00:00
|
|
|
|
2019-07-20 23:07:22 +00:00
|
|
|
//Position determines how note is Positioned
|
|
|
|
activeNote1Position: 0,
|
2019-07-24 18:06:50 +00:00
|
|
|
activeNote2Position: 0,
|
2019-12-20 05:50:50 +00:00
|
|
|
|
2020-01-03 01:26:55 +00:00
|
|
|
lastVisibilityState: null,
|
|
|
|
|
2020-02-14 01:08:46 +00:00
|
|
|
foundAttachments: [],
|
|
|
|
|
|
|
|
noteSections: {
|
|
|
|
'pinned': {},
|
|
|
|
'archived': {},
|
|
|
|
'recieved': {},
|
|
|
|
'sent':{},
|
|
|
|
'notes':{},
|
|
|
|
'textMatch':{}
|
|
|
|
}
|
2020-02-01 22:21:22 +00:00
|
|
|
|
2019-07-19 20:51:57 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
beforeMount(){
|
2019-07-30 19:10:31 +00:00
|
|
|
|
2019-12-20 05:50:50 +00:00
|
|
|
this.$parent.loginGateway()
|
|
|
|
|
2020-02-11 21:11:14 +00:00
|
|
|
//Update totals for app
|
|
|
|
this.$store.dispatch('fetchAndUpdateUserTotals')
|
|
|
|
|
|
|
|
this.$bus.$on('close_active_note', ({position, noteId, modified}) => {
|
2019-07-20 23:07:22 +00:00
|
|
|
this.closeNote(position)
|
2020-02-11 21:11:14 +00:00
|
|
|
this.$store.dispatch('fetchAndUpdateUserTotals')
|
|
|
|
if(modified){
|
|
|
|
this.updateSingleNote(noteId)
|
|
|
|
}
|
|
|
|
|
2019-07-20 23:07:22 +00:00
|
|
|
})
|
2020-01-03 01:26:55 +00:00
|
|
|
this.$bus.$on('note_deleted', (noteId) => {
|
|
|
|
//Remove deleted note from set, its deleted
|
|
|
|
this.notes.forEach( (note, index) => {
|
|
|
|
if(note.id == noteId){
|
|
|
|
if(note.pinned == 1){
|
|
|
|
this.containsPinnednotes--
|
|
|
|
} else {
|
|
|
|
this.containsNormalNotes--
|
|
|
|
}
|
|
|
|
this.notes.splice(index, 1)
|
|
|
|
}
|
|
|
|
})
|
2019-07-29 07:22:47 +00:00
|
|
|
})
|
2019-09-10 18:10:11 +00:00
|
|
|
this.$bus.$on('update_fast_filters', newFilter => {
|
|
|
|
this.fastFilters = newFilter
|
2020-01-03 01:26:55 +00:00
|
|
|
//Fast filters always return all the results and tags
|
|
|
|
this.search(true, this.batchSize, false).then( () => {
|
|
|
|
return this.fetchUserTags()
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
//Event to update search from other areas
|
|
|
|
this.$bus.$on('update_search_term', sentInSearchTerm => {
|
|
|
|
this.searchTerm = sentInSearchTerm
|
|
|
|
this.search(true, this.batchSize)
|
|
|
|
.then( () => {
|
2020-02-01 22:21:22 +00:00
|
|
|
|
|
|
|
this.searchAttachments()
|
|
|
|
|
2020-01-03 01:26:55 +00:00
|
|
|
return this.fetchUserTags()
|
|
|
|
})
|
2019-12-20 05:50:50 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
//New note button pushes open note event
|
|
|
|
this.$bus.$on('open_note', noteId => {
|
|
|
|
this.openNote(noteId)
|
2019-09-10 18:10:11 +00:00
|
|
|
})
|
|
|
|
|
2020-01-03 01:26:55 +00:00
|
|
|
//Reload page content
|
|
|
|
this.$bus.$on('note_reload', () => {
|
|
|
|
this.reset()
|
|
|
|
})
|
|
|
|
|
2019-09-10 18:10:11 +00:00
|
|
|
//Mount notes on load if note ID is set
|
|
|
|
if(this.$route.params && this.$route.params.id){
|
|
|
|
const id = this.$route.params.id
|
|
|
|
this.openNote(id)
|
|
|
|
}
|
2019-12-20 05:50:50 +00:00
|
|
|
window.addEventListener('scroll', this.onScroll)
|
|
|
|
|
2020-01-03 01:26:55 +00:00
|
|
|
//Close notes when back button is pressed
|
|
|
|
window.addEventListener('hashchange', this.hashChangeAction)
|
|
|
|
|
2020-02-01 22:21:22 +00:00
|
|
|
//update note on visibility change
|
2020-01-03 01:26:55 +00:00
|
|
|
document.addEventListener('visibilitychange', this.visibiltyChangeAction);
|
2019-09-10 18:10:11 +00:00
|
|
|
|
2019-12-20 05:50:50 +00:00
|
|
|
},
|
|
|
|
beforeDestroy(){
|
|
|
|
window.removeEventListener('scroll', this.onScroll)
|
2020-01-03 01:26:55 +00:00
|
|
|
window.removeEventListener('hashchange', this.hashChangeAction)
|
|
|
|
document.removeEventListener('visibilitychange', this.visibiltyChangeAction)
|
2020-01-03 01:54:11 +00:00
|
|
|
|
|
|
|
//We want to remove event listeners, but something here is messing them up and preventing ALL event listeners from working
|
|
|
|
// this.$off() // Remove all event listeners
|
|
|
|
// this.$bus.$off()
|
2019-07-19 20:51:57 +00:00
|
|
|
},
|
|
|
|
mounted() {
|
2020-02-11 21:11:14 +00:00
|
|
|
|
2020-01-03 01:26:55 +00:00
|
|
|
//Loads initial batch and tags
|
|
|
|
this.reset()
|
2019-07-19 20:51:57 +00:00
|
|
|
},
|
|
|
|
methods: {
|
2019-12-20 05:50:50 +00:00
|
|
|
showOneColumn(){
|
|
|
|
//If note 1 or 2 is open, show one column. Or if the user is on mobile
|
|
|
|
return (this.activeNoteId1 != null || this.activeNoteId2 != null) &&
|
|
|
|
!this.$store.getters.getIsUserOnMobile
|
|
|
|
},
|
2020-01-03 01:26:55 +00:00
|
|
|
openNote(id, event = null){
|
|
|
|
|
|
|
|
//Don't open note if a link is clicked in display card
|
|
|
|
if(event && event.target && event.target.nodeName){
|
|
|
|
const nodeClick = event.target.nodeName
|
|
|
|
if(nodeClick == 'A'){ return }
|
|
|
|
}
|
2019-07-20 23:07:22 +00:00
|
|
|
|
|
|
|
//Do not open same note twice
|
|
|
|
if(this.activeNoteId1 == id || this.activeNoteId2 == id){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//1 note open
|
|
|
|
if(this.activeNoteId1 == null && this.activeNoteId2 == null){
|
|
|
|
this.activeNoteId1 = id
|
|
|
|
this.activeNote1Position = 0 //Middel of page
|
2019-09-10 18:10:11 +00:00
|
|
|
this.$router.push('/notes/open/'+this.activeNoteId1)
|
2019-07-20 23:07:22 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
//2 notes open
|
|
|
|
if(this.activeNoteId1 != null && this.activeNoteId2 == null){
|
|
|
|
this.activeNoteId2 = id
|
|
|
|
this.activeNote1Position = 1 //Right side of page
|
|
|
|
this.activeNote2Position = 2 //Left side of page
|
|
|
|
return
|
|
|
|
}
|
2019-09-10 18:10:11 +00:00
|
|
|
//2 notes open
|
|
|
|
if(this.activeNoteId2 != null && this.activeNoteId1 == null){
|
|
|
|
this.activeNoteId1 = id
|
|
|
|
this.activeNote1Position = 2 //Right side of page
|
|
|
|
this.activeNote2Position = 1 //Left side of page
|
|
|
|
return
|
|
|
|
}
|
2019-07-20 23:07:22 +00:00
|
|
|
},
|
|
|
|
closeNote(position){
|
|
|
|
//One note open, close that note
|
|
|
|
if(position == 0){
|
|
|
|
this.activeNoteId1 = null
|
|
|
|
this.activeNoteId2 = null
|
|
|
|
}
|
|
|
|
//Right note closed, thats 1
|
|
|
|
if(position == 1){
|
|
|
|
this.activeNoteId1 = null
|
|
|
|
}
|
|
|
|
if(position == 2){
|
|
|
|
this.activeNoteId2 = null
|
|
|
|
}
|
|
|
|
|
2020-01-03 01:26:55 +00:00
|
|
|
//IF two notes get opened, update ID of open note
|
|
|
|
if(this.activeNoteId1 || this.activeNoteId2){
|
|
|
|
this.$router.push('/notes/open/'+Math.max(this.activeNoteId1,this.activeNoteId2))
|
|
|
|
} else {
|
|
|
|
//No notes are open, just show notes page
|
|
|
|
this.$router.push('/notes')
|
|
|
|
}
|
2019-09-10 18:10:11 +00:00
|
|
|
|
2019-07-20 23:07:22 +00:00
|
|
|
this.activeNote1Position = 0
|
|
|
|
this.activeNote2Position = 0
|
|
|
|
|
|
|
|
},
|
2019-07-19 20:51:57 +00:00
|
|
|
toggleTagFilter(tagId){
|
|
|
|
|
|
|
|
if(this.searchTags.includes(tagId)){
|
|
|
|
this.searchTags.splice( this.searchTags.indexOf(tagId) , 1);
|
|
|
|
} else {
|
|
|
|
this.searchTags.push(tagId)
|
|
|
|
}
|
|
|
|
|
2020-01-03 01:26:55 +00:00
|
|
|
//Reset note set and load up notes and tags
|
|
|
|
if(this.searchTags.length > 0){
|
|
|
|
this.search(true, this.batchSize)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
//If no tags are selected, reset entire page
|
|
|
|
this.reset()
|
|
|
|
|
2019-07-19 20:51:57 +00:00
|
|
|
},
|
2019-12-20 05:50:50 +00:00
|
|
|
onScroll(e){
|
2019-09-10 18:10:11 +00:00
|
|
|
|
2019-12-20 05:50:50 +00:00
|
|
|
clearTimeout(this.loadingBatchTimeout)
|
|
|
|
this.loadingBatchTimeout = setTimeout(() => {
|
2019-09-10 18:10:11 +00:00
|
|
|
|
2019-12-20 05:50:50 +00:00
|
|
|
//Distance to bottom of page
|
|
|
|
const bottomOfWindow =
|
|
|
|
Math.max(window.pageYOffset, document.documentElement.scrollTop, document.body.scrollTop)
|
|
|
|
+ window.innerHeight
|
|
|
|
|
|
|
|
//height of page
|
|
|
|
const offsetHeight = this.$refs.content.clientHeight
|
|
|
|
|
|
|
|
//Determine percentage down the page
|
|
|
|
const percentageDown = Math.round( (bottomOfWindow/offsetHeight)*100 )
|
|
|
|
|
|
|
|
// console.log( percentageDown + '%' )
|
|
|
|
|
|
|
|
//If greater than 80 of the way down the page, load the next batch
|
|
|
|
if(percentageDown >= 80){
|
2020-02-10 21:09:09 +00:00
|
|
|
|
2019-12-20 05:50:50 +00:00
|
|
|
this.search(false, this.batchSize, true)
|
|
|
|
}
|
|
|
|
|
|
|
|
}, 50)
|
2019-09-10 18:10:11 +00:00
|
|
|
|
|
|
|
|
2019-12-20 05:50:50 +00:00
|
|
|
return
|
|
|
|
},
|
2020-01-03 01:26:55 +00:00
|
|
|
//Try to close notes on URL hash change /notes/open/123 to /notes - parse 123, close note id 123
|
|
|
|
hashChangeAction(event){
|
2020-02-10 17:44:43 +00:00
|
|
|
|
2020-01-03 01:26:55 +00:00
|
|
|
//Clean up path of hash change
|
|
|
|
let path = window.location.protocol + '//' + window.location.hostname + window.location.pathname + window.location.hash
|
|
|
|
let newPath = event.newURL.replace(path,'')
|
|
|
|
let oldPath = event.oldURL.replace(path,'')
|
|
|
|
|
|
|
|
//If we go from open note ID to no note ID, close the note
|
|
|
|
if(newPath == '' && oldPath.indexOf('/open/') != -1){
|
|
|
|
//Pull note ID out of URL
|
|
|
|
const noteIdToClose = oldPath.split('/').pop()
|
|
|
|
|
|
|
|
if(this.$refs.note1 && this.$refs.note1.currentNoteId == noteIdToClose){
|
|
|
|
this.$refs.note1.close()
|
|
|
|
}
|
|
|
|
|
|
|
|
if(this.$refs.note2 && this.$refs.note2.currentNoteId == noteIdToClose){
|
|
|
|
this.$refs.note2.close()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
visibiltyChangeAction(event){
|
|
|
|
|
|
|
|
//@TODO - set a timeout on this like 2 minutes or just dont do shit and update it via socket.io
|
|
|
|
//If user leaves page then returns to page, reload the first batch
|
|
|
|
if(this.lastVisibilityState == 'hidden' && document.visibilityState == 'visible'){
|
|
|
|
// console.log('Welcome back. Reloading a batch')
|
|
|
|
//Load initial batch, then tags, then other batch
|
|
|
|
this.search(false, this.firstLoadBatchSize)
|
|
|
|
.then( () => {
|
|
|
|
return this.fetchUserTags()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
this.lastVisibilityState = document.visibilityState
|
|
|
|
|
|
|
|
},
|
|
|
|
// @TODO Don't even trigger this if the note wasn't changed
|
|
|
|
updateSingleNote(noteId){
|
|
|
|
|
|
|
|
//Lookup one note using passed in ID
|
|
|
|
const postData = {
|
|
|
|
searchQuery: this.searchTerm,
|
|
|
|
searchTags: this.searchTags,
|
|
|
|
fastFilters:{
|
|
|
|
noteIdSet:[noteId]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
axios.post('/api/note/search', postData)
|
|
|
|
.then(results => {
|
|
|
|
|
|
|
|
//Pull note data out of note set
|
|
|
|
let newNote = results.data.notes[0]
|
|
|
|
let foundNote = false
|
|
|
|
|
|
|
|
if(newNote === undefined){
|
|
|
|
console.log('Note not visible on this page')
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
//Go through each note and find the one just updated
|
|
|
|
this.notes.forEach( (note,index) => {
|
|
|
|
|
|
|
|
if(note.id == noteId){
|
|
|
|
foundNote = true
|
|
|
|
|
|
|
|
//Don't move notes that were not changed
|
|
|
|
if(note.updated == newNote.updated){
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
//Compare note tags, if they changed, reload tags
|
|
|
|
if(newNote.tag_count != note.tag_count){
|
|
|
|
console.log('Tags changed, update those bitches')
|
|
|
|
this.fetchUserTags()
|
|
|
|
}
|
|
|
|
|
|
|
|
//go through each prop and update it with new values
|
|
|
|
Object.keys(newNote).forEach(prop => {
|
|
|
|
note[prop] = newNote[prop]
|
|
|
|
})
|
|
|
|
|
|
|
|
this.notes.splice(index, 1)
|
|
|
|
this.notes.unshift(note)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
//This note was not found, update it in list
|
|
|
|
if(foundNote == false){
|
|
|
|
if(newNote.pinned == 1){
|
|
|
|
this.containsPinnednotes++
|
|
|
|
} else {
|
|
|
|
this.containsNormalNotes++
|
|
|
|
}
|
|
|
|
this.notes.unshift(newNote)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
},
|
2020-02-01 22:21:22 +00:00
|
|
|
searchAttachments(){
|
|
|
|
axios.post('/api/attachment/textsearch', {'searchTerm':this.searchTerm})
|
|
|
|
.then(results => {
|
|
|
|
console.log('Attachment Results')
|
|
|
|
console.log(results.data)
|
|
|
|
this.foundAttachments = results.data
|
|
|
|
})
|
|
|
|
},
|
2019-12-20 05:50:50 +00:00
|
|
|
search(showLoading = true, notesInNextLoad = null, mergeExisting = false){
|
|
|
|
return new Promise((resolve, reject) => {
|
2019-09-10 18:10:11 +00:00
|
|
|
|
2020-01-03 01:26:55 +00:00
|
|
|
//Don't double load note batches
|
2019-12-20 05:50:50 +00:00
|
|
|
if(this.loadingInProgress){
|
|
|
|
return resolve()
|
|
|
|
}
|
|
|
|
|
2020-01-03 01:26:55 +00:00
|
|
|
//Reset a lot of stuff if we are not merging batches
|
|
|
|
if(!mergeExisting){
|
|
|
|
this.batchOffset = 0 // Reset batch offset if we are not merging note batches
|
|
|
|
// this.commonTags = [] //Don't reset tags, if search returns tags, they will be set
|
|
|
|
}
|
|
|
|
|
|
|
|
//Remove all filter limits from previous queries
|
2019-12-20 05:50:50 +00:00
|
|
|
delete this.fastFilters.limitSize
|
|
|
|
delete this.fastFilters.limitOffset
|
|
|
|
|
|
|
|
let postData = {
|
|
|
|
searchQuery: this.searchTerm,
|
|
|
|
searchTags: this.searchTags,
|
|
|
|
fastFilters: this.fastFilters,
|
|
|
|
}
|
|
|
|
|
|
|
|
if(showLoading){
|
|
|
|
this.working = true
|
|
|
|
}
|
|
|
|
|
|
|
|
//Save initial post data on first load
|
|
|
|
if(this.initialPostData == null){
|
|
|
|
this.initialPostData = JSON.stringify(postData)
|
|
|
|
}
|
|
|
|
//If post data is not the same as initial, show clear button
|
|
|
|
if(JSON.stringify(postData) != this.initialPostData){
|
|
|
|
this.showClear = true
|
|
|
|
}
|
|
|
|
|
|
|
|
if(notesInNextLoad && notesInNextLoad > 0){
|
|
|
|
//Create limit based off of the number of notes already loaded
|
|
|
|
postData.fastFilters.limitSize = notesInNextLoad
|
|
|
|
postData.fastFilters.limitOffset = this.batchOffset
|
|
|
|
}
|
|
|
|
|
|
|
|
//Perform search - or die
|
|
|
|
this.loadingInProgress = true
|
|
|
|
axios.post('/api/note/search', postData).
|
|
|
|
then(response => {
|
|
|
|
|
|
|
|
//Save the number of notes just loaded
|
|
|
|
this.batchOffset += response.data.notes.length
|
|
|
|
|
2020-01-03 01:26:55 +00:00
|
|
|
//Mush the two new sets of data together (set will be empty is reset is on)
|
|
|
|
if(response.data.tags.length > 0){
|
|
|
|
this.commonTags = response.data.tags
|
|
|
|
}
|
|
|
|
|
|
|
|
//Either reload all notes with return data or merge return data
|
|
|
|
if(!mergeExisting){
|
|
|
|
this.notes = response.data.notes
|
|
|
|
} else {
|
|
|
|
this.notes = this.notes.concat(response.data.notes)
|
|
|
|
}
|
2019-12-20 05:50:50 +00:00
|
|
|
|
|
|
|
//Go through each note and see which section to display
|
2020-01-03 01:26:55 +00:00
|
|
|
let textResultsCount = 0
|
|
|
|
let pinnedResultsCount = 0
|
|
|
|
let normalNotesCount = 0
|
2019-12-20 05:50:50 +00:00
|
|
|
response.data.notes.forEach(note => {
|
|
|
|
|
|
|
|
if(note.note_highlights.length > 0){
|
2020-01-03 01:26:55 +00:00
|
|
|
textResultsCount++
|
2019-12-20 05:50:50 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if(note.pinned == 1){
|
2020-01-03 01:26:55 +00:00
|
|
|
pinnedResultsCount++
|
2019-12-20 05:50:50 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-01-03 01:26:55 +00:00
|
|
|
normalNotesCount++
|
2019-12-20 05:50:50 +00:00
|
|
|
})
|
2020-01-03 01:26:55 +00:00
|
|
|
|
|
|
|
if(!mergeExisting){
|
|
|
|
this.containsNormalNotes = normalNotesCount
|
|
|
|
this.containsPinnednotes = pinnedResultsCount
|
|
|
|
this.containsTextResults = textResultsCount
|
|
|
|
} else {
|
|
|
|
this.containsNormalNotes += normalNotesCount
|
|
|
|
this.containsPinnednotes += pinnedResultsCount
|
|
|
|
this.containsTextResults += textResultsCount
|
|
|
|
}
|
2019-12-20 05:50:50 +00:00
|
|
|
|
|
|
|
this.working = false
|
|
|
|
this.loadingInProgress = false
|
|
|
|
|
|
|
|
return resolve(true)
|
|
|
|
})
|
2019-07-19 20:51:57 +00:00
|
|
|
})
|
|
|
|
},
|
|
|
|
searchKeyUp(){
|
|
|
|
let vm = this
|
|
|
|
clearTimeout(vm.searchDebounce)
|
|
|
|
vm.searchDebounce = setTimeout(() => {
|
2020-01-03 01:26:55 +00:00
|
|
|
this.search(true, this.batchSize)
|
|
|
|
.then( () => {
|
|
|
|
return this.fetchUserTags()
|
|
|
|
})
|
2019-12-20 05:50:50 +00:00
|
|
|
}, 500)
|
2019-07-19 20:51:57 +00:00
|
|
|
},
|
|
|
|
ucWords(str){
|
|
|
|
return (str + '')
|
|
|
|
.replace(/^(.)|\s+(.)/g, function ($1) {
|
|
|
|
return $1.toUpperCase()
|
|
|
|
})
|
|
|
|
},
|
|
|
|
reset(){
|
2019-12-20 05:50:50 +00:00
|
|
|
this.showClear = false
|
2019-07-19 20:51:57 +00:00
|
|
|
this.searchTerm = ''
|
|
|
|
this.searchTags = []
|
2019-09-10 18:10:11 +00:00
|
|
|
this.fastFilters = {}
|
2020-02-01 22:21:22 +00:00
|
|
|
this.foundAttachments = [] //Remove all attachments
|
2019-09-10 18:10:11 +00:00
|
|
|
this.$bus.$emit('reset_fast_filters')
|
2020-01-03 01:26:55 +00:00
|
|
|
|
|
|
|
//Load initial batch, then tags, then other batch
|
|
|
|
this.search(true, this.firstLoadBatchSize)
|
|
|
|
.then( () => {
|
|
|
|
return this.fetchUserTags()
|
|
|
|
})
|
|
|
|
.then( () => {
|
|
|
|
//Load a larger batch once first batch has loaded
|
|
|
|
return this.search(false, this.batchSize, true)
|
|
|
|
})
|
|
|
|
.then( i => {
|
|
|
|
//Thats how you promise chain
|
|
|
|
})
|
|
|
|
},
|
|
|
|
fetchUserTags(){
|
|
|
|
return new Promise((resolve, reject) => {
|
2020-02-12 05:29:56 +00:00
|
|
|
|
|
|
|
let postData = {
|
|
|
|
searchQuery: this.searchTerm,
|
|
|
|
searchTags: this.searchTags,
|
|
|
|
fastFilters: this.fastFilters,
|
|
|
|
}
|
|
|
|
|
|
|
|
axios.post('/api/tag/usertags', postData)
|
2020-01-03 01:26:55 +00:00
|
|
|
.then( ({data}) => {
|
|
|
|
this.commonTags = data
|
|
|
|
resolve(data)
|
|
|
|
})
|
|
|
|
})
|
2020-02-11 21:11:14 +00:00
|
|
|
},
|
|
|
|
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)
|
2019-07-19 20:51:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
<style type="text/css" scoped>
|
2019-12-20 05:50:50 +00:00
|
|
|
.mush-it-up {
|
|
|
|
width: calc(50% - 130px);
|
|
|
|
}
|
2019-07-19 20:51:57 +00:00
|
|
|
.detail {
|
|
|
|
float: right;
|
|
|
|
}
|
2019-07-29 07:22:47 +00:00
|
|
|
.note-card-display-area {
|
|
|
|
display: flex;
|
|
|
|
flex-wrap: wrap;
|
|
|
|
}
|
2019-12-20 05:50:50 +00:00
|
|
|
.display-area-title {
|
|
|
|
width: 100%;
|
|
|
|
display: inline-block;
|
|
|
|
}
|
|
|
|
.note-card-section {
|
|
|
|
/*padding-bottom: 15px;*/
|
|
|
|
}
|
|
|
|
.note-card-section + .note-card-section {
|
|
|
|
padding: 15px 0 0;
|
|
|
|
}
|
2019-07-19 20:51:57 +00:00
|
|
|
</style>
|