feat(wiki): improvements to the wiki's UI

This commit is contained in:
Tasia Iso 2024-02-22 18:11:13 +01:00
parent a4bf3542e0
commit 1d5cdf9607
4 changed files with 39 additions and 11 deletions

View File

@ -5,6 +5,7 @@ class TfCollectionElement extends LitElement {
static get properties() { static get properties() {
return { return {
whoami: {type: String}, whoami: {type: String},
category: {type: String},
collection: {type: Object}, collection: {type: Object},
selected_id: {type: String}, selected_id: {type: String},
is_creating: {type: Boolean}, is_creating: {type: Boolean},
@ -68,7 +69,7 @@ class TfCollectionElement extends LitElement {
<link rel="stylesheet" href="tildefriends.css"/> <link rel="stylesheet" href="tildefriends.css"/>
<span class="inline-flex-row"> <span class="inline-flex-row">
<select class="button" @change=${this.on_selected} id="select" value=${this.selected_id}> <select class="button" @change=${this.on_selected} id="select" value=${this.selected_id}>
<option value="" ?selected=${this.selected_id === ''} disabled hidden>(select)</option> <option value="" ?selected=${this.selected_id === ''} disabled hidden>(select ${this.category})</option>
${Object.values(this.collection ?? {}).sort((x, y) => x.name.localeCompare(y.name)).map(x => html`<option value=${x.id} ?selected=${this.selected_id === x.id}>${x.name}</option>`)} ${Object.values(this.collection ?? {}).sort((x, y) => x.name.localeCompare(y.name)).map(x => html`<option value=${x.id} ?selected=${this.selected_id === x.id}>${x.name}</option>`)}
</select> </select>
<span ?hidden=${!this.is_renaming || !this.whoami}> <span ?hidden=${!this.is_renaming || !this.whoami}>

View File

@ -242,15 +242,20 @@ class TfCollectionsAppElement extends LitElement {
return html` return html`
<link rel="stylesheet" href="tildefriends.css"/> <link rel="stylesheet" href="tildefriends.css"/>
<style> <style>
.toc { .toc-item {
white-space: nowrap; white-space: nowrap;
cursor: pointer; cursor: pointer;
} }
.toc:hover { .toc-item:hover {
background-color: #0cc; background-color: #0cc;
} }
.toc.selected { .toc-item.selected {
background-color: #088; background-color: #088;
font-weight: bold;
}
.table-of-contents {
flex: 0 0;
margin-right: 16px;
} }
</style> </style>
<div> <div>
@ -260,6 +265,7 @@ class TfCollectionsAppElement extends LitElement {
${keyed(this.whoami, html`<tf-collection ${keyed(this.whoami, html`<tf-collection
.collection=${this.wikis} .collection=${this.wikis}
whoami=${this.whoami} whoami=${this.whoami}
category="wiki"
selected_id=${this.wiki?.id} selected_id=${this.wiki?.id}
@create=${this.on_wiki_create} @create=${this.on_wiki_create}
@rename=${this.on_wiki_rename} @rename=${this.on_wiki_rename}
@ -268,6 +274,7 @@ class TfCollectionsAppElement extends LitElement {
${keyed(this.wiki_doc?.id, html`<tf-collection ${keyed(this.wiki_doc?.id, html`<tf-collection
.collection=${this.wiki_docs} .collection=${this.wiki_docs}
whoami=${this.whoami} whoami=${this.whoami}
category="document"
selected_id=${(this.wiki_doc && this.wiki_doc?.parent == this.wiki?.id) ? this.wiki_doc?.id : ''} selected_id=${(this.wiki_doc && this.wiki_doc?.parent == this.wiki?.id) ? this.wiki_doc?.id : ''}
@create=${this.on_wiki_doc_create} @create=${this.on_wiki_doc_create}
@rename=${this.on_wiki_doc_rename} @rename=${this.on_wiki_doc_rename}
@ -292,12 +299,12 @@ class TfCollectionsAppElement extends LitElement {
</div> </div>
</div> </div>
<div class="flex-row"> <div class="flex-row">
<div style="flex: 0 0"> <div class="box table-of-contents">
${Object.values(this.wikis || {}).sort((x, y) => x.name.localeCompare(y.name)).map(wiki => html` ${Object.values(this.wikis || {}).sort((x, y) => x.name.localeCompare(y.name)).map(wiki => html`
<div class="toc ${self.wiki?.id === wiki.id ? 'selected' : ''}" @click=${() => self.on_wiki_changed({detail: {value: wiki}})}>📕${wiki.name}</div> <div class="toc-item ${self.wiki?.id === wiki.id ? 'selected' : ''}" @click=${() => self.on_wiki_changed({detail: {value: wiki}})}>${self.wiki?.id === wiki.id ? '' : '>'} ${wiki.name}</div>
<ul> <ul>
${Object.values(self.wiki_docs || {}).filter(doc => doc.parent === wiki?.id).sort((x, y) => x.name.localeCompare(y.name)).map(doc => html` ${Object.values(self.wiki_docs || {}).filter(doc => doc.parent === wiki?.id).sort((x, y) => x.name.localeCompare(y.name)).map(doc => html`
<li class="toc ${self.wiki_doc?.id === doc.id ? 'selected' : ''}" style="list-style: none; text-indent: -1rem" @click=${() => self.on_wiki_doc_changed({detail: {value: doc}})}>${doc?.private ? '🔒' : '📄'} ${doc.name}</li> <li class="toc-item ${self.wiki_doc?.id === doc.id ? 'selected' : ''}" style="list-style: none; text-indent: -1rem" @click=${() => self.on_wiki_doc_changed({detail: {value: doc}})}>${doc?.private ? '🔒' : '📄'} ${doc.name}</li>
`)} `)}
</ul> </ul>
`)} `)}

View File

@ -76,7 +76,9 @@ class TfWikiDocElement extends LitElement {
async load_blob() { async load_blob() {
let blob = await tfrpc.rpc.get_blob(this.value?.blob); let blob = await tfrpc.rpc.get_blob(this.value?.blob);
if (blob.endsWith('.box')) { if(!blob) {
console.warn("no blob found, we're going to assume the document is empty (load_blob())");
} else if (blob.endsWith('.box')) {
let d = await tfrpc.rpc.try_decrypt(this.whoami, blob); let d = await tfrpc.rpc.try_decrypt(this.whoami, blob);
if (d) { if (d) {
blob = d; blob = d;
@ -239,6 +241,15 @@ class TfWikiDocElement extends LitElement {
a:visited { color: #6c71c4 } a:visited { color: #6c71c4 }
a:hover { color: #859900 } a:hover { color: #859900 }
a:active { color: #2aa198 } a:active { color: #2aa198 }
#editor-text-area {
background-color: #00000040;
color: white;
style="flex: 1 1;
min-height: 10em;
font-size: larger;
${this.value?.private ? 'border: 4px solid #800' : ''
}
</style> </style>
<div class="inline-flex-row"> <div class="inline-flex-row">
<button ?disabled=${!this.whoami || this.is_editing} @click=${() => self.is_editing = true}>Edit</button> <button ?disabled=${!this.whoami || this.is_editing} @click=${() => self.is_editing = true}>Edit</button>
@ -249,15 +260,16 @@ class TfWikiDocElement extends LitElement {
<button ?disabled=${!this.is_editing} @click=${this.on_blog_publish}>Publish Blog</button> <button ?disabled=${!this.is_editing} @click=${this.on_blog_publish}>Publish Blog</button>
</div> </div>
<div ?hidden=${!this.value?.private} style="color: #800">🔒 document is private</div> <div ?hidden=${!this.value?.private} style="color: #800">🔒 document is private</div>
<div class="flex-row" ${this.value?.private ? 'border-top: 4px solid #800' : ''}"> <div class="flex-column" ${this.value?.private ? 'border-top: 4px solid #800' : ''}">
<textarea <textarea
?hidden=${!this.is_editing} ?hidden=${!this.is_editing}
style="flex: 1 1; min-height: 10em; ${this.value?.private ? 'border: 4px solid #800' : ''}" id="editor-text-area"
@input=${this.on_edit} @input=${this.on_edit}
@paste=${this.paste} @paste=${this.paste}
.value=${this.blob ?? ''}></textarea> .value=${this.blob ?? ''}></textarea>
<div style="flex: 1 1"> <div style="flex: 1 1">
<div ?hidden=${!this.is_editing} style="border: 1px solid #fff; border-radius: 1em; padding: 0.5em"> <div ?hidden=${!this.is_editing} class="box">
Summary
<img ?hidden=${!thumbnail_ref} style="max-width: 128px; max-height: 128px; float: right" src="/${thumbnail_ref}/view"> <img ?hidden=${!thumbnail_ref} style="max-width: 128px; max-height: 128px; float: right" src="/${thumbnail_ref}/view">
<h1 ?hidden=${!this.title(this.blob)}>${unsafeHTML(this.markdown(this.title(this.blob)))}</h1> <h1 ?hidden=${!this.title(this.blob)}>${unsafeHTML(this.markdown(this.title(this.blob)))}</h1>
${unsafeHTML(this.markdown(this.summary(this.blob)))} ${unsafeHTML(this.markdown(this.summary(this.blob)))}

View File

@ -100,3 +100,11 @@ tr:nth-child(even) {
display: inline-flex; display: inline-flex;
flex-direction: row; flex-direction: row;
} }
.box {
background-color: #00000020;
border: 1px solid grey;
border-radius: 8px;
padding: 16px;
margin: 4px;
}