Feature and UI update
- added version history panel - classification of iterations and unique entries
This commit is contained in:
parent
7adda3e71f
commit
ecf86ef764
135
css/main.css
135
css/main.css
@ -447,14 +447,6 @@ button:active,
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
#main_page {
|
|
||||||
padding: 1.5rem;
|
|
||||||
}
|
|
||||||
#main_page > section:nth-of-type(1) {
|
|
||||||
-ms-flex-line-pack: start;
|
|
||||||
align-content: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
display: grid;
|
display: grid;
|
||||||
-webkit-box-align: center;
|
-webkit-box-align: center;
|
||||||
@ -559,7 +551,7 @@ sm-checkbox {
|
|||||||
#article_wrapper {
|
#article_wrapper {
|
||||||
justify-self: center;
|
justify-self: center;
|
||||||
padding: 1rem 0;
|
padding: 1rem 0;
|
||||||
gap: 0.5rem 0;
|
gap: 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.heading {
|
.heading {
|
||||||
@ -576,15 +568,28 @@ sm-checkbox {
|
|||||||
background-color: var(--accent-color);
|
background-color: var(--accent-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-wrapper {
|
.article-section {
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
display: -ms-flexbox;
|
display: -ms-flexbox;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 1rem;
|
gap: 0.5rem;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
.article-section:not(:last-of-type) {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-card-container {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-card {
|
.content-card {
|
||||||
width: min(60ch, 100%);
|
width: min(50ch, 100%);
|
||||||
|
-ms-flex-negative: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
background-color: var(--foreground-color);
|
background-color: var(--foreground-color);
|
||||||
border: solid thin rgba(var(--text-color), 0.16);
|
border: solid thin rgba(var(--text-color), 0.16);
|
||||||
@ -602,7 +607,8 @@ sm-checkbox {
|
|||||||
transition: -webkit-box-shadow 0.1s;
|
transition: -webkit-box-shadow 0.1s;
|
||||||
transition: box-shadow 0.1s;
|
transition: box-shadow 0.1s;
|
||||||
transition: box-shadow 0.1s, -webkit-box-shadow 0.1s;
|
transition: box-shadow 0.1s, -webkit-box-shadow 0.1s;
|
||||||
min-height: 70vh;
|
height: 60vh;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
.content__area:empty::before {
|
.content__area:empty::before {
|
||||||
content: attr(placeholder);
|
content: attr(placeholder);
|
||||||
@ -616,11 +622,19 @@ sm-checkbox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.content__options {
|
.content__options {
|
||||||
gap: 1rem;
|
gap: 0.5rem;
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
grid-template-columns: auto auto 1fr auto;
|
grid-template-columns: auto auto 1fr auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content__editor {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
background-color: rgba(var(--text-color), 0.06);
|
||||||
|
border-radius: 0.3rem;
|
||||||
|
padding: 0.2rem 0.3rem;
|
||||||
|
color: rgba(var(--text-color), 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
.actionable-button {
|
.actionable-button {
|
||||||
padding: 0.5rem 0.8rem;
|
padding: 0.5rem 0.8rem;
|
||||||
background-color: rgba(var(--text-color), 0.1);
|
background-color: rgba(var(--text-color), 0.1);
|
||||||
@ -632,9 +646,30 @@ sm-checkbox {
|
|||||||
margin-left: 0.3rem;
|
margin-left: 0.3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.formatting-button {
|
#text_toolbar {
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
-webkit-transition: -webkit-transform 0.1s;
|
||||||
|
transition: -webkit-transform 0.1s;
|
||||||
|
transition: transform 0.1s;
|
||||||
|
transition: transform 0.1s, -webkit-transform 0.1s;
|
||||||
|
background-color: var(--foreground-color);
|
||||||
|
border: solid thin rgba(var(--text-color), 0.2);
|
||||||
padding: 0.2rem;
|
padding: 0.2rem;
|
||||||
border-radius: 0.3rem;
|
border-radius: 0.3rem;
|
||||||
|
-webkit-box-shadow: 0 0.1rem 0.2rem rgba(0, 0, 0, 0.06), 0 1rem 1.5rem -0.5rem rgba(0, 0, 0, 0.2);
|
||||||
|
box-shadow: 0 0.1rem 0.2rem rgba(0, 0, 0, 0.06), 0 1rem 1.5rem -0.5rem rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.formatting-button {
|
||||||
|
padding: 0.3rem;
|
||||||
|
border-radius: 0.3rem;
|
||||||
-webkit-transition: background-color 0.1s;
|
-webkit-transition: background-color 0.1s;
|
||||||
transition: background-color 0.1s;
|
transition: background-color 0.1s;
|
||||||
}
|
}
|
||||||
@ -652,10 +687,9 @@ sm-checkbox {
|
|||||||
.quote-template {
|
.quote-template {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
margin: 1rem;
|
margin: 1rem 0;
|
||||||
background-color: var(--foreground-color);
|
background-color: var(--foreground-color);
|
||||||
-webkit-box-shadow: 0 0.5rem 1rem -0.5rem rgba(0, 0, 0, 0.1);
|
border: solid thin rgba(var(--text-color), 0.2);
|
||||||
box-shadow: 0 0.5rem 1rem -0.5rem rgba(0, 0, 0, 0.1);
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
justify-self: center;
|
justify-self: center;
|
||||||
@ -682,20 +716,51 @@ sm-checkbox {
|
|||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#text_toolbar {
|
#version_history_panel {
|
||||||
position: absolute;
|
position: fixed;
|
||||||
z-index: 1;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
top: 0;
|
||||||
-webkit-transition: -webkit-transform 0.3s;
|
bottom: 0;
|
||||||
transition: -webkit-transform 0.3s;
|
right: 0;
|
||||||
transition: transform 0.3s;
|
margin: 1rem;
|
||||||
transition: transform 0.3s, -webkit-transform 0.3s;
|
border-radius: 0.5rem;
|
||||||
|
padding: 1rem;
|
||||||
|
width: min(22rem, 100%);
|
||||||
background-color: var(--foreground-color);
|
background-color: var(--foreground-color);
|
||||||
padding: 0.3rem;
|
-webkit-box-shadow: -0.5rem 0 1rem rgba(0, 0, 0, 0.1);
|
||||||
|
box-shadow: -0.5rem 0 1rem rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#version_timeline {
|
||||||
|
height: 100%;
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-entry {
|
||||||
|
padding: 1rem;
|
||||||
border-radius: 0.3rem;
|
border-radius: 0.3rem;
|
||||||
-webkit-box-shadow: 0 0.1rem 0.2rem rgba(0, 0, 0, 0.06), 0 0.5rem 1rem -0.5rem rgba(0, 0, 0, 0.1);
|
-webkit-user-select: none;
|
||||||
box-shadow: 0 0.1rem 0.2rem rgba(0, 0, 0, 0.06), 0 0.5rem 1rem -0.5rem rgba(0, 0, 0, 0.1);
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
.history-entry:last-of-type::before {
|
||||||
|
content: "CREATED";
|
||||||
|
letter-spacing: 0.03em;
|
||||||
|
display: -webkit-inline-box;
|
||||||
|
display: -ms-inline-flexbox;
|
||||||
|
display: inline-flex;
|
||||||
|
justify-self: flex-start;
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 0.2rem 0.3rem;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
background-color: rgba(var(--text-color), 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.entry__time,
|
||||||
|
.entry__author {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 40rem) and (any-hover: none) {
|
@media screen and (max-width: 40rem) and (any-hover: none) {
|
||||||
@ -742,23 +807,13 @@ sm-checkbox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.page-layout {
|
.page-layout {
|
||||||
grid-template-columns: 1fr 90vw 1fr;
|
grid-template-columns: 1.5rem minmax(0, 1fr) 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hide-on-desktop {
|
.hide-on-desktop {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media screen and (min-width: 72rem) {
|
|
||||||
.page-layout {
|
|
||||||
grid-template-columns: 1fr 90vw 1fr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media screen and (min-width: 120rem) {
|
|
||||||
.page-layout {
|
|
||||||
grid-template-columns: 1fr 90vw 1fr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media (any-hover: hover) {
|
@media (any-hover: hover) {
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 0.5rem;
|
width: 0.5rem;
|
||||||
|
|||||||
2
css/main.min.css
vendored
2
css/main.min.css
vendored
File diff suppressed because one or more lines are too long
111
css/main.scss
111
css/main.scss
@ -397,11 +397,6 @@ button:active,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#main_page {
|
#main_page {
|
||||||
padding: 1.5rem;
|
|
||||||
|
|
||||||
& > section:nth-of-type(1) {
|
|
||||||
align-content: flex-start;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.logo {
|
.logo {
|
||||||
display: grid;
|
display: grid;
|
||||||
@ -492,7 +487,7 @@ sm-checkbox {
|
|||||||
#article_wrapper {
|
#article_wrapper {
|
||||||
justify-self: center;
|
justify-self: center;
|
||||||
padding: 1rem 0;
|
padding: 1rem 0;
|
||||||
gap: 0.5rem 0;
|
gap: 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.heading {
|
.heading {
|
||||||
@ -507,13 +502,22 @@ sm-checkbox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-wrapper {
|
.article-section {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 1rem;
|
gap: 0.5rem;
|
||||||
|
overflow-x: auto;
|
||||||
|
&:not(:last-of-type) {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.content-card-container {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-card {
|
.content-card {
|
||||||
width: min(60ch, 100%);
|
width: min(50ch, 100%);
|
||||||
|
flex-shrink: 0;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
background-color: var(--foreground-color);
|
background-color: var(--foreground-color);
|
||||||
border: solid thin rgba(var(--text-color), 0.16);
|
border: solid thin rgba(var(--text-color), 0.16);
|
||||||
@ -530,7 +534,8 @@ sm-checkbox {
|
|||||||
background-color: rgba(var(--text-color), 0.02);
|
background-color: rgba(var(--text-color), 0.02);
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
transition: box-shadow 0.1s;
|
transition: box-shadow 0.1s;
|
||||||
min-height: 70vh;
|
height: 60vh;
|
||||||
|
overflow-y: auto;
|
||||||
&:empty::before {
|
&:empty::before {
|
||||||
content: attr(placeholder);
|
content: attr(placeholder);
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
@ -542,10 +547,17 @@ sm-checkbox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.content__options {
|
.content__options {
|
||||||
gap: 1rem;
|
gap: 0.5rem;
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
grid-template-columns: auto auto 1fr auto;
|
grid-template-columns: auto auto 1fr auto;
|
||||||
}
|
}
|
||||||
|
.content__editor {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
background-color: rgba(var(--text-color), 0.06);
|
||||||
|
border-radius: 0.3rem;
|
||||||
|
padding: 0.2rem 0.3rem;
|
||||||
|
color: rgba(var(--text-color), 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
.actionable-button {
|
.actionable-button {
|
||||||
padding: 0.5rem 0.8rem;
|
padding: 0.5rem 0.8rem;
|
||||||
@ -557,9 +569,23 @@ sm-checkbox {
|
|||||||
margin-left: 0.3rem;
|
margin-left: 0.3rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.formatting-button {
|
#text_toolbar {
|
||||||
|
user-select: none;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
transition: transform 0.1s;
|
||||||
|
background-color: var(--foreground-color);
|
||||||
|
border: solid thin rgba(var(--text-color), 0.2);
|
||||||
padding: 0.2rem;
|
padding: 0.2rem;
|
||||||
border-radius: 0.3rem;
|
border-radius: 0.3rem;
|
||||||
|
box-shadow: 0 0.1rem 0.2rem rgba(0, 0, 0, 0.06),
|
||||||
|
0 1rem 1.5rem -0.5rem rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
.formatting-button {
|
||||||
|
padding: 0.3rem;
|
||||||
|
border-radius: 0.3rem;
|
||||||
transition: background-color 0.1s;
|
transition: background-color 0.1s;
|
||||||
&.active:hover {
|
&.active:hover {
|
||||||
background-color: var(--accent-color);
|
background-color: var(--accent-color);
|
||||||
@ -575,9 +601,9 @@ sm-checkbox {
|
|||||||
.quote-template {
|
.quote-template {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
margin: 1rem;
|
margin: 1rem 0;
|
||||||
background-color: var(--foreground-color);
|
background-color: var(--foreground-color);
|
||||||
box-shadow: 0 0.5rem 1rem -0.5rem rgba(0, 0, 0, 0.1);
|
border: solid thin rgba(var(--text-color), 0.2);
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
justify-self: center;
|
justify-self: center;
|
||||||
@ -602,17 +628,42 @@ sm-checkbox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#text_toolbar {
|
#version_history_panel {
|
||||||
position: absolute;
|
position: fixed;
|
||||||
z-index: 1;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
top: 0;
|
||||||
transition: transform 0.3s;
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
margin: 1rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
padding: 1rem;
|
||||||
|
width: min(22rem, 100%);
|
||||||
background-color: var(--foreground-color);
|
background-color: var(--foreground-color);
|
||||||
padding: 0.3rem;
|
box-shadow: -0.5rem 0 1rem rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
#version_timeline {
|
||||||
|
height: 100%;
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
.history-entry {
|
||||||
|
padding: 1rem;
|
||||||
border-radius: 0.3rem;
|
border-radius: 0.3rem;
|
||||||
box-shadow: 0 0.1rem 0.2rem rgba(0, 0, 0, 0.06),
|
user-select: none;
|
||||||
0 0.5rem 1rem -0.5rem rgba(0, 0, 0, 0.1);
|
&:last-of-type::before {
|
||||||
|
content: "CREATED";
|
||||||
|
letter-spacing: 0.03em;
|
||||||
|
display: inline-flex;
|
||||||
|
justify-self: flex-start;
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 0.2rem 0.3rem;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
background-color: rgba(var(--text-color), 0.06);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.entry__time,
|
||||||
|
.entry__author {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 40rem) and (any-hover: none) {
|
@media screen and (max-width: 40rem) and (any-hover: none) {
|
||||||
@ -656,26 +707,12 @@ sm-checkbox {
|
|||||||
--width: 24rem;
|
--width: 24rem;
|
||||||
}
|
}
|
||||||
.page-layout {
|
.page-layout {
|
||||||
grid-template-columns: 1fr 90vw 1fr;
|
grid-template-columns: 1.5rem minmax(0, 1fr) 1.5rem;
|
||||||
}
|
}
|
||||||
.hide-on-desktop {
|
.hide-on-desktop {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media screen and (min-width: 48rem) {
|
|
||||||
}
|
|
||||||
@media screen and (max-width: 64rem) {
|
|
||||||
}
|
|
||||||
@media screen and (min-width: 72rem) {
|
|
||||||
.page-layout {
|
|
||||||
grid-template-columns: 1fr 90vw 1fr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media screen and (min-width: 120rem) {
|
|
||||||
.page-layout {
|
|
||||||
grid-template-columns: 1fr 90vw 1fr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media (any-hover: hover) {
|
@media (any-hover: hover) {
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 0.5rem;
|
width: 0.5rem;
|
||||||
|
|||||||
494
index.html
494
index.html
@ -56,103 +56,126 @@
|
|||||||
<sm-button variant="no-outline" class="submit-btn">OK</sm-button>
|
<sm-button variant="no-outline" class="submit-btn">OK</sm-button>
|
||||||
</div>
|
</div>
|
||||||
</sm-popup>
|
</sm-popup>
|
||||||
<header id="main_header">
|
<article id="main_page" class="grid">
|
||||||
<div class="logo">
|
<header id="main_header">
|
||||||
<svg class="main-logo" width="23" height="22" viewBox="0 0 23 22" fill="none"
|
<div class="logo">
|
||||||
xmlns="http://www.w3.org/2000/svg">
|
<svg class="main-logo" width="23" height="22" viewBox="0 0 23 22" fill="none"
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
d="M15 0.749881C10.9026 2.35002 8 6.33604 8 11C8 15.664 10.9026 19.65 15 21.2501C13.7603 21.7343 12.4112 22 11 22C4.92487 22 0 17.0751 0 11C0 4.92487 4.92487 0 11 0C12.4112 0 13.7603 0.26573 15 0.749881Z" />
|
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
d="M15 0.749881C10.9026 2.35002 8 6.33604 8 11C8 15.664 10.9026 19.65 15 21.2501C13.7603 21.7343 12.4112 22 11 22C4.92487 22 0 17.0751 0 11C0 4.92487 4.92487 0 11 0C12.4112 0 13.7603 0.26573 15 0.749881Z" />
|
||||||
d="M14 16.591C16.2349 15.7182 17.8182 13.544 17.8182 11C17.8182 8.45602 16.2349 6.28183 14 5.40903C14.6762 5.14494 15.4121 5 16.1818 5C19.4955 5 22.1818 7.68629 22.1818 11C22.1818 14.3137 19.4955 17 16.1818 17C15.4121 17 14.6762 16.8551 14 16.591Z" />
|
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||||
</svg>
|
d="M14 16.591C16.2349 15.7182 17.8182 13.544 17.8182 11C17.8182 8.45602 16.2349 6.28183 14 5.40903C14.6762 5.14494 15.4121 5 16.1818 5C19.4955 5 22.1818 7.68629 22.1818 11C22.1818 14.3137 19.4955 17 16.1818 17C15.4121 17 14.6762 16.8551 14 16.591Z" />
|
||||||
<div class="grid">
|
</svg>
|
||||||
<span class="label">RanchiMall</span>
|
<div class="grid">
|
||||||
<h4>Content Collab</h4>
|
<span class="label">RanchiMall</span>
|
||||||
|
<h4>Content Collab</h4>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div id="article_name_wrapper" class="flex align-center justify-center">
|
||||||
<div id="article_name_wrapper" class="flex align-center justify-center">
|
<button title="Create new article" class="button__icon--left"
|
||||||
<button title="Create new article" class="button__icon--left" onclick="showPopup('create_article_popup')">
|
onclick="showPopup('create_article_popup')">
|
||||||
|
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
||||||
|
fill="#000000">
|
||||||
|
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||||
|
<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<h4 id="current_article_name"></h4>
|
||||||
|
<button class="button__icon--right" onclick="showPopup('article_list_popup')">
|
||||||
|
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
||||||
|
fill="#000000">
|
||||||
|
<path d="M24 24H0V0h24v24z" fill="none" opacity=".87" />
|
||||||
|
<path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6-1.41-1.41z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<theme-toggle></theme-toggle>
|
||||||
|
<button onclick="showPopup('user_popup')">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="icon" height="24px" viewBox="0 0 24 24" width="24px"
|
||||||
|
fill="#000000">
|
||||||
|
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||||
|
<path
|
||||||
|
d="M12 5.9c1.16 0 2.1.94 2.1 2.1s-.94 2.1-2.1 2.1S9.9 9.16 9.9 8s.94-2.1 2.1-2.1m0 9c2.97 0 6.1 1.46 6.1 2.1v1.1H5.9V17c0-.64 3.13-2.1 6.1-2.1M12 4C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 9c-2.67 0-8 1.34-8 4v3h16v-3c0-2.66-5.33-4-8-4z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</header>
|
||||||
|
<div id="text_toolbar" class="hide-completely">
|
||||||
|
<button id="strong_button" title="Bold (ctrl+b)" class="formatting-button" onclick="formatDoc('bold')">
|
||||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
||||||
fill="#000000">
|
fill="#000000">
|
||||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||||
<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
|
<path
|
||||||
|
d="M15.6 10.79c.97-.67 1.65-1.77 1.65-2.79 0-2.26-1.75-4-4-4H7v14h7.04c2.09 0 3.71-1.7 3.71-3.79 0-1.52-.86-2.82-2.15-3.42zM10 6.5h3c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5h-3v-3zm3.5 9H10v-3h3.5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5z" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<h4 id="current_article_name"></h4>
|
<button id="em_button" title="Italic (ctrl+i)" class="formatting-button" onclick="formatDoc('italic');">
|
||||||
<button class="button__icon--right" onclick="showPopup('article_list_popup')">
|
|
||||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
|
||||||
fill="#000000">
|
|
||||||
<path d="M24 24H0V0h24v24z" fill="none" opacity=".87" />
|
|
||||||
<path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6-1.41-1.41z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<theme-toggle></theme-toggle>
|
|
||||||
<button onclick="showPopup('user_popup')">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon" height="24px" viewBox="0 0 24 24" width="24px"
|
|
||||||
fill="#000000">
|
|
||||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
|
||||||
<path
|
|
||||||
d="M12 5.9c1.16 0 2.1.94 2.1 2.1s-.94 2.1-2.1 2.1S9.9 9.16 9.9 8s.94-2.1 2.1-2.1m0 9c2.97 0 6.1 1.46 6.1 2.1v1.1H5.9V17c0-.64 3.13-2.1 6.1-2.1M12 4C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 9c-2.67 0-8 1.34-8 4v3h16v-3c0-2.66-5.33-4-8-4z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</header>
|
|
||||||
<div id="text_toolbar" class="hide-completely">
|
|
||||||
<button id="strong_button" class="formatting-button" onclick="formatDoc('bold')">
|
|
||||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
|
||||||
fill="#000000">
|
|
||||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
|
||||||
<path
|
|
||||||
d="M15.6 10.79c.97-.67 1.65-1.77 1.65-2.79 0-2.26-1.75-4-4-4H7v14h7.04c2.09 0 3.71-1.7 3.71-3.79 0-1.52-.86-2.82-2.15-3.42zM10 6.5h3c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5h-3v-3zm3.5 9H10v-3h3.5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<button id="em_button" class="formatting-button" onclick="formatDoc('italic');">
|
|
||||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
|
||||||
fill="#000000">
|
|
||||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
|
||||||
<path d="M10 4v3h2.21l-3.42 8H6v3h8v-3h-2.21l3.42-8H18V4h-8z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<button id="u_button" class="formatting-button" onclick="formatDoc('underline');">
|
|
||||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
|
||||||
fill="#000000">
|
|
||||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
|
||||||
<path
|
|
||||||
d="M12 17c3.31 0 6-2.69 6-6V3h-2.5v8c0 1.93-1.57 3.5-3.5 3.5S8.5 12.93 8.5 11V3H6v8c0 3.31 2.69 6 6 6zm-7 2v2h14v-2H5z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div id="article_wrapper" class="grid page-layout"></div>
|
|
||||||
<section class="grid page-layout">
|
|
||||||
<div id="action_button_group" class="flex align-center gap-0-5">
|
|
||||||
<span>
|
|
||||||
<b>
|
|
||||||
Add
|
|
||||||
</b>
|
|
||||||
</span>
|
|
||||||
<button class="actionable-button" title="Add paragraph">
|
|
||||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
||||||
fill="#000000">
|
fill="#000000">
|
||||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||||
<path d="M14 17H4v2h10v-2zm6-8H4v2h16V9zM4 15h16v-2H4v2zM4 5v2h16V5H4z" />
|
<path d="M10 4v3h2.21l-3.42 8H6v3h8v-3h-2.21l3.42-8H18V4h-8z" />
|
||||||
</svg>
|
</svg>
|
||||||
<span class="actionable-button__title">
|
|
||||||
Section
|
|
||||||
</span>
|
|
||||||
</button>
|
</button>
|
||||||
<button class="actionable-button" title="Add paragraph" onclick="insertBlockquote()">
|
<button id="u_button" title="Underline (ctrl+u)" class="formatting-button"
|
||||||
|
onclick="formatDoc('underline');">
|
||||||
|
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
||||||
|
fill="#000000">
|
||||||
|
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||||
|
<path
|
||||||
|
d="M12 17c3.31 0 6-2.69 6-6V3h-2.5v8c0 1.93-1.57 3.5-3.5 3.5S8.5 12.93 8.5 11V3H6v8c0 3.31 2.69 6 6 6zm-7 2v2h14v-2H5z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button class="formatting-button" title="Add quote" onclick="insertBlockquote()">
|
||||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
||||||
fill="#000000">
|
fill="#000000">
|
||||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||||
<path
|
<path
|
||||||
d="M18.62 18h-5.24l2-4H13V6h8v7.24L18.62 18zm-2-2h.76L19 12.76V8h-4v4h3.62l-2 4zm-8 2H3.38l2-4H3V6h8v7.24L8.62 18zm-2-2h.76L9 12.76V8H5v4h3.62l-2 4z" />
|
d="M18.62 18h-5.24l2-4H13V6h8v7.24L18.62 18zm-2-2h.76L19 12.76V8h-4v4h3.62l-2 4zm-8 2H3.38l2-4H3V6h8v7.24L8.62 18zm-2-2h.76L9 12.76V8H5v4h3.62l-2 4z" />
|
||||||
</svg>
|
</svg>
|
||||||
<span class="actionable-button__title">
|
|
||||||
Quote
|
|
||||||
</span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
<div id="article_wrapper" class="grid page-layout"></div>
|
||||||
|
<section class="grid page-layout">
|
||||||
|
<div id="action_button_group" class="flex align-center gap-0-5">
|
||||||
|
<span>
|
||||||
|
<b>
|
||||||
|
Add
|
||||||
|
</b>
|
||||||
|
</span>
|
||||||
|
<button class="actionable-button" title="Add paragraph">
|
||||||
|
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
||||||
|
fill="#000000">
|
||||||
|
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||||
|
<path d="M14 17H4v2h10v-2zm6-8H4v2h16V9zM4 15h16v-2H4v2zM4 5v2h16V5H4z" />
|
||||||
|
</svg>
|
||||||
|
<span class="actionable-button__title">
|
||||||
|
Section
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<aside id="version_history_panel" class="flex direction-column hide-completely">
|
||||||
|
<div class="flex align-center space-between">
|
||||||
|
<div class="flex align-center">
|
||||||
|
<svg class="icon button__icon--left" xmlns="http://www.w3.org/2000/svg" height="24px"
|
||||||
|
viewBox="0 0 24 24" width="24px" fill="#000000">
|
||||||
|
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||||
|
<path
|
||||||
|
d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.25 2.52.77-1.28-3.52-2.09V8z" />
|
||||||
|
</svg>
|
||||||
|
<h4>Version history</h4>
|
||||||
|
</div>
|
||||||
|
<button onclick="hideVersionHistory()">
|
||||||
|
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
||||||
|
fill="#000000">
|
||||||
|
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||||
|
<path
|
||||||
|
d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<ul id="version_timeline" class="flex direction-column gap-0-5"></ul>
|
||||||
|
</aside>
|
||||||
|
</article>
|
||||||
<sm-popup id="article_list_popup">
|
<sm-popup id="article_list_popup">
|
||||||
<header slot="header" class="popup__header">
|
<header slot="header" class="popup__header">
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
@ -199,7 +222,7 @@
|
|||||||
</sm-popup>
|
</sm-popup>
|
||||||
<template id="section_template">
|
<template id="section_template">
|
||||||
<h4 class="heading"></h4>
|
<h4 class="heading"></h4>
|
||||||
<section class="article-section flex gap-1">
|
<section class="article-section">
|
||||||
<div class="content-card content-card--empty">
|
<div class="content-card content-card--empty">
|
||||||
<div class="content__area" data-type="origin" placeholder="Write something new or edit existing content"
|
<div class="content__area" data-type="origin" placeholder="Write something new or edit existing content"
|
||||||
contenteditable="true"></div>
|
contenteditable="true"></div>
|
||||||
@ -211,24 +234,28 @@
|
|||||||
<template id="content_card_template">
|
<template id="content_card_template">
|
||||||
<div class="content-card">
|
<div class="content-card">
|
||||||
<div class="content__area"></div>
|
<div class="content__area"></div>
|
||||||
<div class="content__options grid align-center">
|
<div class="flex align-center space-between">
|
||||||
<button class="version-history-button" title="See version history">
|
<div class="content__options grid align-center">
|
||||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
<button class="version-history-button" title="See version history">
|
||||||
fill="#000000">
|
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24"
|
||||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
width="24px" fill="#000000">
|
||||||
<path
|
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||||
d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.25 2.52.77-1.28-3.52-2.09V8z" />
|
<path
|
||||||
</svg>
|
d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.25 2.52.77-1.28-3.52-2.09V8z" />
|
||||||
</button>
|
</svg>
|
||||||
<button title="Give score">
|
</button>
|
||||||
<svg class="icon button__icon--left" xmlns="http://www.w3.org/2000/svg" height="24px"
|
<button title="Give score">
|
||||||
viewBox="0 0 24 24" width="24px" fill="#000000">
|
<svg class="icon button__icon--left" xmlns="http://www.w3.org/2000/svg" height="24px"
|
||||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
viewBox="0 0 24 24" width="24px" fill="#000000">
|
||||||
<path
|
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||||
d="M12 7.13l.97 2.29.47 1.11 1.2.1 2.47.21-1.88 1.63-.91.79.27 1.18.56 2.41-2.12-1.28-1.03-.64-1.03.62-2.12 1.28.56-2.41.27-1.18-.91-.79-1.88-1.63 2.47-.21 1.2-.1.47-1.11.97-2.27M12 2L9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2z" />
|
<path
|
||||||
</svg>
|
d="M12 7.13l.97 2.29.47 1.11 1.2.1 2.47.21-1.88 1.63-.91.79.27 1.18.56 2.41-2.12-1.28-1.03-.64-1.03.62-2.12 1.28.56-2.41.27-1.18-.91-.79-1.88-1.63 2.47-.21 1.2-.1.47-1.11.97-2.27M12 2L9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2z" />
|
||||||
<span class="content__score">47</span>
|
</svg>
|
||||||
</button>
|
<span class="content__score">47</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="content__editor"></div>
|
||||||
|
<button class="submit-entry">Submit</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -240,6 +267,19 @@
|
|||||||
<figcaption class="flex"><span class="by" contenteditable="true"></span><cite class="citation"
|
<figcaption class="flex"><span class="by" contenteditable="true"></span><cite class="citation"
|
||||||
contenteditable="true"></cite></figcaption>
|
contenteditable="true"></cite></figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
|
<p><br></p>
|
||||||
|
</template>
|
||||||
|
<template id="history_entry_template">
|
||||||
|
<li class="history-entry interact grid gap-0-5">
|
||||||
|
<div class="flex align-center space-between">
|
||||||
|
<time class="entry__time"></time>
|
||||||
|
<span class="entry__score"></span>
|
||||||
|
</div>
|
||||||
|
<div class="grid">
|
||||||
|
<div class="label">Author</div>
|
||||||
|
<span class="entry__author breakable"></span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
</template>
|
</template>
|
||||||
<script id="ui_utils">
|
<script id="ui_utils">
|
||||||
// Global letiables
|
// Global letiables
|
||||||
@ -385,31 +425,6 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// displays a popup for asking user input. Use this instead of JS prompt
|
|
||||||
function getPromptInput(title, message = '', options = {}) {
|
|
||||||
const { isPassword = true, cancelText = 'Cancel', confirmText = 'OK' } = options
|
|
||||||
showPopup('prompt_popup', true)
|
|
||||||
getRef('prompt_title').textContent = title;
|
|
||||||
getRef('prompt_message').textContent = message;
|
|
||||||
let buttons = getRef('prompt_popup').querySelectorAll("sm-button");
|
|
||||||
if (isPassword)
|
|
||||||
getRef('prompt_input').setAttribute("type", "password")
|
|
||||||
getRef('prompt_input').focusIn()
|
|
||||||
buttons[0].textContent = cancelText;
|
|
||||||
buttons[1].textContent = confirmText;
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
buttons[0].onclick = () => {
|
|
||||||
hidePopup()
|
|
||||||
return (null);
|
|
||||||
}
|
|
||||||
buttons[1].onclick = () => {
|
|
||||||
const value = getRef('prompt_input').value;
|
|
||||||
hidePopup()
|
|
||||||
resolve(value)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//Function for displaying toast notifications. pass in error for mode param if you want to show an error.
|
//Function for displaying toast notifications. pass in error for mode param if you want to show an error.
|
||||||
function notify(message, mode, options = {}) {
|
function notify(message, mode, options = {}) {
|
||||||
const { pinned = false, sound = false } = options
|
const { pinned = false, sound = false } = options
|
||||||
@ -432,17 +447,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFormattedTime(timeString, relative) {
|
function getFormattedTime(time, relative) {
|
||||||
try {
|
try {
|
||||||
const [date, time] = timeString.split('T')
|
if (String(time).indexOf('_'))
|
||||||
const [year, month, day] = date.split('-').map(v => parseInt(v))
|
time = String(time).split('_')[0]
|
||||||
let [hours, minutes] = time.split(':').map(v => parseInt(v))
|
const intTime = parseInt(time)
|
||||||
const currentTime = new Date()
|
if (String(intTime).length < 13)
|
||||||
const currentTimeFrag = currentTime.toString().split(' ')
|
time *= 1000
|
||||||
const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
let timeFrag = new Date(intTime).toString().split(' '),
|
||||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
day = timeFrag[0],
|
||||||
];
|
month = timeFrag[1],
|
||||||
const monthName = monthNames[month]
|
date = timeFrag[2],
|
||||||
|
year = timeFrag[3],
|
||||||
|
minutes = new Date(intTime).getMinutes(),
|
||||||
|
hours = new Date(intTime).getHours(),
|
||||||
|
currentTime = new Date().toString().split(' ')
|
||||||
|
|
||||||
minutes = minutes < 10 ? `0${minutes}` : minutes
|
minutes = minutes < 10 ? `0${minutes}` : minutes
|
||||||
let finalHours = ``;
|
let finalHours = ``;
|
||||||
@ -456,25 +475,25 @@
|
|||||||
finalHours = hours >= 12 ? `${finalHours} PM` : `${finalHours} AM`
|
finalHours = hours >= 12 ? `${finalHours} PM` : `${finalHours} AM`
|
||||||
if (relative) {
|
if (relative) {
|
||||||
if (year == currentYear) {
|
if (year == currentYear) {
|
||||||
if ((currentTime.getMonth() + 1) === month) {
|
if (currentTime[1] === month) {
|
||||||
const dateDiff = (parseInt(currentTimeFrag[2]) - parseInt(day))
|
const dateDiff = (parseInt(currentTime[2]) - parseInt(date))
|
||||||
if (dateDiff === 0)
|
if (dateDiff === 0)
|
||||||
return `${finalHours}`;
|
return `${finalHours}`;
|
||||||
else if (dateDiff === 1)
|
else if (dateDiff === 1)
|
||||||
return `Yesterday`;
|
return `Yesterday`;
|
||||||
else if (dateDiff > 1 && dateDiff < 8)
|
else if (dateDiff > 1 && dateDiff < 8)
|
||||||
return currentTimeFrag[0];
|
return currentTime[0];
|
||||||
else
|
else
|
||||||
return ` ${day} ${monthName}`;
|
return ` ${date} ${month}`;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return ` ${day} ${monthName}`;
|
return ` ${date} ${month}`;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return `${monthName} ${year}`;
|
return `${month} ${year}`;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return `${finalHours}, ${monthName} ${day} ${year}`;
|
return `${month} ${date} ${year}, ${finalHours}`;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
return time;
|
return time;
|
||||||
@ -706,21 +725,32 @@
|
|||||||
|
|
||||||
getRef('article_wrapper').addEventListener('click', e => {
|
getRef('article_wrapper').addEventListener('click', e => {
|
||||||
if (e.target.closest('.submit-entry')) {
|
if (e.target.closest('.submit-entry')) {
|
||||||
const parent = e.target.parentNode.querySelector('.content__area')
|
const contentCard = e.target.closest('.content-card')
|
||||||
parent.querySelectorAll('[style=""]').forEach((el) => {
|
const contentArea = contentCard.querySelector('.content__area')
|
||||||
|
const uid = contentCard.dataset.uid
|
||||||
|
const isUniqueEntry = contentArea.dataset.type === 'origin'
|
||||||
|
contentArea.querySelectorAll('[style=""]').forEach((el) => {
|
||||||
el.removeAttribute('style')
|
el.removeAttribute('style')
|
||||||
})
|
})
|
||||||
const clean = DOMPurify.sanitize(parent.innerHTML);
|
const clean = DOMPurify.sanitize(contentArea.innerHTML);
|
||||||
floCloudAPI.sendGeneralData({
|
if (clean.trim() === '') return
|
||||||
section: parent.closest('.article-section').dataset.id,
|
let previousVersion, contributors
|
||||||
origin: parent.dataset.type === 'origin' ? floCrypto.randString(16, true) : parent.parentNode.dataset.uid,
|
if (!isUniqueEntry)
|
||||||
data: parent.dataset.type === 'origin' ? clean : getDiff('', clean),
|
({ data: previousVersion, contributors } = getIterationDetails(uid))
|
||||||
}, `${currentArticle.id}_gd`)
|
const entry = {
|
||||||
|
section: contentCard.closest('.article-section').dataset.id,
|
||||||
|
origin: isUniqueEntry ? floCrypto.randString(16, true) : uid,
|
||||||
|
data: isUniqueEntry ? clean : getDiff(previousVersion, clean),
|
||||||
|
}
|
||||||
|
floCloudAPI.sendGeneralData(entry, `${currentArticle.id}_gd`)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
console.log(res)
|
console.log(res)
|
||||||
notify('sent data', 'success')
|
notify('sent data', 'success')
|
||||||
parent.innerHTML = ''
|
if (isUniqueEntry)
|
||||||
|
contentArea.innerHTML = ''
|
||||||
})
|
})
|
||||||
|
} else if (e.target.closest('.version-history-button')) {
|
||||||
|
showVersionHistory(e.target.closest('.content-card').dataset.uid)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
getRef('article_wrapper').addEventListener("paste", e => {
|
getRef('article_wrapper').addEventListener("paste", e => {
|
||||||
@ -735,6 +765,8 @@
|
|||||||
})
|
})
|
||||||
getRef('article_wrapper').addEventListener("focusin", e => {
|
getRef('article_wrapper').addEventListener("focusin", e => {
|
||||||
if (e.target.closest('.content__area')) {
|
if (e.target.closest('.content__area')) {
|
||||||
|
document.addEventListener('selectionchange', detectFormatting)
|
||||||
|
|
||||||
const target = e.target.closest('.content__area')
|
const target = e.target.closest('.content__area')
|
||||||
if (target.childNodes[0] === undefined) {
|
if (target.childNodes[0] === undefined) {
|
||||||
target.innerHTML = `<p><br/></p>`
|
target.innerHTML = `<p><br/></p>`
|
||||||
@ -746,17 +778,25 @@
|
|||||||
})
|
})
|
||||||
getRef('article_wrapper').addEventListener("focusout", e => {
|
getRef('article_wrapper').addEventListener("focusout", e => {
|
||||||
if (e.target.closest('.content__area')) {
|
if (e.target.closest('.content__area')) {
|
||||||
|
document.removeEventListener('selectionchange', detectFormatting)
|
||||||
childObserver.disconnect()
|
childObserver.disconnect()
|
||||||
|
normalizeText(e.target.closest('.content__area'))
|
||||||
|
const selection = window.getSelection()
|
||||||
|
if (!e.relatedTarget?.closest('#text_toolbar')) {
|
||||||
|
getRef('text_toolbar').classList.add('hide-completely')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const childObserver = new MutationObserver((mutations, observer) => {
|
const childObserver = new MutationObserver((mutations, observer) => {
|
||||||
mutations.forEach(mutation => {
|
mutations.forEach(mutation => {
|
||||||
if (mutation.type === 'childList' && mutation.target.childNodes[0] === undefined) {
|
if (mutation.type === 'childList') {
|
||||||
observer.disconnect()
|
if (mutation.removedNodes.length && mutation.target.childNodes[0] === undefined) {
|
||||||
mutation.target.innerHTML = `<p><br/></p>`
|
observer.disconnect()
|
||||||
childObserver.observe(mutation.target, {
|
mutation.target.innerHTML = `<p><br/></p>`
|
||||||
childList: true
|
childObserver.observe(mutation.target, {
|
||||||
})
|
childList: true
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -766,60 +806,6 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script>
|
||||||
const CC = {
|
|
||||||
defaultArticle: '',
|
|
||||||
he78r1he74187er1h8e: 'Big Techs And Their Dominance'
|
|
||||||
}
|
|
||||||
const genData = [
|
|
||||||
{
|
|
||||||
section: 'edg4ewr8g4e98r',
|
|
||||||
origin: 'erg1e98r1ge9r1',
|
|
||||||
data: '',
|
|
||||||
score: 45,
|
|
||||||
editor: '',
|
|
||||||
timestamp: 1636485447518
|
|
||||||
},
|
|
||||||
{
|
|
||||||
section: 'edg4ewr8g4e98r',
|
|
||||||
origin: 'erg1e98r1ge9r1',
|
|
||||||
data: 'u2',
|
|
||||||
score: 45,
|
|
||||||
editor: '',
|
|
||||||
timestamp: 1636485393538
|
|
||||||
},
|
|
||||||
{
|
|
||||||
section: 'edg4ewr8g4e98r',
|
|
||||||
origin: 'erg1e98r1ge9r1',
|
|
||||||
data: '',
|
|
||||||
score: 45,
|
|
||||||
editor: '',
|
|
||||||
timestamp: 1636485459328
|
|
||||||
},
|
|
||||||
{
|
|
||||||
section: 'edg4ewr8g4e98r',
|
|
||||||
origin: 'er98g4er8g1erg',
|
|
||||||
data: 'u1',
|
|
||||||
score: 45,
|
|
||||||
editor: '',
|
|
||||||
timestamp: 1636485440013
|
|
||||||
},
|
|
||||||
{
|
|
||||||
section: 'edg4ewr8g4e98r',
|
|
||||||
origin: 'erg1e98r1ge9r1',
|
|
||||||
data: '',
|
|
||||||
score: 45,
|
|
||||||
editor: '',
|
|
||||||
timestamp: 1636485477636
|
|
||||||
},
|
|
||||||
{
|
|
||||||
section: 'edg4ewr8g4e98r',
|
|
||||||
origin: 'er98g4er8g1erg',
|
|
||||||
data: '',
|
|
||||||
score: 45,
|
|
||||||
editor: '',
|
|
||||||
timestamp: 1636485484595
|
|
||||||
},
|
|
||||||
]
|
|
||||||
let currentArticle = {}
|
let currentArticle = {}
|
||||||
const render = {
|
const render = {
|
||||||
section(sectionID, { title, uniqueEntries }) {
|
section(sectionID, { title, uniqueEntries }) {
|
||||||
@ -827,26 +813,22 @@
|
|||||||
const frag = document.createDocumentFragment()
|
const frag = document.createDocumentFragment()
|
||||||
section.children[1].dataset.id = sectionID
|
section.children[1].dataset.id = sectionID
|
||||||
section.querySelector('.heading').textContent = title
|
section.querySelector('.heading').textContent = title
|
||||||
currentArticle.sect
|
currentArticle.sections[sectionID].uniqueEntries.forEach(entry => {
|
||||||
|
frag.append(render.contentCard(entry))
|
||||||
|
})
|
||||||
section.querySelector('.content-card-container').append(frag)
|
section.querySelector('.content-card-container').append(frag)
|
||||||
return section
|
return section
|
||||||
},
|
},
|
||||||
contentCard(id, version = 0) {
|
contentCard(id, version = 0) {
|
||||||
const clone = getRef('content_card_template').content.cloneNode(true).firstElementChild;
|
const clone = getRef('content_card_template').content.cloneNode(true).firstElementChild;
|
||||||
const { paragraphs, score } = articles[currentArticle.id].pieces[piece]
|
clone.dataset.uid = id
|
||||||
for (const paraKey in paragraphs) {
|
if (!floGlobals.subAdmins.includes(myFloID)) {
|
||||||
const versions = paragraphs[paraKey]
|
clone.querySelector('.content__area').setAttribute('contentEditable', true)
|
||||||
const { content, writer } = articles[currentArticle.id].versionHistory[versions[version]]
|
|
||||||
const paragraph = createElement('div', {
|
|
||||||
className: 'content__area',
|
|
||||||
textContent: content,
|
|
||||||
attributes: { contentEditable: true }
|
|
||||||
})
|
|
||||||
frag.append(paragraph)
|
|
||||||
}
|
}
|
||||||
clone.querySelector('.paragraph-wrapper').append(frag)
|
const { data, contributors } = getIterationDetails(id)
|
||||||
clone.querySelector('.content__score').textContent = score;
|
clone.querySelector('.content__area').innerHTML = DOMPurify.sanitize(data)
|
||||||
|
clone.querySelector('.content__editor').textContent = `by ${contributors}`;
|
||||||
|
// clone.querySelector('.content__score').textContent = score;
|
||||||
return clone
|
return clone
|
||||||
},
|
},
|
||||||
article(id) {
|
article(id) {
|
||||||
@ -861,6 +843,13 @@
|
|||||||
getRef('current_article_name').textContent = title
|
getRef('current_article_name').textContent = title
|
||||||
getRef('article_wrapper').innerHTML = ''
|
getRef('article_wrapper').innerHTML = ''
|
||||||
getRef('article_wrapper').append(frag)
|
getRef('article_wrapper').append(frag)
|
||||||
|
},
|
||||||
|
historyEntry(details) {
|
||||||
|
const { editor, timestamp } = details
|
||||||
|
const clone = getRef('history_entry_template').content.cloneNode(true).firstElementChild;
|
||||||
|
clone.querySelector('.entry__time').textContent = getFormattedTime(timestamp)
|
||||||
|
clone.querySelector('.entry__author').textContent = editor
|
||||||
|
return clone
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -871,21 +860,22 @@
|
|||||||
sections.forEach(({ id, title }) => {
|
sections.forEach(({ id, title }) => {
|
||||||
currentArticle['sections'][id] = {
|
currentArticle['sections'][id] = {
|
||||||
title,
|
title,
|
||||||
uniqueEntries: []
|
uniqueEntries: new Set()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
currentArticle['uniqueEntries'] = {}
|
currentArticle['uniqueEntries'] = {}
|
||||||
for (const key in generalData) {
|
for (const key in generalData) {
|
||||||
const { section, data, origin } = generalData[key].message
|
const { message: { section, data, origin }, senderID } = generalData[key]
|
||||||
if (!currentArticle.uniqueEntries.hasOwnProperty(origin)) {
|
if (!currentArticle.uniqueEntries.hasOwnProperty(origin)) {
|
||||||
currentArticle.uniqueEntries[origin] = {
|
currentArticle.uniqueEntries[origin] = {
|
||||||
iterations: []
|
iterations: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
currentArticle.sections[section].uniqueEntries.push(origin)
|
currentArticle.sections[section].uniqueEntries.add(origin)
|
||||||
currentArticle.uniqueEntries[origin]['iterations'].push({
|
currentArticle.uniqueEntries[origin]['iterations'].push({
|
||||||
timestamp: generalData[key].time,
|
timestamp: generalData[key].time,
|
||||||
data
|
data,
|
||||||
|
editor: senderID
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
for (const entry in currentArticle.uniqueEntries) {
|
for (const entry in currentArticle.uniqueEntries) {
|
||||||
@ -893,12 +883,38 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const splitAt = (string, index) => [string.slice(0, index), string.slice(index)]
|
function getIterationDetails(uid, targetIndex) {
|
||||||
getRef('article_wrapper').addEventListener('focusout', e => {
|
let merged
|
||||||
if (e.target.closest('.content__area')) {
|
const contributors = new Set()
|
||||||
normalizeText(e.target.closest('.content__area'))
|
const limit = targetIndex || currentArticle.uniqueEntries[uid].iterations.length - 1
|
||||||
|
for (let i = 0; i <= limit; i++) {
|
||||||
|
const { data, editor } = currentArticle.uniqueEntries[uid].iterations[i]
|
||||||
|
merged = i ? updateString(merged, data) : data
|
||||||
|
contributors.add(editor)
|
||||||
}
|
}
|
||||||
})
|
return {
|
||||||
|
data: merged,
|
||||||
|
contributors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showVersionHistory(uid) {
|
||||||
|
const { iterations } = currentArticle.uniqueEntries[uid]
|
||||||
|
const frag = document.createDocumentFragment()
|
||||||
|
iterations.forEach(iter => {
|
||||||
|
frag.prepend(render.historyEntry(iter))
|
||||||
|
})
|
||||||
|
getRef('version_timeline').innerHTML = ''
|
||||||
|
getRef('version_timeline').append(frag)
|
||||||
|
getRef('version_history_panel').classList.remove('hide-completely')
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideVersionHistory() {
|
||||||
|
getRef('version_history_panel').classList.add('hide-completely')
|
||||||
|
getRef('version_timeline').innerHTML = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const splitAt = (string, index) => [string.slice(0, index), string.slice(index)]
|
||||||
|
|
||||||
function normalizeText(target) {
|
function normalizeText(target) {
|
||||||
if (target) {
|
if (target) {
|
||||||
@ -914,15 +930,23 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const detectFormatting = debounce(() => {
|
function manageFormattingOptions() {
|
||||||
const selection = window.getSelection();
|
const selection = window.getSelection();
|
||||||
if (selection.isCollapsed) {
|
if (selection.isCollapsed && selection.focusNode.textContent.trim() !== '') {
|
||||||
getRef('text_toolbar').classList.add('hide-completely')
|
getRef('text_toolbar').classList.add('hide-completely')
|
||||||
document.querySelectorAll('.formatting-button').forEach(elem => elem.classList.remove('active'))
|
document.querySelectorAll('.formatting-button').forEach(elem => elem.classList.remove('active'))
|
||||||
} else {
|
} else {
|
||||||
|
const pos = selection.isCollapsed ? selection.anchorNode.getBoundingClientRect() : selection.getRangeAt(0).getBoundingClientRect()
|
||||||
|
getRef('text_toolbar').style.transform = `translate(${pos.left}px, calc(${pos.bottom + window.pageYOffset}px + 1rem))`
|
||||||
getRef('text_toolbar').classList.remove('hide-completely')
|
getRef('text_toolbar').classList.remove('hide-completely')
|
||||||
const pos = selection.getRangeAt(0).getBoundingClientRect()
|
|
||||||
getRef('text_toolbar').style.transform = `translate(${pos.left}px, calc(${pos.bottom + window.pageYOffset}px + 0.3rem))`
|
getRef('text_toolbar').style.transform = `translate(${pos.left}px, calc(${pos.bottom + window.pageYOffset}px + 0.3rem))`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const detectFormatting = debounce((e) => {
|
||||||
|
const selection = window.getSelection();
|
||||||
|
manageFormattingOptions()
|
||||||
|
if (!selection.isCollapsed) {
|
||||||
const isBold = document.queryCommandState('bold')
|
const isBold = document.queryCommandState('bold')
|
||||||
const isItalic = document.queryCommandState('italic')
|
const isItalic = document.queryCommandState('italic')
|
||||||
const isUnderlined = document.queryCommandState('underline')
|
const isUnderlined = document.queryCommandState('underline')
|
||||||
@ -944,8 +968,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
200)
|
200)
|
||||||
document.addEventListener('selectionchange', detectFormatting)
|
|
||||||
|
|
||||||
|
|
||||||
const replaceBetween = (origin, startIndex, endIndex, insertion) =>
|
const replaceBetween = (origin, startIndex, endIndex, insertion) =>
|
||||||
`${origin.substring(0, startIndex)}${insertion}${origin.substring(endIndex)}`;
|
`${origin.substring(0, startIndex)}${insertion}${origin.substring(endIndex)}`;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user