Tons of littele interface changes and cleanups
Massive update to image scraper with much better image getter Lots of little ui updates for mobile
This commit is contained in:
parent
d4be0d6471
commit
848c86327a
@ -53,7 +53,7 @@ helpers.timeAgo = (time) => {
|
|||||||
if (typeof format[2] == 'string') {
|
if (typeof format[2] == 'string') {
|
||||||
return format[list_choice]
|
return format[list_choice]
|
||||||
} else {
|
} else {
|
||||||
return Math.floor(seconds / format[2]) + ' ' + format[1]// + ' ' + token
|
return Math.floor(seconds / format[2]) + ' ' + format[1] + ' ' + token
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ html {
|
|||||||
height:100%;
|
height:100%;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background: none;
|
background: var(--body_bg_color);
|
||||||
}
|
}
|
||||||
a:hover {
|
a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
|
@ -2117,7 +2117,7 @@ var cleanTree = function cleanTree ( node, config, preserveWS ) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data = data.replace( /^[ \t\r\n]+/g, sibling ? ' ' : '' );
|
data = data.replace( /^[ \r\n]+/g, sibling ? ' ' : '' );
|
||||||
}
|
}
|
||||||
if ( endsWithWS ) {
|
if ( endsWithWS ) {
|
||||||
walker.currentNode = child;
|
walker.currentNode = child;
|
||||||
@ -2132,7 +2132,7 @@ var cleanTree = function cleanTree ( node, config, preserveWS ) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data = data.replace( /[ \t\r\n]+$/g, sibling ? ' ' : '' );
|
data = data.replace( /[ \r\n]+$/g, sibling ? ' ' : '' );
|
||||||
}
|
}
|
||||||
if ( data ) {
|
if ( data ) {
|
||||||
child.data = data;
|
child.data = data;
|
||||||
@ -2693,7 +2693,8 @@ var sanitizeToDOMFragment = function ( html, isPaste, self ) {
|
|||||||
ALLOW_UNKNOWN_PROTOCOLS: true,
|
ALLOW_UNKNOWN_PROTOCOLS: true,
|
||||||
WHOLE_DOCUMENT: false,
|
WHOLE_DOCUMENT: false,
|
||||||
RETURN_DOM: true,
|
RETURN_DOM: true,
|
||||||
RETURN_DOM_FRAGMENT: true
|
RETURN_DOM_FRAGMENT: true,
|
||||||
|
FORCE_BODY: false
|
||||||
}) : null;
|
}) : null;
|
||||||
return frag ? doc.importNode( frag, true ) : doc.createDocumentFragment();
|
return frag ? doc.importNode( frag, true ) : doc.createDocumentFragment();
|
||||||
};
|
};
|
||||||
@ -5011,4 +5012,4 @@ if ( typeof exports === 'object' ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}( document ) );
|
}( document ) );
|
||||||
|
@ -1,54 +1,59 @@
|
|||||||
<template>
|
<template>
|
||||||
|
|
||||||
|
|
||||||
<div :style="{ 'background-color':allStyles['noteBackground'], 'color':allStyles['noteText']}">
|
<div>
|
||||||
<div class="ui basic segment">
|
|
||||||
<div class="ui grid">
|
<div class="ui grid">
|
||||||
|
|
||||||
<div class="ui sixteen wide center aligned column">
|
<div class="ui sixteen wide column">
|
||||||
<div class="ui fluid button" v-on:click="clearStyles">
|
<div class="ui dividing header">
|
||||||
|
Reset Background Color and Icon
|
||||||
|
</div>
|
||||||
|
<div class="ui labeled basic icon button" v-on:click="clearStyles">
|
||||||
<i class="refresh icon"></i>
|
<i class="refresh icon"></i>
|
||||||
Clear All Styles
|
Reset
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="sixteen wide column rounded" :style="{ 'background-color':allStyles['noteBackground'], 'color':allStyles['noteText']}">
|
||||||
<div class="sixteen wide column">
|
<div class="ui dividing header" :style="{ 'color':allStyles['noteText']}">
|
||||||
<br>
|
<i class="fill drip icon"></i>
|
||||||
<p>Note Color</p>
|
Background Color
|
||||||
<div v-for="color in colors"
|
</div>
|
||||||
class="color-button"
|
<div v-for="color in colors"
|
||||||
:style="{ backgroundColor:color }"
|
class="color-button"
|
||||||
v-on:click="chosenColor(color)"
|
:style="{ backgroundColor:color }"
|
||||||
></div>
|
v-on:click="chosenColor(color)"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="sixteen wide column">
|
||||||
|
<div class="ui dividing header">
|
||||||
|
<span v-if="allStyles.noteIcon" >
|
||||||
|
<i :class="`large ${allStyles.noteIcon} icon`" :style="{ 'color':allStyles.iconColor }"></i>
|
||||||
|
</span>
|
||||||
|
Note Icon
|
||||||
|
</div>
|
||||||
|
<div v-for="icon in icons" class="icon-button" v-on:click="chosenIcon(icon)" >
|
||||||
|
<i :class="`large ${icon} icon`"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="sixteen wide column">
|
||||||
<div class="sixteen wide column">
|
<div class="ui dividing header">
|
||||||
<p>Note Icon
|
<span v-if="allStyles.noteIcon" >
|
||||||
<span v-if="allStyles.noteIcon" >
|
<i :class="`large ${allStyles.noteIcon} icon`" :style="{ 'color':allStyles.iconColor }"></i>
|
||||||
<i :class="`large ${allStyles.noteIcon} icon`" :style="{ 'color':allStyles.iconColor }"></i>
|
</span>
|
||||||
</span>
|
Icon Color
|
||||||
</p>
|
</div>
|
||||||
<div v-for="icon in icons" class="icon-button" v-on:click="chosenIcon(icon)" >
|
<div v-for="color in getReducedColors()"
|
||||||
<i :class="`large ${icon} icon`" :style="{ 'color':allStyles.iconColor }"></i>
|
class="color-button"
|
||||||
</div>
|
:style="{ backgroundColor:color }"
|
||||||
|
v-on:click="chooseIconColor(color)"
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="sixteen wide column">
|
|
||||||
<p>Icon Color</p>
|
|
||||||
<div v-for="color in getReducedColors()"
|
|
||||||
class="color-button"
|
|
||||||
:style="{ backgroundColor:color }"
|
|
||||||
v-on:click="chooseIconColor(color)"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -147,20 +152,20 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style type="text/css" scoped>
|
<style type="text/css" scoped>
|
||||||
.icon-button {
|
.icon-button, .color-button {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
width: calc(10% - 7px);
|
width: calc(10% - 7px);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 1.3em;
|
font-size: 1.3em;
|
||||||
}
|
border: 1px solid grey;
|
||||||
.color-button {
|
text-align: center;
|
||||||
display: inline-block;
|
padding: 5px 0 0;
|
||||||
width: calc(10% - 7px);
|
border-radius: 4px;
|
||||||
height: 30px;
|
|
||||||
border-radius: 30px;
|
|
||||||
box-shadow: 0px 1px 3px 0px #3e3e3e;
|
box-shadow: 0px 1px 3px 0px #3e3e3e;
|
||||||
margin: 7px 7px 0 0;
|
margin: 7px 7px 0 0;
|
||||||
cursor: pointer;
|
}
|
||||||
|
.rounded {
|
||||||
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- change class to .master-note-edit to have it popup on the screen -->
|
<!-- change class to .master-note-edit to have it popup on the screen.
|
||||||
|
@keyup.esc="closeButtonAction()" -->
|
||||||
<div
|
<div
|
||||||
id="InputNotes"
|
id="InputNotes"
|
||||||
class="master-note-edit"
|
class="master-note-edit"
|
||||||
@keyup.esc="closeButtonAction()"
|
|
||||||
>
|
>
|
||||||
|
|
||||||
<!-- Giant Edit Note Menu -->
|
<!-- Giant Edit Note Menu -->
|
||||||
@ -89,9 +89,9 @@
|
|||||||
|
|
||||||
<div class="edit-divide"></div>
|
<div class="edit-divide"></div>
|
||||||
|
|
||||||
<div class="edit-button" v-on:click="$router.push(`/notes/open/${noteid}/menu/colors`)" data-tooltip="Note Color" data-position="bottom center" :style="{ 'background-color':styleObject['noteBackground'], 'color':styleObject['noteText']}">
|
<!-- <div class="edit-button" v-on:click="$router.push(`/notes/open/${noteid}/menu/colors`)" data-tooltip="Note Color" data-position="bottom center" :style="{ 'background-color':styleObject['noteBackground'], 'color':styleObject['noteText']}">
|
||||||
<i class="paint brush icon"></i>
|
<i class="paint brush icon"></i>
|
||||||
</div>
|
</div> -->
|
||||||
<!-- <div class="edit-button" v-on:click="$router.push(`/notes/open/${noteid}/menu/tags`)" data-tooltip="Tags" data-position="bottom center">
|
<!-- <div class="edit-button" v-on:click="$router.push(`/notes/open/${noteid}/menu/tags`)" data-tooltip="Tags" data-position="bottom center">
|
||||||
<i class="tags icon"></i>
|
<i class="tags icon"></i>
|
||||||
</div> -->
|
</div> -->
|
||||||
@ -107,7 +107,9 @@
|
|||||||
<div class="edit-divide"></div>
|
<div class="edit-divide"></div>
|
||||||
|
|
||||||
<div class="edit-button" v-on:click="$router.push(`/notes/open/${noteid}/menu/options`)" data-tooltip="More Options" data-position="bottom center">
|
<div class="edit-button" v-on:click="$router.push(`/notes/open/${noteid}/menu/options`)" data-tooltip="More Options" data-position="bottom center">
|
||||||
|
|
||||||
<i class="ellipsis horizontal icon"></i>
|
<i class="ellipsis horizontal icon"></i>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="edit-divide"></div>
|
<div class="edit-divide"></div>
|
||||||
@ -128,6 +130,7 @@
|
|||||||
|
|
||||||
<div class="edit-button ui" v-on:click="closeButtonAction()" :data-tooltip="`Close\n(ESC)`" data-position="bottom center">
|
<div class="edit-button ui" v-on:click="closeButtonAction()" :data-tooltip="`Close\n(ESC)`" data-position="bottom center">
|
||||||
<i class="green close icon"></i>
|
<i class="green close icon"></i>
|
||||||
|
<span class="ui green text">Done</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -139,7 +142,7 @@
|
|||||||
:class="{ 'side-menu-open':sideMenuOpen, 'size-down':(sizeDown == true),}">
|
:class="{ 'side-menu-open':sideMenuOpen, 'size-down':(sizeDown == true),}">
|
||||||
|
|
||||||
<!-- Squire box grows -->
|
<!-- Squire box grows -->
|
||||||
<div id="text-box-container" class="note-wrapper">
|
<div id="text-box-container" class="note-wrapper" :style="{ 'background-color':styleObject['noteBackground']}">
|
||||||
|
|
||||||
<!-- Loading indicator -->
|
<!-- Loading indicator -->
|
||||||
<transition name="fade">
|
<transition name="fade">
|
||||||
@ -161,19 +164,22 @@
|
|||||||
v-on:blur="save" type="text" v-model="noteTitle" placeholder="Title" class="stealth-input glint">
|
v-on:blur="save" type="text" v-model="noteTitle" placeholder="Title" class="stealth-input glint">
|
||||||
</textarea>
|
</textarea>
|
||||||
|
|
||||||
<div class="large-close-button glint" v-on:click="closeButtonAction()">
|
<!-- close button giant -->
|
||||||
|
<div v-if="!$store.getters.getIsUserOnMobile" class="large-close-button" v-on:click="closeButtonAction()">
|
||||||
<i class="fitted green close icon"></i>
|
<i class="fitted green close icon"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- little tags on the side, only show on desktop -->
|
<!-- tags on the side, only show on desktop -->
|
||||||
<div class="note-mini-tag-area" :class="{ 'size-down':sizeDown }" v-on:click="$router.push(`/notes/open/${noteid}/menu/tags`)">
|
<div class="note-mini-tag-area" :class="{ 'size-down':sizeDown }"
|
||||||
<span class="add-mini-tag" v-if="noteTags.length == 0">
|
v-on:click="$router.push(`/notes/open/${noteid}/menu/tags`)"
|
||||||
|
:style="{ 'background-color':styleObject['noteBackground'] }">
|
||||||
|
<span class="add-mini-tag" v-if="allTags.length == 0">
|
||||||
<i class="tags icon"></i>Add Tags
|
<i class="tags icon"></i>Add Tags
|
||||||
</span>
|
</span>
|
||||||
<span v-for="tag in allTags" class="active-mini-tag" v-if="isTagOnNote(tag.id)">
|
<span v-for="tag in allTags" class="active-mini-tag">
|
||||||
#{{ tag.text }}
|
#{{ tag }}
|
||||||
</span>
|
</span>
|
||||||
<span class="active-mini-tag" v-if="noteTags.length > 0">
|
<span class="active-mini-tag" v-if="allTags.length > 0">
|
||||||
+
|
+
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
@ -201,21 +207,23 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Side slide menus for colors, tags, images and other options -->
|
<!-- Side slide menus for colors, tags, images and other options -->
|
||||||
<side-slide-menu v-if="colors" v-on:close="colors = false" name="colors">
|
<!-- <side-slide-menu v-if="colors" v-on:close="colors = false" name="colors">
|
||||||
<color-picker
|
<color-picker
|
||||||
@changeColor="onChangeColor"
|
@changeColor="onChangeColor"
|
||||||
@close="colors = false; $router.go(-1)"
|
@close="colors = false; $router.go(-1)"
|
||||||
:style-object="styleObject"
|
:style-object="styleObject"
|
||||||
/>
|
/>
|
||||||
</side-slide-menu>
|
</side-slide-menu> -->
|
||||||
|
|
||||||
<side-slide-menu v-if="tags" v-on:close="tags = false; fetchNoteTags()" name="tags" :style-object="styleObject">
|
<!-- tag edit menu -->
|
||||||
|
<side-slide-menu v-if="tags" v-on:close="tags = false; fetchNoteTags()" name="tags">
|
||||||
<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-if="images" v-on:close="images = false" name="images" :style-object="styleObject">
|
<!-- images menu -->
|
||||||
|
<side-slide-menu v-if="images" v-on:close="images = false" name="images">
|
||||||
<div class="ui basic segment">
|
<div class="ui basic segment">
|
||||||
<simple-attachment-note
|
<simple-attachment-note
|
||||||
:note-id="noteid"
|
:note-id="noteid"
|
||||||
@ -224,67 +232,81 @@
|
|||||||
</div>
|
</div>
|
||||||
</side-slide-menu>
|
</side-slide-menu>
|
||||||
|
|
||||||
<side-slide-menu v-if="options" v-on:close="options = false" name="note-options" :style-object="styleObject">
|
<side-slide-menu v-if="options" v-on:close="options = false" name="note-options">
|
||||||
<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">
|
|
||||||
<h3>Note Options</h3>
|
|
||||||
</div>
|
|
||||||
<div class="eight wide column">
|
<div class="eight wide column">
|
||||||
|
<div class="ui dividing header">
|
||||||
|
Note Options
|
||||||
|
</div>
|
||||||
<div class="ui labeled icon fluid basic button" v-on:click="onToggleArchived()">
|
<div class="ui labeled icon fluid basic button" v-on:click="onToggleArchived()">
|
||||||
<i class="archive icon" :class="{'green':(archived == 1)}"></i>
|
<i class="archive icon" :class="{'green':(archived == 1)}"></i>
|
||||||
<span v-if="archived == 1">Un-Archive Note</span>
|
<span v-if="archived == 1">Un-Archive Note</span>
|
||||||
<span v-if="archived != 1">Archive Note</span>
|
<span v-if="archived != 1">Archive Note</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="eight wide column">
|
|
||||||
<div class="ui labeled icon fluid basic button" v-on:click="onTogglePinned">
|
<div class="ui labeled icon fluid basic button" v-on:click="onTogglePinned">
|
||||||
<i class="pin icon" :class="{'green':(pinned == 1)}"></i>
|
<i class="pin icon" :class="{'green':(pinned == 1)}"></i>
|
||||||
<span v-if="pinned == 1">Un-Pin Note</span>
|
<span v-if="pinned == 1">Un-Pin Note</span>
|
||||||
<span v-if="pinned != 1">Pin Note</span>
|
<span v-if="pinned != 1">Pin Note</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="sixteen wide column">
|
|
||||||
<h3>List Options</h3>
|
<div class="eight wide column">
|
||||||
</div>
|
<div class="ui dividing header">
|
||||||
<div class="sixteen wide column">
|
List Options
|
||||||
|
</div>
|
||||||
<div class="ui labeled icon fluid basic button" v-on:click="sortList">
|
<div class="ui labeled icon fluid basic button" v-on:click="sortList">
|
||||||
<i class="sort amount up icon"></i>
|
<i class="sort amount up icon"></i>
|
||||||
Sort List
|
Sort List (Complete to bottom)
|
||||||
|
</div>
|
||||||
|
<div class="ui labeled icon fluid basic button" v-on:click="uncheckAllListItems">
|
||||||
|
<i class="list ul icon"></i>
|
||||||
|
Uncheck All
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="eight wide column">
|
|
||||||
<div class="ui labeled icon fluid basic button" v-on:click="deleteCompletedListItems">
|
<div class="ui labeled icon fluid basic button" v-on:click="deleteCompletedListItems">
|
||||||
<i class="trash icon"></i>
|
<i class="trash icon"></i>
|
||||||
Delete Checked
|
Delete Checked
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="eight wide column">
|
<div class="eight wide column">
|
||||||
<div class="ui labeled icon fluid basic button" v-on:click="uncheckAllListItems">
|
<div class="ui dividing header">
|
||||||
<i class="list ul icon"></i>
|
Calculate Line
|
||||||
Uncheck All
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<p>
|
||||||
<div class="sixteen wide column">
|
Calculates algebra before '='
|
||||||
<h3>Misc Options</h3>
|
</p>
|
||||||
</div>
|
<div class="ui labeled icon fluid basic button" v-on:click="calculateMath">
|
||||||
<div class="eight wide column">
|
|
||||||
<div class="ui labeled icon fluid basic button" v-on:click="calculateMath" data-tooltip="Calculates algebra before '='">
|
|
||||||
<i class="calculator icon"></i>
|
<i class="calculator icon"></i>
|
||||||
Simple Math
|
Calculate Simple Math
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="eight wide column">
|
|
||||||
<!-- data-tooltip="Files on note" -->
|
|
||||||
<div v-on:click="openEditAttachment" class="ui labeled icon fluid basic button">
|
|
||||||
<i class="folder icon"></i>
|
|
||||||
Note Files
|
|
||||||
{{ attachmentCount }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="eight wide column">
|
||||||
|
<!-- data-tooltip="Files on note" -->
|
||||||
|
<div class="ui dividing header">
|
||||||
|
Note Attachments & Links
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
Attachment & Link Count {{ attachmentCount }}
|
||||||
|
</p>
|
||||||
|
<div v-on:click="openEditAttachment" class="ui labeled icon fluid basic button">
|
||||||
|
<i class="folder icon"></i>
|
||||||
|
View all Attachments & Links
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<color-picker
|
||||||
|
@changeColor="onChangeColor"
|
||||||
|
@close="colors = false; $router.go(-1)"
|
||||||
|
:style-object="styleObject"
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="sixteen wide column" v-if="rawTextId > 0">
|
<div class="sixteen wide column" v-if="rawTextId > 0">
|
||||||
<h3>Share Note</h3>
|
<div class="ui dividing header">
|
||||||
|
Share Note
|
||||||
|
</div>
|
||||||
<share-note-component
|
<share-note-component
|
||||||
:note-id="noteid"
|
:note-id="noteid"
|
||||||
:raw-text-id="rawTextId"
|
:raw-text-id="rawTextId"
|
||||||
@ -296,7 +318,7 @@
|
|||||||
</side-slide-menu>
|
</side-slide-menu>
|
||||||
|
|
||||||
<!-- create table option -->
|
<!-- create table option -->
|
||||||
<side-slide-menu v-if="table" v-on:close="table = false; fetchNoteTags()" name="table" :style-object="styleObject">
|
<side-slide-menu v-if="table" v-on:close="table = false;" name="table" :style-object="styleObject">
|
||||||
<div class="ui basic segment">
|
<div class="ui basic segment">
|
||||||
<h2>Insert Table</h2>
|
<h2>Insert Table</h2>
|
||||||
<div class="table-tic-table">
|
<div class="table-tic-table">
|
||||||
@ -521,77 +543,15 @@
|
|||||||
|
|
||||||
}, totalTime + 40)
|
}, totalTime + 40)
|
||||||
},
|
},
|
||||||
removeTag(tagId){
|
|
||||||
|
|
||||||
this.allTags = []
|
|
||||||
let entryId = 0
|
|
||||||
|
|
||||||
//Find fucking note tag for removal
|
|
||||||
this.noteTags.forEach(noteTag => {
|
|
||||||
if(noteTag['tagId'] == tagId){
|
|
||||||
entryId = noteTag['entryId']
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
let postData = {
|
|
||||||
'tagId':entryId,
|
|
||||||
'noteId':this.noteid
|
|
||||||
}
|
|
||||||
|
|
||||||
axios.post('/api/tag/removefromnote', postData)
|
|
||||||
.then(response => {
|
|
||||||
this.fetchNoteTags()
|
|
||||||
})
|
|
||||||
.catch(error => { this.$bus.$emit('notification', 'Failed to Remove Tag') })
|
|
||||||
},
|
|
||||||
addTag(tagText){
|
|
||||||
|
|
||||||
this.allTags = []
|
|
||||||
|
|
||||||
let postData = {
|
|
||||||
'tagText':tagText,
|
|
||||||
'noteId':this.noteid
|
|
||||||
}
|
|
||||||
|
|
||||||
axios.post('/api/tag/addtonote', postData)
|
|
||||||
.then(response => {
|
|
||||||
this.fetchNoteTags()
|
|
||||||
})
|
|
||||||
.catch(error => { this.$bus.$emit('notification', 'Failed to Add Tag') })
|
|
||||||
},
|
|
||||||
fetchNoteTags(){
|
fetchNoteTags(){
|
||||||
axios.post('/api/tag/get', {'noteId': this.noteid})
|
axios.post('/api/tag/fornote', {'noteId': this.noteid})
|
||||||
.then(({data}) => {
|
.then(({data}) => {
|
||||||
this.allTags = data.allTags
|
|
||||||
this.noteTags = data.noteTagIds
|
|
||||||
|
|
||||||
//Stick used tags at top.
|
//Setup note tags from string
|
||||||
if(this.noteTags.length > 0){
|
this.allTags = data.tags ? data.tags.split(',') : []
|
||||||
|
|
||||||
let frontTags = []
|
|
||||||
|
|
||||||
for (var i = this.allTags.length - 1; i >= 0; i--) {
|
|
||||||
this.noteTags.forEach(noteTag => {
|
|
||||||
if(this.allTags[i]['id'] == noteTag['tagId']){
|
|
||||||
frontTags.push(this.allTags[i])
|
|
||||||
this.allTags.splice(i,1)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
this.allTags.unshift(...frontTags)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
isTagOnNote(id){
|
|
||||||
for (let i = 0; i < this.noteTags.length; i++) {
|
|
||||||
const current = this.noteTags[i]
|
|
||||||
if(current && current['tagId'] == id){
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
},
|
|
||||||
initSquire(){
|
initSquire(){
|
||||||
|
|
||||||
//Set up squire and load note text
|
//Set up squire and load note text
|
||||||
@ -604,10 +564,6 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Load tags on mobile
|
|
||||||
this.fetchNoteTags()
|
|
||||||
|
|
||||||
|
|
||||||
//Set up websockets after squire is set up
|
//Set up websockets after squire is set up
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.setupWebSockets()
|
this.setupWebSockets()
|
||||||
@ -783,6 +739,9 @@
|
|||||||
this.lastNoteHash = this.hashString( response.data.text )
|
this.lastNoteHash = this.hashString( response.data.text )
|
||||||
// this.diffNoteText = response.data.text
|
// this.diffNoteText = response.data.text
|
||||||
|
|
||||||
|
//Setup note tags
|
||||||
|
this.allTags = response.data.tags ? response.data.tags.split(','):[]
|
||||||
|
|
||||||
//Set up note colors
|
//Set up note colors
|
||||||
if(response.data.color){
|
if(response.data.color){
|
||||||
this.styleObject = JSON.parse(response.data.color)
|
this.styleObject = JSON.parse(response.data.color)
|
||||||
|
@ -21,27 +21,9 @@
|
|||||||
class="big-text"><p>{{ note.title }}</p></span>
|
class="big-text"><p>{{ note.title }}</p></span>
|
||||||
|
|
||||||
<span class="tags" v-if="note.tags">
|
<span class="tags" v-if="note.tags">
|
||||||
<span v-for="tag in (note.tags.split(','))" class="little-tag" v-on:click="$emit('tagClick', tag.split(':')[1] )">#{{ tag.split(':')[0] }}</span>
|
<span v-for="tag in (note.tags.split(','))" class="little-tag" v-on:click="$emit('tagClick', tag.split(':')[1] )">#{{ tag.split(':')[0] }}</span>
|
||||||
<br>
|
<br>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<!-- Sub text display -->
|
|
||||||
<span v-if="note.subtext.length > 0"
|
|
||||||
class="small-text"
|
|
||||||
v-html="note.subtext"></span>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Not indexed warning -->
|
|
||||||
<!-- <span v-if="note.indexed != 1">
|
|
||||||
<span class="green label">Not Indexed</span>
|
|
||||||
</span> -->
|
|
||||||
|
|
||||||
|
|
||||||
<div class="ui fluid basic button" v-if="note.encrypted == 1">
|
|
||||||
<i class="green lock icon"></i>
|
|
||||||
Locked
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Shared Details -->
|
<!-- Shared Details -->
|
||||||
<span class="subtext" v-if="note.shared == 2">
|
<span class="subtext" v-if="note.shared == 2">
|
||||||
@ -62,23 +44,71 @@
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
</div>
|
<!-- Sub text display -->
|
||||||
|
<span v-if="note.subtext.length > 0"
|
||||||
|
class="small-text"
|
||||||
|
v-html="note.subtext"></span>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Not indexed warning -->
|
||||||
|
<!-- <span v-if="note.indexed != 1">
|
||||||
|
<span class="green label">Not Indexed</span>
|
||||||
|
</span> -->
|
||||||
|
|
||||||
|
|
||||||
<div v-if="titleView" class="single-line-text" @click="cardClicked">
|
<!-- <div class="ui fluid basic button" v-if="note.encrypted == 1">
|
||||||
<span class="title-line" v-if="note.title.length > 0">{{ note.title }}<br></span>
|
<i class="green lock icon"></i>
|
||||||
<span class="sub-line" v-if="note.subtext.length > 0">{{ removeHtml(note.subtext) }}</span>
|
Locked
|
||||||
<span v-if="note.title.length == 0 && note.title.length == 0">Empty Note</span>
|
</div> -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- slim card view -->
|
||||||
|
<div v-if="titleView" class="thin-container" @click="cardClicked">
|
||||||
|
|
||||||
|
<!-- icon -->
|
||||||
|
<span v-if="noteIcon" class="thin-icon">
|
||||||
|
<i :class="`${noteIcon} icon`" :style="{ 'color':iconColor }"></i>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<!-- title -->
|
||||||
|
<span class="thin-title" v-if="note.title.length > 0">{{ note.title }}</span>
|
||||||
|
|
||||||
|
<!-- snippet -->
|
||||||
|
<span class="thin-sub" v-if="note.subtext.length > 0">{{ removeHtml(note.subtext) }}</span>
|
||||||
|
<span v-if="note.title.length == 0 && removeHtml(note.subtext).length == 0">Empty Note</span>
|
||||||
|
|
||||||
|
<!-- tags -->
|
||||||
|
<span v-if="note.tags" class="thin-tags" >
|
||||||
|
<span v-for="tag in (note.tags.split(','))" class="little-tag" v-on:click="$emit('tagClick', tag.split(':')[1] )">#{{ tag.split(':')[0] }}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<!-- edited -->
|
||||||
|
<span class="thin-right">
|
||||||
|
{{$helpers.timeAgo( note.updated )}}
|
||||||
|
|
||||||
|
<i class="green link ellipsis vertical icon"></i>
|
||||||
|
</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Toolbar on the bottom -->
|
<!-- Toolbar on the bottom -->
|
||||||
<div class="tool-bar" @click.self="cardClicked" v-if="!titleView">
|
<div class="tool-bar" @click.self="cardClicked" v-if="!titleView">
|
||||||
<div class="icon-bar">
|
|
||||||
|
|
||||||
<span class="time-ago-display" :class="{ 'hover-hide':(!$store.getters.getIsUserOnMobile) }">
|
<div v-if="getThumbs.length > 0">
|
||||||
|
<div class="tiny-thumb-box" v-on:click="openEditAttachment">
|
||||||
|
<img v-for="thumb in getThumbs" class="tiny-thumb" :src="`/api/static/thumb_${thumb}`">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="icon-bar" :class="{ 'hover-hide':(!$store.getters.getIsUserOnMobile) }">
|
||||||
|
|
||||||
|
<span class="time-ago-display">
|
||||||
{{$helpers.timeAgo( note.updated )}}
|
{{$helpers.timeAgo( note.updated )}}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span class="teeny-buttons" :class="{ 'hover-hide':(!$store.getters.getIsUserOnMobile) }">
|
<span class="teeny-buttons">
|
||||||
|
|
||||||
<span v-if="!note.trashed">
|
<span v-if="!note.trashed">
|
||||||
|
|
||||||
@ -115,19 +145,13 @@
|
|||||||
</i>
|
</i>
|
||||||
<delete-button class="teeny-button" :note-id="note.id" />
|
<delete-button class="teeny-button" :note-id="note.id" />
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="getThumbs.length > 0">
|
|
||||||
<div class="tiny-thumb-box" v-on:click="openEditAttachment">
|
|
||||||
<img v-for="thumb in getThumbs" class="tiny-thumb" :src="`/api/static/thumb_${thumb}`">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- tag edit menu -->
|
||||||
<side-slide-menu v-if="showTagSlideMenu" v-on:close="toggleTags(false)" :full-shadow="true" :skip-history="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"/>
|
||||||
@ -333,13 +357,11 @@
|
|||||||
|
|
||||||
.teeny-buttons {
|
.teeny-buttons {
|
||||||
float: right;
|
float: right;
|
||||||
width: 65%;
|
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
.time-ago-display {
|
.time-ago-display {
|
||||||
width: 35%;
|
font-size: 11px;
|
||||||
float: left;
|
font-weight: bold;
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
.tags {
|
.tags {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -364,9 +386,7 @@
|
|||||||
|
|
||||||
/*Strict font sizes for card display*/
|
/*Strict font sizes for card display*/
|
||||||
.small-text {
|
.small-text {
|
||||||
max-height: 267px;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
|
||||||
display: inline-block;
|
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 {
|
||||||
@ -426,7 +446,7 @@
|
|||||||
/*width: calc(33.333% - 10px);*/
|
/*width: calc(33.333% - 10px);*/
|
||||||
width: calc(25% - 10px);
|
width: calc(25% - 10px);
|
||||||
/*min-width: 190px;*/
|
/*min-width: 190px;*/
|
||||||
min-height: 130px;
|
/*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;
|
||||||
@ -435,7 +455,11 @@
|
|||||||
letter-spacing: 0.05rem;
|
letter-spacing: 0.05rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
|
||||||
|
min-height: 100px;
|
||||||
|
max-height: 450px;
|
||||||
}
|
}
|
||||||
.note-title-display-card:hover {
|
.note-title-display-card:hover {
|
||||||
/*box-shadow: 0px 2px 2px 1px rgba(210, 211, 211, 0.8);*/
|
/*box-shadow: 0px 2px 2px 1px rgba(210, 211, 211, 0.8);*/
|
||||||
@ -446,21 +470,49 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 20px;
|
min-height: 20px;
|
||||||
max-width: none;
|
max-width: none;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 0;
|
||||||
|
border: none;
|
||||||
/*box-shadow: 0px 0px 1px 1px rgba(210, 211, 211, 0.46);*/
|
/*box-shadow: 0px 0px 1px 1px rgba(210, 211, 211, 0.46);*/
|
||||||
}
|
}
|
||||||
|
.title-view + .title-view {
|
||||||
.single-line-text {
|
border-top: 1px solid var(--border_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thin-container.single-line-text {
|
||||||
width: calc(100% - 25px);
|
width: calc(100% - 25px);
|
||||||
margin: 5px 10px;
|
/*margin: 5px 10px;*/
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
.title-line {
|
|
||||||
|
.thin-container .thin-title {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
padding: 0 20px 0 0;
|
}
|
||||||
|
.thin-container .thin-sub {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
.thin-container .thin-tags {
|
||||||
|
float: left;
|
||||||
|
margin-top: 3px;
|
||||||
|
}
|
||||||
|
.thin-container .thin-right {
|
||||||
|
float: right;
|
||||||
|
color: var(--dark_border_color);
|
||||||
|
}
|
||||||
|
.thin-container .thin-icon {
|
||||||
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-bar {
|
.icon-bar {
|
||||||
@ -468,6 +520,7 @@
|
|||||||
padding: 5px 10px 0;
|
padding: 5px 10px 0;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
background-color: rgba(200, 200, 200, 0.2);
|
||||||
}
|
}
|
||||||
.hover-hide {
|
.hover-hide {
|
||||||
opacity: 0.0;
|
opacity: 0.0;
|
||||||
|
@ -191,11 +191,24 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Overview -->
|
||||||
|
<div class="middle aligned centered row">
|
||||||
|
<div class="six wide column">
|
||||||
|
<h2 class="ui dividing header">Powerful text editing and privacy</h2>
|
||||||
|
<h3>Easily edit, share and organize thousands of notes.</h3>
|
||||||
|
<h3>Feel safe knowing no one can read your notes but you.</h3>
|
||||||
|
<!-- <h3>Tools to organize and collaborate on thousands of notes while maintaining security and respecting your privacy.</h3> -->
|
||||||
|
</div>
|
||||||
|
<div class="four wide column">
|
||||||
|
<img loading="lazy" width="100%" src="/api/static/assets/marketing/idea.svg" alt="Explosion of New Ideas">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- theme selector -->
|
<!-- theme selector -->
|
||||||
<div class="ui white row">
|
<div class="ui white row">
|
||||||
<div class="sixteen wide middle aligned column">
|
<div class="sixteen wide middle aligned column">
|
||||||
<div class="ui container">
|
<div class="ui container">
|
||||||
<h2>
|
<h2 style="color: var(--main-accent);">
|
||||||
Pick your theme
|
Pick your theme
|
||||||
</h2>
|
</h2>
|
||||||
<h3 v-if="$parent.loggedIn">Go to settings to change theme</h3>
|
<h3 v-if="$parent.loggedIn">Go to settings to change theme</h3>
|
||||||
@ -211,19 +224,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Overview -->
|
|
||||||
<div class="middle aligned centered row">
|
|
||||||
<div class="six wide column">
|
|
||||||
<h2 class="ui dividing header">Powerful text editing and privacy</h2>
|
|
||||||
<h3>Easily edit, share and organize thousands of notes.</h3>
|
|
||||||
<h3>Feel safe knowing no one can read your notes but you.</h3>
|
|
||||||
<!-- <h3>Tools to organize and collaborate on thousands of notes while maintaining security and respecting your privacy.</h3> -->
|
|
||||||
</div>
|
|
||||||
<div class="four wide column">
|
|
||||||
<img loading="lazy" width="100%" src="/api/static/assets/marketing/idea.svg" alt="Explosion of New Ideas">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- features list -->
|
<!-- features list -->
|
||||||
<div class="top aligned centered row">
|
<div class="top aligned centered row">
|
||||||
|
|
||||||
@ -355,7 +355,7 @@
|
|||||||
<i class="grey lock icon"></i>
|
<i class="grey lock icon"></i>
|
||||||
<i class="bottom left corner yellow key icon"></i>
|
<i class="bottom left corner yellow key icon"></i>
|
||||||
</i>
|
</i>
|
||||||
All Note Text is Encrypted
|
Secure Notes
|
||||||
<div class="sub header">All note text is encrypted. No one can read your notes. None of your data is shared.</div>
|
<div class="sub header">All note text is encrypted. No one can read your notes. None of your data is shared.</div>
|
||||||
</div>
|
</div>
|
||||||
</h2>
|
</h2>
|
||||||
@ -365,7 +365,7 @@
|
|||||||
<i class="grey search icon"></i>
|
<i class="grey search icon"></i>
|
||||||
<i class="bottom left corner orange font icon"></i>
|
<i class="bottom left corner orange font icon"></i>
|
||||||
</i>
|
</i>
|
||||||
Note Search is Encrypted
|
Private Search
|
||||||
<div class="sub header">Search the contents of all your notes without compromising security.</div>
|
<div class="sub header">Search the contents of all your notes without compromising security.</div>
|
||||||
</div>
|
</div>
|
||||||
</h2>
|
</h2>
|
||||||
@ -375,7 +375,7 @@
|
|||||||
<i class="grey share alternate icon"></i>
|
<i class="grey share alternate icon"></i>
|
||||||
<i class="bottom left corner share icon"></i>
|
<i class="bottom left corner share icon"></i>
|
||||||
</i>
|
</i>
|
||||||
Encrypted Note Sharing
|
Encrypted Sharing
|
||||||
<div class="sub header">Shared notes are still encrypted, only readable by you and the shared users.</div>
|
<div class="sub header">Shared notes are still encrypted, only readable by you and the shared users.</div>
|
||||||
</div>
|
</div>
|
||||||
</h2>
|
</h2>
|
||||||
|
@ -27,9 +27,15 @@
|
|||||||
v-on:tagClick="tagId => toggleTagFilter(tagId)"
|
v-on:tagClick="tagId => toggleTagFilter(tagId)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="ui basic shrinking icon button" v-on:click="toggleTitleView()" v-if="$store.getters.totals && $store.getters.totals['totalNotes'] > 0">
|
<div class="ui right floated basic shrinking icon button" v-on:click="toggleTitleView()" v-if="$store.getters.totals && $store.getters.totals['totalNotes'] > 0">
|
||||||
<i v-if="titleView" class="th icon"></i>
|
<span v-if="titleView">
|
||||||
<i v-if="!titleView" class="bars icon"></i>
|
<i class="th icon"></i> Tiles
|
||||||
|
</span>
|
||||||
|
<span v-if="!titleView">
|
||||||
|
<i class="list icon"></i> List
|
||||||
|
</span>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -223,6 +229,9 @@
|
|||||||
|
|
||||||
this.$parent.loginGateway()
|
this.$parent.loginGateway()
|
||||||
|
|
||||||
|
//If user is on title view,
|
||||||
|
this.titleView = this.$store.getters.getIsUserOnMobile
|
||||||
|
|
||||||
this.$io.on('new_note_created', noteId => {
|
this.$io.on('new_note_created', noteId => {
|
||||||
|
|
||||||
//Do not update note if its open
|
//Do not update note if its open
|
||||||
|
@ -11,4 +11,5 @@ common.js
|
|||||||
bundle.*
|
bundle.*
|
||||||
client/dist*
|
client/dist*
|
||||||
server/public/*
|
server/public/*
|
||||||
client/dist*
|
client/dist*
|
||||||
|
*_scrape*
|
@ -6,6 +6,7 @@ const speakeasy = require('speakeasy')
|
|||||||
let Auth = {}
|
let Auth = {}
|
||||||
|
|
||||||
const tokenSecretKey = process.env.JSON_KEY
|
const tokenSecretKey = process.env.JSON_KEY
|
||||||
|
const sessionTokenUses = 300 //Defines number of uses each session token has before being refreshed
|
||||||
|
|
||||||
//Creates session token
|
//Creates session token
|
||||||
Auth.createToken = (userId, masterKey, pastId = null, pastCreatedDate = null) => {
|
Auth.createToken = (userId, masterKey, pastId = null, pastCreatedDate = null) => {
|
||||||
@ -26,7 +27,7 @@ Auth.createToken = (userId, masterKey, pastId = null, pastCreatedDate = null) =>
|
|||||||
|
|
||||||
return db.promise().query(
|
return db.promise().query(
|
||||||
'INSERT INTO user_active_session (salt, encrypted_master_password, created, uses, user_hash, session_id) VALUES (?,?,?,?,?,?)',
|
'INSERT INTO user_active_session (salt, encrypted_master_password, created, uses, user_hash, session_id) VALUES (?,?,?,?,?,?)',
|
||||||
[salt, encryptedMasterPass, created, 40, userHash, sessionId])
|
[salt, encryptedMasterPass, created, sessionTokenUses, userHash, sessionId])
|
||||||
|
|
||||||
})
|
})
|
||||||
.then((r,f) => {
|
.then((r,f) => {
|
||||||
|
@ -54,7 +54,7 @@ SiteScrape.getCleanUrls = (textBlock) => {
|
|||||||
SiteScrape.getHostName = (url) => {
|
SiteScrape.getHostName = (url) => {
|
||||||
|
|
||||||
var hostname = 'https://'+(new URL(url)).hostname;
|
var hostname = 'https://'+(new URL(url)).hostname;
|
||||||
console.log('hostname', hostname)
|
// console.log('hostname', hostname)
|
||||||
return hostname
|
return hostname
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,36 +63,95 @@ SiteScrape.getDisplayImage = ($, url) => {
|
|||||||
|
|
||||||
const hostname = SiteScrape.getHostName(url)
|
const hostname = SiteScrape.getHostName(url)
|
||||||
|
|
||||||
let metaImg = $('meta[property="og:image"]')
|
let metaImg = $('[property="og:image"]')
|
||||||
let shortcutIcon = $('link[rel="shortcut icon"]')
|
let shortcutIcon = $('[rel="shortcut icon"]')
|
||||||
let favicon = $('link[rel="icon"]')
|
let favicon = $('[rel="icon"]')
|
||||||
let randomImg = $('img')
|
let randomImg = $('img')
|
||||||
|
|
||||||
console.log('----')
|
//Set of images we may want gathered from various places in source
|
||||||
|
let imagesWeWant = []
|
||||||
|
let thumbnail = ''
|
||||||
|
|
||||||
//Scrape metadata for page image
|
//Scrape metadata for page image
|
||||||
//Grab the first random image we find
|
if(randomImg && randomImg.length > 0){
|
||||||
if(randomImg && randomImg[0] && randomImg[0].attribs){
|
|
||||||
thumbnail = hostname + randomImg[0].attribs.src
|
let imgSrcs = []
|
||||||
console.log('random img '+thumbnail)
|
for (let i = 0; i < randomImg.length; i++) {
|
||||||
|
imgSrcs.push( randomImg[i].attribs.src )
|
||||||
|
}
|
||||||
|
|
||||||
|
const half = Math.ceil(imgSrcs.length / 2)
|
||||||
|
imagesWeWant = [...imgSrcs.slice(-half), ...imgSrcs.slice(0,half) ]
|
||||||
|
|
||||||
}
|
}
|
||||||
//Grab the favicon of the site
|
//Grab the shortcut icon
|
||||||
if(favicon && favicon[0] && favicon[0].attribs){
|
if(favicon && favicon[0] && favicon[0].attribs){
|
||||||
thumbnail = hostname + favicon[0].attribs.href
|
imagesWeWant.push(favicon[0].attribs.href)
|
||||||
console.log('favicon '+thumbnail)
|
|
||||||
}
|
}
|
||||||
//Grab the shortcut icon
|
//Grab the shortcut icon
|
||||||
if(shortcutIcon && shortcutIcon[0] && shortcutIcon[0].attribs){
|
if(shortcutIcon && shortcutIcon[0] && shortcutIcon[0].attribs){
|
||||||
thumbnail = hostname + shortcutIcon[0].attribs.href
|
imagesWeWant.push(shortcutIcon[0].attribs.href)
|
||||||
console.log('shortcut '+thumbnail)
|
|
||||||
}
|
}
|
||||||
//Grab the presentation image for the site
|
//Grab the presentation image for the site
|
||||||
if(metaImg && metaImg[0] && metaImg[0].attribs){
|
if(metaImg && metaImg[0] && metaImg[0].attribs){
|
||||||
thumbnail = metaImg[0].attribs.content
|
imagesWeWant.unshift(metaImg[0].attribs.content)
|
||||||
console.log('ogImg '+thumbnail)
|
}
|
||||||
|
|
||||||
|
// console.log(imagesWeWant)
|
||||||
|
|
||||||
|
//Remove everything that isn't an accepted file format
|
||||||
|
for (let i = imagesWeWant.length - 1; i >= 0; i--) {
|
||||||
|
|
||||||
|
let img = String(imagesWeWant[i])
|
||||||
|
|
||||||
|
if(
|
||||||
|
!img.includes('.jpg') &&
|
||||||
|
!img.includes('.jpeg') &&
|
||||||
|
!img.includes('.png') &&
|
||||||
|
!img.includes('.gif')
|
||||||
|
){
|
||||||
|
imagesWeWant.splice(i,1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Find if we have absolute thumbnails or not
|
||||||
|
let foundAbsolute = false
|
||||||
|
for (let i = imagesWeWant.length - 1; i >= 0; i--) {
|
||||||
|
|
||||||
|
let img = imagesWeWant[i]
|
||||||
|
|
||||||
|
//Add host name if its not included
|
||||||
|
if(String(img).includes('//') || String(img).includes('http')){
|
||||||
|
foundAbsolute = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Go through all found images. Grab the one closest to the top. Closer is better
|
||||||
|
for (let i = imagesWeWant.length - 1; i >= 0; i--) {
|
||||||
|
|
||||||
|
let img = imagesWeWant[i]
|
||||||
|
|
||||||
|
if(!String(img).includes('//') && foundAbsolute){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Only add host to images if no absolute images were found
|
||||||
|
if(!String(img).includes('//') ){
|
||||||
|
if(img.indexOf('/') != 0){
|
||||||
|
img = '/' + img
|
||||||
|
}
|
||||||
|
img = hostname + img
|
||||||
|
}
|
||||||
|
|
||||||
|
if(img.indexOf('//') == 0){
|
||||||
|
img = 'https:' + img //Scrape breaks without protocol
|
||||||
|
}
|
||||||
|
|
||||||
|
thumbnail = img
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('-----')
|
|
||||||
return thumbnail
|
return thumbnail
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,7 +257,6 @@ const printResults = true
|
|||||||
let UserTest = require('@models/User')
|
let UserTest = require('@models/User')
|
||||||
let NoteTest = require('@models/Note')
|
let NoteTest = require('@models/Note')
|
||||||
let AuthTest = require('@helpers/Auth')
|
let AuthTest = require('@helpers/Auth')
|
||||||
|
|
||||||
Auth.test()
|
Auth.test()
|
||||||
UserTest.keyPairTest('genMan30', '1', printResults)
|
UserTest.keyPairTest('genMan30', '1', printResults)
|
||||||
.then( ({testUserId, masterKey}) => NoteTest.test(testUserId, masterKey, printResults))
|
.then( ({testUserId, masterKey}) => NoteTest.test(testUserId, masterKey, printResults))
|
||||||
@ -266,7 +265,6 @@ UserTest.keyPairTest('genMan30', '1', printResults)
|
|||||||
Auth.testTwoFactor()
|
Auth.testTwoFactor()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
//Test
|
//Test
|
||||||
app.get('/api', (req, res) => res.send('Solidscribe API is up and running'))
|
app.get('/api', (req, res) => res.send('Solidscribe API is up and running'))
|
||||||
|
|
||||||
|
@ -325,14 +325,14 @@ Attachment.downloadFileFromUrl = (url) => {
|
|||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
||||||
if(url == null){
|
if(url == null || url == undefined || url == ''){
|
||||||
resolve(null)
|
resolve(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
const random = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
|
const random = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
|
||||||
const extension = '.'+url.split('.').pop() //This is throwing an error
|
let extension = ''
|
||||||
let fileName = random+'_scrape'+extension
|
let fileName = random+'_scrape'
|
||||||
const thumbPath = 'thumb_'+fileName
|
let thumbPath = 'thumb_'+fileName
|
||||||
|
|
||||||
console.log('Scraping image url')
|
console.log('Scraping image url')
|
||||||
console.log(url)
|
console.log(url)
|
||||||
@ -347,6 +347,8 @@ Attachment.downloadFileFromUrl = (url) => {
|
|||||||
.on('response', res => {
|
.on('response', res => {
|
||||||
console.log(res.statusCode)
|
console.log(res.statusCode)
|
||||||
console.log(res.headers['content-type'])
|
console.log(res.headers['content-type'])
|
||||||
|
//Get mime type from header content type
|
||||||
|
// extension = '.'+String(res.headers['content-type']).split('/').pop()
|
||||||
})
|
})
|
||||||
.pipe(fs.createWriteStream(filePath+thumbPath))
|
.pipe(fs.createWriteStream(filePath+thumbPath))
|
||||||
.on('close', () => {
|
.on('close', () => {
|
||||||
@ -354,14 +356,17 @@ Attachment.downloadFileFromUrl = (url) => {
|
|||||||
//resize image if its real big
|
//resize image if its real big
|
||||||
gm(filePath+thumbPath)
|
gm(filePath+thumbPath)
|
||||||
.resize(550) //Resize to width of 550 px
|
.resize(550) //Resize to width of 550 px
|
||||||
.quality(75) //compression level 0 - 100 (best)
|
.quality(85) //compression level 0 - 100 (best)
|
||||||
.write(filePath+thumbPath, function (err) {
|
.write(filePath+thumbPath, function (err) {
|
||||||
if(err){ console.log(err) }
|
if(err){
|
||||||
|
console.log(err)
|
||||||
|
return resolve(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Saved Image')
|
||||||
|
return resolve(fileName)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
console.log('Saved Image')
|
|
||||||
resolve(fileName)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -396,7 +401,7 @@ Attachment.processUrl = (userId, noteId, url) => {
|
|||||||
.query(`INSERT INTO attachment
|
.query(`INSERT INTO attachment
|
||||||
(note_id, user_id, attachment_type, text, url, last_indexed, file_location)
|
(note_id, user_id, attachment_type, text, url, last_indexed, file_location)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
||||||
[noteId, userId, 1, 'Processing...', url, created, null])
|
[noteId, userId, 1, url, url, created, null])
|
||||||
.then((rows, fields) => {
|
.then((rows, fields) => {
|
||||||
//Set two bigger variables then return request for processing
|
//Set two bigger variables then return request for processing
|
||||||
request = rp(options)
|
request = rp(options)
|
||||||
|
@ -681,6 +681,7 @@ Note.get = (userId, noteId, masterKey) => {
|
|||||||
note_raw_text.text,
|
note_raw_text.text,
|
||||||
note_raw_text.salt,
|
note_raw_text.salt,
|
||||||
note_raw_text.updated as updated,
|
note_raw_text.updated as updated,
|
||||||
|
GROUP_CONCAT(DISTINCT(tag.text) ORDER BY tag.text DESC) AS tags,
|
||||||
note.id,
|
note.id,
|
||||||
note.user_id,
|
note.user_id,
|
||||||
note.created,
|
note.created,
|
||||||
@ -697,7 +698,9 @@ Note.get = (userId, noteId, masterKey) => {
|
|||||||
JOIN note_raw_text ON (note_raw_text.id = note.note_raw_text_id)
|
JOIN note_raw_text ON (note_raw_text.id = note.note_raw_text_id)
|
||||||
LEFT JOIN attachment ON (note.id = attachment.note_id)
|
LEFT JOIN attachment ON (note.id = attachment.note_id)
|
||||||
LEFT JOIN user as shareUser ON (note.share_user_id = shareUser.id)
|
LEFT JOIN user as shareUser ON (note.share_user_id = shareUser.id)
|
||||||
WHERE note.user_id = ? AND note.id = ? LIMIT 1`, [userId, noteId])
|
LEFT JOIN note_tag ON (note.id = note_tag.note_id AND note_tag.user_id = ?)
|
||||||
|
LEFT JOIN tag ON (note_tag.tag_id = tag.id)
|
||||||
|
WHERE note.user_id = ? AND note.id = ? LIMIT 1`, [userId, userId, noteId])
|
||||||
|
|
||||||
})
|
})
|
||||||
.then((rows, fields) => {
|
.then((rows, fields) => {
|
||||||
|
@ -138,6 +138,33 @@ Tag.get = (userId, noteId) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get just tag string for note
|
||||||
|
//
|
||||||
|
Tag.fornote = (userId, noteId) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
|
||||||
|
|
||||||
|
db.promise()
|
||||||
|
.query(`SELECT GROUP_CONCAT(DISTINCT(tag.text) ORDER BY tag.text DESC) AS tags
|
||||||
|
FROM note_tag
|
||||||
|
LEFT JOIN tag ON (note_tag.tag_id = tag.id)
|
||||||
|
WHERE note_tag.note_id = ?
|
||||||
|
AND user_id = ?;
|
||||||
|
`, [noteId,userId])
|
||||||
|
.then((rows, fields) => {
|
||||||
|
|
||||||
|
//pull IDs out of returned results
|
||||||
|
// let ids = rows[0].map( item => {})
|
||||||
|
|
||||||
|
resolve( rows[0][0] ) //Return all tags found by query
|
||||||
|
})
|
||||||
|
.catch(console.log)
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get all tags for a note and concatinate into a string 'all, tags, like, this'
|
// Get all tags for a note and concatinate into a string 'all, tags, like, this'
|
||||||
//
|
//
|
||||||
|
@ -9,7 +9,7 @@ const speakeasy = require('speakeasy')
|
|||||||
|
|
||||||
let User = module.exports = {}
|
let User = module.exports = {}
|
||||||
|
|
||||||
const version = '3.3.1'
|
const version = '3.3.3'
|
||||||
|
|
||||||
//Login a user, if that user does not exist create them
|
//Login a user, if that user does not exist create them
|
||||||
//Issues login token
|
//Issues login token
|
||||||
|
@ -50,6 +50,12 @@ router.post('/get', function (req, res) {
|
|||||||
.then( data => res.send(data) )
|
.then( data => res.send(data) )
|
||||||
})
|
})
|
||||||
|
|
||||||
|
//Get the latest notes the user has created
|
||||||
|
router.post('/fornote', function (req, res) {
|
||||||
|
Tags.fornote(userId, req.body.noteId)
|
||||||
|
.then( data => res.send(data) )
|
||||||
|
})
|
||||||
|
|
||||||
//Get all the tags for this user in order of usage
|
//Get all the tags for this user in order of usage
|
||||||
router.post('/usertags', function (req, res) {
|
router.post('/usertags', function (req, res) {
|
||||||
Tags.userTags(userId, req.body.searchQuery, req.body.searchTags, req.body.fastFilters)
|
Tags.userTags(userId, req.body.searchQuery, req.body.searchTags, req.body.fastFilters)
|
||||||
|
Loading…
Reference in New Issue
Block a user