I swear, I'm going to start doing regular commits
+ Added a ton of shit + About to add socket.io oh god.
This commit is contained in:
@@ -1,110 +0,0 @@
|
||||
<style scoped>
|
||||
.shade {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: rgba(0,0,0,0.7);
|
||||
z-index: 1200;
|
||||
cursor: pointer;
|
||||
}
|
||||
.editor {
|
||||
position: fixed;
|
||||
top: 10%;
|
||||
bottom: 10%;
|
||||
left: 10%;
|
||||
right: 10%;
|
||||
z-index: 1300;
|
||||
overflow-y: scroll;
|
||||
background-color: var(--background_color);
|
||||
border: 3px solid;
|
||||
border-color: var(--border_color);
|
||||
}
|
||||
.attachment-image {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="shade" v-on:click="closeAttachmentEditor"></div>
|
||||
<div class="editor">
|
||||
<div class="ui basic segment">
|
||||
|
||||
<h2>Edit Attachments</h2>
|
||||
|
||||
<div class="ui vertically divided grid">
|
||||
<div v-for="item in attachments" class="row">
|
||||
|
||||
<div class="ui sixteen wide column">
|
||||
<div class="ui form">
|
||||
<div class="field">
|
||||
<textarea v-on:blur="saveIt(item)" v-model="item.text" :key="item.id + 'text'"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ui sixteen wide column">
|
||||
<a v-if="item.url" :href="item.url" target="_blank">{{item.url}}</a>
|
||||
|
||||
<!-- Display image -->
|
||||
<div v-if="item.file_location && item.attachment_type == 2">
|
||||
<img class="attachment-image" :src="`/api/static/${item.file_location}`">
|
||||
</div>
|
||||
|
||||
<!-- provide link -->
|
||||
<a v-if="item.file_location" :href="`/api/static/${item.file_location}`" target="_blank">Download</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
|
||||
name: 'AttachmentEditor',
|
||||
props: [ 'noteId' ],
|
||||
data: function(){
|
||||
return {
|
||||
attachments: []
|
||||
}
|
||||
},
|
||||
beforeCreate: function(){
|
||||
},
|
||||
mounted: function(){
|
||||
|
||||
this.fetchAttachments()
|
||||
},
|
||||
methods: {
|
||||
fetchAttachments(){
|
||||
axios.post('/api/attachment/get', {'noteId':this.noteId})
|
||||
.then(results => {
|
||||
this.attachments = results.data
|
||||
})
|
||||
},
|
||||
closeAttachmentEditor(){
|
||||
this.$bus.$emit('close_edit_attachment')
|
||||
},
|
||||
saveIt(attachment){
|
||||
const data = {
|
||||
'attachmentId': attachment.id,
|
||||
'updatedText': attachment.text,
|
||||
'noteId': this.noteId
|
||||
}
|
||||
axios.post('/api/attachment/update', data)
|
||||
.then(results => {})
|
||||
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
@@ -7,9 +7,12 @@
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<div class="ui clickable basic button">
|
||||
<div class="ui small compact basic icon button clickable">
|
||||
<form>
|
||||
<label :for="`upfile-${noteId}`" class="clickable">File Yeet {{uploadPercentage}}</label>
|
||||
<label :for="`upfile-${noteId}`" class="clickable">
|
||||
<i class="upload icon"></i>
|
||||
Upload File <span v-if="uploadPercentage != 0">{{uploadPercentage}}%</span>
|
||||
</label>
|
||||
<input class="hidden-up" type="file" :id="`upfile-${noteId}`" ref="file" v-on:change="handleFileUpload()" />
|
||||
</form>
|
||||
<!-- <button v-if="file" v-on:click="uploadFileToServer()">Submit</button> -->
|
||||
@@ -47,7 +50,7 @@
|
||||
}
|
||||
}
|
||||
).then(results => {
|
||||
this.uploadPercentage = 'DONE'
|
||||
this.uploadPercentage = 0
|
||||
this.file = null
|
||||
console.log('SUCCESS!!');
|
||||
|
||||
@@ -76,7 +79,7 @@
|
||||
|
||||
})
|
||||
.catch(results => {
|
||||
this.uploadPercentage = 'FAIL'
|
||||
this.uploadPercentage = 0
|
||||
console.log('FAILURE!!');
|
||||
})
|
||||
},
|
||||
|
@@ -21,10 +21,10 @@
|
||||
|
||||
.menu-item {
|
||||
color: #fff;
|
||||
padding: 10px 0px 10px 10px;
|
||||
padding: 0.8em 0px 0.8em 0.8em;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
font-size: 1.1rem;
|
||||
font-size: 1.15em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.sub {
|
||||
@@ -60,28 +60,60 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
.top-menu-bar {
|
||||
color: var(--text_color);
|
||||
width: calc(100% - 20px);
|
||||
/*color: var(--text_color);*/
|
||||
/*width: 100%;*/
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 999;
|
||||
background-color: var(--background_color);
|
||||
border-bottom: 1px solid;
|
||||
border-color: var(--border_color);
|
||||
padding: 5px 1rem 5px;
|
||||
}
|
||||
.place-holder {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
}
|
||||
.top-menu-bar img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
|
||||
<div class="place-holder" v-if="collapsed && !menuOpen"></div>
|
||||
|
||||
<!-- collapsed menu, appears as a bar -->
|
||||
<div class="top-menu-bar menu-item" v-if="collapsed || mobile" v-on:click="collapseMenu">
|
||||
<div class="top-menu-bar" v-if="(collapsed || mobile) && !menuOpen">
|
||||
<div class="ui grid">
|
||||
<div class="five wide column">
|
||||
<i class="bars icon"></i> Menu
|
||||
|
||||
<div class="three wide column">
|
||||
<div class="ui large basic compact icon button" v-on:click="collapseMenu">
|
||||
<i class="green bars icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="six wide center aligned column">
|
||||
<img src="/api/static/assets/favicon.ico" alt="logo" />
|
||||
<div class="ten wide center aligned column">
|
||||
<img v-if="!loggedIn" src="/api/static/assets/favicon.ico" alt="logo" />
|
||||
<search-input v-if="loggedIn"></search-input>
|
||||
</div>
|
||||
<div class="three wide right aligned column">
|
||||
|
||||
<!-- mobile create note button -->
|
||||
<div v-if="loggedIn">
|
||||
<div v-if="!disableNewNote" @click="createNote" class="ui large basic compact icon button">
|
||||
<i class="green plus icon"></i>
|
||||
</div>
|
||||
<div v-if="disableNewNote" class="ui large basic compact icon button">
|
||||
<i class="grey plus icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="five wide right aligned column"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -94,7 +126,7 @@
|
||||
|
||||
<div class="menu-section">
|
||||
<div class="menu-item menu-button" v-on:click="collapseMenu">
|
||||
<i class="caret square left icon"></i>
|
||||
<i class="caret square left outline icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -108,7 +140,7 @@
|
||||
</div>
|
||||
|
||||
<div class="menu-section" v-if="loggedIn">
|
||||
<router-link exact-active-class="active" class="menu-item menu-button" to="/notes">
|
||||
<router-link exact-active-class="active" class="menu-item menu-button" to="/notes" v-on:click.native="emitReloadEvent()">
|
||||
<i class="file icon"></i>Notes
|
||||
</router-link>
|
||||
<div>
|
||||
@@ -168,13 +200,16 @@
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
|
||||
components: {
|
||||
'search-input': require('@/components/SearchInput.vue').default,
|
||||
},
|
||||
data: function(){
|
||||
return {
|
||||
username: '',
|
||||
collapsed: false,
|
||||
mobile: false,
|
||||
disableNewNote: false
|
||||
disableNewNote: false,
|
||||
menuOpen: true,
|
||||
}
|
||||
},
|
||||
beforeCreate: function(){
|
||||
@@ -182,6 +217,10 @@
|
||||
mounted: function(){
|
||||
this.mobile = this.$store.getters.getIsUserOnMobile
|
||||
this.collapsed = this.$store.getters.getIsUserOnMobile
|
||||
|
||||
if(this.mobile){
|
||||
this.menuOpen = false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
loggedIn () {
|
||||
@@ -194,10 +233,18 @@
|
||||
//Collapse menu when item is clicked in mobile
|
||||
if(this.mobile && !this.collapsed){
|
||||
this.collapsed = true
|
||||
this.menuOpen = false
|
||||
}
|
||||
},
|
||||
collapseMenu(){
|
||||
this.collapsed = !this.collapsed
|
||||
|
||||
if(!this.collapsed){
|
||||
this.menuOpen = true
|
||||
} else {
|
||||
this.menuOpen = false
|
||||
}
|
||||
|
||||
},
|
||||
createNote(event){
|
||||
const title = ''
|
||||
@@ -227,6 +274,10 @@
|
||||
return $1.toUpperCase()
|
||||
})
|
||||
},
|
||||
emitReloadEvent(){
|
||||
//Reloads note page to initial state
|
||||
this.$bus.$emit('note_reload')
|
||||
},
|
||||
updateFastFilters(index){
|
||||
|
||||
//A little hacky, brings user to notes page then filters on click
|
||||
|
@@ -3,7 +3,7 @@
|
||||
<span class="clickable" @click="confirmDelete()" v-if="click == 0" data-tooltip="Delete" data-inverted="" data-position="top right">
|
||||
<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" data-inverted="">
|
||||
<span class="clickable" @click="actuallyDelete()" @mouseleave="reset" v-if="click == 1" data-tooltip="Click again to delete." data-position="top right" data-inverted="">
|
||||
<i class="red trash alternate icon"></i>
|
||||
</span>
|
||||
</span>
|
||||
@@ -26,9 +26,11 @@
|
||||
this.click++
|
||||
},
|
||||
actuallyDelete(){
|
||||
|
||||
axios.post('/api/note/delete', {'noteId':this.noteId}).then(response => {
|
||||
if(response.data == true){
|
||||
this.$bus.$emit('note_deleted')
|
||||
console.log('Lets delete this note!')
|
||||
this.$bus.$emit('note_deleted', this.noteId)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
@@ -15,40 +15,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Menu -->
|
||||
<div class="note-top-menu">
|
||||
<div @click="close" class="ui basic icon button" data-tooltip="Close" data-position="right center" data-inverted="">
|
||||
<i class="close icon"></i>
|
||||
</div>
|
||||
<span class="note-status-indicator" v-on:click="save()">{{statusText}}</span>
|
||||
|
||||
<div @click="onTogglePinned" class="ui basic icon button" data-tooltip="Pin to Top" data-position="right center" data-inverted="">
|
||||
<i class="pin icon" :class="{green:(pinned == 1)}"></i> {{(pinned == 1)?'Pinned':''}}
|
||||
</div>
|
||||
<div @click="onToggleArchived" class="ui basic icon button" data-tooltip="Hide on main" data-position="right center" data-inverted="">
|
||||
<i class="archive icon" :class="{green:(archived == 1)}"></i> {{(archived == 1)?'Archived':''}}
|
||||
</div>
|
||||
|
||||
<!-- <file-upload-button :noteId="noteid" /> -->
|
||||
|
||||
<span class="relative" v-on:click="showColorPicker">
|
||||
<span class="ui basic icon button">
|
||||
<i class="paint brush icon"></i>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<div v-if="attachmentCount > 0" class="ui basic icon button" v-on:click="openEditAttachment" data-tooltip="View Links/Images" data-position="right center" data-inverted="">
|
||||
<i class="folder icon"></i>
|
||||
</div>
|
||||
|
||||
<span class="note-status-indicator">{{statusText}}</span>
|
||||
<div class="tinymce-container">
|
||||
<textarea :id="noteid+'-tinymce-editor'">{{noteText}}</textarea>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<textarea :id="noteid+'-tinymce-editor'">{{noteText}}</textarea>
|
||||
|
||||
<note-tag-edit v-if="!$store.getters.getIsUserOnMobile" :noteId="noteid" :key="'tags-for-note-'+noteid"/>
|
||||
|
||||
<color-picker
|
||||
v-if="colorPickerVisible"
|
||||
:location="colorPickerLocation"
|
||||
@@ -56,7 +28,51 @@
|
||||
:style-object="styleObject"
|
||||
/>
|
||||
|
||||
<div v-if="$store.getters.getIsNoteSettingsOpen">
|
||||
|
||||
<div class="all-settings">
|
||||
<div class="ui grid">
|
||||
<div class="row">
|
||||
<div class="sixteen wide column">
|
||||
|
||||
<note-tag-edit :noteId="noteid" :key="'tags-for-note-'+noteid"/><br>
|
||||
|
||||
<!-- close button -->
|
||||
<div class="ui small compact basic icon button" v-on:click="$store.commit('toggleNoteSettingsPane')">
|
||||
<i class="close icon"></i> Close Settings
|
||||
</div>
|
||||
<!-- Pin Button -->
|
||||
<div @click="onToggleArchived" class="ui small compact basic icon button">
|
||||
<i class="archive icon" :class="{green:(archived == 1)}"></i>
|
||||
{{(archived == 1)?'Archived':'Archive'}}
|
||||
</div>
|
||||
<!-- archive button -->
|
||||
<div @click="onTogglePinned" class="ui small compact basic icon button">
|
||||
<i class="pin icon" :class="{green:(pinned == 1)}"></i>
|
||||
{{(pinned == 1)?'Pinned':'Pin'}}
|
||||
</div>
|
||||
<!-- colors button -->
|
||||
<span class="relative" v-on:click="showColorPicker">
|
||||
<span class="ui small compact basic icon button">
|
||||
<i class="paint brush icon"></i>
|
||||
Colors
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<!-- attachment button -->
|
||||
<div v-if="attachmentCount > 0" class="ui small compact basic icon button" v-on:click="openEditAttachment">
|
||||
<i class="folder icon"></i> Attachments
|
||||
</div>
|
||||
<!-- file upload button -->
|
||||
<file-upload-button :noteId="noteid" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="shade" v-on:click="showAllSettings = false"></div> -->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
@@ -72,6 +88,7 @@
|
||||
'note-tag-edit': require('@/components/NoteTagEdit.vue').default,
|
||||
'color-picker': require('@/components/ColorPicker.vue').default,
|
||||
'file-upload-button': require('@/components/FileUploadButton.vue').default,
|
||||
'delete-button': require('@/components/NoteDeleteButtonComponent.vue').default,
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
@@ -95,6 +112,10 @@
|
||||
colorPickerLocation: null,
|
||||
|
||||
tinymce: null, //Initialized editor instance
|
||||
|
||||
//Settings vars
|
||||
showAllSettings: true,
|
||||
lastVisibilityState: null,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -114,10 +135,21 @@
|
||||
}
|
||||
},
|
||||
beforeMount(){
|
||||
|
||||
//Load tinymce into the page only do it once
|
||||
if(document.querySelectorAll('[data-mceload]').length == 0){
|
||||
let tinyMceIncluder = document.createElement('script')
|
||||
tinyMceIncluder.setAttribute('src', '/api/static/assets/tinymce/tinymce.min.js')
|
||||
tinyMceIncluder.setAttribute('data-mceload','loaded')
|
||||
document.head.appendChild(tinyMceIncluder)
|
||||
}
|
||||
},
|
||||
beforeDestroy(){
|
||||
this.$bus.$off('toggle_night_mode', this.listener)
|
||||
|
||||
document.removeEventListener('visibilitychange', this.visibiltyChangeAction)
|
||||
|
||||
this.$off() // Remove all event listeners
|
||||
this.$bus.$off()
|
||||
|
||||
//Trash editor instance on close
|
||||
this.tinymce.remove()
|
||||
|
||||
@@ -127,6 +159,8 @@
|
||||
//Change TinyMce styles on nightmored change
|
||||
this.$bus.$on('toggle_night_mode', this.setEditorTextColor )
|
||||
|
||||
document.addEventListener('visibilitychange', this.checkForUpdatedNote)
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.loadNote(this.noteid)
|
||||
})
|
||||
@@ -139,10 +173,17 @@
|
||||
// {title: 'My image 2', value: 'http://www.moxiecode.com/my2.gif'}
|
||||
// ]
|
||||
|
||||
//Default plugin options for big browsers
|
||||
let toolbarOptions = 'customCloseButton | mceTogglePinned | forecolor styleselect | bold italic underline | link | bullist numlist | outdent indent table | h | image'
|
||||
let pluginOptions = 'paste, link, code, lists, table, hr, image'
|
||||
|
||||
//Tweak doc height for mobile
|
||||
let docHeight = 'calc(100vh - 90px)'
|
||||
let docHeight = 'calc(100vh - 1px)'
|
||||
if(this.$store.getters.getIsUserOnMobile){
|
||||
docHeight = 'calc(100vh - 37px)'
|
||||
docHeight = 'calc(100vh - 1px)'
|
||||
|
||||
toolbarOptions = 'customCloseButton | bullist numlist | mceTogglePinned'
|
||||
pluginOptions = 'lists'
|
||||
}
|
||||
|
||||
//setup skin as dark if night mode is enabled
|
||||
@@ -152,12 +193,13 @@
|
||||
}
|
||||
|
||||
const editorId = '#'+this.noteid+'-tinymce-editor'
|
||||
let vm = this
|
||||
|
||||
//Globally defined included in index HTML
|
||||
tinymce.init({
|
||||
selector: editorId,
|
||||
toolbar: 'forecolor backcolor styleselect | bold italic underline | link image | code | undo redo | bullist numlist | outdent indent table, hr, searchreplace | removeformat',
|
||||
plugins: 'paste, link, code, lists, table, hr, searchreplace, image',
|
||||
toolbar: toolbarOptions,
|
||||
plugins: pluginOptions,
|
||||
browser_spellcheck: true,
|
||||
menubar: false,
|
||||
branding: false,
|
||||
@@ -167,6 +209,25 @@
|
||||
contextmenu: false,
|
||||
init_instance_callback: this.editorInitCallback,
|
||||
imagetools_toolbar: "imageoptions",
|
||||
setup: editor => {
|
||||
//Add custom buttons to tinymce instance
|
||||
editor.ui.registry.addButton('customCloseButton', {
|
||||
text: 'Close',
|
||||
icon: 'close',
|
||||
onAction: function (_) {
|
||||
vm.close()
|
||||
}
|
||||
})
|
||||
|
||||
//Add custom buttons to tinymce instance
|
||||
editor.ui.registry.addButton('mceTogglePinned', {
|
||||
text: 'Note Settings',
|
||||
icon: 'settings',
|
||||
onAction: function (_) {
|
||||
vm.$store.commit('toggleNoteSettingsPane')
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
editorInitCallback(editor){
|
||||
@@ -197,7 +258,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
setText(inText){
|
||||
return this.tinymce.setContent(inText)
|
||||
},
|
||||
getText(){
|
||||
//Return text from tinyMce Editor
|
||||
@@ -208,7 +271,6 @@
|
||||
this.colorPickerLocation = {'x':event.clientX, 'y':event.clientY}
|
||||
},
|
||||
openEditAttachment(){
|
||||
// this.$bus.$emit('open_edit_attachment', this.currentNoteId)
|
||||
this.$router.push('/attachments/note/'+this.currentNoteId)
|
||||
},
|
||||
onTogglePinned(){
|
||||
@@ -300,11 +362,12 @@
|
||||
save(){
|
||||
return new Promise((resolve, reject) => {
|
||||
//Clear other debounced events to prevent double calling of save
|
||||
clearTimeout(this.editDebounce)
|
||||
// clearTimeout(this.editDebounce)
|
||||
|
||||
//Don't save note if its hash doesn't change
|
||||
const currentNoteText = this.getText()
|
||||
if( this.lastNoteHash == this.hashString( currentNoteText )){
|
||||
this.statusText = 'Saved'
|
||||
return resolve(true)
|
||||
}
|
||||
|
||||
@@ -341,6 +404,34 @@
|
||||
})
|
||||
|
||||
},
|
||||
checkForUpdatedNote(){
|
||||
|
||||
//If user leaves page then returns to page, reload the first batch
|
||||
if(this.lastVisibilityState == 'hidden' && document.visibilityState == 'visible'){
|
||||
console.log('Checking for changes is note data')
|
||||
const postData = {
|
||||
noteId:this.currentNoteId,
|
||||
text:this.getText(),
|
||||
updated: this.updated
|
||||
}
|
||||
|
||||
axios.post('/api/note/difftext', postData)
|
||||
.then( ({data}) => {
|
||||
|
||||
//Don't do anything if nothing has changed
|
||||
if(data == ''){ return }
|
||||
|
||||
if(data.diffs > 0){
|
||||
//Update text and last updated time for note
|
||||
this.setText(data.updatedText)
|
||||
this.updated = data.updated
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//Track visibility state
|
||||
this.lastVisibilityState = document.visibilityState
|
||||
},
|
||||
hashString(text){
|
||||
|
||||
var hash = 0;
|
||||
@@ -369,7 +460,7 @@
|
||||
this.sizeDown = true
|
||||
//This timeout allows animation to play before closing
|
||||
setTimeout(() => {
|
||||
this.$bus.$emit('close_active_note', this.position)
|
||||
this.$bus.$emit('close_active_note', {position: this.position, noteId: this.noteid})
|
||||
return
|
||||
}, 300)
|
||||
})
|
||||
@@ -381,6 +472,28 @@
|
||||
|
||||
<style type="text/css" scoped>
|
||||
|
||||
/*Settings manager styles */
|
||||
.all-settings {
|
||||
position: absolute;
|
||||
bottom: -5px;
|
||||
right: 10px;
|
||||
left: 10px;
|
||||
z-index: 99;
|
||||
border: 1px solid;
|
||||
background-color: var(--background_color);
|
||||
border-color: var(--border_color);
|
||||
box-sizing: border-box;
|
||||
border-radius: 7px;
|
||||
box-shadow: 0px 3px 7px 0px rgba(140,140,140,1);
|
||||
padding: 1em;
|
||||
}
|
||||
/*End Settings manager styles */
|
||||
|
||||
.tinymce-container {
|
||||
/* Uncomment this to see the */
|
||||
/*border-bottom: 2px solid green !important;*/
|
||||
}
|
||||
|
||||
.note-top-menu {
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
|
@@ -1,8 +1,9 @@
|
||||
<template>
|
||||
<div v-on:mouseover="fullTagEdit = true">
|
||||
<div v-on:click="fullTagEdit = true">
|
||||
|
||||
<!-- simple string view -->
|
||||
<div v-if="!fullTagEdit" class="ui basic segment">
|
||||
<!-- class="ui basic segment" -->
|
||||
<div v-if="!fullTagEdit">
|
||||
<div class="simple-tag-display">
|
||||
|
||||
<!-- Show Loading -->
|
||||
@@ -10,11 +11,11 @@
|
||||
|
||||
<!-- Default count -->
|
||||
<span v-if="loaded">
|
||||
<i class="tags icon"></i> <b>{{tags.length}} Tags</b>
|
||||
<i class="tags icon"></i> <b>{{tags.length}} Tag<span v-if="tags.length > 1">s</span></b>
|
||||
</span>
|
||||
|
||||
<!-- No tags default text -->
|
||||
<span v-if="tags.length == 0 && loaded" class="ui small compact green button">
|
||||
<span v-if="tags.length == 0 && loaded" class="ui small compact basic green button">
|
||||
<i class="plus icon"></i> Add a tag
|
||||
</span>
|
||||
|
||||
@@ -28,6 +29,13 @@
|
||||
<!-- hover over view -->
|
||||
<div v-if="fullTagEdit" class="full-tag-area fade-in-fwd" v-on:mouseleave="fullTagEdit = false; clearSuggestions()">
|
||||
|
||||
<!-- existing tags -->
|
||||
<div class="delete-tag-display" v-if="tags.length > 0">
|
||||
<div class="ui icon large label" v-for="tag in tags" :class="{ 'green':(newTagInput == tag.text) }">
|
||||
{{ucWords(tag.text)}} <i class="delete icon" v-on:click="removeTag(tag.id)"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- tag input and suggestion popup -->
|
||||
<div class="ui form">
|
||||
<input
|
||||
@@ -45,13 +53,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- existing tags -->
|
||||
<div class="delete-tag-display" v-if="tags.length > 0">
|
||||
<div class="ui icon large label" v-for="tag in tags" :class="{ 'green':(newTagInput == tag.text) }">
|
||||
{{ucWords(tag.text)}} <i class="delete icon" v-on:click="removeTag(tag.id)"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -233,28 +234,27 @@
|
||||
|
||||
/* note tag edit area */
|
||||
.full-tag-area {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
color: var(--text_color);
|
||||
background-color: var(--background_color);
|
||||
padding: 15px;
|
||||
border: 1px solid;
|
||||
/*padding: 15px;*/
|
||||
/*border: 1px solid;*/
|
||||
border-color: var(--border_color);
|
||||
}
|
||||
.full-tag-area .delete-tag-display {
|
||||
margin-top: 15px;
|
||||
/*margin-top: 15px;*/
|
||||
}
|
||||
.full-tag-area .ui.label {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.simple-tag-display {
|
||||
width: 100%;
|
||||
width: calc(100% - 0px);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-height: 35px;
|
||||
color: var(--text_color);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* tag suggestion box styles */
|
||||
@@ -269,8 +269,8 @@
|
||||
height: 40px;
|
||||
padding: 10px 15px;
|
||||
cursor: pointer;
|
||||
background: white;
|
||||
color: black;
|
||||
background-color: var(--background_color);
|
||||
color: var(--text_color);
|
||||
}
|
||||
.suggestion-item.active {
|
||||
background: green;
|
||||
|
@@ -11,33 +11,45 @@
|
||||
<div class="ui grid max-height">
|
||||
|
||||
<!-- Show title and snippet below it -->
|
||||
<div class="top aligned row" @click.stop="onClick(note.id)">
|
||||
<div class="top aligned row" @click.self="onClick(note.id)">
|
||||
|
||||
<div class="sixteen wide column overflow-hidden" @click="e => onClick(note.id, e)">
|
||||
|
||||
<!-- Title display -->
|
||||
<div v-if="note.title.length > 0"
|
||||
data-test-id="title"
|
||||
:class="{ 'big-text':(note.titleLength <= 100), 'small-text-title':(note.titleLength >= 100) }"
|
||||
v-html="note.title"></div>
|
||||
|
||||
<!-- Sub text display -->
|
||||
<div v-if="note.subtext.length > 0 && !isShowingSearchResults()"
|
||||
data-test-id="subtext"
|
||||
:class="{ 'big-text':(note.subtextLength <= 100 && note.titleLength <= 100), 'small-text':(note.subtextLength >= 100) }"
|
||||
v-html="note.subtext"></div>
|
||||
|
||||
<div class="sixteen wide column overflow-hidden">
|
||||
<h3 class="clickable">{{note.title}}</h3>
|
||||
<p v-if="!isShowingSearchResults()" class="clickable">{{note.subtext}}</p>
|
||||
<!-- Display highlights from solr results -->
|
||||
<div v-if="note.note_highlights.length > 0 && textResults" class="term-usage">
|
||||
<div class="usage-row" v-for="highlight in note.note_highlights" v-html="cleanHighlight(highlight)"></div>
|
||||
<div
|
||||
class="usage-row"
|
||||
v-for="highlight in note.note_highlights"
|
||||
:class="{ 'big-text':(highlight <= 100), 'small-text-title':(highlight >= 100) }"
|
||||
v-html="cleanHighlight(highlight)"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- <div class="sixteen wide column overflow-hidden" v-if="isShowingSearchResults()">
|
||||
|
||||
</div> -->
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Toolbar on the bottom -->
|
||||
<div class="bottom aligned row icon-bar" @click.self.stop="onClick(note.id)">
|
||||
<div class="six wide column clickable" @click.stop="onClick(note.id)">
|
||||
<div class="bottom aligned row icon-bar" @click.self="onClick(note.id)">
|
||||
<div class="six wide column clickable" @click="onClick(note.id)">
|
||||
{{$helpers.timeAgo(note.updated)}}
|
||||
<!-- {{(note.chars.toLocaleString())}} -->
|
||||
</div>
|
||||
|
||||
<div class="ten wide right aligned column split-spans">
|
||||
<div class="ten wide right aligned column">
|
||||
|
||||
<delete-button class="hover-hide" :note-id="note.id" />
|
||||
<!-- ALways show delete button on mobile -->
|
||||
<delete-button :class="{ 'hover-hide':(!$store.getters.getIsUserOnMobile) }" :note-id="note.id" />
|
||||
|
||||
<span v-if="note.pinned == 1" data-position="top right" data-tooltip="Pinned" data-inverted="">
|
||||
<i class="green pin icon"></i>
|
||||
@@ -45,7 +57,7 @@
|
||||
<span v-if="note.archived == 1" data-position="top right" data-tooltip="Archived" data-inverted="">
|
||||
<i class="green archive icon"></i>
|
||||
</span>
|
||||
<span v-if="note.attachment_count > 0" v-on:click.stop="openEditAttachment">
|
||||
<span v-if="note.attachment_count > 0" v-on:click.stop="openEditAttachment" class="clickable">
|
||||
<i class="linkify icon"></i> {{note.attachment_count}}
|
||||
</span>
|
||||
<span v-if="note.tag_count == 1" data-position="top right" data-tooltip="Note has 1 tag" data-inverted="">
|
||||
@@ -88,7 +100,6 @@
|
||||
},
|
||||
openEditAttachment(){
|
||||
this.$router.push('/attachments/note/'+this.note.id)
|
||||
// this.$bus.$emit('open_edit_attachment', this.note.id)
|
||||
},
|
||||
},
|
||||
data () {
|
||||
@@ -132,6 +143,20 @@
|
||||
</script>
|
||||
<style type="text/css">
|
||||
|
||||
/*Strict font sizes for card display*/
|
||||
.small-text, .small-text > p, .small-text > h1, .small-text > h2 {
|
||||
font-size: 1.0em !important;
|
||||
}
|
||||
.small-text > p, , .small-text > h1, .small-text > h2 {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
.big-text, .big-text > p, .big-text > h1, .big-text > h2 {
|
||||
font-size: 1.3em !important;
|
||||
}
|
||||
.big-text > p, .big-text > h1, .big-text > h2 {
|
||||
margin-bottom: 0.3em;
|
||||
}
|
||||
|
||||
.note-title-display-card h3 {
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
@@ -166,7 +191,7 @@
|
||||
border: 1px solid;
|
||||
border-color: var(--border_color);
|
||||
width: calc(33.333% - 10px);
|
||||
transition: box-shadow 0.3s;
|
||||
/*transition: box-shadow 0.3s;*/
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
|
||||
|
44
client/src/components/SearchInput.vue
Normal file
44
client/src/components/SearchInput.vue
Normal file
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<div class="ui form">
|
||||
<div class="fields">
|
||||
<div class="sixteen wide field">
|
||||
<input v-model="searchTerm" @keyup="searchKeyUp" @:keyup.enter="search" placeholder="Search Notes" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
|
||||
data: function(){
|
||||
return {
|
||||
searchTerm: '',
|
||||
searchTimeout: null,
|
||||
searchDebounceDuration: 300,
|
||||
}
|
||||
},
|
||||
beforeCreate: function(){
|
||||
},
|
||||
mounted: function(){
|
||||
|
||||
//search clear
|
||||
this.$bus.$on('reset_fast_filters', () => {
|
||||
this.searchTerm = ''
|
||||
})
|
||||
|
||||
},
|
||||
methods: {
|
||||
searchKeyUp(){
|
||||
clearTimeout(this.searchTimeout)
|
||||
this.searchTimeout = setTimeout(() => {
|
||||
this.search()
|
||||
}, this.searchDebounceDuration)
|
||||
},
|
||||
search(){
|
||||
this.$bus.$emit('update_search_term', this.searchTerm)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
Reference in New Issue
Block a user