* Cleaned up unused things * Updated squire which had a comment typo update...thats it * Background color picker has matching colors and styles to text color picker * Added new black theme * Moved search to main page, show it on mobile and added options to push things to notes from search with experimental tag searching * Added active note menu buttons based on cursor location in text * Added more instant updating if app is open in two locations for the same user Scratch Pad and home page update with new notes and new text in real time
758 lines
22 KiB
Vue
758 lines
22 KiB
Vue
<template>
|
|
<div class="ui basic segment no-fluf-segment">
|
|
|
|
<div class="ui grid" ref="content">
|
|
|
|
<div class="sixteen wide column">
|
|
<!-- :class="{ 'sixteen wide column':showOneColumn(), 'sixteen wide column':!showOneColumn() }" -->
|
|
|
|
<div class="ui stackable grid">
|
|
|
|
<div class="ten wide column"
|
|
:class="{ 'sixteen wide column':$store.getters.getIsUserOnMobile }">
|
|
|
|
<div class="ui basic button shrinking"
|
|
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
|
|
<span class="floating ui green label" v-if="$store.getters.totals['unreadNotes'] > 0">
|
|
{{ $store.getters.totals['unreadNotes'] }}
|
|
</span>
|
|
</div>
|
|
|
|
<div class="ui basic button shrinking" 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>
|
|
|
|
<tag-display
|
|
:active-tags="searchTags"
|
|
v-on:tagClick="tagId => toggleTagFilter(tagId)"
|
|
/>
|
|
|
|
<div class="ui basic shrinking icon button" v-on:click="toggleTitleView()">
|
|
<i v-if="titleView" class="th icon"></i>
|
|
<i v-if="!titleView" class="bars icon"></i>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="six wide column">
|
|
<search-input
|
|
v-on:tagClick="tagId => toggleTagFilter(tagId)"
|
|
v-if="$store.getters.totals && $store.getters.totals['totalNotes']" />
|
|
</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>Show All Notes
|
|
</span>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="sixteen wide column" v-if="searchTerm.length > 0 && !loadingInProgress">
|
|
<h2 class="ui header">
|
|
<div class="content">
|
|
{{ searchResultsCount.toLocaleString() }} notes with keyword "{{ searchTerm }}"
|
|
<div v-if="searchResultsCount == 0" class="sub header">
|
|
Search can only find key words. Try a single word search.
|
|
</div>
|
|
</div>
|
|
</h2>
|
|
</div>
|
|
|
|
<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>
|
|
<h2 v-if="fastFilters['onlyShowEncrypted'] == 1">Password Protected - No longer supported</h2>
|
|
|
|
<!-- Note title card display -->
|
|
<div class="sixteen wide column">
|
|
|
|
<h3 v-if="$store.getters.totals && $store.getters.totals['totalNotes'] == 0">
|
|
No Notes Yet. <br>Thats ok.<br><br> <br>
|
|
<img loading="lazy" width="25%" src="/api/static/assets/marketing/hamburger.svg" alt="Create a new note"><br>
|
|
Create one when you feel ready.
|
|
</h3>
|
|
|
|
<!-- Go to one wide column, do not do this on mobile interface -->
|
|
<div :class="{'one-column':( showOneColumn() )}">
|
|
|
|
<!-- render each section based on notes in set -->
|
|
<div v-for="section,index in noteSections" v-if="section.length > 0" class="note-card-section">
|
|
<h5 class="ui tiny dividing header"><i :class="`green ${sectionData[index][0]} icon`"></i>{{ sectionData[index][1] }}</h5>
|
|
|
|
<div class="note-card-display-area">
|
|
<note-title-display-card
|
|
v-for="note in section"
|
|
:ref="'note-'+note.id"
|
|
:onClick="openNote"
|
|
:data="note"
|
|
:title-view="titleView"
|
|
: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 + '-' + note.tag_count + note.updated"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<loading-icon v-if="loadingInProgress" message="Decrypting Notes" />
|
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<!-- found attachments -->
|
|
<div class="sixteen wide column" v-if="foundAttachments.length > 0">
|
|
<h4><i class="folder open outline icon"></i> Found in Files ({{ foundAttachments.length }})</h4>
|
|
<attachment-display
|
|
v-for="item in foundAttachments"
|
|
:item="item"
|
|
:key="item.id"
|
|
:search-params="{}"
|
|
/>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
<input-notes
|
|
v-if="activeNoteId1 != null"
|
|
:noteid="activeNoteId1"
|
|
:position="activeNote1Position"
|
|
:url-data="$route.params"
|
|
ref="note1" />
|
|
<input-notes
|
|
v-if="activeNoteId2 != null"
|
|
:noteid="activeNoteId2"
|
|
:position="activeNote2Position"
|
|
ref="note2" />
|
|
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
|
|
import axios from 'axios'
|
|
|
|
export default {
|
|
name: 'SearchBar',
|
|
components: {
|
|
|
|
'input-notes': () => import(/* webpackChunkName: "NoteInputPanel" */ '@/components/NoteInputPanel.vue'),
|
|
|
|
'note-title-display-card': require('@/components/NoteTitleDisplayCard.vue').default,
|
|
'fast-filters': require('@/components/FastFilters.vue').default,
|
|
'search-input': require('@/components/SearchInput.vue').default,
|
|
'attachment-display': require('@/components/AttachmentDisplayCard').default,
|
|
'counter':require('@/components/AnimatedCounterComponent.vue').default,
|
|
'tag-display':require('@/components/TagDisplayComponent.vue').default,
|
|
'loading-icon':require('@/components/LoadingIconComponent.vue').default,
|
|
},
|
|
data () {
|
|
return {
|
|
initComponent: true,
|
|
commonTags: [],
|
|
searchTerm: '',
|
|
searchResultsCount: 0,
|
|
searchTags: [],
|
|
notes: [],
|
|
highlights: [],
|
|
searchDebounce: null,
|
|
fastFilters: {},
|
|
titleView: false,
|
|
|
|
//Load up notes in batches
|
|
firstLoadBatchSize: 10, //First set of rapidly loaded notes
|
|
batchSize: 25, //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,
|
|
scrollLoadEnabled: true,
|
|
|
|
//Clear button is not visible
|
|
showClear: false,
|
|
initialPostData: null,
|
|
currentPostData: null,
|
|
|
|
containsNormalNotes: 0,
|
|
containsPinnednotes: 0,
|
|
containsTextResults: 0,
|
|
// containsTagResults: 0,
|
|
// containsAttachmentResults: 0,
|
|
|
|
//Currently open notes in app
|
|
activeNoteId1: null,
|
|
activeNoteId2: null,
|
|
|
|
//Position determines how note is Positioned
|
|
activeNote1Position: 0,
|
|
activeNote2Position: 0,
|
|
|
|
lastVisibilityState: null,
|
|
|
|
foundAttachments: [],
|
|
|
|
sectionData: {
|
|
'pinned': ['thumbtack', 'Pinned'],
|
|
'archived': ['archive', 'Archived'],
|
|
'shared': ['envelope outline', 'Received Notes'],
|
|
'sent': ['paper plane outline', 'Shared Notes'],
|
|
'notes': ['file','Notes'],
|
|
'highlights': ['paragraph', 'Found In Text']
|
|
},
|
|
noteSections: {
|
|
pinned: [],
|
|
archived: [],
|
|
shared:[],
|
|
sent:[],
|
|
notes: [],
|
|
highlights: []
|
|
},
|
|
|
|
}
|
|
},
|
|
beforeMount(){
|
|
|
|
this.$parent.loginGateway()
|
|
|
|
this.$io.on('new_note_created', noteId => {
|
|
//Do not update note if its open
|
|
if(this.activeNoteId1 != noteId){
|
|
this.updateSingleNote(parseInt(noteId))
|
|
}
|
|
})
|
|
|
|
//Update title cards when new note text is saved
|
|
this.$io.on('new_note_text_saved', ({noteId, hash}) => {
|
|
//Do not update note if its open
|
|
if(this.activeNoteId1 != noteId){
|
|
this.updateSingleNote(parseInt(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(parseInt(noteId))
|
|
}
|
|
})
|
|
|
|
this.$bus.$on('update_single_note', (noteId) => {
|
|
this.updateSingleNote(noteId)
|
|
})
|
|
|
|
this.$bus.$on('note_deleted', (noteId) => {
|
|
//Remove deleted note from set, its deleted
|
|
|
|
Object.keys(this.noteSections).forEach( key => {
|
|
this.noteSections[key].forEach( (note, index) => {
|
|
if(note.id == noteId){
|
|
this.noteSections[key].splice(index,1)
|
|
this.$store.dispatch('fetchAndUpdateUserTotals')
|
|
return
|
|
}
|
|
})
|
|
})
|
|
})
|
|
|
|
this.$bus.$on('update_fast_filters', newFilter => {
|
|
this.fastFilters = newFilter
|
|
//Fast filters always return all the results and tags
|
|
this.search(true, this.batchSize, false).then( () => {
|
|
// return
|
|
})
|
|
})
|
|
|
|
//Event to update search from other areas
|
|
this.$bus.$on('update_search_term', sentInSearchTerm => {
|
|
this.searchTerm = sentInSearchTerm
|
|
this.search(true, this.batchSize)
|
|
.then( () => {
|
|
|
|
console.log('Search attachments disabled for now')
|
|
// this.searchAttachments()
|
|
|
|
// return
|
|
})
|
|
})
|
|
|
|
//New note button pushes open note event
|
|
this.$bus.$on('open_note', noteId => {
|
|
this.openNote(noteId)
|
|
})
|
|
|
|
//Reload page content
|
|
this.$bus.$on('note_reload', () => {
|
|
this.reset()
|
|
})
|
|
|
|
//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)
|
|
}
|
|
|
|
window.addEventListener('scroll', this.onScroll)
|
|
|
|
//Close notes when back button is pressed
|
|
window.addEventListener('hashchange', this.hashChangeAction)
|
|
|
|
//update note on visibility change
|
|
document.addEventListener('visibilitychange', this.visibiltyChangeAction);
|
|
|
|
},
|
|
beforeDestroy(){
|
|
window.removeEventListener('scroll', this.onScroll)
|
|
window.removeEventListener('hashchange', this.hashChangeAction)
|
|
document.removeEventListener('visibilitychange', this.visibiltyChangeAction)
|
|
|
|
this.$bus.$off('note_reload')
|
|
this.$bus.$off('close_active_note')
|
|
this.$bus.$off('update_single_note')
|
|
this.$bus.$off('note_deleted')
|
|
this.$bus.$off('update_fast_filters')
|
|
this.$bus.$off('update_search_term')
|
|
this.$bus.$off('open_note')
|
|
|
|
//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()
|
|
},
|
|
mounted() {
|
|
|
|
//Loads initial batch and tags
|
|
this.reset()
|
|
},
|
|
methods: {
|
|
toggleTitleView(){
|
|
this.titleView = !this.titleView
|
|
},
|
|
showOneColumn(){
|
|
|
|
return this.$store.getters.getIsUserOnMobile
|
|
|
|
//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
|
|
},
|
|
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 }
|
|
}
|
|
|
|
//1 note open
|
|
if(this.activeNoteId1 == null){
|
|
this.activeNoteId1 = id
|
|
this.activeNote1Position = 0 //Middel of page
|
|
this.$router.push('/notes/open/'+this.activeNoteId1)
|
|
return
|
|
}
|
|
},
|
|
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
|
|
}
|
|
|
|
//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')
|
|
}
|
|
|
|
this.activeNote1Position = 0
|
|
this.activeNote2Position = 0
|
|
|
|
},
|
|
toggleTagFilter(tagId){
|
|
|
|
this.searchTags = [tagId]
|
|
|
|
//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()
|
|
|
|
},
|
|
onScroll(e){
|
|
|
|
clearTimeout(this.loadingBatchTimeout)
|
|
this.loadingBatchTimeout = setTimeout(() => {
|
|
|
|
//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 )
|
|
|
|
//If greater than 80 of the way down the page, load the next batch
|
|
if(percentageDown >= 65 && this.scrollLoadEnabled){
|
|
|
|
this.search(false, this.batchSize, true)
|
|
}
|
|
|
|
}, 50)
|
|
|
|
|
|
return
|
|
},
|
|
//Try to close notes on URL hash change /notes/open/123 to /notes - parse 123, close note id 123
|
|
hashChangeAction(event){
|
|
|
|
//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,'')
|
|
|
|
// console.log(this.$route.params)
|
|
// console.log(this.$router)
|
|
|
|
//Open note if user goes forward to a note id
|
|
if(this.$route.params && this.$route.params.id){
|
|
this.openNote(this.$route.params.id)
|
|
}
|
|
|
|
//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()
|
|
|
|
// console.log(noteIdToClose)
|
|
|
|
if(this.$refs.note1 && this.$refs.note1.currentNoteId == noteIdToClose){
|
|
// this.$refs.note1.close()
|
|
}
|
|
}
|
|
},
|
|
visibiltyChangeAction(event){
|
|
|
|
//Fuck this shit, just use web sockets
|
|
return
|
|
|
|
//@TODO - phase this out, update it via socket.io
|
|
//If user leaves page then returns to page, reload the first batch
|
|
if(this.lastVisibilityState == 'hidden' && document.visibilityState == 'visible'){
|
|
//Load initial batch, then tags, then other batch
|
|
this.search(false, this.firstLoadBatchSize)
|
|
.then( () => {
|
|
// return
|
|
})
|
|
}
|
|
|
|
this.lastVisibilityState = document.visibilityState
|
|
|
|
},
|
|
// @TODO Don't even trigger this if the note wasn't changed
|
|
updateSingleNote(noteId){
|
|
|
|
//Find local note, if it exists; continue
|
|
|
|
|
|
//Lookup one note using passed in ID
|
|
const postData = {
|
|
searchQuery: this.searchTerm,
|
|
searchTags: this.searchTags,
|
|
fastFilters:{
|
|
noteIdSet:[noteId]
|
|
}
|
|
}
|
|
|
|
//Note data must be fetched, then sorted into existing note data
|
|
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){
|
|
return
|
|
}
|
|
|
|
//Find Just updated note and modify all its attributes
|
|
Object.keys(this.noteSections).forEach(key => {
|
|
|
|
this.noteSections[key].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){
|
|
|
|
}
|
|
|
|
//go through each prop and update it with new values
|
|
Object.keys(newNote).forEach(prop => {
|
|
note[prop] = newNote[prop]
|
|
})
|
|
|
|
//Remove note from location and push to front
|
|
this.noteSections[key].splice(index, 1)
|
|
this.noteSections[key].unshift(note)
|
|
|
|
this.$nextTick( () => {
|
|
|
|
//Trigger close animation on note
|
|
if(this.$refs['note-'+noteId] && this.$refs['note-'+noteId][0]){
|
|
this.$refs['note-'+noteId][0].justClosed()
|
|
}
|
|
})
|
|
|
|
return
|
|
}
|
|
})
|
|
})
|
|
|
|
//New notes don't exist in list, push them to the front
|
|
if(!foundNote){
|
|
this.noteSections.notes.unshift(newNote)
|
|
}
|
|
//Trigger section rebuild
|
|
this.rebuildNoteCategorise()
|
|
})
|
|
.catch(error => { this.$bus.$emit('notification', 'Failed to Search Notes') })
|
|
},
|
|
searchAttachments(){
|
|
axios.post('/api/attachment/textsearch', {'searchTerm':this.searchTerm})
|
|
.then(results => {
|
|
this.foundAttachments = results.data
|
|
})
|
|
.catch(error => { this.$bus.$emit('notification', 'Failed to Search Attachments') })
|
|
},
|
|
search(showLoading = true, notesInNextLoad = null, mergeExisting = false){
|
|
return new Promise((resolve, reject) => {
|
|
|
|
//Don't double load note batches
|
|
if(this.loadingInProgress){
|
|
console.log('Loading in progress, cancel operation')
|
|
return resolve()
|
|
}
|
|
|
|
//Reset a lot of stuff if we are not merging batches
|
|
if(!mergeExisting){
|
|
Object.keys(this.noteSections).forEach( key => {
|
|
this.noteSections[key] = []
|
|
})
|
|
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
|
|
}
|
|
this.searchResultsCount = 0
|
|
|
|
//Remove all filter limits from previous queries
|
|
delete this.fastFilters.limitSize
|
|
delete this.fastFilters.limitOffset
|
|
|
|
let postData = {
|
|
searchQuery: this.searchTerm,
|
|
searchTags: this.searchTags,
|
|
fastFilters: this.fastFilters,
|
|
}
|
|
|
|
//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
|
|
// console.time('Fetch TitleCard Batch '+notesInNextLoad)
|
|
axios.post('/api/note/search', postData)
|
|
.then(response => {
|
|
|
|
// console.timeEnd('Fetch TitleCard Batch '+notesInNextLoad)
|
|
|
|
//Save the number of notes just loaded
|
|
this.batchOffset += response.data.notes.length
|
|
|
|
//Enable or disable scroll loading
|
|
this.scrollLoadEnabled = response.data.notes.length > 0
|
|
|
|
//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
|
|
// }
|
|
|
|
if(response.data.total > 0){
|
|
this.searchResultsCount = response.data.total
|
|
}
|
|
|
|
this.loadingInProgress = false
|
|
this.generateNoteCategories(response.data.notes, mergeExisting)
|
|
|
|
return resolve(true)
|
|
})
|
|
.catch(error => { this.$bus.$emit('notification', 'Failed to Search Notes') })
|
|
})
|
|
},
|
|
rebuildNoteCategorise(){
|
|
let currentNotes = []
|
|
Object.keys(this.noteSections).forEach( key => {
|
|
this.noteSections[key].forEach( note => {
|
|
currentNotes.push(note)
|
|
})
|
|
})
|
|
this.generateNoteCategories(currentNotes, false)
|
|
},
|
|
generateNoteCategories(notes, mergeExisting){
|
|
// Place each note in a category based on certain attributes and fast filters
|
|
|
|
//Reset all sections if we are not merging existing
|
|
if(!mergeExisting){
|
|
Object.keys(this.noteSections).forEach( key => {
|
|
this.noteSections[key] = []
|
|
})
|
|
}
|
|
|
|
//Sort notes into defined sections
|
|
notes.forEach(note => {
|
|
|
|
//Show archived notes
|
|
if(note.archived == 1 && this.fastFilters.onlyArchived == 1){
|
|
this.noteSections.archived.push(note)
|
|
return
|
|
}
|
|
if(note.shareUsername != null){
|
|
this.noteSections.shared.push(note)
|
|
return
|
|
}
|
|
//Only show sent notes section if shared is selected
|
|
if(note.shared == 2 && this.fastFilters.onlyShowSharedNotes == 1){
|
|
this.noteSections.sent.push(note)
|
|
return
|
|
}
|
|
if(note.note_highlights.length > 0){
|
|
this.noteSections.highlights.push(note)
|
|
return
|
|
}
|
|
// Pinned notes are always first, they can appear in the archive
|
|
if(note.pinned == 1){
|
|
this.noteSections.pinned.push(note)
|
|
return
|
|
}
|
|
//If the note is not archived, push it.
|
|
if(note.archived != 1 && this.fastFilters.onlyArchived != 1){
|
|
this.noteSections.notes.push(note)
|
|
}
|
|
})
|
|
|
|
},
|
|
reset(){
|
|
this.showClear = false
|
|
this.scrollLoadEnabled = true
|
|
this.searchTerm = ''
|
|
this.searchTags = []
|
|
this.fastFilters = {}
|
|
this.foundAttachments = [] //Remove all attachments
|
|
this.$bus.$emit('reset_fast_filters')
|
|
|
|
//Load initial batch, then tags, then other batch
|
|
this.search(true, this.firstLoadBatchSize)
|
|
.then( () => {
|
|
|
|
|
|
//Load a larger batch once first batch has loaded
|
|
return this.search(false, this.batchSize, true)
|
|
})
|
|
.then( i => {
|
|
//Thats how you promise chain
|
|
})
|
|
},
|
|
updateFastFilters(index){
|
|
|
|
//clear out tags
|
|
this.searchTags = []
|
|
|
|
//A little hacky, brings user to notes page then filters on click
|
|
if(this.$route.name != 'Note Page'){
|
|
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
|
|
'onlyShowEncrypted',
|
|
]
|
|
|
|
let filter = {}
|
|
filter[options[index]] = 1
|
|
|
|
this.$bus.$emit('update_fast_filters', filter)
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<style type="text/css" scoped>
|
|
|
|
.detail {
|
|
float: right;
|
|
}
|
|
.note-card-display-area {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
}
|
|
.display-area-title {
|
|
width: 100%;
|
|
display: inline-block;
|
|
}
|
|
.note-card-section {
|
|
/*padding-bottom: 15px;*/
|
|
}
|
|
.note-card-section + .note-card-section {
|
|
padding: 15px 0 0;
|
|
}
|
|
</style> |