1
Fork 0
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:
Steffo 2019-06-20 19:58:44 +02:00 committed by GitHub
commit 3059eadeaf
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 483 additions and 10 deletions

View file

@ -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__":

View file

@ -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"]

View 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))

View 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 %}

View file

@ -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>

View file

@ -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 %}

View file

@ -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

View file

@ -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;
}
}
}

View file

@ -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>