Big Update:

* Menus open and close based on URL, allowing for back button on note menus to close

Minor Updates:
* Made night mode buttons green
* Widend the global menu
* Added a version display
* Made the create note button real big
* Made the creane note button more visible on mobile
* Hide the note button if there are no notes
* Changed quick menu item to "Quick Note"
* Added reload option if version is clicked
* Moved around menu buttons at the bottom of the note
* Moved tags back into the main footer on note
* Disabled hiding of toolbar on mobile when editor focused
* Updated locked note display on main title card
* Put last edit on note display
* Tweaked display styles to be more minimal, added fade-in on hover
* Added solid scribe to all title displays on the site
* Reactivated help page and put some good help on it...decent help
* Increased max upload size for files to 5MB
* Shortened text on title display cards to make them all the same size
This commit is contained in:
Max G 2020-04-10 03:47:15 +00:00
parent 25b2bd237b
commit a3fa4b0f3c
12 changed files with 246 additions and 184 deletions

View File

@ -48,6 +48,9 @@ div.ui.basic.segment.no-fluf-segment {
background-color: #877A61 !important; background-color: #877A61 !important;
border-color: #877A61 !important; border-color: #877A61 !important;
} }
.night-mode .green.button {
background-color: #534428 !important;
}
/* OVERWRITE DEFAULT SEMANTIC STYLES FOR CUSTOM/NIGHT MODES*/ /* OVERWRITE DEFAULT SEMANTIC STYLES FOR CUSTOM/NIGHT MODES*/
body { body {

View File

@ -181,6 +181,7 @@
openNote(){ openNote(){
const noteId = this.item.note_id const noteId = this.item.note_id
this.$router.push('/notes/open/'+noteId) this.$router.push('/notes/open/'+noteId)
this.$bus.$emit('open_note', noteId)
}, },
openEditAttachments(){ openEditAttachments(){
const noteId = this.item.note_id const noteId = this.item.note_id

View File

@ -1,12 +1,12 @@
<style scoped> <style scoped>
.slotholder { .slotholder {
height: 100vh; height: 100vh;
width: 140px; width: 155px;
display: block; display: block;
float: left; float: left;
} }
.global-menu { .global-menu {
width: 140px; width: 155px;
background: #221f2b; background: #221f2b;
margin: 0; margin: 0;
padding: 0; padding: 0;
@ -89,6 +89,17 @@
width: 30px; width: 30px;
height: 30px; height: 30px;
} }
.version-display {
position: absolute;
bottom: 0;
left: -20px;
right: 0;
height: 30px;
padding: 5px 0;
text-align: center;
color: #8c80ae;
cursor: pointer;
}
</style> </style>
@ -130,8 +141,8 @@
<search-input v-if="loggedIn && mobile"></search-input> <search-input v-if="loggedIn && mobile"></search-input>
<!-- mobile create note button --> <!-- mobile create note button -->
<span v-if="loggedIn"> <span v-if="loggedIn">
<span v-if="!disableNewNote" @click="createNote" class="ui large basic compact icon button"> <span v-if="!disableNewNote" @click="createNote" class="ui large green compact icon button">
<i class="green plus icon"></i> <i class="plus icon"></i>
</span> </span>
<span v-if="disableNewNote" class="ui large basic compact icon button"> <span v-if="disableNewNote" class="ui large basic compact icon button">
<i class="grey plus icon"></i> <i class="grey plus icon"></i>
@ -158,14 +169,18 @@
<div class="menu-section" v-if="loggedIn"> <div class="menu-section" v-if="loggedIn">
<div v-if="!disableNewNote" @click="createNote" class="menu-item menu-item menu-button"> <div v-if="!disableNewNote" @click="createNote" class="menu-item menu-item menu-button">
<i class="green plus icon"></i>New Note <div class="ui green button">
<i class="plus icon"></i>New Note
</div>
</div> </div>
<div v-if="disableNewNote" class="menu-item menu-item menu-button"> <div v-if="disableNewNote" class="menu-item menu-item menu-button">
<i class="purple plus icon"></i>Creating <div class="ui basic button">
<i class="plus loading icon"></i>New Note
</div>
</div> </div>
</div> </div>
<div class="menu-section" v-if="loggedIn"> <div class="menu-section" v-if="loggedIn && $store.getters.totals && $store.getters.totals['totalNotes']">
<router-link exact-active-class="active" class="menu-item menu-button" to="/notes" v-on:click.native="emitReloadEvent()"> <router-link exact-active-class="active" class="menu-item menu-button" to="/notes" v-on:click.native="emitReloadEvent()">
<i class="file outline icon"></i>Notes <i class="file outline icon"></i>Notes
<counter class="float-right" number-id="totalNotes" /> <counter class="float-right" number-id="totalNotes" />
@ -174,7 +189,6 @@
<!-- <div class="menu-item sub">Show Only <i class="caret down icon"></i></div> --> <!-- <div class="menu-item sub">Show Only <i class="caret down icon"></i></div> -->
<!-- <div v-on:click="updateFastFilters(0)" class="menu-item menu-button sub"><i class="grey linkify icon"></i>Links</div> --> <!-- <div v-on:click="updateFastFilters(0)" class="menu-item menu-button sub"><i class="grey linkify icon"></i>Links</div> -->
<!-- <div v-on:click="updateFastFilters(1)" class="menu-item menu-button sub"><i class="grey tags icon"></i>Tags</div> --> <!-- <div v-on:click="updateFastFilters(1)" class="menu-item menu-button sub"><i class="grey tags icon"></i>Tags</div> -->
</div> </div>
</div> </div>
@ -187,7 +201,7 @@
<div class="menu-section" v-if="loggedIn"> <div class="menu-section" v-if="loggedIn">
<router-link v-if="loggedIn" exact-active-class="active" class="menu-item menu-button" to="/quick"> <router-link v-if="loggedIn" exact-active-class="active" class="menu-item menu-button" to="/quick">
<i class="paper plane outline icon"></i>Quick <i class="paper plane outline icon"></i>Quick Note
</router-link> </router-link>
</div> </div>
@ -210,15 +224,24 @@
</div> </div>
</div> </div>
<div class="menu-section" v-if="loggedIn" data-tooltip="Click to log out" data-inverted="" data-position="right center"> <div class="menu-section">
<div v-if="loggedIn" v-on:click="destroyLoginToken" class="menu-item menu-button"> <router-link class="menu-item menu-button" exact-active-class="active" to="/help">
<i class="question circle outline icon"></i>Help
</router-link>
</div>
<div class="menu-section" v-if="loggedIn" :data-tooltip="`Logout ${this.$store.getters.getUsername}`" data-inverted="" data-position="right center">
<div v-on:click="destroyLoginToken" class="menu-item menu-button">
<i v-if="userIcon" class="user outline icon"></i>{{ usernameDisplay }} <i v-if="userIcon" class="user outline icon"></i>{{ usernameDisplay }}
</div> </div>
</div> </div>
<div v-on:click="reloadPage" class="version-display">
<i :class="`${getVersionIcon()} icon`"></i> {{ version }}
</div>
<!-- <router-link class="ui basic compact button" exact-active-class="active" to="/help">
<i class="question mark icon"></i>Help
</router-link> -->
</div> </div>
</div> </div>
</template> </template>
@ -234,6 +257,7 @@
}, },
data: function(){ data: function(){
return { return {
version: '1.0.2',
username: '', username: '',
collapsed: false, collapsed: false,
mobile: false, mobile: false,
@ -272,6 +296,10 @@
this.userIcon = false this.userIcon = false
} }
if(name.length > 16){
this.userIcon = false
}
return this.ucWords(name.substring(0, 16)) return this.ucWords(name.substring(0, 16))
}, },
}, },
@ -346,6 +374,15 @@
filter[options[index]] = 1 filter[options[index]] = 1
this.$bus.$emit('update_fast_filters', filter) this.$bus.$emit('update_fast_filters', filter)
},
reloadPage(){
location.reload(true)
},
getVersionIcon(){
const icons = ['cat','crow','dog','dove','dragon','fish','frog','hippo','horse','kiwi bird','otter','spider']
const index = ( parseInt(this.version.replace(/\./g,'')) % (icons.length))
return icons[index]
} }
} }
} }

View File

@ -93,47 +93,41 @@
<!-- bottom stats --> <!-- bottom stats -->
<div class="ui basic segment"> <div class="ui basic segment">
<div class="ui grid reduced-padding"> <div class="ui grid compact">
<div class="four wide column"> <div class="four wide column">
<!-- Tags --> <button class="ui compact basic fluid icon button shrinking" v-if="!isEncrypted"
<button class="ui compact basic fluid button shrinking" v-on:click="showTagSlideMenu = !showTagSlideMenu; modified = true"> v-on:click="$router.push(`/notes/open/${noteid}/menu/passwordprotect`)" data-tooltip="Add Password">
<i class="tags icon"></i> Tags <i class="shield alternate icon"></i>
Protect
</button>
<button class="ui compact basic fluid icon button shrinking" v-if="isEncrypted && isDecrypted" v-on:click="disableEncryption" data-tooltip="Remove Password Protection">
<i class="unlock icon"></i>
Un-protect
</button> </button>
</div> </div>
<div class="four wide column"> <div class="four wide column">
<!-- Archive Button --> <!-- Archive Button -->
<button class="ui compact basic fluid button shrinking" v-on:click="onToggleArchived"> <button class="ui compact basic fluid icon button shrinking" v-on:click="onToggleArchived" :data-tooltip="archived == 1?'Move to main list':'Move to Archive'">
<span v-if="archived == 1"><i class="green archive icon"></i> Archived</span> <span v-if="archived == 1"><i class="green archive icon"></i> Archived</span>
<span v-if="archived != 1"><i class="archive icon"></i> Archive</span> <span v-if="archived != 1"><i class="archive icon"></i> Archive</span>
</button> </button>
</div> </div>
<div class="four wide column"><!-- Pin button --> <div class="four wide column">
<button class="ui compact basic fluid button shrinking" v-on:click="onTogglePinned"> <!-- Pin button -->
<button class="ui compact basic fluid icon button shrinking" v-on:click="onTogglePinned" :data-tooltip="pinned == 1?'Un-pin from top':'Pin to top'">
<span v-if="pinned == 1"><i class="green pin icon"></i> Pinned</span> <span v-if="pinned == 1"><i class="green pin icon"></i> Pinned</span>
<span v-if="pinned != 1"><i class="pin icon"></i> Pin</span> <span v-if="pinned != 1"><i class="pin icon"></i> Pin</span>
</button></div> </button></div>
<div class="four wide column"> <div class="four wide column">
<!-- files button --> <!-- files button -->
<button class="ui compact basic fluid button shrinking" v-on:click="openEditAttachment"> <button class="ui compact basic fluid icon button shrinking" v-on:click="openEditAttachment" data-tooltip="Files on note">
<i class="folder icon"></i> Files <i class="folder icon"></i> Files
</button> </button>
</div> </div>
<!-- <div class="sixteen wide column"></div> --> <div class="one wide column"></div>
<div class="eight wide middle aligned column">
<div class="eight wide column">
<button class="ui basic compact button shrinking" v-if="!isEncrypted" v-on:click="passwordEnterVisible = true">
<i class="shield alternate icon"></i>
Password Protect
</button>
<button class="ui icon basic compact button shrinking" v-if="isEncrypted && isDecrypted" v-on:click="disableEncryption">
<i class="unlock icon"></i>
Remove Password
</button>
</div>
<div class="seven wide right aligned middle aligned column">
<span :data-tooltip="`Created: ${$helpers.timeAgo(created)}`"> <span :data-tooltip="`Created: ${$helpers.timeAgo(created)}`">
Edited: {{ $helpers.timeAgo(updated) }} Edited: {{ $helpers.timeAgo(updated) }}
</span> </span>
@ -151,13 +145,21 @@
</span> </span>
<!-- Note options on the bottom of note --> <!-- Note options on the bottom of note -->
<div class="all-settings" :class="{ 'low-settings':!extraToolbarsVisible }"> <div class="all-settings">
<div class="note-menu shrink-icons-on-mobile"> <div class="note-menu shrink-icons-on-mobile">
<!-- Tags -->
<nm-button
v-on:click.native="$router.push(`/notes/open/${noteid}/menu/tags`)"
icon="tags"
text="Tags"
tip="Tags"
></nm-button>
<!-- colors button --> <!-- colors button -->
<nm-button <nm-button
v-on:click.native="showColorPicker" v-on:click.native="$router.push(`/notes/open/${noteid}/menu/colors`)"
icon="paint brush" icon="paint brush"
text="Color" text="Color"
tip="Note Color" tip="Note Color"
@ -165,7 +167,7 @@
<!-- add images panel --> <!-- add images panel -->
<nm-button <nm-button
v-on:click.native="showFilesSideMenu = !showFilesSideMenu" v-on:click.native="$router.push(`/notes/open/${noteid}/menu/images`)"
icon="image" icon="image"
text="Images" text="Images"
tip="Images" tip="Images"
@ -182,7 +184,7 @@
icon="ellipsis horizontal" icon="ellipsis horizontal"
text="Options" text="Options"
tip="More Options" tip="More Options"
v-on:click.native="showNoteOptions = !showNoteOptions" /> v-on:click.native="$router.push(`/notes/open/${noteid}/menu/options`)" />
</div> </div>
</div> </div>
@ -191,31 +193,31 @@
<!-- Side slide menus for colors, tags, images and other options --> <!-- Side slide menus for colors, tags, images and other options -->
<side-slide-menu v-show="colorPickerVisible" v-on:close="colorPickerVisible = false" name="colors"> <side-slide-menu v-show="colors" v-on:close="colors = false" name="colors">
<color-picker <color-picker
@changeColor="onChangeColor" @changeColor="onChangeColor"
@close="onCloseColorChanger" @close="colors = false"
:style-object="styleObject" :style-object="styleObject"
/> />
</side-slide-menu> </side-slide-menu>
<side-slide-menu v-show="showTagSlideMenu" v-on:close="showTagSlideMenu = false" name="tags" :style-object="styleObject"> <side-slide-menu v-show="tags" v-on:close="tags = false" name="tags" :style-object="styleObject">
<div class="ui basic segment"> <div class="ui basic segment">
<note-tag-edit :noteId="noteid" :key="'tags-for-note-'+noteid"/> <note-tag-edit :noteId="noteid" :key="'tags-for-note-'+noteid"/>
</div> </div>
</side-slide-menu> </side-slide-menu>
<side-slide-menu v-show="showFilesSideMenu" v-on:close="showFilesSideMenu = false" name="images" :style-object="styleObject"> <side-slide-menu v-show="images" v-on:close="images = false" name="images" :style-object="styleObject">
<div class="ui basic segment"> <div class="ui basic segment">
<simple-attachment-note <simple-attachment-note
v-on:close="showFilesSideMenu = false" v-on:close="images = false"
:note-id="noteid" :note-id="noteid"
:squire-editor="editor"> :squire-editor="editor">
</simple-attachment-note> </simple-attachment-note>
</div> </div>
</side-slide-menu> </side-slide-menu>
<side-slide-menu v-show="showNoteOptions" v-on:close="showNoteOptions = false" name="note-options" :style-object="styleObject"> <side-slide-menu v-show="options" v-on:close="options = false" name="note-options" :style-object="styleObject">
<div class="ui basic padded segment"> <div class="ui basic padded segment">
<div class="ui grid"> <div class="ui grid">
<div class="sixteen wide column"> <div class="sixteen wide column">
@ -257,7 +259,7 @@
</div> </div>
</side-slide-menu> </side-slide-menu>
<side-slide-menu v-show="passwordEnterVisible" v-on:close="passwordEnterVisible = false" :fullShadow="true" name="encrypt note"> <side-slide-menu v-show="passwordprotect" v-on:close="passwordprotect = false" :fullShadow="true" name="encrypt note">
<div class="ui basic segment" v-if="isDecrypted && isEncrypted"> <div class="ui basic segment" v-if="isDecrypted && isEncrypted">
<p>Note Decrypted</p> <p>Note Decrypted</p>
<div class="ui green button" v-on:click="lockNote">Lock Note</div> <div class="ui green button" v-on:click="lockNote">Lock Note</div>
@ -319,7 +321,7 @@
export default { export default {
name: 'InputNotes', name: 'InputNotes',
props: [ 'noteid', 'position' ], props: [ 'noteid', 'position', 'openMenu', 'urlData' ],
components:{ components:{
'note-tag-edit': () => import('@/components/NoteTagEdit.vue'), 'note-tag-edit': () => import('@/components/NoteTagEdit.vue'),
'color-picker': () => import('@/components/ColorPicker.vue'), 'color-picker': () => import('@/components/ColorPicker.vue'),
@ -371,11 +373,10 @@
// pastFocusedNode: null, // pastFocusedNode: null,
usersOnNote: 0, usersOnNote: 0,
extraToolbarsVisible: true, tags: false,
showTagSlideMenu: false, colors: false,
colorPickerVisible: false, images: false,
showFilesSideMenu: false, options: false,
showNoteOptions: false,
//Encryption options //Encryption options
passwordHint: '', passwordHint: '',
@ -384,7 +385,7 @@
hashedPass: '', //sha-256 password hash, sends to server for decryption hashedPass: '', //sha-256 password hash, sends to server for decryption
isEncrypted: false, isEncrypted: false,
isDecrypted: false, isDecrypted: false,
passwordEnterVisible: false, passwordprotect: false,
decryptAttempts: 0, decryptAttempts: 0,
lockedOut: false, lockedOut: false,
autoLockTimeout: null, autoLockTimeout: null,
@ -404,6 +405,30 @@
this.currentNoteId = newVal this.currentNoteId = newVal
this.loadNote(this.currentNoteId) this.loadNote(this.currentNoteId)
},
urlData(newVal, oldVal){
//Handle changes in URL to
if(newVal.id == undefined || newVal.id != this.noteid){
this.close()
}
//Reset all note menus on URL change
this.colors = false
this.tags = false
this.passwordprotect = false
this.options = false
this.images = false
//If a menu value is set, open it
if(newVal.openMenu){
//Only modify menu boolean if its defined
if(typeof this[newVal.openMenu] == 'boolean'){
this[newVal.openMenu] = true
}
}
} }
}, },
beforeMount(){ beforeMount(){
@ -518,13 +543,11 @@
//Show and hide additional toolbars //Show and hide additional toolbars
this.editor.addEventListener('focus', e => { this.editor.addEventListener('focus', e => {
if(this.$store.getters.getIsUserOnMobile){ //Add events here if you like
this.extraToolbarsVisible = false
}
}) })
this.editor.addEventListener('blur', e => { this.editor.addEventListener('blur', e => {
this.save() this.save()
this.extraToolbarsVisible = true
}) })
}, },
//If nothing is selected, select the entire line //If nothing is selected, select the entire line
@ -598,7 +621,7 @@
//Close menu if user is on mobile, then sort list //Close menu if user is on mobile, then sort list
if(this.$store.getters.getIsUserOnMobile){ if(this.$store.getters.getIsUserOnMobile){
this.showNoteOptions = false this.options = false
} }
//Fetch the container //Fetch the container
@ -615,7 +638,7 @@
//Close menu if user is on mobile, then sort list //Close menu if user is on mobile, then sort list
if(this.$store.getters.getIsUserOnMobile){ if(this.$store.getters.getIsUserOnMobile){
this.showNoteOptions = false this.options = false
} }
//Fetch the container //Fetch the container
@ -671,7 +694,7 @@
//Close menu if user is on mobile, then sort list //Close menu if user is on mobile, then sort list
if(this.$store.getters.getIsUserOnMobile){ if(this.$store.getters.getIsUserOnMobile){
this.showNoteOptions = false this.options = false
} }
//Fetch the container //Fetch the container
@ -735,7 +758,7 @@
//Close menu if user is on mobile, then sort list //Close menu if user is on mobile, then sort list
if(this.$store.getters.getIsUserOnMobile){ if(this.$store.getters.getIsUserOnMobile){
this.showNoteOptions = false this.options = false
} }
//Fetch the container //Fetch the container
@ -791,11 +814,6 @@
return this.editor.getHTML() return this.editor.getHTML()
}, },
showColorPicker(event){
this.colorPickerVisible = !this.colorPickerVisible
this.colorPickerLocation = {'x':event.clientX, 'y':event.clientY}
},
openEditAttachment(){ openEditAttachment(){
this.$router.push('/attachments/note/'+this.currentNoteId) this.$router.push('/attachments/note/'+this.currentNoteId)
@ -822,10 +840,6 @@
this.lastNoteHash = 0 this.lastNoteHash = 0
this.save() this.save()
}, },
onCloseColorChanger(){
this.colorPickerVisible = false
},
onChangeColor(newStyleObject){ onChangeColor(newStyleObject){
//Set new style object for note, page will use some styles, styles will be saved to database //Set new style object for note, page will use some styles, styles will be saved to database
@ -1136,8 +1150,6 @@
this.updated = Math.round((+new Date)/1000) this.updated = Math.round((+new Date)/1000)
this.modified = true this.modified = true
console.log('Saved')
//Update last saved note hash //Update last saved note hash
this.lastNoteHash = this.hashString( currentNoteText ) this.lastNoteHash = this.hashString( currentNoteText )
this.startAutolockTimer() this.startAutolockTimer()
@ -1198,9 +1210,6 @@
}, },
close(){ close(){
// this.loading = true
// this.loadingMessage = 'Save and Close'
this.save().then( result => { this.save().then( result => {
this.sizeDown = true this.sizeDown = true
@ -1241,7 +1250,7 @@
this.isDecrypted = false this.isDecrypted = false
this.password = '' this.password = ''
this.hashedPass = '' this.hashedPass = ''
this.passwordEnterVisible = false this.passwordprotect = false
this.setText('') this.setText('')
}) })
}, },
@ -1258,7 +1267,7 @@
this.lastNoteHash = 0 this.lastNoteHash = 0
this.password = '' this.password = ''
this.passwordConfirm = '' this.passwordConfirm = ''
this.passwordEnterVisible = false this.passwordprotect = false
this.save() this.save()
.then(results => { .then(results => {
@ -1273,7 +1282,7 @@
this.password = '' this.password = ''
this.passwordConfirm = '' this.passwordConfirm = ''
this.hashedPass = '' this.hashedPass = ''
this.passwordEnterVisible = false this.passwordprotect = false
//Reload Note //Reload Note
this.save() this.save()
@ -1364,14 +1373,6 @@
/*padding: 1.2em 0 0;*/ /*padding: 1.2em 0 0;*/
flex-grow: 0; flex-grow: 0;
} }
.low-settings {
bottom: 0px;
cursor: pointer;
height: 1.4em;
padding-top: 1.5em;
overflow: hidden;
border: 1px solid #534c68;
}
/*End Settings manager styles */ /*End Settings manager styles */

View File

@ -19,13 +19,6 @@
</span> </span>
</span> </span>
<span class="subtext" v-if="note.shared == 2">
You Shared
<span v-if="note.updated > note.opened && !beenClicked" class="ui tiny green compact right floated basic button">
Updated
</span>
</span>
<span v-if="note.title == '' && note.subtext == '' && note.encrypted == 0"> <span v-if="note.title == '' && note.subtext == '' && note.encrypted == 0">
Empty Note Empty Note
</span> </span>
@ -46,10 +39,17 @@
v-html="note.subtext"></span> v-html="note.subtext"></span>
<p v-if="note.encrypted == 1"> <div class="ui fluid basic button" v-if="note.encrypted == 1">
<i class="green lock icon"></i> <i class="green lock icon"></i>
Locked Locked
</p> </div>
<span class="subtext" v-if="note.shared == 2">
You Shared this note
<span v-if="note.updated > note.opened && !beenClicked" class="ui tiny green compact right floated basic button">
Updated
</span>
</span>
<!-- Display highlights from solr results --> <!-- Display highlights from solr results -->
<span v-if="note.note_highlights.length > 0" class="term-usage"> <span v-if="note.note_highlights.length > 0" class="term-usage">
@ -67,7 +67,6 @@
<!-- Toolbar on the bottom --> <!-- Toolbar on the bottom -->
<div class="tool-bar" @click.self="cardClicked"> <div class="tool-bar" @click.self="cardClicked">
<div class="icon-bar"> <div class="icon-bar">
<!-- {{$helpers.timeAgo(note.updated)}} -->
<span v-if="note.pinned == 1" data-position="top left" data-tooltip="Pinned" data-inverted> <span v-if="note.pinned == 1" data-position="top left" data-tooltip="Pinned" data-inverted>
<i class="green pin icon"></i> <i class="green pin icon"></i>
@ -80,7 +79,10 @@
<span v-for="tag in (note.tags.split(','))" class="little-tag">{{ tag }}</span> <span v-for="tag in (note.tags.split(','))" class="little-tag">{{ tag }}</span>
</span> </span>
<!-- :class="{ 'hover-hide':(!$store.getters.getIsUserOnMobile) }" --> <span class="time-ago-display" :class="{ 'hover-hide':(!$store.getters.getIsUserOnMobile) }">
Last Edit {{$helpers.timeAgo(note.updated)}}
</span>
<span class="float-right" :class="{ 'hover-hide':(!$store.getters.getIsUserOnMobile) }"> <span class="float-right" :class="{ 'hover-hide':(!$store.getters.getIsUserOnMobile) }">
<i class="teeny-button" data-tooltip="Tags" data-inverted v-on:click="toggleTags(true)"> <i class="teeny-button" data-tooltip="Tags" data-inverted v-on:click="toggleTags(true)">
@ -100,7 +102,7 @@
<i class="pin icon"></i> <i class="pin icon"></i>
</i> </i>
<delete-button class="teeny-button" :note-id="note.id" /> <delete-button class="teeny-button" :note-id="note.id" />
</span> </span>
</div> </div>
@ -113,7 +115,7 @@
</div> </div>
<side-slide-menu v-if="showTagSlideMenu" v-on:close="toggleTags(false)" :full-shadow="true"> <side-slide-menu v-if="showTagSlideMenu" v-on:close="toggleTags(false)" :full-shadow="true" :skip-history="true">
<div class="ui basic segment"> <div class="ui basic segment">
<note-tag-edit :noteId="note.id" :key="'display-tags-for-note-'+note.id"/> <note-tag-edit :noteId="note.id" :key="'display-tags-for-note-'+note.id"/>
</div> </div>
@ -210,7 +212,7 @@
this.triggerClosedAnimation = true this.triggerClosedAnimation = true
setTimeout(()=>{ setTimeout(()=>{
//After 3 seconds, hide it //After 3 seconds, hide it
this.justClosed = false this.triggerClosedAnimation = false
}, 3000) }, 3000)
}, 500) }, 500)
@ -298,6 +300,11 @@
} }
/*Strict font sizes for card display*/ /*Strict font sizes for card display*/
.small-text {
max-height: 261px;
overflow: hidden;
display: inline-block;
}
.small-text, .small-text > p, .small-text > h1, .small-text > h2 { .small-text, .small-text > p, .small-text > h1, .small-text > h2 {
/*font-size: 1.0em !important;*/ /*font-size: 1.0em !important;*/
font-size: 15px !important; font-size: 15px !important;
@ -342,16 +349,21 @@
.note-title-display-card { .note-title-display-card {
position: relative; position: relative;
/*box-shadow: 0 1px 2px 0 rgba(34,36,38,.15);*/ /*box-shadow: 0 1px 3px 0 rgba(34,36,38,.15);*/
/*box-shadow: 0 0px 5px 1px rgba(34,36,38,0);*/ /*box-shadow: 0 0px 5px 1px rgba(34,36,38,0);*/
box-shadow: 0 1px 2px 0 rgba(34,36,38,.15); /*box-shadow: 0 1px 3px 0 rgba(34,36,38,.15);*/
box-shadow: 0px 1px 2px 1px rgba(210, 211, 211, 0.46);
transition: box-shadow ease 0.3s;
margin: 5px; margin: 5px;
/*padding: 0.7em 1em;*/ /*padding: 0.7em 1em;*/
border-radius: .28571429rem; border-radius: .28571429rem;
border: 1px solid; border: 1px solid transparent;
border-color: var(--border_color); /*border-color: var(--border_color);*/
/*width: calc(33.333% - 10px);*/ /*width: calc(33.333% - 10px);*/
width: calc(25% - 10px); width: calc(25% - 10px);
max-width: 300px;
min-width: 190px;
min-height: 130px;
/*transition: box-shadow 0.3s;*/ /*transition: box-shadow 0.3s;*/
box-sizing: border-box; box-sizing: border-box;
cursor: pointer; cursor: pointer;
@ -360,20 +372,20 @@
letter-spacing: 0.02rem; letter-spacing: 0.02rem;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
text-align: left;
} }
.note-title-display-card:hover { .note-title-display-card:hover {
/*box-shadow: 0 3px 6px -0 rgba(34,36,38,.50);*/ box-shadow: 0px 2px 2px 1px rgba(210, 211, 211, 0.8);
/*box-shadow: 0 0px 5px 1px rgba(34,36,38,0.3);*/
} }
.icon-bar { .icon-bar {
display: inline-block; display: inline-block;
padding: 0 10px 0; padding: 0 10px 0;
opacity: 1; opacity: 1;
width: 100%; width: 100%;
/*margin-top: -2.2rem;*/
} }
.hover-hide { .hover-hide {
opacity: 0.0; opacity: 0.0;
transition: opacity ease 0.6s;
} }
.little-tag { .little-tag {
font-size: 0.7em; font-size: 0.7em;
@ -428,12 +440,16 @@
align-self: flex-end; align-self: flex-end;
flex-grow: 0; flex-grow: 0;
} }
.time-ago-display {
display: inline-block;
width: 100%;
text-align: right;
}
.one-column .note-title-display-card { .one-column .note-title-display-card {
/*margin-right: 65%;*/
/*width: 33%;*/
width: 100%; width: 100%;
max-width: none;
} }
.overflow-hidden { .overflow-hidden {
overflow: hidden; overflow: hidden;
@ -472,6 +488,7 @@
.note-title-display-card { .note-title-display-card {
width: calc(100% + 10px); width: calc(100% + 10px);
margin: 0px -5px 10px -5px; margin: 0px -5px 10px -5px;
max-width: none;
} }
} }
@ -484,18 +501,18 @@
linear-gradient(to right, #21BA45 50%, #21BA45 100%), /* BottomLeft to Right*/ linear-gradient(to right, #21BA45 50%, #21BA45 100%), /* BottomLeft to Right*/
linear-gradient(to bottom, #21BA45 50%, #21BA45 100%); /* TopLeft to Bottom */ linear-gradient(to bottom, #21BA45 50%, #21BA45 100%); /* TopLeft to Bottom */
/*Initial state, no BG*/ /*Initial state, no BG*/
background-size: 0 2px, 2px 0, 0 2px, 2px 0; background-size: 0 3px, 3px 0, 0 3px, 3px 0;
} }
15% { 15% {
/*Middre state, some filled */ /*Middre state, some filled */
background-size: 100% 2px, 2px 0, 100% 2px, 2px 0; background-size: 100% 3px, 3px 0, 100% 3px, 3px 0;
} }
30% { 30% {
/*final state, all filled */ /*final state, all filled */
background-size: 100% 2px, 2px 100%, 100% 2px, 2px 100%; background-size: 100% 3px, 3px 100%, 100% 3px, 3px 100%;
} }
45% { 45% {
background-size: 100% 2px, 2px 100%, 100% 2px, 2px 100%; background-size: 100% 3px, 3px 100%, 100% 3px, 3px 100%;
background-image: background-image:
linear-gradient(to right, #21BA45 50%, #21BA45 100%), /* TopLeft to Right */ linear-gradient(to right, #21BA45 50%, #21BA45 100%), /* TopLeft to Right */
linear-gradient(to bottom, #21BA45 50%, #21BA45 100%), /* TopRight to Bottom */ linear-gradient(to bottom, #21BA45 50%, #21BA45 100%), /* TopRight to Bottom */

View File

@ -109,7 +109,7 @@
<script> <script>
export default { export default {
name: 'SideSlideMenu', name: 'SideSlideMenu',
props: [ 'name', 'styleObject', 'fullShadow' ], props: [ 'name', 'styleObject', 'fullShadow', 'skipHistory' ],
components: { components: {
'nm-button':require('@/components/NoteMenuButtonComponent.vue').default 'nm-button':require('@/components/NoteMenuButtonComponent.vue').default
}, },
@ -145,15 +145,16 @@
//Close all other panels that are not this one //Close all other panels that are not this one
this.$nextTick( () => { this.$nextTick( () => {
this.$bus.$emit('destroy_all_other_side_panels', this.name) // this.$bus.$emit('destroy_all_other_side_panels', this.name)
}) })
}, },
methods: { methods: {
onClickTag(index){
console.log('yup')
},
close() { close() {
this.$emit('close'); if(this.skipHistory != true){
this.$router.go(-1)
}
this.$emit('close'); //Close menu via event
}, },
} }
} }

View File

@ -35,7 +35,7 @@ Object.defineProperties(Vue.prototype, {
// This callback runs before every route change, including on page load. // This callback runs before every route change, including on page load.
// Sets the title of the page using vue router // Sets the title of the page using vue router
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
document.title = to.meta.title; document.title = to.meta.title + ' - Solid Scribe';
next(); next();
}); });

View File

@ -1,34 +1,22 @@
<template> <template>
<div class="ui basic segment"> <div class="ui basic segment">
<div class="ui container"> <div class="ui grid">
<div class="sixteen wide column">
<h2 class="ui dividing header">
Help
</h2>
</div>
<div class="sixteen wide column">
<div class="ui text container">
<!-- Content copied from note -->
<!-- https://www.solidscribe.com/#/notes/open/552 -->
<h2>Note Editing - Keyboard Shortcuts</h2> <p><b>Quick Note</b><br></p><p>The Quick note feature was designed to allow rapid input to a single note. Rather than junking up all your notes with random links, numbers or haikus, you can put them all in one place. <br></p><p>All data pushed to the quick note can still be edited like a normal note.<br></p><p><br></p><p><b>Dark Theme</b><br></p><p>Dark theme was designed to minimize the amount of blue. Less blue entering your eyes is supposed to help you fall asleep.<br></p><p>Most things turn sepia and a filter is applied to images to make them more sepia.<br></p><p>Here is some good research on the topic: <a href="https://justgetflux.com/research.html">https://justgetflux.com/research.html</a><br></p><p><br></p><p><b>Password Protected Notes</b><br></p><p>Note protected with a password are encrypted. This means the data is scrambled and unreadable unless the correct password is used to decrypt them.<br></p><p>If a password is forgotten, it can never be recovered. Passwords are not saved for encrypted notes. If you lose the password to a protected note, that note text is lost. <br></p><p>Only the text of the note is protected. Tags, Files attached to the note, and the title of the note are still visible without a password. You can not search text in a password protected note. But you can search by the title.<br></p><p><br></p><p><b>Links in notes</b><br></p><p>Links put into notes are automatically scraped. This means the data from the link will be scanned to get an image and some text from the website to help make that link more accessible in the future. <br></p><p><br></p><p><b>Files in notes</b><br></p><p>Files can be uploaded to notes. If its an image, the picture will be put into the note.<br></p><p>Images added to notes will have the text pulled out so it can be searched (This isn't super accurate so don't rely to heavily on it.) The text can be updated at any time.<br></p><p><br></p><p><b>Deleting notes</b><br></p><p>When notes are deleted, none of the files related to the note are deleted.<br></p>
<p>CTRL + SHIFT + V - paste without formatting</p> <!-- content copied from note -->
<p>CTRL + Z - Undo in note, <b>Undo youtube video player embed.</b></p> </div>
<p>ESC - Close note editor</p> </div>
<h2>Block formatting</h2>
<p>The following block formatting options are available:</p>
<p> Bulleted list Start a line with * or - followed by a space.</p>
<p> Numbered list Start a line with 1. or 1) followed by a space.</p>
<p> Headings Start a line with # or ## or ### followed by a space to create a heading 1, heading 2 or heading 3 (up to heading 6 if options defines more headings).</p>
<p> Block quote Start a line with > followed by a space.</p>
<h2>Inline formatting</h2>
<p>The following inline formatting options are available:<p>
<p>Bold Type **text** or __text__,</p>
<p>Italic Type *text* or _text_,</p>
<p>Code Type `text`.</p>
<h2>Dark Theme</h2>
<p>Dark theme was desigend to minimize the amount of blue the app contains.</p>
<p>Making it easier to fall asleep at night.</p>
</div> </div>
</div> </div>
</template> </template>

View File

@ -6,11 +6,7 @@
<div class="sixteen wide column"> <div class="sixteen wide column">
<!-- :class="{ 'sixteen wide column':showOneColumn(), 'sixteen wide column':!showOneColumn() }" --> <!-- :class="{ 'sixteen wide column':showOneColumn(), 'sixteen wide column':!showOneColumn() }" -->
<div class="ui grid"> <div class="ui stackable grid">
<div class="six wide column" v-if="!$store.getters.getIsUserOnMobile">
<search-input></search-input>
</div>
<div class="ten wide column" :class="{ 'sixteen wide column':$store.getters.getIsUserOnMobile }"> <div class="ten wide column" :class="{ 'sixteen wide column':$store.getters.getIsUserOnMobile }">
@ -36,6 +32,11 @@
</div> </div>
<div class="six wide column" v-if="!$store.getters.getIsUserOnMobile">
<search-input
v-if="$store.getters.totals && $store.getters.totals['totalNotes']" />
</div>
<div class="eight wide column" v-if="showClear"> <div class="eight wide column" v-if="showClear">
<!-- <fast-filters /> --> <!-- <fast-filters /> -->
<span class="ui fluid green button" <span class="ui fluid green button"
@ -49,11 +50,7 @@
</div> </div>
<!-- <div class="one wide column"></div>
<div class="fourteen wide column">
<input-notes :noteid="3153" :position="3" ref="note3" />
</div>
<div class="one wide column"></div> -->
<h2 v-if="fastFilters['withLinks'] == 1">Notes with Links</h2> <h2 v-if="fastFilters['withLinks'] == 1">Notes with Links</h2>
<h2 v-if="fastFilters['withTags'] == 1">Notes with Tags</h2> <h2 v-if="fastFilters['withTags'] == 1">Notes with Tags</h2>
@ -63,7 +60,7 @@
<!-- tags section --> <!-- tags section -->
<div v-if="commonTags.length > 0" class="sixteen wide column"> <div v-if="commonTags.length > 0" class="sixteen wide column">
<h4><i class="green tags icon"></i>Tags</h4> <h4 class="ui tiny dividing header"><i class="green tags icon"></i>Tags</h4>
<span v-for="tag in commonTags" @click="toggleTagFilter(tag.id)"> <span v-for="tag in commonTags" @click="toggleTagFilter(tag.id)">
<span class="ui clickable basic label" :class="{ 'green':(searchTags.includes(tag.id)) }"> <span class="ui clickable basic label" :class="{ 'green':(searchTags.includes(tag.id)) }">
{{ucWords(tag.text)}} <span class="detail">{{tag.usages}}</span> {{ucWords(tag.text)}} <span class="detail">{{tag.usages}}</span>
@ -75,7 +72,9 @@
<div class="sixteen wide column"> <div class="sixteen wide column">
<h3 v-if="$store.getters.totals && $store.getters.totals['totalNotes'] == 0"> <h3 v-if="$store.getters.totals && $store.getters.totals['totalNotes'] == 0">
No Notes Yet. Thats ok. Create one when you feel ready. 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> </h3>
<!-- Go to one wide column, do not do this on mobile interface --> <!-- Go to one wide column, do not do this on mobile interface -->
@ -86,7 +85,7 @@
<!-- render each section based on notes in set --> <!-- render each section based on notes in set -->
<div v-for="section,index in noteSections" v-if="section.length > 0" class="note-card-section"> <div v-for="section,index in noteSections" v-if="section.length > 0" class="note-card-section">
<h4><i :class="`green ${sectionData[index][0]} icon`"></i>{{ sectionData[index][1] }}</h4> <h5 class="ui tiny dividing header"><i :class="`green ${sectionData[index][0]} icon`"></i>{{ sectionData[index][1] }}</h5>
<div class="note-card-display-area"> <div class="note-card-display-area">
<note-title-display-card <note-title-display-card
@ -118,8 +117,17 @@
</div> </div>
<input-notes v-if="activeNoteId1 != null" :noteid="activeNoteId1" :position="activeNote1Position" ref="note1" /> <input-notes
<input-notes v-if="activeNoteId2 != null" :noteid="activeNoteId2" :position="activeNote2Position" ref="note2" /> 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> </div>
</template> </template>
@ -348,7 +356,7 @@
//IF two notes get opened, update ID of open note //IF two notes get opened, update ID of open note
if(this.activeNoteId1 || this.activeNoteId2){ if(this.activeNoteId1 || this.activeNoteId2){
this.$router.push('/notes/open/'+Math.max(this.activeNoteId1,this.activeNoteId2)) this.$router.push('/notes/open/'+Math.max(this.activeNoteId1, this.activeNoteId2))
} else { } else {
//No notes are open, just show notes page //No notes are open, just show notes page
this.$router.push('/notes') this.$router.push('/notes')
@ -411,17 +419,27 @@
let newPath = event.newURL.replace(path,'') let newPath = event.newURL.replace(path,'')
let oldPath = event.oldURL.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 we go from open note ID to no note ID, close the note
if(newPath == '' && oldPath.indexOf('/open/') != -1){ if(newPath == '' && oldPath.indexOf('/open/') != -1){
//Pull note ID out of URL //Pull note ID out of URL
const noteIdToClose = oldPath.split('/').pop() const noteIdToClose = oldPath.split('/').pop()
// console.log(noteIdToClose)
if(this.$refs.note1 && this.$refs.note1.currentNoteId == noteIdToClose){ if(this.$refs.note1 && this.$refs.note1.currentNoteId == noteIdToClose){
this.$refs.note1.close() // this.$refs.note1.close()
} }
if(this.$refs.note2 && this.$refs.note2.currentNoteId == noteIdToClose){ if(this.$refs.note2 && this.$refs.note2.currentNoteId == noteIdToClose){
this.$refs.note2.close() //this.$refs.note2.close()
} }
} }
}, },
@ -633,16 +651,6 @@
}) })
}, },
searchKeyUp(){
let vm = this
clearTimeout(vm.searchDebounce)
vm.searchDebounce = setTimeout(() => {
this.search(true, this.batchSize)
.then( () => {
return this.fetchUserTags()
})
}, 500)
},
ucWords(str){ ucWords(str){
return (str + '') return (str + '')
.replace(/^(.)|\s+(.)/g, function ($1) { .replace(/^(.)|\s+(.)/g, function ($1) {
@ -692,7 +700,7 @@
this.searchTags = [] this.searchTags = []
//A little hacky, brings user to notes page then filters on click //A little hacky, brings user to notes page then filters on click
if(this.$route.name != 'NotesPage'){ if(this.$route.name != 'Note Page'){
this.$router.push('/notes') this.$router.push('/notes')
setTimeout( () => { setTimeout( () => {
this.updateFastFilters(index) this.updateFastFilters(index)

View File

@ -37,15 +37,21 @@ export default new Router({
}, },
{ {
path: '/notes', path: '/notes',
name: 'NotesPage', name: 'Note Page', //don't change this
meta: {title:'Notes'}, meta: {title:'Notes'},
component: NotesPage component: NotesPage
}, },
{ {
path: '/notes/open/:id', path: '/notes/open/:id',
name: 'NotesPage', name: 'Open Note',
meta: {title:'Notes'}, meta: {title: 'Open Note'},
component: NotesPage component: NotesPage,
},
{
path: '/notes/open/:id/menu/:openMenu',
name: 'Open Note Menu',
meta: {title: 'Open Note Menu'},
component: NotesPage,
}, },
{ {
path: '/help', path: '/help',

View File

@ -103,7 +103,7 @@ http.listen(3001, function(){
}); });
//Enable json body parsing in requests. Allows me to post data in ajax calls //Enable json body parsing in requests. Allows me to post data in ajax calls
app.use(express.json({limit: '2mb'})) app.use(express.json({limit: '5mb'}))
//Prefix defied by route in nginx config //Prefix defied by route in nginx config

View File

@ -584,7 +584,7 @@ Note.search = (userId, searchQuery, searchTags, fastFilters) => {
let searchParams = [userId] let searchParams = [userId]
let noteSearchQuery = ` let noteSearchQuery = `
SELECT note.id, SELECT note.id,
SUBSTRING(note_raw_text.text, 1, 500) as text, SUBSTRING(note_raw_text.text, 1, 300) as text,
note_raw_text.title as title, note_raw_text.title as title,
note_raw_text.updated as updated, note_raw_text.updated as updated,
opened, opened,