add header content

This commit is contained in:
Tan, Kian-ting 2022-11-15 23:49:04 +08:00
parent 373076489c
commit 57b1a870a8
6 changed files with 254 additions and 181 deletions

View file

@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/4.1/ref/settings/
""" """
from pathlib import Path from pathlib import Path
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'. # Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent BASE_DIR = Path(__file__).resolve().parent.parent
@ -117,7 +118,8 @@ USE_TZ = True
# https://docs.djangoproject.com/en/4.1/howto/static-files/ # https://docs.djangoproject.com/en/4.1/howto/static-files/
STATIC_URL = 'static/' STATIC_URL = 'static/'
STATIC_ROOT = '/home/kiantin1/public_html/khaikang/static/' STATICFILES_DIRS= [os.path.join(BASE_DIR, 'static')] # test only
# STATIC_ROOT = '/home/kiantin1/public_html/khaikang/static/' deploy only
# Default primary key field type # Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field # https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field

View file

@ -28,3 +28,4 @@ urlpatterns = [
path('api/get_latest_posts', views.api_get_latest_posts), path('api/get_latest_posts', views.api_get_latest_posts),
path('api/get_previous_posts', views.api_get_previous_posts), path('api/get_previous_posts', views.api_get_previous_posts),
] ]

View file

@ -0,0 +1,33 @@
@media (prefers-color-scheme: dark) {
:root {
--primary: #264b5d;
--primary-fg: #f7f7f7;
--body-fg: #eeeeee;
--body-bg: #121212;
--body-quiet-color: #e0e0e0;
--body-loud-color: #ffffff;
--breadcrumbs-link-fg: #e0e0e0;
--breadcrumbs-bg: var(--primary);
--link-fg: #81d4fa;
--link-hover-color: #4ac1f7;
--link-selected-fg: #6f94c6;
--hairline-color: #272727;
--border-color: #353535;
--error-fg: #e35f5f;
--message-success-bg: #006b1b;
--message-warning-bg: #583305;
--message-error-bg: #570808;
--darkened-bg: #212121;
--selected-bg: #1b1b1b;
--selected-row: #00363a;
--close-button-bg: #333333;
--close-button-hover-bg: #666666;
}
}

View file

@ -0,0 +1,30 @@
/**
* Persist changelist filters state (collapsed/expanded).
*/
'use strict';
{
// Init filters.
let filters = JSON.parse(sessionStorage.getItem('django.admin.filtersState'));
if (!filters) {
filters = {};
}
Object.entries(filters).forEach(([key, value]) => {
const detailElement = document.querySelector(`[data-filter-title='${key}']`);
// Check if the filter is present, it could be from other view.
if (detailElement) {
value ? detailElement.setAttribute('open', '') : detailElement.removeAttribute('open');
}
});
// Save filter state when clicks.
const details = document.querySelectorAll('details');
details.forEach(detail => {
detail.addEventListener('toggle', event => {
filters[`${event.target.dataset.filterTitle}`] = detail.open;
sessionStorage.setItem('django.admin.filtersState', JSON.stringify(filters));
});
});
}

178
static/timeline.js Normal file
View file

@ -0,0 +1,178 @@
timezoneChangingOne = (x)=>{var date= new Date(x.innerHTML);
var year = date.getFullYear().toString();
var month = (date.getMonth()+1).toString().padStart(2, '0');
var day = date.getDate().toString().padStart(2, '0');
var hour = date.getHours().toString().padStart(2, '0');
var min = date.getMinutes().toString().padStart(2, '0');
var sec = date.getSeconds().toString().padStart(2, '0');
local_date_string = `${year}-${month}-${day} ${hour}:${min}:${sec}`;
x.innerHTML=local_date_string;}
function timezoneChanging(){
document.querySelectorAll(".post-time").forEach(
x => timezoneChangingOne(x)
);
}
$name = (x) => document.getElementsByName(x);
$ = (x) => document.getElementById(x);
var httpRequest;
$("submit_post").addEventListener('click', make_req);
async function make_req() {
post_text = $('post_text').value;
post_privilage = $('privil_choosing').value;
if (post_text != ""){
await fetch('/api/post', {
method: 'POST',
headers: {
"X-CSRFToken": "{{ csrf_token }}",
'Content-Type': 'application/json',
},
body: JSON.stringify({
"privilage" : post_privilage,
"text": post_text,
})
}).then(response => {if (response.ok == true)
{$('post_text').value = "";
getLatestPosts(); // wait for a moment then get latest posts
}}
);
}
}
function auto_expand(element) {
element.style.height = 6+"em";
element.style.height = (element.scrollHeight)+"px";
}
timezoneChanging();
function adjust_post_text(){
var post_text = $("post_text");
post_text.style.height = 6+"em";
post_text.style.height = (post_text.scrollHeight)+"px";
}
async function getRecentPostsCounter(){
latest_time_string = $("latest_time").innerHTML;
await fetch('/api/get_recent_posts_counter', {
method: 'POST',
headers: {
"X-CSRFToken": "{{ csrf_token }}",
'Content-Type': 'application/json',
},
body: JSON.stringify({
"latest_time" : latest_time_string,
})
}).then(response => response.json())
.then(the_json => {console.log(the_json);let newer_posts_num = the_json['newer_posts_num'];
if (newer_posts_num == 1)
{ $("new_post_notifier").style.display = "block";
$("new_post_notifier").innerHTML = `1 new post`}
if (newer_posts_num > 1)
{ $("new_post_notifier").style.display = "block";
$("new_post_notifier").innerHTML = `${newer_posts_num} new posts`} });
}
var intervalID = window.setInterval(getRecentPostsCounter, 20000);
function appendPostToTheEnd(post){
var public_tl = $("public_timeline");
var new_div = createPostDiv(post);
public_tl.insertBefore(new_div, $('previous_post_loader'));
}
async function getPreviousPosts(){
var new_oldest_time;
oldest_time_string = $("oldest_time").innerHTML;
await fetch('/api/get_previous_posts', {
method: 'POST',
headers: {
"X-CSRFToken": "{{ csrf_token }}",
'Content-Type': 'application/json',
},
body: JSON.stringify({
"oldest_time" : oldest_time_string,
}) }).then(response => response.json())
.then(item => {new_oldest_time_raw = item['oldest_time'];
new_oldest_time = new_oldest_time_raw.substring(0,10) + " " + new_oldest_time_raw.substring(11,26) + "+0000";
return item['older_posts'];})
.then(posts => {if (posts.length == 0)
{$('previous_post_loader').style.display = 'none';}
else{posts.forEach(post => appendPostToTheEnd(post));
$('oldest_time').innerHTML = new_oldest_time;}})
}
async function getLatestPosts(){
latest_time_string = $("latest_time").innerHTML;
await fetch('/api/get_latest_posts', {
method: 'POST',
headers: {
"X-CSRFToken": "{{ csrf_token }}",
'Content-Type': 'application/json',
},
body: JSON.stringify({
"latest_time" : latest_time_string,
}) }).then(response => response.json())
.then(item => item['newer_posts'])
.then(posts => {posts.forEach(post => addPostToTheBeginning(post));
$('new_post_notifier').style.display = "none";
var nowTime = new Date();
var nowTimeString = nowTime.toISOString();
$("latest_time").innerHTML = nowTimeString.substring(0,10) + " " + nowTimeString.substring(11,23) + "000+0000"; });
}
function createPostDiv(post){
var new_div = document.createElement("div");
new_div.id = `post-${post.id}`;
new_div.className = "post";
post_text_replaced = post.text.replace(/(\r\n|\n\r|\r|\n)/g, "<br>" );
console.log(post_text_replaced);
new_div.innerHTML = `<a href="/user/${post.poster_username}">${post.poster_shown_name}</a>
at <a href="/post/${post.id}" class="post-time">${post.post_time}</a><br>
${post_text_replaced}<br>
<span id="reply-${post.id}" value="${post.id}" class="reply"></span>
- <span id="repost-${post.id}" value="${post.id}" class="repost">🔁</span>
- <span id="fav-${post.id}" value="${post.id}" class="fav"></span>`;
new_div_timestamp = new_div.getElementsByClassName('post-time')[0];
timezoneChangingOne(new_div_timestamp);
return new_div;
}
function addPostToTheBeginning(post){
var public_tl = $("public_timeline");
var new_div = createPostDiv(post);
public_tl.insertBefore(new_div, $('latest_time').nextSibling);
}
$("new_post_notifier").addEventListener('click', getLatestPosts);
$("previous_post_loader").addEventListener('click', getPreviousPosts);
adjust_post_text();

View file

@ -1,7 +1,12 @@
{% extends "base_generic.html" %} {% extends "base_generic.html" %}
{% load static %}
{% load tz %} {% load tz %}
{% get_current_timezone as TIME_ZONE %} {% get_current_timezone as TIME_ZONE %}
{% block headbar %}
{{ request.user.shown_name }} (<a href="/user/{{ request.user.username}}">My timeline</a>) - <a href="/user/config">Configs</a> - <a href="/account/logout">Log out</a>
{% endblock %}
{% block content %} {% block content %}
<form method="POST" id="posting-form"> <form method="POST" id="posting-form">
{% csrf_token %} {% csrf_token %}
@ -31,8 +36,8 @@
{% for public_post in public_timeline_list %} {% for public_post in public_timeline_list %}
<div id="post-{{public_post.id}}" class="post"><a href="user/{{public_post.poster}}">{{public_post.poster.shown_name}}</a> <div id="post-{{public_post.id}}" class="post"><a href="/user/{{public_post.poster}}">{{public_post.poster.shown_name}}</a>
at <a href="post/{{public_post.id}}" class="post-time">{{public_post.post_time|date:"Y-m-d H:i:s.u"}}+0000</a><br/> at <a href="/post/{{public_post.id}}" class="post-time">{{public_post.post_time|date:"Y-m-d H:i:s.u"}}+0000</a><br/>
{{public_post.text|linebreaksbr}}<br/> {{public_post.text|linebreaksbr}}<br/>
<span id="reply-{{public_post.id}}" value="{{public_post.id}}" class="reply">↩️</span> <span id="reply-{{public_post.id}}" value="{{public_post.id}}" class="reply">↩️</span>
- <span id="repost-{{public_post.id}}" value="{{public_post.id}}" class="repost">🔁</span> - <span id="repost-{{public_post.id}}" value="{{public_post.id}}" class="repost">🔁</span>
@ -45,185 +50,9 @@
</div> </div>
<script> <script type="text/javascript" src="{% static 'timeline.js' %}">
timezoneChangingOne = (x)=>{var date= new Date(x.innerHTML);
var year = date.getFullYear().toString();
var month = (date.getMonth()+1).toString().padStart(2, '0');
var day = date.getDate().toString().padStart(2, '0');
var hour = date.getHours().toString().padStart(2, '0');
var min = date.getMinutes().toString().padStart(2, '0');
var sec = date.getSeconds().toString().padStart(2, '0');
local_date_string = `${year}-${month}-${day} ${hour}:${min}:${sec}`;
x.innerHTML=local_date_string;}
function timezoneChanging(){
document.querySelectorAll(".post-time").forEach(
x => timezoneChangingOne(x)
);
}
$name = (x) => document.getElementsByName(x);
$ = (x) => document.getElementById(x);
var httpRequest;
$("submit_post").addEventListener('click', make_req);
async function make_req() {
post_text = $('post_text').value;
post_privilage = $('privil_choosing').value;
if (post_text != ""){
await fetch('/api/post', {
method: 'POST',
headers: {
"X-CSRFToken": "{{ csrf_token }}",
'Content-Type': 'application/json',
},
body: JSON.stringify({
"privilage" : post_privilage,
"text": post_text,
})
}).then(response => {if (response.ok == true)
{$('post_text').value = "";
getLatestPosts(); // wait for a moment then get latest posts
}}
);
}
}
function auto_expand(element) {
element.style.height = 6+"em";
element.style.height = (element.scrollHeight)+"px";
}
timezoneChanging();
function adjust_post_text(){
var post_text = $("post_text");
post_text.style.height = 6+"em";
post_text.style.height = (post_text.scrollHeight)+"px";
}
async function getRecentPostsCounter(){
latest_time_string = $("latest_time").innerHTML;
await fetch('/api/get_recent_posts_counter', {
method: 'POST',
headers: {
"X-CSRFToken": "{{ csrf_token }}",
'Content-Type': 'application/json',
},
body: JSON.stringify({
"latest_time" : latest_time_string,
})
}).then(response => response.json())
.then(the_json => {console.log(the_json);let newer_posts_num = the_json['newer_posts_num'];
if (newer_posts_num == 1)
{ $("new_post_notifier").style.display = "block";
$("new_post_notifier").innerHTML = `1 new post`}
if (newer_posts_num > 1)
{ $("new_post_notifier").style.display = "block";
$("new_post_notifier").innerHTML = `${newer_posts_num} new posts`} });
}
var intervalID = window.setInterval(getRecentPostsCounter, 20000);
function appendPostToTheEnd(post){
var public_tl = $("public_timeline");
var new_div = createPostDiv(post);
public_tl.insertBefore(new_div, $('previous_post_loader'));
}
async function getPreviousPosts(){
var new_oldest_time;
oldest_time_string = $("oldest_time").innerHTML;
await fetch('/api/get_previous_posts', {
method: 'POST',
headers: {
"X-CSRFToken": "{{ csrf_token }}",
'Content-Type': 'application/json',
},
body: JSON.stringify({
"oldest_time" : oldest_time_string,
}) }).then(response => response.json())
.then(item => {new_oldest_time_raw = item['oldest_time'];
new_oldest_time = new_oldest_time_raw.substring(0,10) + " " + new_oldest_time_raw.substring(11,26) + "+0000";
return item['older_posts'];})
.then(posts => {if (posts.length == 0)
{$('previous_post_loader').style.display = 'none';}
else{posts.forEach(post => appendPostToTheEnd(post));
$('oldest_time').innerHTML = new_oldest_time;}})
}
async function getLatestPosts(){
latest_time_string = $("latest_time").innerHTML;
await fetch('/api/get_latest_posts', {
method: 'POST',
headers: {
"X-CSRFToken": "{{ csrf_token }}",
'Content-Type': 'application/json',
},
body: JSON.stringify({
"latest_time" : latest_time_string,
}) }).then(response => response.json())
.then(item => item['newer_posts'])
.then(posts => {posts.forEach(post => addPostToTheBeginning(post));
$('new_post_notifier').style.display = "none";
var nowTime = new Date();
var nowTimeString = nowTime.toISOString();
$("latest_time").innerHTML = nowTimeString.substring(0,10) + " " + nowTimeString.substring(11,23) + "000+0000"; });
}
function createPostDiv(post){
var new_div = document.createElement("div");
new_div.id = `post-${post.id}`;
new_div.className = "post";
post_text_replaced = post.text.replace(/(\r\n|\n\r|\r|\n)/g, "<br>" );
console.log(post_text_replaced);
new_div.innerHTML = `<a href="user/${post.poster_username}">${post.poster_shown_name}</a>
at <a href="post/${post.id}" class="post-time">${post.post_time}</a><br>
${post_text_replaced}<br>
<span id="reply-${post.id}" value="${post.id}" class="reply">↩️</span>
- <span id="repost-${post.id}" value="${post.id}" class="repost">🔁</span>
- <span id="fav-${post.id}" value="${post.id}" class="fav"></span>`;
new_div_timestamp = new_div.getElementsByClassName('post-time')[0];
timezoneChangingOne(new_div_timestamp);
return new_div;
}
function addPostToTheBeginning(post){
var public_tl = $("public_timeline");
var new_div = createPostDiv(post);
public_tl.insertBefore(new_div, $('latest_time').nextSibling);
}
$("new_post_notifier").addEventListener('click', getLatestPosts);
$("previous_post_loader").addEventListener('click', getPreviousPosts);
adjust_post_text();
</script> </script>
{% endblock %} {% endblock %}