Working on template loader

This commit is contained in:
jude 2023-11-01 22:10:56 +00:00
parent e36d2610da
commit b83f1f2f31
9 changed files with 214 additions and 98 deletions

View File

@ -52,6 +52,26 @@ type ChannelInfo = {
name: string;
};
type Template = {
id: number;
name: string;
attachment: string | null;
attachment_name: string | null;
avatar: string | null;
channel: string;
content: string;
embed_author: string;
embed_author_url: string | null;
embed_color: number;
embed_description: string;
embed_footer: string;
embed_footer_url: string | null;
embed_image_url: string | null;
embed_thumbnail_url: string | null;
embed_title: string;
embed_fields: EmbedField[] | null;
};
export function fetchUserInfo(): Promise<UserInfo> {
return axios.get("/dashboard/api/user").then((resp) => resp.data) as Promise<UserInfo>;
}
@ -62,21 +82,34 @@ export function fetchUserGuilds(): Promise<GuildInfo[]> {
>;
}
export function fetchGuildReminders(guild: string): Promise<Reminder[]> {
return axios
.get(`/dashboard/api/guild/${guild}/reminders`)
.then((resp) => resp.data)
.then((value) =>
value.map((reminder) => ({
...reminder,
utc_time: DateTime.fromISO(reminder.utc_time),
expires: reminder.expires === null ? null : DateTime.fromISO(reminder.expires),
})),
) as Promise<Reminder[]>;
}
export const fetchGuildReminders = (guild: string) => ({
queryKey: ["GUILD_REMINDERS", guild],
queryFn: () =>
axios
.get(`/dashboard/api/guild/${guild}/reminders`)
.then((resp) => resp.data)
.then((value) =>
value.map((reminder) => ({
...reminder,
utc_time: DateTime.fromISO(reminder.utc_time),
expires: reminder.expires === null ? null : DateTime.fromISO(reminder.expires),
})),
) as Promise<Reminder[]>,
});
export function fetchGuildChannels(guild: string): Promise<ChannelInfo[]> {
return axios.get(`/dashboard/api/guild/${guild}/channels`).then((resp) => resp.data) as Promise<
ChannelInfo[]
>;
}
export const fetchGuildChannels = (guild: string) => ({
queryKey: ["GUILD_CHANNELS", guild],
queryFn: () =>
axios.get(`/dashboard/api/guild/${guild}/channels`).then((resp) => resp.data) as Promise<
ChannelInfo[]
>,
staleTime: 300,
});
export const guildTemplatesQuery = (guild: string) => ({
queryKey: ["GUILD_TEMPLATES", guild],
queryFn: () =>
axios.get(`/dashboard/api/guild/${guild}/channels`).then((resp) => resp.data) as Promise<
Template[]
>,
});

View File

@ -8,10 +8,7 @@ import { CreateReminder } from "../Reminder/CreateReminder";
export const GuildReminders = () => {
const { guild } = useParams();
const { isSuccess, data } = useQuery({
queryKey: [QueryKeys.GUILD_REMINDERS, guild],
queryFn: () => fetchGuildReminders(guild),
});
const { isSuccess, data } = useQuery(fetchGuildReminders(guild));
return (
<div style={{ margin: "0 12px 12px 12px" }}>

View File

@ -0,0 +1,57 @@
import { JSX } from "preact";
type Props = {
setModalOpen: (open: boolean) => never;
title: string;
onSubmitText?: string;
onSubmit?: () => never;
children: string | JSX.Element | JSX.Element[] | (() => JSX.Element);
};
export const Modal = ({ setModalOpen, title, onSubmit, onSubmitText, children }: Props) => {
return (
<div class="modal is-active">
<div
class="modal-background"
onClick={() => {
setModalOpen(false);
}}
></div>
<div class="modal-card">
<header class="modal-card-head">
<label class="modal-card-title">{title}</label>
<button
class="delete close-modal"
aria-label="close"
onClick={() => {
setModalOpen(false);
}}
></button>
</header>
<section class="modal-card-body">{children}</section>
{onSubmit && (
<footer class="modal-card-foot">
<button class="button is-success" onChange={onSubmit}>
{onSubmitText || "Save"}
</button>
<button
class="button close-modal"
onClick={() => {
setModalOpen(false);
}}
>
Cancel
</button>
</footer>
)}
</div>
<button
class="modal-close is-large close-modal"
aria-label="close"
onClick={() => {
setModalOpen(false);
}}
></button>
</div>
);
};

View File

@ -6,11 +6,7 @@ import { fetchGuildChannels } from "../../api";
export const ChannelSelector = ({ channel }) => {
const { guild } = useParams();
const { isSuccess, data } = useQuery({
queryKey: [QueryKeys.GUILD_CHANNELS, guild],
queryFn: () => fetchGuildChannels(guild),
staleTime: 300,
});
const { isSuccess, data } = useQuery(fetchGuildChannels(guild));
return (
<div class="control has-icons-left">

View File

@ -2,29 +2,56 @@ import { useParams } from "wouter";
import { useState } from "preact/hooks";
import { useQueries } from "react-query";
import { QueryKeys } from "../../consts";
import { fetchGuildChannels, fetchUserInfo } from "../../api";
import { fetchGuildChannels, fetchUserInfo, Reminder } from "../../api";
import { Name } from "./Name";
import { Username } from "./Username";
import React from "react";
import { Content } from "./Content";
import { Embed } from "./Embed";
import { ChannelSelector } from "./ChannelSelector";
import { DateTime } from "luxon";
import { IntervalSelector } from "./IntervalSelector";
import { LoadTemplate } from "./LoadTemplate";
function defaultReminder(): Reminder {
return {
attachment: "",
attachment_name: "",
avatar: "",
channel: "",
content: "",
embed_author: "",
embed_author_url: "",
embed_color: 0,
embed_description: "",
embed_fields: [],
embed_footer: "",
embed_footer_url: "",
embed_image_url: "",
embed_thumbnail_url: "",
embed_title: "",
enabled: true,
expires: null,
interval_days: null,
interval_months: null,
interval_seconds: null,
name: "",
restartable: false,
tts: false,
uid: "",
username: "",
utc_time: DateTime.now(),
};
}
export const CreateReminder = () => {
const { guild } = useParams();
const [reminder, setReminder] = useState({});
const [reminder, setReminder] = useState(defaultReminder);
const [
{ isSuccess: channelsFetched, data: guildChannels },
{ isSuccess: userFetched, data: userInfo },
] = useQueries([
{
queryKey: [QueryKeys.GUILD_CHANNELS, guild],
queryFn: () => fetchGuildChannels(guild),
staleTime: 300,
},
fetchGuildChannels(guild),
{
queryKey: [QueryKeys.USER_DATA],
queryFn: fetchUserInfo,
@ -101,7 +128,7 @@ export const CreateReminder = () => {
Channel*
</label>
</div>
<ChannelSelector channel={null}></ChannelSelector>
<ChannelSelector channel={reminder.channel}></ChannelSelector>
</div>
<div class="field">
@ -220,9 +247,7 @@ export const CreateReminder = () => {
</button>
</div>
<div>
<button class="button is-outlined show-modal is-pulled-right">
Load Template
</button>
<LoadTemplate setReminder={setReminder}></LoadTemplate>
</div>
</div>
</div>

View File

@ -23,11 +23,7 @@ export const EditReminder = ({ reminder: initialReminder }: Props) => {
{ isSuccess: channelsFetched, data: guildChannels },
{ isSuccess: userFetched, data: userInfo },
] = useQueries([
{
queryKey: [QueryKeys.GUILD_CHANNELS, guild],
queryFn: () => fetchGuildChannels(guild),
staleTime: 300,
},
fetchGuildChannels(guild),
{
queryKey: [QueryKeys.USER_DATA],
queryFn: fetchUserInfo,

View File

@ -1,5 +1,6 @@
import { useState } from "preact/hooks";
import { HexColorPicker } from "react-colorful";
import { Modal } from "../../Modal";
export const Color = ({ color: colorProp, onChange }) => {
const [modalOpen, setModalOpen] = useState(false);
@ -31,61 +32,19 @@ const ColorModal = ({ setModalOpen, color: colorProp, onSave }) => {
const [color, setColor] = useState(colorProp);
return (
<div class="modal is-active" id="pickColorModal">
<div
class="modal-background"
onClick={() => {
setModalOpen(false);
}}
></div>
<div class="modal-card">
<header class="modal-card-head">
<label class="modal-card-title" for="colorInput">
Select Color
</label>
<button
class="delete close-modal"
aria-label="close"
onClick={() => {
setModalOpen(false);
}}
></button>
</header>
<section class="modal-card-body">
<div class="colorpicker-container">
<HexColorPicker color={color} onChange={setColor}></HexColorPicker>
</div>
<br></br>
<input
class="input"
id="colorInput"
value={color}
onChange={(ev) => {
setColor(ev.currentTarget.value);
}}
></input>
</section>
<footer class="modal-card-foot">
<button class="button is-success" onChange={onSave}>
Save
</button>
<button
class="button close-modal"
onClick={() => {
setModalOpen(false);
}}
>
Cancel
</button>
</footer>
<Modal setModalOpen={setModalOpen} title={"Select Color"} onSubmit={onSave}>
<div class="colorpicker-container">
<HexColorPicker color={color} onChange={setColor}></HexColorPicker>
</div>
<button
class="modal-close is-large close-modal"
aria-label="close"
onClick={() => {
setModalOpen(false);
<br></br>
<input
class="input"
id="colorInput"
value={color}
onChange={(ev) => {
setColor(ev.currentTarget.value);
}}
></button>
</div>
></input>
</Modal>
);
};

View File

@ -0,0 +1,54 @@
import { useState } from "preact/hooks";
import { Modal } from "../Modal";
import { useQuery } from "react-query";
import { guildTemplatesQuery } from "../../api";
import { useParams } from "wouter";
export const LoadTemplate = ({ setReminder }) => {
const [modalOpen, setModalOpen] = useState(false);
return (
<div>
<button
class="button is-outlined show-modal is-pulled-right"
onClick={() => {
setModalOpen(true);
}}
>
Load Template
</button>
{modalOpen && <LoadTemplateModal setModalOpen={setModalOpen}></LoadTemplateModal>}
</div>
);
};
const LoadTemplateModal = ({ setModalOpen }) => {
const { guild } = useParams();
const { status, data: templates } = useQuery(guildTemplatesQuery(guild));
return (
<Modal setModalOpen={setModalOpen} title={"Load Template"}>
<div class="control has-icons-left">
<div class="select is-fullwidth">
<select id="templateSelect">
{templates.map((template) => (
<option value={template.id}>{template.name}</option>
))}
</select>
</div>
<div class="icon is-small is-left">
<i class="fas fa-file-spreadsheet"></i>
</div>
</div>
<br></br>
<div class="has-text-centered">
<button class="button is-success close-modal" id="load-template">
Load Template
</button>
<button class="button is-danger" id="delete-template">
Delete
</button>
</div>
</Modal>
);
};

View File

@ -2,5 +2,4 @@ export enum QueryKeys {
USER_DATA = "userData",
USER_GUILDS = "userGuilds",
GUILD_REMINDERS = "guildReminders",
GUILD_CHANNELS = "guildChannels",
}