Added a night mode and no way to toggle it!
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
This commit is contained in:
parent
b0a8071b41
commit
fcee24a61d
@ -1,18 +1,110 @@
|
||||
/*body, h3, h2, h1, p {
|
||||
color: #3d3d3d;
|
||||
}*/
|
||||
|
||||
:root {
|
||||
--primary_color: #1C84DA;
|
||||
--secondary_color: #1EAEDB;
|
||||
|
||||
--element_background_color: #FFF;
|
||||
|
||||
|
||||
|
||||
--background_color: #fff;
|
||||
--text_color: #3d3d3d;
|
||||
--outline_color: rgba(34,36,38,.15);
|
||||
}
|
||||
|
||||
/* Night mode colors */
|
||||
:root {
|
||||
--background_color: #000;
|
||||
--text_color: #a98457;
|
||||
--outline_color: #a98457;
|
||||
}
|
||||
|
||||
/* OVERWRITE DEFAULT SEMANTIC STYLES FOR CUSTOM/NIGHT MODES*/
|
||||
body{
|
||||
color: var(--text_color);
|
||||
background-color: var(--background_color);
|
||||
}
|
||||
.ui.form input:not([type]),
|
||||
.ui.form input:not([type]):focus {
|
||||
color: var(--text_color);
|
||||
background-color: var(--background_color);
|
||||
border-color: var(--border_color);
|
||||
}
|
||||
.ui.basic.label {
|
||||
color: var(--text_color);
|
||||
background-color: var(--background_color);
|
||||
border-color: var(--border_color);
|
||||
}
|
||||
div.ui.basic.green.label {
|
||||
background-color: var(--background_color) !important;
|
||||
}
|
||||
.ui.basic.button, .ui.basic.buttons .button {
|
||||
background-color: var(--background_color) !important;
|
||||
color: var(--text_color) !important;
|
||||
border: 1px solid;
|
||||
border-color: var(--border_color) !important;
|
||||
box-shadow: none;
|
||||
}
|
||||
.ui.basic.button:focus, .ui.basic.button:hover {
|
||||
background-color: var(--background_color) !important;
|
||||
color: var(--text_color) !important;
|
||||
box-shadow: none;
|
||||
}
|
||||
.ui.tabular.menu .item {
|
||||
background-color: var(--background_color) !important;
|
||||
color: var(--text_color) !important;
|
||||
}
|
||||
.ui.tabular.menu .item.active {
|
||||
background-color: var(--background_color) !important;
|
||||
color: var(--text_color) !important;
|
||||
border-color: var(--border_color) !important;
|
||||
}
|
||||
/* OVERWRITE DEFAULT SEMANTIC STYLES FOR CUSTOM/NIGHT MODES*/
|
||||
|
||||
|
||||
|
||||
.clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.textarea-height {
|
||||
height: calc(100% - 105px);
|
||||
}
|
||||
.ck-content {
|
||||
font-family: 'Open Sans' !important;
|
||||
font-size: 1.3rem !important;
|
||||
background-color: rgba(255, 255, 255, 0);
|
||||
height: 100%;
|
||||
height: calc(100% - 40px);
|
||||
overflow: hidden;
|
||||
}
|
||||
.ck .ck-editor__nested-editable:focus {
|
||||
background-color: var(--background_color) !important;
|
||||
}
|
||||
.ui.white.button {
|
||||
background: #FFF;
|
||||
}
|
||||
|
||||
.fade-in-fwd {
|
||||
animation: fade-in-fwd 0.8s both;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------
|
||||
* Generated by Animista on 2019-7-25 17:12:5
|
||||
* w: http://animista.net, t: @cssanimista
|
||||
* ---------------------------------------------- */
|
||||
|
||||
/**
|
||||
* ----------------------------------------
|
||||
* animation fade-in-fwd
|
||||
* ----------------------------------------
|
||||
*/
|
||||
@keyframes fade-in-fwd {
|
||||
0% {
|
||||
transform: translateZ(-80px);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateZ(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
40
client/src/components/DeleteButtonComponent.vue
Normal file
40
client/src/components/DeleteButtonComponent.vue
Normal file
@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<span>
|
||||
<span class="clickable" @click="confirmDelete()" v-if="click == 0">
|
||||
<i class="grey trash alternate icon"></i>
|
||||
</span>
|
||||
<span class="clickable" @click="actuallyDelete()" @mouseleave="reset" v-if="click == 1" data-tooltip="Click again to delete." data-position="left center">
|
||||
<i class="red trash alternate icon"></i>
|
||||
</span>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'NoteTitleDisplayCard',
|
||||
props: [ 'noteId', 'displayText' ],
|
||||
data () {
|
||||
return {
|
||||
click: 0,
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
confirmDelete(){
|
||||
this.click++
|
||||
},
|
||||
actuallyDelete(){
|
||||
axios.post('/api/notes/delete', {'noteId':this.noteId}).then(response => {
|
||||
if(response.data == true){
|
||||
this.$bus.$emit('note_deleted')
|
||||
}
|
||||
})
|
||||
},
|
||||
reset(){
|
||||
this.click = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -2,6 +2,9 @@
|
||||
<div class="ui basic segment">
|
||||
<div class="ui container">
|
||||
|
||||
CTRL + SHIFT + V - paste without formatting
|
||||
CTRL + Z - Undo in note, <b>Undo youtube video player embed.</b>
|
||||
|
||||
<h2>Block formatting</h2>
|
||||
|
||||
<p>The following block formatting options are available:</p>
|
||||
|
@ -1,49 +1,54 @@
|
||||
<template>
|
||||
<div id="InputNotes" class="master-note-edit" :class="[ 'position-'+position ]" @keyup.esc="close" :style="{'background-color':color, 'color':fontColor}">
|
||||
<div
|
||||
id="InputNotes" class="master-note-edit"
|
||||
@keyup.esc="close"
|
||||
:class="[{'size-down':(sizeDown == true)}, 'position-'+position ]"
|
||||
:style="{'background-color':color, 'color':fontColor}"
|
||||
>
|
||||
|
||||
<div v-if="fancyInput == 1" class="textarea-height no-flow">
|
||||
<ckeditor ref="main-edit"
|
||||
:editor="editor" @ready="onReady" v-model="noteText" :config="editorConfig" v-on:blur="save" />
|
||||
</div>
|
||||
|
||||
<div v-if="fancyInput == 1" class="textarea-height no-flow">
|
||||
<ckeditor ref="main-edit"
|
||||
:editor="editor" @ready="onReady" v-model="noteText" :config="editorConfig" v-on:blur="save" />
|
||||
</div>
|
||||
<textarea
|
||||
class="textarea-height raw-edit"
|
||||
v-if="fancyInput == 0"
|
||||
v-model="noteText"
|
||||
v-on:blur="save"
|
||||
v-on:keyup="onKeyup"
|
||||
/>
|
||||
|
||||
<textarea
|
||||
class="textarea-height raw-edit"
|
||||
v-if="fancyInput == 0"
|
||||
v-model="noteText"
|
||||
v-on:blur="save"
|
||||
v-on:keyup="onKeyup"
|
||||
/>
|
||||
|
||||
<div class="ui buttons">
|
||||
<div class="ui right floated green button">{{statusText}}</div>
|
||||
<div class="ui button">Delete</div>
|
||||
<div @click="close" class="ui button">Close (ESC)</div>
|
||||
<div @click="onToggleFancyInput" class="ui button">
|
||||
Fancy ({{fancyInput?'On':'Off'}})
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui buttons">
|
||||
<button @click="onChangeColor" class="ui icon white button"></button>
|
||||
<button @click="onChangeColor" class="ui icon red button"></button>
|
||||
<button @click="onChangeColor" class="ui icon orange button"></button>
|
||||
<button @click="onChangeColor" class="ui icon yellow button"></button>
|
||||
<button @click="onChangeColor" class="ui icon olive button"></button>
|
||||
<button @click="onChangeColor" class="ui icon green button"></button>
|
||||
<button @click="onChangeColor" class="ui icon teal button"></button>
|
||||
<button @click="onChangeColor" class="ui icon blue button"></button>
|
||||
<button @click="onChangeColor" class="ui icon violet button"></button>
|
||||
<button @click="onChangeColor" class="ui icon purple button"></button>
|
||||
<button @click="onChangeColor" class="ui icon pink button"></button>
|
||||
<button @click="onChangeColor" class="ui icon brown button"></button>
|
||||
<button @click="onChangeColor" class="ui icon grey button"></button>
|
||||
<button @click="onChangeColor" class="ui icon black button"></button>
|
||||
</div>
|
||||
<div class="ui buttons">
|
||||
<div @click="close" class="ui button">Close + Save (ESC)</div>
|
||||
<div class="ui button">Delete</div>
|
||||
|
||||
<div @click="onToggleFancyInput" class="ui button">
|
||||
Fancy ({{fancyInput?'On':'Off'}})
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui buttons">
|
||||
<button @click="onChangeColor" class="ui icon white button"></button>
|
||||
<button @click="onChangeColor" class="ui icon red button"></button>
|
||||
<button @click="onChangeColor" class="ui icon orange button"></button>
|
||||
<button @click="onChangeColor" class="ui icon yellow button"></button>
|
||||
<button @click="onChangeColor" class="ui icon olive button"></button>
|
||||
<button @click="onChangeColor" class="ui icon green button"></button>
|
||||
<button @click="onChangeColor" class="ui icon teal button"></button>
|
||||
<button @click="onChangeColor" class="ui icon blue button"></button>
|
||||
<button @click="onChangeColor" class="ui icon violet button"></button>
|
||||
<button @click="onChangeColor" class="ui icon purple button"></button>
|
||||
<button @click="onChangeColor" class="ui icon pink button"></button>
|
||||
<button @click="onChangeColor" class="ui icon brown button"></button>
|
||||
<button @click="onChangeColor" class="ui icon grey button"></button>
|
||||
<button @click="onChangeColor" class="ui icon black button"></button>
|
||||
</div>
|
||||
<div class="ui right floated green button">{{statusText}}</div>
|
||||
<!-- <p>
|
||||
Last Updated: {{$helpers.timeAgo(updated)}}
|
||||
</p> -->
|
||||
Last Updated: {{$helpers.timeAgo(updated)}}
|
||||
</p> -->
|
||||
|
||||
<note-tag-edit :noteId="noteid" :key="'tags-for-note-'+noteid"/>
|
||||
<note-tag-edit :noteId="noteid" :key="'tags-for-note-'+noteid"/>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
@ -64,7 +69,7 @@
|
||||
return {
|
||||
currentNoteId: 0,
|
||||
noteText: '',
|
||||
statusText: 'Save',
|
||||
statusText: 'Saved',
|
||||
lastNoteHash: null,
|
||||
saveDebounce: null, //Prevent save from being called numerous times quickly
|
||||
lastSaved: 0,
|
||||
@ -74,6 +79,7 @@
|
||||
fancyInput: 0, //Default to basic text edit. Upgrade if set to 1
|
||||
color: '#FFF',
|
||||
fontColor: '#000',
|
||||
sizeDown: false,
|
||||
|
||||
editor: DecoupledEditor,
|
||||
editorConfig: {
|
||||
@ -127,7 +133,7 @@
|
||||
|
||||
if(this.color == "rgb(255, 255, 255)" || this.color == '#FFF'){
|
||||
this.color = null
|
||||
this.fontColor = '#000'
|
||||
this.fontColor = null
|
||||
}
|
||||
|
||||
this.lastNoteHash = 0 //Update hash to force note update on next save
|
||||
@ -150,7 +156,7 @@
|
||||
this.fontColor = '#FFF'
|
||||
if(this.color == "rgb(255, 255, 255)" || this.color == '#FFF' || this.color == null){
|
||||
this.color = null
|
||||
this.fontColor = '#000'
|
||||
this.fontColor = null
|
||||
}
|
||||
|
||||
if(response.data.raw_input == 1){
|
||||
@ -201,14 +207,16 @@
|
||||
|
||||
} );
|
||||
},
|
||||
//Used by simple editor
|
||||
onKeyup(){
|
||||
let vm = this
|
||||
vm.statusText = 'Modified'
|
||||
//Each note, save after 5 seconds, focus lost or 30 characters typed.
|
||||
clearTimeout(vm.editDebounce)
|
||||
vm.editDebounce = setTimeout(() => {
|
||||
vm.save()
|
||||
}, 5000)
|
||||
//Save after 20 keystrokes
|
||||
//Save after 30 keystrokes
|
||||
vm.keyPressesCounter = (vm.keyPressesCounter + 1)
|
||||
if(vm.keyPressesCounter > 30){
|
||||
vm.keyPressesCounter = 0
|
||||
@ -216,36 +224,40 @@
|
||||
}
|
||||
},
|
||||
save(){
|
||||
|
||||
clearTimeout(this.editDebounce)
|
||||
return new Promise((resolve, reject) => {
|
||||
clearTimeout(this.editDebounce)
|
||||
|
||||
//Don't save note if its hash doesn't change
|
||||
if( this.lastNoteHash == this.hashString(this.noteText) ){
|
||||
return
|
||||
}
|
||||
|
||||
const postData = {
|
||||
'noteId':this.currentNoteId,
|
||||
'text': this.noteText,
|
||||
'fancyInput': this.fancyInput,
|
||||
'color': this.color
|
||||
}
|
||||
//Don't save note if its hash doesn't change
|
||||
if( this.lastNoteHash == this.hashString(this.noteText) ){
|
||||
setTimeout(() => {
|
||||
resolve(true)
|
||||
return
|
||||
}, 500)
|
||||
}
|
||||
|
||||
const postData = {
|
||||
'noteId':this.currentNoteId,
|
||||
'text': this.noteText,
|
||||
'fancyInput': this.fancyInput,
|
||||
'color': this.color
|
||||
}
|
||||
|
||||
let vm = this
|
||||
//Only save every 1 second
|
||||
clearTimeout(this.saveDebounce)
|
||||
this.saveDebounce = setTimeout(() => {
|
||||
//Only notify user if saving - may help with debugging in the future
|
||||
vm.statusText = 'Saving'
|
||||
axios.post('/api/notes/update', postData).then( response => {
|
||||
vm.statusText = 'Save'
|
||||
vm.updated = Math.round((+new Date)/1000)
|
||||
|
||||
//Update last saved note hash
|
||||
vm.lastNoteHash = vm.hashString(vm.noteText)
|
||||
})
|
||||
}, 500)
|
||||
let vm = this
|
||||
//Only save every 1 second
|
||||
clearTimeout(this.saveDebounce)
|
||||
this.saveDebounce = setTimeout(() => {
|
||||
//Only notify user if saving - may help with debugging in the future
|
||||
vm.statusText = 'Saving'
|
||||
axios.post('/api/notes/update', postData).then( response => {
|
||||
vm.statusText = 'Saved'
|
||||
vm.updated = Math.round((+new Date)/1000)
|
||||
|
||||
//Update last saved note hash
|
||||
vm.lastNoteHash = vm.hashString(vm.noteText)
|
||||
resolve(true)
|
||||
})
|
||||
}, 500)
|
||||
})
|
||||
|
||||
},
|
||||
hashString(text){
|
||||
@ -261,8 +273,11 @@
|
||||
return hash;
|
||||
},
|
||||
close(){
|
||||
this.save()
|
||||
this.$bus.$emit('close_active_note', this.position)
|
||||
this.sizeDown = true
|
||||
this.save().then( () => {
|
||||
this.$bus.$emit('close_active_note', this.position)
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -270,9 +285,7 @@
|
||||
|
||||
<style type="text/css" scoped>
|
||||
|
||||
.textarea-height {
|
||||
height: calc(100% - 177px);
|
||||
}
|
||||
|
||||
.no-flow {
|
||||
overflow: hidden;
|
||||
}
|
||||
@ -280,7 +293,7 @@
|
||||
.raw-edit {
|
||||
font-family: 'Open Sans' !important;
|
||||
font-size: 1.3rem !important;
|
||||
background: white;
|
||||
background: rgba(0,0,0,0);
|
||||
width: 100%;
|
||||
resize: none;
|
||||
padding: 15px;
|
||||
@ -292,7 +305,8 @@
|
||||
.master-note-edit {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
background: white;
|
||||
background: var(--background_color);
|
||||
/*color: var(--text_color);*/
|
||||
height: 100vh;
|
||||
box-shadow: 0px 0px 5px 2px rgba(140,140,140,1);
|
||||
}
|
||||
@ -320,4 +334,19 @@
|
||||
right: 50%;
|
||||
}
|
||||
|
||||
.size-down {
|
||||
animation: size-down 0.5s linear both;
|
||||
}
|
||||
|
||||
@keyframes size-down {
|
||||
0% {
|
||||
opacity: 1;
|
||||
top: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
top: 405vh;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
@ -1,7 +1,35 @@
|
||||
<template>
|
||||
<div class="ui clickable segment" @click="onClick(note.id)" :style="{'background-color':color, 'color':fontColor}">
|
||||
<h3>{{note.text}}</h3>
|
||||
<p>Edited: {{$helpers.timeAgo(note.updated)}}</p>
|
||||
<div class="note-title-display-card fade-in-fwd" :style="{'background-color':color, 'color':fontColor}">
|
||||
|
||||
<div class="ui grid max-height">
|
||||
|
||||
<div class="top aligned row">
|
||||
<div class="sixteen wide column overflow-hidden">
|
||||
<h3 @click="onClick(note.id)" class="clickable">{{note.title}}</h3>
|
||||
</div>
|
||||
<div class="sixteen wide column overflow-hidden">
|
||||
<p @click="onClick(note.id)" class="clickable">{{note.subtext}}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bottom aligned row">
|
||||
<div class="ten wide column clickable" @click="onClick(note.id)">Edited: {{$helpers.timeAgo(note.updated)}}</div>
|
||||
|
||||
<div class="six wide right aligned column">
|
||||
<span v-if="note.attachment_count > 0" class>
|
||||
<i class="grey linkify icon"></i> {{note.attachment_count}}
|
||||
</span>
|
||||
<span v-if="note.tag_count == 1" data-tooltip="Note has 1 tag">
|
||||
<i class="grey tags icon"></i> {{note.tag_count}}
|
||||
</span>
|
||||
<span v-if="note.tag_count > 1" :data-tooltip="`Note has ${note.tag_count} tags`">
|
||||
<i class="grey tags icon"></i> {{note.tag_count}}
|
||||
</span>
|
||||
<delete-button :note-id="note.id" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Display highlights from solr results -->
|
||||
<div v-if="note.note_highlights.length > 0" class="term-usage">
|
||||
@ -9,13 +37,14 @@
|
||||
<div class="usage-row" v-for="highlight in note.note_highlights" v-html="highlight"></div>
|
||||
</div>
|
||||
<div v-if="note.attachment_highlights.length > 0" class="term-usage">
|
||||
<p>Note URL Text</p>
|
||||
<p><i class="linkify icon"></i> Note URL Text</p>
|
||||
<div class="usage-row" v-for="highlight in note.attachment_highlights" v-html="highlight"></div>
|
||||
</div>
|
||||
<div v-if="note.tag_highlights.length > 0" class="term-usage">
|
||||
Tag
|
||||
<i class="tags icon"></i> Tag
|
||||
<div class="ui icon large label" v-for="highlight in note.tag_highlights" v-html="highlight"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -24,11 +53,14 @@
|
||||
export default {
|
||||
name: 'NoteTitleDisplayCard',
|
||||
props: [ 'onClick', 'data' ],
|
||||
components: {
|
||||
'delete-button': require('./DeleteButtonComponent.vue').default,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
note: null,
|
||||
color: '#FFF',
|
||||
fontColor: '#000'
|
||||
color: null, //'#FFF',
|
||||
fontColor: null, //'#000'
|
||||
}
|
||||
},
|
||||
beforeMount(){
|
||||
@ -43,6 +75,7 @@
|
||||
}
|
||||
</script>
|
||||
<style type="text/css">
|
||||
|
||||
.term-usage {
|
||||
border: 1px solid #DDD;
|
||||
padding: 10px;
|
||||
@ -57,4 +90,34 @@
|
||||
border-top: 1px solid #DDD;
|
||||
margin: 8px 0 0;
|
||||
}
|
||||
|
||||
.note-title-display-card {
|
||||
position: relative;
|
||||
box-shadow: 0 1px 2px 0 rgba(34,36,38,.15);
|
||||
margin: 0 15px 15px 0;
|
||||
padding: 1em;
|
||||
border-radius: .28571429rem;
|
||||
border: 1px solid;
|
||||
border-color: var(--border_color);
|
||||
width: 31.5%;
|
||||
/*transition: width 0.2s;*/
|
||||
}
|
||||
.one-column .note-title-display-card {
|
||||
margin-right: 65%;
|
||||
width: 18%;
|
||||
}
|
||||
.overflow-hidden {
|
||||
overflow: hidden;
|
||||
word-break: break-all;
|
||||
}
|
||||
.max-height {
|
||||
height: calc(100% + 30px);
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 740px) {
|
||||
.note-title-display-card {
|
||||
width: 100%;
|
||||
margin: 15px 0 0 0;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div id="NotesPage">
|
||||
<div class="ui segment">
|
||||
<div class="ui basic segment">
|
||||
<search-bar />
|
||||
</div>
|
||||
|
||||
|
@ -50,7 +50,7 @@
|
||||
|
||||
<!-- tags display -->
|
||||
<div class="ui two wide large screen only column">
|
||||
<div class="ui basic fluid button" @click="reset">Reset</div>
|
||||
<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)) }">
|
||||
@ -61,7 +61,7 @@
|
||||
<!-- Note title cards -->
|
||||
<div class="ui fourteen wide computer sixteen wide mobile column">
|
||||
<h2>Notes ({{notes.length}})</h2>
|
||||
<div v-if="notes !== null">
|
||||
<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"
|
||||
@ -113,7 +113,9 @@
|
||||
this.$bus.$on('close_active_note', position => {
|
||||
this.closeNote(position)
|
||||
})
|
||||
|
||||
this.$bus.$on('note_deleted', () => {
|
||||
this.search()
|
||||
})
|
||||
|
||||
},
|
||||
mounted() {
|
||||
@ -223,6 +225,7 @@
|
||||
},
|
||||
destroyLoginToken() {
|
||||
this.$store.commit('destroyLoginToken')
|
||||
this.$router.push('/')
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -231,4 +234,8 @@
|
||||
.detail {
|
||||
float: right;
|
||||
}
|
||||
.note-card-display-area {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
</style>
|
@ -9,6 +9,14 @@ import store from './stores/mainStore';
|
||||
import App from './App'
|
||||
import router from './router'
|
||||
|
||||
// This callback runs before every route change, including on page load.
|
||||
// Sets the title of the page using vue router
|
||||
router.beforeEach((to, from, next) => {
|
||||
|
||||
document.title = to.meta.title;
|
||||
next();
|
||||
});
|
||||
|
||||
//Attach event bus to main vue object, all components will inherit event bus
|
||||
import EventBus from './EventBus'
|
||||
import Helpers from './Helpers'
|
||||
|
@ -13,21 +13,25 @@ export default new Router({
|
||||
{
|
||||
path: '/',
|
||||
name: 'HelloWorld',
|
||||
meta: {title:'Home'},
|
||||
component: HelloWorld
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: 'Login',
|
||||
meta: {title:'Login'},
|
||||
component: Login
|
||||
},
|
||||
{
|
||||
path: '/notes',
|
||||
name: 'Notes',
|
||||
meta: {title:'Notes'},
|
||||
component: Notes
|
||||
},
|
||||
{
|
||||
path: '/help',
|
||||
name: 'Help',
|
||||
meta: {title:'Help'},
|
||||
component: HelpPage
|
||||
},
|
||||
]
|
||||
|
@ -16,8 +16,6 @@ export default new Vuex.Store({
|
||||
state.count++
|
||||
},
|
||||
setLoginToken(state, userData){
|
||||
|
||||
console.log(userData)
|
||||
|
||||
const username = userData.username
|
||||
const token = userData.token
|
||||
|
@ -38,7 +38,10 @@ Attachment.scanTextForWebsites = (userId, noteId, noteText) => {
|
||||
|
||||
//Find all URLs in text
|
||||
const urlPattern = /(?:(?:https?|ftp|file):\/\/|www\.|ftp\.)(?:\([-A-Z0-9+&@#/%=~_|$?!:,.]*\)|[-A-Z0-9+&@#/%=~_|$?!:,.])*(?:\([-A-Z0-9+&@#/%=~_|$?!:,.]*\)|[A-Z0-9+&@#/%=~_|$])/igm
|
||||
let foundUrls = noteText.match(urlPattern)
|
||||
let allUrls = noteText.match(urlPattern)
|
||||
|
||||
//Remove all duplicates
|
||||
let foundUrls = [...new Set(allUrls)]
|
||||
|
||||
//Go through each attachment, check for existing URLs
|
||||
attachments.forEach(attachment => {
|
||||
@ -54,7 +57,7 @@ Attachment.scanTextForWebsites = (userId, noteId, noteText) => {
|
||||
})
|
||||
|
||||
//No newly scraped URLs, resolve with looked up attachment text
|
||||
if(foundUrls.length == 0){
|
||||
if(foundUrls == null || foundUrls.length == 0){
|
||||
resolve(solrAttachmentText)
|
||||
}
|
||||
|
||||
@ -166,12 +169,14 @@ Attachment.processUrl = (userId, noteId, url) => {
|
||||
|
||||
let finalWords = []
|
||||
for(let i=0; i<15; i++){
|
||||
if(sortable[i][0]){
|
||||
if(sortable[i] && sortable[i][0]){
|
||||
finalWords.push(sortable[i][0])
|
||||
}
|
||||
}
|
||||
|
||||
desiredSearchText += finalWords.join(', ')
|
||||
console.log('TexT Scraped')
|
||||
console.log(desiredSearchText)
|
||||
|
||||
const created = Math.round((+new Date)/1000)
|
||||
|
||||
|
@ -75,7 +75,20 @@ Notes.update = (userId, noteId, noteText, fancyInput, color) => {
|
||||
|
||||
Notes.delete = (userId, noteId) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
//Create new note, return created or finger your butt
|
||||
// DELETE FROM notes WHERE notes.id = 290 AND notes.user = 61;
|
||||
// DELETE FROM attachment WHERE attachment.note_id = 290 AND attachment.user_id = 61;
|
||||
// DELETE FROM notes_tags WHERE notes_tags.note_id = 290 AND notes_tags.user_id = 61;
|
||||
db.promise().query('DELETE FROM notes WHERE notes.id = ? AND notes.user = ?', [noteId,userId])
|
||||
.then((rows, fields) => {
|
||||
db.promise().query('DELETE FROM attachment WHERE attachment.note_id = ? AND attachment.user_id = ?', [noteId,userId])
|
||||
.then((rows, fields)=> {
|
||||
db.promise().query('DELETE FROM notes_tags WHERE notes_tags.note_id = ? AND notes_tags.user_id = ?', [noteId,userId])
|
||||
.then((rows, fields)=> {
|
||||
console.log('All Deleted')
|
||||
resolve(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@ -153,9 +166,10 @@ Notes.search = (userId, searchQuery, searchTags) => {
|
||||
|
||||
//Default note lookup gets all notes
|
||||
let noteSearchQuery = `
|
||||
SELECT notes.id, SUBSTRING(text, 1, 200) as text, updated, color
|
||||
SELECT notes.id, SUBSTRING(notes.text, 1, 400) as text, updated, color, count(distinct notes_tags.id) as tag_count, count(distinct attachment.id) as attachment_count
|
||||
FROM notes
|
||||
LEFT JOIN notes_tags ON (notes.id = notes_tags.note_id)
|
||||
LEFT JOIN attachment ON (notes.id = attachment.note_id AND attachment.attachment_type = 1)
|
||||
WHERE user = ?`
|
||||
let searchParams = [userId]
|
||||
|
||||
@ -193,16 +207,30 @@ Notes.search = (userId, searchQuery, searchTags) => {
|
||||
noteIds.push(note.id)
|
||||
|
||||
//Attempt to pull string out of first tag in note
|
||||
let reg = note.text.match(/<([\w]+)[^>]*>(.*?)<\/\1>/)
|
||||
if(reg != null){
|
||||
note.text = reg[2]
|
||||
let reg = note.text.match(/<([\w]+)[^>]*>(.*?)<\/\1>/g)
|
||||
|
||||
//Pull out first html tag contents, that is the title
|
||||
if(reg != null && reg[0]){
|
||||
note.title = reg[0] //First line from HTML
|
||||
} else {
|
||||
note.title = note.text //Entire note
|
||||
}
|
||||
|
||||
//Return all notes with HTML tags pulled out
|
||||
note.text = note.text
|
||||
//Clean up html title
|
||||
note.title = note.title
|
||||
.replace(/&[#A-Za-z0-9]+;/g,'') //Rip out all HTML entities
|
||||
.replace(/<[^>]+>/g, '') //Rip out all HTML tags
|
||||
|
||||
//Generate Subtext
|
||||
if(note.text != '' && note.title != ''){
|
||||
note.subtext = note.text
|
||||
.replace(/&[#A-Za-z0-9]+;/g,' ') //Rip out all HTML entities
|
||||
.replace(/<[^>]+>/g, ' ') //Rip out all HTML tags
|
||||
.replace(/\s+/g, ' ') //Remove all whitespace
|
||||
.substring(note.title.length + 2)
|
||||
}
|
||||
|
||||
|
||||
note.note_highlights = []
|
||||
note.attachment_highlights = []
|
||||
note.tag_highlights = []
|
||||
|
@ -24,6 +24,11 @@ router.post('/get', function (req, res) {
|
||||
.then( data => res.send(data) )
|
||||
})
|
||||
|
||||
router.post('/delete', function (req, res) {
|
||||
Notes.delete(userId, req.body.noteId)
|
||||
.then( data => res.send(data) )
|
||||
})
|
||||
|
||||
router.post('/create', function (req, res) {
|
||||
Notes.create(userId, req.body.title)
|
||||
.then( id => res.send({id}) )
|
||||
|
Loading…
Reference in New Issue
Block a user