Lists support (draft)
This commit is contained in:
parent
cbd7fc6446
commit
fe4ea02cb0
4 changed files with 195 additions and 1 deletions
104
app.py
104
app.py
|
@ -1578,6 +1578,14 @@ def admin_new():
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/admin/lists", methods=["GET"])
|
||||||
|
@login_required
|
||||||
|
def admin_lists():
|
||||||
|
lists = list(DB.lists.find())
|
||||||
|
|
||||||
|
return render_template("lists.html", lists=lists)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/admin/notifications")
|
@app.route("/admin/notifications")
|
||||||
@login_required
|
@login_required
|
||||||
def admin_notifications():
|
def admin_notifications():
|
||||||
|
@ -1895,6 +1903,34 @@ def admin_stream():
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/admin/list/<name>")
|
||||||
|
@login_required
|
||||||
|
def admin_list(name):
|
||||||
|
list_ = DB.lists.find_one({"name": name})
|
||||||
|
if not list_:
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
q = {
|
||||||
|
"meta.stream": True,
|
||||||
|
"meta.deleted": False,
|
||||||
|
"meta.actor_id": {"$in": list_["members"]},
|
||||||
|
}
|
||||||
|
|
||||||
|
tpl = "stream.html"
|
||||||
|
if request.args.get("debug"):
|
||||||
|
tpl = "stream_debug.html"
|
||||||
|
if request.args.get("debug_inbox"):
|
||||||
|
q = {}
|
||||||
|
|
||||||
|
inbox_data, older_than, newer_than = paginated_query(
|
||||||
|
DB.activities, q, limit=int(request.args.get("limit", 25))
|
||||||
|
)
|
||||||
|
|
||||||
|
return render_template(
|
||||||
|
tpl, inbox_data=inbox_data, older_than=older_than, newer_than=newer_than
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/admin/bookmarks")
|
@app.route("/admin/bookmarks")
|
||||||
@login_required
|
@login_required
|
||||||
def admin_bookmarks():
|
def admin_bookmarks():
|
||||||
|
@ -2073,6 +2109,72 @@ def api_debug():
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/api/new_list", methods=["POST"])
|
||||||
|
@api_required
|
||||||
|
def api_new_list():
|
||||||
|
name = _user_api_arg("name")
|
||||||
|
if not name:
|
||||||
|
raise ValueError("missing name")
|
||||||
|
|
||||||
|
if not DB.lists.find_one({"name": name}):
|
||||||
|
DB.lists.insert_one({"name": name, "members": []})
|
||||||
|
|
||||||
|
return _user_api_response(name=name)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/api/delete_list", methods=["POST"])
|
||||||
|
@api_required
|
||||||
|
def api_delete_list():
|
||||||
|
name = _user_api_arg("name")
|
||||||
|
if not name:
|
||||||
|
raise ValueError("missing name")
|
||||||
|
|
||||||
|
if not DB.lists.find_one({"name": name}):
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
DB.lists.delete_one({"name": name})
|
||||||
|
|
||||||
|
return _user_api_response()
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/api/add_to_list", methods=["POST"])
|
||||||
|
@api_required
|
||||||
|
def api_add_to_list():
|
||||||
|
list_name = _user_api_arg("list_name")
|
||||||
|
if not list_name:
|
||||||
|
raise ValueError("missing list_name")
|
||||||
|
|
||||||
|
if not DB.lists.find_one({"name": list_name}):
|
||||||
|
raise ValueError(f"list {list_name} does not exist")
|
||||||
|
|
||||||
|
actor_id = _user_api_arg("actor_id")
|
||||||
|
if not actor_id:
|
||||||
|
raise ValueError("missing actor_id")
|
||||||
|
|
||||||
|
DB.lists.update_one({"name": list_name}, {"$addToSet": {"members": actor_id}})
|
||||||
|
|
||||||
|
return _user_api_response()
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/api/remove_from_list", methods=["POST"])
|
||||||
|
@api_required
|
||||||
|
def api_remove_from_list():
|
||||||
|
list_name = _user_api_arg("list_name")
|
||||||
|
if not list_name:
|
||||||
|
raise ValueError("missing list_name")
|
||||||
|
|
||||||
|
if not DB.lists.find_one({"name": list_name}):
|
||||||
|
raise ValueError(f"list {list_name} does not exist")
|
||||||
|
|
||||||
|
actor_id = _user_api_arg("actor_id")
|
||||||
|
if not actor_id:
|
||||||
|
raise ValueError("missing actor_id")
|
||||||
|
|
||||||
|
DB.lists.update_one({"name": list_name}, {"$pull": {"members": actor_id}})
|
||||||
|
|
||||||
|
return _user_api_response()
|
||||||
|
|
||||||
|
|
||||||
@app.route("/api/new_note", methods=["POST"])
|
@app.route("/api/new_note", methods=["POST"])
|
||||||
@api_required
|
@api_required
|
||||||
def api_new_note():
|
def api_new_note():
|
||||||
|
@ -2322,11 +2424,13 @@ def following():
|
||||||
for doc in following
|
for doc in following
|
||||||
if "remote_id" in doc and "object" in doc.get("meta", {})
|
if "remote_id" in doc and "object" in doc.get("meta", {})
|
||||||
]
|
]
|
||||||
|
lists = list(DB.lists.find())
|
||||||
return render_template(
|
return render_template(
|
||||||
"following.html",
|
"following.html",
|
||||||
following_data=following,
|
following_data=following,
|
||||||
older_than=older_than,
|
older_than=older_than,
|
||||||
newer_than=newer_than,
|
newer_than=newer_than,
|
||||||
|
lists=lists,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,12 +11,40 @@
|
||||||
{% for (follow_id, follow) in following_data %}
|
{% for (follow_id, follow) in following_data %}
|
||||||
{% if session.logged_in %}
|
{% if session.logged_in %}
|
||||||
<div style="margin-left:90px;padding-bottom:5px;margin-bottom:15px;display:inline-block;">
|
<div style="margin-left:90px;padding-bottom:5px;margin-bottom:15px;display:inline-block;">
|
||||||
<form action="/api/undo" class="action-form" method="POST">
|
<form action="/api/undo" class="action-form" method="post">
|
||||||
<input type="hidden" name="redirect" value="{{ request.path }}"/>
|
<input type="hidden" name="redirect" value="{{ request.path }}"/>
|
||||||
<input type="hidden" name="id" value="{{ follow_id }}"/>
|
<input type="hidden" name="id" value="{{ follow_id }}"/>
|
||||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||||
<button type="submit" class="bar-item">unfollow</button>
|
<button type="submit" class="bar-item">unfollow</button>
|
||||||
</form>
|
</form>
|
||||||
|
<form action="/api/add_to_list" class="action-form" method="post">
|
||||||
|
<input type="hidden" name="redirect" value="{{ request.path }}"/>
|
||||||
|
<input type="hidden" name="actor_id" value="{{ follow.id }}"/>
|
||||||
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||||
|
<select name="list_name" style="float:left;">
|
||||||
|
<option></option>
|
||||||
|
{% for l in lists %}
|
||||||
|
{% if follow.id not in l.members %}
|
||||||
|
<option value="{{l.name}}">{{l.name}}</option>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
<button type="submit" class="bar-item">add to list</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% for l in lists %}
|
||||||
|
{% if follow.id in l.members %}
|
||||||
|
<form action="/api/remove_from_list" class="action-form" method="post">
|
||||||
|
<input type="hidden" name="redirect" value="{{ request.path }}"/>
|
||||||
|
<input type="hidden" name="actor_id" value="{{ follow.id }}"/>
|
||||||
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||||
|
<button type="submit" class="bar-item">remove from {{ l.name }}</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
<li class="left"><a href="/admin/new"{% if request.path == "/admin/new" %} class="selected" {% endif %}>New</a></li>
|
<li class="left"><a href="/admin/new"{% if request.path == "/admin/new" %} class="selected" {% endif %}>New</a></li>
|
||||||
<li class="left"><a href="/admin/stream"{% if request.path == "/admin/stream" %} class="selected" {% endif %}>Stream</a></li>
|
<li class="left"><a href="/admin/stream"{% if request.path == "/admin/stream" %} class="selected" {% endif %}>Stream</a></li>
|
||||||
<li class="left"><a href="/admin/notifications"{% if request.path == "/admin/notifications" %} class="selected" {% endif %}>Notifications</a></li>
|
<li class="left"><a href="/admin/notifications"{% if request.path == "/admin/notifications" %} class="selected" {% endif %}>Notifications</a></li>
|
||||||
|
<li class="left"><a href="/admin/lists"{% if request.path == url_for('admin_lists') %} class="selected" {% endif %}>Lists</a></li>
|
||||||
<li class="left"><a href="/admin/bookmarks"{% if request.path == "/admin/bookmarks" %} class="selected" {% endif %}>Bookmarks</a></li>
|
<li class="left"><a href="/admin/bookmarks"{% if request.path == "/admin/bookmarks" %} class="selected" {% endif %}>Bookmarks</a></li>
|
||||||
<li class="left"><a href="/admin/lookup"{% if request.path == "/admin/lookup" %} class="selected" {% endif %}>Lookup</a></li>
|
<li class="left"><a href="/admin/lookup"{% if request.path == "/admin/lookup" %} class="selected" {% endif %}>Lookup</a></li>
|
||||||
<li class="left"><a href="/admin/logout">Logout</a></li>
|
<li class="left"><a href="/admin/logout">Logout</a></li>
|
||||||
|
|
61
templates/lists.html
Normal file
61
templates/lists.html
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
{% extends "layout.html" %}
|
||||||
|
{% import 'utils.html' as utils %}
|
||||||
|
{% block title %}Lists - {{ config.NAME }}{% endblock %}
|
||||||
|
{% block headers %}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div id="container">
|
||||||
|
{% include "header.html" %}
|
||||||
|
|
||||||
|
<div id="following">
|
||||||
|
<h2>New List</h2>
|
||||||
|
<form action="/api/new_list" method="POST">
|
||||||
|
<input type="hidden" name="redirect" value="{{ url_for('admin_lists') }}">
|
||||||
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||||
|
<input type="text" name="name" placeholder="My list">
|
||||||
|
<input type="submit" value="Create">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<h2>Lists</h2>
|
||||||
|
<p>Manage list members in the <a href="{{ url_for('following') }}">Following section</a></p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
{% for l in lists %}
|
||||||
|
<li><a href="{{url_for('admin_list', name=l.name)}}">{{ l.name }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>Manage lists</h2>
|
||||||
|
{% for l in lists %}
|
||||||
|
<h3><a href="{{url_for("admin_list", name=l.name)}}">{{ l.name }}</a> <small style="font-weight:normal">{{ l.members | length }} members</small></h3>
|
||||||
|
<form action="/api/delete_list" method="post">
|
||||||
|
<input type="hidden" name="redirect" value="{{ request.path }}"/>
|
||||||
|
<input type="hidden" name="name" value="{{ l.name }}"/>
|
||||||
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||||
|
<button type="submit" class="bar-item">delete list</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div style="clear:both;padding-top:30px;">
|
||||||
|
|
||||||
|
{% for member in l.members %}
|
||||||
|
<div style="margin-left:90px;padding-bottom:5px;margin-bottom:15px;display:inline-block;">
|
||||||
|
<form action="/api/remove_from_list" class="action-form" method="post">
|
||||||
|
<input type="hidden" name="redirect" value="{{ request.path }}"/>
|
||||||
|
<input type="hidden" name="actor_id" value="{{ member }}"/>
|
||||||
|
<input type="hidden" name="list_name" value="{{ l.name }}"/>
|
||||||
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||||
|
<button type="submit" class="bar-item">remove from {{ l.name }}</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="height: 100px;">
|
||||||
|
{{ utils.display_actor_inline(member | get_actor, size=80) }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
Loading…
Reference in a new issue