message page
This commit is contained in:
parent
156a9becc1
commit
17fc3d6ffe
10 changed files with 77 additions and 43 deletions
|
@ -21,6 +21,7 @@ BASE_DIR = Path(__file__).resolve().parent.parent
|
|||
|
||||
STATIC_DIR = BASE_DIR / "tmessage/static"
|
||||
ALLOWED_HOSTS = ["*"]
|
||||
CSRF_TRUSTED_ORIGINS = [config["services"]["message"]["url"]["pub"]]
|
||||
|
||||
INSTALLED_APPS = [
|
||||
"django.contrib.admin",
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
width: calc(90vw - 40px);
|
||||
max-width: 400px;
|
||||
padding: 20px;
|
||||
padding-top: 2px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 30px;
|
||||
border-radius: 6px;
|
||||
|
|
|
@ -10,11 +10,13 @@ function getMessageHTML(messageJSON, canRespond) {
|
|||
let el = document.createElement("div");
|
||||
el.classList.add("message-container");
|
||||
el.dataset.messageId = messageJSON.id;
|
||||
el.innerHTML = `<blockquote class="message">
|
||||
<div><b>${messageJSON.from || "Anonymous"}</b> writes: <small>${timeSince(messageJSON.timestamp)}</small></div>
|
||||
<pre class="not-code">${escapeHTML(messageJSON.content)}</pre>
|
||||
el.innerHTML = `
|
||||
<p>Messaging <a href="/u/${messageJSON.to}/">${messageJSON.to}</a>: ${messageJSON.response ? `<small>${timeSince(messageJSON.response_timestamp)}</small>` : ""}</p>
|
||||
<blockquote class="message">
|
||||
<div><${messageJSON.from ? "a" : "b"} href="/u/${messageJSON.from}/">${messageJSON.from || "Anony­mous"}</${messageJSON.from ? "a" : "b"}> writes: <small>${timeSince(messageJSON.timestamp)}</small></div>
|
||||
<a class="fake-link" href="/msg/${messageJSON.id}/"><pre class="not-code">${escapeHTML(messageJSON.content)}</pre></a>
|
||||
</blockquote>
|
||||
${messageJSON.response ? `<small>${timeSince(messageJSON.response_timestamp)}</small><pre class="not-code no-margin">\n${escapeHTML(messageJSON.response)}</pre>` : ""}
|
||||
${messageJSON.response ? `<a class="fake-link" href="/msg/${messageJSON.id}/"><pre class="not-code no-margin">${escapeHTML(messageJSON.response)}</pre></a>` : ""}
|
||||
${
|
||||
canRespond ? `
|
||||
<div class="msg-error"></div>
|
||||
|
@ -29,31 +31,6 @@ function getMessageHTML(messageJSON, canRespond) {
|
|||
return el
|
||||
}
|
||||
|
||||
function timeSince(date) {
|
||||
let months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
||||
let dateObject = new Date(date * 1000);
|
||||
let dateString = `${months[dateObject.getMonth()]} ${dateObject.getDate()}, ${dateObject.getFullYear()}, ${String(dateObject.getHours()).padStart(2, "0")}:${String(dateObject.getMinutes()).padStart(2, "0")}:${String(dateObject.getSeconds()).padStart(2, "0")}`;
|
||||
let seconds = Math.floor((+(new Date()) / 1000 - date + 1));
|
||||
let unit = "second";
|
||||
let amount = seconds > 0 ? seconds : 0;
|
||||
const timeAmounts = [
|
||||
{ name: "minute", amount: 60 },
|
||||
{ name: "hour", amount: 3600 },
|
||||
{ name: "day", amount: 86400 },
|
||||
{ name: "month", amount: 2592000 },
|
||||
{ name: "year", amount: 31536000 }
|
||||
];
|
||||
|
||||
for (const info of timeAmounts) {
|
||||
let interval = seconds / info.amount;
|
||||
if (interval >= 1) {
|
||||
unit = info.name;
|
||||
amount = Math.floor(interval);
|
||||
}
|
||||
}
|
||||
return `<span data-timestamp="${date}" title="${dateString}">${Math.floor(amount)} ${unit}${Math.floor(amount) == 1 ? "" : "s"} ago</span>`;
|
||||
}
|
||||
|
||||
function replyTo(messageID) {
|
||||
let msgContainer = document.querySelector(`.message-container[data-message-id="${messageID}"]`);
|
||||
let self = msgContainer.querySelector(".reply-button")
|
||||
|
@ -197,9 +174,3 @@ function fetchMessages(fetchFromStart=false) {
|
|||
}
|
||||
|
||||
fetchMessages(true);
|
||||
|
||||
setInterval(function () {
|
||||
for (const timestamp of document.querySelectorAll("[data-timestamp]")) {
|
||||
timestamp.innerHTML = timeSince(Number(timestamp.dataset.timestamp));
|
||||
}
|
||||
}, 5000);
|
||||
|
|
25
tmessage/templates/message-page.html
Normal file
25
tmessage/templates/message-page.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="/static/css/messages.css?v={{ config.version_str }}">
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="message-container">
|
||||
<p>Messaging <a href="/u/{{ message.u_to.username }}/">{{ message.u_to.username }}</a>: {% if message.response %}<small><span data-timestamp="{{ message.response_timestamp }}"></span></small>{% endif %}</p>
|
||||
<blockquote class="message">
|
||||
<div>{% if not message.anonymous and message.u_from.username %}<a href="/u/{{ message.u_from.username }}/">{{ message.u_from.username }}</a>{% else %}<b>Anony­mous</b>{% endif %} writes: <small><span data-timestamp="{{ message.sent_timestamp }}"></span></small></div>
|
||||
<pre class="not-code">{{ message.content }}</pre>
|
||||
</blockquote>
|
||||
<pre class="not-code no-margin">{{ message.response }}</pre>
|
||||
</div>
|
||||
|
||||
{% if username %}
|
||||
Logged in as <a href="/u/{{ username }}/">{{ username }}</b>
|
||||
<p><a href="/messages/">View your messages</a></p>
|
||||
{% else %}
|
||||
Not logged in.
|
||||
{% if config.new_users %}<a href="{{ config.services.auth.url.pub }}/signup/">Sign up</a>{% else %}<a href="{{ config.services.auth.url.pub }}/login/">Log in</a>{% endif %}?
|
||||
{% endif %}
|
||||
<script src="{{ config.services.common.url.pub }}/static/js/base.js?v={{ config.version_str }}"></script>
|
||||
{% endblock %}
|
|
@ -8,7 +8,7 @@
|
|||
{% csrf_token %}
|
||||
<p><textarea class="auto-size" name="message" id="message" required maxlength="10000" placeholder="Your message"></textarea></p>
|
||||
{% if self_username %}
|
||||
Logged in as <b>{{ self_username }}</b>
|
||||
Logged in as <a href="/u/{{ username }}/">{{ username }}</b>
|
||||
<div>
|
||||
<input name="anonymous" id="anonymous" type="checkbox">
|
||||
<label data-fake-checkbox for="anonymous">Don't attach your username</label>
|
||||
|
@ -18,5 +18,6 @@
|
|||
{% if config.new_users %}<a href="{{ config.services.auth.url.pub }}/signup/">Sign up</a>{% else %}<a href="{{ config.services.auth.url.pub }}/login/">Log in</a>{% endif %}?
|
||||
{% endif %}
|
||||
<p><input type="submit" value="Send message"></p>
|
||||
{% if self_username %}<p><a href="/messages/">View your messages</a></p>{% endif %}
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
|
@ -7,14 +7,27 @@
|
|||
|
||||
{% block body %}
|
||||
<h1>Your messages</h1>
|
||||
Logged in as <b>{{ username }}</b>
|
||||
<p>Logged in as <a href="/u/{{ username }}">{{ username }}</a></p>
|
||||
<hr>
|
||||
<button id="refresh" onclick="fetchMessages(true);">Refresh</button>
|
||||
<p>
|
||||
<div>Your message link: <code class="cursor-pointer" id="message-link">{{ config.services.message.url.pub }}/m/{{ username }}/</code></div>
|
||||
<div><small>(click to copy)</small></div>
|
||||
</p>
|
||||
|
||||
<p><button id="refresh" onclick="fetchMessages(true);">Refresh</button></p>
|
||||
<p id="switch">
|
||||
<b data-url="/api/messages/" data-id="all" href="javascript:(() => { updateURL('all'); })()">All messages</b> -
|
||||
<a data-url="/api/messages/?unread" data-id="unread" class="not-bold" href="javascript:(() => { updateURL('unread'); })()">Not responded</a>
|
||||
</p>
|
||||
<div id="messages"><i class="delete-if-more-messages">Loading...</i></div>
|
||||
<button hidden id="more-button" onclick="fetchMessages(false);">Load more</button>
|
||||
<script src="{{ config.services.common.url.pub }}/static/js/base.js?v={{ config.version_str }}"></script>
|
||||
<script src="/static/js/messages.js?v={{ config.version_str }}"></script>
|
||||
<script>
|
||||
document.getElementById("message-link").addEventListener("click", function() {
|
||||
navigator.clipboard.writeText(this.innerText);
|
||||
this.classList.remove("success-anim");
|
||||
setTimeout(() => { this.classList.add("success-anim"); }, 10);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
from django.contrib import admin
|
||||
from django.urls import include, path
|
||||
|
||||
from .views import api_messages, auth, index, message, messages, profile
|
||||
from .views import (api_messages, auth, index, message, message_page, messages,
|
||||
profile)
|
||||
|
||||
urlpatterns = [
|
||||
path("", index),
|
||||
|
@ -9,6 +10,7 @@ urlpatterns = [
|
|||
path("messages/", messages),
|
||||
path("u/<str:username>/", profile),
|
||||
path("m/<str:username>/", message),
|
||||
path("msg/<int:message_id>/", message_page),
|
||||
path("api/messages/", api_messages),
|
||||
path("static/", include("tmessage.views.static")),
|
||||
path("django-admin/", admin.site.urls)
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
from .api import api_messages # noqa: F401
|
||||
from .templates import auth, index, message, messages, profile # noqa: F401
|
||||
from .templates import (auth, index, message, message_page, # noqa: F401
|
||||
messages, profile)
|
||||
|
|
|
@ -96,7 +96,7 @@ def api_messages(request: WSGIRequest) -> HttpResponse:
|
|||
|
||||
output = []
|
||||
messages = msgObjects.order_by("-message_id")[:50].values_list(
|
||||
"message_id", "content", "response", "anonymous", "u_from", "sent_timestamp", "response_timestamp"
|
||||
"message_id", "content", "response", "anonymous", "u_from", "u_to", "sent_timestamp", "response_timestamp"
|
||||
)
|
||||
|
||||
for message in messages:
|
||||
|
@ -105,8 +105,9 @@ def api_messages(request: WSGIRequest) -> HttpResponse:
|
|||
"content": message[1],
|
||||
"response": message[2],
|
||||
"from": message[4] if not message[3] and message[4] else None,
|
||||
"timestamp": message[5],
|
||||
"response_timestamp": message[6]
|
||||
"to": message[5],
|
||||
"timestamp": message[6],
|
||||
"response_timestamp": message[7]
|
||||
})
|
||||
|
||||
return _json_response({
|
||||
|
|
|
@ -38,6 +38,22 @@ def index(request: WSGIRequest) -> HttpResponse:
|
|||
def profile(request: WSGIRequest, username: str) -> HttpResponse:
|
||||
...
|
||||
|
||||
def message_page(request: WSGIRequest, message_id: int) -> HttpResponse:
|
||||
try:
|
||||
message = tMMessage.objects.get(message_id=message_id)
|
||||
except tMMessage.DoesNotExist:
|
||||
return render_template(
|
||||
request, "404.html",
|
||||
status=404
|
||||
)
|
||||
|
||||
return render_template(
|
||||
request, "message-page.html",
|
||||
title="Viewing a Message",
|
||||
message=message,
|
||||
username=get_username(request)
|
||||
)
|
||||
|
||||
def message(request: WSGIRequest, username: str) -> HttpResponse:
|
||||
if not username_exists(username):
|
||||
return render_template(
|
||||
|
@ -73,6 +89,7 @@ def message(request: WSGIRequest, username: str) -> HttpResponse:
|
|||
|
||||
return render_template(
|
||||
request, "message.html",
|
||||
title=f"Messaging {username}",
|
||||
username=username,
|
||||
error=error,
|
||||
self_username=get_username(request)
|
||||
|
@ -86,5 +103,6 @@ def messages(request: WSGIRequest) -> HttpResponse:
|
|||
|
||||
return render_template(
|
||||
request, "messages.html",
|
||||
title="Messages",
|
||||
username=username
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue