Start work on todo list support for dashboard

This commit is contained in:
jude 2024-04-06 14:27:58 +01:00
parent b951db3f55
commit 9989ab3b35
8 changed files with 170 additions and 5 deletions

View File

@ -49,6 +49,12 @@ export type Reminder = {
utc_time: string;
};
export type Todo = {
id: string;
channel_id: string;
value: string;
};
export type ChannelInfo = {
id: string;
name: string;
@ -190,6 +196,33 @@ export const deleteGuildTemplate = (guild: string) => ({
}),
});
export const fetchGuildTodos = (guild: string) => ({
queryKey: ["GUILD_TODOS", guild],
queryFn: () =>
axios.get(`/dashboard/api/guild/${guild}/todos`).then((resp) => resp.data) as Promise<
Todo[]
>,
staleTime: OTHER_STALE_TIME,
});
export const patchGuildTodo = (guild: string) => ({
mutationFn: (todo: Todo) => axios.patch(`/dashboard/api/guild/${guild}/todos`, todo),
});
export const postGuildTodo = (guild: string) => ({
mutationFn: (reminder: Reminder) =>
axios.post(`/dashboard/api/guild/${guild}/todos`, reminder).then((resp) => resp.data),
});
export const deleteGuildTodo = () => ({
mutationFn: (todo: Todo) =>
axios.delete(`/dashboard/api/todos`, {
data: {
id: todo.id,
},
}),
});
export const fetchUserReminders = () => ({
queryKey: ["USER_REMINDERS"],
queryFn: () =>

View File

@ -6,6 +6,8 @@ import { Guild } from "../Guild";
import { FlashProvider } from "./FlashProvider";
import { TimezoneProvider } from "./TimezoneProvider";
import { User } from "../User";
import { GuildReminders } from "../Guild/GuildReminders";
import { GuildTodos } from "../Guild/GuildTodos";
export function App() {
const queryClient = new QueryClient();
@ -20,7 +22,22 @@ export function App() {
<div class="column is-main-content">
<Switch>
<Route path={"/@me/reminders"} component={User}></Route>
<Route path={"/:guild/reminders"} component={Guild}></Route>
<Route
path={"/:guild/reminders"}
component={() => (
<Guild>
<GuildReminders />
</Guild>
)}
></Route>
<Route
path={"/:guild/todos"}
component={
<Guild>
<GuildTodos />
</Guild>
}
></Route>
<Route>
<Welcome />
</Route>

View File

@ -0,0 +1,21 @@
import { useQuery, useQueryClient } from "react-query";
import { fetchGuildChannels, fetchGuildTodos } from "../../api";
import { useState } from "preact/hooks";
import { useGuild } from "../App/useGuild";
export const GuildTodos = () => {
const guild = useGuild();
const {
isSuccess,
isFetching,
isFetched,
data: guildReminders,
} = useQuery(fetchGuildTodos(guild));
const { data: channels } = useQuery(fetchGuildChannels(guild));
const [collapsed, setCollapsed] = useState(false);
const queryClient = useQueryClient();
return <></>;
};

View File

@ -1,12 +1,11 @@
import { useQuery } from "react-query";
import { fetchGuildInfo } from "../../api";
import { GuildReminders } from "./GuildReminders";
import { GuildError } from "./GuildError";
import { createPortal } from "preact/compat";
import { createPortal, PropsWithChildren } from "preact/compat";
import { Import } from "../Import";
import { useGuild } from "../App/useGuild";
export const Guild = () => {
export const Guild = ({ children }: PropsWithChildren) => {
const guild = useGuild();
const { isSuccess, data: guildInfo } = useQuery(fetchGuildInfo(guild));
@ -20,7 +19,7 @@ export const Guild = () => {
return (
<>
{importModal}
<GuildReminders />
{children}
</>
);
}

View File

@ -0,0 +1,23 @@
import { Todo as TodoT } from "../../api";
type Props = {
todo: TodoT;
};
export const Todo = ({ todo }: Props) => {
return (
<div>
<textarea value={todo.value} onInput={() => null} />
<button onClick={() => null} class="btn save-btn">
<span class="icon">
<i class="fa fa-save"></i>
</span>
</button>
<button onClick={() => null} class="btn delete-btn">
<span class="icon">
<i class="fa fa-trash"></i>
</span>
</button>
</div>
);
};

View File

@ -145,6 +145,10 @@ pub async fn initialize(
routes::dashboard::api::guild::create_guild_reminder,
routes::dashboard::api::guild::get_reminders,
routes::dashboard::api::guild::edit_reminder,
routes::dashboard::api::guild::create_todo,
routes::dashboard::api::guild::get_todo,
routes::dashboard::api::guild::update_todo,
routes::dashboard::api::guild::delete_todo,
routes::dashboard::export::export_reminders,
routes::dashboard::export::export_reminder_templates,
routes::dashboard::export::export_todos,

View File

@ -3,6 +3,7 @@ mod emojis;
mod reminders;
mod roles;
mod templates;
mod todos;
use std::env;
@ -16,6 +17,7 @@ use serenity::{
model::id::{GuildId, RoleId},
};
pub use templates::*;
pub use todos::{create_todo, delete_todo, get_todo, update_todo};
use crate::web::{check_authorization, routes::JsonResult};

View File

@ -0,0 +1,66 @@
use rocket::{
delete, get,
http::CookieJar,
patch, post,
serde::json::{json, Json},
State,
};
use serde::Deserialize;
use serenity::prelude::Context;
use crate::web::{check_authorization, guards::transaction::Transaction, routes::JsonResult};
#[derive(Deserialize)]
struct CreateTodo {
channel_id: Option<u64>,
value: String,
}
#[post("/api/guild/<id>/todos", data = "<todo>")]
pub async fn create_todo(
id: u64,
todo: Json<CreateTodo>,
cookies: &CookieJar<'_>,
ctx: &State<Context>,
mut transaction: Transaction<'_>,
) -> JsonResult {
check_authorization(cookies, ctx.inner(), id).await?;
Ok(json!({}))
}
#[get("/api/guild/<id>/todos")]
pub async fn get_todo(
id: u64,
cookies: &CookieJar<'_>,
ctx: &State<Context>,
mut transaction: Transaction<'_>,
) -> JsonResult {
check_authorization(cookies, ctx.inner(), id).await?;
Ok(json!([]))
}
#[patch("/api/guild/<id>/todos")]
pub async fn update_todo(
id: u64,
cookies: &CookieJar<'_>,
ctx: &State<Context>,
mut transaction: Transaction<'_>,
) -> JsonResult {
check_authorization(cookies, ctx.inner(), id).await?;
Ok(json!({}))
}
#[delete("/api/guild/<id>/todos")]
pub async fn delete_todo(
id: u64,
cookies: &CookieJar<'_>,
ctx: &State<Context>,
mut transaction: Transaction<'_>,
) -> JsonResult {
check_authorization(cookies, ctx.inner(), id).await?;
Ok(json!({}))
}