Add modal for image picker
This commit is contained in:
parent
b83f1f2f31
commit
5dc7ceb8aa
31
src/api.ts
31
src/api.ts
@ -52,6 +52,11 @@ type ChannelInfo = {
|
|||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type RoleInfo = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
|
||||||
type Template = {
|
type Template = {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
@ -72,15 +77,16 @@ type Template = {
|
|||||||
embed_fields: EmbedField[] | null;
|
embed_fields: EmbedField[] | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function fetchUserInfo(): Promise<UserInfo> {
|
export const fetchUserInfo = () => ({
|
||||||
return axios.get("/dashboard/api/user").then((resp) => resp.data) as Promise<UserInfo>;
|
queryKey: ["USER_INFO"],
|
||||||
}
|
queryFn: () => axios.get("/dashboard/api/user").then((resp) => resp.data) as Promise<UserInfo>,
|
||||||
|
});
|
||||||
|
|
||||||
export function fetchUserGuilds(): Promise<GuildInfo[]> {
|
export const fetchUserGuilds = () => ({
|
||||||
return axios.get("/dashboard/api/user/guilds").then((resp) => resp.data) as Promise<
|
queryKey: ["USER_GUILDS"],
|
||||||
GuildInfo[]
|
queryFn: () =>
|
||||||
>;
|
axios.get("/dashboard/api/user/guilds").then((resp) => resp.data) as Promise<GuildInfo[]>,
|
||||||
}
|
});
|
||||||
|
|
||||||
export const fetchGuildReminders = (guild: string) => ({
|
export const fetchGuildReminders = (guild: string) => ({
|
||||||
queryKey: ["GUILD_REMINDERS", guild],
|
queryKey: ["GUILD_REMINDERS", guild],
|
||||||
@ -106,6 +112,15 @@ export const fetchGuildChannels = (guild: string) => ({
|
|||||||
staleTime: 300,
|
staleTime: 300,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const fetchGuildRoles = (guild: string) => ({
|
||||||
|
queryKey: ["GUILD_ROLES", guild],
|
||||||
|
queryFn: () =>
|
||||||
|
axios.get(`/dashboard/api/guild/${guild}/roles`).then((resp) => resp.data) as Promise<
|
||||||
|
RoleInfo[]
|
||||||
|
>,
|
||||||
|
staleTime: 300,
|
||||||
|
});
|
||||||
|
|
||||||
export const guildTemplatesQuery = (guild: string) => ({
|
export const guildTemplatesQuery = (guild: string) => ({
|
||||||
queryKey: ["GUILD_TEMPLATES", guild],
|
queryKey: ["GUILD_TEMPLATES", guild],
|
||||||
queryFn: () =>
|
queryFn: () =>
|
||||||
|
@ -4,7 +4,7 @@ type Props = {
|
|||||||
setModalOpen: (open: boolean) => never;
|
setModalOpen: (open: boolean) => never;
|
||||||
title: string;
|
title: string;
|
||||||
onSubmitText?: string;
|
onSubmitText?: string;
|
||||||
onSubmit?: () => never;
|
onSubmit?: () => void;
|
||||||
children: string | JSX.Element | JSX.Element[] | (() => JSX.Element);
|
children: string | JSX.Element | JSX.Element[] | (() => JSX.Element);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { useParams } from "wouter";
|
import { useParams } from "wouter";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
import { useQueries } from "react-query";
|
import { useQuery } from "react-query";
|
||||||
import { QueryKeys } from "../../consts";
|
import { fetchUserInfo, Reminder } from "../../api";
|
||||||
import { fetchGuildChannels, fetchUserInfo, Reminder } from "../../api";
|
|
||||||
import { Name } from "./Name";
|
import { Name } from "./Name";
|
||||||
import { Username } from "./Username";
|
import { Username } from "./Username";
|
||||||
import { Content } from "./Content";
|
import { Content } from "./Content";
|
||||||
@ -11,6 +10,7 @@ import { ChannelSelector } from "./ChannelSelector";
|
|||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
import { IntervalSelector } from "./IntervalSelector";
|
import { IntervalSelector } from "./IntervalSelector";
|
||||||
import { LoadTemplate } from "./LoadTemplate";
|
import { LoadTemplate } from "./LoadTemplate";
|
||||||
|
import { ImagePicker } from "./ImagePicker";
|
||||||
|
|
||||||
function defaultReminder(): Reminder {
|
function defaultReminder(): Reminder {
|
||||||
return {
|
return {
|
||||||
@ -47,21 +47,11 @@ export const CreateReminder = () => {
|
|||||||
const { guild } = useParams();
|
const { guild } = useParams();
|
||||||
const [reminder, setReminder] = useState(defaultReminder);
|
const [reminder, setReminder] = useState(defaultReminder);
|
||||||
|
|
||||||
const [
|
const { isSuccess: userFetched, data: userInfo } = useQuery(fetchUserInfo());
|
||||||
{ isSuccess: channelsFetched, data: guildChannels },
|
|
||||||
{ isSuccess: userFetched, data: userInfo },
|
|
||||||
] = useQueries([
|
|
||||||
fetchGuildChannels(guild),
|
|
||||||
{
|
|
||||||
queryKey: [QueryKeys.USER_DATA],
|
|
||||||
queryFn: fetchUserInfo,
|
|
||||||
staleTime: Infinity,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
const [collapsed, setCollapsed] = useState(false);
|
const [collapsed, setCollapsed] = useState(false);
|
||||||
|
|
||||||
if (!channelsFetched || !userFetched) {
|
if (!userFetched) {
|
||||||
// todo
|
// todo
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
@ -87,13 +77,11 @@ export const CreateReminder = () => {
|
|||||||
<article class="media">
|
<article class="media">
|
||||||
<figure class="media-left">
|
<figure class="media-left">
|
||||||
<p class="image is-32x32 customizable">
|
<p class="image is-32x32 customizable">
|
||||||
<a>
|
<ImagePicker
|
||||||
<img
|
class="is-rounded avatar"
|
||||||
class="is-rounded avatar"
|
alt="Image for discord avatar"
|
||||||
src="/static/img/bg.webp"
|
setImage={() => {}}
|
||||||
alt="Image for discord avatar"
|
></ImagePicker>
|
||||||
></img>
|
|
||||||
</a>
|
|
||||||
</p>
|
</p>
|
||||||
</figure>
|
</figure>
|
||||||
<div class="media-content">
|
<div class="media-content">
|
||||||
|
@ -22,14 +22,7 @@ export const EditReminder = ({ reminder: initialReminder }: Props) => {
|
|||||||
const [
|
const [
|
||||||
{ isSuccess: channelsFetched, data: guildChannels },
|
{ isSuccess: channelsFetched, data: guildChannels },
|
||||||
{ isSuccess: userFetched, data: userInfo },
|
{ isSuccess: userFetched, data: userInfo },
|
||||||
] = useQueries([
|
] = useQueries([fetchGuildChannels(guild), fetchUserInfo()]);
|
||||||
fetchGuildChannels(guild),
|
|
||||||
{
|
|
||||||
queryKey: [QueryKeys.USER_DATA],
|
|
||||||
queryFn: fetchUserInfo,
|
|
||||||
staleTime: Infinity,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
const [collapsed, setCollapsed] = useState(false);
|
const [collapsed, setCollapsed] = useState(false);
|
||||||
|
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
|
import { ImagePicker } from "../ImagePicker";
|
||||||
|
|
||||||
export const Author = ({ name, icon }) => {
|
export const Author = ({ name, icon }) => {
|
||||||
return (
|
return (
|
||||||
<div class="embed-author-box">
|
<div class="embed-author-box">
|
||||||
<div class="a">
|
<div class="a">
|
||||||
<p class="image is-24x24 customizable">
|
<p class="image is-24x24 customizable">
|
||||||
<a>
|
<ImagePicker
|
||||||
<img
|
class="is-rounded embed_author_url"
|
||||||
class="is-rounded embed_author_url"
|
url={icon}
|
||||||
src={icon || "/static/img/bg.webp"}
|
alt="Image for embed author"
|
||||||
alt="Image for embed author"
|
setImage={() => {}}
|
||||||
></img>
|
></ImagePicker>
|
||||||
</a>
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -4,11 +4,7 @@ import { Description } from "./Description";
|
|||||||
import { Footer } from "./Footer";
|
import { Footer } from "./Footer";
|
||||||
import { Color } from "./Color";
|
import { Color } from "./Color";
|
||||||
import { Reminder } from "../../../api";
|
import { Reminder } from "../../../api";
|
||||||
|
import { ImagePicker } from "../ImagePicker";
|
||||||
type Props = {
|
|
||||||
reminder: Reminder;
|
|
||||||
setReminder: (reminder: Reminder) => {};
|
|
||||||
};
|
|
||||||
|
|
||||||
function colorToInt(hex: string) {
|
function colorToInt(hex: string) {
|
||||||
return parseInt(hex.substring(1), 16);
|
return parseInt(hex.substring(1), 16);
|
||||||
@ -85,25 +81,21 @@ export const Embed = ({ reminder, setReminder }) => {
|
|||||||
|
|
||||||
<div class="b">
|
<div class="b">
|
||||||
<p class="image thumbnail customizable">
|
<p class="image thumbnail customizable">
|
||||||
<a>
|
<ImagePicker
|
||||||
<img
|
class="embed_thumbnail_url"
|
||||||
class="embed_thumbnail_url"
|
alt="Square thumbnail embedded image"
|
||||||
src="/static/img/bg.webp"
|
setImage={() => {}}
|
||||||
alt="Square thumbnail embedded image"
|
></ImagePicker>
|
||||||
></img>
|
|
||||||
</a>
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="image is-400x300 customizable">
|
<p class="image is-400x300 customizable">
|
||||||
<a>
|
<ImagePicker
|
||||||
<img
|
class="embed_image_url"
|
||||||
class="embed_image_url"
|
alt="Large embedded image"
|
||||||
src="/static/img/bg.webp"
|
setImage={() => {}}
|
||||||
alt="Large embedded image"
|
></ImagePicker>
|
||||||
></img>
|
|
||||||
</a>
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<Footer footer={reminder.embed_footer} icon={reminder.embed_footer_url}></Footer>
|
<Footer footer={reminder.embed_footer} icon={reminder.embed_footer_url}></Footer>
|
||||||
|
49
src/components/Reminder/ImagePicker.tsx
Normal file
49
src/components/Reminder/ImagePicker.tsx
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { Modal } from "../Modal";
|
||||||
|
import { useState } from "preact/hooks";
|
||||||
|
|
||||||
|
export const ImagePicker = ({ alt, url, setImage, ...props }) => {
|
||||||
|
const [modalOpen, setModalOpen] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<a
|
||||||
|
onClick={() => {
|
||||||
|
setModalOpen(true);
|
||||||
|
}}
|
||||||
|
role={"button"}
|
||||||
|
>
|
||||||
|
<img {...props} src={url || "/static/img/bg.webp"} alt={alt}></img>
|
||||||
|
</a>
|
||||||
|
{modalOpen && (
|
||||||
|
<ImagePickerModal
|
||||||
|
setModalOpen={setModalOpen}
|
||||||
|
setImage={setImage}
|
||||||
|
></ImagePickerModal>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ImagePickerModal = ({ setModalOpen, setImage }) => {
|
||||||
|
const [value, setValue] = useState("");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
setModalOpen={setModalOpen}
|
||||||
|
title={"Enter Image URL"}
|
||||||
|
onSubmit={() => {
|
||||||
|
setImage(value);
|
||||||
|
}}
|
||||||
|
onSubmitText={"Save"}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="input"
|
||||||
|
id="urlInput"
|
||||||
|
placeholder="Image URL..."
|
||||||
|
onChange={(ev) => {
|
||||||
|
setValue(ev.currentTarget.value);
|
||||||
|
}}
|
||||||
|
></input>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
@ -1,5 +1,4 @@
|
|||||||
export enum QueryKeys {
|
export enum QueryKeys {
|
||||||
USER_DATA = "userData",
|
|
||||||
USER_GUILDS = "userGuilds",
|
USER_GUILDS = "userGuilds",
|
||||||
GUILD_REMINDERS = "guildReminders",
|
GUILD_REMINDERS = "guildReminders",
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user