refactor: add typescript support to project

This commit is contained in:
HD
2022-06-21 15:08:35 +08:00
parent 88ec2b742a
commit bd799ebea8
259 changed files with 1042 additions and 458 deletions
@@ -10,10 +10,8 @@ import InviteModal from "../../../common/component/InviteModal";
import Tooltip from "../../../common/component/Tooltip";
import IconSetting from "../../../assets/icons/setting.svg";
import IconInvite from "../../../assets/icons/invite.from.channel.svg";
// import { useDebounce} from "rooks";
import { useReadMessageMutation } from "../../../app/services/message";
import { useUpdateMuteSettingMutation } from "../../../app/services/contact";
import StyledLink from "./styled";
import ChannelIcon from "../../../common/component/ChannelIcon";
import { getUnreadCount } from "../utils";
@@ -1,12 +1,11 @@
import { useState } from "react";
import { useSelector } from "react-redux";
import DeleteConfirmModal from "../../settingChannel/DeleteConfirmModal";
import NavItem from "./NavItem";
import { useAppSelector } from "../../../app/store";
export default function ChannelList({ setDropFiles }) {
const [currId, setCurrId] = useState(null);
const { channelIds } = useSelector((store) => {
const { channelIds } = useAppSelector((store) => {
return { channelIds: store.channels.ids };
});
@@ -82,4 +82,5 @@ const Styled = styled(NavLink)`
}
}
`;
export default Styled;
@@ -3,7 +3,6 @@ import { useSelector } from "react-redux";
import { useDebounce } from "rooks";
import Tippy from "@tippyjs/react";
import FavList from "../FavList";
import Tooltip from "../../../common/component/Tooltip";
import FavIcon from "../../../assets/icons/bookmark.svg";
// import searchIcon from "../../../assets/icons/search.svg?url";
@@ -16,6 +15,7 @@ import { StyledHeader, StyledDMChat } from "./styled";
import LoadMore from "../LoadMore";
import { renderMessageFragment } from "../utils";
import useMessageFeed from "../../../common/hook/useMessageFeed";
export default function DMChat({ uid = "", dropFiles = [] }) {
const {
list: msgIds,
@@ -1,11 +1,15 @@
// import React from "react";
import { useSelector } from "react-redux";
import { FC } from "react";
import { getUnreadCount } from "../utils";
import NavItem from "./NavItem";
export default function DMList({ uids, setDropFiles }) {
const { userMessage, messageData, readUsers, loginUid } = useSelector((store) => {
import { useAppSelector } from "../../../app/store";
interface Props {
uids: number[];
setDropFiles: () => void;
}
const DMList: FC<Props> = ({ uids, setDropFiles }) => {
const { userMessage, messageData, readUsers, loginUid } = useAppSelector((store) => {
return {
loginUid: store.authData.uid,
readUsers: store.footprint.readUsers,
@@ -31,14 +35,20 @@ export default function DMList({ uids, setDropFiles }) {
return { lastMid, unreads, uid };
});
// console.log("temp uids", sessions);
return sessions
.sort((s1, s2) => {
if (!s1.lastMid) return s2.lastMid - Infinity;
return s2.lastMid - s1.lastMid;
})
.map(({ lastMid, uid, unreads }) => {
return (
<NavItem key={uid} uid={uid} mid={lastMid} unreads={unreads} setFiles={setDropFiles} />
);
});
}
return (
<>
{sessions
.sort((s1, s2) => {
if (!s1.lastMid) return s2.lastMid - Infinity;
return s2.lastMid - s1.lastMid;
})
.map(({ lastMid, uid, unreads }) => {
return (
<NavItem key={uid} uid={uid} mid={lastMid} unreads={unreads} setFiles={setDropFiles} />
);
})}
</>
);
};
export default DMList;
@@ -6,6 +6,7 @@ import IconSurprise from "../../assets/icons/emoji.suprise.svg";
// import IconForward from "../../../assets/icons/forward.svg";
import IconRemove from "../../assets/icons/close.svg";
import useFavMessage from "../../common/hook/useFavMessage";
const Styled = styled.div`
padding: 16px;
background: #f9fafb;
@@ -83,6 +84,7 @@ const Styled = styled.div`
}
}
`;
export default function FavList({ cid = null, uid = null }) {
const { favorites, removeFavorite } = useFavMessage({ cid, uid });
const handleRemove = (evt) => {
@@ -1,7 +1,7 @@
import { useState } from "react";
import styled from "styled-components";
import { useDispatch, useSelector } from "react-redux";
import { useKey } from "rooks";
import toast from "react-hot-toast";
import useDeleteMessage from "../../../common/hook/useDeleteMessage";
import useFavMessage from "../../../common/hook/useFavMessage";
import { updateSelectMessages } from "../../../app/slices/ui";
@@ -10,8 +10,9 @@ import IconBookmark from "../../../assets/icons/bookmark.svg";
import IconDelete from "../../../assets/icons/delete.svg";
import IconClose from "../../../assets/icons/close.circle.svg";
import ForwardModal from "../../../common/component/ForwardModal";
import toast from "react-hot-toast";
import DeleteMessageConfirmModal from "../../../common/component/DeleteMessageConfirm";
import { useAppDispatch, useAppSelector } from "../../../app/store";
const Styled = styled.div`
position: relative;
padding: 16px;
@@ -40,16 +41,19 @@ const Styled = styled.div`
transform: translateY(-50%);
}
`;
export default function Operations({ context, id }) {
const [deleteModalVisible, setDeleteModalVisible] = useState(false);
const { canDelete } = useDeleteMessage();
const { addFavorite } = useFavMessage({});
const mids = useSelector((store) => store.ui.selectMessages[`${context}_${id}`]);
const mids = useAppSelector((store) => store.ui.selectMessages[`${context}_${id}`]);
const [forwardModalVisible, setForwardModalVisible] = useState(false);
const dispatch = useDispatch();
const dispatch = useAppDispatch();
const handleClose = () => {
dispatch(updateSelectMessages({ context, id, operation: "reset" }));
};
const handleFav = async () => {
const added = await addFavorite(mids);
if (added) {
@@ -60,6 +64,7 @@ export default function Operations({ context, id }) {
toast.error("Operation Failed!");
}
};
const toggleDeleteModal = (isSuccess = false) => {
setDeleteModalVisible((prev) => !prev);
if (isSuccess) {
@@ -67,14 +72,17 @@ export default function Operations({ context, id }) {
toast.success("Messages Deleted!");
}
};
const toggleForwardModal = () => {
setForwardModalVisible((prev) => !prev);
};
useKey("Escape", (evt) => {
console.log("Escape keypress", evt);
dispatch(updateSelectMessages({ context, id, operation: "reset" }));
});
const canDel = canDelete(mids);
return (
<>
<Styled>
@@ -1,7 +1,5 @@
import { useState, useRef, useEffect } from "react";
import { useState, useRef, useEffect, FC, ReactElement } from "react";
import { useDrop } from "react-dnd";
import { useSelector } from "react-redux";
import { NativeTypes } from "react-dnd-html5-backend";
import ImagePreviewModal from "../../../common/component/ImagePreviewModal";
import Send from "../../../common/component/Send";
@@ -9,8 +7,19 @@ import Styled from "./styled";
import Operations from "./Operations";
import useUploadFile from "../../../common/hook/useUploadFile";
import { ChatPrefixs } from "../../../app/config";
import { useAppSelector } from "../../../app/store";
export default function Layout({
interface Props {
children: ReactElement;
header: ReactElement;
aside: ReactElement | null;
contacts: ReactElement | null;
dropFiles: [];
context: string;
to: number | null;
}
const Layout: FC<Props> = ({
children,
header,
aside = null,
@@ -18,11 +27,11 @@ export default function Layout({
dropFiles = [],
context = "channel",
to = null
}) {
}) => {
const { addStageFile } = useUploadFile({ context, id: to });
const messagesContainer = useRef(undefined);
const messagesContainer = useRef<HTMLDivElement>(null);
const [previewImage, setPreviewImage] = useState(null);
const { selects, channelsData, contactsData } = useSelector((store) => {
const { selects, channelsData, contactsData } = useAppSelector((store) => {
return {
selects: store.ui.selectMessages[`${context}_${to}`],
channelsData: store.channels.byId,
@@ -49,6 +58,7 @@ export default function Layout({
}),
[context, to]
);
useEffect(() => {
if (dropFiles?.length) {
const filesData = dropFiles.map((file) => {
@@ -63,6 +73,7 @@ export default function Layout({
const closePreviewModal = () => {
setPreviewImage(null);
};
useEffect(() => {
const container = messagesContainer?.current;
if (container) {
@@ -85,6 +96,7 @@ export default function Layout({
}
}, []);
const name = context == "channel" ? channelsData[to]?.name : contactsData[to]?.name;
return (
<>
{previewImage && <ImagePreviewModal data={previewImage} closeModal={closePreviewModal} />}
@@ -112,4 +124,6 @@ export default function Layout({
</Styled>
</>
);
}
};
export default Layout;
@@ -1,4 +1,3 @@
// import React from 'react'
import Tippy from "@tippyjs/react";
import { useDispatch, useSelector } from "react-redux";
import { useNavigate, useLocation, useMatch } from "react-router-dom";
@@ -30,9 +29,11 @@ export default function SessionContextMenu({
channelMuted: context == "channel" ? store.footprint.muteChannels[id] : false
};
});
const handleChannelSetting = () => {
navigateTo(`/setting/channel/${id}?f=${pathname}`);
};
const handleReadAll = () => {
// console.log("last mid", mids, lastMid);
if (mid) {
@@ -41,16 +42,19 @@ export default function SessionContextMenu({
updateReadIndex(param);
}
};
const handleRemoveSession = () => {
dispatch(removeUserSession(id));
if (pathMatched) {
navigateTo("/chat");
}
};
const handleChannelMute = () => {
const data = channelMuted ? { remove_groups: [id] } : { add_groups: [{ gid: id }] };
muteChannel(data);
};
const items =
context == "user"
? [
@@ -13,7 +13,10 @@ import IconLock from "../../../assets/icons/lock.svg";
import useContextMenu from "../../../common/hook/useContextMenu";
import { useNavigate, NavLink } from "react-router-dom";
import useUploadFile from "../../../common/hook/useUploadFile";
// todo: move to root file
dayjs.extend(relativeTime);
export default function Session({
type = "user",
id,
@@ -23,6 +26,7 @@ export default function Session({
}) {
const navigate = useNavigate();
const { addStageFile } = useUploadFile({ context: type, id });
const [{ isActive }, drop] = useDrop(
() => ({
accept: [NativeTypes.FILE],
@@ -44,6 +48,7 @@ export default function Session({
}),
[type, id]
);
const { visible: contextMenuVisible, handleContextMenuEvent, hideContextMenu } = useContextMenu();
const [data, setData] = useState(null);
const { messageData, contactData, channelData, readIndex, loginUid, mids, muted } = useSelector(
@@ -60,10 +65,12 @@ export default function Session({
};
}
);
const handleImageError = (evt) => {
evt.target.classList.add("channel_default");
evt.target.src = iconChannel;
};
useEffect(() => {
const tmp = type == "user" ? contactData[id] : channelData[id];
if (!tmp) return;
@@ -81,6 +88,7 @@ export default function Session({
messageData,
loginUid
});
return (
<li className="session">
<ContextMenu
@@ -1,15 +1,16 @@
import { useState, useEffect } from "react";
import { useSelector } from "react-redux";
import Styled from "./styled";
import Session from "./Session";
import DeleteChannelConfirmModal from "../../settingChannel/DeleteConfirmModal";
import InviteModal from "../../../common/component/InviteModal";
import { useAppSelector } from "../../../app/store";
export default function SessionList({ tempSession = null }) {
const [deleteId, setDeleteId] = useState(null);
const [inviteChannelId, setInviteChannelId] = useState(null);
const [sessions, setSessions] = useState([]);
const { channelIDs, DMs, readChannels, readUsers, channelMessage, userMessage, loginUid } =
useSelector((store) => {
useAppSelector((store) => {
return {
loginUid: store.authData.uid,
channelIDs: store.channels.ids,
@@ -20,6 +21,7 @@ export default function SessionList({ tempSession = null }) {
readUsers: store.footprint.readUsers
};
});
useEffect(() => {
const cSessions = channelIDs.map((id) => {
const mids = channelMessage[id];
@@ -51,6 +53,7 @@ export default function SessionList({ tempSession = null }) {
userMessage,
tempSession
]);
return (
<>
<Styled>
@@ -1,14 +1,14 @@
import { useState } from "react";
import { useSelector } from "react-redux";
// import { useUpdateChannelMutation } from "../../app/services/channel";
import { useUpdateMuteSettingMutation } from "../../app/services/contact";
import { useReadMessageMutation } from "../../app/services/message";
import { useAppSelector } from "../../app/store";
export default function useSession({ type, id }) {
const [inviteModalVisible, setInviteModalVisible] = useState(false);
const [muteChannel] = useUpdateMuteSettingMutation();
const [updateReadIndex] = useReadMessageMutation();
const { messageData, contactData, channelData } = useSelector((store) => {
const { messageData, contactData, channelData } = useAppSelector((store) => {
return {
messageData: store.message,
contactData: store.contacts.byId,
@@ -1,6 +1,7 @@
import React from "react";
import dayjs from "dayjs";
import styled from "styled-components";
import reactStringReplace from "react-string-replace";
import { useDispatch, useSelector } from "react-redux";
import { isImage } from "../../common/utils";
import { ContentTypes } from "../../app/config";
@@ -9,7 +10,7 @@ import Divider from "../../common/component/Divider";
import Message from "../../common/component/Message";
import { updateSelectMessages } from "../../app/slices/ui";
import Mention from "../../common/component/Message/Mention";
import reactStringReplace from "react-string-replace";
// function debounce(callback, wait = 2000, immediate = false) {
// let timeout = null;
// return function () {
@@ -22,6 +23,7 @@ import reactStringReplace from "react-string-replace";
// }
// };
// }
export function getUnreadCount({ mids = [], messageData = {}, loginUid = 0, readIndex = 0 }) {
// console.log({ mids, loginUid, readIndex });
// 先过滤掉空信息和from自己的
@@ -124,6 +126,7 @@ const StyledWrapper = styled.div`
}
}
`;
const MessageWrapper = ({ selectMode = false, context, id, mid, children, ...rest }) => {
const dispatch = useDispatch();
@@ -142,6 +145,7 @@ const MessageWrapper = ({ selectMode = false, context, id, mid, children, ...res
</StyledWrapper>
);
};
export const renderMessageFragment = ({
selectMode = false,
isFirst = false,
@@ -1,8 +1,9 @@
// import React from 'react';
import { FC } from "react";
import styled from "styled-components";
import Avatar from "../../common/component/Avatar";
import { useSelector } from "react-redux";
import { NavLink, useLocation } from "react-router-dom";
import Avatar from "../../common/component/Avatar";
import { useAppSelector } from "../../app/store";
const StyledWrapper = styled.div`
padding: 10px 12px;
.avatar {
@@ -16,10 +17,16 @@ const StyledWrapper = styled.div`
}
}
`;
export default function User({ uid = null }) {
interface Props {
uid: number;
}
const User: FC<Props> = ({ uid }) => {
const { pathname } = useLocation();
const user = useSelector((store) => store.contacts.byId[uid]);
const user = useAppSelector((store) => store.contacts.byId[uid]);
if (!user) return null;
return (
<StyledWrapper>
<NavLink to={`/setting?nav=my_account&f=${pathname}`}>
@@ -29,4 +36,6 @@ export default function User({ uid = null }) {
</NavLink>
</StyledWrapper>
);
}
};
export default User;
@@ -1,10 +1,10 @@
import { useEffect } from "react";
import { useSelector } from "react-redux";
import initCache, { useRehydrate } from "../../app/cache";
import { useLazyGetFavoritesQuery } from "../../app/services/message";
import { useLazyGetContactsQuery } from "../../app/services/contact";
import { useLazyGetServerQuery } from "../../app/services/server";
import useStreaming from "../../common/hook/useStreaming";
import { useAppSelector } from "../../app/store";
// pollingInterval: 0,
// const querySetting = {
// refetchOnMountOrArgChange: true,
@@ -12,7 +12,7 @@ import useStreaming from "../../common/hook/useStreaming";
// let request = null;
export default function usePreload() {
const { rehydrate, rehydrated } = useRehydrate();
const { loginUid, token } = useSelector((store) => {
const { loginUid, token } = useAppSelector((store) => {
return { loginUid: store.authData.uid, token: store.authData.token };
});
const { setStreamingReady } = useStreaming();
@@ -1,16 +1,18 @@
// import { useState, useEffect } from "react";
import Button from "../../common/component/styled/Button";
import styled from "styled-components";
import { useNavigate } from "react-router-dom";
import Button from "../../common/component/styled/Button";
const StyledMagicButton = styled(Button)`
width: 100%;
margin-bottom: 16px;
`;
export default function MagicLinkLogin() {
const navigate = useNavigate();
const handleGoogleLogin = () => {
navigate("/send_magic_link");
// signIn();
};
return <StyledMagicButton onClick={handleGoogleLogin}>Sign in with Magic Link</StyledMagicButton>;
}
@@ -13,6 +13,7 @@ export default function OidcLoginEntry({ issuer }) {
redirect_uri: `${location.origin}/#/login`
});
};
useEffect(() => {
if (isSuccess) {
console.log("wtf", data);
@@ -21,6 +22,7 @@ export default function OidcLoginEntry({ issuer }) {
}
}, [data, isSuccess]);
console.log(issuer);
return (
<StyledSocialButton disabled={isLoading} onClick={handleSolidLogin}>
{Boolean(issuer.favicon) && <img src={issuer.favicon} className="icon" alt="icon" />}
@@ -21,11 +21,13 @@ const StyledSignUpLink = styled.p`
cursor: pointer;
}
`;
export default function MagicLinkLogin() {
const navigate = useNavigate();
const handleSignUp = () => {
navigate("/register");
};
return (
<StyledSignUpLink>
<span>Dont have an account?</span>
@@ -16,6 +16,7 @@ import useGoogleAuthConfig from "../../common/hook/useGoogleAuthConfig";
import useGithubAuthConfig from "../../common/hook/useGithubAuthConfig";
import GoogleLoginButton from "../../common/component/GoogleLoginButton";
import GithubLoginButton from "../../common/component/GithubLoginButton";
export default function LoginPage() {
const { data: enableSMTP } = useGetSMTPStatusQuery();
const [login, { isSuccess, isLoading, error }] = useLoginMutation();
@@ -26,6 +27,7 @@ export default function LoginPage() {
email: "",
password: ""
});
useEffect(() => {
const query = new URLSearchParams(location.search);
// const githubCode = query.get("gcode");
@@ -121,6 +123,7 @@ export default function LoginPage() {
};
const { email, password } = input;
if (!loginConfigSuccess) return null;
const {
magic_link,
github: enableGithubLogin,
@@ -129,10 +132,12 @@ export default function LoginPage() {
oidc = [],
who_can_sign_up: whoCanSignUp
} = loginConfig;
const enableMagicLink = enableSMTP && magic_link;
const googleLogin = enableGoogleLogin && clientId;
const hasDivider =
enableMagicLink || googleLogin || enableMetamaskLogin || oidc.length > 0 || enableGithubLogin;
return (
<StyledWrapper>
<div className="form">
@@ -1,5 +1,6 @@
import styled from "styled-components";
import Button from "../../common/component/styled/Button";
export const StyledSocialButton = styled(Button)`
width: 100%;
margin-bottom: 16px;
@@ -15,6 +16,7 @@ export const StyledSocialButton = styled(Button)`
height: 24px;
}
`;
const StyledWrapper = styled.div`
display: flex;
justify-content: center;
@@ -1,4 +1,5 @@
import styled from "styled-components";
const StyledWrapper = styled.div`
display: flex;
justify-content: center;
@@ -7,7 +8,7 @@ const StyledWrapper = styled.div`
.form {
padding: 36px 40px 32px 40px;
/* border: 1px solid #eee; */
box-shadow: 0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06);
box-shadow: 0 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06);
border-radius: 12px;
.tips {
display: flex;
@@ -41,7 +42,7 @@ const StyledWrapper = styled.div`
width: 360px;
background: #ffffff;
border: 1px solid #d0d5dd;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
box-shadow: 0 1px 2px rgba(16, 24, 40, 0.05);
border-radius: 8px;
padding: 10px 14px;
font-weight: normal;
@@ -61,7 +62,7 @@ const StyledWrapper = styled.div`
padding: 10px;
background: #1fe1f9;
border: 1px solid #1fe1f9;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
box-shadow: 0 1px 2px rgba(16, 24, 40, 0.05);
border-radius: 8px;
&.google {
color: #344054;
@@ -1,5 +1,5 @@
// import React from "react";
import styled from "styled-components";
const Styled = styled.div`
display: flex;
flex-direction: column;
@@ -22,6 +22,7 @@ const Styled = styled.div`
}
}
`;
export default function EmailNextTip() {
return (
<Styled>
@@ -1,5 +1,6 @@
// import React from "react";
import styled from "styled-components";
const Styled = styled.div`
display: flex;
flex-direction: column;
@@ -22,6 +23,7 @@ const Styled = styled.div`
}
}
`;
export default function ExpiredTip() {
return (
<Styled>
@@ -1,12 +1,9 @@
import { useState, useEffect } from "react";
// import { useDispatch } from "react-redux";
import { useState, useEffect, FormEvent, ChangeEvent } from "react";
import { useNavigate } from "react-router-dom";
// import toast from "react-hot-toast";
import Input from "../../common/component/styled/Input";
import Button from "../../common/component/styled/Button";
import { useSendRegMagicLinkMutation } from "../../app/services/auth";
import EmailNextTip from "./EmailNextStepTip";
// import { useSendLoginMagicLinkMutation } from "../../app/services/auth";
export default function Reg() {
const [sendRegMagicLink, { isLoading, data, isSuccess }] = useSendRegMagicLinkMutation();
@@ -17,6 +14,7 @@ export default function Reg() {
password: "",
confirmPassword: ""
});
useEffect(() => {
const query = new URLSearchParams(location.search);
// const githubCode = query.get("gcode");
@@ -25,6 +23,7 @@ export default function Reg() {
setMagicToken(token);
}
}, []);
useEffect(() => {
if (isSuccess && data) {
const { new_magic_token, mail_is_sent } = data;
@@ -35,7 +34,7 @@ export default function Reg() {
}
}, [isSuccess, data]);
const handleReg = (evt) => {
const handleReg = (evt: FormEvent<HTMLFormElement>) => {
evt.preventDefault();
const { email, password } = input;
sendRegMagicLink({
@@ -46,7 +45,7 @@ export default function Reg() {
// sendMagicLink(email);
};
const handleInput = (evt) => {
const handleInput = (evt: ChangeEvent<HTMLInputElement>) => {
const { type } = evt.target.dataset;
const { value } = evt.target;
// console.log(type, value);
@@ -55,6 +54,7 @@ export default function Reg() {
return { ...prev };
});
};
const { email, password } = input;
if (data?.mail_is_sent) return <EmailNextTip />;
return (
@@ -20,6 +20,7 @@ const StyledSignInLink = styled.p`
cursor: pointer;
}
`;
export default function SignInLink() {
const navigate = useNavigate();
const handleSignIn = () => {
@@ -1,4 +1,5 @@
import styled from "styled-components";
const StyledWrapper = styled.div`
display: flex;
justify-content: center;
@@ -7,7 +8,7 @@ const StyledWrapper = styled.div`
.form {
max-width: 440px;
padding: 36px 40px 32px 40px;
box-shadow: 0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06);
box-shadow: 0 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06);
border-radius: 12px;
.tips {
display: flex;
@@ -1,16 +1,15 @@
// import React from 'react'
// import { useSelector } from "react-redux";
import styled from "styled-components";
import CheckSign from "../../../assets/icons/check.sign.svg";
import ChannelIcon from "../../../common/component/ChannelIcon";
import Search from "../Search";
import useFilteredChannels from "../../../common/hook/useFilteredChannels";
const Styled = styled.div`
padding: 0 4px 4px 4px;
background: #ffffff;
max-height: 400px;
overflow: auto;
box-shadow: 0px 24px 48px -12px rgba(16, 24, 40, 0.18);
box-shadow: 0 24px 48px -12px rgba(16, 24, 40, 0.18);
border-radius: 8px;
display: flex;
flex-direction: column;
@@ -52,11 +51,13 @@ const Styled = styled.div`
}
}
`;
export default function Channel({ select = "", updateFilter }) {
const { input, updateInput, channels } = useFilteredChannels();
const handleClick = (gid) => {
updateFilter({ channel: gid });
};
return (
<Styled>
<div className="search">
@@ -1,5 +1,3 @@
// import React from 'react'
// import { useSelector } from "react-redux";
import styled from "styled-components";
import CheckSign from "../../../assets/icons/check.sign.svg";
@@ -39,6 +37,7 @@ const Styled = styled.div`
}
}
`;
export const Dates = {
today: {
title: "Today",
@@ -57,6 +56,7 @@ export const Dates = {
title: "Last 12 months"
}
};
export default function Date({ select = "", updateFilter }) {
// const { input, updateInput, contacts } = useFilteredUsers();
// const contacts=useSelector(store=>store.contacts);
@@ -66,6 +66,7 @@ export default function Date({ select = "", updateFilter }) {
const handleClick = (dur) => {
updateFilter({ date: dur });
};
return (
<Styled>
<ul className="list">
@@ -1,17 +1,15 @@
// import React from 'react'
// import { useSelector } from "react-redux";
import styled from "styled-components";
import Search from "../Search";
import CheckSign from "../../../assets/icons/check.sign.svg";
import Contact from "../../../common/component/Contact";
import useFilteredUsers from "../../../common/hook/useFilteredUsers";
const Styled = styled.div`
padding: 0 4px 4px 4px;
background: #ffffff;
max-height: 300px;
overflow: auto;
box-shadow: 0px 24px 48px -12px rgba(16, 24, 40, 0.18);
box-shadow: 0 24px 48px -12px rgba(16, 24, 40, 0.18);
border-radius: 8px;
display: flex;
flex-direction: column;
@@ -49,6 +47,7 @@ const Styled = styled.div`
}
}
`;
export default function From({ select = "", updateFilter }) {
const { input, updateInput, contacts } = useFilteredUsers();
// const contacts=useSelector(store=>store.contacts);
@@ -58,6 +57,7 @@ export default function From({ select = "", updateFilter }) {
const handleClick = (uid) => {
updateFilter({ from: uid });
};
return (
<Styled>
<div className="search">
@@ -1,5 +1,3 @@
// import React from 'react'
// import { useSelector } from "react-redux";
import styled from "styled-components";
import IconPdf from "../../../assets/icons/file.pdf.svg";
import IconAudio from "../../../assets/icons/file.audio.svg";
@@ -16,7 +14,7 @@ const Styled = styled.div`
min-width: 200px;
/* max-height: 230px; */
overflow: auto;
box-shadow: 0px 24px 48px -12px rgba(16, 24, 40, 0.18);
box-shadow: 0 24px 48px -12px rgba(16, 24, 40, 0.18);
border-radius: 8px;
display: flex;
flex-direction: column;
@@ -33,7 +31,6 @@ const Styled = styled.div`
display: flex;
align-items: center;
gap: 8px;
color: #616161;
font-weight: 600;
font-size: 14px;
line-height: 20px;
@@ -1,13 +1,14 @@
import { useState } from "react";
import styled from "styled-components";
import Tippy from "@tippyjs/react";
import { useSelector } from "react-redux";
import Avatar from "../../../common/component/Avatar";
import FilterDate, { Dates } from "./Date";
import FilterFrom from "./From";
import FilterChannel from "./Channel";
import FilterType, { FileTypes } from "./Type";
import ArrowDown from "../../../assets/icons/arrow.down.svg";
import { useAppSelector } from "../../../app/store";
const Styled = styled.div`
/* padding: 20px 0; */
display: flex;
@@ -20,7 +21,7 @@ const Styled = styled.div`
gap: 8px;
border: 1px solid #d0d5dd;
box-sizing: border-box;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
box-shadow: 0 1px 2px rgba(16, 24, 40, 0.05);
border-radius: var(--br);
padding: 7px 12px;
font-weight: 500;
@@ -49,24 +50,25 @@ export default function Filter({ filter, updateFilter }) {
from: false,
type: false
});
const toggleFilterVisible = (obj) => {
setFiltersVisible((prev) => {
return { ...prev, ...obj };
});
};
const handleUpdateFilter = (data) => {
updateFilter(data);
let _key = Object.keys(data)[0];
let tmp = {
[_key]: false
};
console.log("wtffff", tmp);
toggleFilterVisible(tmp);
};
const { contactMap, channelMap } = useSelector((store) => {
const { contactMap, channelMap } = useAppSelector((store) => {
return { contactMap: store.contacts.byId, channelMap: store.channels.byId };
});
console.log("maps", contactMap, filter);
const { from, channel, type, date } = filter;
const {
channel: channelVisible,
@@ -74,6 +76,7 @@ export default function Filter({ filter, updateFilter }) {
type: typeVisible,
from: fromVisible
} = filtersVisible;
return (
<Styled>
<Tippy
@@ -1,10 +1,10 @@
// import React from "react";
import styled from "styled-components";
import iconSearch from "../../assets/icons/search.svg?url";
const Styled = styled.div`
width: 100%;
padding: 6px 16px;
box-shadow: 0px 1px 0px rgba(0, 0, 0, 0.1);
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
&.embed {
padding: 6px 8px;
box-shadow: none;
@@ -23,12 +23,14 @@ const Styled = styled.div`
background-position: 8px center;
}
`;
export default function Search({ value = "", updateSearchValue = null, embed = false }) {
const handleChange = (evt) => {
if (updateSearchValue) {
updateSearchValue(evt.target.value);
}
};
return (
<Styled className={embed ? "embed" : ""}>
<input value={value} onChange={handleChange} className="search" placeholder="Search..." />
@@ -1,14 +1,15 @@
// import React from 'react'
import { MouseEvent } from "react";
import styled from "styled-components";
import { useDispatch } from "react-redux";
import { updateFileListView } from "../../app/slices/ui";
import { Views } from "../../app/config";
import IconList from "../../assets/icons/file.list.svg";
import IconGrid from "../../assets/icons/file.grid.svg";
const Styled = styled.ul`
display: flex;
border: 1px solid #d0d5dd;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
box-shadow: 0 1px 2px rgba(16, 24, 40, 0.05);
border-radius: 8px;
box-sizing: border-box;
@@ -23,7 +24,7 @@ const Styled = styled.ul`
&.item .item,
&.grid .grid {
border: 1px solid #52edff;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
box-shadow: 0 1px 2px rgba(16, 24, 40, 0.05);
border-radius: 8px;
svg {
transition: all 0.2s ease;
@@ -36,11 +37,12 @@ const Styled = styled.ul`
export default function View({ view = Views.item }) {
const dispatch = useDispatch();
const handleChangeView = (evt) => {
const handleChangeView = (evt: MouseEvent<HTMLLIElement>) => {
const { view: clickView } = evt.currentTarget.dataset;
if (clickView == view) return;
dispatch(updateFileListView(view == Views.item ? Views.grid : Views.item));
};
return (
<Styled className={view}>
<li className="view item" data-view={Views.item} onClick={handleChangeView}>
@@ -1,15 +1,14 @@
import { useState, useEffect, useRef, memo } from "react";
import Styled from "./styled";
import { useSelector } from "react-redux";
import Masonry from "masonry-layout";
// import waterfall from "waterfall.js/src/waterfall";
import Styled from "./styled";
import { Views } from "../../app/config";
import View from "./View";
import Search from "./Search";
import Filter from "./Filter";
import FileBox from "../../common/component/FileBox";
import { useAppSelector } from "../../app/store";
const checkFilter = (data, filter, channelMessage) => {
console.log("filter data", data);
let selected = true;
const { mid, file_type, created_at, from_uid, properties } = data;
const {
@@ -35,11 +34,12 @@ const checkFilter = (data, filter, channelMessage) => {
}
return selected;
};
let msnry = null;
function ResourceManagement({ fileMessages }) {
const listContainerRef = useRef(null);
const [filter, setFilter] = useState({});
const { message, view, channelMessage } = useSelector((store) => {
const { message, view, channelMessage } = useAppSelector((store) => {
return {
message: store.message,
channelMessage: store.channelMessage,
@@ -52,11 +52,13 @@ function ResourceManagement({ fileMessages }) {
return { ...prev, ...data };
});
};
const handleUpdateSearch = (val) => {
setFilter((prev) => {
return { ...prev, name: val };
});
};
useEffect(() => {
if (view == Views.grid && listContainerRef) {
const container = listContainerRef.current;
@@ -84,7 +86,6 @@ function ResourceManagement({ fileMessages }) {
// }
}, [view, filter]);
console.log("files", fileMessages);
return (
<Styled>
<Search value={filter.name} updateSearchValue={handleUpdateSearch} />
@@ -119,7 +120,9 @@ function ResourceManagement({ fileMessages }) {
</Styled>
);
}
const equals = (a, b) => a.length === b.length && a.every((v, i) => v == b[i]);
export default memo(ResourceManagement, (prevs, nexts) => {
return equals(prevs.fileMessages, nexts.fileMessages);
});
@@ -1,4 +1,5 @@
import styled from "styled-components";
const Styled = styled.div`
height: 100vh;
overflow-y: scroll;
@@ -1,6 +1,12 @@
// import React from "react";
import Button from "../../common/component/styled/Button";
export default function SentTip({ email, reset }) {
import { FC, MouseEvent } from "react";
interface Props {
email: string;
reset?: (e: MouseEvent<HTMLButtonElement>) => void;
}
const SentTip: FC<Props> = ({ email, reset }) => {
return (
<div className="tips">
<h2 className="title">Check your email</h2>
@@ -12,4 +18,6 @@ export default function SentTip({ email, reset }) {
</Button>
</div>
);
}
};
export default SentTip;
@@ -1,6 +1,4 @@
/* eslint-disable no-undef */
import { useState, useEffect } from "react";
// import { useDispatch } from "react-redux";
import { useState, useEffect, ChangeEvent, FormEvent } from "react";
import { useNavigate } from "react-router-dom";
import toast from "react-hot-toast";
import BASE_URL from "../../app/config";
@@ -13,10 +11,9 @@ import SentTip from "./SentTip";
export default function SendMagicLinkPage() {
const [sent, setSent] = useState(false);
const [sendMagicLink, { isSuccess, isLoading, error }] = useSendLoginMagicLinkMutation();
const navigateTo = useNavigate();
// const dispatch = useDispatch();
const [email, setEmail] = useState("");
useEffect(() => {
if (isSuccess) {
toast.success("Send Email Successfully!");
@@ -48,20 +45,23 @@ export default function SendMagicLinkPage() {
const handlePwdPath = () => {
navigateTo("/login");
};
const handleLogin = (evt) => {
const handleLogin = (evt: FormEvent<HTMLFormElement>) => {
evt.preventDefault();
sendMagicLink(email);
};
const handleInput = (evt) => {
const handleInput = (evt: ChangeEvent<HTMLInputElement>) => {
const { value } = evt.target;
console.log(value);
setEmail(value);
};
const handleReset = () => {
setEmail("");
setSent(false);
};
return (
<StyledWrapper>
<div className="form">
@@ -1,6 +1,15 @@
import { useEffect } from "react";
import styled from "styled-components";
import Tippy from "@tippyjs/react";
import toast from "react-hot-toast";
import { hideAll } from "tippy.js";
import Input from "../../common/component/styled/Input";
import Button from "../../common/component/styled/Button";
import {
useGetThirdPartySecretQuery,
useUpdateThirdPartySecretMutation
} from "../../app/services/server";
const StyledConfirm = styled.div`
padding: 12px;
border-radius: 10px;
@@ -48,19 +57,12 @@ const Styled = styled.div`
line-height: 1.5;
}
`;
import Input from "../../common/component/styled/Input";
import Button from "../../common/component/styled/Button";
import {
useGetThirdPartySecretQuery,
useUpdateThirdPartySecretMutation
} from "../../app/services/server";
import Tippy from "@tippyjs/react";
import toast from "react-hot-toast";
export default function APIConfig() {
const { data } = useGetThirdPartySecretQuery();
const [updateSecret, { data: updatedSecret, isSuccess, isLoading }] =
useUpdateThirdPartySecretMutation();
console.log("secret", data);
useEffect(() => {
if (isSuccess) {
hideAll();
@@ -1,11 +1,12 @@
import { useEffect, useState } from "react";
import { useEffect, useState, MouseEvent } from "react";
import styled from "styled-components";
import { useSelector } from "react-redux";
import toast from "react-hot-toast";
import { useUpdateAvatarMutation } from "../../app/services/contact";
import AvatarUploader from "../../common/component/AvatarUploader";
import ProfileBasicEditModal from "./ProfileBasicEditModal";
import UpdatePasswordModal from "./UpdatePasswordModal";
import { useAppSelector } from "../../app/store";
const StyledWrapper = styled.div`
display: flex;
flex-direction: column;
@@ -109,28 +110,34 @@ const EditModalInfo = {
intro: "Enter a new email."
}
};
export default function MyAccount() {
const [passwordModal, setPasswordModal] = useState(false);
const [editModal, setEditModal] = useState(null);
const [uploadAvatar, { isSuccess: uploadSuccess }] = useUpdateAvatarMutation();
const loginUser = useSelector((store) => {
const loginUser = useAppSelector((store) => {
return store.contacts.byId[store.authData.uid];
});
useEffect(() => {
if (uploadSuccess) {
toast.success("update avatar successfully!");
}
}, [uploadSuccess]);
const handleBasicEdit = (evt) => {
const handleBasicEdit = (evt: MouseEvent<HTMLButtonElement>) => {
const { edit } = evt.target.dataset;
setEditModal(edit);
};
const closeBasicEditModal = () => {
setEditModal(null);
};
const togglePasswordModal = () => {
setPasswordModal((prev) => !prev);
};
if (!loginUser) return null;
const { uid, avatar, name, email } = loginUser;
return (
@@ -1,12 +1,13 @@
// import React from "react";
import styled from "styled-components";
import useNotification from "../../common/hook/useNotification";
import StyledToggle from "../../common/component/styled/Toggle";
import Label from "../../common/component/styled/Label";
const StyledWrapper = styled.div`
display: flex;
flex-direction: column;
`;
export default function Notifications() {
const { status, enableNotification } = useNotification();
const handleEnableNotify = () => {
@@ -14,6 +15,7 @@ export default function Notifications() {
enableNotification();
}
};
return (
<StyledWrapper>
<Label>Notification Setting:</Label>
@@ -1,6 +1,6 @@
import { useState, useEffect } from "react";
import styled from "styled-components";
import { useSelector } from "react-redux";
import toast from "react-hot-toast";
import {
useGetServerQuery,
useUpdateServerMutation,
@@ -13,8 +13,8 @@ import Input from "../../common/component/styled/Input";
import Label from "../../common/component/styled/Label";
import Textarea from "../../common/component/styled/Textarea";
import SaveTip from "../../common/component/SaveTip";
import toast from "react-hot-toast";
import StyledRadio from "../../common/component/styled/Radio";
import { useAppSelector } from "../../app/store";
const StyledWrapper = styled.div`
position: relative;
@@ -55,7 +55,7 @@ const StyledWrapper = styled.div`
background: #ecfeff;
border: 1px solid #ecfeff;
box-sizing: border-box;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
box-shadow: 0 1px 2px rgba(16, 24, 40, 0.05);
border-radius: 8px;
}
}
@@ -97,8 +97,9 @@ const StyledWrapper = styled.div`
}
}
`;
export default function Overview() {
const loginUser = useSelector((store) => {
const loginUser = useAppSelector((store) => {
return store.contacts.byId[store.authData.uid];
});
const [changed, setChanged] = useState(false);
@@ -1,10 +1,13 @@
// import React from "react";
import { useEffect, useState } from "react";
import styled from "styled-components";
import toast from "react-hot-toast";
import Input from "../../common/component/styled/Input";
import { useUpdateInfoMutation } from "../../app/services/contact";
import StyledModal from "../../common/component/styled/Modal";
import Button from "../../common/component/styled/Button";
import Modal from "../../common/component/Modal";
const StyledEdit = styled(StyledModal)`
.input {
margin: 48px 0;
@@ -20,8 +23,7 @@ const StyledEdit = styled(StyledModal)`
}
}
`;
import Modal from "../../common/component/Modal";
import toast from "react-hot-toast";
export default function ProfileBasicEditModal({
label = "Username",
valueKey = "name",
@@ -1,10 +1,12 @@
// import React from "react";
import { useEffect, useState } from "react";
import { ChangeEvent, useEffect, useState, FC } from "react";
import styled from "styled-components";
import toast from "react-hot-toast";
import Input from "../../common/component/styled/Input";
import { useUpdatePasswordMutation, useGetCredentialsQuery } from "../../app/services/auth";
import StyledModal from "../../common/component/styled/Modal";
import Button from "../../common/component/styled/Button";
import Modal from "../../common/component/Modal";
const StyledEdit = styled(StyledModal)`
.input {
margin: 16px 0;
@@ -20,9 +22,12 @@ const StyledEdit = styled(StyledModal)`
}
}
`;
import Modal from "../../common/component/Modal";
import toast from "react-hot-toast";
export default function ProfileBasicEditModal({ closeModal }) {
interface Props {
closeModal: () => void;
}
const ProfileBasicEditModal: FC<Props> = ({ closeModal }) => {
const { data } = useGetCredentialsQuery();
const [input, setInput] = useState({
current: "",
@@ -31,7 +36,7 @@ export default function ProfileBasicEditModal({ closeModal }) {
});
// const dispatch = useDispatch();
const [updatePassword, { isLoading, isSuccess }] = useUpdatePasswordMutation();
const handleChange = (evt) => {
const handleChange = (evt: ChangeEvent<HTMLInputElement>) => {
const { type } = evt.target.dataset;
setInput((prev) => {
return { ...prev, [type]: evt.target.value };
@@ -116,4 +121,6 @@ export default function ProfileBasicEditModal({ closeModal }) {
</StyledEdit>
</Modal>
);
}
};
export default ProfileBasicEditModal;
@@ -1,4 +1,3 @@
// import { useState, useEffect } from "react";
import StyledContainer from "./StyledContainer";
import Input from "../../../common/component/styled/Input";
import Textarea from "../../../common/component/styled/Textarea";
@@ -6,12 +5,14 @@ import Label from "../../../common/component/styled/Label";
import Toggle from "../../../common/component/styled/Toggle";
import SaveTip from "../../../common/component/SaveTip";
import useConfig from "../../../common/hook/useConfig";
export default function ConfigAgora() {
const { changed, reset, values, setValues, toggleEnable, updateConfig } = useConfig("agora");
const handleUpdate = () => {
// const { token_url, description } = values;
updateConfig(values);
};
const handleChange = (evt) => {
const newValue = evt.target.value;
const { type } = evt.target.dataset;
@@ -29,6 +30,7 @@ export default function ConfigAgora() {
rtm_secret,
enabled = false
} = values ?? {};
return (
<StyledContainer>
<div className="inputs">
@@ -1,4 +1,4 @@
import { useState } from "react";
import { ChangeEvent, useState } from "react";
import Select from "../../../../common/component/styled/Select";
import Button from "../../../../common/component/styled/Button";
import Input from "../../../../common/component/styled/Input";
@@ -11,13 +11,16 @@ import IconMinus from "../../../../assets/icons/minus.circle.svg";
export default function IssuerList({ issuers = [], onChange }) {
const [select, setSelect] = useState({});
const [newDomain, setNewDomain] = useState("");
const handleNewDomain = (evt) => {
const handleNewDomain = (evt: ChangeEvent<HTMLInputElement>) => {
setNewDomain(evt.target.value);
};
const disableBtn =
(!newDomain && !select?.value) ||
!select?.title ||
issuers.some((issuer) => issuer.domain === newDomain);
return (
<Styled>
<ul className="issuers">
@@ -1,4 +1,5 @@
import styled from "styled-components";
const Styled = styled.div`
padding: 16px 0;
width: 100%;
@@ -1,4 +1,3 @@
// import { useState } from "react";
import toast from "react-hot-toast";
import StyledContainer from "./StyledContainer";
import Toggle from "../../../common/component/styled/Toggle";
@@ -10,6 +9,7 @@ import Tooltip from "./Tooltip";
import IssuerList from "./IssuerList";
import useGoogleAuthConfig from "../../../common/hook/useGoogleAuthConfig";
import useGithubAuthConfig from "../../../common/hook/useGithubAuthConfig";
export default function Logins() {
const {
changed: clientIdChanged,
@@ -1,4 +1,5 @@
import styled from "styled-components";
const StyledContainer = styled.div`
position: relative;
width: 512px;
@@ -1,10 +1,11 @@
import { useState } from "react";
// import { useDispatch } from "react-redux";
import { useNavigate, useSearchParams } from "react-router-dom";
import StyledSettingContainer from "../../common/component/StyledSettingContainer";
import useNavs from "./navs";
import LogoutConfirmModal from "./LogoutConfirmModal";
let from = null;
let from: string | null = null;
export default function Setting() {
const [searchParams] = useSearchParams();
const navs = useNavs();
@@ -26,6 +27,7 @@ export default function Setting() {
setLogoutConfirm((prev) => !prev);
};
const currNav = flatenNavs.find((n) => n.name == navKey) || flatenNavs[0];
return (
<>
<StyledSettingContainer
@@ -1,14 +1,14 @@
import { useSelector } from "react-redux";
import MyAccount from "./MyAccount";
import Overview from "./Overview";
import Logins from "./config/Logins";
import ConfigFirebase from "./config/Firebase";
import ConfigSMTP from "./config/SMTP";
// import Notifications from "./Notifications";
import APIConfig from "./APIConfig";
import ManageMembers from "../../common/component/ManageMembers";
import FAQ from "../../common/component/FAQ";
import ConfigAgora from "./config/Agora";
import { useAppSelector } from "../../app/store";
const navs = [
{
title: "General",
@@ -93,18 +93,18 @@ const navs = [
]
}
];
const useNavs = () => {
const loginUser = useSelector((store) => {
const loginUser = useAppSelector((store) => {
return store.contacts.byId[store.authData.uid];
});
const Navs = navs.filter((nav) => {
return navs.filter((nav) => {
if (loginUser?.is_admin) {
return true;
} else {
return !nav.admin;
}
});
return Navs;
};
export default useNavs;
@@ -1,5 +1,4 @@
// import React from "react";
import { useEffect } from "react";
import { useEffect, FC } from "react";
import toast from "react-hot-toast";
import { useNavigate } from "react-router-dom";
import Modal from "../../common/component/Modal";
@@ -7,13 +6,19 @@ import { useLazyRemoveChannelQuery } from "../../app/services/channel";
import StyledModal from "../../common/component/styled/Modal";
import Button from "../../common/component/styled/Button";
export default function DeleteConfirmModal({ id, closeModal }) {
interface Props {
id?: number;
closeModal: () => void;
}
const DeleteConfirmModal: FC<Props> = ({ id, closeModal }) => {
const navigateTo = useNavigate();
// const pathMatched = useMatch(`/chat/channel/${id}`);
const [deleteChannel, { isLoading, isSuccess }] = useLazyRemoveChannelQuery();
const handleDelete = () => {
deleteChannel(id);
};
useEffect(() => {
if (isSuccess) {
toast.success("delete channel successfully!");
@@ -21,6 +26,7 @@ export default function DeleteConfirmModal({ id, closeModal }) {
navigateTo("/chat");
}
}, [isSuccess]);
if (!id) return null;
return (
<Modal id="modal-modal">
@@ -42,4 +48,6 @@ export default function DeleteConfirmModal({ id, closeModal }) {
></StyledModal>
</Modal>
);
}
};
export default DeleteConfirmModal;
@@ -12,7 +12,8 @@ import Label from "../../common/component/styled/Label";
import Textarea from "../../common/component/styled/Textarea";
import SaveTip from "../../common/component/SaveTip";
import channelIcon from "../../assets/icons/channel.svg?url";
import { useSelector } from "react-redux";
import { useAppSelector } from "../../app/store";
const StyledWrapper = styled.div`
position: relative;
width: 512px;
@@ -43,7 +44,7 @@ const StyledWrapper = styled.div`
}
`;
export default function Overview({ id = 0 }) {
const { loginUser, channel } = useSelector((store) => {
const { loginUser, channel } = useAppSelector((store) => {
return {
loginUser: store.contacts.byId[store.authData.uid],
channel: store.channels.byId[id]
@@ -58,6 +59,7 @@ export default function Overview({ id = 0 }) {
const { name, description } = values;
updateChannel({ id, name, description });
};
const handleChange = (evt) => {
const newValue = evt.target.value;
const { type } = evt.target.dataset;
@@ -65,18 +67,22 @@ export default function Overview({ id = 0 }) {
return { ...prev, [type]: newValue };
});
};
const updateIcon = (image) => {
updateChannelIcon({ gid: id, image });
};
const handleReset = () => {
console.log("reset", data);
setValues(data);
};
useEffect(() => {
if (data) {
setValues(data);
}
}, [data]);
useEffect(() => {
if (data && values) {
const { name, description } = values;
@@ -99,7 +105,7 @@ export default function Overview({ id = 0 }) {
if (!values || !id) return null;
const { name, description } = values;
const readOnly = !loginUser?.is_admin && channel?.owner != loginUser?.uid;
console.log("channel icon", channel);
return (
<StyledWrapper>
<AvatarUploader type="channel" url={channel?.icon} name={name} uploadImage={updateIcon} />
@@ -1,14 +1,16 @@
import { useState } from "react";
import { useSelector } from "react-redux";
import { useParams, useNavigate, useSearchParams } from "react-router-dom";
import LeaveChannel from "../../common/component/LeaveChannel";
import StyledSettingContainer from "../../common/component/StyledSettingContainer";
import DeleteConfirmModal from "./DeleteConfirmModal";
import useNavs from "./navs";
let from = null;
import { useAppSelector } from "../../app/store";
let from: string | null = null;
export default function ChannelSetting() {
const { cid } = useParams();
const { isAdmin, loginUid, channel } = useSelector((store) => {
const { isAdmin, loginUid, channel } = useAppSelector((store) => {
return {
loginUid: store.authData.uid,
isAdmin: store.contacts.byId[store.authData.uid]?.is_admin,