Tweaked a lot of styles and added some cool animations Added a little to the help text Quickly adding a note, saving and closing no longer causes half formed or empty notes to appear Close Editor animation Display cards text show at the bottom of card Added a delete function, and it works Added browser title attributes More debugging and error checking on scraped links Updated not search to display title and text below the title
241 lines
5.8 KiB
Vue
241 lines
5.8 KiB
Vue
<template>
|
|
<div>
|
|
|
|
|
|
<div class="ui equal width grid">
|
|
|
|
<!-- mobile search menu -->
|
|
<div class="ui mobile only row">
|
|
<!-- Small screen new note button -->
|
|
<div class="ui four wide column">
|
|
<div @click="createNote" class="ui fluid green icon button">
|
|
<i class="plus icon"></i>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="ui twelve wide column">
|
|
<div class="ui form">
|
|
<input v-model="searchTerm" @keyup="searchKeyUp" @:keyup.enter="search" placeholder="Search Notes" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- search menu -->
|
|
<div class="ui large screen only row">
|
|
|
|
<div class="ui two wide column">
|
|
<div @click="createNote" class="ui fluid green button">
|
|
<i class="plus icon"></i>
|
|
New Note
|
|
</div>
|
|
</div>
|
|
|
|
<div class="ui five wide column">
|
|
<div class="ui form">
|
|
<input v-model="searchTerm" @keyup="searchKeyUp" @:keyup.enter="search" placeholder="Search Notes" />
|
|
</div>
|
|
</div>
|
|
|
|
<div class="ui nine wide column">
|
|
|
|
<router-link class="ui basic button" to="/help">Help</router-link>
|
|
|
|
<div class="ui right floated basic button"
|
|
data-tooltip="Log Out" data-position="left center"
|
|
v-on:click="destroyLoginToken">{{username}}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="ui row">
|
|
|
|
<!-- tags display -->
|
|
<div class="ui two wide large screen only column">
|
|
<div class="ui basic fluid button" @click="reset"><i class="undo icon"></i>All Notes</div>
|
|
<div class="ui divider"></div>
|
|
<div class="ui clickable basic fluid large label" v-for="tag in commonTags" @click="toggleTagFilter(tag.id)"
|
|
:class="{ 'green':(searchTags.includes(tag.id)) }">
|
|
{{ucWords(tag.text)}} <div class="detail">{{tag.usages}}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Note title cards -->
|
|
<div class="ui fourteen wide computer sixteen wide mobile column">
|
|
<h2>Notes ({{notes.length}})</h2>
|
|
<div v-if="notes !== null" class="note-card-display-area" :class="{'one-column':(activeNoteId1 != null || activeNoteId2 != null )}">
|
|
<note-title-display-card
|
|
v-for="note in notes"
|
|
:onClick="openNote"
|
|
:data="note"
|
|
:key="note.id + note.color + searchTerm + note.note_highlights.length + note.attachment_highlights.length + note.tag_highlights.length"
|
|
/>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<input-notes v-if="activeNoteId1 != null" :noteid="activeNoteId1" :position="activeNote1Position" />
|
|
<input-notes v-if="activeNoteId2 != null" :noteid="activeNoteId2" :position="activeNote2Position" />
|
|
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
|
|
import axios from 'axios';
|
|
|
|
export default {
|
|
name: 'SearchBar',
|
|
components: {
|
|
'input-notes': require('./InputNotes.vue').default,
|
|
'note-title-display-card': require('./NoteTitleDisplayCard.vue').default,
|
|
},
|
|
data () {
|
|
return {
|
|
username:'',
|
|
initComponent: true,
|
|
commonTags: [],
|
|
searchTerm: '',
|
|
searchTags: [],
|
|
notes: [],
|
|
searchDebounce: null,
|
|
|
|
//Currently open notes in app
|
|
activeNoteId1: null,
|
|
activeNoteId2: null,
|
|
//Position determines how note is Positioned
|
|
activeNote1Position: 0,
|
|
activeNote2Position: 0,
|
|
}
|
|
},
|
|
beforeMount(){
|
|
this.$bus.$on('close_active_note', position => {
|
|
this.closeNote(position)
|
|
})
|
|
this.$bus.$on('note_deleted', () => {
|
|
this.search()
|
|
})
|
|
|
|
},
|
|
mounted() {
|
|
let username = this.$store.getters.getUsername
|
|
this.username = this.ucWords(username)
|
|
|
|
this.search()
|
|
|
|
},
|
|
methods: {
|
|
openNote(id){
|
|
|
|
//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
|
|
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
|
|
}
|
|
},
|
|
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
|
|
}
|
|
|
|
this.activeNote1Position = 0
|
|
this.activeNote2Position = 0
|
|
|
|
this.search()
|
|
},
|
|
toggleTagFilter(tagId){
|
|
|
|
if(this.searchTags.includes(tagId)){
|
|
this.searchTags.splice( this.searchTags.indexOf(tagId) , 1);
|
|
} else {
|
|
this.searchTags.push(tagId)
|
|
}
|
|
|
|
this.search()
|
|
},
|
|
search(){
|
|
let postData = {
|
|
searchQuery: this.searchTerm,
|
|
searchTags: this.searchTags
|
|
}
|
|
//Perform search
|
|
let vm = this
|
|
axios.post('/api/notes/search', postData).
|
|
then(response => {
|
|
console.log('Notes and Tags')
|
|
console.log(response.data)
|
|
|
|
vm.commonTags = response.data.tags
|
|
vm.notes = response.data.notes
|
|
vm.highlights = response.data.highlights
|
|
})
|
|
},
|
|
searchKeyUp(){
|
|
let vm = this
|
|
clearTimeout(vm.searchDebounce)
|
|
vm.searchDebounce = setTimeout(() => {
|
|
vm.search()
|
|
}, 300)
|
|
},
|
|
createNote(event){
|
|
const title = ''
|
|
let vm = this
|
|
|
|
axios.post('/api/notes/create', {title})
|
|
.then(response => {
|
|
|
|
if(response.data && response.data.id){
|
|
vm.openNote(response.data.id)
|
|
}
|
|
})
|
|
},
|
|
ucWords(str){
|
|
return (str + '')
|
|
.replace(/^(.)|\s+(.)/g, function ($1) {
|
|
return $1.toUpperCase()
|
|
})
|
|
},
|
|
reset(){
|
|
this.searchTerm = ''
|
|
this.searchTags = []
|
|
this.search()
|
|
},
|
|
destroyLoginToken() {
|
|
this.$store.commit('destroyLoginToken')
|
|
this.$router.push('/')
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<style type="text/css" scoped>
|
|
.detail {
|
|
float: right;
|
|
}
|
|
.note-card-display-area {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
}
|
|
</style> |