Add overlay when data fetching

This commit is contained in:
jude 2024-02-24 17:23:31 +00:00
parent a8ef3d03f9
commit 79e6498245
13 changed files with 168 additions and 146 deletions

3
.gitignore vendored
View File

@ -2,7 +2,7 @@ target
.env .env
/venv /venv
.cargo .cargo
/.idea .idea
web/static/index.html web/static/index.html
web/static/assets web/static/assets
# Logs # Logs
@ -22,7 +22,6 @@ dist-ssr
# Editor directories and files # Editor directories and files
.vscode/* .vscode/*
!.vscode/extensions.json !.vscode/extensions.json
.idea
.DS_Store .DS_Store
*.suo *.suo
*.ntvs* *.ntvs*

2
Cargo.lock generated
View File

@ -2358,7 +2358,7 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]] [[package]]
name = "reminder-rs" name = "reminder-rs"
version = "1.7.0-rc1" version = "1.7.0-rc2"
dependencies = [ dependencies = [
"base64 0.21.7", "base64 0.21.7",
"chrono", "chrono",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "reminder-rs" name = "reminder-rs"
version = "1.7.0-rc1" version = "1.7.0-rc2"
authors = ["Jude Southworth <judesouthworth@pm.me>"] authors = ["Jude Southworth <judesouthworth@pm.me>"]
edition = "2021" edition = "2021"
license = "AGPL-3.0 only" license = "AGPL-3.0 only"

View File

@ -12,8 +12,8 @@ This also allows me to expand my frontend skills, which is relevant to part of m
## Developing ## Developing
1. Download the parent repo: https://gitea.jellypro.xyz/jude/reminder-bot 1. Run both `npm run dev` and `cargo run`
2. Initialise the submodules: `git pull --recurse-submodules` 2. Symlink assets: assuming cloned
3. Run both `npm run dev` and `cargo run` into `$HOME`, `ln -s $HOME/reminder-bot/reminder-dashboard/dist/index.html $HOME/reminder-bot/web/static/index.html`
4. Symlink assets: assuming cloned into `$HOME`, `ln -s $HOME/reminder-bot/reminder-dashboard/dist/index.html $HOME/reminder-bot/web/static/index.html` and and
`ln -s $HOME/reminder-bot/reminder-dashboard/dist/static/assets $HOME/reminder-bot/web/static/assets` `ln -s $HOME/reminder-bot/reminder-dashboard/dist/static/assets $HOME/reminder-bot/web/static/assets`

View File

@ -14,7 +14,7 @@ enum Sort {
export const GuildReminders = () => { export const GuildReminders = () => {
const { guild } = useParams(); const { guild } = useParams();
const { isSuccess, data: guildReminders } = useQuery(fetchGuildReminders(guild)); const { isSuccess, isFetching, data: guildReminders } = useQuery(fetchGuildReminders(guild));
const { data: channels } = useQuery(fetchGuildChannels(guild)); const { data: channels } = useQuery(fetchGuildChannels(guild));
const [collapsed, setCollapsed] = useState(false); const [collapsed, setCollapsed] = useState(false);
@ -85,7 +85,7 @@ export const GuildReminders = () => {
</div> </div>
</div> </div>
<div id={"guildReminders"}> <div id={"guildReminders"} className={isFetching ? "loading" : ""}>
{isSuccess && {isSuccess &&
guildReminders guildReminders
.sort((r1, r2) => { .sort((r1, r2) => {

View File

@ -97,3 +97,15 @@ macro_rules! json_err {
Err(json!({ "error": $message })) Err(json!({ "error": $message }))
}; };
} }
macro_rules! path {
($path:expr) => {{
use rocket::fs::relative;
if Path::new(concat!("/lib/reminder-rs/", $path)).exists() {
concat!("/lib/reminder-rs/", $path)
} else {
relative!($path)
}
}};
}

View File

@ -2,12 +2,8 @@ use std::path::Path;
use chrono::{naive::NaiveDateTime, Utc}; use chrono::{naive::NaiveDateTime, Utc};
use rand::{rngs::OsRng, seq::IteratorRandom}; use rand::{rngs::OsRng, seq::IteratorRandom};
use rocket::{ use rocket::{fs::NamedFile, http::CookieJar, response::Redirect, serde::json::json};
fs::{relative, NamedFile}, use rocket_dyn_templates::Template;
http::CookieJar,
response::Redirect,
serde::json::json,
};
use secrecy::ExposeSecret; use secrecy::ExposeSecret;
use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use serenity::{ use serenity::{
@ -19,6 +15,7 @@ use serenity::{
use sqlx::types::Json; use sqlx::types::Json;
use crate::{ use crate::{
catchers::internal_server_error,
check_guild_subscription, check_subscription, check_guild_subscription, check_subscription,
consts::{ consts::{
CHARACTERS, DAY, DEFAULT_AVATAR, MAX_CONTENT_LENGTH, MAX_EMBED_AUTHOR_LENGTH, CHARACTERS, DAY, DEFAULT_AVATAR, MAX_CONTENT_LENGTH, MAX_EMBED_AUTHOR_LENGTH,
@ -672,28 +669,44 @@ async fn create_database_channel(
Ok(row.id) Ok(row.id)
} }
#[get("/")] #[derive(Responder)]
pub async fn dashboard_home(cookies: &CookieJar<'_>) -> Result<NamedFile, Redirect> { pub enum DashboardPage {
if cookies.get_private("userid").is_some() { #[response(status = 200)]
NamedFile::open(Path::new(relative!("static/index.html"))).await.map_err(|e| { Ok(NamedFile),
warn!("Couldn't render dashboard: {:?}", e); #[response(status = 200)]
Unauthorised(Redirect),
#[response(status = 500)]
NotConfigured(Template),
}
Redirect::to("/login/discord") #[get("/")]
}) pub async fn dashboard_home(cookies: &CookieJar<'_>) -> DashboardPage {
if cookies.get_private("userid").is_some() {
match NamedFile::open(Path::new(path!("static/index.html"))).await {
Ok(f) => DashboardPage::Ok(f),
Err(e) => {
warn!("Couldn't render dashboard: {:?}", e);
DashboardPage::NotConfigured(internal_server_error().await)
}
}
} else { } else {
Err(Redirect::to("/login/discord")) DashboardPage::Unauthorised(Redirect::to("/login/discord"))
} }
} }
#[get("/<_..>")] #[get("/<_..>")]
pub async fn dashboard(cookies: &CookieJar<'_>) -> Result<NamedFile, Redirect> { pub async fn dashboard(cookies: &CookieJar<'_>) -> DashboardPage {
if cookies.get_private("userid").is_some() { if cookies.get_private("userid").is_some() {
NamedFile::open(Path::new(relative!("static/index.html"))).await.map_err(|e| { match NamedFile::open(Path::new(path!("static/index.html"))).await {
warn!("Couldn't render dashboard: {:?}", e); Ok(f) => DashboardPage::Ok(f),
Err(e) => {
warn!("Couldn't render dashboard: {:?}", e);
Redirect::to("/login/discord") DashboardPage::NotConfigured(internal_server_error().await)
}) }
}
} else { } else {
Err(Redirect::to("/login/discord")) DashboardPage::Unauthorised(Redirect::to("/login/discord"))
} }
} }

View File

@ -1 +1 @@
/home/jude/reminder-dashboard/dist/static/assets /home/jude/reminder-bot/reminder-dashboard/dist/static/assets

View File

@ -55,6 +55,7 @@ div.reminderContent.is-collapsed .hide-box {
div.reminderContent.is-collapsed .hide-box i { div.reminderContent.is-collapsed .hide-box i {
transform: rotate(90deg); transform: rotate(90deg);
} }
/* END */ /* END */
/* dashboard styles */ /* dashboard styles */
@ -202,6 +203,7 @@ div.interval-group {
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
} }
/* !Interval inputs */ /* !Interval inputs */
.left-pad { .left-pad {
@ -239,7 +241,7 @@ span.spacer {
} }
nav .dashboard-button { nav .dashboard-button {
background: white ; background: white;
} }
span.patreon-color { span.patreon-color {
@ -694,7 +696,7 @@ li.highlight {
} }
} }
/* loader */ /* loaders */
#loader { #loader {
position: fixed; position: fixed;
top: 0; top: 0;
@ -707,6 +709,11 @@ li.highlight {
font-size: 6rem; font-size: 6rem;
} }
.loading {
opacity: 0.2;
pointer-events: none;
}
/* END */ /* END */
div.reminderError { div.reminderError {

View File

@ -1 +0,0 @@
/home/jude/reminder-dashboard/dist/index.html

View File

@ -32,27 +32,54 @@
</div> </div>
{% endif %} {% endif %}
<nav class="navbar is-dark is-spaced is-size-4" role="navigation" aria-label="main navigation"> <div style="min-height: 100vh;">
<div class="navbar-brand"> <nav class="navbar is-dark is-spaced is-size-4" role="navigation" aria-label="main navigation">
<a class="navbar-item" href="/"> <div class="navbar-brand">
<figure class="image"> <a class="navbar-item" href="/">
<img src="/static/img/logo_flat.webp" alt="Reminder Bot Logo" class="is-rounded" style="width: auto;"> <figure class="image">
</figure> <img src="/static/img/logo_flat.webp" alt="Reminder Bot Logo" class="is-rounded" style="width: auto;">
</a> </figure>
</a>
<a role="button" class="navbar-burger is-right" aria-label="menu" aria-expanded="false" data-target="pageNavbar"> <a role="button" class="navbar-burger is-right" aria-label="menu" aria-expanded="false" data-target="pageNavbar">
<span aria-hidden="true"></span> <span aria-hidden="true"></span>
<span aria-hidden="true"></span> <span aria-hidden="true"></span>
<span aria-hidden="true"></span> <span aria-hidden="true"></span>
</a> </a>
</div> </div>
<div class="navbar-menu"> <div class="navbar-menu">
<div class="navbar-start"> <div class="navbar-start">
<a class="navbar-item" href="https://invite.reminder-bot.com">
<i class="fas fa-plus"></i>
</a>
<a class="navbar-item" href="https://gitea.jellypro.xyz/jude">
<i class="fab fa-git-square"></i>
</a>
<a class="navbar-item" href="https://discord.jellywx.com">
<i class="fab fa-discord"></i>
</a>
<a class="navbar-item" href="/help">
<i class="fas fa-book"></i>
</a>
</div>
<div class="navbar-end">
<div class="navbar-item">
<a class="button is-rounded is-light" href="/dashboard">
<p>
<span>Dashboard</span> <span class="icon"><i class="fas fa-chevron-right"></i></span>
</p>
</a>
</div>
</div>
</div>
<div class="navbar-menu is-hidden-desktop" id="pageNavbar">
<a class="navbar-item" href="https://invite.reminder-bot.com"> <a class="navbar-item" href="https://invite.reminder-bot.com">
<i class="fas fa-plus"></i> <i class="fas fa-plus"></i>
</a> </a>
<a class="navbar-item" href="https://gitea.jellypro.xyz/jude"> <a class="navbar-item" href="https://github.com/jellywx">
<i class="fab fa-git-square"></i> <i class="fab fa-github"></i>
</a> </a>
<a class="navbar-item" href="https://discord.jellywx.com"> <a class="navbar-item" href="https://discord.jellywx.com">
<i class="fab fa-discord"></i> <i class="fab fa-discord"></i>
@ -60,92 +87,67 @@
<a class="navbar-item" href="/help"> <a class="navbar-item" href="/help">
<i class="fas fa-book"></i> <i class="fas fa-book"></i>
</a> </a>
</div>
<div class="navbar-end">
<div class="navbar-item"> <div class="navbar-item">
<a class="button is-rounded is-light" href="/dashboard"> <a href="/dashboard">
<p> <p>
<span>Dashboard</span> <span class="icon"><i class="fas fa-chevron-right"></i></span> Dashboard <span class="icon"><i class="fas fa-chevron-right"></i></span>
</p> </p>
</a> </a>
</div> </div>
</div> </div>
</div> </nav>
<div class="navbar-menu is-hidden-desktop" id="pageNavbar"> {% if not hide_title_block %}
<a class="navbar-item" href="https://invite.reminder-bot.com"> <section class="hero is-small is-dark">
<i class="fas fa-plus"></i> <div class="hero-body">
</a> <div class="">
<a class="navbar-item" href="https://github.com/jellywx"> <h1 class="title is-1">{{ page_title }}</h1>
<i class="fab fa-github"></i> <h2 class="subtitle is-3">{{ page_subtitle }}
</a> {% if page_emoji %}
<a class="navbar-item" href="https://discord.jellywx.com"> <span class="icon"><i class="fas {{ page_emoji }}"></i></span>
<i class="fab fa-discord"></i> {% endif %}
</a> </h2>
<a class="navbar-item" href="/help"> </div>
<i class="fas fa-book"></i>
</a>
<div class="navbar-item">
<a href="/dashboard">
<p>
Dashboard <span class="icon"><i class="fas fa-chevron-right"></i></span>
</p>
</a>
</div>
</div>
</nav>
{% if not hide_title_block %}
<section class="hero is-small is-dark">
<div class="hero-body">
<div class="">
<h1 class="title is-1">{{ page_title }}</h1>
<h2 class="subtitle is-3">{{ page_subtitle }}
{% if page_emoji %}
<span class="icon"><i class="fas {{ page_emoji }}"></i></span>
{% endif %}
</h2>
</div> </div>
</div>
{% if show_invite %} {% if show_invite %}
<div class="hero-foot has-text-centered"> <div class="hero-foot has-text-centered">
<a class="button is-size-4 is-rounded is-success" href="https://invite.reminder-bot.com"> <a class="button is-size-4 is-rounded is-success" href="https://invite.reminder-bot.com">
<p class="is-size-4"> <p class="is-size-4">
<span>Add to your Server</span> <span class="icon"><i class="fas fa-chevron-right"></i></span> <span>Add to your Server</span> <span class="icon"><i class="fas fa-chevron-right"></i></span>
</p> </p>
</a> </a>
</div> </div>
{% elif show_contact %} {% elif show_contact %}
<div class="hero-foot has-text-centered"> <div class="hero-foot has-text-centered">
<a class="button is-size-4 is-rounded is-primary" href="https://discord.jellywx.com"> <a class="button is-size-4 is-rounded is-primary" href="https://discord.jellywx.com">
<p class="is-size-4"> <p class="is-size-4">
<span>Join Discord</span> <span class="icon"><i class="fas fa-chevron-right"></i></span> <span>Join Discord</span> <span class="icon"><i class="fas fa-chevron-right"></i></span>
</p> </p>
</a> </a>
</div> </div>
{% elif show_login %} {% elif show_login %}
<div class="hero-foot has-text-centered"> <div class="hero-foot has-text-centered">
<a class="button is-size-4 is-rounded is-light" href="/login/discord"> <a class="button is-size-4 is-rounded is-light" href="/login/discord">
<p class="is-size-4"> <p class="is-size-4">
<span>Login with Discord</span> <span class="icon"><i class="fas fa-chevron-right"></i></span> <span>Login with Discord</span> <span class="icon"><i class="fas fa-chevron-right"></i></span>
</p> </p>
</a> </a>
</div> </div>
{% endif %} {% endif %}
</section> </section>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 160"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 160">
<path transform="scale(1, 0.5)" fill="#98dc9a" fill-opacity="1" d="M0,288L80,266.7C160,245,320,203,480,202.7C640,203,800,245,960,218.7C1120,192,1280,96,1360,48L1440,0L1440,0L1360,0C1280,0,1120,0,960,0C800,0,640,0,480,0C320,0,160,0,80,0L0,0Z"></path> <path transform="scale(1, 0.5)" fill="#98dc9a" fill-opacity="1" d="M0,288L80,266.7C160,245,320,203,480,202.7C640,203,800,245,960,218.7C1120,192,1280,96,1360,48L1440,0L1440,0L1360,0C1280,0,1120,0,960,0C800,0,640,0,480,0C320,0,160,0,80,0L0,0Z"></path>
<path transform="scale(1, 0.5)" fill="#363636" fill-opacity="1" d="M0,224L60,202.7C120,181,240,139,360,138.7C480,139,600,181,720,197.3C840,213,960,203,1080,176C1200,149,1320,107,1380,85.3L1440,64L1440,0L1380,0C1320,0,1200,0,1080,0C960,0,840,0,720,0C600,0,480,0,360,0C240,0,120,0,60,0L0,0Z"> <path transform="scale(1, 0.5)" fill="#363636" fill-opacity="1" d="M0,224L60,202.7C120,181,240,139,360,138.7C480,139,600,181,720,197.3C840,213,960,203,1080,176C1200,149,1320,107,1380,85.3L1440,64L1440,0L1380,0C1320,0,1200,0,1080,0C960,0,840,0,720,0C600,0,480,0,360,0C240,0,120,0,60,0L0,0Z">
</path> </path>
</svg> </svg>
{% endif %} {% endif %}
{% block content %} {% block content %}
{% endblock %} {% endblock %}
</div>
<br> <br>
<footer class="footer"> <footer class="footer">
@ -165,25 +167,15 @@
<script> <script>
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
// Get all "navbar-burger" elements
const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0); const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
// Check if there are any navbar burgers
if ($navbarBurgers.length > 0) { if ($navbarBurgers.length > 0) {
$navbarBurgers.forEach( el => {
el.addEventListener('click', () => {
const target = el.dataset.target;
const $target = document.getElementById(target);
// Add a click event on each of them el.classList.toggle('is-active');
$navbarBurgers.forEach( el => { $target.classList.toggle('is-active');
el.addEventListener('click', () => {
// Get the target from the "data-target" attribute
const target = el.dataset.target;
const $target = document.getElementById(target);
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
el.classList.toggle('is-active');
$target.classList.toggle('is-active');
}); });
}); });
} }

View File

@ -6,5 +6,5 @@
{% set show_contact = True %} {% set show_contact = True %}
{% set page_title = "Forbidden" %} {% set page_title = "Forbidden" %}
{% set page_subtitle = "You currently cannot access this page, if it exists. Sorry." %} {% set page_subtitle = "You currently cannot access this page, if it exists." %}
{% endblock %} {% endblock %}

View File

@ -6,5 +6,5 @@
{% set show_contact = True %} {% set show_contact = True %}
{% set page_title = "File Not Found" %} {% set page_title = "File Not Found" %}
{% set page_subtitle = "This page does not exist. Sorry." %} {% set page_subtitle = "This page does not exist." %}
{% endblock %} {% endblock %}