Add edit page and callbacks
This commit is contained in:
parent
d8f37f27f8
commit
2ddb1281c1
|
@ -63,13 +63,7 @@ class TagOptions:
|
|||
_PRIVATE_KEY = 'private'
|
||||
|
||||
def __init__(self, **kwargs) -> None:
|
||||
self.options = 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)
|
||||
self.options: dict = OrderedDict(**kwargs)
|
||||
|
||||
def to_json(self):
|
||||
return self.options
|
||||
|
|
|
@ -10,12 +10,13 @@ from flask import (
|
|||
Flask,
|
||||
redirect,
|
||||
render_template,
|
||||
request,
|
||||
safe_join,
|
||||
url_for,
|
||||
)
|
||||
|
||||
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'
|
||||
|
@ -54,6 +55,47 @@ def new():
|
|||
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():
|
||||
parser = argparse.ArgumentParser(description="Run the redstring server.")
|
||||
parser.add_argument("--config", help="Config file path.")
|
||||
|
|
|
@ -101,12 +101,20 @@
|
|||
table.page-table td:nth-child(2) {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
table.page-table td:nth-child(2) a {
|
||||
table.page-table a {
|
||||
color: #8af;
|
||||
}
|
||||
table.page-table td:nth-child(2) a:visited {
|
||||
table.page-table a:visited {
|
||||
color: #88f;
|
||||
}
|
||||
|
||||
/* Edit page styling */
|
||||
input.tag-name {
|
||||
}
|
||||
textarea.tag-value {
|
||||
resize: none;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
{% block page_scripts %}{% endblock %}
|
||||
</head>
|
||||
|
|
|
@ -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 -%}
|
||||
│
|
||||
{%- else -%}
|
||||
<a href="/edit/{{ document.get_tag('id').value }}?add=subtag&tag={{ tag.name }}">└ +</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 -%}
|
||||
│
|
||||
{%- else -%}
|
||||
<a href="/edit/{{ document.get_tag('id').value }}?add=subtag&tag={{ tag.name }}">└ +</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 %}
|
Loading…
Reference in New Issue