Implement saving content
This commit is contained in:
parent
c3604f38b2
commit
faea8ccc72
|
@ -168,7 +168,7 @@ class DocumentTab:
|
||||||
return tag
|
return tag
|
||||||
return None
|
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):
|
if tag := self.get_tag(name):
|
||||||
return tag.value
|
return tag.value
|
||||||
return default
|
return default
|
||||||
|
@ -200,7 +200,7 @@ class Document:
|
||||||
return tag
|
return tag
|
||||||
return None
|
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):
|
if tag := self.get_tag(name):
|
||||||
return tag.value
|
return tag.value
|
||||||
return default
|
return default
|
||||||
|
|
|
@ -16,7 +16,16 @@ from flask import (
|
||||||
)
|
)
|
||||||
|
|
||||||
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, DocumentTab, DocumentTag, TagOptions, DocumentSubtag
|
from redstring.parser import (
|
||||||
|
Document,
|
||||||
|
DocumentTab,
|
||||||
|
DocumentTag,
|
||||||
|
DocumentSubtag,
|
||||||
|
dump,
|
||||||
|
load,
|
||||||
|
parse_document_from_json,
|
||||||
|
TagOptions,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
CONFIG_ENVVAR = 'REDSTRING_CONFIG'
|
CONFIG_ENVVAR = 'REDSTRING_CONFIG'
|
||||||
|
@ -57,14 +66,23 @@ def new():
|
||||||
|
|
||||||
@app.route('/edit/<document_id>', methods=['GET', 'POST'])
|
@app.route('/edit/<document_id>', methods=['GET', 'POST'])
|
||||||
def edit(document_id):
|
def edit(document_id):
|
||||||
# Load the document to edit
|
|
||||||
doc_path = safe_join(current_app.config['root'], f'{document_id}.json')
|
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):
|
if not os.path.isfile(doc_path):
|
||||||
return abort(404)
|
return abort(404)
|
||||||
with open(doc_path) as f:
|
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 := request.args.get('add'):
|
||||||
if add == 'tab':
|
if add == 'tab':
|
||||||
new_tab = DocumentTab('newtab', [])
|
new_tab = DocumentTab('newtab', [])
|
||||||
|
|
|
@ -103,6 +103,11 @@
|
||||||
}
|
}
|
||||||
table.page-table a {
|
table.page-table a {
|
||||||
color: #8af;
|
color: #8af;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
table.page-table .numeric-input {
|
||||||
|
width: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Edit page styling */
|
/* Edit page styling */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{% extends 'base.jinja' %}
|
{% 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', '') %}
|
{% set page_summary = document.get_tag_value('summary', '') %}
|
||||||
|
|
||||||
{% block page_scripts %}
|
{% block page_scripts %}
|
||||||
|
@ -48,6 +48,85 @@ function addTab() {
|
||||||
wrapper.appendChild(newPage);
|
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 () {
|
window.onload = function () {
|
||||||
// Respect fragment as a tab selector shortcut
|
// Respect fragment as a tab selector shortcut
|
||||||
if (window.location.hash) {
|
if (window.location.hash) {
|
||||||
|
@ -67,21 +146,17 @@ window.onload = function () {
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><i>tab name</i></td>
|
<td><i>tab name</i></td>
|
||||||
<td><div contenteditable>{{ tab.name }}</div></td>
|
<td><div class="edit-tab-name" contenteditable>{{ tab.name }}</div></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr><td></td>
|
<tr><td></td>
|
||||||
<td><i>priority: <a href="/edit/{{ document.get_tag('id').value }}?tab={{ tab.name }}&option=priority">{{ tab.options.priority }}</a> — hide_names: <a href="/edit/{{ document.get_tag('id').value }}?tab={{ tab.name }}&option=hide_names">{{ tab.options.hide_names|lower }}</a> — private: <a href="/edit/{{ document.get_tag('id').value }}?tab={{ tab.name }}&option=private">{{ tab.options.private|lower }}</a></td>
|
<td><input class="tab-priority numeric-input" type="number" value="{{ tab.options.priority }}"> <i>priority</i> — <input class="tab-hidenames" type="checkbox"{% if tab.options.hide_names %} checked {% endif %}> <i>hide names</i> — <input class="tab-private" type="checkbox"{% if tab.options.private %} checked{% endif %}> <i>private</i></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
{% for tag in tab.tags %}
|
{% for tag in tab.tags %}
|
||||||
<tr>
|
<tr class="edit-tag" data-tag="{{ tag.name }}" >
|
||||||
{%- if tag.name == 'id' -%}
|
<td><div class="edit-tag-name"{% if tag.name != 'id' %} contenteditable{% endif %}>{{ tag.name }}</div></td>
|
||||||
<td>{{ tag.name }}</td>
|
<td><div class="edit-tag-value" contenteditable>{{ tag.value }}</div></td>
|
||||||
{%- else -%}
|
|
||||||
<td><div contenteditable>{{ tag.name }}</div></td>
|
|
||||||
{% endif %}
|
|
||||||
<td><div contenteditable>{{ tag.value }}</div></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
{%- if tag.name != 'id' -%}
|
{%- if tag.name != 'id' -%}
|
||||||
|
@ -91,14 +166,14 @@ window.onload = function () {
|
||||||
{%- else -%}
|
{%- else -%}
|
||||||
<a href="/edit/{{ document.get_tag('id').value }}?add=subtag&tag={{ tag.name }}">└ +</a>
|
<a href="/edit/{{ document.get_tag('id').value }}?add=subtag&tag={{ tag.name }}">└ +</a>
|
||||||
{%- endif -%}</td>
|
{%- endif -%}</td>
|
||||||
<td><i>hyperlink: <a href="/edit/{{ document.get_tag('id').value }}?tag={{ tag.name }}&option=hyperlink">{{ tag.options.hyperlink|lower }}</a> — interlink: <a href="/edit/{{ document.get_tag('id').value }}?tag={{ tag.name }}&option=interlink">{{ tag.options.interlink|lower }}</a> — private: <a href="/edit/{{ document.get_tag('id').value }}?tag={{ tag.name }}&option=private">{{ tag.options.private|lower }}</a></td>
|
<td><input class="tag-hyperlink" type="checkbox"{% if tag.options.hyperlink %} checked {% endif %}> <i>hyperlink</i> — <input class="tag-interlink" type="checkbox"{% if tag.options.interlink %} checked {% endif %}> <i>interlink</i> — <input class="tag-private" type="checkbox"{% if tag.options.private %} checked {% endif %}> <i>private</i></td>
|
||||||
</tr>
|
</tr>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
|
|
||||||
{% for subtag in tag.subtags %}
|
{% for subtag in tag.subtags %}
|
||||||
<tr>
|
<tr class="edit-subtag" data-tag="{{ tag.name }}">
|
||||||
<td><div contenteditable>{{ subtag.name }}</div></td>
|
<td><div class="edit-subtag-name" contenteditable>{{ subtag.name }}</div></td>
|
||||||
<td><div contenteditable>{{ subtag.value }}</div></td>
|
<td><div class="edit-subtag-value" contenteditable>{{ subtag.value }}</div></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -109,7 +184,7 @@ window.onload = function () {
|
||||||
<a href="/edit/{{ document.get_tag('id').value }}?add=subtag&tag={{ tag.name }}">└ +</a>
|
<a href="/edit/{{ document.get_tag('id').value }}?add=subtag&tag={{ tag.name }}">└ +</a>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td><input class="tag-hyperlink" type="checkbox"{% if subtag.options.hyperlink %} checked {% endif %}> <i>hyperlink</i> — <input class="tag-interlink" type="checkbox"{% if subtag.options.interlink %} checked {% endif %}> <i>interlink</i> — <input class="tag-private" type="checkbox"{% if subtag.options.private %} checked {% endif %}> <i>private</i></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
@ -120,6 +195,11 @@ window.onload = function () {
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td><a onclick="javascript:save()">submit changes</a></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
Loading…
Reference in New Issue