implemented version history feature in UI
This commit is contained in:
parent
ecf86ef764
commit
05480c7462
66
css/main.css
66
css/main.css
@ -548,9 +548,19 @@ sm-checkbox {
|
|||||||
fill: var(--danger-color);
|
fill: var(--danger-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#main_page {
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
#article_wrapper {
|
#article_wrapper {
|
||||||
justify-self: center;
|
display: -webkit-box;
|
||||||
padding: 1rem 0;
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-box-direction: normal;
|
||||||
|
-ms-flex-direction: column;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 1rem;
|
||||||
gap: 1rem 0;
|
gap: 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -574,6 +584,8 @@ sm-checkbox {
|
|||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
-ms-flex-negative: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
.article-section:not(:last-of-type) {
|
.article-section:not(:last-of-type) {
|
||||||
margin-bottom: 1.5rem;
|
margin-bottom: 1.5rem;
|
||||||
@ -717,32 +729,24 @@ sm-checkbox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#version_history_panel {
|
#version_history_panel {
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
padding: 1rem;
|
width: min(24rem, 100%);
|
||||||
width: min(22rem, 100%);
|
|
||||||
background-color: var(--foreground-color);
|
background-color: var(--foreground-color);
|
||||||
-webkit-box-shadow: -0.5rem 0 1rem rgba(0, 0, 0, 0.1);
|
overflow-y: auto;
|
||||||
box-shadow: -0.5rem 0 1rem rgba(0, 0, 0, 0.1);
|
}
|
||||||
|
#version_history_panel > :first-child {
|
||||||
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#version_timeline {
|
#version_timeline {
|
||||||
|
padding: 1rem;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin-top: 1.5rem;
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.history-entry {
|
.history-entry:not(:last-of-type) {
|
||||||
padding: 1rem;
|
padding-bottom: 1rem;
|
||||||
border-radius: 0.3rem;
|
border-bottom: thin solid rgba(var(--text-color), 0.3);
|
||||||
-webkit-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
}
|
||||||
.history-entry:last-of-type::before {
|
.history-entry:last-of-type::before {
|
||||||
content: "CREATED";
|
content: "CREATED";
|
||||||
@ -753,8 +757,9 @@ sm-checkbox {
|
|||||||
justify-self: flex-start;
|
justify-self: flex-start;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
padding: 0.2rem 0.3rem;
|
padding: 0.2rem 0.3rem;
|
||||||
font-size: 0.8rem;
|
font-size: 0.7rem;
|
||||||
background-color: rgba(var(--text-color), 0.06);
|
border-radius: 0.2rem;
|
||||||
|
border: solid thin rgba(var(--text-color), 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry__time,
|
.entry__time,
|
||||||
@ -763,6 +768,13 @@ sm-checkbox {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.entry__changes .added {
|
||||||
|
background-color: #00e67650;
|
||||||
|
}
|
||||||
|
.entry__changes .removed {
|
||||||
|
background-color: #ff3a4a50;
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 40rem) and (any-hover: none) {
|
@media screen and (max-width: 40rem) and (any-hover: none) {
|
||||||
.cancel-order span {
|
.cancel-order span {
|
||||||
display: none;
|
display: none;
|
||||||
@ -799,6 +811,7 @@ sm-checkbox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.popup__header {
|
.popup__header {
|
||||||
|
grid-column: 1/-1;
|
||||||
padding: 1rem 1.5rem 0 0.5rem;
|
padding: 1rem 1.5rem 0 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -813,6 +826,17 @@ sm-checkbox {
|
|||||||
.hide-on-desktop {
|
.hide-on-desktop {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#main_page.active-sidebar {
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: hidden;
|
||||||
|
grid-template-rows: auto 1fr;
|
||||||
|
grid-template-columns: minmax(0, 1fr) 24rem;
|
||||||
|
}
|
||||||
|
#main_page.active-sidebar #article_wrapper {
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@media (any-hover: hover) {
|
@media (any-hover: hover) {
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
|
|||||||
2
css/main.min.css
vendored
2
css/main.min.css
vendored
File diff suppressed because one or more lines are too long
@ -395,9 +395,6 @@ button:active,
|
|||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
#main_page {
|
|
||||||
}
|
|
||||||
.logo {
|
.logo {
|
||||||
display: grid;
|
display: grid;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -484,9 +481,14 @@ sm-checkbox {
|
|||||||
fill: var(--danger-color);
|
fill: var(--danger-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#main_page {
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
#article_wrapper {
|
#article_wrapper {
|
||||||
justify-self: center;
|
display: flex;
|
||||||
padding: 1rem 0;
|
flex-direction: column;
|
||||||
|
padding: 1rem;
|
||||||
gap: 1rem 0;
|
gap: 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,6 +508,7 @@ sm-checkbox {
|
|||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
flex-shrink: 0;
|
||||||
&:not(:last-of-type) {
|
&:not(:last-of-type) {
|
||||||
margin-bottom: 1.5rem;
|
margin-bottom: 1.5rem;
|
||||||
}
|
}
|
||||||
@ -629,26 +632,24 @@ sm-checkbox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#version_history_panel {
|
#version_history_panel {
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
padding: 1rem;
|
width: min(24rem, 100%);
|
||||||
width: min(22rem, 100%);
|
|
||||||
background-color: var(--foreground-color);
|
background-color: var(--foreground-color);
|
||||||
box-shadow: -0.5rem 0 1rem rgba(0, 0, 0, 0.1);
|
overflow-y: auto;
|
||||||
|
& > :first-child {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#version_timeline {
|
#version_timeline {
|
||||||
|
padding: 1rem;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin-top: 1.5rem;
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
.history-entry {
|
.history-entry {
|
||||||
padding: 1rem;
|
&:not(:last-of-type) {
|
||||||
border-radius: 0.3rem;
|
padding-bottom: 1rem;
|
||||||
user-select: none;
|
border-bottom: thin solid rgba(var(--text-color), 0.3);
|
||||||
|
}
|
||||||
&:last-of-type::before {
|
&:last-of-type::before {
|
||||||
content: "CREATED";
|
content: "CREATED";
|
||||||
letter-spacing: 0.03em;
|
letter-spacing: 0.03em;
|
||||||
@ -656,8 +657,9 @@ sm-checkbox {
|
|||||||
justify-self: flex-start;
|
justify-self: flex-start;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
padding: 0.2rem 0.3rem;
|
padding: 0.2rem 0.3rem;
|
||||||
font-size: 0.8rem;
|
font-size: 0.7rem;
|
||||||
background-color: rgba(var(--text-color), 0.06);
|
border-radius: 0.2rem;
|
||||||
|
border: solid thin rgba(var(--text-color), 0.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.entry__time,
|
.entry__time,
|
||||||
@ -665,6 +667,14 @@ sm-checkbox {
|
|||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
.entry__changes {
|
||||||
|
.added {
|
||||||
|
background-color: #00e67650;
|
||||||
|
}
|
||||||
|
.removed {
|
||||||
|
background-color: #ff3a4a50;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 40rem) and (any-hover: none) {
|
@media screen and (max-width: 40rem) and (any-hover: none) {
|
||||||
.cancel-order {
|
.cancel-order {
|
||||||
@ -701,6 +711,7 @@ sm-checkbox {
|
|||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
.popup__header {
|
.popup__header {
|
||||||
|
grid-column: 1/-1;
|
||||||
padding: 1rem 1.5rem 0 0.5rem;
|
padding: 1rem 1.5rem 0 0.5rem;
|
||||||
}
|
}
|
||||||
#confirmation_popup {
|
#confirmation_popup {
|
||||||
@ -712,6 +723,18 @@ sm-checkbox {
|
|||||||
.hide-on-desktop {
|
.hide-on-desktop {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
#main_page {
|
||||||
|
&.active-sidebar {
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: hidden;
|
||||||
|
grid-template-rows: auto 1fr;
|
||||||
|
grid-template-columns: minmax(0, 1fr) 24rem;
|
||||||
|
#article_wrapper {
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@media (any-hover: hover) {
|
@media (any-hover: hover) {
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
|
|||||||
118
index.html
118
index.html
@ -133,8 +133,8 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="article_wrapper" class="grid page-layout"></div>
|
<div id="article_wrapper"></div>
|
||||||
<section class="grid page-layout">
|
<!-- <div class="grid page-layout">
|
||||||
<div id="action_button_group" class="flex align-center gap-0-5">
|
<div id="action_button_group" class="flex align-center gap-0-5">
|
||||||
<span>
|
<span>
|
||||||
<b>
|
<b>
|
||||||
@ -142,8 +142,8 @@
|
|||||||
</b>
|
</b>
|
||||||
</span>
|
</span>
|
||||||
<button class="actionable-button" title="Add paragraph">
|
<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"
|
||||||
fill="#000000">
|
width="24px" 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="M14 17H4v2h10v-2zm6-8H4v2h16V9zM4 15h16v-2H4v2zM4 5v2h16V5H4z" />
|
||||||
</svg>
|
</svg>
|
||||||
@ -152,7 +152,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</div> -->
|
||||||
<aside id="version_history_panel" class="flex direction-column hide-completely">
|
<aside id="version_history_panel" class="flex direction-column hide-completely">
|
||||||
<div class="flex align-center space-between">
|
<div class="flex align-center space-between">
|
||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
@ -173,7 +173,7 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<ul id="version_timeline" class="flex direction-column gap-0-5"></ul>
|
<ul id="version_timeline" class="flex direction-column gap-1-5"></ul>
|
||||||
</aside>
|
</aside>
|
||||||
</article>
|
</article>
|
||||||
<sm-popup id="article_list_popup">
|
<sm-popup id="article_list_popup">
|
||||||
@ -270,7 +270,7 @@
|
|||||||
<p><br></p>
|
<p><br></p>
|
||||||
</template>
|
</template>
|
||||||
<template id="history_entry_template">
|
<template id="history_entry_template">
|
||||||
<li class="history-entry interact grid gap-0-5">
|
<li class="history-entry grid gap-0-5">
|
||||||
<div class="flex align-center space-between">
|
<div class="flex align-center space-between">
|
||||||
<time class="entry__time"></time>
|
<time class="entry__time"></time>
|
||||||
<span class="entry__score"></span>
|
<span class="entry__score"></span>
|
||||||
@ -279,6 +279,7 @@
|
|||||||
<div class="label">Author</div>
|
<div class="label">Author</div>
|
||||||
<span class="entry__author breakable"></span>
|
<span class="entry__author breakable"></span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="entry__changes"></div>
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
<script id="ui_utils">
|
<script id="ui_utils">
|
||||||
@ -673,8 +674,16 @@
|
|||||||
returns newStr
|
returns newStr
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
function splitHTML(string) {
|
||||||
|
const el = createElement('div', {
|
||||||
|
innerHTML: string
|
||||||
|
});
|
||||||
|
return Array.from(el.childNodes).map(e => (e.outerHTML || e.innerHTML || e.nodeValue).split(' ').filter(t => t)).flat();
|
||||||
|
}
|
||||||
|
|
||||||
function getDiff(oldStr, newStr) {
|
function getDiff(oldStr, newStr) {
|
||||||
let d = patienceDiff(oldStr.split(" "), newStr.split(" "), true);
|
console.log(splitHTML(oldStr), splitHTML(newStr))
|
||||||
|
let d = patienceDiff(splitHTML(oldStr), splitHTML(newStr), true);
|
||||||
return [d.aMoveIndex, d.bMove, d.bMoveIndex]
|
return [d.aMoveIndex, d.bMove, d.bMoveIndex]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -732,16 +741,17 @@
|
|||||||
contentArea.querySelectorAll('[style=""]').forEach((el) => {
|
contentArea.querySelectorAll('[style=""]').forEach((el) => {
|
||||||
el.removeAttribute('style')
|
el.removeAttribute('style')
|
||||||
})
|
})
|
||||||
const clean = DOMPurify.sanitize(contentArea.innerHTML);
|
const clean = DOMPurify.sanitize(contentArea.innerHTML.split('\n').map(v => v.trim()).filter(v => v));
|
||||||
if (clean.trim() === '') return
|
if (clean.trim() === '') return
|
||||||
let previousVersion, contributors
|
let previousVersion, contributors
|
||||||
if (!isUniqueEntry)
|
if (!isUniqueEntry)
|
||||||
({ data: previousVersion, contributors } = getIterationDetails(uid))
|
({ data: previousVersion, contributors } = getIterationDetails(uid))
|
||||||
const entry = {
|
const entry = {
|
||||||
section: contentCard.closest('.article-section').dataset.id,
|
section: contentCard.closest('.article-section').dataset.sectionId,
|
||||||
origin: isUniqueEntry ? floCrypto.randString(16, true) : uid,
|
origin: isUniqueEntry ? floCrypto.randString(16, true) : uid,
|
||||||
data: isUniqueEntry ? clean : getDiff(previousVersion, clean),
|
data: isUniqueEntry ? clean : getDiff(previousVersion, clean),
|
||||||
}
|
}
|
||||||
|
console.log(entry)
|
||||||
floCloudAPI.sendGeneralData(entry, `${currentArticle.id}_gd`)
|
floCloudAPI.sendGeneralData(entry, `${currentArticle.id}_gd`)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
console.log(res)
|
console.log(res)
|
||||||
@ -750,7 +760,10 @@
|
|||||||
contentArea.innerHTML = ''
|
contentArea.innerHTML = ''
|
||||||
})
|
})
|
||||||
} else if (e.target.closest('.version-history-button')) {
|
} else if (e.target.closest('.version-history-button')) {
|
||||||
showVersionHistory(e.target.closest('.content-card').dataset.uid)
|
if (isHistoryPanelOpen)
|
||||||
|
hideVersionHistory()
|
||||||
|
else
|
||||||
|
showVersionHistory(e.target.closest('.content-card').dataset.uid)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
getRef('article_wrapper').addEventListener("paste", e => {
|
getRef('article_wrapper').addEventListener("paste", e => {
|
||||||
@ -776,6 +789,15 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
getRef('article_wrapper').addEventListener("dblclick", e => {
|
||||||
|
if (e.target.closest('.heading')) {
|
||||||
|
const target = e.target.closest('.heading')
|
||||||
|
if (!target.isContentEditable) {
|
||||||
|
target.contentEditable = true
|
||||||
|
target.focus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
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)
|
document.removeEventListener('selectionchange', detectFormatting)
|
||||||
@ -785,6 +807,12 @@
|
|||||||
if (!e.relatedTarget?.closest('#text_toolbar')) {
|
if (!e.relatedTarget?.closest('#text_toolbar')) {
|
||||||
getRef('text_toolbar').classList.add('hide-completely')
|
getRef('text_toolbar').classList.add('hide-completely')
|
||||||
}
|
}
|
||||||
|
} else if (e.target.closest('.heading')) {
|
||||||
|
const target = e.target.closest('.heading')
|
||||||
|
if (target.isContentEditable) {
|
||||||
|
floGlobals.appObjects[currentArticle.id].sections[target.dataset.index].title = target.textContent.trim()
|
||||||
|
target.contentEditable = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const childObserver = new MutationObserver((mutations, observer) => {
|
const childObserver = new MutationObserver((mutations, observer) => {
|
||||||
@ -808,10 +836,11 @@
|
|||||||
<script>
|
<script>
|
||||||
let currentArticle = {}
|
let currentArticle = {}
|
||||||
const render = {
|
const render = {
|
||||||
section(sectionID, { title, uniqueEntries }) {
|
section(sectionID, { title, uniqueEntries }, index) {
|
||||||
const section = getRef('section_template').content.cloneNode(true)
|
const section = getRef('section_template').content.cloneNode(true)
|
||||||
const frag = document.createDocumentFragment()
|
const frag = document.createDocumentFragment()
|
||||||
section.children[1].dataset.id = sectionID
|
section.children[0].dataset.index = index
|
||||||
|
section.children[1].dataset.sectionId = sectionID
|
||||||
section.querySelector('.heading').textContent = title
|
section.querySelector('.heading').textContent = title
|
||||||
currentArticle.sections[sectionID].uniqueEntries.forEach(entry => {
|
currentArticle.sections[sectionID].uniqueEntries.forEach(entry => {
|
||||||
frag.append(render.contentCard(entry))
|
frag.append(render.contentCard(entry))
|
||||||
@ -837,18 +866,33 @@
|
|||||||
const { title } = floGlobals.appObjects.cc.articleList[id]
|
const { title } = floGlobals.appObjects.cc.articleList[id]
|
||||||
const { writer, sections } = currentArticle
|
const { writer, sections } = currentArticle
|
||||||
const frag = document.createDocumentFragment()
|
const frag = document.createDocumentFragment()
|
||||||
|
let index = 0
|
||||||
for (const sectionID in sections) {
|
for (const sectionID in sections) {
|
||||||
frag.append(render.section(sectionID, sections[sectionID]))
|
frag.append(render.section(sectionID, sections[sectionID], index))
|
||||||
|
index += 1
|
||||||
}
|
}
|
||||||
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) {
|
historyEntry(details, oldText) {
|
||||||
const { editor, timestamp } = details
|
const { editor, timestamp, data } = details
|
||||||
const clone = getRef('history_entry_template').content.cloneNode(true).firstElementChild;
|
const clone = getRef('history_entry_template').content.cloneNode(true).firstElementChild;
|
||||||
clone.querySelector('.entry__time').textContent = getFormattedTime(timestamp)
|
clone.querySelector('.entry__time').textContent = getFormattedTime(timestamp)
|
||||||
clone.querySelector('.entry__author').textContent = editor
|
clone.querySelector('.entry__author').textContent = editor
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
console.log(data)
|
||||||
|
const [removedAt, addedWords, addedAt] = data
|
||||||
|
const changed = oldText.split(' ')
|
||||||
|
let firstAddedPlace
|
||||||
|
let startIndex, endIndex
|
||||||
|
let addedNodes
|
||||||
|
addedAt.forEach((place, index) => {
|
||||||
|
changed.splice(place, 0, `<span class="added">${addedWords[index]}</span>`)
|
||||||
|
})
|
||||||
|
removedAt.forEach(place => changed[place] = `<span class="removed">${changed[place]}</span>`)
|
||||||
|
clone.querySelector('.entry__changes').innerHTML = changed.join(' ')
|
||||||
|
}
|
||||||
return clone
|
return clone
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -866,7 +910,7 @@
|
|||||||
currentArticle['uniqueEntries'] = {}
|
currentArticle['uniqueEntries'] = {}
|
||||||
for (const key in generalData) {
|
for (const key in generalData) {
|
||||||
const { message: { section, data, origin }, senderID } = generalData[key]
|
const { message: { section, data, origin }, senderID } = generalData[key]
|
||||||
if (!currentArticle.uniqueEntries.hasOwnProperty(origin)) {
|
if (!currentArticle.uniqueEntries.hasOwnProperty(origin)) { // check if gen data has origin that's already defined
|
||||||
currentArticle.uniqueEntries[origin] = {
|
currentArticle.uniqueEntries[origin] = {
|
||||||
iterations: []
|
iterations: []
|
||||||
}
|
}
|
||||||
@ -878,6 +922,9 @@
|
|||||||
editor: senderID
|
editor: senderID
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
for (const sectionID in currentArticle.sections) {
|
||||||
|
currentArticle.sections[sectionID].uniqueEntries = [...currentArticle.sections[sectionID].uniqueEntries].reverse()
|
||||||
|
}
|
||||||
for (const entry in currentArticle.uniqueEntries) {
|
for (const entry in currentArticle.uniqueEntries) {
|
||||||
currentArticle.uniqueEntries[entry]['iterations'].sort((a, b) => a.timestamp - b.timestamp)
|
currentArticle.uniqueEntries[entry]['iterations'].sort((a, b) => a.timestamp - b.timestamp)
|
||||||
}
|
}
|
||||||
@ -898,20 +945,47 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isHistoryPanelOpen = false
|
||||||
function showVersionHistory(uid) {
|
function showVersionHistory(uid) {
|
||||||
const { iterations } = currentArticle.uniqueEntries[uid]
|
const { iterations } = currentArticle.uniqueEntries[uid]
|
||||||
const frag = document.createDocumentFragment()
|
const frag = document.createDocumentFragment()
|
||||||
iterations.forEach(iter => {
|
let mergedChanges/* , oldText */
|
||||||
frag.prepend(render.historyEntry(iter))
|
// oldText = createElement('div', {
|
||||||
|
// innerHTML: mergedChanges
|
||||||
|
// }).textContent
|
||||||
|
iterations.forEach((iter, index) => {
|
||||||
|
// const tempText = createElement('div', {
|
||||||
|
// innerHTML: tempMergedChanges
|
||||||
|
// }).textContent
|
||||||
|
// const changes = {
|
||||||
|
// diff: getDiff(oldText, tempText),
|
||||||
|
// }
|
||||||
|
// const versions = {
|
||||||
|
// oldText: mergedChanges,
|
||||||
|
// newText: tempMergedChanges
|
||||||
|
// }
|
||||||
|
// oldText = tempText
|
||||||
|
// console.log(mergedChanges, iter.data, tempMergedChanges)
|
||||||
|
frag.prepend(render.historyEntry(iter, mergedChanges))
|
||||||
|
mergedChanges = index ? updateString(mergedChanges, iter.data) : iter.data
|
||||||
|
// mergedChanges = tempMergedChanges
|
||||||
})
|
})
|
||||||
getRef('version_timeline').innerHTML = ''
|
getRef('version_timeline').innerHTML = ''
|
||||||
getRef('version_timeline').append(frag)
|
getRef('version_timeline').append(frag)
|
||||||
getRef('version_history_panel').classList.remove('hide-completely')
|
if (!isHistoryPanelOpen) {
|
||||||
|
getRef('version_history_panel').classList.remove('hide-completely')
|
||||||
|
getRef('main_page').classList.add('active-sidebar')
|
||||||
|
isHistoryPanelOpen = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideVersionHistory() {
|
function hideVersionHistory() {
|
||||||
getRef('version_history_panel').classList.add('hide-completely')
|
if (isHistoryPanelOpen) {
|
||||||
getRef('version_timeline').innerHTML = ''
|
getRef('version_history_panel').classList.add('hide-completely')
|
||||||
|
getRef('version_timeline').innerHTML = ''
|
||||||
|
getRef('main_page').classList.remove('active-sidebar')
|
||||||
|
isHistoryPanelOpen = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const splitAt = (string, index) => [string.slice(0, index), string.slice(index)]
|
const splitAt = (string, index) => [string.slice(0, index), string.slice(index)]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user