Working on template loader
This commit is contained in:
		
							
								
								
									
										49
									
								
								src/api.ts
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								src/api.ts
									
									
									
									
									
								
							@@ -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,8 +82,10 @@ export function fetchUserGuilds(): Promise<GuildInfo[]> {
 | 
			
		||||
    >;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function fetchGuildReminders(guild: string): Promise<Reminder[]> {
 | 
			
		||||
    return axios
 | 
			
		||||
export const fetchGuildReminders = (guild: string) => ({
 | 
			
		||||
    queryKey: ["GUILD_REMINDERS", guild],
 | 
			
		||||
    queryFn: () =>
 | 
			
		||||
        axios
 | 
			
		||||
            .get(`/dashboard/api/guild/${guild}/reminders`)
 | 
			
		||||
            .then((resp) => resp.data)
 | 
			
		||||
            .then((value) =>
 | 
			
		||||
@@ -72,11 +94,22 @@ export function fetchGuildReminders(guild: string): Promise<Reminder[]> {
 | 
			
		||||
                    utc_time: DateTime.fromISO(reminder.utc_time),
 | 
			
		||||
                    expires: reminder.expires === null ? null : DateTime.fromISO(reminder.expires),
 | 
			
		||||
                })),
 | 
			
		||||
        ) as Promise<Reminder[]>;
 | 
			
		||||
}
 | 
			
		||||
            ) as Promise<Reminder[]>,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export function fetchGuildChannels(guild: string): Promise<ChannelInfo[]> {
 | 
			
		||||
    return axios.get(`/dashboard/api/guild/${guild}/channels`).then((resp) => resp.data) as Promise<
 | 
			
		||||
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[]
 | 
			
		||||
        >,
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -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" }}>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										57
									
								
								src/components/Modal/index.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/components/Modal/index.tsx
									
									
									
									
									
										Normal 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>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
@@ -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">
 | 
			
		||||
 
 | 
			
		||||
@@ -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>
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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,27 +32,7 @@ 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">
 | 
			
		||||
        <Modal setModalOpen={setModalOpen} title={"Select Color"} onSubmit={onSave}>
 | 
			
		||||
            <div class="colorpicker-container">
 | 
			
		||||
                <HexColorPicker color={color} onChange={setColor}></HexColorPicker>
 | 
			
		||||
            </div>
 | 
			
		||||
@@ -64,28 +45,6 @@ const ColorModal = ({ setModalOpen, color: colorProp, onSave }) => {
 | 
			
		||||
                    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>
 | 
			
		||||
            </div>
 | 
			
		||||
            <button
 | 
			
		||||
                class="modal-close is-large close-modal"
 | 
			
		||||
                aria-label="close"
 | 
			
		||||
                onClick={() => {
 | 
			
		||||
                    setModalOpen(false);
 | 
			
		||||
                }}
 | 
			
		||||
            ></button>
 | 
			
		||||
        </div>
 | 
			
		||||
        </Modal>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										54
									
								
								src/components/Reminder/LoadTemplate.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/components/Reminder/LoadTemplate.tsx
									
									
									
									
									
										Normal 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>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
@@ -2,5 +2,4 @@ export enum QueryKeys {
 | 
			
		||||
    USER_DATA = "userData",
 | 
			
		||||
    USER_GUILDS = "userGuilds",
 | 
			
		||||
    GUILD_REMINDERS = "guildReminders",
 | 
			
		||||
    GUILD_CHANNELS = "guildChannels",
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user