✨ Realms utilities
This commit is contained in:
		| @@ -1,7 +1,10 @@ | ||||
| import { createSignal, For, Show } from "solid-js"; | ||||
| import { closeModel, openModel } from "../../scripts/modals.ts"; | ||||
| import { getAtk } from "../../stores/userinfo.tsx"; | ||||
|  | ||||
| export default function RealmDirectoryPage() { | ||||
|   const [error, setError] = createSignal<string | null>(null); | ||||
|   const [submitting, setSubmitting] = createSignal(false); | ||||
|  | ||||
|   const [realms, setRealms] = createSignal<any>(null); | ||||
|  | ||||
| @@ -16,6 +19,32 @@ export default function RealmDirectoryPage() { | ||||
|  | ||||
|   readRealms(); | ||||
|  | ||||
|   async function createRealm(evt: SubmitEvent) { | ||||
|     evt.preventDefault(); | ||||
|  | ||||
|     const form = evt.target as HTMLFormElement; | ||||
|     const data = Object.fromEntries(new FormData(form)); | ||||
|  | ||||
|     setSubmitting(true); | ||||
|     const res = await fetch("/api/realms", { | ||||
|       method: "POST", | ||||
|       headers: { "Authorization": `Bearer ${getAtk()}`, "Content-Type": "application/json" }, | ||||
|       body: JSON.stringify({ | ||||
|         name: data.name, | ||||
|         description: data.description, | ||||
|         is_public: data.is_public != null | ||||
|       }) | ||||
|     }); | ||||
|     if (res.status !== 200) { | ||||
|       setError(await res.text()); | ||||
|     } else { | ||||
|       await readRealms(); | ||||
|       closeModel("#create-realm"); | ||||
|       form.reset(); | ||||
|     } | ||||
|     setSubmitting(false); | ||||
|   } | ||||
|  | ||||
|   return ( | ||||
|     <> | ||||
|       <div id="alerts"> | ||||
| @@ -31,6 +60,13 @@ export default function RealmDirectoryPage() { | ||||
|         </Show> | ||||
|       </div> | ||||
|  | ||||
|       <div class="mt-1 px-7 flex items-center justify-between"> | ||||
|         <h3 class="py-3 font-bold">Realms directory</h3> | ||||
|         <button type="button" class="btn btn-primary" onClick={() => openModel("#create-realm")}> | ||||
|           <i class="fa-solid fa-plus"></i> | ||||
|         </button> | ||||
|       </div> | ||||
|  | ||||
|       <For each={realms()}> | ||||
|         {item => <div class="px-7 pt-7 pb-5 border-t border-base-200"> | ||||
|           <h2 class="text-xl font-bold">{item.name}</h2> | ||||
| @@ -41,6 +77,38 @@ export default function RealmDirectoryPage() { | ||||
|           </div> | ||||
|         </div>} | ||||
|       </For> | ||||
|  | ||||
|       <dialog id="create-realm" class="modal"> | ||||
|         <div class="modal-box"> | ||||
|           <h2 class="card-title px-1">Create a realm</h2> | ||||
|           <form class="mt-2" onSubmit={createRealm}> | ||||
|             <label class="form-control w-full"> | ||||
|               <div class="label"> | ||||
|                 <span class="label-text">Realm name</span> | ||||
|               </div> | ||||
|               <input name="name" type="text" placeholder="Type here" class="input input-bordered w-full" /> | ||||
|             </label> | ||||
|             <label class="form-control w-full"> | ||||
|               <div class="label"> | ||||
|                 <span class="label-text">Realm description</span> | ||||
|               </div> | ||||
|               <textarea name="description" placeholder="Type here" class="textarea textarea-bordered w-full" /> | ||||
|             </label> | ||||
|             <div class="form-control mt-2"> | ||||
|               <label class="label cursor-pointer"> | ||||
|                 <span class="label-text">Make it public</span> | ||||
|                 <input type="checkbox" name="is_public" class="checkbox checkbox-primary" /> | ||||
|               </label> | ||||
|             </div> | ||||
|  | ||||
|             <button type="submit" class="btn btn-primary mt-2" disabled={submitting()}> | ||||
|               <Show when={submitting()} fallback={"Submit"}> | ||||
|                 <span class="loading"></span> | ||||
|               </Show> | ||||
|             </button> | ||||
|           </form> | ||||
|         </div> | ||||
|       </dialog> | ||||
|     </> | ||||
|   ); | ||||
| } | ||||
| @@ -1,20 +1,26 @@ | ||||
| import { createSignal, Show } from "solid-js"; | ||||
| import { createStore } from "solid-js/store"; | ||||
| import { useParams } from "@solidjs/router"; | ||||
| import { useNavigate, useParams } from "@solidjs/router"; | ||||
|  | ||||
| import PostList from "../../components/PostList.tsx"; | ||||
| import PostPublish from "../../components/PostPublish.tsx"; | ||||
|  | ||||
| import styles from "./realm.module.css"; | ||||
| import { getAtk, useUserinfo } from "../../stores/userinfo.tsx"; | ||||
| import { closeModel, openModel } from "../../scripts/modals.ts"; | ||||
|  | ||||
| export default function RealmPage() { | ||||
|   const userinfo = useUserinfo(); | ||||
|  | ||||
|   const [error, setError] = createSignal<string | null>(null); | ||||
|   const [submitting, setSubmitting] = createSignal(false); | ||||
|  | ||||
|   const [realm, setRealm] = createSignal<any>(null); | ||||
|   const [page, setPage] = createSignal(0); | ||||
|   const [info, setInfo] = createSignal<any>(null); | ||||
|  | ||||
|   const params = useParams(); | ||||
|   const navigate = useNavigate(); | ||||
|  | ||||
|   async function readRealm() { | ||||
|     const res = await fetch(`/api/realms/${params["realmId"]}`); | ||||
| @@ -32,7 +38,7 @@ export default function RealmPage() { | ||||
|     const res = await fetch(`/api/posts?` + new URLSearchParams({ | ||||
|       take: (10).toString(), | ||||
|       offset: ((page() - 1) * 10).toString(), | ||||
|       realmId: params["realmId"], | ||||
|       realmId: params["realmId"] | ||||
|     })); | ||||
|     if (res.status !== 200) { | ||||
|       setError(await res.text()); | ||||
| @@ -42,6 +48,90 @@ export default function RealmPage() { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   async function editRealm(evt: SubmitEvent) { | ||||
|     evt.preventDefault(); | ||||
|  | ||||
|     const form = evt.target as HTMLFormElement; | ||||
|     const data = Object.fromEntries(new FormData(form)); | ||||
|  | ||||
|     setSubmitting(true); | ||||
|     const res = await fetch(`/api/realms/${params["realmId"]}`, { | ||||
|       method: "PUT", | ||||
|       headers: { "Authorization": `Bearer ${getAtk()}`, "Content-Type": "application/json" }, | ||||
|       body: JSON.stringify({ | ||||
|         name: data.name, | ||||
|         description: data.description, | ||||
|         is_public: data.is_public != null | ||||
|       }) | ||||
|     }); | ||||
|     if (res.status !== 200) { | ||||
|       setError(await res.text()); | ||||
|     } else { | ||||
|       await readRealm(); | ||||
|       closeModel("#edit-realm"); | ||||
|       form.reset(); | ||||
|     } | ||||
|     setSubmitting(false); | ||||
|   } | ||||
|  | ||||
|   async function inviteMember(evt: SubmitEvent) { | ||||
|     evt.preventDefault(); | ||||
|  | ||||
|     const form = evt.target as HTMLFormElement; | ||||
|     const data = Object.fromEntries(new FormData(form)); | ||||
|  | ||||
|     setSubmitting(true); | ||||
|     const res = await fetch(`/api/realms/${params["realmId"]}/invite`, { | ||||
|       method: "POST", | ||||
|       headers: { "Authorization": `Bearer ${getAtk()}`, "Content-Type": "application/json" }, | ||||
|       body: JSON.stringify(data) | ||||
|     }); | ||||
|     if (res.status !== 200) { | ||||
|       setError(await res.text()); | ||||
|     } else { | ||||
|       await readRealm(); | ||||
|       closeModel("#invite-member"); | ||||
|       form.reset(); | ||||
|     } | ||||
|     setSubmitting(false); | ||||
|   } | ||||
|  | ||||
|   async function kickMember(evt: SubmitEvent) { | ||||
|     evt.preventDefault(); | ||||
|  | ||||
|     const form = evt.target as HTMLFormElement; | ||||
|     const data = Object.fromEntries(new FormData(form)); | ||||
|  | ||||
|     setSubmitting(true); | ||||
|     const res = await fetch(`/api/realms/${params["realmId"]}/kick`, { | ||||
|       method: "POST", | ||||
|       headers: { "Authorization": `Bearer ${getAtk()}`, "Content-Type": "application/json" }, | ||||
|       body: JSON.stringify(data) | ||||
|     }); | ||||
|     if (res.status !== 200) { | ||||
|       setError(await res.text()); | ||||
|     } else { | ||||
|       await readRealm(); | ||||
|       closeModel("#kick-member"); | ||||
|       form.reset(); | ||||
|     } | ||||
|     setSubmitting(false); | ||||
|   } | ||||
|  | ||||
|   async function breakRealm() { | ||||
|     if (!confirm("Are you sure about that? All posts in this realm will disappear forever.")) return; | ||||
|  | ||||
|     const res = await fetch(`/api/realms/${params["realmId"]}`, { | ||||
|       method: "DELETE", | ||||
|       headers: { "Authorization": `Bearer ${getAtk()}` } | ||||
|     }); | ||||
|     if (res.status !== 200) { | ||||
|       setError(await res.text()); | ||||
|     } else { | ||||
|       navigate("/realms"); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   function setMeta(data: any, field: string, scroll = true) { | ||||
|     const meta: { [id: string]: any } = { | ||||
|       reposting: null, | ||||
| @@ -81,6 +171,14 @@ export default function RealmPage() { | ||||
|  | ||||
|         <div class={`${styles.description} text-sm mt-3`}> | ||||
|           <p>Realm #{realm()?.id}</p> | ||||
|           <Show when={realm()?.account_id === userinfo?.profiles?.id}> | ||||
|             <div class="flex gap-2"> | ||||
|               <button class="link" onClick={() => openModel("#edit-realm")}>Edit</button> | ||||
|               <button class="link" onClick={() => openModel("#invite-member")}>Invite</button> | ||||
|               <button class="link" onClick={() => openModel("#kick-member")}>Kick</button> | ||||
|               <button class="link" onClick={() => breakRealm()}>Break-up</button> | ||||
|             </div> | ||||
|           </Show> | ||||
|         </div> | ||||
|       </div> | ||||
|  | ||||
| @@ -102,6 +200,91 @@ export default function RealmPage() { | ||||
|         onReply={(item) => setMeta(item, "replying")} | ||||
|         onEdit={(item) => setMeta(item, "editing")} | ||||
|       /> | ||||
|  | ||||
|       <dialog id="edit-realm" class="modal"> | ||||
|         <div class="modal-box"> | ||||
|           <h2 class="card-title px-1">Create a realm</h2> | ||||
|           <form class="mt-2" onSubmit={editRealm}> | ||||
|             <label class="form-control w-full"> | ||||
|               <div class="label"> | ||||
|                 <span class="label-text">Realm name</span> | ||||
|               </div> | ||||
|               <input value={realm()?.name} name="name" type="text" placeholder="Type here" | ||||
|                      class="input input-bordered w-full" /> | ||||
|             </label> | ||||
|             <label class="form-control w-full"> | ||||
|               <div class="label"> | ||||
|                 <span class="label-text">Realm description</span> | ||||
|               </div> | ||||
|               <textarea value={realm()?.description} name="description" placeholder="Type here" | ||||
|                         class="textarea textarea-bordered w-full" /> | ||||
|             </label> | ||||
|             <div class="form-control mt-2"> | ||||
|               <label class="label cursor-pointer"> | ||||
|                 <span class="label-text">Make it public</span> | ||||
|                 <input checked={realm()?.is_public} type="checkbox" name="is_public" | ||||
|                        class="checkbox checkbox-primary" /> | ||||
|               </label> | ||||
|             </div> | ||||
|  | ||||
|             <button type="submit" class="btn btn-primary mt-2" disabled={submitting()}> | ||||
|               <Show when={submitting()} fallback={"Submit"}> | ||||
|                 <span class="loading"></span> | ||||
|               </Show> | ||||
|             </button> | ||||
|           </form> | ||||
|         </div> | ||||
|       </dialog> | ||||
|  | ||||
|       <dialog id="invite-member" class="modal"> | ||||
|         <div class="modal-box"> | ||||
|           <h2 class="card-title px-1">Invite someone as a member</h2> | ||||
|           <form class="mt-2" onSubmit={inviteMember}> | ||||
|             <label class="form-control w-full"> | ||||
|               <div class="label"> | ||||
|                 <span class="label-text">Username</span> | ||||
|               </div> | ||||
|               <input name="account_name" type="text" placeholder="Type here" class="input input-bordered w-full" /> | ||||
|               <div class="label"> | ||||
|                 <span class="label-text-alt"> | ||||
|                   Invite someone via their username so that they can publish content in non-public realm. | ||||
|                 </span> | ||||
|               </div> | ||||
|             </label> | ||||
|  | ||||
|             <button type="submit" class="btn btn-primary mt-2" disabled={submitting()}> | ||||
|               <Show when={submitting()} fallback={"Submit"}> | ||||
|                 <span class="loading"></span> | ||||
|               </Show> | ||||
|             </button> | ||||
|           </form> | ||||
|         </div> | ||||
|       </dialog> | ||||
|  | ||||
|       <dialog id="kick-member" class="modal"> | ||||
|         <div class="modal-box"> | ||||
|           <h2 class="card-title px-1">Kick someone out of your realm</h2> | ||||
|           <form class="mt-2" onSubmit={kickMember}> | ||||
|             <label class="form-control w-full"> | ||||
|               <div class="label"> | ||||
|                 <span class="label-text">Username</span> | ||||
|               </div> | ||||
|               <input name="account_name" type="text" placeholder="Type here" class="input input-bordered w-full" /> | ||||
|               <div class="label"> | ||||
|                 <span class="label-text-alt"> | ||||
|                   Remove someone out of your realm. | ||||
|                 </span> | ||||
|               </div> | ||||
|             </label> | ||||
|  | ||||
|             <button type="submit" class="btn btn-primary mt-2" disabled={submitting()}> | ||||
|               <Show when={submitting()} fallback={"Submit"}> | ||||
|                 <span class="loading"></span> | ||||
|               </Show> | ||||
|             </button> | ||||
|           </form> | ||||
|         </div> | ||||
|       </dialog> | ||||
|     </> | ||||
|   ); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user