From dd500a3ebb0cc6414605a1dd7ebe3543483b94e7 Mon Sep 17 00:00:00 2001 From: IrohDW Date: Wed, 2 Oct 2024 09:45:23 -0600 Subject: [PATCH] Publish Forum button changed to Manage Forums. It handles both publishing and editing forums. --- src/App.tsx | 28 +- src/components/common/SelectField.tsx | 24 +- src/pages/Forum/ActionBar.tsx | 28 -- src/pages/Forum/Components/ActionBar.tsx | 49 +++ src/pages/Forum/Components/ModalButton.tsx | 121 +++++++ .../Forum/{ => Components}/QmailTextField.tsx | 18 +- src/pages/Forum/Forum.tsx | 16 +- src/pages/Forum/ForumModal-Data.ts | 137 ++++---- src/pages/Forum/ForumModal.tsx | 329 +++++++++--------- src/pages/Forum/ForumThreads.tsx | 28 +- src/pages/Forum/GroupPermissionsForm.tsx | 58 +-- src/pages/Home/Home-styles.ts | 2 +- src/pages/Home/Home.tsx | 3 +- src/utils/QortalRequests.ts | 6 +- 14 files changed, 512 insertions(+), 335 deletions(-) delete mode 100644 src/pages/Forum/ActionBar.tsx create mode 100644 src/pages/Forum/Components/ActionBar.tsx create mode 100644 src/pages/Forum/Components/ModalButton.tsx rename src/pages/Forum/{ => Components}/QmailTextField.tsx (70%) diff --git a/src/App.tsx b/src/App.tsx index 03d37cd..d7ff3b0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,31 +1,20 @@ // @ts-nocheck -import { signal } from "@preact/signals-react"; -import { useEffect } from "react"; -import { Routes, Route } from "react-router-dom"; +import { CssBaseline } from "@mui/material"; import { ThemeProvider } from "@mui/material/styles"; -import { CssBaseline } from "@mui/material"; -import { ForumData } from "./pages/Forum/ForumModal"; -import { Home } from "./pages/Home/Home"; -import { lightTheme, darkTheme } from "./styles/theme"; -import { store } from "./state/store"; import { Provider } from "react-redux"; -import { fetchForumData } from "./utils/QortalRequests"; -import GlobalWrapper from "./wrappers/GlobalWrapper"; -import DownloadWrapper from "./wrappers/DownloadWrapper"; +import { Route, Routes } from "react-router-dom"; import Notification from "./components/common/Notification/Notification"; - -export const forums = signal([]); +import { Home } from "./pages/Home/Home"; +import { store } from "./state/store"; +import { darkTheme } from "./styles/theme"; +import DownloadWrapper from "./wrappers/DownloadWrapper"; +import GlobalWrapper from "./wrappers/GlobalWrapper"; function App() { const themeColor = window._qdnTheme; - useEffect(() => { - fetchForumData().then(data => { - if (data) forums.value = data; - console.log("forums is : ", forums.value); - }); - }, []); + return ( @@ -35,6 +24,7 @@ function App() { } /> + } /> } /> diff --git a/src/components/common/SelectField.tsx b/src/components/common/SelectField.tsx index 5c4c504..9236c65 100644 --- a/src/components/common/SelectField.tsx +++ b/src/components/common/SelectField.tsx @@ -4,28 +4,38 @@ import { MenuItem, OutlinedInput, Select, + SelectChangeEvent, } from "@mui/material"; import { SxProps } from "@mui/system"; -import { signal, Signal } from "@preact/signals-react"; +import { signal, Signal, useSignal } from "@preact/signals-react"; import { useSignals } from "@preact/signals-react/runtime"; -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; interface SelectFieldProps { options: string[]; - value: Signal; + initialValue?: string; label: string; sx?: SxProps; + afterChange?: (e: string) => void; + width?: string; } export const SelectField = ({ options, - value, + initialValue = "", label, sx = {}, + width = "100%", + afterChange, }: SelectFieldProps) => { useSignals(); + const value = useSignal(initialValue); + useEffect(() => { + value.value = initialValue; + }, [initialValue]); + return ( - + { - value.value = e.target.value; + const eventValue = e.target.value; + value.value = eventValue; + if (afterChange) afterChange(eventValue); }} sx={{ color: "black", ...sx }} > diff --git a/src/pages/Forum/ActionBar.tsx b/src/pages/Forum/ActionBar.tsx deleted file mode 100644 index f024f3d..0000000 --- a/src/pages/Forum/ActionBar.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import MenuBookIcon from "@mui/icons-material/MenuBook"; -import React from "react"; -import { useNavigate } from "react-router-dom"; -import { forums } from "../../App"; -import { - ComposeContainer, - ComposeP, - InstanceContainer, -} from "../Home/Home-styles"; -import { ForumModal } from "./ForumModal"; - -export const ActionBar = () => { - const navigate = useNavigate(); - - return ( - - - - navigate("/sponsorshipData")} - > - - {"Sponsorship Data"} - - - ); -}; diff --git a/src/pages/Forum/Components/ActionBar.tsx b/src/pages/Forum/Components/ActionBar.tsx new file mode 100644 index 0000000..fb00bbc --- /dev/null +++ b/src/pages/Forum/Components/ActionBar.tsx @@ -0,0 +1,49 @@ +import MenuBookIcon from "@mui/icons-material/MenuBook"; +import { Signal, signal } from "@preact/signals-react"; +import { useSignals } from "@preact/signals-react/runtime"; +import React, { useEffect } from "react"; +import { useNavigate } from "react-router-dom"; +import { fetchForumData } from "../../../utils/QortalRequests"; +import { + ComposeContainer, + ComposeP, + InstanceContainer, +} from "../../Home/Home-styles"; +import { ForumData, ForumModal } from "../ForumModal"; + +export const forums = signal([]); +export const resetForumIndexes = (forums: Signal) => { + forums.value = forums.value.map((forum, index) => { + forum.listIndex = index; + return forum; + }); +}; + +export const ActionBar = () => { + useSignals(); + + useEffect(() => { + fetchForumData().then(data => { + if (data) + forums.value = data.map((forum, index) => { + forum.listIndex = index; + return forum; + }); + // console.log("forums are : ", forums.value); + }); + }, []); + + const navigate = useNavigate(); + return ( + + + navigate("/sponsorshipData")} + > + + {"Sponsorship Data"} + + + ); +}; diff --git a/src/pages/Forum/Components/ModalButton.tsx b/src/pages/Forum/Components/ModalButton.tsx new file mode 100644 index 0000000..21af72f --- /dev/null +++ b/src/pages/Forum/Components/ModalButton.tsx @@ -0,0 +1,121 @@ +import { Box } from "@mui/material"; +import { useSignal } from "@preact/signals-react"; +import React, { PropsWithChildren } from "react"; +import ComposeIconSVG from "../../../assets/svgs/ComposeIcon.svg"; +import { CreateThreadIcon } from "../../../assets/svgs/CreateThreadIcon"; +import ModalCloseSVG from "../../../assets/svgs/ModalClose.svg"; +import { ReusableModal } from "../../../components/modals/ReusableModal"; +import { + CloseContainer, + ComposeContainer, + ComposeIcon, + ComposeP, + InstanceFooter, + InstanceListContainer, + InstanceListHeader, + NewMessageCloseImg, + NewMessageHeaderP, + NewMessageSendButton, + NewMessageSendP, +} from "../../Home/Home-styles"; +import { publishForum } from "../ForumModal-Data"; + +export interface ModalButtonProps { + onSubmit: () => Promise; + onClose?: () => void; + isRenderModal: boolean; + modalLabel: string; + buttonLabel: string; +} +export const ModalButton = ({ + onClose, + onSubmit, + isRenderModal, + modalLabel, + buttonLabel, + children, +}: PropsWithChildren) => { + const isOpen = useSignal(false); + const closeModal = () => { + isOpen.value = false; + if (onClose) onClose(); + }; + + return ( + + {isRenderModal && ( + (isOpen.value = true)}> + + {modalLabel} + + )} + + + {modalLabel} + + + + + + {children} + + + { + onSubmit().then(success => { + if (success) closeModal(); + }); + }} + > + {buttonLabel} + + + + + + + ); +}; diff --git a/src/pages/Forum/QmailTextField.tsx b/src/pages/Forum/Components/QmailTextField.tsx similarity index 70% rename from src/pages/Forum/QmailTextField.tsx rename to src/pages/Forum/Components/QmailTextField.tsx index 8c35245..77b71a4 100644 --- a/src/pages/Forum/QmailTextField.tsx +++ b/src/pages/Forum/Components/QmailTextField.tsx @@ -1,27 +1,33 @@ import { Input } from "@mui/material"; import { SxProps } from "@mui/system"; -import { Signal, useSignalEffect } from "@preact/signals-react"; +import { Signal, useSignal, useSignalEffect } from "@preact/signals-react"; import { useSignals } from "@preact/signals-react/runtime"; -import React from "react"; +import React, { useEffect } from "react"; interface QmailTextFieldProps { - value: Signal; label: string; sx?: SxProps; filter?: RegExp; maxLength?: number; + initialValue?: string; + afterChange?: (s: string) => void; } export const QmailTextField = ({ - value, label, sx = {}, filter, maxLength = 60, + initialValue = "", + afterChange, }: QmailTextFieldProps) => { useSignals(); + const value = useSignal(initialValue); useSignalEffect(() => { if (filter) value.value = value.value.replace(filter, ""); }); + useEffect(() => { + value.value = initialValue; + }, [initialValue]); return ( <> @@ -29,7 +35,9 @@ export const QmailTextField = ({ id="standard-adornment-name" value={value.value} onChange={e => { - if (e.target.value.length <= maxLength) value.value = e.target.value; + const eventValue = e.target.value; + if (eventValue.length <= maxLength) value.value = eventValue; + if (afterChange) afterChange(value.value); }} placeholder={label} disableUnderline diff --git a/src/pages/Forum/Forum.tsx b/src/pages/Forum/Forum.tsx index 1995b42..0a10bc0 100644 --- a/src/pages/Forum/Forum.tsx +++ b/src/pages/Forum/Forum.tsx @@ -21,13 +21,13 @@ export const Forum = ({ }: ForumData) => { const [currentThread, setCurrentThread] = useState(null); - const openNewThread = () => { - if (currentThread) { - executeEvent("openNewThreadMessageModal", {}); - return; - } - executeEvent("openNewThreadModal", {}); - }; + // const openNewThread = () => { + // if (currentThread) { + // executeEvent("openNewThreadMessageModal", {}); + // return; + // } + // executeEvent("openNewThreadModal", {}); + // }; const forumWidth = 95; const forumMarginLeft = (100 - forumWidth) / 2; @@ -51,8 +51,8 @@ export const Forum = ({ }} > {title} - {descriptionText.trim()} + {descriptionText.trim()} // diff --git a/src/pages/Forum/ForumModal-Data.ts b/src/pages/Forum/ForumModal-Data.ts index 518fdcb..36847de 100644 --- a/src/pages/Forum/ForumModal-Data.ts +++ b/src/pages/Forum/ForumModal-Data.ts @@ -1,30 +1,18 @@ -import { ReadonlySignal } from "@preact/signals-react"; -import ShortUniqueId from "short-unique-id"; -import { forums } from "../../App"; -import { - ATTATCHMENT_BASE, - FORUMS_ID, - THREAD_BASE, -} from "../../constants/Identifiers"; -import { - MAIL_ATTACHMENT_SERVICE_TYPE, - MAIL_SERVICE_TYPE, - THREAD_SERVICE_TYPE, -} from "../../constants/mail"; -import { appOwner } from "../../constants/Misc"; +import { FORUMS_ID } from "../../constants/Identifiers"; import { setNotification } from "../../state/features/notificationsSlice"; import { store } from "../../state/store"; import { getGroup } from "../../utils/QortalRequests"; -import { objectToBase64, toBase64 } from "../../utils/toBase64"; +import { objectToBase64 } from "../../utils/toBase64"; +import { ForumData } from "./ForumModal"; import { Group } from "./GroupPermissionsForm"; -import { descriptionMaxLength, ForumData } from "./ForumModal"; -const getGroupNames = async (groups: Group[]) => { - const groupPromises = groups.map(group => getGroup(group.id.value)); +const getGroupsData = async (groups: Group[]) => { + const groupPromises = groups.map(group => getGroup(group.id)); return await Promise.all(groupPromises); }; const verifyData = async (formData: ForumData) => { + debugger; const userName = store.getState()?.auth?.user?.name; const { title, encryption, groups, descriptionHTML, descriptionText } = formData; @@ -38,51 +26,33 @@ const verifyData = async (formData: ForumData) => { if (groups.filter(group => !!group.permissions).length < groups.length) errorMsg = "A group has empty permissions"; - const groupsWithNames = await getGroupNames(groups); + const groupsWithNames = await getGroupsData(groups); if ( groupsWithNames.filter(group => !!group?.groupName).length < groups.length ) errorMsg = "A group ID provided doesn't exist"; - if (errorMsg) { - store.dispatch( - setNotification({ - msg: errorMsg, - alertType: "error", - }) - ); - } return errorMsg; }; -export const addForum = async (formData: ForumData) => { - const errorMsg = await verifyData(formData); - if (errorMsg) return; - forums.value = [...forums.value, formData]; +const verifyAllData = async (formData: ForumData[]) => { + const errorListAll = await Promise.all( + formData.map(data => verifyData(data)) + ); + // don't loop through all errors, take the first one and use that. + const firstErrorIndex = errorListAll.findIndex(data => !!data); + if (firstErrorIndex === -1) return ""; + return `Forum ${firstErrorIndex + 1} has error: ${ + errorListAll[firstErrorIndex] + }`; }; -export const editForums = async (newForums: ForumData[]) => { - const errorMsgPromises = newForums.map(forumData => verifyData(forumData)); - const errorMsgs = await Promise.all(errorMsgPromises); - const errorMsgNum = errorMsgs.filter(msg => !!msg).length; - - if (errorMsgNum > 0) return; - - forums.value = newForums; -}; - -export const publishForum = async (formData: ForumData) => { - let success = false; - const errorMsg = await verifyData(formData); - if (errorMsg) return success; +export const publishForum = async (formData: ForumData[]): Promise => { try { - await addForum(formData); - - const publishDescription = - formData.title + - "_" + - formData.descriptionText.substring(0, descriptionMaxLength); + console.log("formData is: ", formData); + const errorMsg = await verifyAllData(formData); + if (errorMsg) throw new Error(errorMsg); const userName = store.getState()?.auth?.user?.name; await qortalRequest({ @@ -90,40 +60,51 @@ export const publishForum = async (formData: ForumData) => { name: userName, service: "METADATA", identifier: FORUMS_ID, - description: publishDescription, - data64: await objectToBase64(forums), + data64: await objectToBase64(formData), }); - success = true; store.dispatch( setNotification({ msg: "Forum published", alertType: "success", }) ); + return true; } catch (error: any) { - let notificationObj = null; - const defaultErrorMessage = "Failed to submit forum data"; - - if (typeof error === "string") { - notificationObj = { - msg: error || defaultErrorMessage, - alertType: "error", - }; - } else if (typeof error?.error === "string") { - notificationObj = { - msg: error?.error || defaultErrorMessage, - alertType: "error", - }; - } else { - notificationObj = { - msg: error?.message || defaultErrorMessage, - alertType: "error", - }; - } - if (!notificationObj) return; - store.dispatch(setNotification(notificationObj)); - - throw new Error(defaultErrorMessage); + console.log("error is: ", error); + formErrorHandler(error); + // throw new Error(defaultErrorMessage); + return false; } - return success; +}; + +const formErrorHandler = (error: any) => { + let notificationObj = null; + const defaultErrorMessage = "Failed to submit forum data"; + + if (typeof error === "string") { + notificationObj = { + msg: error || defaultErrorMessage, + alertType: "error", + }; + } else if (typeof error?.error === "string") { + notificationObj = { + msg: error?.error || defaultErrorMessage, + alertType: "error", + }; + } else { + notificationObj = { + msg: error?.message || defaultErrorMessage, + alertType: "error", + }; + } + if (notificationObj) store.dispatch(setNotification(notificationObj)); +}; + +export const forumToString = (forum: ForumData) => + `${forum?.listIndex !== undefined ? forum.listIndex + 1 : "?"} - ${ + forum?.title + }`; + +export const deepCopyArray = (array: object[]) => { + return JSON.parse(JSON.stringify(array)); }; diff --git a/src/pages/Forum/ForumModal.tsx b/src/pages/Forum/ForumModal.tsx index d330551..20f5752 100644 --- a/src/pages/Forum/ForumModal.tsx +++ b/src/pages/Forum/ForumModal.tsx @@ -1,45 +1,25 @@ -import MenuBookIcon from "@mui/icons-material/MenuBook"; -import { Box } from "@mui/material"; +import { Box, Button } from "@mui/material"; import { - ReadonlySignal, Signal, - signal, useComputed, useSignal, + useSignalEffect, } from "@preact/signals-react"; import { useSignals } from "@preact/signals-react/runtime"; -import React from "react"; +import React, { useEffect } from "react"; import { useSelector } from "react-redux"; -import { useNavigate } from "react-router-dom"; -import ComposeIconSVG from "../../assets/svgs/ComposeIcon.svg"; - -import { CreateThreadIcon } from "../../assets/svgs/CreateThreadIcon"; -import ModalCloseSVG from "../../assets/svgs/ModalClose.svg"; import { SelectField } from "../../components/common/SelectField"; import { Spacer } from "../../components/common/Spacer"; import { TextEditor } from "../../components/common/TextEditor/TextEditor"; -import { ReusableModal } from "../../components/modals/ReusableModal"; import { useTestIdentifiers } from "../../constants/Identifiers"; import { appOwner } from "../../constants/Misc"; import { RootState } from "../../state/store"; -import { - CloseContainer, - ComposeContainer, - ComposeIcon, - ComposeP, - InstanceContainer, - InstanceFooter, - InstanceListContainer, - InstanceListHeader, - NewMessageCloseImg, - NewMessageHeaderP, - NewMessageInputRow, - NewMessageSendButton, - NewMessageSendP, -} from "../Home/Home-styles"; +import { NewMessageInputRow } from "../Home/Home-styles"; +import { resetForumIndexes } from "./Components/ActionBar"; +import { ModalButton } from "./Components/ModalButton"; +import { QmailTextField } from "./Components/QmailTextField"; +import { deepCopyArray, forumToString, publishForum } from "./ForumModal-Data"; import { Group, GroupPermissionsForm } from "./GroupPermissionsForm"; -import { publishForum } from "./ForumModal-Data"; -import { QmailTextField } from "./QmailTextField"; export type EncryptionType = "None" | "Group" | "GroupAdmin" | ""; export interface ForumData { @@ -48,6 +28,7 @@ export interface ForumData { groups: Group[]; descriptionHTML: string; descriptionText: string; + listIndex: number; } export type GroupPermissionType = "Read" | "Write"; @@ -60,159 +41,181 @@ export const titleMaxLength = 60; export const descriptionMaxLength = 160; interface NewForumModalProps { - forumData?: ForumData[]; + forumData: Signal; } export const ForumModal = ({ forumData }: NewForumModalProps) => { useSignals(); - const isOpen = useSignal(false); - const forumTitle = useSignal(""); - const descriptionHTML = useSignal(""); - const descriptionText = useSignal(""); - const groups = useSignal([ - { - id: signal(""), - permissions: signal("Read"), - }, - ]); + const tempData = useSignal([]); - const selectedEncryptionType = useSignal("None"); - - const { user } = useSelector((state: RootState) => state.auth); - - const formData: ReadonlySignal = useComputed(() => { - return { - title: forumTitle.value, - encryption: selectedEncryptionType.value, - groups: groups.value, - descriptionHTML: descriptionHTML.value, - descriptionText: descriptionText.value, - }; - }); - - const closeModal = () => { - isOpen.value = false; + const emptyForum: ForumData = { + title: "", + encryption: "None", + groups: [], + descriptionHTML: "", + descriptionText: "", + listIndex: 0, + }; + + const { user } = useSelector((state: RootState) => state.auth); + const isRenderModal = user?.name === appOwner || useTestIdentifiers; + + const selectedForumIndex = useSignal(0); + const selectedForum = useComputed(() => { + return tempData.value[selectedForumIndex.value]; + }); + + const initializeTempData = () => { + tempData.value = + forumData.value.length === 0 + ? [emptyForum] + : deepCopyArray(forumData.value); + selectedForumIndex.value = 0; + }; + + useEffect(() => { + initializeTempData(); + }, [forumData.value]); + + const addForum = () => { + const newForum = { ...emptyForum }; + newForum.listIndex = tempData.value.length; + tempData.value = [...tempData.value, newForum]; + selectedForumIndex.value = newForum.listIndex; + }; + + const removeForum = () => { + if (tempData.value.length <= 1) { + tempData.value = [{ ...emptyForum }]; + selectedForumIndex.value = 0; + } else { + tempData.value = tempData.value.filter( + (group, index) => index !== selectedForumIndex.value + ); + + if (selectedForumIndex.value > 0) selectedForumIndex.value -= 1; + else selectedForumIndex.value = 0; + } + resetForumIndexes(tempData); + }; + + const updateForums = () => { + tempData.value = [...tempData.value]; }; - const forumText = !!forumData ? "Edit Forums" : "Add Forum"; - const publishText = !!forumData ? "Edit Forums" : "Create Forum"; return ( - initializeTempData()} + onSubmit={async () => { + updateForums(); + const pub = await publishForum(tempData.value); + + if (pub) forumData.value = tempData.value; + return pub; }} + modalLabel={"Manage Forums"} + buttonLabel={"Publish Forums"} > - {(user?.name === appOwner || useTestIdentifiers) && ( - (isOpen.value = true)}> - - {forumText} - - )} - - forumToString(forum))} + label={"Forum #"} + initialValue={forumToString(selectedForum.value)} + afterChange={s => { + //tempData.value[selectedForumIndex.value] = selectedForum.value; + tempData.value = [...tempData.value]; + selectedForumIndex.value = +s.split(" ")[0] - 1; }} - > - {forumText} - - - - - + + + + { + tempData.value[selectedForumIndex.value].title = s; + updateForums(); + }} + label={"Forum Title"} sx={{ - backgroundColor: "rgba(217, 217, 217, 1)", - padding: "20px 42px", - alignItems: "center", - height: "90px", + height: "60px", + borderBottom: "1px solid gray", }} - > - { - publishForum(formData.value).then(success => { - if (success) closeModal(); - }); - }} - > - {publishText} - - - - - - + maxLength={titleMaxLength} + /> + + (selectedForum.value.encryption = s as EncryptionType) + } + sx={{ + "& .MuiSvgIcon-root": { + color: "gray", + height: "60px", + }, + }} + /> + + { + tempData.value[selectedForumIndex.value].groups = g; + //updateForums(); + }} + /> + + +

Description

+ { + selectedForum.value.descriptionHTML = value; + selectedForum.value.descriptionText = editor.getText(value); + }} + /> +
+ ); }; diff --git a/src/pages/Forum/ForumThreads.tsx b/src/pages/Forum/ForumThreads.tsx index 426686f..14510e3 100644 --- a/src/pages/Forum/ForumThreads.tsx +++ b/src/pages/Forum/ForumThreads.tsx @@ -1,3 +1,27 @@ -export const ForumThreads = () => { - return <>; +import { useSignal } from "@preact/signals-react"; +import { useSignals } from "@preact/signals-react/runtime"; +import { useState } from "react"; +import { GroupData } from "../../utils/QortalRequests"; +import { GroupMail } from "../Mail/GroupMail"; +import { Thread } from "../Mail/Thread"; + +export interface ForumThreadsProps { + id: number; +} +export const ForumThreads = ({ id }: ForumThreadsProps) => { + useSignals(); + const [currentThread, setCurrentThread] = useState(null); + const [filterMode, setFilterMode] = useState("Recently active"); + + const groupInfo = useSignal(undefined); + + return ( + + ); }; diff --git a/src/pages/Forum/GroupPermissionsForm.tsx b/src/pages/Forum/GroupPermissionsForm.tsx index fd948cd..cf3ccf1 100644 --- a/src/pages/Forum/GroupPermissionsForm.tsx +++ b/src/pages/Forum/GroupPermissionsForm.tsx @@ -1,41 +1,46 @@ import AddIcon from "@mui/icons-material/Add"; import RemoveIcon from "@mui/icons-material/Remove"; -import { - Box, - Button, - IconButton, - MenuItem, - OutlinedInput, - Select, - SelectChangeEvent, -} from "@mui/material"; +import { Box, IconButton } from "@mui/material"; import { styled } from "@mui/material/styles"; -import { signal, Signal } from "@preact/signals-react"; +import { Signal, useSignal } from "@preact/signals-react"; import { useSignals } from "@preact/signals-react/runtime"; import React, { useEffect } from "react"; import ShortUniqueId from "short-unique-id"; import { SelectField } from "../../components/common/SelectField"; import { NewMessageInputRow } from "../Home/Home-styles"; +import { QmailTextField } from "./Components/QmailTextField"; import { GroupPermissionType } from "./ForumModal"; -import { QmailTextField } from "./QmailTextField"; export interface Group { - id: Signal; - permissions: Signal; + id: string; + permissions: GroupPermissionType; } export interface GroupPermissionsFormProps { - groups: Signal; + initialGroups?: Group[]; + afterChange?: (g: Group[]) => void; } -export const GroupPermissionsForm = ({ groups }: GroupPermissionsFormProps) => { +export const GroupPermissionsForm = ({ + initialGroups, + afterChange, +}: GroupPermissionsFormProps) => { useSignals(); - const uid = new ShortUniqueId(); const newGroup = { - id: signal(""), - permissions: signal("Read"), + id: "", + permissions: "Read", } as Group; + const groups = useSignal(initialGroups || [newGroup]); + + useEffect(() => { + if (initialGroups) + groups.value = initialGroups?.length > 0 ? initialGroups : [newGroup]; + }, [initialGroups]); + + const uid = new ShortUniqueId(); + const addGroup = () => { groups.value = [...groups.value, newGroup]; + if (afterChange) afterChange(groups.value); }; const removeGroup = (groupIndex: number) => { @@ -44,8 +49,12 @@ export const GroupPermissionsForm = ({ groups }: GroupPermissionsFormProps) => { (group, index) => index !== groupIndex ); else groups.value = [newGroup]; + if (afterChange) afterChange(groups.value); }; + const updateGroups = () => { + if (afterChange) afterChange(groups.value); + }; const buttonStyle = { width: "70px", height: "70px", @@ -99,7 +108,11 @@ export const GroupPermissionsForm = ({ groups }: GroupPermissionsFormProps) => { { + group.id = s; + updateGroups(); + }} + initialValue={group.id} label={"Group ID"} filter={/[^0-9]/} sx={{ @@ -110,10 +123,13 @@ export const GroupPermissionsForm = ({ groups }: GroupPermissionsFormProps) => { maxLength={10} /> - { + group.permissions = s as GroupPermissionType; + updateGroups(); + }} label={"Group Permissions"} sx={{ "& .MuiSvgIcon-root": { diff --git a/src/pages/Home/Home-styles.ts b/src/pages/Home/Home-styles.ts index 12cc9c1..6b638a3 100644 --- a/src/pages/Home/Home-styles.ts +++ b/src/pages/Home/Home-styles.ts @@ -84,7 +84,7 @@ export const MailBodyInnerScroll = styled(Box)` export const ComposeContainer = styled(Box)(({ theme }) => ({ display: "flex", - width: "150px", + width: "100%", alignItems: "center", gap: "7px", height: "100%", diff --git a/src/pages/Home/Home.tsx b/src/pages/Home/Home.tsx index c2787c6..d25d33b 100644 --- a/src/pages/Home/Home.tsx +++ b/src/pages/Home/Home.tsx @@ -1,8 +1,7 @@ import { Box } from "@mui/material"; import { useSignals } from "@preact/signals-react/runtime"; import React from "react"; -import { forums } from "../../App"; -import { ActionBar } from "../Forum/ActionBar"; +import { ActionBar, forums } from "../Forum/Components/ActionBar"; import { Forum } from "../Forum/Forum"; export const Home = () => { diff --git a/src/utils/QortalRequests.ts b/src/utils/QortalRequests.ts index b56d995..f46bda1 100644 --- a/src/utils/QortalRequests.ts +++ b/src/utils/QortalRequests.ts @@ -1,5 +1,6 @@ import { FORUMS_ID } from "../constants/Identifiers"; import { appOwner } from "../constants/Misc"; +import { ForumData } from "../pages/Forum/ForumModal"; export interface GroupData { groupId: number; @@ -19,6 +20,7 @@ export const listGroups = async () => { }; export const getGroup = async (groupID: number | string) => { + if (!groupID) return undefined; const url = `/groups/${groupID.toString()}`; try { @@ -36,12 +38,12 @@ export const getGroup = async (groupID: number | string) => { export const fetchForumData = async () => { try { - return await qortalRequest({ + return (await qortalRequest({ action: "FETCH_QDN_RESOURCE", name: appOwner, service: "METADATA", identifier: FORUMS_ID, - }); + })) as ForumData[]; } catch (error) { console.log(error); return undefined;