feat: lots updates

This commit is contained in:
zerosoul
2022-03-22 16:10:49 +08:00
parent eef55e5cb3
commit a23800b042
40 changed files with 504 additions and 415 deletions
@@ -10,6 +10,7 @@ import Label from "../styled/Label";
import Textarea from "../styled/Textarea";
import SaveTip from "../SaveTip";
import channelIcon from "../../../assets/icons/channel.svg?url";
import { useSelector } from "react-redux";
const StyledWrapper = styled.div`
position: relative;
width: 512px;
@@ -30,7 +31,7 @@ const StyledWrapper = styled.div`
gap: 8px;
.name {
padding-left: 36px;
background: url(${channelIcon});
background-image: url(${channelIcon});
background-size: 20px;
background-position-x: 8px;
background-position-y: 8px;
@@ -40,6 +41,9 @@ const StyledWrapper = styled.div`
}
`;
export default function Overview({ id = 0 }) {
const loginUser = useSelector(
(store) => store.contacts.byId[store.authData.uid]
);
const { data, refetch } = useGetChannelQuery(id);
const [changed, setChanged] = useState(false);
const [values, setValues] = useState(null);
@@ -85,12 +89,14 @@ export default function Overview({ id = 0 }) {
if (!values || !id) return null;
const { name, description } = values;
const isAdmin = loginUser.is_admin;
return (
<StyledWrapper>
<div className="inputs">
<div className="input">
<Label htmlFor="name">Channel Name</Label>
<Input
disabled={!isAdmin}
className="name"
data-type="name"
onChange={handleChange}
@@ -103,6 +109,7 @@ export default function Overview({ id = 0 }) {
<div className="input">
<Label htmlFor="desc">Channel Topic</Label>
<Textarea
disabled={!isAdmin}
data-type="description"
onChange={handleChange}
value={description ?? ""}
+19 -27
View File
@@ -1,15 +1,6 @@
import Overview from "./Overview";
import ManageMembers from "../ManageMembers";
import { useSelector } from "react-redux";
const useNavs = (channelId) => {
const { channels, contactIds } = useSelector((store) => {
return {
channels: store.channels.byId,
contactIds: store.contacts.ids,
};
});
let ids = channels[channelId]?.members ?? [];
ids = ids.length == 0 ? contactIds : ids;
const navs = [
{
title: "General",
@@ -19,30 +10,31 @@ const useNavs = (channelId) => {
title: "Overview",
component: <Overview id={channelId} />,
},
{
name: "permissions",
title: "Permissions",
},
{
name: "invites",
title: "Invites",
},
{
name: "integrations",
title: "Integrations",
},
],
},
{
title: "User Management",
items: [
{
name: "members",
title: "Members",
component: <ManageMembers members={ids} />,
component: <ManageMembers cid={channelId} />,
},
// {
// name: "permissions",
// title: "Permissions",
// },
// {
// name: "invites",
// title: "Invites",
// },
// {
// name: "integrations",
// title: "Integrations",
// },
],
},
// {
// title: "User Management",
// items: [
// ],
// },
];
return navs;
};
-2
View File
@@ -2,7 +2,6 @@
import styled from "styled-components";
import { useSelector } from "react-redux";
import Tippy from "@tippyjs/react";
import "tippy.js/animations/scale-subtle.css";
import Avatar from "./Avatar";
import Profile from "./Profile";
@@ -75,7 +74,6 @@ export default function Contact({
>
<Tippy
inertia={true}
animation="scale"
interactive
disabled={!popover}
placement="left"
+1 -9
View File
@@ -1,13 +1,5 @@
// import React from "react";
import dayjs from "dayjs";
export default function FAQ() {
console.log("build time", process.env);
return (
<div>
Build Time:
{dayjs(new Date(Number(process.env.REACT_APP_BUILD_TIME + "000"))).format(
"YYYY-MM-DD HH:mm:ss"
)}
</div>
);
return <div>Build Timestamp: {process.env.REACT_APP_BUILD_TIME}</div>;
}
+1 -1
View File
@@ -27,7 +27,7 @@ const StyledWrapper = styled.div`
gap: 10px;
img {
max-width: 70vw;
max-height: 70vw;
max-height: 80vh;
}
.origin {
font-weight: bold;
+1
View File
@@ -16,6 +16,7 @@ const StyledWrapper = styled.div`
margin-bottom: 8px;
}
.link {
width: 512px;
margin-bottom: 12px;
display: flex;
justify-content: space-between;
+69 -44
View File
@@ -1,10 +1,13 @@
import { useState, useRef, useEffect } from "react";
import { useEffect } from "react";
import styled from "styled-components";
import { useOutsideClick } from "rooks";
// import { useOutsideClick } from "rooks";
import Tippy from "@tippyjs/react";
import { hideAll } from "tippy.js";
import { useSelector } from "react-redux";
import toast from "react-hot-toast";
import useCopy from "../hook/useCopy";
import { useLazyDeleteContactQuery } from "../../app/services/contact";
import { useRemoveMembersMutation } from "../../app/services/channel";
import Contact from "./Contact";
import StyledMenu from "./StyledMenu";
import InviteLink from "./InviteLink";
@@ -12,7 +15,9 @@ import moreIcon from "../../assets/icons/more.svg?url";
const StyledWrapper = styled.section`
display: flex;
flex-direction: column;
width: 512px;
width: 100%;
height: calc(100vh - 94px);
overflow-y: scroll;
.intro {
display: flex;
flex-direction: column;
@@ -34,6 +39,8 @@ const StyledWrapper = styled.section`
display: flex;
flex-direction: column;
gap: 24px;
width: 512px;
margin-bottom: 176px;
.member {
width: 100%;
display: flex;
@@ -87,38 +94,55 @@ const StyledWrapper = styled.section`
}
}
`;
export default function ManageMembers({ members = [] }) {
const contacts = useSelector((store) => store.contacts);
const [copied, copy] = useCopy();
const [remove, { isSuccess: removeSuccess }] = useLazyDeleteContactQuery();
const wrapperRef = useRef(null);
const [menuVisible, setMenuVisible] = useState(null);
useOutsideClick(wrapperRef, () => {
setMenuVisible(null);
export default function ManageMembers({ cid = null }) {
const { contacts, channels, loginUser } = useSelector((store) => {
return {
contacts: store.contacts,
channels: store.channels,
loginUser: store.contacts.byId[store.authData.uid],
};
});
const toggleMenu = (evt) => {
const { uid } = evt.target.dataset;
if (menuVisible == uid) {
setMenuVisible(null);
} else {
setMenuVisible(uid);
}
};
const [copied, copy] = useCopy();
const [
removeUser,
{ isSuccess: removeSuccess },
] = useLazyDeleteContactQuery();
const [
removeMemberFromChannel,
{ isSuccess: removeMemberSuccess },
] = useRemoveMembersMutation();
const remove = cid ? removeMemberFromChannel : removeUser;
const handleRemoveUser = (uid) => {
remove(uid);
remove(cid ? { id: cid, members: [+uid] } : uid);
};
useEffect(() => {
if (removeSuccess) {
toast.success("delete successfully");
}
}, [removeSuccess]);
useEffect(() => {
if (removeMemberSuccess) {
toast.success("remove member successfully");
}
}, [removeMemberSuccess]);
const handleCopy = (str) => {
copy(str);
// const tippyInstance = tippyRef.current._tippy;
setTimeout(() => {
console.log("tippy close");
hideAll();
}, 800);
};
const uids = !members || members.length == 0 ? contacts.ids : members;
const channel = channels.byId[cid] ?? null;
const uids = channel
? channel.is_public
? contacts.ids
: channel.members
: contacts.ids;
return (
<StyledWrapper>
<InviteLink />
{loginUser?.is_admin && <InviteLink />}
<div className="intro">
<h4 className="title">Manage Members</h4>
<p className="desc">
@@ -140,35 +164,36 @@ export default function ManageMembers({ members = [] }) {
</div>
<div className="right">
<span className="role">{is_admin ? "Admin" : "User"}</span>
<div className="opts">
<img
data-uid={uid}
onClick={toggleMenu}
className="dots"
src={moreIcon}
alt="dots icon"
/>
{menuVisible == uid && (
<StyledMenu ref={wrapperRef} className="menu">
<Tippy
interactive
placement="right-start"
trigger="click"
content={
<StyledMenu className="menu">
<li
className="item"
onClick={handleCopy.bind(null, email)}
>
{copied ? "Copied" : `Copy Email`}
</li>
<li className="item">Mute</li>
<li className="item underline">Change Nickname</li>
<li className="item danger">Ban</li>
<li
className="item danger"
onClick={handleRemoveUser.bind(null, uid)}
data-uid={uid}
>
Remove
</li>
{/* <li className="item underline">Mute</li> */}
{/* <li className="item underline">Change Nickname</li> */}
{/* <li className="item danger">Ban</li> */}
{loginUser?.is_admin && (
<li
className="item danger"
onClick={handleRemoveUser.bind(null, uid)}
>
Remove
</li>
)}
</StyledMenu>
)}
</div>
}
>
<div className="opts">
<img className="dots" src={moreIcon} alt="dots icon" />
</div>
</Tippy>
</div>
</li>
);
+52 -39
View File
@@ -1,8 +1,9 @@
import { useState, useRef } from "react";
import { useDispatch, useSelector } from "react-redux";
import styled from "styled-components";
import Tippy from "@tippyjs/react";
import { hideAll } from "tippy.js";
// import toast from "react-hot-toast";
import { useOutsideClick } from "rooks";
import { addReplyingMessage } from "../../../app/slices/message";
import StyledMenu from "../StyledMenu";
import DeleteMessageConfirm from "./DeleteMessageConfirm";
@@ -54,69 +55,81 @@ export default function Commands({
contextId = 0,
mid = 0,
from_uid = 0,
menuVisible,
toggleMenu,
emojiPopVisible,
toggleEmojiPopover,
toggleEditMessage,
}) {
const dispatch = useDispatch();
const [deleteModalVisible, setDeleteModalVisible] = useState(false);
const [tippyVisible, setTippyVisible] = useState(false);
const currUid = useSelector((store) => store.authData.uid);
const menuRef = useRef(null);
const handleReply = (fromMenu = false) => {
const cmdsRef = useRef(null);
const handleReply = (fromMenu) => {
if (contextId) {
dispatch(addReplyingMessage({ id: contextId, mid }));
}
if (fromMenu) {
toggleMenu();
hideAll();
}
// toast.success("cooming soon");
};
useOutsideClick(menuRef, toggleMenu);
const toggleDeleteModal = () => {
hideAll();
setDeleteModalVisible((prev) => !prev);
};
const alwaysVisible = menuVisible || emojiPopVisible;
const handleTippyVisible = (visible = true) => {
setTippyVisible(visible);
};
return (
<StyledCmds className={`cmds ${alwaysVisible ? "visible" : ""}`}>
<li className="cmd" onClick={toggleEmojiPopover}>
<img src={reactIcon} alt="icon emoji" />
</li>
{emojiPopVisible && (
<div className="picker">
<EmojiPicker mid={mid} hidePicker={toggleEmojiPopover} />
</div>
)}
<StyledCmds
ref={cmdsRef}
className={`cmds ${tippyVisible ? "visible" : ""}`}
>
<Tippy
onShow={handleTippyVisible.bind(null, true)}
onHide={handleTippyVisible.bind(null, false)}
interactive
placement="left-start"
trigger="click"
content={<EmojiPicker mid={mid} hidePicker={hideAll} />}
>
<li className="cmd">
<img src={reactIcon} className="toggler" alt="icon emoji" />
</li>
</Tippy>
{currUid == from_uid ? (
<li className="cmd" onClick={toggleEditMessage}>
<img src={editIcon} alt="icon edit" />
</li>
) : (
<li className="cmd" onClick={handleReply.bind(null, false)}>
<li className="cmd" onClick={handleReply}>
<img src={replyIcon} alt="icon reply" />
</li>
)}
<li className="cmd" onClick={toggleMenu}>
<img src={moreIcon} alt="icon emoji" />
</li>
{menuVisible && (
<StyledMenu className="menu" ref={menuRef}>
{/* <li className="item">Edit Message</li> */}
<li className="item underline">Pin Message</li>
<li className="item" onClick={handleReply.bind(null, true)}>
Reply
</li>
{currUid == from_uid && (
<li className="item danger" onClick={toggleDeleteModal}>
Delete Message
<Tippy
onShow={handleTippyVisible.bind(null, true)}
onHide={handleTippyVisible.bind(null, false)}
interactive
placement="right-start"
trigger="click"
content={
<StyledMenu className="menu">
{/* <li className="item">Edit Message</li> */}
<li className="item underline">Pin Message</li>
<li className="item" onClick={handleReply.bind(null, true)}>
Reply
</li>
)}
</StyledMenu>
)}
{currUid == from_uid && (
<li className="item danger" onClick={toggleDeleteModal}>
Delete Message
</li>
)}
</StyledMenu>
}
>
<li className="cmd">
<img src={moreIcon} alt="icon more" />
</li>
</Tippy>
{deleteModalVisible && (
<DeleteMessageConfirm closeModal={toggleDeleteModal} mid={mid} />
)}
+8 -12
View File
@@ -1,25 +1,25 @@
// import Picker from "../EmojiPicker";
import { useRef } from "react";
import styled from "styled-components";
import { useOutsideClick } from "rooks";
import { useSelector } from "react-redux";
import { useReactMessageMutation } from "../../../app/services/message";
import { Emojis } from "../../../app/config";
import Emoji from "../Emoji";
const StyledPicker = styled.div`
background-color: #fff;
background: none;
z-index: 999;
.emojis {
padding: 4px;
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 8px;
background: #ffffff;
background: #fff;
filter: drop-shadow(0px 25px 50px rgba(31, 41, 55, 0.25));
border-radius: 12px;
&.reacting {
opacity: 0.6;
}
.wrapper {
display: flex;
cursor: pointer;
border-radius: 8px;
padding: 4px;
@@ -36,7 +36,7 @@ const StyledPicker = styled.div`
`;
export default function EmojiPicker({ mid, hidePicker }) {
const wrapperRef = useRef(null);
// const wrapperRef = useRef(null);
const [reactMessage, { isLoading }] = useReactMessageMutation();
const { reactionData, currUid } = useSelector((store) => {
return {
@@ -44,18 +44,14 @@ export default function EmojiPicker({ mid, hidePicker }) {
currUid: store.authData.uid,
};
});
useOutsideClick(wrapperRef, hidePicker);
// useOutsideClick(wrapperRef, hidePicker);
const handleReact = (emoji) => {
console.log("react", emoji);
reactMessage({ mid, action: emoji });
hidePicker();
};
return (
<StyledPicker ref={wrapperRef}>
{/* <Picker
onSelect={handleReact}
className={`picker ${isLoading ? "reacting" : ""}`}
/> */}
<StyledPicker>
<ul className={`emojis ${isLoading ? "reacting" : ""}`}>
{Emojis.map((emoji) => {
let reacted =
+11 -18
View File
@@ -1,6 +1,8 @@
import { useState } from "react";
// import { useState } from "react";
import { useSelector } from "react-redux";
import styled from "styled-components";
import Tippy from "@tippyjs/react";
import { hideAll } from "tippy.js";
import Emoji from "../Emoji";
import EmojiPicker from "./EmojiPicker";
import { useReactMessageMutation } from "../../../app/services/message";
@@ -60,18 +62,11 @@ const StyledWrapper = styled.span`
background-color: #cff9fe;
}
}
.picker {
position: absolute;
right: 0;
top: 0;
transform: translateX(105%);
}
&:hover > .add {
visibility: visible;
}
`;
export default function Reaction({ mid, reactions = null }) {
const [pickerVisible, setPickerVisible] = useState(false);
const [reactWithEmoji] = useReactMessageMutation();
const { currUid } = useSelector((store) => {
return {
@@ -81,10 +76,6 @@ export default function Reaction({ mid, reactions = null }) {
const handleReact = (emoji) => {
reactWithEmoji({ mid, action: emoji });
};
const togglePickerVisible = (wtf) => {
console.log("clicked", wtf);
setPickerVisible((prev) => !prev);
};
console.log("curr reactions", reactions);
if (!reactions || Object.entries(reactions).length == 0) return null;
return (
@@ -108,12 +99,14 @@ export default function Reaction({ mid, reactions = null }) {
</span>
) : null;
})}
<button onClick={togglePickerVisible} className="add"></button>
{pickerVisible && (
<div className="picker">
<EmojiPicker mid={mid} hidePicker={togglePickerVisible} />
</div>
)}
<Tippy
interactive
placement="right-start"
trigger="click"
content={<EmojiPicker mid={mid} hidePicker={hideAll} />}
>
<button className="add"></button>
</Tippy>
</StyledWrapper>
);
}
+2 -1
View File
@@ -4,6 +4,7 @@ import { useSelector } from "react-redux";
import { ContentTypes } from "../../../app/config";
import Avatar from "../Avatar";
const Styled = styled.div`
cursor: pointer;
display: flex;
align-items: center;
padding: 16px;
@@ -68,7 +69,7 @@ export default function Reply({ mid }) {
const currUser = users[data.from_uid];
if (!currUser) return null;
return (
<Styled className="reply">
<Styled data-mid={mid} className="reply">
<div className="user">
<Avatar className="avatar" url={currUser.avatar} name={currUser.name} />
<span className="name">{currUser.name}</span>
+3 -15
View File
@@ -18,8 +18,7 @@ function Message({ contextId = 0, mid = "", context = "user" }) {
const updateReadDebounced = useDebounce(updateReadIndex, 300);
const [myRef, inView] = useInViewRef();
const [edit, setEdit] = useState(false);
const [emojiPopVisible, setEmojiPopVisible] = useState(false);
const [menuVisible, setMenuVisible] = useState(false);
const avatarRef = useRef(null);
const {
footprint,
@@ -36,15 +35,10 @@ function Message({ contextId = 0, mid = "", context = "user" }) {
contactsData: store.contacts.byId,
};
});
const toggleMenu = () => {
setMenuVisible((prev) => !prev);
};
const toggleEditMessage = () => {
setEdit((prev) => !prev);
};
const toggleEmojiPopover = () => {
setEmojiPopVisible((prev) => !prev);
};
const {
reply_mid,
@@ -78,9 +72,7 @@ function Message({ contextId = 0, mid = "", context = "user" }) {
<StyledWrapper
data-mid={mid}
ref={myRef}
className={`message ${menuVisible ? "menu" : ""} ${
inView ? "in_view" : ""
}`}
className={`message ${inView ? "in_view" : ""}`}
>
<Tippy
interactive
@@ -122,10 +114,6 @@ function Message({ contextId = 0, mid = "", context = "user" }) {
contextId={contextId}
mid={mid}
from_uid={fromUid}
toggleMenu={toggleMenu}
menuVisible={menuVisible}
emojiPopVisible={emojiPopVisible}
toggleEmojiPopover={toggleEmojiPopover}
toggleEditMessage={toggleEditMessage}
/>
)}
-3
View File
@@ -19,9 +19,6 @@ const StyledMsg = styled.div`
visibility: visible;
}
}
&.menu {
z-index: 9;
}
.avatar {
cursor: pointer;
img {
+1 -1
View File
@@ -3,7 +3,7 @@ import styled from "styled-components";
const StyledWrapper = styled.div`
width: 100%;
position: absolute;
bottom: 50px;
bottom: 64px;
left: 0;
padding: 8px;
display: flex;
+37 -38
View File
@@ -1,6 +1,9 @@
import { useState } from "react";
import styled from "styled-components";
import { useSelector } from "react-redux";
import Tippy from "@tippyjs/react";
import { hideAll } from "tippy.js";
import searchIcon from "../../assets/icons/search.svg?url";
import addIcon from "../../assets/icons/add.svg?url";
import mailIcon from "../../assets/icons/mail.svg?url";
@@ -42,9 +45,6 @@ const StyledWrapper = styled.div`
border-radius: 8px;
color: #616161;
background: #fff;
position: absolute;
top: 50px;
right: 8px;
display: flex;
flex-direction: column;
padding: 4px;
@@ -68,23 +68,21 @@ export default function Search() {
const currentUser = useSelector(
(store) => store.contacts.byId[store.authData.uid]
);
const [popupVisible, setPopupVisible] = useState(false);
const [channelModalVisible, setChannelModalVisible] = useState(false);
const [contactsModalVisible, setContactsModalVisible] = useState(false);
const [isPrivate, setIsPrivate] = useState(false);
const toggleContactsModalVisible = () => {
if (!contactsModalVisible) {
togglePopupVisible();
}
setContactsModalVisible((prev) => !prev);
};
const togglePopupVisible = () => {
setPopupVisible((prev) => !prev);
setContactsModalVisible((prevVisible) => {
if (!prevVisible) {
hideAll();
}
return !prevVisible;
});
};
const handleOpenChannelModal = (isPrivate) => {
setIsPrivate(isPrivate);
setChannelModalVisible(true);
togglePopupVisible();
hideAll();
};
const handleCloseModal = () => {
setChannelModalVisible(false);
@@ -102,36 +100,37 @@ export default function Search() {
<img src={searchIcon} />
<input placeholder="Search..." className="input" />
</div>
<img
src={addIcon}
alt="add icon"
className="add"
onClick={togglePopupVisible}
/>
{popupVisible && (
<ul className="popup">
{currentUser?.is_admin && (
<Tippy
interactive
placement="bottom-end"
trigger="click"
content={
<ul className="popup">
{currentUser?.is_admin && (
<li
className="item"
onClick={handleOpenChannelModal.bind(null, false)}
>
<ChannelIcon />
New Channel
</li>
)}
<li
className="item"
onClick={handleOpenChannelModal.bind(null, false)}
onClick={handleOpenChannelModal.bind(null, true)}
>
<ChannelIcon />
New Channel
<ChannelIcon personal={true} />
New Private Channel
</li>
)}
<li
className="item"
onClick={handleOpenChannelModal.bind(null, true)}
>
<ChannelIcon personal={true} />
New Private Channel
</li>
<li className="item" onClick={toggleContactsModalVisible}>
<img src={mailIcon} alt="icon mail" />
New Message
</li>
</ul>
)}
<li className="item" onClick={toggleContactsModalVisible}>
<img src={mailIcon} alt="icon mail" />
New Message
</li>
</ul>
}
>
<img src={addIcon} alt="add icon" className="add" />
</Tippy>
</StyledWrapper>
);
}
@@ -53,7 +53,7 @@ export default function UploadModal({
uploadFn({
id: sendTo,
content: files[0],
properties: btoa(JSON.stringify(properties[0])),
properties: { ...properties[0], local_id: new Date().getTime() },
type: "image",
from_uid,
});
+7 -1
View File
@@ -96,7 +96,12 @@ export default function Send({
});
dispatch(removeReplyingMessage(id));
} else {
sendMessage({ id, content: msg, from_uid });
sendMessage({
id,
content: msg,
from_uid,
properties: { local_id: new Date().getTime() },
});
}
setMsg("");
};
@@ -106,6 +111,7 @@ export default function Send({
id,
content: markdown,
from_uid,
properties: { local_id: new Date().getTime() },
type: "markdown",
});
setMarkdown("");
+86 -86
View File
@@ -1,3 +1,4 @@
import { useSelector } from "react-redux";
import MyAccount from "./MyAccount";
import Overview from "./Overview";
import ConfigFirebase from "./config/Firebase";
@@ -6,93 +7,92 @@ import Notifications from "./Notifications";
import ManageMembers from "../ManageMembers";
import FAQ from "../FAQ";
import ConfigAgora from "./config/Agora";
const navs = [
{
title: "General",
items: [
{
name: "overview",
title: "Overview",
component: <Overview />,
},
{
name: "members",
title: "Members",
component: <ManageMembers />,
admin: true,
},
{
name: "notification",
title: "Notification",
component: <Notifications />,
},
],
},
{
title: "User",
items: [
{
name: "my_account",
title: "My Account",
component: <MyAccount />,
},
],
},
{
title: "Configuration",
items: [
{
name: "firebase",
title: "Firebase",
component: <ConfigFirebase />,
},
{
name: "agora",
title: "Agora",
component: <ConfigAgora />,
},
{
name: "smtp",
title: "SMTP",
component: <ConfigSMTP />,
},
],
admin: true,
},
{
title: "About",
items: [
{
name: "faq",
title: "FAQ",
component: <FAQ />,
},
{
name: "terms",
title: "Terms & Privacy",
component: "Terms & Privacy",
},
{
name: "feedback",
title: "Feedback",
component: "feedback",
},
],
},
];
const useNavs = () => {
const navs = [
{
title: "General",
items: [
{
name: "overview",
title: "Overview",
component: <Overview />,
},
{
name: "roles",
title: "Roles",
},
{
name: "notification",
title: "Notification",
component: <Notifications />,
},
],
},
{
title: "User",
items: [
{
name: "my_account",
title: "My Account",
component: <MyAccount />,
},
{
name: "auth_apps",
title: "Authorized Apps",
},
],
},
{
title: "User Management",
items: [
{
name: "members",
title: "Members",
component: <ManageMembers />,
},
],
},
{
title: "Configuration",
items: [
{
name: "firebase",
title: "Firebase",
component: <ConfigFirebase />,
},
{
name: "agora",
title: "Agora",
component: <ConfigAgora />,
},
{
name: "smtp",
title: "SMTP",
component: <ConfigSMTP />,
},
],
},
{
title: "About",
items: [
{
name: "faq",
title: "FAQ",
component: <FAQ />,
},
{
name: "terms",
title: "Terms & Privacy",
component: "Terms & Privacy",
},
{
name: "feedback",
title: "Feedback",
component: "feedback",
},
],
},
];
return navs;
const loginUser = useSelector((store) => {
return store.contacts.byId[store.authData.uid];
});
const Navs = navs.filter((nav) => {
if (loginUser.is_admin) {
return true;
} else {
return !nav.admin;
}
});
return Navs;
};
export default useNavs;
@@ -85,7 +85,7 @@ export default function StyledSettingContainer({
};
return (
<Modal>
<StyledWrapper className="animate__animated animate__fadeInUp animate__faster">
<StyledWrapper>
<div className="left">
<h2 onClick={closeModal} className="title">
{title}
+1
View File
@@ -11,6 +11,7 @@ const StyledInput = styled.input`
color: #333;
padding: 8px;
&.none {
outline: none;
border: none;
background: none;
box-shadow: none;