mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-23 19:44:20 +00:00
Royalprint: Wikiedit (#66)
This commit is contained in:
commit
3059eadeaf
10 changed files with 483 additions and 10 deletions
|
@ -1,6 +1,6 @@
|
|||
import os
|
||||
from .web import create_app
|
||||
from .web.royalprints import rp_home, rp_wikiview, rp_tglogin, rp_docs
|
||||
from .web.royalprints import *
|
||||
|
||||
|
||||
class TestConfig:
|
||||
|
@ -8,7 +8,7 @@ class TestConfig:
|
|||
TG_AK = os.environ["TG_AK"]
|
||||
|
||||
|
||||
app = create_app(TestConfig, [rp_home, rp_wikiview, rp_tglogin, rp_docs])
|
||||
app = create_app(TestConfig, [rp_home, rp_wikiview, rp_tglogin, rp_docs, rp_wikiedit])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -4,5 +4,6 @@ from .home import rp as rp_home
|
|||
from .wikiview import rp as rp_wikiview
|
||||
from .tglogin import rp as rp_tglogin
|
||||
from .docs import rp as rp_docs
|
||||
from .wikiedit import rp as rp_wikiedit
|
||||
|
||||
__all__ = ["rp_home", "rp_wikiview", "rp_tglogin", "rp_docs"]
|
||||
__all__ = ["rp_home", "rp_wikiview", "rp_tglogin", "rp_docs", "rp_wikiedit"]
|
||||
|
|
77
royalnet/web/royalprints/wikiedit/__init__.py
Normal file
77
royalnet/web/royalprints/wikiedit/__init__.py
Normal file
|
@ -0,0 +1,77 @@
|
|||
"""A Royal Games Wiki viewer :py:class:`royalnet.web.Royalprint`. Doesn't support any kind of edit."""
|
||||
import flask as f
|
||||
import uuid
|
||||
import os
|
||||
import datetime
|
||||
import difflib
|
||||
from ... import Royalprint
|
||||
from ....database.tables import Royal, WikiPage, WikiRevision
|
||||
|
||||
|
||||
tmpl_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')
|
||||
rp = Royalprint("wikiedit", __name__, url_prefix="/wikiedit", template_folder=tmpl_dir,
|
||||
required_tables={Royal, WikiPage, WikiRevision})
|
||||
|
||||
|
||||
@rp.route("/newpage", methods=["GET", "POST"])
|
||||
def wikiedit_newpage():
|
||||
if "royal" not in f.session:
|
||||
return "Please login to edit wiki pages", 403
|
||||
|
||||
if f.request.method == "GET":
|
||||
return f.render_template("wikiedit_page.html", page=None)
|
||||
|
||||
elif f.request.method == "POST":
|
||||
fd = f.request.form
|
||||
if not ("title" in fd and "content" in fd and "css" in fd):
|
||||
return "Missing field", 400
|
||||
alchemy, alchemy_session = f.current_app.config["ALCHEMY"], f.current_app.config["ALCHEMY_SESSION"]
|
||||
page = alchemy.WikiPage(page_id=uuid.uuid4(),
|
||||
title=fd["title"],
|
||||
content=fd["content"],
|
||||
format="markdown",
|
||||
css=fd["css"] if fd["css"] != "None" else None)
|
||||
revision = alchemy.WikiRevision(revision_id=uuid.uuid4(),
|
||||
page=page,
|
||||
author_id=f.session["royal"]["uid"],
|
||||
timestamp=datetime.datetime.now(),
|
||||
reason=fd.get("reason"),
|
||||
diff="\n".join(difflib.unified_diff([], page.content.split("\n"))))
|
||||
alchemy_session.add(page)
|
||||
alchemy_session.add(revision)
|
||||
alchemy_session.commit()
|
||||
return f.redirect(f.url_for("wikiview.wikiview_by_id", page_id=page.page_id, title=page.title))
|
||||
|
||||
|
||||
@rp.route("/<uuid:page_id>", defaults={"title": ""}, methods=["GET", "POST"])
|
||||
@rp.route("/<uuid:page_id>/<title>", methods=["GET", "POST"])
|
||||
def wikiedit_by_id(page_id: uuid.UUID, title: str):
|
||||
if "royal" not in f.session:
|
||||
return "Please login to edit wiki pages", 403
|
||||
|
||||
alchemy, alchemy_session = f.current_app.config["ALCHEMY"], f.current_app.config["ALCHEMY_SESSION"]
|
||||
page = alchemy_session.query(alchemy.WikiPage).filter(alchemy.WikiPage.page_id == page_id).one_or_none()
|
||||
if page is None:
|
||||
return "No such page", 404
|
||||
|
||||
if f.request.method == "GET":
|
||||
return f.render_template("wikiedit_page.html", page=page)
|
||||
|
||||
elif f.request.method == "POST":
|
||||
fd = f.request.form
|
||||
if not ("title" in fd and "content" in fd and "css" in fd):
|
||||
return "Missing field", 400
|
||||
# Create new revision
|
||||
revision = alchemy.WikiRevision(revision_id=uuid.uuid4(),
|
||||
page=page,
|
||||
author_id=f.session["royal"]["uid"],
|
||||
timestamp=datetime.datetime.now(),
|
||||
reason=fd.get("reason"),
|
||||
diff="\n".join(difflib.unified_diff(page.content.split("\n"), fd["content"].split("\n"))))
|
||||
alchemy_session.add(revision)
|
||||
# Apply changes
|
||||
page.content = fd["content"]
|
||||
page.title = fd["title"]
|
||||
page.css = fd["css"] if fd["css"] != "None" else None
|
||||
alchemy_session.commit()
|
||||
return f.redirect(f.url_for("wikiview.wikiview_by_id", page_id=page.page_id, title=page.title))
|
145
royalnet/web/royalprints/wikiedit/templates/wikiedit_page.html
Normal file
145
royalnet/web/royalprints/wikiedit/templates/wikiedit_page.html
Normal file
|
@ -0,0 +1,145 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}
|
||||
{{ page.title }} - RYGwikieditor
|
||||
{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css">
|
||||
<script src="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="doublebox">
|
||||
<div class="top">
|
||||
<span class="left">
|
||||
Wiki Editor
|
||||
</span>
|
||||
</div>
|
||||
<div class="bot">
|
||||
<form method="POST" class="wikiedit-form">
|
||||
<label for="wikiedit-title">
|
||||
<span class="label-text">Titolo</span>
|
||||
<input id="wikiedit-title" type="text" name="title" value="{{ page.title }}">
|
||||
</label>
|
||||
<label for="wikiedit-format">
|
||||
<span class="label-text">Formato</span>
|
||||
<input id="wikiedit-format" type="text" name="format" disabled value="{{ page.format }}">
|
||||
</label>
|
||||
<!--suppress HtmlFormInputWithoutLabel -->
|
||||
<textarea id="wikiedit-content" name="content">{{ page.content }}</textarea>
|
||||
<label for="wikiedit-css">
|
||||
<span class="label-text">Tema</span>
|
||||
<select id="wikiedit-css" name="css">
|
||||
<option value="None" {% if page.css == None %}selected{% endif %}>Royal Games</option>
|
||||
<option value="tf2.css" {% if page.css == "tf2.css" %}selected{% endif %}>Team Fortress 2</option>
|
||||
</select>
|
||||
</label>
|
||||
<label for="wikiedit-reason">
|
||||
<span class="label-text">Motivo</span>
|
||||
<input id="wikiedit-reason" type="text" name="reason">
|
||||
</label>
|
||||
<label for="wikiedit-submit">
|
||||
<input id="wikiedit-submit" type="submit" value="Salva">
|
||||
</label>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block footscripts %}
|
||||
<script>
|
||||
//TODO: maybe enable autosave?
|
||||
let simplemde = new SimpleMDE({
|
||||
element: document.getElementById("wikiedit-content"),
|
||||
blockStyles: {
|
||||
italic: "_"
|
||||
},
|
||||
tabSize: 4,
|
||||
spellChecker: false,
|
||||
toolbar: [
|
||||
{
|
||||
name: "bold",
|
||||
action: SimpleMDE.toggleBold,
|
||||
className: "fas fa-bold no-icon",
|
||||
title: "Grassetto",
|
||||
},
|
||||
{
|
||||
name: "italic",
|
||||
action: SimpleMDE.toggleItalic,
|
||||
className: "fas fa-italic no-icon",
|
||||
title: "Corsivo",
|
||||
},
|
||||
{
|
||||
name: "strikethrough",
|
||||
action: SimpleMDE.toggleStrikethrough,
|
||||
className: "fas fa-strikethrough no-icon",
|
||||
title: "Barrato",
|
||||
},
|
||||
{
|
||||
name: "link",
|
||||
action: SimpleMDE.drawLink,
|
||||
className: "fas fa-link no-icon",
|
||||
title: "Link",
|
||||
},
|
||||
"|",
|
||||
{
|
||||
name: "heading-smaller",
|
||||
action: SimpleMDE.toggleHeadingSmaller,
|
||||
className: "fas fa-header no-icon",
|
||||
title: "(Rimpicciolisci) Titolo",
|
||||
},
|
||||
{
|
||||
name: "heading",
|
||||
action: SimpleMDE.toggleHeadingBigger,
|
||||
className: "fas fa-header fa-lg no-icon",
|
||||
title: "(Ingrandisci) Titolo",
|
||||
},
|
||||
"|",
|
||||
{
|
||||
name: "code",
|
||||
action: SimpleMDE.toggleCodeBlock,
|
||||
className: "fas fa-code no-icon",
|
||||
title: "Codice",
|
||||
},
|
||||
{
|
||||
name: "quote",
|
||||
action: SimpleMDE.toggleBlockquote,
|
||||
className: "fas fa-quote-left no-icon",
|
||||
title: "Citazione",
|
||||
},
|
||||
{
|
||||
name: "unordered-list",
|
||||
action: SimpleMDE.toggleUnorderedList,
|
||||
className: "fas fa-list-ul no-icon",
|
||||
title: "Lista puntata",
|
||||
},
|
||||
{
|
||||
name: "ordered-list",
|
||||
action: SimpleMDE.toggleOrderedList,
|
||||
className: "fas fa-list-ol no-icon",
|
||||
title: "Lista ordinata",
|
||||
},
|
||||
{
|
||||
name: "horizontal-rule",
|
||||
action: SimpleMDE.drawHorizontalRule,
|
||||
className: "fas fa-minus no-icon",
|
||||
title: "Separatore",
|
||||
},
|
||||
"|",
|
||||
{
|
||||
name: "image",
|
||||
action: SimpleMDE.drawImage,
|
||||
className: "fas fa-picture-o no-icon",
|
||||
title: "Immagine",
|
||||
},
|
||||
{
|
||||
name: "table",
|
||||
action: SimpleMDE.drawTable,
|
||||
className: "fas fa-table no-icon",
|
||||
title: "Tabella",
|
||||
}
|
||||
],
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -12,6 +12,11 @@
|
|||
</span>
|
||||
</div>
|
||||
<div class="bot">
|
||||
{% if session.royal %}
|
||||
<a href="{{ url_for("wikiedit.wikiedit_newpage") }}" class="btn no-icon">Crea nuova pagina</a>
|
||||
{% else %}
|
||||
<button disabled title="Devi fare il login per creare nuove pagine!">Crea nuova pagina</button>
|
||||
{% endif %}
|
||||
<ul>
|
||||
{% for page in pages %}
|
||||
<li><a href="{{ url_for("wikiview.wikiview_by_id", page_id=page.page_id|string, title=page.title) }}">{{ page.title }}</a></li>
|
||||
|
|
|
@ -8,14 +8,27 @@
|
|||
<div class="doublebox">
|
||||
<div class="top">
|
||||
<span class="left">
|
||||
{{ page.title }}
|
||||
Wiki page
|
||||
</span>
|
||||
<span class="right">
|
||||
<a class="permalink no-icon" href="{{ url_for("wikiview.wikiview_by_id", page_id=page.page_id|string, title=page.title) }}">#</a>
|
||||
{% if session.royal %}
|
||||
<a class="edit no-icon" href="{{ url_for("wikiedit.wikiedit_by_id", page_id=page.page_id|string, title=page.title) }}">Modifica</a>
|
||||
{% else %}
|
||||
<a class="edit no-icon faded" title="Devi fare il login per creare nuove pagine!">Modifica</a>
|
||||
{% endif %}
|
||||
|
|
||||
<a class="permalink no-icon" href="{{ url_for("wikiview.wikiview_by_id", page_id=page.page_id|string, title=page.title) }}">Permalink</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="bot">
|
||||
<div class="wikiview-page">
|
||||
<h1 class="wikiview-title">
|
||||
{{ page.title }}
|
||||
</h1>
|
||||
<div class="wikiview-content">
|
||||
{{ parsed_content }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -176,6 +176,32 @@ input[type="submit"]:active,
|
|||
color: white;
|
||||
border-color: white;
|
||||
}
|
||||
input[type="text"],
|
||||
input[type="password"],
|
||||
input[type="email"] {
|
||||
background-color: rgba(160, 204, 255, 0.1);
|
||||
color: #a0ccff;
|
||||
border: none;
|
||||
border-bottom: 1px dashed #a0ccff;
|
||||
padding: 2px;
|
||||
margin: 1px;
|
||||
font-size: medium;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
select {
|
||||
background-color: rgba(160, 204, 255, 0.1);
|
||||
color: #a0ccff;
|
||||
border: none;
|
||||
border-bottom: 1px dotted #a0ccff;
|
||||
padding: 2px;
|
||||
margin: 1px;
|
||||
font-size: medium;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
select option {
|
||||
background-color: #293c61;
|
||||
color: #a0ccff;
|
||||
}
|
||||
pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -403,7 +429,88 @@ nav .nav-login-unavailable {
|
|||
.spoiler:hover {
|
||||
color: #a0ccff;
|
||||
}
|
||||
.faded {
|
||||
.faded,
|
||||
input[disabled=""],
|
||||
button[disabled=""] {
|
||||
opacity: 0.3;
|
||||
}
|
||||
.wikiedit-form label {
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
display: flex;
|
||||
}
|
||||
.wikiedit-form label .label-text {
|
||||
margin-right: 12px;
|
||||
min-width: 60px;
|
||||
}
|
||||
.wikiedit-form label input {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.wikiedit-form label[for="wikiedit-title"] {
|
||||
font-size: x-large;
|
||||
}
|
||||
.wikiedit-form label[for="wikiedit-title"] * {
|
||||
font-size: x-large;
|
||||
}
|
||||
.wikiedit-form .editor-toolbar,
|
||||
.wikiedit-form .editor-statusbar {
|
||||
background-color: #2a3d62;
|
||||
color: #a0ccff !important;
|
||||
border: 0;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
.wikiedit-form .editor-toolbar a,
|
||||
.wikiedit-form .editor-statusbar a {
|
||||
color: #a0ccff !important;
|
||||
border: 0;
|
||||
}
|
||||
.wikiedit-form .editor-toolbar a:hover,
|
||||
.wikiedit-form .editor-statusbar a:hover {
|
||||
background-color: rgba(160, 204, 255, 0.2);
|
||||
color: #ffffff !important;
|
||||
}
|
||||
.wikiedit-form .editor-toolbar a.active,
|
||||
.wikiedit-form .editor-statusbar a.active {
|
||||
background-color: rgba(160, 204, 255, 0.3);
|
||||
color: white !important;
|
||||
}
|
||||
.wikiedit-form .editor-toolbar a.active:hover,
|
||||
.wikiedit-form .editor-statusbar a.active:hover {
|
||||
background-color: rgba(160, 204, 255, 0.2);
|
||||
color: #ffffff !important;
|
||||
}
|
||||
.wikiedit-form .CodeMirror {
|
||||
font-family: "Consolas", monospace !important;
|
||||
background-color: transparent;
|
||||
color: #a0ccff;
|
||||
border-top: 0;
|
||||
border-bottom: 0;
|
||||
border-left: 1px solid rgba(160, 204, 255, 0.2);
|
||||
border-right: 1px solid rgba(160, 204, 255, 0.2);
|
||||
border-radius: 0;
|
||||
}
|
||||
.wikiedit-form .CodeMirror .cm-link {
|
||||
color: #7dffff !important;
|
||||
}
|
||||
.wikiedit-form .CodeMirror .cm-url {
|
||||
color: #00caca !important;
|
||||
}
|
||||
.wikiedit-form .CodeMirror .cm-tag {
|
||||
color: #ff7dff !important;
|
||||
}
|
||||
.wikiedit-form .CodeMirror .cm-strong {
|
||||
color: #ffff7d !important;
|
||||
}
|
||||
.wikiedit-form .CodeMirror .cm-em {
|
||||
color: #ffbb7d !important;
|
||||
}
|
||||
.wikiedit-form .CodeMirror .cm-quote {
|
||||
color: #7dff7d !important;
|
||||
}
|
||||
.wikiedit-form .CodeMirror .cm-comment {
|
||||
color: #ff7d7d !important;
|
||||
}
|
||||
.wikiedit-form .CodeMirror .cm-header {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
/*# sourceMappingURL=ryg.css.map */
|
File diff suppressed because one or more lines are too long
|
@ -215,6 +215,33 @@ button, input[type="submit"], .btn {
|
|||
}
|
||||
}
|
||||
|
||||
input[type="text"], input[type="password"], input[type="email"] {
|
||||
background-color: fade(@fg, 10%);
|
||||
color: @fg;
|
||||
border: none;
|
||||
border-bottom: 1px dashed @fg;
|
||||
padding: 2px;
|
||||
margin: 1px;
|
||||
font-size: medium;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
select {
|
||||
background-color: fade(@fg, 10%);
|
||||
color: @fg;
|
||||
border: none;
|
||||
border-bottom: 1px dotted @fg;
|
||||
padding: 2px;
|
||||
margin: 1px;
|
||||
font-size: medium;
|
||||
font-family: sans-serif;
|
||||
|
||||
option {
|
||||
background-color: #293c61;
|
||||
color: @fg;
|
||||
}
|
||||
}
|
||||
|
||||
pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -494,6 +521,103 @@ nav {
|
|||
}
|
||||
}
|
||||
|
||||
.faded {
|
||||
.faded, input[disabled=""], button[disabled=""] {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.wikiedit-form {
|
||||
|
||||
label {
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
display: flex;
|
||||
|
||||
.label-text {
|
||||
margin-right: 12px;
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
input {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
||||
label[for="wikiedit-title"] {
|
||||
font-size: x-large;
|
||||
|
||||
* {
|
||||
font-size: x-large;
|
||||
}
|
||||
}
|
||||
|
||||
.editor-toolbar, .editor-statusbar {
|
||||
background-color: #2a3d62;
|
||||
color: @fg !important;
|
||||
border: 0;
|
||||
opacity: 1 !important;
|
||||
|
||||
a {
|
||||
color: @fg !important;
|
||||
border: 0;
|
||||
|
||||
&:hover {
|
||||
background-color: fade(@fg, 20%);
|
||||
color: lighten(@fg, 25%) !important;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: fade(@fg, 30%);
|
||||
color: white !important;
|
||||
|
||||
&:hover {
|
||||
background-color: fade(@fg, 20%);
|
||||
color: lighten(@fg, 25%) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.CodeMirror {
|
||||
font-family: "Consolas", monospace !important;
|
||||
background-color: transparent;
|
||||
color: @fg;
|
||||
border-top: 0;
|
||||
border-bottom: 0;
|
||||
border-left: 1px solid fade(@fg, 20%);
|
||||
border-right: 1px solid fade(@fg, 20%);
|
||||
border-radius: 0;
|
||||
|
||||
.cm-link {
|
||||
color: @pastel-cyan !important;
|
||||
}
|
||||
|
||||
.cm-url {
|
||||
color: @li !important;
|
||||
}
|
||||
|
||||
.cm-tag {
|
||||
color: @pastel-magenta !important;
|
||||
}
|
||||
|
||||
.cm-strong {
|
||||
color: @pastel-yellow !important;
|
||||
}
|
||||
|
||||
.cm-em {
|
||||
color: @pastel-orange !important;
|
||||
}
|
||||
|
||||
.cm-quote {
|
||||
color: @pastel-lime !important;
|
||||
}
|
||||
|
||||
.cm-comment {
|
||||
color: @pastel-red !important;
|
||||
}
|
||||
|
||||
.cm-header {
|
||||
color: @ec !important;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
<link rel="stylesheet" href="{{ url_for("static", filename="ryg.css") }}">
|
||||
{% endif %}
|
||||
<link rel="icon" href="{{ url_for("static", filename="logo.png") }}" type="image/png">
|
||||
{% block head %}{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
|
|
Loading…
Reference in a new issue