* Added fake site warning
* Fixed a bunch of style bugs for chrome browsers * Improved check box styles on desktop and mobile * Touch up tool tip styles. Only dark now. * Created a separate terms page * Added 2FA auth token options to login * Added tool tip displays to some buttons on editor * Added pinned and archived options to overflow menu * Changed shared note styles * Disabled Scroll into view * Made image display smaller when adding images to notes * Added a last used color option * Updated help page * Fixed spelling error on terms page * Added a big ass green label on the new note icon * Scratch pad now opens a note, which is the scratch pad * Added better 2fa guide * Added change password option * Added log out and log out all active sessions option * Added strict rate limiting on login and register actions * Added middleware to routes that force authentication to be accessed * Fixed bug that was causing shared notes to appear empty * Updated option now appears on shared notes after they are actually updated
This commit is contained in:
parent
e7d1cc7bc9
commit
3447b2e0e6
@ -1,9 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="app" :class="{ 'night-mode':($store.getters.getIsNightMode == 2) }">
|
<div id="app" :class="{ 'night-mode':($store.getters.getIsNightMode == 2) }">
|
||||||
|
|
||||||
<global-site-menu />
|
<div class="ui container" v-if="showFakeSite">
|
||||||
|
<div class="ui basic very padded segment">
|
||||||
|
<div class="ui inverted red segment">
|
||||||
|
<h1>WARNING - False site detected</h1>
|
||||||
|
<h2>The Domain for this website is not correct.</h2>
|
||||||
|
<h2>Only trust <a class="ui button" href="https://www.solidscribe.com">https://www.solidscribe.com</a></h2>
|
||||||
|
<h2>Do not any enter any personal information into this website.</h2>
|
||||||
|
<h2>You will be redirected to the correct domain in {{redirectSeconds}}</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<router-view />
|
|
||||||
|
<global-site-menu v-if="!showFakeSite" />
|
||||||
|
|
||||||
|
<router-view v-if="!showFakeSite" />
|
||||||
|
|
||||||
<global-notification />
|
<global-notification />
|
||||||
|
|
||||||
@ -22,7 +35,8 @@ export default {
|
|||||||
},
|
},
|
||||||
data: function(){
|
data: function(){
|
||||||
return {
|
return {
|
||||||
// loggedIn:
|
showFakeSite:false, //Incorrect domain detection
|
||||||
|
redirectSeconds: 15,
|
||||||
fetchingInProgress: false, //Prevent start getting token while fetch is in progress
|
fetchingInProgress: false, //Prevent start getting token while fetch is in progress
|
||||||
blockUntilNextRequest: false //If token was just renewed, don't fetch more until next request
|
blockUntilNextRequest: false //If token was just renewed, don't fetch more until next request
|
||||||
}
|
}
|
||||||
@ -112,6 +126,17 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted: function(){
|
mounted: function(){
|
||||||
|
|
||||||
|
const isDev = process.env['NODE_ENV'] == 'development'
|
||||||
|
if(window.location.hostname.toLowerCase() != "www.solidscribe.com" && !isDev){
|
||||||
|
this.showFakeSite = true
|
||||||
|
setInterval(() => {
|
||||||
|
this.redirectSeconds--
|
||||||
|
if(this.redirectSeconds == 0){
|
||||||
|
window.location.href = 'https://www.solidscribe.com'
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
//Update totals for entire app on event
|
//Update totals for entire app on event
|
||||||
this.$io.on('update_counts', () => {
|
this.$io.on('update_counts', () => {
|
||||||
console.log('Got event, update totals')
|
console.log('Got event, update totals')
|
||||||
|
@ -116,6 +116,9 @@ body {
|
|||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border-color: var(--dark_border_color);
|
border-color: var(--dark_border_color);
|
||||||
}
|
}
|
||||||
|
.ui.dividing.header {
|
||||||
|
border-bottom-color: var(--dark_border_color);
|
||||||
|
}
|
||||||
.ui.icon.input > i.icon {
|
.ui.icon.input > i.icon {
|
||||||
color: var(--text_color);
|
color: var(--text_color);
|
||||||
}
|
}
|
||||||
@ -251,6 +254,13 @@ i.green.icon.icon.icon.icon {
|
|||||||
z-index: 100;
|
z-index: 100;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
.text-container {
|
||||||
|
max-width: 1000px;
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
background-color: var(--small_element_bg_color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* squire text styles */
|
/* squire text styles */
|
||||||
.squire-box {
|
.squire-box {
|
||||||
@ -264,7 +274,7 @@ i.green.icon.icon.icon.icon {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 10px 15px 10px;
|
padding: 10px 15px 10px;
|
||||||
/*background: transparent;*/
|
/*background: transparent;*/
|
||||||
overflow-x: scroll;
|
overflow: hidden;
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
line-height: 1.8em;
|
line-height: 1.8em;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
@ -295,7 +305,7 @@ i.green.icon.icon.icon.icon {
|
|||||||
|
|
||||||
.note-card-text pre,
|
.note-card-text pre,
|
||||||
.squire-box pre {
|
.squire-box pre {
|
||||||
word-wrap: break-word;
|
/*word-wrap: break-word;*/
|
||||||
}
|
}
|
||||||
.note-card-text p,
|
.note-card-text p,
|
||||||
.squire-box p {
|
.squire-box p {
|
||||||
@ -307,6 +317,10 @@ i.green.icon.icon.icon.icon {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0 0 0 2.5em;
|
padding: 0 0 0 2.5em;
|
||||||
}
|
}
|
||||||
|
.note-card-text u,
|
||||||
|
.squire-box u {
|
||||||
|
text-decoration-color: var(--main-accent);
|
||||||
|
}
|
||||||
.note-card-text img {
|
.note-card-text img {
|
||||||
max-width:100%;
|
max-width:100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
@ -322,7 +336,12 @@ i.green.icon.icon.icon.icon {
|
|||||||
.squire-box li > p {
|
.squire-box li > p {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
.note-card-text ol,
|
||||||
|
.squire-box ol,
|
||||||
|
.note-card-text ul,
|
||||||
|
.squire-box ul {
|
||||||
|
margin: 8px 0 0 0;
|
||||||
|
}
|
||||||
.note-card-text ul > li,
|
.note-card-text ul > li,
|
||||||
.squire-box ul > li {
|
.squire-box ul > li {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -331,35 +350,53 @@ i.green.icon.icon.icon.icon {
|
|||||||
.note-card-text ul > li:before,
|
.note-card-text ul > li:before,
|
||||||
.squire-box ul > li:before {
|
.squire-box ul > li:before {
|
||||||
|
|
||||||
|
/*filled circle */
|
||||||
content: "\f111";
|
content: "\f111";
|
||||||
|
/*empty square*/
|
||||||
|
/*content: "\F0C8";*/
|
||||||
|
|
||||||
font-family: 'Icons';
|
font-family: 'Icons';
|
||||||
|
/*font-family: 'outline-icons';*/
|
||||||
backface-visibility: hidden;
|
backface-visibility: hidden;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
text-decoration: inherit;
|
text-decoration: inherit;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 1.4em;
|
font-size: 0.25em;
|
||||||
font-size: 0.75em;
|
|
||||||
|
|
||||||
height: 17px;
|
height: 100%;
|
||||||
width: 17px;
|
width: 20px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
||||||
left: -30px;
|
left: -25px;
|
||||||
/*border: 2px solid #444;*/
|
/*border: 2px solid #444;*/
|
||||||
/*border-radius: 4px;*/
|
/*border-radius: 4px;*/
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
top: 4px;
|
top: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
|
|
||||||
|
color: var(--text_color);
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
/* filled in check circle */
|
||||||
ul > li.active:before {
|
ul > li.active:before {
|
||||||
|
|
||||||
font-family: 'Icons';
|
font-family: 'Icons';
|
||||||
content: "\f058";
|
content: "\F14A";
|
||||||
color: var(--main-accent);
|
color: var(--main-accent);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
/* hover - transparent icon */
|
||||||
|
.squire-box ul > li:hover:not(.active):before {
|
||||||
|
font-family: 'outline-icons';
|
||||||
|
content: "\f14a";
|
||||||
|
opacity: 0.4;
|
||||||
|
|
||||||
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-title-display-card .divide,
|
.note-title-display-card .divide,
|
||||||
@ -447,27 +484,28 @@ i.green.icon.icon.icon.icon {
|
|||||||
min-height: 30px;
|
min-height: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*empty check box*/
|
||||||
.note-card-text ul > li:before,
|
.note-card-text ul > li:before,
|
||||||
.squire-box ul > li:before {
|
.squire-box ul > li:before,
|
||||||
|
.squire-box ul > li:hover:not(.active):before {
|
||||||
|
|
||||||
|
/*empty checkmark*/
|
||||||
|
/*font-family: 'Icons';*/
|
||||||
|
/*content: "\f058";*/
|
||||||
|
|
||||||
content: "\f111";
|
content: "\F0C8";
|
||||||
font-family: outline-icons;
|
font-family: 'outline-icons';
|
||||||
|
|
||||||
height: 24px;
|
|
||||||
width: 24px;
|
|
||||||
|
|
||||||
left: -40px;
|
left: -40px;
|
||||||
bottom: 0;
|
|
||||||
top: 0px;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
line-height: 0.9em;
|
|
||||||
font-size: 1.4em;
|
font-size: 1.4em;
|
||||||
|
opacity: 0.2;
|
||||||
}
|
}
|
||||||
|
/*Filled check box */
|
||||||
ul > li.active:before {
|
ul > li.active:before {
|
||||||
|
|
||||||
font-family: 'Icons';
|
font-family: 'Icons';
|
||||||
content: "\f058";
|
content: "\F14A";
|
||||||
|
|
||||||
color: var(--main-accent);
|
color: var(--main-accent);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
@ -539,36 +577,34 @@ i.green.icon.icon.icon.icon {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
content: '';
|
content: '';
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
width: 0.71428571em;
|
width: 10px;
|
||||||
height: 0.71428571em;
|
height: 10px;
|
||||||
background: #FFFFFF;
|
background: #1B1C1D;
|
||||||
-webkit-transform: rotate(45deg);
|
-webkit-transform: rotate(45deg);
|
||||||
transform: rotate(45deg);
|
transform: rotate(45deg);
|
||||||
z-index: 1901;
|
z-index: 1901;
|
||||||
-webkit-box-shadow: 1px 1px 0 0 #bababc;
|
|
||||||
box-shadow: 1px 1px 0 0 #bababc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Popup */
|
/* Popup */
|
||||||
[data-tooltip]:after {
|
[data-tooltip]:after {
|
||||||
|
min-width: 40px;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
content: attr(data-tooltip);
|
content: attr(data-tooltip);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
text-align: left;
|
text-align: center;
|
||||||
white-space: nowrap;
|
white-space: pre;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
border: 1px solid #D4D4D5;
|
border: 1px solid #D4D4D5;
|
||||||
line-height: 1.4285em;
|
line-height: 1.4285em;
|
||||||
max-width: none;
|
max-width: none;
|
||||||
background: #FFFFFF;
|
background: #1B1C1D;
|
||||||
padding: 0.833em 1em;
|
padding: 0.5em;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
color: rgba(0, 0, 0, 0.87);
|
/*color: var(--main-accent);*/
|
||||||
|
color: white;
|
||||||
border-radius: 0.28571429rem;
|
border-radius: 0.28571429rem;
|
||||||
-webkit-box-shadow: 0 2px 4px 0 rgba(34, 36, 38, 0.12), 0 2px 10px 0 rgba(34, 36, 38, 0.15);
|
|
||||||
box-shadow: 0 2px 4px 0 rgba(34, 36, 38, 0.12), 0 2px 10px 0 rgba(34, 36, 38, 0.15);
|
|
||||||
z-index: 1900;
|
z-index: 1900;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,7 +614,7 @@ i.green.icon.icon.icon.icon {
|
|||||||
right: auto;
|
right: auto;
|
||||||
bottom: 100%;
|
bottom: 100%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
background: #FFFFFF;
|
background: #1B1C1D;
|
||||||
margin-left: -0.07142857rem;
|
margin-left: -0.07142857rem;
|
||||||
margin-bottom: 0.14285714rem;
|
margin-bottom: 0.14285714rem;
|
||||||
}
|
}
|
||||||
@ -596,7 +632,7 @@ i.green.icon.icon.icon.icon {
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity 0.2s ease;
|
/*transition: opacity 0.2s ease;*/
|
||||||
}
|
}
|
||||||
[data-tooltip]:before {
|
[data-tooltip]:before {
|
||||||
-webkit-transform: rotate(45deg) scale(0) !important;
|
-webkit-transform: rotate(45deg) scale(0) !important;
|
||||||
@ -619,93 +655,13 @@ i.green.icon.icon.icon.icon {
|
|||||||
transform: rotate(45deg) scale(1) !important;
|
transform: rotate(45deg) scale(1) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Animation Position */
|
|
||||||
[data-tooltip]:after,
|
|
||||||
[data-tooltip][data-position="top center"]:after,
|
|
||||||
[data-tooltip][data-position="bottom center"]:after {
|
|
||||||
-webkit-transform: translateX(-50%) scale(0) !important;
|
|
||||||
transform: translateX(-50%) scale(0) !important;
|
|
||||||
}
|
|
||||||
[data-tooltip]:hover:after,
|
|
||||||
[data-tooltip][data-position="bottom center"]:hover:after {
|
|
||||||
-webkit-transform: translateX(-50%) scale(1) !important;
|
|
||||||
transform: translateX(-50%) scale(1) !important;
|
|
||||||
}
|
|
||||||
[data-tooltip][data-position="left center"]:after,
|
|
||||||
[data-tooltip][data-position="right center"]:after {
|
|
||||||
-webkit-transform: translateY(-50%) scale(0) !important;
|
|
||||||
transform: translateY(-50%) scale(0) !important;
|
|
||||||
}
|
|
||||||
[data-tooltip][data-position="left center"]:hover:after,
|
|
||||||
[data-tooltip][data-position="right center"]:hover:after {
|
|
||||||
-webkit-transform: translateY(-50%) scale(1) !important;
|
|
||||||
transform: translateY(-50%) scale(1) !important;
|
|
||||||
}
|
|
||||||
[data-tooltip][data-position="top left"]:after,
|
|
||||||
[data-tooltip][data-position="top right"]:after,
|
|
||||||
[data-tooltip][data-position="bottom left"]:after,
|
|
||||||
[data-tooltip][data-position="bottom right"]:after {
|
|
||||||
-webkit-transform: scale(0) !important;
|
|
||||||
transform: scale(0) !important;
|
|
||||||
}
|
|
||||||
[data-tooltip][data-position="top left"]:hover:after,
|
|
||||||
[data-tooltip][data-position="top right"]:hover:after,
|
|
||||||
[data-tooltip][data-position="bottom left"]:hover:after,
|
|
||||||
[data-tooltip][data-position="bottom right"]:hover:after {
|
|
||||||
-webkit-transform: scale(1) !important;
|
|
||||||
transform: scale(1) !important;
|
|
||||||
}
|
|
||||||
[data-tooltip][data-variation~="fixed"]:after {
|
|
||||||
white-space: normal;
|
|
||||||
width: 250px;
|
|
||||||
}
|
|
||||||
[data-tooltip][data-variation*="wide fixed"]:after {
|
|
||||||
width: 350px;
|
|
||||||
}
|
|
||||||
[data-tooltip][data-variation*="very wide fixed"]:after {
|
|
||||||
width: 550px;
|
|
||||||
}
|
|
||||||
@media only screen and (max-width: 767.98px) {
|
|
||||||
[data-tooltip][data-variation~="fixed"]:after {
|
|
||||||
width: 250px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------
|
|
||||||
Inverted
|
|
||||||
---------------*/
|
|
||||||
|
|
||||||
|
|
||||||
/* Arrow */
|
|
||||||
[data-tooltip][data-inverted]:before {
|
|
||||||
-webkit-box-shadow: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Arrow Position */
|
|
||||||
[data-tooltip][data-inverted]:before {
|
|
||||||
background: #1B1C1D;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Popup */
|
|
||||||
[data-tooltip][data-inverted]:after {
|
|
||||||
background: #1B1C1D;
|
|
||||||
color: #FFFFFF;
|
|
||||||
border: none;
|
|
||||||
-webkit-box-shadow: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
[data-tooltip][data-inverted]:after .header {
|
|
||||||
background: none;
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------
|
/*--------------
|
||||||
Position
|
Position
|
||||||
---------------*/
|
---------------*/
|
||||||
|
|
||||||
[data-position~="top"][data-tooltip]:before {
|
[data-position~="top"][data-tooltip]:before {
|
||||||
background: #FFFFFF;
|
background: #1B1C1D;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Top Center */
|
/* Top Center */
|
||||||
@ -723,7 +679,7 @@ i.green.icon.icon.icon.icon {
|
|||||||
right: auto;
|
right: auto;
|
||||||
bottom: 100%;
|
bottom: 100%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
background: #FFFFFF;
|
background: #1B1C1D;
|
||||||
margin-left: -0.07142857rem;
|
margin-left: -0.07142857rem;
|
||||||
margin-bottom: 0.14285714rem;
|
margin-bottom: 0.14285714rem;
|
||||||
}
|
}
|
||||||
@ -762,7 +718,7 @@ i.green.icon.icon.icon.icon {
|
|||||||
margin-bottom: 0.14285714rem;
|
margin-bottom: 0.14285714rem;
|
||||||
}
|
}
|
||||||
[data-position~="bottom"][data-tooltip]:before {
|
[data-position~="bottom"][data-tooltip]:before {
|
||||||
background: #FFFFFF;
|
background: #1B1C1D;
|
||||||
-webkit-box-shadow: -1px -1px 0 0 #bababc;
|
-webkit-box-shadow: -1px -1px 0 0 #bababc;
|
||||||
box-shadow: -1px -1px 0 0 #bababc;
|
box-shadow: -1px -1px 0 0 #bababc;
|
||||||
}
|
}
|
||||||
@ -781,7 +737,7 @@ i.green.icon.icon.icon.icon {
|
|||||||
bottom: auto;
|
bottom: auto;
|
||||||
right: auto;
|
right: auto;
|
||||||
top: 100%;
|
top: 100%;
|
||||||
left: 50%;
|
left: 30%;
|
||||||
margin-left: -0.07142857rem;
|
margin-left: -0.07142857rem;
|
||||||
margin-top: 0.14285714rem;
|
margin-top: 0.14285714rem;
|
||||||
}
|
}
|
||||||
@ -829,9 +785,7 @@ i.green.icon.icon.icon.icon {
|
|||||||
top: 50%;
|
top: 50%;
|
||||||
margin-top: -0.14285714rem;
|
margin-top: -0.14285714rem;
|
||||||
margin-right: -0.07142857rem;
|
margin-right: -0.07142857rem;
|
||||||
background: #FFFFFF;
|
background: #1B1C1D;
|
||||||
-webkit-box-shadow: 1px -1px 0 0 #bababc;
|
|
||||||
box-shadow: 1px -1px 0 0 #bababc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Right Center */
|
/* Right Center */
|
||||||
@ -847,30 +801,9 @@ i.green.icon.icon.icon.icon {
|
|||||||
top: 50%;
|
top: 50%;
|
||||||
margin-top: -0.07142857rem;
|
margin-top: -0.07142857rem;
|
||||||
margin-left: 0.14285714rem;
|
margin-left: 0.14285714rem;
|
||||||
background: #FFFFFF;
|
background: #1B1C1D;
|
||||||
-webkit-box-shadow: -1px 1px 0 0 #bababc;
|
|
||||||
box-shadow: -1px 1px 0 0 #bababc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Inverted Arrow Color */
|
|
||||||
[data-inverted][data-position~="bottom"][data-tooltip]:before {
|
|
||||||
background: #1B1C1D;
|
|
||||||
-webkit-box-shadow: -1px -1px 0 0 #bababc;
|
|
||||||
box-shadow: -1px -1px 0 0 #bababc;
|
|
||||||
}
|
|
||||||
[data-inverted][data-position="left center"][data-tooltip]:before {
|
|
||||||
background: #1B1C1D;
|
|
||||||
-webkit-box-shadow: 1px -1px 0 0 #bababc;
|
|
||||||
box-shadow: 1px -1px 0 0 #bababc;
|
|
||||||
}
|
|
||||||
[data-inverted][data-position="right center"][data-tooltip]:before {
|
|
||||||
background: #1B1C1D;
|
|
||||||
-webkit-box-shadow: -1px 1px 0 0 #bababc;
|
|
||||||
box-shadow: -1px 1px 0 0 #bababc;
|
|
||||||
}
|
|
||||||
[data-inverted][data-position~="top"][data-tooltip]:before {
|
|
||||||
background: #1B1C1D;
|
|
||||||
}
|
|
||||||
[data-position~="bottom"][data-tooltip]:before {
|
[data-position~="bottom"][data-tooltip]:before {
|
||||||
-webkit-transform-origin: center bottom;
|
-webkit-transform-origin: center bottom;
|
||||||
transform-origin: center bottom;
|
transform-origin: center bottom;
|
||||||
@ -894,12 +827,4 @@ i.green.icon.icon.icon.icon {
|
|||||||
[data-position="right center"][data-tooltip]:after {
|
[data-position="right center"][data-tooltip]:after {
|
||||||
-webkit-transform-origin: left center;
|
-webkit-transform-origin: left center;
|
||||||
transform-origin: left center;
|
transform-origin: left center;
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------
|
|
||||||
Basic
|
|
||||||
---------------*/
|
|
||||||
|
|
||||||
[data-tooltip][data-variation~="basic"]:before {
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
@ -7,7 +7,7 @@
|
|||||||
min-height: 50px;
|
min-height: 50px;
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
max-width: calc(100% - 30px);
|
max-width: calc(100% - 30px);
|
||||||
z-index: 1002;
|
z-index: 1020;
|
||||||
|
|
||||||
box-shadow: 0px 0px 5px 2px rgba(140,140,140,1);
|
box-shadow: 0px 0px 5px 2px rgba(140,140,140,1);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
@ -86,7 +86,7 @@
|
|||||||
}
|
}
|
||||||
.place-holder {
|
.place-holder {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 50px;
|
height: 40px;
|
||||||
}
|
}
|
||||||
.logo-display {
|
.logo-display {
|
||||||
width: 27px;
|
width: 27px;
|
||||||
@ -273,11 +273,17 @@
|
|||||||
|
|
||||||
<div class="menu-section">
|
<div class="menu-section">
|
||||||
<router-link class="menu-item menu-button" exact-active-class="active" to="/help">
|
<router-link class="menu-item menu-button" exact-active-class="active" to="/help">
|
||||||
<i class="question circle outline icon"></i>Help | Terms
|
<i class="question circle outline icon"></i>Help
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="menu-section" v-if="loggedIn" :data-tooltip="`Settings for ${this.$store.getters.getUsername}`" data-inverted="" data-position="right center">
|
<div class="menu-section">
|
||||||
|
<router-link class="menu-item menu-button" exact-active-class="active" to="/terms">
|
||||||
|
<i class="info circle icon"></i>Terms
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="menu-section" v-if="loggedIn">
|
||||||
<router-link class="menu-item menu-button" exact-active-class="active" to="/settings">
|
<router-link class="menu-item menu-button" exact-active-class="active" to="/settings">
|
||||||
<i v-if="userIcon" class="cog icon"></i>{{ usernameDisplay }}
|
<i v-if="userIcon" class="cog icon"></i>{{ usernameDisplay }}
|
||||||
</router-link>
|
</router-link>
|
||||||
@ -365,7 +371,6 @@
|
|||||||
axios.post('/api/quick-note/get')
|
axios.post('/api/quick-note/get')
|
||||||
.then( ({data}) => {
|
.then( ({data}) => {
|
||||||
|
|
||||||
console.log(data)
|
|
||||||
this.$router.push({'path':'/notes/open/'+data.noteId})
|
this.$router.push({'path':'/notes/open/'+data.noteId})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
<div class="sixteen wide column">
|
<div class="sixteen wide column">
|
||||||
<span class="small-terms">
|
<span class="small-terms">
|
||||||
By signing up you agree to Solid Scribe's
|
By signing up you agree to Solid Scribe's
|
||||||
<router-link to="/help">
|
<router-link to="/terms">
|
||||||
Terms of Use
|
Terms of Use
|
||||||
</router-link>
|
</router-link>
|
||||||
</span>
|
</span>
|
||||||
@ -77,7 +77,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<span class="small-terms">
|
<span class="small-terms">
|
||||||
By signing up you agree to Solid Scribe's
|
By signing up you agree to Solid Scribe's
|
||||||
<router-link to="/help">
|
<router-link to="/terms">
|
||||||
Terms of Use
|
Terms of Use
|
||||||
</router-link>
|
</router-link>
|
||||||
</span>
|
</span>
|
||||||
@ -147,7 +147,7 @@
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
axios.post('/api/user/register', {'username': this.username, 'password': this.password})
|
axios.post('/api/public/register', {'username': this.username, 'password': this.password})
|
||||||
.then(({data}) => {
|
.then(({data}) => {
|
||||||
|
|
||||||
if(data == false){
|
if(data == false){
|
||||||
@ -167,7 +167,7 @@
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
axios.post('/api/user/login', {'username': this.username, 'password': this.password, 'authToken':this.authToken })
|
axios.post('/api/public/login', {'username': this.username, 'password': this.password, 'authToken':this.authToken })
|
||||||
.then(({data}) => {
|
.then(({data}) => {
|
||||||
|
|
||||||
//Enable 2FA on form
|
//Enable 2FA on form
|
||||||
@ -193,7 +193,7 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
this.$bus.$emit('notification', 'Unable to Login - Incorrect Username or Password')
|
this.$bus.$emit('notification', error)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<!-- 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 -->
|
||||||
<div
|
<div
|
||||||
id="InputNotes"
|
id="InputNotes"
|
||||||
class="master-note-edit full-focus position-0"
|
class="master-note-edit"
|
||||||
@keyup.esc="closeButtonAction()"
|
@keyup.esc="closeButtonAction()"
|
||||||
>
|
>
|
||||||
|
|
||||||
@ -13,47 +13,51 @@
|
|||||||
<div class="edit-spacer"></div>
|
<div class="edit-spacer"></div>
|
||||||
|
|
||||||
<div class="menu-top-half">
|
<div class="menu-top-half">
|
||||||
<div class="edit-button" v-on:click="closeButtonAction()" data-tooltip="Close" data-position="bottom center" data-inverted>
|
<div class="edit-button" v-on:click="closeButtonAction()" :data-tooltip="`Close\n(ESC)`" data-position="bottom center">
|
||||||
<i class="close icon"></i>
|
<i class="close icon"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="edit-divide"></div>
|
<div class="edit-divide"></div>
|
||||||
|
|
||||||
<div class="edit-button" v-on:click="toggleList('ul')" data-tooltip="Task List" data-position="bottom center" data-inverted :class="{'edit-active':activeToDo}">
|
<div class="edit-button" v-on:click="toggleList('ul')" :data-tooltip="`Task List\n(CTRL + SHIFT + 8)`" data-position="bottom center" :class="{'edit-active':activeToDo}">
|
||||||
<i class="tasks icon"></i>
|
<i class="tasks icon"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="edit-button" v-on:click="toggleList('ol')" data-tooltip="Numbered List" data-position="bottom center" data-inverted :class="{'edit-active':activeList}">
|
<div class="edit-button" v-on:click="toggleList('ol')" :data-tooltip="`Ordered List\n(CTRL + SHIFT + 9)`" data-position="bottom center" :class="{'edit-active':activeList}">
|
||||||
<i class="list ol icon"></i>
|
<i class="list ol icon"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="edit-divide"></div>
|
<div class="edit-divide"></div>
|
||||||
|
|
||||||
<div class="edit-button" v-on:click="colorpicker = true" data-tooltip="Text Color" data-position="bottom center" data-inverted :style="{'color':activeColor}">
|
<div class="edit-button" v-on:click="colorpicker = true" data-tooltip="Text Color" data-position="bottom center">
|
||||||
<i class="font icon"></i>
|
<i class="font icon"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="edit-button" v-on:click="toggleBold()" data-tooltip="Bold" data-position="bottom center" data-inverted :class="{'edit-active':activeBold}">
|
<div v-if="lastUsedColor" class="edit-button" v-on:click="applyLastUsedColor()" data-tooltip="Last Color" data-position="bottom center" :style="{'color':lastUsedColor}">
|
||||||
|
<i class="eye dropper icon"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="edit-button" v-on:click="toggleBold()" :data-tooltip="`Bold\n(CTRL + b)`" data-position="bottom center" :class="{'edit-active':activeBold}">
|
||||||
<i class="bold icon"></i>
|
<i class="bold icon"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="edit-button" v-on:click="toggleItalic()" data-tooltip="Italic" data-position="bottom center" data-inverted :class="{'edit-active':activeItalics}">
|
<div class="edit-button" v-on:click="toggleItalic()" :data-tooltip="`Italic\n(CRTL + i)`" data-position="bottom center" :class="{'edit-active':activeItalics}">
|
||||||
<i class="italic icon"></i>
|
<i class="italic icon"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="edit-button" v-on:click="toggleUnderline()" data-tooltip="Underline" data-position="bottom center" data-inverted :class="{'edit-active':activeUnderline}">
|
<div class="edit-button" v-on:click="toggleUnderline()" :data-tooltip="`Underline\n(CRTL + u)`" data-position="bottom center" :class="{'edit-active':activeUnderline}">
|
||||||
<i class="underline icon"></i>
|
<i class="underline icon"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="edit-button" v-on:click="modifyFont('1.4em')" data-tooltip="Title" data-position="bottom center" data-inverted :class="{'edit-active':activeTitle}">
|
<div class="edit-button" v-on:click="modifyFont('1.4em')" data-tooltip="Title" data-position="bottom center" :class="{'edit-active':activeTitle}">
|
||||||
<i class="text height icon"></i>
|
<i class="text height icon"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="edit-divide"></div>
|
<div class="edit-divide"></div>
|
||||||
|
|
||||||
<div class="edit-button" v-on:click="editor.increaseQuoteLevel()" data-tooltip="Indent" data-position="bottom center" data-inverted>
|
<div class="edit-button" v-on:click="editor.increaseQuoteLevel()" :data-tooltip="`Indent\n(TAB)`" data-position="bottom center">
|
||||||
<i class="indent icon"></i>
|
<i class="indent icon"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="edit-button" v-on:click="editor.decreaseQuoteLevel()" data-tooltip="Outdent" data-position="bottom center" data-inverted>
|
<div class="edit-button" v-on:click="editor.decreaseQuoteLevel()" :data-tooltip="`Un-Indent\n(SHIFT + TAB)`" data-position="bottom center">
|
||||||
<i class="outdent icon"></i>
|
<i class="outdent icon"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -61,60 +65,49 @@
|
|||||||
|
|
||||||
<div class="menu-bottom-half">
|
<div class="menu-bottom-half">
|
||||||
|
|
||||||
<div class="edit-button" v-on:click="$router.push(`/notes/open/${noteid}/menu/table`)" data-tooltip="Insert Table" data-position="bottom center" data-inverted>
|
<div class="edit-button" v-on:click="$router.push(`/notes/open/${noteid}/menu/table`)" data-tooltip="Insert Table" data-position="bottom center">
|
||||||
<i class="border all icon"></i>
|
<i class="border all icon"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="edit-button" v-on:click="insertDivide()" data-tooltip="Insert Divide" data-position="bottom center" data-inverted>
|
<div class="edit-button" v-on:click="insertDivide()" data-tooltip="Insert Divide" data-position="bottom center">
|
||||||
<i class="grip lines icon"></i>
|
<i class="grip lines icon"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="edit-button" v-on:click="removeFormatting()" data-tooltip="Remove Formatting" data-position="bottom center" data-inverted>
|
<div class="edit-button" v-on:click="removeFormatting()" data-tooltip="Remove Formatting" data-position="bottom center">
|
||||||
<i class="remove format icon"></i>
|
<i class="remove format icon"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="edit-button" v-on:click="undoCustom()" data-tooltip="Undo" data-position="bottom center" data-inverted>
|
<div class="edit-button" v-on:click="undoCustom()" :data-tooltip="`Undo\n(CTRL + z)`" data-position="bottom center">
|
||||||
<i class="undo icon"></i>
|
<i class="undo icon"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<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" data-inverted :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" data-inverted>
|
<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>
|
||||||
<div class="edit-button" v-on:click="$router.push(`/notes/open/${noteid}/menu/images`)" data-tooltip="Images" data-position="bottom center" data-inverted>
|
<div class="edit-button" v-on:click="$router.push(`/notes/open/${noteid}/menu/images`)" data-tooltip="Images" data-position="bottom center">
|
||||||
<i class="image icon"></i>
|
<i class="image icon"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<file-upload-button
|
<file-upload-button
|
||||||
data-tooltip="Upload File" data-position="bottom center" data-inverted
|
data-tooltip="Upload File" data-position="bottom center"
|
||||||
class="edit-button"
|
class="edit-button"
|
||||||
:noteId="noteid" />
|
:noteId="noteid" />
|
||||||
|
|
||||||
<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" data-inverted>
|
<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>
|
||||||
|
|
||||||
<!--
|
|
||||||
<div class="edit-button" v-on:click="onToggleArchived()" :data-tooltip="archived == 1?'Move to main list':'Move to Archive'" data-position="bottom center" data-inverted>
|
|
||||||
<span v-if="archived == 1"><i class="green archive icon"></i></span>
|
|
||||||
<span v-if="archived != 1"><i class="archive icon"></i></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="edit-button" v-on:click="onTogglePinned" :data-tooltip="pinned == 1?'Un-pin from top':'Pin to top'" data-position="bottom center" data-inverted>
|
<div class="edit-button" v-if="usersOnNote > 1" :data-tooltip="`Viewers`" data-position="bottom center">
|
||||||
<span v-if="pinned == 1"><i class="green pin icon"></i></span>
|
|
||||||
<span v-if="pinned != 1"><i class="pin icon"></i></span>
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
|
|
||||||
<div class="edit-button" v-if="usersOnNote > 1">
|
|
||||||
<i class="green eye icon"></i> {{ usersOnNote }}
|
<i class="green eye icon"></i> {{ usersOnNote }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -123,7 +116,7 @@
|
|||||||
<i class="purple bolt icon"></i>
|
<i class="purple bolt icon"></i>
|
||||||
</div> -->
|
</div> -->
|
||||||
|
|
||||||
<div class="edit-button" v-on:click=" hash=0; save() ">
|
<div class="edit-button" v-on:click=" hash=0; save() " :data-tooltip="`Save\n(CTRL + S)`" data-position="bottom center">
|
||||||
<i class="icons">
|
<i class="icons">
|
||||||
<i class="grey save outline icon"></i>
|
<i class="grey save outline icon"></i>
|
||||||
<i v-if="statusText == 'saved'" class="green small bottom left corner check icon"></i>
|
<i v-if="statusText == 'saved'" class="green small bottom left corner check icon"></i>
|
||||||
@ -131,7 +124,7 @@
|
|||||||
</i>
|
</i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="edit-button" v-if="diffsApplied > 0">
|
<div class="edit-button" v-if="diffsApplied > 0" :data-tooltip="`Unsaved Changes`" data-position="bottom center">
|
||||||
+{{ diffsApplied }}
|
+{{ diffsApplied }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -172,8 +165,8 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- little tags on the side -->
|
<!-- little tags on the side, only show on desktop -->
|
||||||
<div class="note-mini-tag-area" :class="{ 'size-down':sizeDown }">
|
<div class="note-mini-tag-area" :class="{ 'size-down':sizeDown }" v-if="!$store.getters.getIsUserOnMobile">
|
||||||
<span v-for="tag in allTags" class="subtle-tag active-mini-tag" v-if="isTagOnNote(tag.id)" v-on:click="removeTag(tag.id)">
|
<span v-for="tag in allTags" class="subtle-tag active-mini-tag" v-if="isTagOnNote(tag.id)" v-on:click="removeTag(tag.id)">
|
||||||
<i class="tag icon"></i>
|
<i class="tag icon"></i>
|
||||||
{{ tag.text }}
|
{{ tag.text }}
|
||||||
@ -222,7 +215,24 @@
|
|||||||
<div class="ui basic padded segment">
|
<div class="ui basic padded segment">
|
||||||
<div class="ui grid">
|
<div class="ui grid">
|
||||||
<div class="sixteen wide column">
|
<div class="sixteen wide column">
|
||||||
<h2>Additional Note Options</h2>
|
<h3>Note Options</h3>
|
||||||
|
</div>
|
||||||
|
<div class="eight wide column">
|
||||||
|
<div class="ui labeled icon fluid basic button" v-on:click="onToggleArchived()">
|
||||||
|
<i class="archive icon" :class="{'green':(archived == 1)}"></i>
|
||||||
|
<span v-if="archived == 1">Un-Archive Note</span>
|
||||||
|
<span v-if="archived != 1">Archive Note</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="eight wide column">
|
||||||
|
<div class="ui labeled icon fluid basic button" v-on:click="onTogglePinned">
|
||||||
|
<i class="pin icon" :class="{'green':(pinned == 1)}"></i>
|
||||||
|
<span v-if="pinned == 1">Un-Pin Note</span>
|
||||||
|
<span v-if="pinned != 1">Pin Note</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sixteen wide column">
|
||||||
|
<h3>List Options</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="sixteen wide column">
|
<div class="sixteen wide column">
|
||||||
<div class="ui labeled icon fluid basic button" v-on:click="sortList">
|
<div class="ui labeled icon fluid basic button" v-on:click="sortList">
|
||||||
@ -242,6 +252,9 @@
|
|||||||
Uncheck All
|
Uncheck All
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="sixteen wide column">
|
||||||
|
<h3>Misc Options</h3>
|
||||||
|
</div>
|
||||||
<div class="eight wide column">
|
<div class="eight wide column">
|
||||||
<div class="ui labeled icon fluid basic button" v-on:click="calculateMath" data-tooltip="Calculates algebra before '='">
|
<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>
|
||||||
@ -258,7 +271,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="sixteen wide column" v-if="rawTextId > 0">
|
<div class="sixteen wide column" v-if="rawTextId > 0">
|
||||||
<h2>Share Note</h2>
|
<h3>Share Note</h3>
|
||||||
<share-note-component
|
<share-note-component
|
||||||
:note-id="noteid"
|
:note-id="noteid"
|
||||||
:raw-text-id="rawTextId"
|
:raw-text-id="rawTextId"
|
||||||
@ -287,7 +300,7 @@
|
|||||||
<div class="full-focus-shade shade1"
|
<div class="full-focus-shade shade1"
|
||||||
:class="{ 'slide-out-left':sizeDown }"
|
:class="{ 'slide-out-left':sizeDown }"
|
||||||
v-on:click="closeButtonAction()"></div>
|
v-on:click="closeButtonAction()"></div>
|
||||||
<div class="full-focus-shade shade2"
|
<div class="full-focus-shade shade2"
|
||||||
:class="{ 'slide-out-right':sizeDown }"
|
:class="{ 'slide-out-right':sizeDown }"
|
||||||
v-on:click="closeButtonAction()"></div>
|
v-on:click="closeButtonAction()"></div>
|
||||||
|
|
||||||
@ -404,6 +417,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeMount(){
|
beforeMount(){
|
||||||
|
|
||||||
this.$bus.$on('new_file_upload', ({noteId, imageCode}) => {
|
this.$bus.$on('new_file_upload', ({noteId, imageCode}) => {
|
||||||
if(this.noteid == noteId && this.editor){
|
if(this.noteid == noteId && this.editor){
|
||||||
this.editor.moveCursorToEnd()
|
this.editor.moveCursorToEnd()
|
||||||
@ -438,6 +452,9 @@
|
|||||||
// document.addEventListener('visibilitychange', this.checkForUpdatedNote)
|
// document.addEventListener('visibilitychange', this.checkForUpdatedNote)
|
||||||
|
|
||||||
//Init squire as early as possible
|
//Init squire as early as possible
|
||||||
|
if(this.editor && this.editor.destroy){
|
||||||
|
this.editor.destroy()
|
||||||
|
}
|
||||||
this.editor = new Squire( this.$refs.squirebox, {blockTag: 'p' })
|
this.editor = new Squire( this.$refs.squirebox, {blockTag: 'p' })
|
||||||
|
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
@ -1052,10 +1069,11 @@
|
|||||||
titleResize(){
|
titleResize(){
|
||||||
//Resize the title field
|
//Resize the title field
|
||||||
let element = this.$refs.titleTextarea
|
let element = this.$refs.titleTextarea
|
||||||
let padding = 0
|
if(element){
|
||||||
|
|
||||||
element.style.height = 'auto'
|
element.style.height = 'auto'
|
||||||
element.style.height = (element.scrollHeight + padding) +'px'
|
element.style.height = (element.scrollHeight) +'px'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1072,7 +1090,7 @@
|
|||||||
background-color: var(--menu-accent);
|
background-color: var(--menu-accent);
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
opacity: 0.8;
|
opacity: 0.88;
|
||||||
}
|
}
|
||||||
.shade1 {
|
.shade1 {
|
||||||
left: 50%;
|
left: 50%;
|
||||||
@ -1089,7 +1107,8 @@
|
|||||||
left: 15%;
|
left: 15%;
|
||||||
right: 15%;
|
right: 15%;
|
||||||
z-index: 1005;
|
z-index: 1005;
|
||||||
overflow-x: scroll;
|
overflow-y: scroll;
|
||||||
|
overflow-x: hidden;
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
scrollbar-color: transparent transparent;
|
scrollbar-color: transparent transparent;
|
||||||
}
|
}
|
||||||
@ -1248,20 +1267,20 @@
|
|||||||
}
|
}
|
||||||
/*End Settings manager styles */
|
/*End Settings manager styles */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* container styles change based on mobile and number of open screens */
|
/* container styles change based on mobile and number of open screens */
|
||||||
.master-note-edit {
|
/* .master-note-edit {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
z-index: 1001;
|
z-index: 1001;
|
||||||
|
left: 15%;
|
||||||
|
right: 15%;
|
||||||
|
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
scrollbar-color: transparent transparent;
|
scrollbar-color: transparent transparent;
|
||||||
}
|
}*/
|
||||||
.loading-note {
|
.loading-note {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
@ -1282,19 +1301,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* One note open, in the middle of the screen */
|
/* One note open, in the middle of the screen */
|
||||||
.master-note-edit.position-0 {
|
|
||||||
left: 50%;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
.master-note-edit.full-focus {
|
|
||||||
left: 15%;
|
|
||||||
right: 15%;
|
|
||||||
}
|
|
||||||
.side-menu-open {
|
.side-menu-open {
|
||||||
left: calc(50% + 10px) !important;
|
left: calc(50% + 10px) !important;
|
||||||
right: calc(0% + 10px) !important;
|
right: calc(0% + 10px) !important;
|
||||||
}
|
}
|
||||||
@media only screen and (max-width: 740px) {
|
@media only screen and (max-width: 740px) {
|
||||||
|
|
||||||
|
.master-note-edit {
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.input-container-wrapper {
|
.input-container-wrapper {
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
@ -1338,27 +1356,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Two Notes Open, each takes up 50% of the space */
|
|
||||||
.master-note-edit.position-1 {
|
|
||||||
left: 50%;
|
|
||||||
right: 0%;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.master-note-edit.position-2 {
|
|
||||||
left: 0%;
|
|
||||||
right: 50%;
|
|
||||||
}
|
|
||||||
.master-note-edit.position-3 {
|
|
||||||
display: inline-block;
|
|
||||||
position: inherit;
|
|
||||||
width: 100%;
|
|
||||||
min-height: 200px;
|
|
||||||
height: auto;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* animations START */
|
/* animations START */
|
||||||
|
|
||||||
.slide-out-top {
|
.slide-out-top {
|
||||||
|
@ -8,17 +8,6 @@
|
|||||||
<!-- Show title and snippet below it -->
|
<!-- Show title and snippet below it -->
|
||||||
<div class="overflow-hidden note-card-text" @click="cardClicked" v-if="!titleView">
|
<div class="overflow-hidden note-card-text" @click="cardClicked" v-if="!titleView">
|
||||||
|
|
||||||
<span class="subtext" v-if="note.shareUsername">
|
|
||||||
Shared by {{ note.shareUsername }}
|
|
||||||
|
|
||||||
<span v-if="note.opened == null && !beenClicked" class="ui tiny green compact right floated button">
|
|
||||||
New
|
|
||||||
</span>
|
|
||||||
<span v-else-if="note.updated > note.opened && !beenClicked" class="ui tiny green compact right floated basic button">
|
|
||||||
Updated
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span v-if="note.title == '' && note.subtext == ''">
|
<span v-if="note.title == '' && note.subtext == ''">
|
||||||
Empty Note
|
Empty Note
|
||||||
</span>
|
</span>
|
||||||
@ -42,9 +31,22 @@
|
|||||||
Locked
|
Locked
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Shared Details -->
|
||||||
<span class="subtext" v-if="note.shared == 2">
|
<span class="subtext" v-if="note.shared == 2">
|
||||||
You Shared this note
|
<i class="green paper plane outline icon"></i> Shared
|
||||||
<span v-if="note.updated > note.opened && !beenClicked" class="ui tiny green compact right floated basic button">
|
<span v-if="note.updated/1000 > note.opened && !beenClicked" class="ui tiny green compact right floated basic button">
|
||||||
|
Updated
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span class="subtext" v-if="note.shareUsername">
|
||||||
|
<i class="green paper plane outline icon"></i> Shared by {{ note.shareUsername }}
|
||||||
|
|
||||||
|
<span v-if="note.opened == null && !beenClicked" class="ui tiny green compact right floated button">
|
||||||
|
New
|
||||||
|
</span>
|
||||||
|
<span v-else-if="note.updated/1000 > note.opened && !beenClicked" class="ui tiny green compact right floated basic button">
|
||||||
Updated
|
Updated
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
@ -235,11 +237,11 @@
|
|||||||
justClosed(){
|
justClosed(){
|
||||||
|
|
||||||
// Scroll note into view
|
// Scroll note into view
|
||||||
this.$el.scrollIntoView({
|
// this.$el.scrollIntoView({
|
||||||
behavior: 'smooth',
|
// behavior: 'smooth',
|
||||||
block: 'center',
|
// block: 'center',
|
||||||
inline: 'center'
|
// inline: 'center'
|
||||||
})
|
// })
|
||||||
|
|
||||||
//After scroll, trigger green outline animation
|
//After scroll, trigger green outline animation
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.img-row {
|
.img-row {
|
||||||
height: 30vh;
|
height: 20vh;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
.colors {
|
.colors {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 1023;
|
z-index: 1023;
|
||||||
top: 42px;
|
top: 5px;
|
||||||
/*height: 100px;*/
|
/*height: 100px;*/
|
||||||
/*width: 415px;*/
|
width: 400px;
|
||||||
left: 0;
|
left: 20%;
|
||||||
}
|
}
|
||||||
.colors-container {
|
.colors-container {
|
||||||
max-width: 370px;
|
max-width: 370px;
|
||||||
|
@ -9,6 +9,8 @@ const SquireButtonFunctions = {
|
|||||||
activeList: false,
|
activeList: false,
|
||||||
activeToDo: false,
|
activeToDo: false,
|
||||||
activeColor: null,
|
activeColor: null,
|
||||||
|
//
|
||||||
|
lastUsedColor: null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -49,7 +51,10 @@ const SquireButtonFunctions = {
|
|||||||
if(colorIndex > -1){
|
if(colorIndex > -1){
|
||||||
//Get all digigs after color index, then limit to 3
|
//Get all digigs after color index, then limit to 3
|
||||||
let colors = e.path.substring(colorIndex).match(/\d+/g).slice(0,3)
|
let colors = e.path.substring(colorIndex).match(/\d+/g).slice(0,3)
|
||||||
this.activeColor=`rgb(${colors.join(',')})`
|
|
||||||
|
const lastColor = `rgb(${colors.join(',')})`
|
||||||
|
this.activeColor = lastColor
|
||||||
|
this.lastUsedColor = lastColor
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -93,6 +98,11 @@ const SquireButtonFunctions = {
|
|||||||
this.selectLineIfNoSelect()
|
this.selectLineIfNoSelect()
|
||||||
//Set color of font
|
//Set color of font
|
||||||
this.editor.setTextColour(color)
|
this.editor.setTextColour(color)
|
||||||
|
|
||||||
|
this.lastUsedColor = color
|
||||||
|
},
|
||||||
|
applyLastUsedColor(){
|
||||||
|
this.modifyColor(this.lastUsedColor)
|
||||||
},
|
},
|
||||||
toggleList(type){
|
toggleList(type){
|
||||||
|
|
||||||
|
File diff suppressed because one or more lines are too long
@ -19,7 +19,7 @@
|
|||||||
v-if="$store.getters.totals && ($store.getters.totals['youGotMailCount'] > 0)"
|
v-if="$store.getters.totals && ($store.getters.totals['youGotMailCount'] > 0)"
|
||||||
style="position: relative;">
|
style="position: relative;">
|
||||||
<i class="green mail icon"></i>Inbox
|
<i class="green mail icon"></i>Inbox
|
||||||
+{{ $store.getters.totals['youGotMailCount'] }}
|
<span class="tiny circular floating ui green label">+{{ $store.getters.totals['youGotMailCount'] }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<tag-display
|
<tag-display
|
||||||
|
@ -1,129 +1,162 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="ui grid">
|
<div class="squire-box">
|
||||||
<div class="row"></div>
|
<div class="">
|
||||||
<!-- spacer column -->
|
|
||||||
<div class="sixteen wide column">
|
|
||||||
<h2 class="ui dividing header">
|
|
||||||
<i class="cog icon"></i>
|
|
||||||
Settings
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div class="ui segment">
|
<h3 class="ui dividing header">
|
||||||
<h3>Change Password</h3>
|
<i class="green cog icon"></i>
|
||||||
<p>Create a new scratch pad. Old scratch pad will turn into a normal note.</p>
|
Settings
|
||||||
<div class="ui compact basic button shrinking" v-if="!showNewNoteConfirm" v-on:click="showNewNoteConfirm = true">
|
</h3>
|
||||||
<i class="sync alternate reload icon"></i>
|
|
||||||
New Scratch Pad
|
|
||||||
</div>
|
|
||||||
<div v-if="showNewNoteConfirm" class="ui compact basic button shrinking" v-on:click="showNewNoteConfirm = false">
|
|
||||||
<i class="close icon"></i>
|
|
||||||
Cancel
|
|
||||||
</div>
|
|
||||||
<div v-if="showNewNoteConfirm" class="ui compact basic button shrinking" v-on:click="newQuickNote()">
|
|
||||||
<i class="green thumbs up icon"></i>
|
|
||||||
Confirm
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Accent Color -->
|
<h4>New Scratch Pad</h4>
|
||||||
<div class="ui segment">
|
<div class="ui segment">
|
||||||
<div class="ui grid">
|
<p>Create a new scratch pad. Old scratch pad will turn into a normal note.</p>
|
||||||
<div class="sixteen wide column">
|
<div class="ui compact basic button shrinking" v-if="!showNewNoteConfirm" v-on:click="showNewNoteConfirm = true">
|
||||||
<h3 class="ui header">
|
<i class="sync alternate reload icon"></i>
|
||||||
Accent Color
|
New Scratch Pad
|
||||||
</h3>
|
</div>
|
||||||
<div
|
<div v-if="showNewNoteConfirm" class="ui compact basic button shrinking" v-on:click="showNewNoteConfirm = false">
|
||||||
v-for="color in themeColors"
|
<i class="close icon"></i>
|
||||||
class="ui compact basic button"
|
Cancel
|
||||||
:style="`background: linear-gradient(0deg, ${color} 4%, rgba(0,0,0,0) 5%);`"
|
</div>
|
||||||
v-on:click="setAccentColor(color)">
|
<div v-if="showNewNoteConfirm" class="ui compact basic button shrinking" v-on:click="newQuickNote()">
|
||||||
<logo style="width: 33px; height: auto;" :color="color" />
|
<i class="green thumbs up icon"></i>
|
||||||
</div>
|
Confirm
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Enable Two Factor -->
|
|
||||||
<div class="ui segment">
|
|
||||||
<h3>Two Factor Authentication</h3>
|
|
||||||
<div class="ui stackable grid">
|
|
||||||
<div class="four wide column">
|
|
||||||
<p>1. Enter Password and get QR</p>
|
|
||||||
<div class="ui fluid action input">
|
|
||||||
<input type="password" placeholder="Current Password" v-model="password">
|
|
||||||
|
|
||||||
<div v-if="password.length == 0" class="ui disabled button">
|
|
||||||
Get QR code
|
|
||||||
</div>
|
|
||||||
<div v-if="password.length > 0" class="ui green button" v-on:click="getQrCode()">
|
|
||||||
Get QR code
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="five wide column">
|
|
||||||
<p>2. Scan QR Code</p>
|
|
||||||
<p v-if="qrCode == ''">QR Code Will appear here.</p>
|
|
||||||
<img v-if="qrCode != ''" :src="qrCode" alt="QR Code">
|
|
||||||
</div>
|
|
||||||
<div class="four wide column">
|
|
||||||
<p>3. Verify with code</p>
|
|
||||||
<div class="ui input" v-if="qrCode != ''">
|
|
||||||
<input type="text" placeholder="Verification Code" v-model="verificationToken" v-on:keyup.enter="verifyQrCode()">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- change password -->
|
|
||||||
<div class="ui segment">
|
|
||||||
<h3>Change Password</h3>
|
|
||||||
<div class="ui grid">
|
|
||||||
<div class="five wide column">
|
|
||||||
<label>Current Password</label>
|
|
||||||
<div class="ui fluid input">
|
|
||||||
<input v-model="change1" type="password" placeholder="Current Password">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="five wide column">
|
|
||||||
<label>New Password</label>
|
|
||||||
<div class="ui fluid input">
|
|
||||||
<input v-model="change2" type="password" placeholder="New Password">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="six wide column">
|
|
||||||
<label>Rereat New Password</label>
|
|
||||||
<div class="ui fluid action input">
|
|
||||||
<input v-model="change3" type="password" placeholder="Repeat Password">
|
|
||||||
<div v-on:click="passwordChange()" class="ui button" :class="{'green':(change1.length > 0 && change2 == change3)}">
|
|
||||||
Change it!
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- log out -->
|
|
||||||
<div class="ui segment">
|
|
||||||
<div class="ui grid">
|
|
||||||
<div class="sixteen wide column">
|
|
||||||
<h3>Log Out</h3>
|
|
||||||
</div>
|
|
||||||
<div class="eight wide column">
|
|
||||||
<div class="ui button" v-on:click="logout()">
|
|
||||||
Log Out this browser
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="eight wide column">
|
|
||||||
<div class="ui button" v-on:click="revokeAllSessions()">
|
|
||||||
Log Out all other browsers
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Accent Color -->
|
||||||
|
<h4 class="ui header">
|
||||||
|
Accent Color
|
||||||
|
</h4>
|
||||||
|
<div class="ui segment">
|
||||||
|
<div class="ui doubling grid">
|
||||||
|
<div class="sixteen wide column">
|
||||||
|
<p>Theme changes are only saved to this browser.</p>
|
||||||
|
<div
|
||||||
|
v-for="color in themeColors"
|
||||||
|
class="ui compact basic button"
|
||||||
|
:style="`background: linear-gradient(0deg, ${color} 4%, rgba(0,0,0,0) 5%);`"
|
||||||
|
v-on:click="setAccentColor(color)">
|
||||||
|
<logo style="width: 33px; height: auto;" :color="color" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Enable Two Factor -->
|
||||||
|
<h4>Two Factor Authentication</h4>
|
||||||
|
<div class="ui segment">
|
||||||
|
<div class="ui stackable grid">
|
||||||
|
<div class="six wide column">
|
||||||
|
<p>1. Enter Password and get QR</p>
|
||||||
|
<div class="ui fluid action input">
|
||||||
|
<input type="password" placeholder="Current Password" v-model="password">
|
||||||
|
|
||||||
|
<div v-if="password.length == 0" class="ui disabled button">
|
||||||
|
Get QR code
|
||||||
|
</div>
|
||||||
|
<div v-if="password.length > 0" class="ui green button" v-on:click="getQrCode()">
|
||||||
|
Get QR code
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="four wide column">
|
||||||
|
<p>2. Scan QR Code</p>
|
||||||
|
<p v-if="qrCode == ''">(QR Code will appear here)</p>
|
||||||
|
<img v-if="qrCode != ''" :src="qrCode" alt="QR Code">
|
||||||
|
</div>
|
||||||
|
<div class="six wide column">
|
||||||
|
<p>3. Verify with code</p>
|
||||||
|
<div class="ui fluid action input" v-if="qrCode != ''">
|
||||||
|
<input type="text" placeholder="Verification Code" v-model="verificationToken" v-on:keyup.enter="verifyQrCode()">
|
||||||
|
<div class="ui green button">
|
||||||
|
Verify!
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui fluid action input" v-if="qrCode == ''">
|
||||||
|
<input type="text" placeholder="Verification Code" >
|
||||||
|
<div class="ui disabled button">
|
||||||
|
Verify!
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- change password -->
|
||||||
|
<h4>Change Password</h4>
|
||||||
|
<div class="ui segment">
|
||||||
|
<div class="ui stackable grid">
|
||||||
|
<div class="five wide column">
|
||||||
|
<p>Current Password</p>
|
||||||
|
<div class="ui fluid input">
|
||||||
|
<input v-model="change1" type="password" placeholder="Current Password">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="five wide column">
|
||||||
|
<p>New Password</p>
|
||||||
|
<div class="ui fluid input">
|
||||||
|
<input v-model="change2" type="password" placeholder="New Password">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="six wide column">
|
||||||
|
<p>Rereat New Password</p>
|
||||||
|
<div class="ui fluid action input">
|
||||||
|
<input v-model="change3" type="password" placeholder="Repeat Password">
|
||||||
|
<div v-on:click="passwordChange()" class="ui button" :class="{'green':(change1.length > 0 && change2 == change3)}">
|
||||||
|
Change it!
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- log out -->
|
||||||
|
<h4>Log Out</h4>
|
||||||
|
<div class="ui segment">
|
||||||
|
<div class="ui stackable grid">
|
||||||
|
<div class="eight wide column">
|
||||||
|
<div class="ui button" v-on:click="logout()">
|
||||||
|
<i class="power off icon"></i>
|
||||||
|
Log Out on this browser
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="eight wide column">
|
||||||
|
<div class="ui button" v-on:click="revokeAllSessions()">
|
||||||
|
<i class="sign out icon"></i>
|
||||||
|
Log Out all other browsers
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h4>Export All Data (In Development)</h4>
|
||||||
|
<div class="ui segment">
|
||||||
|
<p>Download all files and notes in raw text or html</p>
|
||||||
|
<div class="ui button">Export all Data</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h4>Delete Account (In Development)</h4>
|
||||||
|
<div class="ui segment">
|
||||||
|
<div class="ui stackable grid">
|
||||||
|
<div class="eight wide column">
|
||||||
|
<p>Delete all data. This can not be undone.</p>
|
||||||
|
<div class="ui fluid input">
|
||||||
|
<input type="password" placeholder="Current Password" v-model="password">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="four wide bottom aligned column">
|
||||||
|
<div class="ui fluid button">Verify</div>
|
||||||
|
</div>
|
||||||
|
<div class="four wide bottom aligned column">
|
||||||
|
<div class="ui disabled fluid button">Delete Account</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
17
client/src/pages/TermsPage.vue
Normal file
17
client/src/pages/TermsPage.vue
Normal file
File diff suppressed because one or more lines are too long
@ -6,6 +6,7 @@ import Router from 'vue-router'
|
|||||||
const HomePage = () => import(/* webpackChunkName: "HomePage" */ '@/pages/HomePage')
|
const HomePage = () => import(/* webpackChunkName: "HomePage" */ '@/pages/HomePage')
|
||||||
const LoginPage = () => import(/* webpackChunkName: "LoginPage" */ '@/pages/LoginPage')
|
const LoginPage = () => import(/* webpackChunkName: "LoginPage" */ '@/pages/LoginPage')
|
||||||
const HelpPage = () => import(/* webpackChunkName: "HelpPage" */ '@/pages/HelpPage')
|
const HelpPage = () => import(/* webpackChunkName: "HelpPage" */ '@/pages/HelpPage')
|
||||||
|
const TermsPage = () => import(/* webpackChunkName: "TermsPage" */ '@/pages/TermsPage')
|
||||||
const SettingsPage = () => import(/* webpackChunkName: "SettingsPage" */ '@/pages/SettingsPage')
|
const SettingsPage = () => import(/* webpackChunkName: "SettingsPage" */ '@/pages/SettingsPage')
|
||||||
const SharePage = () => import(/* webpackChunkName: "SharePage" */ '@/pages/SharePage')
|
const SharePage = () => import(/* webpackChunkName: "SharePage" */ '@/pages/SharePage')
|
||||||
const NotesPage = () => import(/* webpackChunkName: "NotesPage" */ '@/pages/NotesPage')
|
const NotesPage = () => import(/* webpackChunkName: "NotesPage" */ '@/pages/NotesPage')
|
||||||
@ -53,7 +54,13 @@ export default new Router({
|
|||||||
meta: {title:'Help'},
|
meta: {title:'Help'},
|
||||||
component: HelpPage
|
component: HelpPage
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
path: '/terms',
|
||||||
|
name: 'Terms',
|
||||||
|
meta: {title:'Terms'},
|
||||||
|
component: TermsPage
|
||||||
|
},
|
||||||
|
{
|
||||||
path: '/settings',
|
path: '/settings',
|
||||||
name: 'Settings',
|
name: 'Settings',
|
||||||
meta: {title:'Settings'},
|
meta: {title:'Settings'},
|
||||||
|
@ -21,17 +21,17 @@ const port = 3000
|
|||||||
//
|
//
|
||||||
// Request Rate Limiter
|
// Request Rate Limiter
|
||||||
//
|
//
|
||||||
const rateLimit = require('express-rate-limit');
|
const rateLimit = require('express-rate-limit')
|
||||||
|
//Limiter for the entire app
|
||||||
const limiter = rateLimit({
|
const limiter = rateLimit({
|
||||||
windowMs: 10 * 60 * 1000, // minutes
|
windowMs: 10 * 60 * 1000, // 10 minutes
|
||||||
max: 1000 // limit each IP to 100 requests per windowMs
|
max: 1000 // limit each IP to 1000 requests per windowMs
|
||||||
});
|
})
|
||||||
|
|
||||||
// apply to all requests
|
// apply to all requests
|
||||||
app.use(limiter);
|
app.use(limiter);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var http = require('http').createServer(app);
|
var http = require('http').createServer(app);
|
||||||
var io = require('socket.io')(http, {
|
var io = require('socket.io')(http, {
|
||||||
path:'/socket'
|
path:'/socket'
|
||||||
@ -222,6 +222,7 @@ app.use(express.json({limit: '5mb'}))
|
|||||||
app.use(function(req, res, next){
|
app.use(function(req, res, next){
|
||||||
|
|
||||||
//Always null out master key, never allow it set from outside
|
//Always null out master key, never allow it set from outside
|
||||||
|
req.headers.userId = null
|
||||||
req.headers.masterKey = null
|
req.headers.masterKey = null
|
||||||
req.headers.sessionId = null
|
req.headers.sessionId = null
|
||||||
|
|
||||||
@ -243,10 +244,7 @@ app.use(function(req, res, next){
|
|||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
|
||||||
console.log(error)
|
next('Unauthorized')
|
||||||
|
|
||||||
res.statusMessage = error //Throw 400 error if token is bad
|
|
||||||
res.status(400).end()
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
next() //No token. Move along.
|
next() //No token. Move along.
|
||||||
@ -260,13 +258,12 @@ 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.testTwoFactor()
|
|
||||||
|
|
||||||
Auth.test()
|
Auth.test()
|
||||||
UserTest.keyPairTest('genMan23', '1', printResults)
|
UserTest.keyPairTest('genMan25', '1', printResults)
|
||||||
.then( ({testUserId, masterKey}) => NoteTest.test(testUserId, masterKey, printResults))
|
.then( ({testUserId, masterKey}) => NoteTest.test(testUserId, masterKey, printResults))
|
||||||
.then( message => {
|
.then( message => {
|
||||||
if(printResults) console.log(message)
|
if(printResults) console.log(message)
|
||||||
|
Auth.testTwoFactor()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@ -303,4 +300,16 @@ app.use('/api/quick-note', quickNote)
|
|||||||
//Output running status
|
//Output running status
|
||||||
app.listen(port, () => {
|
app.listen(port, () => {
|
||||||
// console.log(`Listening on port ${port}!`)
|
// console.log(`Listening on port ${port}!`)
|
||||||
|
})
|
||||||
|
|
||||||
|
//
|
||||||
|
//Error handlers
|
||||||
|
//
|
||||||
|
//Default error handler just say unauthorized for everything
|
||||||
|
app.use(function (err, req, res, next) {
|
||||||
|
if (err) {
|
||||||
|
res.status(401).send('Unauthorized')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
next()
|
||||||
})
|
})
|
@ -449,8 +449,7 @@ Note.update = (userId, noteId, noteText, noteTitle, color, pinned, archived, has
|
|||||||
//Shared notes use encrypted key - decrypt key then decrypt note
|
//Shared notes use encrypted key - decrypt key then decrypt note
|
||||||
const encryptedShareKey = rows[0][0].encrypted_share_password_key
|
const encryptedShareKey = rows[0][0].encrypted_share_password_key
|
||||||
if(encryptedShareKey != null){
|
if(encryptedShareKey != null){
|
||||||
masterKey = crypto.privateDecrypt(userPrivateKey,
|
masterKey = crypto.privateDecrypt(userPrivateKey, Buffer.from(encryptedShareKey, 'base64') )
|
||||||
Buffer.from(encryptedShareKey, 'base64') )
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let encryptedNoteText = ''
|
let encryptedNoteText = ''
|
||||||
@ -475,10 +474,14 @@ Note.update = (userId, noteId, noteText, noteTitle, color, pinned, archived, has
|
|||||||
for (var i = 0; i < rows[0].length; i++) {
|
for (var i = 0; i < rows[0].length; i++) {
|
||||||
const otherNote = rows[0][i]
|
const otherNote = rows[0][i]
|
||||||
//Re-encrypt for other user
|
//Re-encrypt for other user
|
||||||
const updatedSnippet = cs.encrypt(masterKey, otherNote.snippet_salt, snippet)
|
let updatedSnippet = '' //Default to no snippet
|
||||||
|
if(noteText.length > 500){
|
||||||
|
updatedSnippet = cs.encrypt(masterKey, otherNote.snippet_salt, snippet)
|
||||||
|
}
|
||||||
db.promise().query('UPDATE note SET snippet = ? WHERE id = ?', [updatedSnippet, otherNote.id])
|
db.promise().query('UPDATE note SET snippet = ? WHERE id = ?', [updatedSnippet, otherNote.id])
|
||||||
|
.then((rows, fields) => {
|
||||||
SocketIo.to(otherNote['user_id']).emit('new_note_text_saved', {'noteId':otherNote.id, hash})
|
SocketIo.to(otherNote['user_id']).emit('new_note_text_saved', {'noteId':otherNote.id, hash})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -489,10 +492,13 @@ Note.update = (userId, noteId, noteText, noteTitle, color, pinned, archived, has
|
|||||||
})
|
})
|
||||||
.then( (rows, fields) => {
|
.then( (rows, fields) => {
|
||||||
|
|
||||||
|
//Set openend time to a minute ago
|
||||||
|
const theFuture = Math.round((+new Date)/1000) + 10
|
||||||
|
|
||||||
//Update other note attributes
|
//Update other note attributes
|
||||||
return db.promise()
|
return db.promise()
|
||||||
.query('UPDATE note SET pinned = ?, archived = ?, color = ?, snippet = ?, indexed = 0 WHERE id = ? AND user_id = ? LIMIT 1',
|
.query('UPDATE note SET pinned = ?, archived = ?, color = ?, snippet = ?, indexed = 0, opened = ? WHERE id = ? AND user_id = ? LIMIT 1',
|
||||||
[pinned, archived, color, noteSnippet, noteId, userId])
|
[pinned, archived, color, noteSnippet, theFuture, noteId, userId])
|
||||||
|
|
||||||
})
|
})
|
||||||
.then((rows, fields) => {
|
.then((rows, fields) => {
|
||||||
@ -750,7 +756,6 @@ Note.get = (userId, noteId, masterKey) => {
|
|||||||
})
|
})
|
||||||
.then((rows, fields) => {
|
.then((rows, fields) => {
|
||||||
|
|
||||||
const nowTime = Math.round((+new Date)/1000)
|
|
||||||
let noteLockedOut = false
|
let noteLockedOut = false
|
||||||
let noteData = rows[0][0]
|
let noteData = rows[0][0]
|
||||||
// const rawTextId = noteData['rawTextId']
|
// const rawTextId = noteData['rawTextId']
|
||||||
@ -776,6 +781,7 @@ Note.get = (userId, noteId, masterKey) => {
|
|||||||
noteData.title = textObject[0]
|
noteData.title = textObject[0]
|
||||||
noteData.text = textObject[1]
|
noteData.text = textObject[1]
|
||||||
|
|
||||||
|
const nowTime = Math.round((+new Date)/1000)
|
||||||
db.promise().query(`UPDATE note SET opened = ? WHERE (id = ?)`, [nowTime, noteId])
|
db.promise().query(`UPDATE note SET opened = ? WHERE (id = ?)`, [nowTime, noteId])
|
||||||
|
|
||||||
//Return note data
|
//Return note data
|
||||||
@ -1122,7 +1128,7 @@ Note.search = (userId, searchQuery, searchTags, fastFilters, masterKey) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
console.log('Error opening note id -> ', note.id)
|
console.log('Error opening note id -> '+note.id+' for userId -> '+userId)
|
||||||
console.log(err)
|
console.log(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ const speakeasy = require('speakeasy')
|
|||||||
|
|
||||||
let User = module.exports = {}
|
let User = module.exports = {}
|
||||||
|
|
||||||
const version = '3.1.5'
|
const version = '3.1.6'
|
||||||
|
|
||||||
//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
|
||||||
@ -498,6 +498,7 @@ User.deleteUser = (userId, password) => {
|
|||||||
|
|
||||||
let deletePromises = []
|
let deletePromises = []
|
||||||
|
|
||||||
|
//Delete all notes and raw text
|
||||||
let noteDelete = db.promise().query(`
|
let noteDelete = db.promise().query(`
|
||||||
DELETE note, note_raw_text
|
DELETE note, note_raw_text
|
||||||
FROM note
|
FROM note
|
||||||
@ -506,12 +507,14 @@ User.deleteUser = (userId, password) => {
|
|||||||
`,[userId])
|
`,[userId])
|
||||||
deletePromises.push(noteDelete)
|
deletePromises.push(noteDelete)
|
||||||
|
|
||||||
|
//Delete user entry
|
||||||
let userDelete = db.promise().query(`
|
let userDelete = db.promise().query(`
|
||||||
DELETE FROM user WHERE id = ?
|
DELETE FROM user WHERE id = ?
|
||||||
`,[userId])
|
`,[userId])
|
||||||
deletePromises.push(userDelete)
|
deletePromises.push(userDelete)
|
||||||
|
|
||||||
let tables = ['user_key', 'user_encrypted_search_index', 'attachment']
|
//Delete user_key, encrypted search index
|
||||||
|
let tables = ['user_key', 'user_encrypted_search_index']
|
||||||
tables.forEach(tableName => {
|
tables.forEach(tableName => {
|
||||||
|
|
||||||
const query = `DELETE FROM ${tableName} WHERE user_id = ?`
|
const query = `DELETE FROM ${tableName} WHERE user_id = ?`
|
||||||
@ -519,6 +522,8 @@ User.deleteUser = (userId, password) => {
|
|||||||
deletePromises.push(deleteQuery)
|
deletePromises.push(deleteQuery)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
//Remove all note attachments and files
|
||||||
|
|
||||||
return Promise.all(deletePromises)
|
return Promise.all(deletePromises)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,16 +6,23 @@ let router = express.Router()
|
|||||||
|
|
||||||
let Attachment = require('@models/Attachment')
|
let Attachment = require('@models/Attachment')
|
||||||
let Note = require('@models/Note')
|
let Note = require('@models/Note')
|
||||||
|
|
||||||
let userId = null
|
let userId = null
|
||||||
|
let masterKey = null
|
||||||
|
|
||||||
// middleware that is specific to this router
|
// middleware that is specific to this router
|
||||||
router.use(function setUserId (req, res, next) {
|
router.use(function setUserId (req, res, next) {
|
||||||
if(userId = req.headers.userId){
|
|
||||||
|
//Session key is required to continue
|
||||||
|
if(!req.headers.sessionId){
|
||||||
|
next('Unauthorized')
|
||||||
|
}
|
||||||
|
|
||||||
|
if(req.headers.userId){
|
||||||
userId = req.headers.userId
|
userId = req.headers.userId
|
||||||
masterKey = req.headers.masterKey
|
masterKey = req.headers.masterKey
|
||||||
|
next()
|
||||||
}
|
}
|
||||||
|
|
||||||
next()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
router.post('/search', function (req, res) {
|
router.post('/search', function (req, res) {
|
||||||
|
@ -10,12 +10,17 @@ let masterKey = null
|
|||||||
|
|
||||||
// middleware that is specific to this router
|
// middleware that is specific to this router
|
||||||
router.use(function setUserId (req, res, next) {
|
router.use(function setUserId (req, res, next) {
|
||||||
|
|
||||||
|
//Session key is required to continue
|
||||||
|
if(!req.headers.sessionId){
|
||||||
|
next('Unauthorized')
|
||||||
|
}
|
||||||
|
|
||||||
if(req.headers.userId){
|
if(req.headers.userId){
|
||||||
userId = req.headers.userId
|
userId = req.headers.userId
|
||||||
masterKey = req.headers.masterKey
|
masterKey = req.headers.masterKey
|
||||||
|
next()
|
||||||
}
|
}
|
||||||
|
|
||||||
next()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1,17 +1,60 @@
|
|||||||
var express = require('express')
|
var express = require('express')
|
||||||
var router = express.Router()
|
var router = express.Router()
|
||||||
|
const rateLimit = require('express-rate-limit')
|
||||||
|
|
||||||
|
const Note = require('@models/Note')
|
||||||
|
const User = require('@models/User')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let Note = require('@models/Note')
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Public Note action
|
// Public Note action
|
||||||
//
|
//
|
||||||
router.post('/opensharednote', function (req, res) {
|
const sharedNoteLimiter = rateLimit({
|
||||||
|
windowMs: 30 * 60 * 1000, //30 min window
|
||||||
|
max: 50, // start blocking after 50 requests
|
||||||
|
message:'Unable to open that many shared notes'
|
||||||
|
})
|
||||||
|
router.post('/opensharednote', sharedNoteLimiter, function (req, res) {
|
||||||
|
|
||||||
Note.getShared(req.body.noteId, req.body.sharedKey)
|
Note.getShared(req.body.noteId, req.body.sharedKey)
|
||||||
.then(results => res.send(results))
|
.then(results => res.send(results))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
//
|
||||||
|
// Login User
|
||||||
|
//
|
||||||
|
const loginLimiter = rateLimit({
|
||||||
|
windowMs: 30 * 60 * 1000, // 30 min window
|
||||||
|
max: 25, // start blocking after 25 requests
|
||||||
|
message:'Please try to login again later'
|
||||||
|
})
|
||||||
|
router.post('/login', loginLimiter, function (req, res) {
|
||||||
|
|
||||||
|
User.login(req.body.username, req.body.password, req.body.authToken)
|
||||||
|
.then( returnData => {
|
||||||
|
|
||||||
|
res.send(returnData)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
//
|
||||||
|
// Register User
|
||||||
|
//
|
||||||
|
const registerLimiter = rateLimit({
|
||||||
|
windowMs: 60 * 60 * 1000, // 1 hour window
|
||||||
|
max: 5, // start blocking after 5 requests
|
||||||
|
message:'Please try again to create an acount in an hour'
|
||||||
|
})
|
||||||
|
router.post('/register', registerLimiter, function (req, res) {
|
||||||
|
|
||||||
|
User.register(req.body.username, req.body.password)
|
||||||
|
.then( returnData => {
|
||||||
|
|
||||||
|
res.send(returnData)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,13 +6,19 @@ let QuickNote = require('@models/QuickNote');
|
|||||||
let userId = null
|
let userId = null
|
||||||
let masterKey = null
|
let masterKey = null
|
||||||
|
|
||||||
|
// middleware that is specific to this router
|
||||||
router.use(function setUserId (req, res, next) {
|
router.use(function setUserId (req, res, next) {
|
||||||
|
|
||||||
|
//Session key is required to continue
|
||||||
|
if(!req.headers.sessionId){
|
||||||
|
next('Unauthorized')
|
||||||
|
}
|
||||||
|
|
||||||
if(req.headers.userId){
|
if(req.headers.userId){
|
||||||
userId = req.headers.userId
|
userId = req.headers.userId
|
||||||
masterKey = req.headers.masterKey
|
masterKey = req.headers.masterKey
|
||||||
|
next()
|
||||||
}
|
}
|
||||||
|
|
||||||
next()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
//Get quick note text
|
//Get quick note text
|
||||||
|
@ -1,16 +1,24 @@
|
|||||||
var express = require('express')
|
var express = require('express')
|
||||||
var router = express.Router()
|
var router = express.Router()
|
||||||
|
|
||||||
let Tags = require('@models/Tag');
|
let Tags = require('@models/Tag')
|
||||||
|
|
||||||
let userId = null
|
let userId = null
|
||||||
|
let masterKey = null
|
||||||
|
|
||||||
// middleware that is specific to this router
|
// middleware that is specific to this router
|
||||||
router.use(function setUserId (req, res, next) {
|
router.use(function setUserId (req, res, next) {
|
||||||
if(userId = req.headers.userId){
|
|
||||||
userId = req.headers.userId
|
//Session key is required to continue
|
||||||
|
if(!req.headers.sessionId){
|
||||||
|
next('Unauthorized')
|
||||||
|
}
|
||||||
|
|
||||||
|
if(req.headers.userId){
|
||||||
|
userId = req.headers.userId
|
||||||
|
masterKey = req.headers.masterKey
|
||||||
|
next()
|
||||||
}
|
}
|
||||||
|
|
||||||
next()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
//Get the latest notes the user has created
|
//Get the latest notes the user has created
|
||||||
|
@ -5,20 +5,24 @@ const User = require('@models/User')
|
|||||||
const Auth = require('@helpers/Auth')
|
const Auth = require('@helpers/Auth')
|
||||||
const cs = require('@helpers/CryptoString')
|
const cs = require('@helpers/CryptoString')
|
||||||
|
|
||||||
|
let userId = null
|
||||||
|
let masterKey = null
|
||||||
|
|
||||||
// middleware that is specific to this router
|
// middleware that is specific to this router
|
||||||
router.use(function timeLog (req, res, next) {
|
router.use(function setUserId (req, res, next) {
|
||||||
// console.log('Time: ', Date.now())
|
|
||||||
next()
|
//Session key is required to continue
|
||||||
|
if(!req.headers.sessionId){
|
||||||
|
next('Unauthorized')
|
||||||
|
}
|
||||||
|
|
||||||
|
if(req.headers.userId){
|
||||||
|
userId = req.headers.userId
|
||||||
|
masterKey = req.headers.masterKey
|
||||||
|
next()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Login User
|
|
||||||
router.post('/login', function (req, res) {
|
|
||||||
|
|
||||||
User.login(req.body.username, req.body.password, req.body.authToken)
|
|
||||||
.then( returnData => {
|
|
||||||
res.send(returnData)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
// Logout User
|
// Logout User
|
||||||
router.post('/logout', function (req, res) {
|
router.post('/logout', function (req, res) {
|
||||||
|
|
||||||
@ -28,19 +32,6 @@ router.post('/logout', function (req, res) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// Register User
|
|
||||||
router.post('/register', function (req, res) {
|
|
||||||
|
|
||||||
User.register(req.body.username, req.body.password)
|
|
||||||
.then( returnData => {
|
|
||||||
|
|
||||||
res.send(returnData)
|
|
||||||
})
|
|
||||||
.catch(e => {
|
|
||||||
res.send(false)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// change password
|
// change password
|
||||||
router.post('/changepassword', function (req, res) {
|
router.post('/changepassword', function (req, res) {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user