diff --git a/redstring/parser.py b/redstring/parser.py index 6891d59..de438ae 100644 --- a/redstring/parser.py +++ b/redstring/parser.py @@ -168,7 +168,7 @@ class DocumentTab: return tag return None - def get_tag_value(self, name: str, default: str): + def get_tag_value(self, name: str, default: str = None): if tag := self.get_tag(name): return tag.value return default @@ -200,7 +200,7 @@ class Document: return tag return None - def get_tag_value(self, name: str, default: str): + def get_tag_value(self, name: str, default: str = None): if tag := self.get_tag(name): return tag.value return default diff --git a/redstring/server.py b/redstring/server.py index 6258660..c8e701e 100644 --- a/redstring/server.py +++ b/redstring/server.py @@ -16,7 +16,16 @@ from flask import ( ) from redstring.library import generate_index_document, generate_default_document -from redstring.parser import load, dump, DocumentTab, DocumentTag, TagOptions, DocumentSubtag +from redstring.parser import ( + Document, + DocumentTab, + DocumentTag, + DocumentSubtag, + dump, + load, + parse_document_from_json, + TagOptions, +) CONFIG_ENVVAR = 'REDSTRING_CONFIG' @@ -57,14 +66,23 @@ def new(): @app.route('/edit/', methods=['GET', 'POST']) def edit(document_id): - # Load the document to edit doc_path = safe_join(current_app.config['root'], f'{document_id}.json') + + # Check for content updates + if request.method == 'POST': + sent_json = request.json + new_doc: Document = parse_document_from_json(sent_json) + with open(doc_path, 'w') as f: + dump(new_doc, f) + return {} + + # Load the document to edit if not os.path.isfile(doc_path): return abort(404) with open(doc_path) as f: - doc = load(f) + doc: Document = load(f) - # Check for structural change requests + # Check for structural updates if add := request.args.get('add'): if add == 'tab': new_tab = DocumentTab('newtab', []) diff --git a/redstring/templates/base.jinja b/redstring/templates/base.jinja index 66c7e87..0293aa2 100644 --- a/redstring/templates/base.jinja +++ b/redstring/templates/base.jinja @@ -103,6 +103,11 @@ } table.page-table a { color: #8af; + cursor: pointer; + text-decoration: underline; + } + table.page-table .numeric-input { + width: 50px; } /* Edit page styling */ diff --git a/redstring/templates/edit.jinja b/redstring/templates/edit.jinja index 8d6139b..ebe3771 100644 --- a/redstring/templates/edit.jinja +++ b/redstring/templates/edit.jinja @@ -1,6 +1,6 @@ {% extends 'base.jinja' %} -{% set page_title = document.get_tag_value('title', document.get_tag('id').value) -%} +{% set page_title = document.get_tag_value('title') or document.get_tag_value('id') -%} {% set page_summary = document.get_tag_value('summary', '') %} {% block page_scripts %} @@ -48,6 +48,85 @@ function addTab() { wrapper.appendChild(newPage); } +function save() { + let tabs = document.querySelectorAll(".tab-page"); + let doc = []; + for (var tabDiv of tabs.values()) { + let tabName = tabDiv.querySelector(".edit-tab-name").innerText; + let tabPriority = tabDiv.querySelector(".tab-priority").value; + let tabHideNames = tabDiv.querySelector(".tab-hidenames").checked; + let tabPrivate = tabDiv.querySelector(".tab-private").checked; + let tab = { + name: tabName, + tags: [], + options: { + priority: parseInt(tabPriority), + hide_names: tabHideNames, + private: tabPrivate, + }, + }; + doc.push(tab) + + let tags = tabDiv.querySelectorAll(".edit-tag"); + let subtags = tabDiv.querySelectorAll(".edit-subtag"); + for (var tagRow of tags.values()) { + let tagRowName = tagRow.querySelector(".edit-tag-name").innerText; + let tagRowValue = tagRow.querySelector(".edit-tag-value").innerText; + let tag = { + name: tagRowName, + value: tagRowValue, + subtags: [], + }; + if (tagRowName != "id") { + let optionsRow = tagRow.nextElementSibling; + let tagHyperlink = optionsRow.querySelector(".tag-hyperlink").checked; + let tagInterlink = optionsRow.querySelector(".tag-interlink").checked; + let tagPrivate = optionsRow.querySelector(".tag-private").checked; + tag.options = { + hyperlink: tagHyperlink, + interlink: tagInterlink, + private: tagPrivate, + }; + } + tab.tags.push(tag); + + let tagRowId = tagRow.dataset.tag; + for (var subtagRow of subtags.values()) { + let subtagRowId = subtagRow.dataset.tag; + if (subtagRowId == tagRowId) { + let subtagRowName = subtagRow.querySelector(".edit-subtag-name").innerText; + let subtagRowValue = subtagRow.querySelector(".edit-subtag-value").innerText; + let subOptionsRow = subtagRow.nextElementSibling; + let subtagHyperlink = subOptionsRow.querySelector(".tag-hyperlink").checked; + let subtagInterlink = subOptionsRow.querySelector(".tag-interlink").checked; + let subtagPrivate = subOptionsRow.querySelector(".tag-private").checked; + let subtag = { + name: subtagRowName, + value: subtagRowValue, + options: { + hyperlink: subtagHyperlink, + interlink: subtagInterlink, + private: subtagPrivate, + } + }; + tag.subtags.push(subtag); + } + } + } + } + + var req = new XMLHttpRequest(); + req.open("POST", "/edit/{{ document.get_tag_value('id') }}", true); + req.setRequestHeader("Content-type", "application/json"); + req.responseType = "json"; + req.onreadystatechange = function () { + if (req.readyState == 4 && req.status == 200) { + window.location.reload(); + } + }; + req.send(JSON.stringify(doc)); +} + window.onload = function () { // Respect fragment as a tab selector shortcut if (window.location.hash) { @@ -67,21 +146,17 @@ window.onload = function () { tab name -
{{ tab.name }}
+
{{ tab.name }}
-priority: {{ tab.options.priority }} — hide_names: {{ tab.options.hide_names|lower }} — private: {{ tab.options.private|lower }} + priority hide names private {% for tag in tab.tags %} - -{%- if tag.name == 'id' -%} -{{ tag.name }} -{%- else -%} -
{{ tag.name }}
-{% endif %} -
{{ tag.value }}
+ +
{{ tag.name }}
+
{{ tag.value }}
{%- if tag.name != 'id' -%} @@ -91,14 +166,14 @@ window.onload = function () { {%- else -%} └ + {%- endif -%} -hyperlink: {{ tag.options.hyperlink|lower }} — interlink: {{ tag.options.interlink|lower }} — private: {{ tag.options.private|lower }} + hyperlink interlink private {%- endif -%} {% for subtag in tag.subtags %} - -
{{ subtag.name }}
-
{{ subtag.value }}
+ +
{{ subtag.name }}
+
{{ subtag.value }}
@@ -109,7 +184,7 @@ window.onload = function () { └ + {%- endif -%} - + hyperlink interlink private {% endfor %} @@ -120,6 +195,11 @@ window.onload = function () { + + +submit changes + + {% endmacro %}