mirror of
https://github.com/minetest/contentdb.git
synced 2024-12-22 22:12:24 +01:00
Add topic searching and topic discarding
This commit is contained in:
parent
b8ca5d24c5
commit
50889ccca5
@ -804,6 +804,7 @@ class ForumTopic(db.Model):
|
|||||||
author = db.relationship("User")
|
author = db.relationship("User")
|
||||||
|
|
||||||
wip = db.Column(db.Boolean, server_default="0")
|
wip = db.Column(db.Boolean, server_default="0")
|
||||||
|
discarded = db.Column(db.Boolean, server_default="0")
|
||||||
|
|
||||||
type = db.Column(db.Enum(PackageType), nullable=False)
|
type = db.Column(db.Enum(PackageType), nullable=False)
|
||||||
title = db.Column(db.String(200), nullable=False)
|
title = db.Column(db.String(200), nullable=False)
|
||||||
@ -836,6 +837,7 @@ class ForumTopic(db.Model):
|
|||||||
"posts": self.posts,
|
"posts": self.posts,
|
||||||
"views": self.views,
|
"views": self.views,
|
||||||
"is_wip": self.wip,
|
"is_wip": self.wip,
|
||||||
|
"discarded": self.discarded,
|
||||||
"created_at": self.created_at.isoformat(),
|
"created_at": self.created_at.isoformat(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,6 +80,14 @@
|
|||||||
color: #7ac;
|
color: #7ac;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.discardtopic {
|
||||||
|
text-decoration: line-through;
|
||||||
|
a {
|
||||||
|
color: #7ac;
|
||||||
|
}
|
||||||
|
filter: brightness(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
.editor-toolbar, .editor-toolbar.fullscreen {
|
.editor-toolbar, .editor-toolbar.fullscreen {
|
||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
background-color: #444 !important;
|
background-color: #444 !important;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>{% block title %}title{% endblock %} - {{ config.USER_APP_NAME }}</title>
|
<title>{% block title %}title{% endblock %} - {{ config.USER_APP_NAME }}</title>
|
||||||
<link rel="stylesheet" type="text/css" href="/static/bootstrap.css">
|
<link rel="stylesheet" type="text/css" href="/static/bootstrap.css">
|
||||||
<link rel="stylesheet" type="text/css" href="/static/custom.css?v=2">
|
<link rel="stylesheet" type="text/css" href="/static/custom.css?v=3">
|
||||||
{% block headextra %}{% endblock %}
|
{% block headextra %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
{% macro render_topics_table(topics, show_author=True) -%}
|
{% macro render_topics_table(topics, show_author=True, show_discard=False) -%}
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<tr>
|
<tr>
|
||||||
<th>Id</th>
|
|
||||||
<th></th>
|
<th></th>
|
||||||
<th>Title</th>
|
<th>Title</th>
|
||||||
{% if show_author %}<th>Author</th>{% endif %}
|
{% if show_author %}<th>Author</th>{% endif %}
|
||||||
@ -10,8 +9,7 @@
|
|||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for topic in topics %}
|
{% for topic in topics %}
|
||||||
<tr{% if topic.wip %} class="wiptopic"{% endif %}>
|
<tr class="{% if topic.wip %}wiptopic{% endif %}{% if topic.discarded %}discardtopic{% endif %}">
|
||||||
<td>{{ topic.topic_id }}</td>
|
|
||||||
<td>
|
<td>
|
||||||
[{{ topic.type.value }}]
|
[{{ topic.type.value }}]
|
||||||
</td>
|
</td>
|
||||||
@ -24,8 +22,20 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<td>{{ topic.name or ""}}</td>
|
<td>{{ topic.name or ""}}</td>
|
||||||
<td>{% if topic.link %}<a href="{{ topic.link }}">{{ topic.link | domain }}</a>{% endif %}</td>
|
<td>{% if topic.link %}<a href="{{ topic.link }}">{{ topic.link | domain }}</a>{% endif %}</td>
|
||||||
<td>
|
<td class="btn-group">
|
||||||
<a href="{{ url_for('create_edit_package_page', author=topic.author.username, repo=topic.getRepoURL(), forums=topic.topic_id, title=topic.title, bname=topic.name) }}">Create</a>
|
<a class="btn btn-primary"
|
||||||
|
href="{{ url_for('create_edit_package_page', author=topic.author.username, repo=topic.getRepoURL(), forums=topic.topic_id, title=topic.title, bname=topic.name) }}">
|
||||||
|
Create
|
||||||
|
</a>
|
||||||
|
{% if show_discard %}
|
||||||
|
<a class="btn btn-{% if topic.discarded %}success{% else %}danger{% endif %} topic-discard" data-tid={{ topic.topic_id }}>
|
||||||
|
{% if topic.discarded %}
|
||||||
|
Show
|
||||||
|
{% else %}
|
||||||
|
Discard
|
||||||
|
{% endif %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -5,11 +5,21 @@ Topics to be Added
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<a class="btn btn-primary float-right" href="{{ url_for('todo_topics_page', q=query, show_discarded=not show_discarded) }}">
|
||||||
|
{% if not show_discarded %}
|
||||||
|
Show
|
||||||
|
{% else %}
|
||||||
|
Hide
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
Discarded Topics
|
||||||
|
</a>
|
||||||
|
|
||||||
<h1>Topics to be Added</h1>
|
<h1>Topics to be Added</h1>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
{{ total - (topic_count) }} / {{ total }} packages have been added.
|
{{ total - (topic_count) }} / {{ total }} topics have been added as packages to CDB.
|
||||||
{{ topics | count }} remaining.
|
{{ topic_count }} remaining.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<form method="GET" action="{{ url_for('todo_topics_page') }}" class="my-4">
|
<form method="GET" action="{{ url_for('todo_topics_page') }}" class="my-4">
|
||||||
@ -18,7 +28,7 @@ Topics to be Added
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% from "macros/topics.html" import render_topics_table %}
|
{% from "macros/topics.html" import render_topics_table %}
|
||||||
{{ render_topics_table(topics) }}
|
{{ render_topics_table(topics, show_discard=True) }}
|
||||||
|
|
||||||
<ul class="pagination mt-4">
|
<ul class="pagination mt-4">
|
||||||
<li class="page-item {% if not prev_url %}disabled{% endif %}">
|
<li class="page-item {% if not prev_url %}disabled{% endif %}">
|
||||||
@ -37,3 +47,40 @@ Topics to be Added
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block scriptextra %}
|
||||||
|
<script>
|
||||||
|
var csrf_token = "{{ csrf_token() }}";
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
$(".topic-discard").click(function() {
|
||||||
|
var ele = $(this);
|
||||||
|
var tid = ele.attr("data-tid");
|
||||||
|
var discard = !ele.parent().parent().hasClass("discardtopic");
|
||||||
|
fetch(new Request("{{ url_for('topic_set_discard') }}?tid=" + tid +
|
||||||
|
"&discard=" + (discard ? "true" : "false"), {
|
||||||
|
method: "post",
|
||||||
|
credentials: "same-origin",
|
||||||
|
headers: {
|
||||||
|
"Accept": "application/json",
|
||||||
|
"X-CSRFToken": csrf_token,
|
||||||
|
},
|
||||||
|
})).then(function(response) {
|
||||||
|
response.text().then(function(txt) {
|
||||||
|
console.log(JSON.parse(txt));
|
||||||
|
if (JSON.parse(txt).discarded) {
|
||||||
|
ele.parent().parent().addClass("discardtopic");
|
||||||
|
ele.removeClass("btn-danger");
|
||||||
|
ele.addClass("btn-success");
|
||||||
|
ele.text("Show");
|
||||||
|
} else {
|
||||||
|
ele.parent().parent().removeClass("discardtopic");
|
||||||
|
ele.removeClass("btn-success");
|
||||||
|
ele.addClass("btn-danger");
|
||||||
|
ele.text("Discard");
|
||||||
|
}
|
||||||
|
}).catch(console.log)
|
||||||
|
}).catch(console.log)
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
@ -68,7 +68,10 @@ def make_flask_user_password(plaintext_str):
|
|||||||
import bcrypt
|
import bcrypt
|
||||||
plaintext = plaintext_str.encode("UTF-8")
|
plaintext = plaintext_str.encode("UTF-8")
|
||||||
password = bcrypt.hashpw(plaintext, bcrypt.gensalt())
|
password = bcrypt.hashpw(plaintext, bcrypt.gensalt())
|
||||||
return password.decode("UTF-8")
|
if isinstance(password, str):
|
||||||
|
return password
|
||||||
|
else:
|
||||||
|
return password.decode("UTF-8")
|
||||||
|
|
||||||
def _do_login_user(user, remember_me=False):
|
def _do_login_user(user, remember_me=False):
|
||||||
def _call_or_get(v):
|
def _call_or_get(v):
|
||||||
|
@ -19,7 +19,7 @@ from flask import *
|
|||||||
from flask_user import *
|
from flask_user import *
|
||||||
from app import app
|
from app import app
|
||||||
from app.models import *
|
from app.models import *
|
||||||
from app.utils import is_package_page
|
from app.utils import is_package_page, rank_required
|
||||||
from .packages import QueryBuilder
|
from .packages import QueryBuilder
|
||||||
|
|
||||||
@app.route("/api/packages/")
|
@app.route("/api/packages/")
|
||||||
@ -43,3 +43,18 @@ def api_topics_page():
|
|||||||
.order_by(db.asc(ForumTopic.wip), db.asc(ForumTopic.name), db.asc(ForumTopic.title))
|
.order_by(db.asc(ForumTopic.wip), db.asc(ForumTopic.name), db.asc(ForumTopic.title))
|
||||||
pkgs = [t.getAsDictionary() for t in query.all()]
|
pkgs = [t.getAsDictionary() for t in query.all()]
|
||||||
return jsonify(pkgs)
|
return jsonify(pkgs)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/api/topic_discard/", methods=["POST"])
|
||||||
|
@rank_required(UserRank.EDITOR)
|
||||||
|
def topic_set_discard():
|
||||||
|
tid = request.args.get("tid")
|
||||||
|
discard = request.args.get("discard")
|
||||||
|
if tid is None or discard is None:
|
||||||
|
abort(400)
|
||||||
|
|
||||||
|
topic = ForumTopic.query.get(tid)
|
||||||
|
topic.discarded = discard == "true"
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return jsonify(topic.getAsDictionary())
|
||||||
|
@ -54,11 +54,16 @@ def todo_page():
|
|||||||
@app.route("/todo/topics/")
|
@app.route("/todo/topics/")
|
||||||
@login_required
|
@login_required
|
||||||
def todo_topics_page():
|
def todo_topics_page():
|
||||||
total = ForumTopic.query.count()
|
query = ForumTopic.query
|
||||||
|
|
||||||
query = ForumTopic.query \
|
show_discarded = request.args.get("show_discarded") == "True"
|
||||||
.filter(~ db.exists().where(Package.forums==ForumTopic.topic_id)) \
|
if not show_discarded:
|
||||||
.order_by(db.asc(ForumTopic.wip), db.asc(ForumTopic.name), db.asc(ForumTopic.title))
|
query = query.filter_by(discarded=False)
|
||||||
|
|
||||||
|
total = query.count()
|
||||||
|
|
||||||
|
query = query.filter(~ db.exists().where(Package.forums==ForumTopic.topic_id)) \
|
||||||
|
.order_by(db.asc(ForumTopic.wip), db.asc(ForumTopic.name), db.asc(ForumTopic.title))
|
||||||
|
|
||||||
topic_count = query.count()
|
topic_count = query.count()
|
||||||
|
|
||||||
@ -75,5 +80,5 @@ def todo_topics_page():
|
|||||||
if query.has_prev else None
|
if query.has_prev else None
|
||||||
|
|
||||||
return render_template("todo/topics.html", topics=query.items, total=total, \
|
return render_template("todo/topics.html", topics=query.items, total=total, \
|
||||||
topic_count=topic_count, query=search, \
|
topic_count=topic_count, query=search, show_discarded=show_discarded, \
|
||||||
next_url=next_url, prev_url=prev_url, page=page, page_max=query.pages)
|
next_url=next_url, prev_url=prev_url, page=page, page_max=query.pages)
|
||||||
|
23
migrations/versions/a791b9b74a4c_.py
Normal file
23
migrations/versions/a791b9b74a4c_.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: a791b9b74a4c
|
||||||
|
Revises: 44e138485931
|
||||||
|
Create Date: 2018-12-23 23:52:02.010281
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'a791b9b74a4c'
|
||||||
|
down_revision = '44e138485931'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.add_column('forum_topic', sa.Column('discarded', sa.Boolean(), server_default='0', nullable=True))
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
op.drop_column('forum_topic', 'discarded')
|
Loading…
Reference in New Issue
Block a user