Add edit page and callbacks

This commit is contained in:
Tim Van Baak 2021-02-12 21:51:21 -08:00
parent d8f37f27f8
commit 2ddb1281c1
4 changed files with 189 additions and 10 deletions

View File

@ -63,13 +63,7 @@ class TagOptions:
_PRIVATE_KEY = 'private' _PRIVATE_KEY = 'private'
def __init__(self, **kwargs) -> None: def __init__(self, **kwargs) -> None:
self.options = OrderedDict(**kwargs) self.options: dict = OrderedDict(**kwargs)
# Tag value is a hyperlink
self.hyperlink: bool = kwargs.get('hyperlink', False)
# Tag value contains redstring interlinks
self.interlink: bool = kwargs.get('interlink', False)
# Hide the tag from unauthenticated viewers
self.private: bool = kwargs.get('private', False)
def to_json(self): def to_json(self):
return self.options return self.options

View File

@ -10,12 +10,13 @@ from flask import (
Flask, Flask,
redirect, redirect,
render_template, render_template,
request,
safe_join, safe_join,
url_for, url_for,
) )
from redstring.library import generate_index_document, generate_default_document from redstring.library import generate_index_document, generate_default_document
from redstring.parser import load, dump from redstring.parser import load, dump, DocumentTab, DocumentTag, TagOptions, DocumentSubtag
CONFIG_ENVVAR = 'REDSTRING_CONFIG' CONFIG_ENVVAR = 'REDSTRING_CONFIG'
@ -54,6 +55,47 @@ def new():
return redirect(url_for('document', document_id=document_id)) return redirect(url_for('document', document_id=document_id))
@app.route('/edit/<document_id>', methods=['GET', 'POST'])
def edit(document_id):
# Load the document to edit
doc_path = safe_join(current_app.config['root'], f'{document_id}.json')
if not os.path.isfile(doc_path):
return abort(404)
with open(doc_path) as f:
doc = load(f)
# Check for structural change requests
if add := request.args.get('add'):
if add == 'tab':
new_tab = DocumentTab('newtab', [])
doc.tabs.append(new_tab)
with open(doc_path, 'w') as f:
dump(doc, f)
return redirect(url_for('edit', document_id=document_id))
elif add == 'tag':
if tab_name := request.args.get('tab'):
tab = doc.get_tab(tab_name)
new_tag = DocumentTag('tag', '', TagOptions(private=True))
tab.tags.append(new_tag)
with open(doc_path, 'w') as f:
dump(doc, f)
return redirect(url_for('edit', document_id=document_id))
return abort(400)
elif add == 'subtag':
if tag_name := request.args.get('tag'):
tag = doc.get_tag(tag_name)
new_subtag = DocumentSubtag('subtag', '', TagOptions(private=True))
tag.subtags.append(new_subtag)
with open(doc_path, 'w') as f:
dump(doc, f)
return redirect(url_for('edit', document_id=document_id))
return abort(400)
# Otherwise, return the editor page
else:
return render_template('edit.jinja', document=doc, index=False)
def main(): def main():
parser = argparse.ArgumentParser(description="Run the redstring server.") parser = argparse.ArgumentParser(description="Run the redstring server.")
parser.add_argument("--config", help="Config file path.") parser.add_argument("--config", help="Config file path.")

View File

@ -101,12 +101,20 @@
table.page-table td:nth-child(2) { table.page-table td:nth-child(2) {
white-space: pre-wrap; white-space: pre-wrap;
} }
table.page-table td:nth-child(2) a { table.page-table a {
color: #8af; color: #8af;
} }
table.page-table td:nth-child(2) a:visited { table.page-table a:visited {
color: #88f; color: #88f;
} }
/* Edit page styling */
input.tag-name {
}
textarea.tag-value {
resize: none;
width: 100%;
}
</style> </style>
{% block page_scripts %}{% endblock %} {% block page_scripts %}{% endblock %}
</head> </head>

View File

@ -0,0 +1,135 @@
{% extends 'base.jinja' %}
{% set page_title = document.get_tag_value('title', document.get_tag('id').value) -%}
{% set page_summary = document.get_tag_value('summary', '') %}
{% block page_scripts %}
<script>
var newTabCounter = 0;
function selectTab(name) {
let tab = document.getElementById("tab-" + name);
if (tab)
{
// Unselect all tabs and content
Array.from(document.getElementsByClassName("tab-content"))
.forEach(e => e.classList.remove("tab-down"));
Array.from(document.getElementsByClassName("tab-page"))
.forEach(e => e.classList.remove("tab-page-selected"));
// Select the new tab and content
tab.classList.add("tab-down");
let content = document.getElementById(name + "-page");
content.classList.add("tab-page-selected");
}
}
function addTab() {
let newTabName = "newtab" + ++newTabCounter;
let tabsDiv = document.querySelector("#tabs");
let wrapper = document.querySelector("#wrapper");
let newTabTab = document.querySelector("#newtab");
// Add tab div
let newTab = document.createElement("div");
newTab.id = "tab-" + newTabName;
newTab.classList = "tab tab-content";
newTab.contenteditable = true;
newTab.innerText = newTabName;
newTab.onclick = function() { selectTab(newTabName); };
tabsDiv.insertBefore(newTab, newTabTab);
// Add page div
let newPage = document.createElement("div");
newPage.id = newTabName + "-page";
newPage.classList = "tag-page";
let newPageTable = document.createElement("table");
newPageTable.id = newTabName + "-page-table";
newPageTable.classList = "page-table";
wrapper.appendChild(newPage);
}
window.onload = function () {
// Respect fragment as a tab selector shortcut
if (window.location.hash) {
selectTab(window.location.hash.substring(1));
}
}
</script>
{% endblock page_scripts %}
{% macro make_content_tab(tab, selected) -%}
<div id="tab-{{ tab.name }}" class="tab tab-content{% if selected %} tab-down{% endif %}{% if index %} tab-right{% endif %}" onclick="javascript:selectTab('{{ tab.name }}')">{{ tab.name }}</div>
{%- endmacro %}
{% macro make_tab_page(tab, selected) %}
<div id="{{ tab.name }}-page" class="tab-page{% if selected %} tab-page-selected{% endif %}">
<table id="{{ tab.name }}-page-table" class="page-table">
<tr>
<td><i>tab name</i></td>
<td><div contenteditable>{{ tab.name }}</div></td>
</tr>
{% for tag in tab.tags %}
<tr>
{%- if tag.name == 'id' -%}
<td>{{ tag.name }}</td>
{%- else -%}
<td><div contenteditable>{{ tag.name }}</div></td>
{% endif %}
<td><div contenteditable>{{ tag.value }}</div></td>
</tr>
<tr>
<td>
{%- if tag.subtags -%}
&#9474;
{%- else -%}
<a href="/edit/{{ document.get_tag('id').value }}?add=subtag&tag={{ tag.name }}">&#9492; +</a>
{%- endif -%}</td>
<td></td>
</tr>
{% for subtag in tag.subtags %}
<tr>
<td><div contenteditable>{{ subtag.name }}</div></td>
<td><div contenteditable>{{ subtag.value }}</div></td>
</tr>
<tr>
<td>
{%- if not loop.last -%}
&#9474;
{%- else -%}
<a href="/edit/{{ document.get_tag('id').value }}?add=subtag&tag={{ tag.name }}">&#9492; +</a>
{%- endif -%}
</td>
<td></td>
</tr>
{% endfor %}
{% endfor %}
<tr>
<td><a href="/edit/{{ document.get_tag('id').value }}?add=tag&tab={{ tab.name }}">Add tag</td>
<td></td>
</tr>
</table>
</div>
{% endmacro %}
{# TODO: tab.priority support #}
{% block page_content %}
<div id="tabs">
{%- for tab in document -%}
{{ make_content_tab(tab, loop.first) }}
{%- endfor -%}
<div id="newtab" class="tab"><a href="/edit/{{ document.get_tag('id').value }}?add=tab">+</div>
<div id="index" class="tab tab-right"><a href="/index/">index</a></div>
</div>
{% for tab in document -%}
{{ make_tab_page(tab, loop.first) }}
{%- endfor -%}
{% endblock page_content %}