Feature update and bug fixes

- Added article title and heading renaming in-place for sub-admins
- fixed bug for version history
- version history UX improvements
This commit is contained in:
sairaj mote 2021-11-18 20:11:32 +05:30
parent fed6e720f6
commit e155bfc341
5 changed files with 459 additions and 140 deletions

View File

@ -3427,4 +3427,234 @@ customElements.define('sm-switch', class extends HTMLElement {
}
}
})
const textField = document.createElement('template')
textField.innerHTML = `
<style>
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
:host{
--accent-color: #4d2588;
--text-color: 17, 17, 17;
--background-color: 255, 255, 255;
}
.text-field{
display: flex;
align-items: center;
}
.text{
padding: 0.6rem 0;
transition: background-color 0.3s;
border-bottom: 0.15rem solid transparent;
overflow-wrap: break-word;
word-wrap: break-word;
word-break: break-all;
word-break: break-word;
-moz-hyphens: auto;
-webkit-hyphens: auto;
hyphens: auto;
}
.text:focus{
outline: none;
border-bottom: 0.15rem solid var(--accent-color);
}
.text:focus-visible{
outline: none;
background: solid rgba(var(--text-color), 0.06);
}
.editable{
border-bottom: 0.15rem solid rgba(var(--text-color), 0.6);
}
.icon-container{
display: grid;
position: relative;
margin-left: 0.5rem;
}
:host([disabled]) .icon-container{
display: none;
}
.icon{
grid-area: 1/-1;
cursor: pointer;
height: 1.2rem;
width: 1.2rem;
fill: rgba(var(--text-color), 1);
}
.hide{
display: none;
}
</style>
<div class="text-field">
<div class="text" part="text"></div>
<div tabindex="0" class="icon-container">
<svg class="edit-button icon" title="edit" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg>
<svg class="save-button icon hide" title="Save" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"/></svg>
</div>
</div>
`
customElements.define('text-field', class extends HTMLElement {
constructor() {
super()
this.attachShadow({
mode: 'open'
}).append(textField.content.cloneNode(true))
this.textField = this.shadowRoot.querySelector('.text-field')
this.textContainer = this.textField.children[0]
this.iconsContainer = this.textField.children[1]
this.editButton = this.textField.querySelector('.edit-button')
this.saveButton = this.textField.querySelector('.save-button')
this.isTextEditable = false
this.isDisabled = false
this.fireEvent = this.fireEvent.bind(this)
this.setEditable = this.setEditable.bind(this)
this.setNonEditable = this.setNonEditable.bind(this)
this.revert = this.revert.bind(this)
}
static get observedAttributes() {
return ['disabled', 'value']
}
get value() {
return this.text
}
set value(val) {
this.setAttribute('value', val)
}
set disabled(val) {
this.isDisabled = val
if (this.isDisabled)
this.setAttribute('disabled', '')
else
this.removeAttribute('disabled')
}
fireEvent(value) {
let event = new CustomEvent('change', {
bubbles: true,
cancelable: true,
composed: true,
detail: {
value
}
});
this.dispatchEvent(event);
}
setEditable() {
if (this.isTextEditable) return
this.textContainer.contentEditable = true
this.textContainer.classList.add('editable')
this.textContainer.focus()
document.execCommand('selectAll', false, null);
this.editButton.animate(this.rotateOut, this.animOptions).onfinish = () => {
this.editButton.classList.add('hide')
}
setTimeout(() => {
this.saveButton.classList.remove('hide')
this.saveButton.animate(this.rotateIn, this.animOptions)
}, 100);
this.isTextEditable = true
}
setNonEditable() {
if (!this.isTextEditable) return
this.textContainer.contentEditable = false
this.textContainer.classList.remove('editable')
const newValue = this.textContainer.textContent.trim()
if (this.text !== newValue && newValue !== '') {
this.setAttribute('value', this.textContainer.textContent)
this.text = this.textContainer.textContent.trim()
this.fireEvent(this.text)
} else {
this.value = this.text
}
this.saveButton.animate(this.rotateOut, this.animOptions).onfinish = () => {
this.saveButton.classList.add('hide')
}
setTimeout(() => {
this.editButton.classList.remove('hide')
this.editButton.animate(this.rotateIn, this.animOptions)
}, 100);
this.isTextEditable = false
}
revert() {
if (this.textContainer.isContentEditable) {
this.value = this.text
this.setNonEditable()
}
}
connectedCallback() {
this.text
if (this.hasAttribute('value')) {
this.text = this.getAttribute('value')
this.textContainer.textContent = this.text
}
if (this.hasAttribute('disabled'))
this.isDisabled = true
else
this.isDisabled = false
this.rotateOut = [
{
transform: 'rotate(0)',
opacity: 1
},
{
transform: 'rotate(90deg)',
opacity: 0
},
]
this.rotateIn = [
{
transform: 'rotate(-90deg)',
opacity: 0
},
{
transform: 'rotate(0)',
opacity: 1
},
]
this.animOptions = {
duration: 300,
easing: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
fill: 'forwards'
}
if (!this.isDisabled) {
this.iconsContainer.classList.remove('hide')
this.textContainer.addEventListener('dblclick', this.setEditable)
this.editButton.addEventListener('click', this.setEditable)
this.saveButton.addEventListener('click', this.setNonEditable)
}
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'disabled') {
if (this.hasAttribute('disabled')) {
this.textContainer.removeEventListener('dblclick', this.setEditable)
this.editButton.removeEventListener('click', this.setEditable)
this.saveButton.removeEventListener('click', this.setNonEditable)
this.revert()
}
else {
this.textContainer.addEventListener('dblclick', this.setEditable)
this.editButton.addEventListener('click', this.setEditable)
this.saveButton.addEventListener('click', this.setNonEditable)
}
} else if (name === 'value') {
this.text = newValue
this.textContainer.textContent = newValue
}
}
disconnectedCallback() {
this.textContainer.removeEventListener('dblclick', this.setEditable)
this.editButton.removeEventListener('click', this.setEditable)
this.saveButton.removeEventListener('click', this.setNonEditable)
}
})

View File

@ -552,6 +552,31 @@ sm-checkbox {
grid-template-columns: minmax(0, 1fr);
}
#current_article_title {
font-weight: 700;
}
.article-link {
padding: 1rem;
color: rgba(var(--text-color), 0.8);
font-weight: 500;
border-radius: 0.3rem;
}
.article-link::first-letter {
text-transform: uppercase;
}
.default-article {
margin-left: auto;
font-size: 0.7rem;
background-color: #00e67650;
padding: 0.2rem 0.4rem;
border-radius: 0.3rem;
font-weight: 700;
letter-spacing: 0.05em;
color: rgba(var(--text-color), 0.8);
}
#article_wrapper {
display: -webkit-box;
display: -ms-flexbox;
@ -565,6 +590,7 @@ sm-checkbox {
}
.heading {
font-weight: 700;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
@ -592,16 +618,12 @@ sm-checkbox {
.article-section:not(:last-of-type) {
margin-bottom: 1.5rem;
}
.content-card-container {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
gap: 0.5rem;
.article-section::-webkit-scrollbar {
display: none;
}
.content-card {
scroll-snap-align: start;
scroll-snap-align: center;
width: min(46ch, 100%);
-ms-flex-negative: 0;
flex-shrink: 0;
@ -778,7 +800,7 @@ sm-checkbox {
}
.entry__changes .added > *,
.entry__changes .removed > * {
background-color: inherit;
background-color: transparent;
}
.entry__changes .added {
background-color: #00e67650;

2
css/main.min.css vendored

File diff suppressed because one or more lines are too long

View File

@ -485,6 +485,30 @@ sm-checkbox {
grid-template-columns: minmax(0, 1fr);
}
#current_article_title {
font-weight: 700;
}
.article-link {
padding: 1rem;
color: rgba(var(--text-color), 0.8);
font-weight: 500;
border-radius: 0.3rem;
&::first-letter {
text-transform: uppercase;
}
}
.default-article {
margin-left: auto;
font-size: 0.7rem;
background-color: #00e67650;
padding: 0.2rem 0.4rem;
border-radius: 0.3rem;
font-weight: 700;
letter-spacing: 0.05em;
color: rgba(var(--text-color), 0.8);
}
#article_wrapper {
display: flex;
flex-direction: column;
@ -493,6 +517,7 @@ sm-checkbox {
}
.heading {
font-weight: 700;
display: flex;
&::before {
content: "";
@ -513,14 +538,12 @@ sm-checkbox {
&:not(:last-of-type) {
margin-bottom: 1.5rem;
}
&::-webkit-scrollbar {
display: none;
}
}
.content-card-container {
display: flex;
gap: 0.5rem;
}
.content-card {
scroll-snap-align: start;
scroll-snap-align: center;
width: min(46ch, 100%);
flex-shrink: 0;
border-radius: 0.5rem;
@ -675,7 +698,7 @@ sm-checkbox {
color: rgba(var(--text-color), 0.8);
.added > *,
.removed > * {
background-color: inherit;
background-color: transparent;
}
.added {
background-color: #00e67650;

View File

@ -80,7 +80,7 @@
<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
</svg>
</button>
<h4 id="current_article_name"></h4>
<text-field id="current_article_title"></text-field>
<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">
@ -189,6 +189,7 @@
<sm-input placeholder="Search articles" type="search"></sm-input>
</div>
</header>
<div id="article_list"></div>
</sm-popup>
<sm-popup id="create_article_popup">
<header slot="header" class="popup__header">
@ -221,14 +222,14 @@
</sm-form>
</sm-popup>
<template id="section_template">
<h4 class="heading"></h4>
<text-field class="heading"></text-field>
<section class="article-section">
<div class="content-card content-card--empty">
<div class="content__area" data-type="origin" placeholder="Write something new or edit existing content"
contenteditable="true"></div>
<button class="submit-entry">Submit</button>
<button class="submit-entry hide-completely">Submit</button>
</div>
<div class="content-card-container"></div>
<!-- <div class="content-card-container"></div> -->
</section>
</template>
<template id="content_card_template">
@ -251,11 +252,11 @@
<path
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" />
</svg>
<span class="content__score">47</span>
<span class="content__score">0</span>
</button>
</div>
<div class="content__editor"></div>
<button class="submit-entry">Submit</button>
<button class="submit-entry hide-completely">Submit</button>
</div>
</div>
</template>
@ -533,51 +534,26 @@
}
} else {
if (targetPage.includes('/')) {
const pages = targetPage.split('/')
pageId = pages[1]
if (targetPage.includes('?')) {
const splitAddress = targetPage.split('?')
searchParams = splitAddress.pop()
const pages = splitAddress.pop().split('/')
pageId = pages[1]
subPageId = pages[2]
} else {
const pages = targetPage.split('/')
pageId = pages[1]
subPageId = pages[2]
}
} else {
pageId = targetPage
}
}
if (pagesData.lastPage !== pageId) {
let target
switch (pageId) {
case 'dashboard':
target = 'dashboard'
break;
case 'my_orders':
target = 'my_orders_section'
break;
case 'market':
target = 'market_orders_section'
break;
case 'wallet':
target = 'user_section'
break;
}
if (target) {
document.querySelectorAll('.mobile-page').forEach(elem => elem.classList.add('hide-on-mobile'))
getRef(target).classList.remove('hide-on-mobile')
document.querySelectorAll('.bottom_nav__item').forEach(elem => elem.classList.remove('bottom_nav__item--active'))
document.querySelector(`.bottom_nav__item[href="#/${pageId}"]`).classList.add('bottom_nav__item--active')
getRef(target)?.animate([
{
transform: 'translateY(1rem)',
opacity: 0,
},
{
transform: 'none',
opacity: 1,
},
],
{
duration: 300,
easing: 'ease'
})
pagesData.lastPage = target
if (!pagesData.openedPages.includes(target)) {
pagesData.openedPages.push(target)
}
document.querySelectorAll('.mobile-page').forEach(elem => elem.classList.add('hide-on-mobile'))
pagesData.lastPage = pageId
if (!pagesData.openedPages.includes(pageId)) {
pagesData.openedPages.push(pageId)
}
}
}
@ -732,26 +708,62 @@
}
}
const checkEntry = debounce(e => {
const contentCard = e.target.closest('.content-card')
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')
})
const clean = DOMPurify.sanitize(contentArea.innerHTML.split('\n').map(v => v.trim()).filter(v => v));
if (clean === '' || clean === '<p><br></p>') {
contentCard.querySelector('.submit-entry').classList.add('hide-completely')
} else {
const hash = Crypto.SHA256(clean)
let previousHash
if (!isUniqueEntry) {
({ hash: previousHash = '' } = getIterationDetails(uid))
} else {
previousHash = ''
}
if (previousHash !== hash)
contentCard.querySelector('.submit-entry').classList.remove('hide-completely')
else
contentCard.querySelector('.submit-entry').classList.add('hide-completely')
}
}, 300)
getRef('article_wrapper').addEventListener('input', e => {
if (e.target.closest('.content__area')) {
checkEntry(e)
}
})
getRef('article_wrapper').addEventListener('click', e => {
if (e.target.closest('.submit-entry')) {
const contentCard = e.target.closest('.content-card')
const contentArea = contentCard.querySelector('.content__area')
const uid = contentCard.dataset.uid
const isUniqueEntry = contentArea.dataset.type === 'origin'
const parentSection = contentCard.closest('.article-section')
const sectionID = parentSection.dataset.sectionId
contentArea.querySelectorAll('[style=""]').forEach((el) => {
el.removeAttribute('style')
})
const clean = DOMPurify.sanitize(contentArea.innerHTML.split('\n').map(v => v.trim()).filter(v => v));
// const clean = contentArea.innerText.trim();
if (clean === '') return
const hash = Crypto.SHA256(clean)
let previousVersion, contributors
if (!isUniqueEntry)
({ data: previousVersion, contributors, hash: previousHash } = getIterationDetails(uid))
let previousVersion, previousHash
if (!isUniqueEntry) {
({ data: previousVersion, hash: previousHash = '' } = getIterationDetails(uid))
} else {
previousHash = ''
}
if (previousHash !== hash) {
const timestamp = Date.now()
const entry = {
section: contentCard.closest('.article-section').dataset.sectionId,
section: sectionID,
origin: isUniqueEntry ? floCrypto.randString(16, true) : uid,
data: isUniqueEntry ? clean : getDiff(previousVersion, clean),
hash
@ -759,21 +771,26 @@
floCloudAPI.sendGeneralData(entry, `${currentArticle.id}_gd`)
.then((res) => {
console.log(res)
e.target.closest('.submit-entry').classList.add('hide-completely')
notify('sent data', 'success')
if (isUniqueEntry)
if (isUniqueEntry) {
contentArea.innerHTML = ''
else {
currentArticle.sections[sectionID].uniqueEntries.push(entry.origin)
currentArticle.uniqueEntries[entry.origin] = { iterations: [{ ...entry, timestamp }] }
parentSection.firstElementChild.after(render.contentCard(entry.origin))
} else {
currentArticle.uniqueEntries[entry.origin].iterations.push({ ...entry, timestamp })
}
})
} else {
notify("Duplicate entry!", 'error')
}
} else if (e.target.closest('.version-history-button')) {
if (isHistoryPanelOpen)
const entryUid = e.target.closest('.content-card').dataset.uid
if (versionHistory.isOpen && entryUid === versionHistory.entryUid)
hideVersionHistory()
else
showVersionHistory(e.target.closest('.content-card').dataset.uid)
showVersionHistory(entryUid)
}
})
getRef('article_wrapper').addEventListener("paste", e => {
@ -786,11 +803,28 @@
event.preventDefault();
})
getRef('current_article_title').addEventListener("change", e => {
floGlobals.appObjects.cc.articleList[currentArticle.id].title = e.target.value.trim()
floCloudAPI.updateObjectData('cc')
.then((res) => {
notify('Renamed article', 'success')
})
.catch(err => console.error(err))
})
getRef('article_wrapper').addEventListener("change", e => {
if (e.target.classList.contains('heading')) {
floGlobals.appObjects[currentArticle.id].sections[e.target.dataset.index].title = e.target.value.trim()
floCloudAPI.updateObjectData(currentArticle.id)
.then((res) => {
notify('Updated heading', 'success')
})
.catch(err => console.error(err))
}
})
getRef('article_wrapper').addEventListener("focusin", e => {
if (e.target.closest('.content__area')) {
document.addEventListener('selectionchange', detectFormatting)
const target = e.target.closest('.content__area')
document.addEventListener('selectionchange', detectFormatting)
if (target.childNodes[0] === undefined) {
target.innerHTML = `<p><br/></p>`
}
@ -799,17 +833,9 @@
})
}
})
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 => {
if (e.target.closest('.content__area')) {
const target = e.target.closest('.content__area')
normalizeText(e.target.closest('.content__area'))
document.removeEventListener('selectionchange', detectFormatting)
const selection = window.getSelection()
@ -817,12 +843,6 @@
getRef('text_toolbar').classList.add('hide-completely')
childObserver.disconnect()
}
} 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) => {
@ -846,17 +866,38 @@
<script>
let currentArticle = {}
const render = {
section(sectionID, { title, uniqueEntries }, index) {
const section = getRef('section_template').content.cloneNode(true)
article(id) {
currentArticle.id = id
parseArticleData()
const { title } = floGlobals.appObjects.cc.articleList[id]
const { writer, sections } = currentArticle
const frag = document.createDocumentFragment()
section.children[0].dataset.index = index
section.children[1].dataset.sectionId = sectionID
section.querySelector('.heading').textContent = title
currentArticle.sections[sectionID].uniqueEntries.forEach(entry => {
frag.append(render.contentCard(entry))
let index = 0
for (const sectionID in sections) {
frag.append(render.section(sectionID, sections[sectionID], index))
index += 1
}
if (!floGlobals.subAdmins.includes(myFloID)) {
getRef('current_article_title').setAttribute('disabled', '')
}
getRef('current_article_title').value = title
getRef('article_wrapper').innerHTML = ''
getRef('article_wrapper').append(frag)
},
articleLink(uid, details, isDefaultArticle) {
const { timestamp, title } = details
const link = createElement('a', {
textContent: title,
attributes: { href: `#/home?articleID=${uid}` },
className: 'article-link flex interact'
})
section.querySelector('.content-card-container').append(frag)
return section
if (isDefaultArticle) {
link.append(createElement('span', {
className: 'default-article',
textContent: 'Active'
}))
}
return link
},
contentCard(id, version = 0) {
const clone = getRef('content_card_template').content.cloneNode(true).firstElementChild;
@ -870,21 +911,6 @@
// clone.querySelector('.content__score').textContent = score;
return clone
},
article(id) {
currentArticle.id = id
parseArticleData()
const { title } = floGlobals.appObjects.cc.articleList[id]
const { writer, sections } = currentArticle
const frag = document.createDocumentFragment()
let index = 0
for (const sectionID in sections) {
frag.append(render.section(sectionID, sections[sectionID], index))
index += 1
}
getRef('current_article_name').textContent = title
getRef('article_wrapper').innerHTML = ''
getRef('article_wrapper').append(frag)
},
historyEntry(details, oldText) {
const { editor, timestamp, data } = details
const clone = getRef('history_entry_template').content.cloneNode(true).firstElementChild;
@ -905,15 +931,34 @@
for (i = index + 1; (changed[i + 1] && changed[i + 1].hasOwnProperty('added') && changed[i + 1].added === type); i++) {
consecutiveWords.push(changed[i].content)
}
changed.splice(index, i - index)
console.log(consecutiveWords)
if (i - index > 1)
changed.splice((index + 1), (i - index - 1))
return `<span class="${type ? 'added' : 'removed'}">${consecutiveWords.join(' ')}</span>`
} else return word
})
clone.querySelector('.entry__changes').innerHTML = final.join(' ')
clone.querySelector('.entry__changes').innerHTML = DOMPurify.sanitize(final.join(' '))
} else {
clone.querySelector('.entry__changes').innerHTML = DOMPurify.sanitize(data)
}
return clone
}
},
section(sectionID, { title, uniqueEntries }, index) {
const section = getRef('section_template').content.cloneNode(true)
const frag = document.createDocumentFragment()
section.children[0].dataset.index = index
section.children[1].dataset.sectionId = sectionID
if (floGlobals.subAdmins.includes(myFloID)) {
section.querySelector('.content-card--empty').remove()
} else {
section.querySelector('.heading').setAttribute('disabled', '')
}
section.querySelector('.heading').setAttribute('value', title)
currentArticle.sections[sectionID].uniqueEntries.forEach(entry => {
frag.append(render.contentCard(entry))
})
section.querySelector('.article-section').append(frag)
return section
},
}
function parseArticleData() {
@ -950,6 +995,17 @@
}
}
function renderArticleList() {
getRef('article_list').innerHTML = ``
const frag = document.createDocumentFragment()
const { articleList, defaultArticle } = floGlobals.appObjects.cc
for (articleKey in articleList) {
const isDefaultArticle = defaultArticle === articleKey
frag.prepend(render.articleLink(articleKey, articleList[articleKey], isDefaultArticle))
}
getRef('article_list').append(frag)
}
function getIterationDetails(uid, targetIndex) {
let merged
const contributors = new Set()
@ -965,47 +1021,34 @@
hash: currentArticle.uniqueEntries[uid].iterations[limit].hash
}
}
let isHistoryPanelOpen = false
const versionHistory = {
isOpen: false,
entryUid: ''
}
function showVersionHistory(uid) {
versionHistory.entryUid = uid
const { iterations } = currentArticle.uniqueEntries[uid]
const frag = document.createDocumentFragment()
let mergedChanges/* , oldText */
// oldText = createElement('div', {
// innerHTML: mergedChanges
// }).textContent
let mergedChanges
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').append(frag)
if (!isHistoryPanelOpen) {
if (!versionHistory.isOpen) {
getRef('version_history_panel').classList.remove('hide-completely')
getRef('main_page').classList.add('active-sidebar')
isHistoryPanelOpen = true
versionHistory.isOpen = true
}
}
function hideVersionHistory() {
if (isHistoryPanelOpen) {
if (versionHistory.isOpen) {
getRef('version_history_panel').classList.add('hide-completely')
getRef('version_timeline').innerHTML = ''
getRef('main_page').classList.remove('active-sidebar')
isHistoryPanelOpen = false
versionHistory.isOpen = false
}
}
@ -1203,6 +1246,7 @@
])
.then(() => {
render.article(floGlobals.appObjects.cc.defaultArticle)
renderArticleList()
})
console.log(result)