I need to get back into using git. The hell is wrong with me!?

This commit is contained in:
Max G
2019-12-20 05:50:50 +00:00
parent 7b77bd37f3
commit 8d07a8e11a
135 changed files with 53273 additions and 699 deletions

View File

@@ -1,71 +1,62 @@
<template>
<!-- change class to .master-note-edit to have it popup on the screen -->
<div
id="InputNotes" class="master-note-edit"
id="InputNotes"
class="master-note-edit"
@keyup.esc="close"
:class="[{'size-down':(sizeDown == true)}, 'position-'+position ]"
:style="{'background-color':color, 'color':fontColor}"
:style="{ 'background-color':styleObject['noteBackground'], 'color':styleObject['noteText']}"
>
<!-- Loading indicator -->
<div v-if="loading" class="loading-note">
<div class="ui active dimmer">
<div class="ui text loader">{{loadingMessage}}...</div>
<div class="ui text loader">{{loadingMessage}}</div>
</div>
</div>
<!-- Menu -->
<div class="note-top-menu">
<div @click="close" class="ui button"><i class="green close icon"></i>Close (ESC)</div>
<div @click="onToggleFancyInput" class="ui button">
Fancy ({{fancyInput?'On':'Off'}})
<div @click="close" class="ui basic icon button" data-tooltip="Close" data-position="right center" data-inverted="">
<i class="close icon"></i>
</div>
<div @click="onTogglePinned" class="ui button">
<i class="pin icon" :class="{green:(pinned == 1)}"></i> {{(pinned == 1)?'pinned':'not pinned'}}
<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 button">
<i class="archive icon" :class="{green:(archived == 1)}"></i> {{(archived == 1)?'archived':'not archived'}}
<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>
<span class="relative" v-on:mouseover="showColorPicker = true" v-on:mouseleave="showColorPicker = false">
<span class="ui icon button">
<!-- <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 v-if="showColorPicker" class="color-picker">
<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>
</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>
<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 :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"
@changeColor="onChangeColor"
:style-object="styleObject"
/>
<note-tag-edit :noteId="noteid" :key="'tags-for-note-'+noteid"/>
</div>
</template>
@@ -73,21 +64,14 @@
<script>
import axios from 'axios'
import DecoupledEditor from '@ckeditor/ckeditor5-build-decoupled-document';
//Start working on some plugin, tag plugin, link to other note, interactive checkbox
class InsertImage extends Plugin {
init() {
console.log( 'InsertImage was initialized' );
}
}
export default {
name: 'InputNotes',
props: [ 'noteid', 'position' ],
components:{
'note-tag-edit': require('@/components/NoteTagEdit.vue').default
'note-tag-edit': require('@/components/NoteTagEdit.vue').default,
'color-picker': require('@/components/ColorPicker.vue').default,
'file-upload-button': require('@/components/FileUploadButton.vue').default,
},
data(){
return {
@@ -98,23 +82,19 @@
statusText: 'Saved',
lastNoteHash: null,
saveDebounce: null, //Prevent save from being called numerous times quickly
lastSaved: 0,
updated: 'Never',
editDebounce: null,
keyPressesCounter: 0,
fancyInput: 0, //Default to basic text edit. Upgrade if set to 1
keyPressesCounter: 0, //Determen keys pressed between saves
pinned: 0,
archived: 0,
color: '#fff',
fontColor: '#000',
sizeDown: false,
showColorPicker: false,
attachmentCount: 0,
styleObject: { 'noteText':null,'noteBackground':null, 'noteIcon':null, 'iconColor':null }, //Style object. Determines colors and badges
editor: DecoupledEditor,
editorConfig: {
startupFocus: 'end',
toolbar: ["alignment", "fontSize", "removeHighlight", "highlight", "bold", "italic", "strikethrough", "underline", "blockQuote", "heading", "link", "numberedList", "bulletedList", "insertTable", "|", "undo", "redo"]
}
sizeDown: false, //Used to animate close state
colorPickerVisible: false,
colorPickerLocation: null,
tinymce: null, //Initialized editor instance
}
},
watch: {
@@ -134,24 +114,102 @@
}
},
beforeMount(){
},
beforeDestroy(){
this.$bus.$off('toggle_night_mode', this.listener)
//Trash editor instance on close
this.tinymce.remove()
},
mounted: function() {
this.loadNote(this.noteid)
//Change TinyMce styles on nightmored change
this.$bus.$on('toggle_night_mode', this.setEditorTextColor )
this.$nextTick(() => {
this.loadNote(this.noteid)
})
},
methods: {
onToggleFancyInput(){
if(this.fancyInput == 0){
this.fancyInput = 1
} else {
this.fancyInput = 0;
initTinyMce(){
// image_list: [
// {title: 'My image 1', value: 'https://www.tinymce.com/my1.gif'},
// {title: 'My image 2', value: 'http://www.moxiecode.com/my2.gif'}
// ]
//Tweak doc height for mobile
let docHeight = 'calc(100vh - 90px)'
if(this.$store.getters.getIsUserOnMobile){
docHeight = 'calc(100vh - 37px)'
}
//Update last note hash, this will tell note to save next update
this.lastNoteHash = 0
//setup skin as dark if night mode is enabled
let skin = 'oxide'
if(this.$store.getters.getIsNightMode){
skin = 'oxide-dark'
}
const editorId = '#'+this.noteid+'-tinymce-editor'
//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',
browser_spellcheck: true,
menubar: false,
branding: false,
statusbar: false,
height: docHeight,
skin: skin,
contextmenu: false,
init_instance_callback: this.editorInitCallback,
imagetools_toolbar: "imageoptions",
})
},
editorInitCallback(editor){
this.loading = false //Turn off loading screed when editor is loaded
this.tinymce = editor
this.setEditorTextColor()
editor
.on('Change', this.onKeyup )
.on('keyup', this.onKeyup )
.on('blur', this.save )
},
setEditorTextColor(){
//Only Set editor text color, background is transparent and set on parent element
//There may be scenarios where editor has not been set up
if(this.tinymce){
//Set editor color to color from app, change with night mode
this.tinymce.getBody().style.color = getComputedStyle(document.documentElement)
.getPropertyValue('--text_color');
//Overwrite set color if theme is set for note.
if(this.styleObject && this.styleObject.noteText){
this.tinymce.getBody().style.color = this.styleObject.noteText
}
}
},
getText(){
//Return text from tinyMce Editor
return this.tinymce.getContent()
},
showColorPicker(event){
this.colorPickerVisible = !this.colorPickerVisible
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(){
if(this.pinned == 0){
@@ -161,6 +219,7 @@
}
//Update last note hash, this will tell note to save next update
this.lastNoteHash = 0
this.save()
},
onToggleArchived(){
if(this.archived == 0){
@@ -170,18 +229,14 @@
}
//Update last note hash, this will tell note to save next update
this.lastNoteHash = 0
this.save()
},
onChangeColor(event){
//Grab the color of the button clicked
const style = getComputedStyle(event.target)
this.color = style['background-color']
this.fontColor = '#FFF'
onChangeColor(newStyleObject){
//If background is white, default to colors in CSS
if(this.color == "rgb(255, 255, 255)" || this.color == '#FFF'){
this.color = null
this.fontColor = null
}
//Set new style object for note, page will use some styles, styles will be saved to database
this.styleObject = newStyleObject
this.setEditorTextColor()
this.lastNoteHash = 0 //Update hash to force note update on next save
this.save()
@@ -190,45 +245,34 @@
let vm = this
let doing = ['Loading','Loading','Getting','Fetching','Grabbing','Sequencing','Organizing','Untangling','Processing','Refining','Extracting','Fusing','Pruning','Expanding','Enlarging','Transfiguring','Quantizing','Ingratiating']
let doing = ['Loading','Loading','Getting','Fetching','Grabbing','Sequencing','Organizing','Untangling','Processing','Refining','Extracting','Fusing','Pruning','Expanding','Enlarging','Transfiguring','Quantizing','Ingratiating','Lumping']
let thing = ['Note','Note','Note','Note','Data','Text','Document','Algorithm','Buffer','Client','Download','File','Frame','Graphics','Hardware','HTML','Interface','Logic','Mainframe','Memory','Media','Nodes','Network','Chaos']
let p1 = doing[Math.floor(Math.random() * doing.length)]
let p2 = thing[Math.floor(Math.random() * thing.length)]
vm.loadingMessage = p1 + ' ' + p2
//Component is activated with NoteId in place, lookup text with associated ID
if(this.$store.getters.getLoggedIn){
axios.post('/api/note/get', {'noteId': noteId})
.then(response => {
vm.loading = false
//Set up local data
vm.currentNoteId = noteId
vm.noteText = response.data.text
vm.updated = response.data.updated
vm.lastNoteHash = vm.hashString(response.data.text)
vm.color = response.data.color
if(response.data.color){
vm.styleObject = JSON.parse(response.data.color) //Load styles json from DB
}
if(response.data.pinned != null){
vm.pinned = response.data.pinned
}
vm.archived = response.data.archived
vm.attachmentCount = response.data.attachment_count
this.fontColor = '#FFF'
if(this.color == "rgb(255, 255, 255)" || this.color == '#FFF' || this.color == null){
this.color = null
this.fontColor = null
}
if(response.data.raw_input == 1){
this.fancyInput = 1
}
//Put focus on note, at the end of the note text
vm.$nextTick(() => {
// vm.$refs['custom-input'].focus()
this.initTinyMce()
})
})
@@ -236,79 +280,53 @@
console.log('Could not fetch note')
}
},
onReady(editor){
let vm = this
// Insert the toolbar before the editable area.
editor.ui.getEditableElement().parentElement.insertBefore(
editor.ui.view.toolbar.element,
editor.ui.getEditableElement()
);
editor.editing.view.focus()
// const editor = this.editor;
const view = editor.editing.view;
const viewDocument = view.document;
//Insert 5 spaces when tab is pressed
viewDocument.on( 'keyup', ( evt, data ) => {
vm.onKeyup(event)
//Optional data bindings for tab key
if( (data.keyCode == 9) && viewDocument.isFocused ){
//Insert 5 spaces to simulate tab
//editor.execute( 'input', { text: " " } );
evt.stop(); // Prevent executing the default handler.
data.preventDefault();
view.scrollToTheSelection();
}
} );
},
//Used by simple editor
onKeyup(){
let vm = this
vm.statusText = 'Modified'
this.statusText = 'Modified'
//Each note, save after 5 seconds, focus lost or 30 characters typed.
clearTimeout(vm.editDebounce)
vm.editDebounce = setTimeout(() => {
vm.save()
clearTimeout(this.editDebounce)
this.editDebounce = setTimeout(() => {
this.save()
}, 5000)
//Save after 30 keystrokes
vm.keyPressesCounter = (vm.keyPressesCounter + 1)
if(vm.keyPressesCounter > 30){
vm.keyPressesCounter = 0
vm.save()
this.keyPressesCounter = (this.keyPressesCounter + 1)
if(this.keyPressesCounter > 30){
this.keyPressesCounter = 0
this.save()
}
},
save(){
return new Promise((resolve, reject) => {
//Clear other debounced events to prevent double calling of save
clearTimeout(this.editDebounce)
//Don't save note if its hash doesn't change
if( this.lastNoteHash == this.hashString(this.noteText) ){
resolve(false)
return
const currentNoteText = this.getText()
if( this.lastNoteHash == this.hashString( currentNoteText )){
return resolve(true)
}
//If user accidentally clears note, it won't delete it
if(currentNoteText == ''){
this.statusText = 'Empty'
console.log('Prevented from saving empty note.')
return resolve(true)
}
const postData = {
'noteId':this.currentNoteId,
'text': this.noteText,
'fancyInput': this.fancyInput,
'color': this.color,
'text': currentNoteText,
'color': JSON.stringify(this.styleObject), //Save little json color object
'pinned': this.pinned,
'archived':this.archived,
}
let vm = this
//Only save every 1 second
clearTimeout(this.saveDebounce)
this.saveDebounce = setTimeout(() => {
//Debounce save to prevent spamming
// clearTimeout(this.saveDebounce)
// this.saveDebounce = setTimeout(() => {
//Only notify user if saving - may help with debugging in the future
vm.statusText = 'Saving'
axios.post('/api/note/update', postData).then( response => {
@@ -316,39 +334,44 @@
vm.updated = Math.round((+new Date)/1000)
//Update last saved note hash
vm.lastNoteHash = vm.hashString(vm.noteText)
resolve(true)
return
vm.lastNoteHash = vm.hashString( currentNoteText )
return resolve(true)
})
}, 300)
// }, 300)
})
},
hashString(text){
var hash = 0;
if (text.length == 0) {
return hash;
}
//Simplified for speed
return text.length
for (let i = 0; i < text.length; i++) {
let char = text.charCodeAt(i);
hash = ((hash<<5)-hash)+char;
hash = hash & hash; // Convert to 32bit integer
}
return hash;
},
close(){
this.sizeDown = true
// this.loading = true
// this.loadingMessage = 'Save and Close'
this.save().then( result => {
//Save has a 300 ms timeout, if it saves animation will complete
if(result){
this.sizeDown = true
//This timeout allows animation to play before closing
setTimeout(() => {
this.$bus.$emit('close_active_note', this.position)
return
} else {
//If save is not called, set timeout manually and then close after animation
setTimeout(() => {
this.$bus.$emit('close_active_note', this.position)
}, 300)
}
}, 300)
})
}
@@ -357,24 +380,20 @@
</script>
<style type="text/css" scoped>
.no-flow {
overflow: hidden;
}
.raw-edit {
font-family: 'Open Sans' !important;
font-size: 1.3rem !important;
background: rgba(0,0,0,0);
width: 100%;
resize: none;
padding: 15px;
border: 1px solid;
}
.note-top-menu {
width: 100%;
display: inline-block;
height: 37px;
border-left: 3px solid var(--border_color);
}
.note-top-menu .ui.basic.button {
border-radius: 0;
border: none;
border-right: 1px solid var(--border_color);
margin: 0px -2px;
padding-left: 15px;
padding-right: 15px;
}
/* container styles change based on mobile and number of open screens */
@@ -386,17 +405,18 @@
height: 100vh;
box-shadow: 0px 0px 5px 2px rgba(140,140,140,1);
z-index: 1001;
/*overflow-x: scroll;*/
}
.loading-note {
position: absolute;
top: 38px;
top: 0;
left: 0;
right: 0;
bottom: 50px;
bottom: 0;
}
/* One note open, in the middle of the screen */
.master-note-edit.position-0 {
left: 30%;
left: 50%;
right: 0;
}
@media only screen and (max-width: 740px) {
@@ -424,12 +444,14 @@
@keyframes size-down {
0% {
opacity: 1;
/*opacity: 1;*/
/*top: 0;*/
top: 0;
}
100% {
opacity: 0;
top: 30vh;
/*opacity: 0;*/
/*top: 30vh;*/
top: 150vh;
}
}