chore: update prettier setting
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import styled from 'styled-components';
|
||||
import styled from "styled-components";
|
||||
const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
display: flex;
|
||||
`;
|
||||
|
||||
export default StyledWrapper;
|
||||
|
||||
@@ -96,9 +96,7 @@ export default function PinList({ id }) {
|
||||
{noPins ? (
|
||||
<div className="none">
|
||||
<IconSurprise />
|
||||
<div className="tip">
|
||||
This channel doesn’t have any pinned message yet.
|
||||
</div>
|
||||
<div className="tip">This channel doesn’t have any pinned message yet.</div>
|
||||
</div>
|
||||
) : (
|
||||
<ul className="list">
|
||||
@@ -115,11 +113,7 @@ export default function PinList({ id }) {
|
||||
<IconForward />
|
||||
</button> */}
|
||||
{canPin && (
|
||||
<button
|
||||
className="btn"
|
||||
data-mid={mid}
|
||||
onClick={handleUnpin}
|
||||
>
|
||||
<button className="btn" data-mid={mid} onClick={handleUnpin}>
|
||||
<IconClose />
|
||||
</button>
|
||||
)}
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
// StyledNotification,
|
||||
StyledContacts,
|
||||
StyledChannelChat,
|
||||
StyledHeader,
|
||||
StyledHeader
|
||||
} from "./styled";
|
||||
import InviteModal from "../../../common/component/InviteModal";
|
||||
import LoadMore from "../LoadMore";
|
||||
@@ -36,9 +36,14 @@ import LoadMore from "../LoadMore";
|
||||
|
||||
export default function ChannelChat({ cid = "", dropFiles = [] }) {
|
||||
const { values: agoraConfig } = useConfig("agora");
|
||||
const { list: msgIds, appends, hasMore, pullUp } = useMessageFeed({
|
||||
const {
|
||||
list: msgIds,
|
||||
appends,
|
||||
hasMore,
|
||||
pullUp
|
||||
} = useMessageFeed({
|
||||
context: "channel",
|
||||
id: cid,
|
||||
id: cid
|
||||
});
|
||||
// const scrollObserveRef = useChatScroll([msgIds, appends]);
|
||||
const [toolVisible, setToolVisible] = useState("");
|
||||
@@ -56,7 +61,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
|
||||
messageData,
|
||||
loginUid,
|
||||
loginUser,
|
||||
footprint,
|
||||
footprint
|
||||
} = useSelector((store) => {
|
||||
return {
|
||||
selects: store.ui.selectMessages[`channel_${cid}`],
|
||||
@@ -66,7 +71,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
|
||||
// msgIds: store.channelMessage[cid] || [],
|
||||
userIds: store.contacts.ids,
|
||||
data: store.channels.byId[cid] || {},
|
||||
messageData: store.message || {},
|
||||
messageData: store.message || {}
|
||||
};
|
||||
});
|
||||
// const ref = useChatScroll(msgIds);
|
||||
@@ -88,9 +93,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
|
||||
};
|
||||
if (!data) return null;
|
||||
const { name, description, is_public, members = [], owner } = data;
|
||||
const memberIds = is_public
|
||||
? userIds
|
||||
: members.slice(0).sort((n) => (n == owner ? -1 : 0));
|
||||
const memberIds = is_public ? userIds : members.slice(0).sort((n) => (n == owner ? -1 : 0));
|
||||
const addVisible = loginUser?.is_admin || owner == loginUid;
|
||||
console.log("channel message list", msgIds);
|
||||
const readIndex = footprint.readChannels[cid];
|
||||
@@ -98,9 +101,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
|
||||
const feeds = [...msgIds, ...appends];
|
||||
return (
|
||||
<>
|
||||
{addMemberModalVisible && (
|
||||
<InviteModal cid={cid} closeModal={toggleAddVisible} />
|
||||
)}
|
||||
{addMemberModalVisible && <InviteModal cid={cid} closeModal={toggleAddVisible} />}
|
||||
<Layout
|
||||
to={cid}
|
||||
context="channel"
|
||||
@@ -116,11 +117,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
|
||||
</Tooltip>
|
||||
</li>
|
||||
)}
|
||||
<Tooltip
|
||||
tip="Pin"
|
||||
placement="left"
|
||||
disabled={toolVisible == "pin"}
|
||||
>
|
||||
<Tooltip tip="Pin" placement="left" disabled={toolVisible == "pin"}>
|
||||
<Tippy
|
||||
onShow={() => {
|
||||
setToolVisible("pin");
|
||||
@@ -145,11 +142,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
|
||||
</li>
|
||||
</Tippy>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
tip="Favorite"
|
||||
placement="left"
|
||||
disabled={toolVisible == "favorite"}
|
||||
>
|
||||
<Tooltip tip="Favorite" placement="left" disabled={toolVisible == "favorite"}>
|
||||
<Tippy
|
||||
onShow={() => {
|
||||
setToolVisible("favorite");
|
||||
@@ -165,9 +158,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
|
||||
content={<FavList cid={cid} />}
|
||||
>
|
||||
<li
|
||||
className={`tool fav ${
|
||||
toolVisible == "favorite" ? "active" : ""
|
||||
} `}
|
||||
className={`tool fav ${toolVisible == "favorite" ? "active" : ""} `}
|
||||
data-count={pinCount}
|
||||
>
|
||||
<IconFav />
|
||||
@@ -246,10 +237,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
|
||||
<div className="info">
|
||||
<h2 className="title">Welcome to #{name} !</h2>
|
||||
<p className="desc">This is the start of the #{name} channel. </p>
|
||||
<NavLink
|
||||
to={`/setting/channel/${cid}?f=${pathname}`}
|
||||
className="edit"
|
||||
>
|
||||
<NavLink to={`/setting/channel/${cid}?f=${pathname}`} className="edit">
|
||||
<EditIcon className="icon" />
|
||||
Edit Channel
|
||||
</NavLink>
|
||||
@@ -270,7 +258,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
|
||||
prev,
|
||||
curr,
|
||||
contextId: cid,
|
||||
context: "channel",
|
||||
context: "channel"
|
||||
});
|
||||
})}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
|
||||
visible: contextMenuVisible,
|
||||
offset,
|
||||
handleContextMenuEvent,
|
||||
hideContextMenu,
|
||||
hideContextMenu
|
||||
} = useContextMenu();
|
||||
const {
|
||||
channel,
|
||||
@@ -37,7 +37,7 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
|
||||
messageData,
|
||||
readIndex,
|
||||
muted,
|
||||
loginUid,
|
||||
loginUid
|
||||
// loginUser,
|
||||
} = useSelector((store) => {
|
||||
return {
|
||||
@@ -47,7 +47,7 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
|
||||
messageData: store.message,
|
||||
loginUid: store.authData.uid,
|
||||
readIndex: store.footprint.readChannels[id],
|
||||
muted: store.footprint.muteChannels[id],
|
||||
muted: store.footprint.muteChannels[id]
|
||||
};
|
||||
});
|
||||
const handleChannelSetting = (evt) => {
|
||||
@@ -72,8 +72,8 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
|
||||
}
|
||||
},
|
||||
collect: (monitor) => ({
|
||||
isActive: monitor.canDrop() && monitor.isOver(),
|
||||
}),
|
||||
isActive: monitor.canDrop() && monitor.isOver()
|
||||
})
|
||||
}));
|
||||
const handleReadAll = () => {
|
||||
const lastMid = mids[mids.length - 1];
|
||||
@@ -91,9 +91,7 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
|
||||
setInviteModalVisible((prev) => !prev);
|
||||
};
|
||||
const handleMute = () => {
|
||||
const data = muted
|
||||
? { remove_groups: [id] }
|
||||
: { add_groups: [{ gid: id }] };
|
||||
const data = muted ? { remove_groups: [id] } : { add_groups: [{ gid: id }] };
|
||||
muteChannel(data);
|
||||
};
|
||||
const { is_public, name, owner } = channel;
|
||||
@@ -101,7 +99,7 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
|
||||
mids,
|
||||
messageData,
|
||||
readIndex,
|
||||
loginUid,
|
||||
loginUid
|
||||
});
|
||||
const isMentions = mentions.length !== 0;
|
||||
const inviteIconVisible = is_public || owner == loginUid;
|
||||
@@ -122,11 +120,11 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
|
||||
{
|
||||
title: "Mark As Read",
|
||||
underline: true,
|
||||
handler: handleReadAll,
|
||||
handler: handleReadAll
|
||||
},
|
||||
{
|
||||
title: muted ? "Unmute" : "Mute",
|
||||
handler: handleMute,
|
||||
handler: handleMute
|
||||
},
|
||||
// {
|
||||
// title: "Notification Settings",
|
||||
@@ -134,13 +132,13 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
|
||||
// },
|
||||
{
|
||||
title: "Invite People",
|
||||
handler: toggleInviteModalVisible,
|
||||
handler: toggleInviteModalVisible
|
||||
},
|
||||
{
|
||||
title: "Delete Channel",
|
||||
danger: true,
|
||||
handler: toggleRemoveConfirm.bind(null, id),
|
||||
},
|
||||
handler: toggleRemoveConfirm.bind(null, id)
|
||||
}
|
||||
]}
|
||||
/>
|
||||
}
|
||||
@@ -150,9 +148,7 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
|
||||
onContextMenu={handleContextMenuEvent}
|
||||
ref={drop}
|
||||
key={id}
|
||||
className={`link ${isActive ? "drop_over" : ""} ${
|
||||
muted ? "muted" : ""
|
||||
}`}
|
||||
className={`link ${isActive ? "drop_over" : ""} ${muted ? "muted" : ""}`}
|
||||
activeclassname="link_active"
|
||||
to={`/chat/channel/${id}`}
|
||||
>
|
||||
|
||||
@@ -20,25 +20,28 @@ import LoadMore from "../LoadMore";
|
||||
import { renderMessageFragment } from "../utils";
|
||||
import useMessageFeed from "../../../common/hook/useMessageFeed";
|
||||
export default function DMChat({ uid = "", dropFiles = [] }) {
|
||||
const { list: msgIds, appends, hasMore, pullUp } = useMessageFeed({
|
||||
const {
|
||||
list: msgIds,
|
||||
appends,
|
||||
hasMore,
|
||||
pullUp
|
||||
} = useMessageFeed({
|
||||
context: "user",
|
||||
id: uid,
|
||||
id: uid
|
||||
});
|
||||
const [updateReadIndex] = useReadMessageMutation();
|
||||
const updateReadDebounced = useDebounce(updateReadIndex, 300);
|
||||
console.log("dm files", dropFiles);
|
||||
// const [mids, setMids] = useState([]);
|
||||
const { currUser, messageData, footprint, loginUid, selects } = useSelector(
|
||||
(store) => {
|
||||
return {
|
||||
selects: store.ui.selectMessages[`user_${uid}`],
|
||||
loginUid: store.authData.uid,
|
||||
footprint: store.footprint,
|
||||
currUser: store.contacts.byId[uid],
|
||||
messageData: store.message,
|
||||
};
|
||||
}
|
||||
);
|
||||
const { currUser, messageData, footprint, loginUid, selects } = useSelector((store) => {
|
||||
return {
|
||||
selects: store.ui.selectMessages[`user_${uid}`],
|
||||
loginUid: store.authData.uid,
|
||||
footprint: store.footprint,
|
||||
currUser: store.contacts.byId[uid],
|
||||
messageData: store.message
|
||||
};
|
||||
});
|
||||
// const ref = useChatScroll(msgIds);
|
||||
|
||||
if (!currUser) return null;
|
||||
@@ -111,7 +114,7 @@ export default function DMChat({ uid = "", dropFiles = [] }) {
|
||||
prev,
|
||||
curr,
|
||||
contextId: uid,
|
||||
context: "user",
|
||||
context: "user"
|
||||
});
|
||||
})}
|
||||
</StyledDMChat>
|
||||
|
||||
@@ -18,25 +18,18 @@ import Contact from "../../../common/component/Contact";
|
||||
import { ContentTypes } from "../../../app/config";
|
||||
const NavItem = ({ uid, mid, unreads, setFiles }) => {
|
||||
const [previewMsg, setPreviewMsg] = useState(null);
|
||||
const {
|
||||
messages: normalizedMessages,
|
||||
normalizeMessage,
|
||||
} = useNormalizeMessage();
|
||||
const { messages: normalizedMessages, normalizeMessage } = useNormalizeMessage();
|
||||
const dispatch = useDispatch();
|
||||
const pathMatched = useMatch(`/chat/dm/${uid}`);
|
||||
const [updateReadIndex] = useReadMessageMutation();
|
||||
const { currMsg, currUser } = useSelector((store) => {
|
||||
return {
|
||||
currUser: store.contacts.byId[uid],
|
||||
currMsg: store.message[mid],
|
||||
currMsg: store.message[mid]
|
||||
};
|
||||
});
|
||||
const navigate = useNavigate();
|
||||
const {
|
||||
visible: contextMenuVisible,
|
||||
handleContextMenuEvent,
|
||||
hideContextMenu,
|
||||
} = useContextMenu();
|
||||
const { visible: contextMenuVisible, handleContextMenuEvent, hideContextMenu } = useContextMenu();
|
||||
const [{ isActive }, drop] = useDrop(() => ({
|
||||
accept: [NativeTypes.FILE],
|
||||
drop({ dataTransfer }) {
|
||||
@@ -51,8 +44,8 @@ const NavItem = ({ uid, mid, unreads, setFiles }) => {
|
||||
}
|
||||
},
|
||||
collect: (monitor) => ({
|
||||
isActive: monitor.canDrop() && monitor.isOver(),
|
||||
}),
|
||||
isActive: monitor.canDrop() && monitor.isOver()
|
||||
})
|
||||
}));
|
||||
useEffect(() => {
|
||||
if (currMsg) {
|
||||
@@ -96,13 +89,13 @@ const NavItem = ({ uid, mid, unreads, setFiles }) => {
|
||||
items={[
|
||||
{
|
||||
title: "Mark As Read",
|
||||
handler: handleReadAll,
|
||||
handler: handleReadAll
|
||||
},
|
||||
{
|
||||
title: "Hide Session",
|
||||
danger: true,
|
||||
handler: handleRemoveSession,
|
||||
},
|
||||
handler: handleRemoveSession
|
||||
}
|
||||
]}
|
||||
/>
|
||||
}
|
||||
@@ -118,9 +111,7 @@ const NavItem = ({ uid, mid, unreads, setFiles }) => {
|
||||
<div className="details">
|
||||
<div className="up">
|
||||
<span className="name">{currUser.name}</span>
|
||||
{previewMsg && (
|
||||
<time>{dayjs(previewMsg.created_at).fromNow()}</time>
|
||||
)}
|
||||
{previewMsg && <time>{dayjs(previewMsg.created_at).fromNow()}</time>}
|
||||
</div>
|
||||
|
||||
<div className="down">
|
||||
|
||||
@@ -5,17 +5,15 @@ import { getUnreadCount } from "../utils";
|
||||
|
||||
import NavItem from "./NavItem";
|
||||
export default function DMList({ uids, setDropFiles }) {
|
||||
const { userMessage, messageData, readUsers, loginUid } = useSelector(
|
||||
(store) => {
|
||||
return {
|
||||
loginUid: store.authData.uid,
|
||||
readUsers: store.footprint.readUsers,
|
||||
contactData: store.contacts.byId,
|
||||
userMessage: store.userMessage.byId,
|
||||
messageData: store.message,
|
||||
};
|
||||
}
|
||||
);
|
||||
const { userMessage, messageData, readUsers, loginUid } = useSelector((store) => {
|
||||
return {
|
||||
loginUid: store.authData.uid,
|
||||
readUsers: store.footprint.readUsers,
|
||||
contactData: store.contacts.byId,
|
||||
userMessage: store.userMessage.byId,
|
||||
messageData: store.message
|
||||
};
|
||||
});
|
||||
const sessions = uids.map((uid) => {
|
||||
const mids = userMessage[uid] || [];
|
||||
if (mids.length == 0) {
|
||||
@@ -27,7 +25,7 @@ export default function DMList({ uids, setDropFiles }) {
|
||||
mids,
|
||||
readIndex,
|
||||
messageData,
|
||||
loginUid,
|
||||
loginUid
|
||||
});
|
||||
|
||||
return { lastMid, unreads, uid };
|
||||
@@ -40,13 +38,7 @@ export default function DMList({ uids, setDropFiles }) {
|
||||
})
|
||||
.map(({ lastMid, uid, unreads }) => {
|
||||
return (
|
||||
<NavItem
|
||||
key={uid}
|
||||
uid={uid}
|
||||
mid={lastMid}
|
||||
unreads={unreads}
|
||||
setFiles={setDropFiles}
|
||||
/>
|
||||
<NavItem key={uid} uid={uid} mid={lastMid} unreads={unreads} setFiles={setDropFiles} />
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -97,9 +97,7 @@ export default function FavList({ cid = null, uid = null }) {
|
||||
{noFavs ? (
|
||||
<div className="none">
|
||||
<IconSurprise />
|
||||
<div className="tip">
|
||||
This channel doesn’t have any saved message yet.
|
||||
</div>
|
||||
<div className="tip">This channel doesn’t have any saved message yet.</div>
|
||||
</div>
|
||||
) : (
|
||||
<ul className="list">
|
||||
|
||||
@@ -44,9 +44,7 @@ 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 = useSelector((store) => store.ui.selectMessages[`${context}_${id}`]);
|
||||
const [forwardModalVisible, setForwardModalVisible] = useState(false);
|
||||
const dispatch = useDispatch();
|
||||
const handleClose = () => {
|
||||
@@ -86,18 +84,12 @@ export default function Operations({ context, id }) {
|
||||
<button className="opt" onClick={handleFav}>
|
||||
<IconBookmark />
|
||||
</button>
|
||||
<button
|
||||
className="opt"
|
||||
disabled={!canDel}
|
||||
onClick={toggleDeleteModal.bind(null, false)}
|
||||
>
|
||||
<button className="opt" disabled={!canDel} onClick={toggleDeleteModal.bind(null, false)}>
|
||||
<IconDelete />
|
||||
</button>
|
||||
<IconClose className="close" onClick={handleClose} />
|
||||
</Styled>
|
||||
{forwardModalVisible && (
|
||||
<ForwardModal mids={mids} closeModal={toggleForwardModal} />
|
||||
)}
|
||||
{forwardModalVisible && <ForwardModal mids={mids} closeModal={toggleForwardModal} />}
|
||||
{deleteModalVisible && (
|
||||
<DeleteMessageConfirmModal mids={mids} closeModal={toggleDeleteModal} />
|
||||
)}
|
||||
|
||||
@@ -17,7 +17,7 @@ export default function Layout({
|
||||
contacts = null,
|
||||
dropFiles = [],
|
||||
context = "channel",
|
||||
to = null,
|
||||
to = null
|
||||
}) {
|
||||
const { addStageFile } = useUploadFile({ context, id: to });
|
||||
const messagesContainer = useRef(undefined);
|
||||
@@ -26,7 +26,7 @@ export default function Layout({
|
||||
return {
|
||||
selects: store.ui.selectMessages[`${context}_${to}`],
|
||||
channelsData: store.channels.byId,
|
||||
contactsData: store.contacts.byId,
|
||||
contactsData: store.contacts.byId
|
||||
};
|
||||
});
|
||||
const [{ isActive }, drop] = useDrop(
|
||||
@@ -44,8 +44,8 @@ export default function Layout({
|
||||
}
|
||||
},
|
||||
collect: (monitor) => ({
|
||||
isActive: monitor.canDrop() && monitor.isOver(),
|
||||
}),
|
||||
isActive: monitor.canDrop() && monitor.isOver()
|
||||
})
|
||||
}),
|
||||
[context, to]
|
||||
);
|
||||
@@ -72,10 +72,7 @@ export default function Layout({
|
||||
(evt) => {
|
||||
console.log(evt);
|
||||
const { target } = evt;
|
||||
if (
|
||||
target.nodeName == "IMG" &&
|
||||
target.classList.contains("preview")
|
||||
) {
|
||||
if (target.nodeName == "IMG" && target.classList.contains("preview")) {
|
||||
const thumbnail = target.src;
|
||||
const originUrl = target.dataset.origin || target.src;
|
||||
const downloadLink = target.dataset.download || target.src;
|
||||
@@ -87,13 +84,10 @@ export default function Layout({
|
||||
);
|
||||
}
|
||||
}, []);
|
||||
const name =
|
||||
context == "channel" ? channelsData[to]?.name : contactsData[to]?.name;
|
||||
const name = context == "channel" ? channelsData[to]?.name : contactsData[to]?.name;
|
||||
return (
|
||||
<>
|
||||
{previewImage && (
|
||||
<ImagePreviewModal data={previewImage} closeModal={closePreviewModal} />
|
||||
)}
|
||||
{previewImage && <ImagePreviewModal data={previewImage} closeModal={closePreviewModal} />}
|
||||
<Styled ref={drop}>
|
||||
{header}
|
||||
<main className="main" ref={messagesContainer}>
|
||||
@@ -107,21 +101,11 @@ export default function Layout({
|
||||
{contacts && <div className="members">{contacts}</div>}
|
||||
{aside && <div className="aside">{aside}</div>}
|
||||
</main>
|
||||
<div
|
||||
className={`drag_tip ${
|
||||
isActive ? "visible animate__animated animate__fadeIn" : ""
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className={`box ${
|
||||
isActive ? "animate__animated animate__bounceIn" : ""
|
||||
}`}
|
||||
>
|
||||
<div className={`drag_tip ${isActive ? "visible animate__animated animate__fadeIn" : ""}`}>
|
||||
<div className={`box ${isActive ? "animate__animated animate__bounceIn" : ""}`}>
|
||||
<div className="inner">
|
||||
<h4 className="head">{`Send to ${ChatPrefixs[context]}${name}`}</h4>
|
||||
<span className="intro">
|
||||
Photos accept jpg, png, max size limit to 10M.
|
||||
</span>
|
||||
<span className="intro">Photos accept jpg, png, max size limit to 10M.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -40,13 +40,7 @@ export default function LoadMore({ pullUp = null }) {
|
||||
}, [ref, pullUp]);
|
||||
return (
|
||||
<Styled ref={ref}>
|
||||
<Waveform
|
||||
className="loading"
|
||||
size={24}
|
||||
lineWeight={5}
|
||||
speed={1}
|
||||
color="#ccc"
|
||||
/>
|
||||
<Waveform className="loading" size={24} lineWeight={5} speed={1} color="#ccc" />
|
||||
</Styled>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ export default function ChatPage() {
|
||||
const [userDropFiles, setUserDropFiles] = useState([]);
|
||||
const { sessionUids } = useSelector((store) => {
|
||||
return {
|
||||
sessionUids: store.userMessage.ids,
|
||||
sessionUids: store.userMessage.ids
|
||||
};
|
||||
});
|
||||
const [channelModalVisible, setChannelModalVisible] = useState(false);
|
||||
@@ -41,8 +41,7 @@ export default function ChatPage() {
|
||||
const listEle = currentTarget.parentElement.parentElement;
|
||||
listEle.classList.toggle("collapse");
|
||||
};
|
||||
const tmpUid =
|
||||
sessionUids.findIndex((i) => i == user_id) > -1 ? null : user_id;
|
||||
const tmpUid = sessionUids.findIndex((i) => i == user_id) > -1 ? null : user_id;
|
||||
// console.log("temp uid", tmpUid);
|
||||
const placeholderVisible = !channel_id && !user_id;
|
||||
return (
|
||||
@@ -50,27 +49,18 @@ export default function ChatPage() {
|
||||
{channelModalVisible && (
|
||||
<ChannelModal closeModal={toggleChannelModalVisible} personal={true} />
|
||||
)}
|
||||
{contactsModalVisible && (
|
||||
<ContactsModal closeModal={toggleContactsModalVisible} />
|
||||
)}
|
||||
{contactsModalVisible && <ContactsModal closeModal={toggleContactsModalVisible} />}
|
||||
<StyledWrapper>
|
||||
<div className="left">
|
||||
<Server />
|
||||
<div className="list channels">
|
||||
<h3 className="title">
|
||||
<span className="txt" onClick={handleToggleExpand}>
|
||||
<AiOutlineCaretDown
|
||||
className="icon"
|
||||
size={18}
|
||||
color="#78787C"
|
||||
/>
|
||||
<AiOutlineCaretDown className="icon" size={18} color="#78787C" />
|
||||
CHANNELS
|
||||
</span>
|
||||
<Tooltip tip="New Channel" placement="bottom">
|
||||
<AddIcon
|
||||
className="add_icon"
|
||||
onClick={toggleChannelModalVisible}
|
||||
/>
|
||||
<AddIcon className="add_icon" onClick={toggleChannelModalVisible} />
|
||||
</Tooltip>
|
||||
</h3>
|
||||
<nav className="nav">
|
||||
@@ -80,18 +70,11 @@ export default function ChatPage() {
|
||||
<div className="list dms">
|
||||
<h3 className="title">
|
||||
<span className="txt" onClick={handleToggleExpand}>
|
||||
<AiOutlineCaretDown
|
||||
className="icon"
|
||||
size={18}
|
||||
color="#78787C"
|
||||
/>
|
||||
<AiOutlineCaretDown className="icon" size={18} color="#78787C" />
|
||||
DIRECT MESSAGE
|
||||
</span>
|
||||
<Tooltip tip="New DM" placement="bottom">
|
||||
<AddIcon
|
||||
className="add_icon"
|
||||
onClick={toggleContactsModalVisible}
|
||||
/>
|
||||
<AddIcon className="add_icon" onClick={toggleContactsModalVisible} />
|
||||
</Tooltip>
|
||||
</h3>
|
||||
<nav className="nav">
|
||||
@@ -105,9 +88,7 @@ export default function ChatPage() {
|
||||
</div>
|
||||
<div className={`right ${placeholderVisible ? "placeholder" : ""}`}>
|
||||
{placeholderVisible && <BlankPlaceholder />}
|
||||
{channel_id && (
|
||||
<ChannelChat cid={channel_id} dropFiles={channelDropFiles} />
|
||||
)}
|
||||
{channel_id && <ChannelChat cid={channel_id} dropFiles={channelDropFiles} />}
|
||||
{user_id && <DMChat uid={user_id} dropFiles={userDropFiles} />}
|
||||
</div>
|
||||
</StyledWrapper>
|
||||
|
||||
@@ -20,12 +20,7 @@ import { updateSelectMessages } from "../../app/slices/ui";
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
export function getUnreadCount({
|
||||
mids = [],
|
||||
messageData = {},
|
||||
loginUid = 0,
|
||||
readIndex = 0,
|
||||
}) {
|
||||
export function getUnreadCount({ mids = [], messageData = {}, loginUid = 0, readIndex = 0 }) {
|
||||
// console.log({ mids, loginUid, readIndex });
|
||||
// 先过滤掉空信息和from自己的
|
||||
const others = mids.filter((mid) => {
|
||||
@@ -123,19 +118,10 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
}
|
||||
`;
|
||||
const MessageWrapper = ({
|
||||
selectMode = false,
|
||||
context,
|
||||
id,
|
||||
mid,
|
||||
children,
|
||||
...rest
|
||||
}) => {
|
||||
const MessageWrapper = ({ selectMode = false, context, id, mid, children, ...rest }) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const selects = useSelector(
|
||||
(store) => store.ui.selectMessages[`${context}_${id}`]
|
||||
);
|
||||
const selects = useSelector((store) => store.ui.selectMessages[`${context}_${id}`]);
|
||||
const selected = !!(selects && selects.find((s) => s == mid));
|
||||
const toggleSelect = () => {
|
||||
const operation = selected ? "remove" : "add";
|
||||
@@ -146,12 +132,7 @@ const MessageWrapper = ({
|
||||
<Checkbox className="check" checked={selected} />
|
||||
{/* {React.cloneElement(children, { readOnly: selected })} */}
|
||||
{children}
|
||||
{selectMode && (
|
||||
<div
|
||||
className="overlay"
|
||||
onClick={selectMode ? toggleSelect : null}
|
||||
></div>
|
||||
)}
|
||||
{selectMode && <div className="overlay" onClick={selectMode ? toggleSelect : null}></div>}
|
||||
</StyledWrapper>
|
||||
);
|
||||
};
|
||||
@@ -163,7 +144,7 @@ export const renderMessageFragment = ({
|
||||
prev = null,
|
||||
curr = null,
|
||||
contextId = 0,
|
||||
context = "user",
|
||||
context = "user"
|
||||
}) => {
|
||||
if (!curr) return null;
|
||||
let { created_at, mid } = curr;
|
||||
|
||||
+11
-20
@@ -14,12 +14,12 @@ const Filters = [
|
||||
{
|
||||
icon: <IconUnkown className="icon" />,
|
||||
title: "All Items",
|
||||
filter: "",
|
||||
filter: ""
|
||||
},
|
||||
{
|
||||
icon: <IconImage className="icon" />,
|
||||
title: "Images",
|
||||
filter: "image",
|
||||
filter: "image"
|
||||
},
|
||||
// {
|
||||
// icon: <IconDoc className="icon" />,
|
||||
@@ -29,13 +29,13 @@ const Filters = [
|
||||
{
|
||||
icon: <IconVideo className="icon" />,
|
||||
title: "Videos",
|
||||
filter: "video",
|
||||
filter: "video"
|
||||
},
|
||||
{
|
||||
icon: <IconAudio className="icon" />,
|
||||
title: "Audios",
|
||||
filter: "audio",
|
||||
},
|
||||
filter: "audio"
|
||||
}
|
||||
];
|
||||
function FavsPage() {
|
||||
const [filter, setFilter] = useState("");
|
||||
@@ -45,7 +45,7 @@ function FavsPage() {
|
||||
return {
|
||||
favorites: store.favorites,
|
||||
userData: store.contacts.byId,
|
||||
channelData: store.channels.byId,
|
||||
channelData: store.channels.byId
|
||||
};
|
||||
});
|
||||
const handleFilter = (ftr) => {
|
||||
@@ -64,10 +64,7 @@ function FavsPage() {
|
||||
const msgs = f.messages || [];
|
||||
return msgs.every((m) => {
|
||||
const file_type = m.properties?.content_type;
|
||||
return (
|
||||
m.content_type == ContentTypes.file &&
|
||||
file_type.startsWith("audio")
|
||||
);
|
||||
return m.content_type == ContentTypes.file && file_type.startsWith("audio");
|
||||
});
|
||||
})
|
||||
);
|
||||
@@ -80,10 +77,7 @@ function FavsPage() {
|
||||
const msgs = f.messages || [];
|
||||
return msgs.every((m) => {
|
||||
const file_type = m.properties?.content_type;
|
||||
return (
|
||||
m.content_type == ContentTypes.file &&
|
||||
file_type.startsWith("video")
|
||||
);
|
||||
return m.content_type == ContentTypes.file && file_type.startsWith("video");
|
||||
});
|
||||
})
|
||||
);
|
||||
@@ -106,10 +100,7 @@ function FavsPage() {
|
||||
const msgs = f.messages || [];
|
||||
return msgs.every((m) => {
|
||||
const file_type = m.properties?.content_type;
|
||||
return (
|
||||
m.content_type == ContentTypes.file &&
|
||||
file_type.startsWith("image")
|
||||
);
|
||||
return m.content_type == ContentTypes.file && file_type.startsWith("image");
|
||||
});
|
||||
});
|
||||
setFavs(tmps);
|
||||
@@ -144,8 +135,8 @@ function FavsPage() {
|
||||
{favs.map(({ id, created_at, messages }) => {
|
||||
const [
|
||||
{
|
||||
source: { gid, uid },
|
||||
},
|
||||
source: { gid, uid }
|
||||
}
|
||||
] = messages;
|
||||
const tip = gid ? (
|
||||
<span className="from channel">
|
||||
|
||||
@@ -48,9 +48,7 @@ export default function ServerDropList({ data, memberCount, expand = true }) {
|
||||
<img className="logo" src={data.logo} alt="logo" />
|
||||
{expand && (
|
||||
<div className="info">
|
||||
<h2 className="title animate__animated animate__fadeIn">
|
||||
{data.name}
|
||||
</h2>
|
||||
<h2 className="title animate__animated animate__fadeIn">{data.name}</h2>
|
||||
<span className="count">{memberCount} members</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -73,29 +73,19 @@ export default function Tools({ expand = true }) {
|
||||
alt="logo"
|
||||
/>
|
||||
</div>
|
||||
{expand && (
|
||||
<h2 className="title animate__animated animate__fadeIn">
|
||||
Webrowse
|
||||
</h2>
|
||||
)}
|
||||
{expand && <h2 className="title animate__animated animate__fadeIn">Webrowse</h2>}
|
||||
</li>
|
||||
<li className="tool">
|
||||
<div className="logo">
|
||||
<IoLogoGithub size={40} className="icon" />
|
||||
</div>
|
||||
{expand && (
|
||||
<h2 className="title animate__animated animate__fadeIn">Github</h2>
|
||||
)}
|
||||
{expand && <h2 className="title animate__animated animate__fadeIn">Github</h2>}
|
||||
</li>
|
||||
<li className="tool add">
|
||||
<div className="logo">
|
||||
<RiAddFill className="icon" size={40} color="#4B5563" />
|
||||
</div>
|
||||
{expand && (
|
||||
<h2 className="title animate__animated animate__fadeIn">
|
||||
Add new app
|
||||
</h2>
|
||||
)}
|
||||
{expand && <h2 className="title animate__animated animate__fadeIn">Add new app</h2>}
|
||||
</li>
|
||||
</ul>
|
||||
</StyledWrapper>
|
||||
|
||||
@@ -27,12 +27,12 @@ export default function HomePage() {
|
||||
loginUid,
|
||||
ui: {
|
||||
ready,
|
||||
remeberedNavs: { chat: chatPath, contact: contactPath },
|
||||
},
|
||||
remeberedNavs: { chat: chatPath, contact: contactPath }
|
||||
}
|
||||
} = useSelector((store) => {
|
||||
return {
|
||||
ui: store.ui,
|
||||
loginUid: store.authData.uid,
|
||||
loginUid: store.authData.uid
|
||||
};
|
||||
});
|
||||
const { loading } = usePreload();
|
||||
@@ -61,10 +61,7 @@ export default function HomePage() {
|
||||
<div className={`col left`}>
|
||||
<User uid={loginUid} />
|
||||
<nav className="link_navs">
|
||||
<NavLink
|
||||
className={`link ${isHomePath ? "active" : ""}`}
|
||||
to={chatNav}
|
||||
>
|
||||
<NavLink className={`link ${isHomePath ? "active" : ""}`} to={chatNav}>
|
||||
<Tooltip tip="Chat">
|
||||
<ChatIcon />
|
||||
</Tooltip>
|
||||
|
||||
@@ -22,8 +22,8 @@ export default function usePreload() {
|
||||
isLoading: favoritesLoading,
|
||||
isSuccess: favoritesSuccess,
|
||||
isError: favoritesError,
|
||||
data: favorites,
|
||||
},
|
||||
data: favorites
|
||||
}
|
||||
] = useLazyGetFavoritesQuery();
|
||||
const [
|
||||
getContacts,
|
||||
@@ -31,17 +31,12 @@ export default function usePreload() {
|
||||
isLoading: contactsLoading,
|
||||
isSuccess: contactsSuccess,
|
||||
isError: contactsError,
|
||||
data: contacts,
|
||||
},
|
||||
data: contacts
|
||||
}
|
||||
] = useLazyGetContactsQuery();
|
||||
const [
|
||||
getServer,
|
||||
{
|
||||
isLoading: serverLoading,
|
||||
isSuccess: serverSuccess,
|
||||
isError: serverError,
|
||||
data: server,
|
||||
},
|
||||
{ isLoading: serverLoading, isSuccess: serverSuccess, isError: serverError, data: server }
|
||||
] = useLazyGetServerQuery();
|
||||
useEffect(() => {
|
||||
initCache();
|
||||
@@ -64,14 +59,13 @@ export default function usePreload() {
|
||||
}, [canStreaming]);
|
||||
|
||||
return {
|
||||
loading:
|
||||
contactsLoading || serverLoading || favoritesLoading || !rehydrated,
|
||||
loading: contactsLoading || serverLoading || favoritesLoading || !rehydrated,
|
||||
error: contactsError && serverError && favoritesError,
|
||||
success: contactsSuccess && serverSuccess && favoritesSuccess,
|
||||
data: {
|
||||
contacts,
|
||||
server,
|
||||
favorites,
|
||||
},
|
||||
favorites
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ import store from "../app/store";
|
||||
const PageRoutes = () => {
|
||||
const {
|
||||
ui: { online },
|
||||
fileMessages,
|
||||
fileMessages
|
||||
} = useSelector((store) => {
|
||||
return { ui: store.ui, fileMessages: store.fileMessage };
|
||||
});
|
||||
|
||||
@@ -15,14 +15,9 @@ export default function InvitePage() {
|
||||
const [valid, setValid] = useState(false);
|
||||
// const [sp] = useSearchParams();
|
||||
// const navigateTo = useNavigate();
|
||||
const [
|
||||
register,
|
||||
{ data, isLoading, isSuccess, isError, error },
|
||||
] = useRegisterMutation();
|
||||
const [
|
||||
checkToken,
|
||||
{ data: isValid, isLoading: checkLoading, isSuccess: checkSuccess },
|
||||
] = useCheckInviteTokenValidMutation();
|
||||
const [register, { data, isLoading, isSuccess, isError, error }] = useRegisterMutation();
|
||||
const [checkToken, { data: isValid, isLoading: checkLoading, isSuccess: checkSuccess }] =
|
||||
useCheckInviteTokenValidMutation();
|
||||
useEffect(() => {
|
||||
// console.log(search);
|
||||
const query = new URLSearchParams(location.search);
|
||||
@@ -45,7 +40,7 @@ export default function InvitePage() {
|
||||
const [input, setInput] = useState({
|
||||
name: "",
|
||||
email: "",
|
||||
password: "",
|
||||
password: ""
|
||||
});
|
||||
|
||||
const handleReg = (evt) => {
|
||||
@@ -58,7 +53,7 @@ export default function InvitePage() {
|
||||
register({
|
||||
...input,
|
||||
magic_token: token,
|
||||
gender: 1,
|
||||
gender: 1
|
||||
});
|
||||
};
|
||||
const handleInput = (evt) => {
|
||||
@@ -105,7 +100,7 @@ export default function InvitePage() {
|
||||
case 409: {
|
||||
const tips = {
|
||||
email_conflict: "email conflict",
|
||||
name_conflict: "name conflict",
|
||||
name_conflict: "name conflict"
|
||||
};
|
||||
toast.error(`Register Failed: ${tips[error.data?.reason]}`);
|
||||
break;
|
||||
@@ -126,11 +121,7 @@ export default function InvitePage() {
|
||||
<StyledWrapper>
|
||||
<div className="form animate__animated animate__fadeInDown animate__faster">
|
||||
<div className="tips">
|
||||
<img
|
||||
src={`${BASE_URL}/resource/organization/logo`}
|
||||
alt="logo"
|
||||
className="logo"
|
||||
/>
|
||||
<img src={`${BASE_URL}/resource/organization/logo`} alt="logo" className="logo" />
|
||||
<h2 className="title">Sign Up to Rustchat</h2>
|
||||
<span className="desc">Please enter your details.</span>
|
||||
</div>
|
||||
@@ -170,11 +161,7 @@ export default function InvitePage() {
|
||||
onChange={handleSecondPwdInput}
|
||||
placeholder="Enter your password again"
|
||||
/>
|
||||
<button
|
||||
disabled={isLoading || isSuccess}
|
||||
className="btn"
|
||||
type="submit"
|
||||
>
|
||||
<button disabled={isLoading || isSuccess} className="btn" type="submit">
|
||||
Sign Up
|
||||
</button>
|
||||
</form>
|
||||
|
||||
+70
-70
@@ -1,75 +1,75 @@
|
||||
import styled from 'styled-components';
|
||||
import styled from "styled-components";
|
||||
const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
.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);
|
||||
border-radius: 12px;
|
||||
.tips {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-bottom: 24px;
|
||||
.logo {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
.title {
|
||||
font-weight: 600;
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
color: #101828;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
.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);
|
||||
border-radius: 12px;
|
||||
.tips {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-bottom: 24px;
|
||||
.logo {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
.title {
|
||||
font-weight: 600;
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
color: #101828;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
.desc {
|
||||
font-weight: normal;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #667085;
|
||||
}
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
input {
|
||||
width: 360px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #d0d5dd;
|
||||
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
|
||||
border-radius: 8px;
|
||||
padding: 10px 14px;
|
||||
font-weight: normal;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #667085;
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #ffffff;
|
||||
padding: 10px;
|
||||
background: #1fe1f9;
|
||||
border: 1px solid #1fe1f9;
|
||||
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
|
||||
border-radius: 8px;
|
||||
&.google {
|
||||
color: #344054;
|
||||
border-color: #d0d5dd;
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.desc {
|
||||
font-weight: normal;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #667085;
|
||||
}
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
input {
|
||||
width: 360px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #d0d5dd;
|
||||
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
|
||||
border-radius: 8px;
|
||||
padding: 10px 14px;
|
||||
font-weight: normal;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #667085;
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #ffffff;
|
||||
padding: 10px;
|
||||
background: #1fe1f9;
|
||||
border: 1px solid #1fe1f9;
|
||||
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
|
||||
border-radius: 8px;
|
||||
&.google {
|
||||
color: #344054;
|
||||
border-color: #d0d5dd;
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default StyledWrapper;
|
||||
|
||||
@@ -13,12 +13,12 @@ export default function GoogleLoginButton({ login, clientId }) {
|
||||
console.info("google oauth success", tokenId, rest);
|
||||
login({
|
||||
id_token: tokenId,
|
||||
type: "google",
|
||||
type: "google"
|
||||
});
|
||||
},
|
||||
onFailure: (wtf) => {
|
||||
console.error("google login failure", wtf);
|
||||
},
|
||||
}
|
||||
});
|
||||
const handleGoogleLogin = () => {
|
||||
signIn();
|
||||
|
||||
@@ -12,9 +12,5 @@ export default function MagicLinkLogin() {
|
||||
navigate("/send_magic_link");
|
||||
// signIn();
|
||||
};
|
||||
return (
|
||||
<StyledMagicButton onClick={handleGoogleLogin}>
|
||||
Sign in with Magic Link
|
||||
</StyledMagicButton>
|
||||
);
|
||||
return <StyledMagicButton onClick={handleGoogleLogin}>Sign in with Magic Link</StyledMagicButton>;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ export default function MetamaskLoginButton({ login }) {
|
||||
public_address: address,
|
||||
nonce,
|
||||
signature,
|
||||
type: "metamask",
|
||||
type: "metamask"
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -58,7 +58,7 @@ export default function MetamaskLoginButton({ login }) {
|
||||
console.log("get sn");
|
||||
const signature = await ethereum.request({
|
||||
method: "personal_sign",
|
||||
params: [nonce, address, "hello from rustchat"],
|
||||
params: [nonce, address, "hello from rustchat"]
|
||||
});
|
||||
return signature;
|
||||
};
|
||||
@@ -68,14 +68,14 @@ export default function MetamaskLoginButton({ login }) {
|
||||
setRequesting(true);
|
||||
try {
|
||||
const tmps = await ethereum.request({
|
||||
method: "eth_requestAccounts",
|
||||
method: "eth_requestAccounts"
|
||||
});
|
||||
setAccounts(tmps);
|
||||
} catch (error) {
|
||||
// toast.error(error.message);
|
||||
ethereum.request({
|
||||
method: "wallet_requestPermissions",
|
||||
params: [{ eth_accounts: {} }],
|
||||
params: [{ eth_accounts: {} }]
|
||||
});
|
||||
// setRequesting(false);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ export default function SolidLoginButton({ issuers }) {
|
||||
getOpenId({
|
||||
// issuer: "solidweb.org",
|
||||
issuer: issuers[0],
|
||||
redirect_uri: `${location.origin}/#/login`,
|
||||
redirect_uri: `${location.origin}/#/login`
|
||||
});
|
||||
};
|
||||
useEffect(() => {
|
||||
|
||||
+10
-24
@@ -11,10 +11,7 @@ import Button from "../../common/component/styled/Button";
|
||||
import GoogleLoginButton from "./GoogleLoginButton";
|
||||
import MagicLinkLogin from "./MagicLinkLogin";
|
||||
import { useLoginMutation } from "../../app/services/auth";
|
||||
import {
|
||||
useGetLoginConfigQuery,
|
||||
useGetSMTPStatusQuery,
|
||||
} from "../../app/services/server";
|
||||
import { useGetLoginConfigQuery, useGetSMTPStatusQuery } from "../../app/services/server";
|
||||
import useGoogleAuthConfig from "../../common/hook/useGoogleAuthConfig";
|
||||
import GithubLoginButton from "./GithubLoginButton";
|
||||
import useGithubAuthConfig from "../../common/hook/useGithubAuthConfig";
|
||||
@@ -23,13 +20,10 @@ export default function LoginPage() {
|
||||
const [login, { isSuccess, isLoading, error }] = useLoginMutation();
|
||||
const { clientId } = useGoogleAuthConfig();
|
||||
const { config: githubAuthConfig } = useGithubAuthConfig();
|
||||
const {
|
||||
data: loginConfig,
|
||||
isSuccess: loginConfigSuccess,
|
||||
} = useGetLoginConfigQuery();
|
||||
const { data: loginConfig, isSuccess: loginConfigSuccess } = useGetLoginConfigQuery();
|
||||
const [input, setInput] = useState({
|
||||
email: "",
|
||||
password: "",
|
||||
password: ""
|
||||
});
|
||||
useEffect(() => {
|
||||
const query = new URLSearchParams(location.search);
|
||||
@@ -45,7 +39,7 @@ export default function LoginPage() {
|
||||
if (code) {
|
||||
login({
|
||||
code: code,
|
||||
type: "github",
|
||||
type: "github"
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -54,7 +48,7 @@ export default function LoginPage() {
|
||||
login({
|
||||
code,
|
||||
state,
|
||||
type: "oidc",
|
||||
type: "oidc"
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -70,7 +64,7 @@ export default function LoginPage() {
|
||||
// login
|
||||
login({
|
||||
token,
|
||||
type: "magiclink",
|
||||
type: "magiclink"
|
||||
});
|
||||
} else {
|
||||
// reg
|
||||
@@ -111,7 +105,7 @@ export default function LoginPage() {
|
||||
console.log("wtf", input);
|
||||
login({
|
||||
...input,
|
||||
type: "password",
|
||||
type: "password"
|
||||
});
|
||||
};
|
||||
|
||||
@@ -131,25 +125,17 @@ export default function LoginPage() {
|
||||
github: enableGithubLogin,
|
||||
google: enableGoogleLogin,
|
||||
metamask: enableMetamaskLogin,
|
||||
oidc = [],
|
||||
oidc = []
|
||||
} = loginConfig;
|
||||
const enableMagicLink = enableSMTP && magic_link;
|
||||
const googleLogin = enableGoogleLogin && clientId;
|
||||
const hasDivider =
|
||||
enableMagicLink ||
|
||||
googleLogin ||
|
||||
enableMetamaskLogin ||
|
||||
oidc.length > 0 ||
|
||||
enableGithubLogin;
|
||||
enableMagicLink || googleLogin || enableMetamaskLogin || oidc.length > 0 || enableGithubLogin;
|
||||
return (
|
||||
<StyledWrapper>
|
||||
<div className="form">
|
||||
<div className="tips">
|
||||
<img
|
||||
src={`${BASE_URL}/resource/organization/logo`}
|
||||
alt="logo"
|
||||
className="logo"
|
||||
/>
|
||||
<img src={`${BASE_URL}/resource/organization/logo`} alt="logo" className="logo" />
|
||||
<h2 className="title">Login to Rustchat</h2>
|
||||
<span className="desc">Please enter your details.</span>
|
||||
</div>
|
||||
|
||||
@@ -23,8 +23,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: 0px 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;
|
||||
|
||||
@@ -8,10 +8,7 @@ import toast from "react-hot-toast";
|
||||
import { setAuthData } from "../../app/slices/auth.data";
|
||||
|
||||
export default function OAuthPage() {
|
||||
const [
|
||||
login,
|
||||
{ data, isSuccess, isError, error: loginError },
|
||||
] = useLoginMutation();
|
||||
const [login, { data, isSuccess, isError, error: loginError }] = useLoginMutation();
|
||||
const { token } = useParams();
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
+70
-70
@@ -1,75 +1,75 @@
|
||||
import styled from 'styled-components';
|
||||
import styled from "styled-components";
|
||||
const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
.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);
|
||||
border-radius: 12px;
|
||||
.tips {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-bottom: 24px;
|
||||
.logo {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
.title {
|
||||
font-weight: 600;
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
color: #101828;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
.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);
|
||||
border-radius: 12px;
|
||||
.tips {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-bottom: 24px;
|
||||
.logo {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
.title {
|
||||
font-weight: 600;
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
color: #101828;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
.desc {
|
||||
font-weight: normal;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #667085;
|
||||
}
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
input {
|
||||
width: 360px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #d0d5dd;
|
||||
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
|
||||
border-radius: 8px;
|
||||
padding: 10px 14px;
|
||||
font-weight: normal;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #667085;
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #ffffff;
|
||||
padding: 10px;
|
||||
background: #1fe1f9;
|
||||
border: 1px solid #1fe1f9;
|
||||
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
|
||||
border-radius: 8px;
|
||||
&.google {
|
||||
color: #344054;
|
||||
border-color: #d0d5dd;
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.desc {
|
||||
font-weight: normal;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #667085;
|
||||
}
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
input {
|
||||
width: 360px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #d0d5dd;
|
||||
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
|
||||
border-radius: 8px;
|
||||
padding: 10px 14px;
|
||||
font-weight: normal;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #667085;
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #ffffff;
|
||||
padding: 10px;
|
||||
background: #1fe1f9;
|
||||
border: 1px solid #1fe1f9;
|
||||
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
|
||||
border-radius: 8px;
|
||||
&.google {
|
||||
color: #344054;
|
||||
border-color: #d0d5dd;
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default StyledWrapper;
|
||||
|
||||
@@ -10,26 +10,26 @@ import CompletedStep from "./steps/6-completed";
|
||||
import StyledOnboardingPage from "./styled";
|
||||
|
||||
export default function OnboardingPage() {
|
||||
const [step, setStep] = useState(0);
|
||||
const [data, setData] = useState({
|
||||
serverName: ""
|
||||
});
|
||||
const props = { setStep, data, setData };
|
||||
const [step, setStep] = useState(0);
|
||||
const [data, setData] = useState({
|
||||
serverName: ""
|
||||
});
|
||||
const props = { setStep, data, setData };
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>Rustchat Setup</title>
|
||||
</Helmet>
|
||||
<StyledOnboardingPage>
|
||||
{step === 0 && <WelcomeStep {...props} />}
|
||||
{step === 1 && <ServerNameStep {...props} />}
|
||||
{step === 2 && <AdminCredentialsStep {...props} />}
|
||||
{step === 3 && <InviteRuleStep {...props} />}
|
||||
{step === 4 && <InviteLinkStep {...props} />}
|
||||
{step === 5 && <CompletedStep {...props} />}
|
||||
{step === 6 && <Navigate replace to="/" />}
|
||||
</StyledOnboardingPage>
|
||||
</>
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>Rustchat Setup</title>
|
||||
</Helmet>
|
||||
<StyledOnboardingPage>
|
||||
{step === 0 && <WelcomeStep {...props} />}
|
||||
{step === 1 && <ServerNameStep {...props} />}
|
||||
{step === 2 && <AdminCredentialsStep {...props} />}
|
||||
{step === 3 && <InviteRuleStep {...props} />}
|
||||
{step === 4 && <InviteLinkStep {...props} />}
|
||||
{step === 5 && <CompletedStep {...props} />}
|
||||
{step === 6 && <Navigate replace to="/" />}
|
||||
</StyledOnboardingPage>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,24 +3,24 @@ import StyledButton from "../../../common/component/styled/Button";
|
||||
import PlayIcon from "../../../assets/icons/play.svg?url";
|
||||
|
||||
const StyledFirstStep = styled.div`
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
export default function WelcomeStep({ setStep }) {
|
||||
return (
|
||||
<StyledFirstStep>
|
||||
<span className="primaryText">Welcome to your Rustchat!</span>
|
||||
<span className="secondaryText">
|
||||
Everything in this space is owned by you. Let’s set up your space!
|
||||
</span>
|
||||
<StyledButton className="startButton" onClick={() => setStep((prev) => prev + 1)}>
|
||||
<img src={PlayIcon} alt="play icon" />
|
||||
<span>Start</span>
|
||||
</StyledButton>
|
||||
</StyledFirstStep>
|
||||
);
|
||||
return (
|
||||
<StyledFirstStep>
|
||||
<span className="primaryText">Welcome to your Rustchat!</span>
|
||||
<span className="secondaryText">
|
||||
Everything in this space is owned by you. Let’s set up your space!
|
||||
</span>
|
||||
<StyledButton className="startButton" onClick={() => setStep((prev) => prev + 1)}>
|
||||
<img src={PlayIcon} alt="play icon" />
|
||||
<span>Start</span>
|
||||
</StyledButton>
|
||||
</StyledFirstStep>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,52 +4,52 @@ import StyledInput from "../../../common/component/styled/Input";
|
||||
import StyledButton from "../../../common/component/styled/Button";
|
||||
|
||||
const StyledSpaceNameStep = styled.div`
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
> .secondaryText {
|
||||
color: #667085;
|
||||
}
|
||||
> .secondaryText {
|
||||
color: #667085;
|
||||
}
|
||||
|
||||
> .button {
|
||||
margin-top: 24px;
|
||||
}
|
||||
> .button {
|
||||
margin-top: 24px;
|
||||
}
|
||||
`;
|
||||
|
||||
export default function ServerNameStep({ setStep, data, setData }) {
|
||||
return (
|
||||
<StyledSpaceNameStep>
|
||||
<span className="primaryText">Create a new server</span>
|
||||
<span className="secondaryText">
|
||||
Servers are shared environments where teams can work on projects and chat.
|
||||
</span>
|
||||
<StyledInput
|
||||
className="input"
|
||||
placeholder="Enter server name"
|
||||
value={data.serverName}
|
||||
onChange={(e) =>
|
||||
setData({
|
||||
...data,
|
||||
serverName: e.target.value
|
||||
})
|
||||
}
|
||||
/>
|
||||
<StyledButton
|
||||
className="button"
|
||||
onClick={() => {
|
||||
// Verification for space name
|
||||
if (data.serverName === "") {
|
||||
toast.error("Please enter server name!");
|
||||
return;
|
||||
}
|
||||
setStep((prev) => prev + 1);
|
||||
}}
|
||||
>
|
||||
Create Server
|
||||
</StyledButton>
|
||||
</StyledSpaceNameStep>
|
||||
);
|
||||
return (
|
||||
<StyledSpaceNameStep>
|
||||
<span className="primaryText">Create a new server</span>
|
||||
<span className="secondaryText">
|
||||
Servers are shared environments where teams can work on projects and chat.
|
||||
</span>
|
||||
<StyledInput
|
||||
className="input"
|
||||
placeholder="Enter server name"
|
||||
value={data.serverName}
|
||||
onChange={(e) =>
|
||||
setData({
|
||||
...data,
|
||||
serverName: e.target.value
|
||||
})
|
||||
}
|
||||
/>
|
||||
<StyledButton
|
||||
className="button"
|
||||
onClick={() => {
|
||||
// Verification for space name
|
||||
if (data.serverName === "") {
|
||||
toast.error("Please enter server name!");
|
||||
return;
|
||||
}
|
||||
setStep((prev) => prev + 1);
|
||||
}}
|
||||
>
|
||||
Create Server
|
||||
</StyledButton>
|
||||
</StyledSpaceNameStep>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,127 +5,127 @@ import { useDispatch } from "react-redux";
|
||||
import StyledInput from "../../../common/component/styled/Input";
|
||||
import StyledButton from "../../../common/component/styled/Button";
|
||||
import {
|
||||
useCreateAdminMutation,
|
||||
useGetServerQuery,
|
||||
useUpdateServerMutation
|
||||
useCreateAdminMutation,
|
||||
useGetServerQuery,
|
||||
useUpdateServerMutation
|
||||
} from "../../../app/services/server";
|
||||
import { useLoginMutation } from "../../../app/services/auth";
|
||||
import { updateInitialized } from "../../../app/slices/auth.data";
|
||||
|
||||
const StyledAdminCredentialsStep = styled.div`
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
> .input:not(:nth-last-child(2)) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
> .input:not(:nth-last-child(2)) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
> .button {
|
||||
margin-top: 24px;
|
||||
}
|
||||
> .button {
|
||||
margin-top: 24px;
|
||||
}
|
||||
`;
|
||||
|
||||
export default function AdminCredentialsStep({ data, setStep }) {
|
||||
const dispatch = useDispatch();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const [createAdmin, { isLoading: isSigningUp, error: signUpError }] = useCreateAdminMutation();
|
||||
const [login, { isLoading: isLoggingIn, isSuccess: isLoggedIn, error: loginError }] =
|
||||
useLoginMutation();
|
||||
const { data: serverData } = useGetServerQuery();
|
||||
const [updateServer, { isLoading: isUpdatingServer, isSuccess: isUpdatedServer }] =
|
||||
useUpdateServerMutation();
|
||||
const [createAdmin, { isLoading: isSigningUp, error: signUpError }] = useCreateAdminMutation();
|
||||
const [login, { isLoading: isLoggingIn, isSuccess: isLoggedIn, error: loginError }] =
|
||||
useLoginMutation();
|
||||
const { data: serverData } = useGetServerQuery();
|
||||
const [updateServer, { isLoading: isUpdatingServer, isSuccess: isUpdatedServer }] =
|
||||
useUpdateServerMutation();
|
||||
|
||||
const [email, setEmail] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [confirm, setConfirm] = useState("");
|
||||
const [email, setEmail] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [confirm, setConfirm] = useState("");
|
||||
|
||||
// Display error
|
||||
useEffect(() => {
|
||||
if (signUpError === undefined) return;
|
||||
toast.error(`Failed to sign up: ${signUpError.data}`);
|
||||
}, [signUpError]);
|
||||
useEffect(() => {
|
||||
if (loginError === undefined) return;
|
||||
toast.error(`Login failed: ${loginError.data}`);
|
||||
}, [loginError]);
|
||||
// Display error
|
||||
useEffect(() => {
|
||||
if (signUpError === undefined) return;
|
||||
toast.error(`Failed to sign up: ${signUpError.data}`);
|
||||
}, [signUpError]);
|
||||
useEffect(() => {
|
||||
if (loginError === undefined) return;
|
||||
toast.error(`Login failed: ${loginError.data}`);
|
||||
}, [loginError]);
|
||||
|
||||
// After logged in
|
||||
useEffect(() => {
|
||||
if (isLoggedIn) {
|
||||
dispatch(updateInitialized(true));
|
||||
setTimeout(() => {
|
||||
// Set server name
|
||||
updateServer({
|
||||
...serverData,
|
||||
name: data.serverName
|
||||
});
|
||||
}, 0);
|
||||
}
|
||||
}, [isLoggedIn]);
|
||||
// After logged in
|
||||
useEffect(() => {
|
||||
if (isLoggedIn) {
|
||||
dispatch(updateInitialized(true));
|
||||
setTimeout(() => {
|
||||
// Set server name
|
||||
updateServer({
|
||||
...serverData,
|
||||
name: data.serverName
|
||||
});
|
||||
}, 0);
|
||||
}
|
||||
}, [isLoggedIn]);
|
||||
|
||||
// After updated server
|
||||
useEffect(() => {
|
||||
if (isUpdatedServer) {
|
||||
setStep((prev) => prev + 1);
|
||||
}
|
||||
}, [isUpdatedServer]);
|
||||
// After updated server
|
||||
useEffect(() => {
|
||||
if (isUpdatedServer) {
|
||||
setStep((prev) => prev + 1);
|
||||
}
|
||||
}, [isUpdatedServer]);
|
||||
|
||||
return (
|
||||
<StyledAdminCredentialsStep>
|
||||
<span className="primaryText">Now let’s set up your admin account</span>
|
||||
<span className="secondaryText">You are the 1st user and admin of your space!</span>
|
||||
<StyledInput
|
||||
className="input"
|
||||
placeholder="Enter your email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
/>
|
||||
<StyledInput
|
||||
className="input"
|
||||
type="password"
|
||||
placeholder="Enter your password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
/>
|
||||
<StyledInput
|
||||
className="input"
|
||||
type="password"
|
||||
placeholder="Confirm your password"
|
||||
value={confirm}
|
||||
onChange={(e) => setConfirm(e.target.value)}
|
||||
/>
|
||||
<StyledButton
|
||||
className="button"
|
||||
onClick={async () => {
|
||||
// Verification for admin credentials
|
||||
if (email === "") {
|
||||
toast.error("Please enter admin email!");
|
||||
return;
|
||||
} else if (password === "") {
|
||||
toast.error("Please enter admin password!");
|
||||
return;
|
||||
} else if (password !== confirm) {
|
||||
toast.error("Two passwords do not match!");
|
||||
return;
|
||||
}
|
||||
await createAdmin({
|
||||
email,
|
||||
name: "Admin",
|
||||
password,
|
||||
gender: 0
|
||||
});
|
||||
await login({
|
||||
email,
|
||||
password,
|
||||
type: "password"
|
||||
});
|
||||
}}
|
||||
>
|
||||
{!(isSigningUp || isLoggingIn || isUpdatingServer) ? "Sign Up" : "..."}
|
||||
</StyledButton>
|
||||
</StyledAdminCredentialsStep>
|
||||
);
|
||||
return (
|
||||
<StyledAdminCredentialsStep>
|
||||
<span className="primaryText">Now let’s set up your admin account</span>
|
||||
<span className="secondaryText">You are the 1st user and admin of your space!</span>
|
||||
<StyledInput
|
||||
className="input"
|
||||
placeholder="Enter your email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
/>
|
||||
<StyledInput
|
||||
className="input"
|
||||
type="password"
|
||||
placeholder="Enter your password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
/>
|
||||
<StyledInput
|
||||
className="input"
|
||||
type="password"
|
||||
placeholder="Confirm your password"
|
||||
value={confirm}
|
||||
onChange={(e) => setConfirm(e.target.value)}
|
||||
/>
|
||||
<StyledButton
|
||||
className="button"
|
||||
onClick={async () => {
|
||||
// Verification for admin credentials
|
||||
if (email === "") {
|
||||
toast.error("Please enter admin email!");
|
||||
return;
|
||||
} else if (password === "") {
|
||||
toast.error("Please enter admin password!");
|
||||
return;
|
||||
} else if (password !== confirm) {
|
||||
toast.error("Two passwords do not match!");
|
||||
return;
|
||||
}
|
||||
await createAdmin({
|
||||
email,
|
||||
name: "Admin",
|
||||
password,
|
||||
gender: 0
|
||||
});
|
||||
await login({
|
||||
email,
|
||||
password,
|
||||
type: "password"
|
||||
});
|
||||
}}
|
||||
>
|
||||
{!(isSigningUp || isLoggingIn || isUpdatingServer) ? "Sign Up" : "..."}
|
||||
</StyledButton>
|
||||
</StyledAdminCredentialsStep>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,55 +6,58 @@ import StyledButton from "../../../common/component/styled/Button";
|
||||
import { useGetLoginConfigQuery, useUpdateLoginConfigMutation } from "../../../app/services/server";
|
||||
|
||||
const StyledInviteRuleStep = styled.div`
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
> .input:not(:nth-last-child(2)) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
> .input:not(:nth-last-child(2)) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
`;
|
||||
|
||||
export default function InviteRuleStep({ setStep }) {
|
||||
const { data: loginConfig } = useGetLoginConfigQuery();
|
||||
const [updateLoginConfig, { isSuccess, error }] = useUpdateLoginConfigMutation();
|
||||
const { data: loginConfig } = useGetLoginConfigQuery();
|
||||
const [updateLoginConfig, { isSuccess, error }] = useUpdateLoginConfigMutation();
|
||||
|
||||
const [value, setValue] = useState(0);
|
||||
const [value, setValue] = useState(0);
|
||||
|
||||
// Display error
|
||||
useEffect(() => {
|
||||
if (error === undefined) return;
|
||||
toast.error(`Failed to update invitation rule: ${error.data}`);
|
||||
}, [error]);
|
||||
// Display error
|
||||
useEffect(() => {
|
||||
if (error === undefined) return;
|
||||
toast.error(`Failed to update invitation rule: ${error.data}`);
|
||||
}, [error]);
|
||||
|
||||
// Increment `step` when updating has completed
|
||||
useEffect(() => {
|
||||
if (isSuccess) setStep((prev) => prev + 1);
|
||||
}, [isSuccess]);
|
||||
// Increment `step` when updating has completed
|
||||
useEffect(() => {
|
||||
if (isSuccess) setStep((prev) => prev + 1);
|
||||
}, [isSuccess]);
|
||||
|
||||
return (
|
||||
<StyledInviteRuleStep>
|
||||
<span className="primaryText">Last step: invite others!</span>
|
||||
<span className="secondaryText">Firstly, who can sign up to this server?</span>
|
||||
<StyledRadio
|
||||
options={["Everyone", "Invitation link only"]}
|
||||
value={value}
|
||||
onChange={async (v) => {
|
||||
setValue(v);
|
||||
if (loginConfig !== undefined) {
|
||||
const whoCanSignUp = ["EveryOne", "InvitationOnly"][v];
|
||||
await updateLoginConfig({
|
||||
...loginConfig,
|
||||
who_can_sign_up: whoCanSignUp
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<StyledButton className="button border_less ghost" onClick={() => setStep((prev) => prev + 1)}>
|
||||
Skip
|
||||
</StyledButton>
|
||||
</StyledInviteRuleStep>
|
||||
);
|
||||
return (
|
||||
<StyledInviteRuleStep>
|
||||
<span className="primaryText">Last step: invite others!</span>
|
||||
<span className="secondaryText">Firstly, who can sign up to this server?</span>
|
||||
<StyledRadio
|
||||
options={["Everyone", "Invitation link only"]}
|
||||
value={value}
|
||||
onChange={async (v) => {
|
||||
setValue(v);
|
||||
if (loginConfig !== undefined) {
|
||||
const whoCanSignUp = ["EveryOne", "InvitationOnly"][v];
|
||||
await updateLoginConfig({
|
||||
...loginConfig,
|
||||
who_can_sign_up: whoCanSignUp
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<StyledButton
|
||||
className="button border_less ghost"
|
||||
onClick={() => setStep((prev) => prev + 1)}
|
||||
>
|
||||
Skip
|
||||
</StyledButton>
|
||||
</StyledInviteRuleStep>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,70 +4,73 @@ import StyledButton from "../../../common/component/styled/Button";
|
||||
import useInviteLink from "../../../common/hook/useInviteLink";
|
||||
|
||||
const StyledInviteLinkStep = styled.div`
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
> .secondaryText {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
> .tip {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #475467;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
> .link {
|
||||
position: relative;
|
||||
background: #ffffff;
|
||||
border: 1px solid #f4f4f5;
|
||||
box-shadow: 0 1px 2px rgba(31, 41, 55, 0.08);
|
||||
border-radius: 4px;
|
||||
width: 374px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
> input {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
padding: 11px 0 11px 8px;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #78787c;
|
||||
> .secondaryText {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
> button {
|
||||
padding: 0 8px;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #22ccee;
|
||||
> .tip {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #475467;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
> .link {
|
||||
position: relative;
|
||||
background: #ffffff;
|
||||
border: 1px solid #f4f4f5;
|
||||
box-shadow: 0 1px 2px rgba(31, 41, 55, 0.08);
|
||||
border-radius: 4px;
|
||||
width: 374px;
|
||||
display: flex;
|
||||
|
||||
> input {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
padding: 11px 0 11px 8px;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #78787c;
|
||||
}
|
||||
|
||||
> button {
|
||||
padding: 0 8px;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #22ccee;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default function InviteLinkStep({ setStep }) {
|
||||
const { link, linkCopied, copyLink } = useInviteLink();
|
||||
const { link, linkCopied, copyLink } = useInviteLink();
|
||||
|
||||
return (
|
||||
<StyledInviteLinkStep>
|
||||
<span className="primaryText">Last step: invite others!</span>
|
||||
<span className="secondaryText">Now let’s invite others!</span>
|
||||
<span className="tip">Send invitation link to your future community members:</span>
|
||||
<div className="link">
|
||||
<StyledInput className="large" readOnly placeholder="Generating" value={link} />
|
||||
<StyledButton onClick={copyLink} className="ghost small border_less">
|
||||
{linkCopied ? "Copied" : `Copy`}
|
||||
</StyledButton>
|
||||
</div>
|
||||
<StyledButton className="button border_less ghost" onClick={() => setStep((prev) => prev + 1)}>
|
||||
Skip
|
||||
</StyledButton>
|
||||
</StyledInviteLinkStep>
|
||||
);
|
||||
return (
|
||||
<StyledInviteLinkStep>
|
||||
<span className="primaryText">Last step: invite others!</span>
|
||||
<span className="secondaryText">Now let’s invite others!</span>
|
||||
<span className="tip">Send invitation link to your future community members:</span>
|
||||
<div className="link">
|
||||
<StyledInput className="large" readOnly placeholder="Generating" value={link} />
|
||||
<StyledButton onClick={copyLink} className="ghost small border_less">
|
||||
{linkCopied ? "Copied" : `Copy`}
|
||||
</StyledButton>
|
||||
</div>
|
||||
<StyledButton
|
||||
className="button border_less ghost"
|
||||
onClick={() => setStep((prev) => prev + 1)}
|
||||
>
|
||||
Skip
|
||||
</StyledButton>
|
||||
</StyledInviteLinkStep>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,42 +3,42 @@ import StyledButton from "../../../common/component/styled/Button";
|
||||
import PlayIcon from "../../../assets/icons/play.svg?url";
|
||||
|
||||
const StyledLastStep = styled.div`
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
> .secondaryText {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
> .tip {
|
||||
width: 560px;
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
margin-bottom: 96px;
|
||||
|
||||
> .strong {
|
||||
font-weight: 700;
|
||||
> .secondaryText {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
> .tip {
|
||||
width: 560px;
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
margin-bottom: 96px;
|
||||
|
||||
> .strong {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default function CompletedStep({ data, setStep }) {
|
||||
return (
|
||||
<StyledLastStep>
|
||||
<span className="primaryText">Welcome to {data.serverName}</span>
|
||||
<span className="secondaryText">Proudly presented by Rustchat</span>
|
||||
<span className="tip">
|
||||
More settings, including domain resolution, privileges, securities, and invites are available in{" "}
|
||||
<span className="strong">Settings</span>
|
||||
</span>
|
||||
<StyledButton className="startButton" onClick={() => setStep((prev) => prev + 1)}>
|
||||
<img src={PlayIcon} alt="play icon" />
|
||||
<span>Enter</span>
|
||||
</StyledButton>
|
||||
</StyledLastStep>
|
||||
);
|
||||
return (
|
||||
<StyledLastStep>
|
||||
<span className="primaryText">Welcome to {data.serverName}</span>
|
||||
<span className="secondaryText">Proudly presented by Rustchat</span>
|
||||
<span className="tip">
|
||||
More settings, including domain resolution, privileges, securities, and invites are
|
||||
available in <span className="strong">Settings</span>
|
||||
</span>
|
||||
<StyledButton className="startButton" onClick={() => setStep((prev) => prev + 1)}>
|
||||
<img src={PlayIcon} alt="play icon" />
|
||||
<span>Enter</span>
|
||||
</StyledButton>
|
||||
</StyledLastStep>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,75 +1,75 @@
|
||||
import styled from "styled-components";
|
||||
|
||||
const StyledOnboardingPage = styled.div`
|
||||
height: 100vh;
|
||||
overflow-y: auto;
|
||||
height: 100vh;
|
||||
overflow-y: auto;
|
||||
|
||||
// shared with child components
|
||||
.primaryText,
|
||||
.secondaryText {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.primaryText {
|
||||
font-weight: 700;
|
||||
font-size: 24px;
|
||||
line-height: 30px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.secondaryText {
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.startButton {
|
||||
width: 128px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 15px 0 12px;
|
||||
|
||||
> img {
|
||||
margin-bottom: 7px;
|
||||
// shared with child components
|
||||
.primaryText,
|
||||
.secondaryText {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
> span {
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
.primaryText {
|
||||
font-weight: 700;
|
||||
font-size: 24px;
|
||||
line-height: 30px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
width: 360px;
|
||||
height: 44px;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
input.input {
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
padding: 10px 14px;
|
||||
border: 1px solid #d0d5dd;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 1px 2px rgba(16, 24, 40, 0.05);
|
||||
}
|
||||
|
||||
.button {
|
||||
width: 360px;
|
||||
|
||||
&.ghost.border_less {
|
||||
width: fit-content;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #98a2b3;
|
||||
margin-top: 14px;
|
||||
.secondaryText {
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.startButton {
|
||||
width: 128px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 15px 0 12px;
|
||||
|
||||
> img {
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
|
||||
> span {
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
width: 360px;
|
||||
height: 44px;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
input.input {
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
padding: 10px 14px;
|
||||
border: 1px solid #d0d5dd;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 1px 2px rgba(16, 24, 40, 0.05);
|
||||
}
|
||||
|
||||
.button {
|
||||
width: 360px;
|
||||
|
||||
&.ghost.border_less {
|
||||
width: fit-content;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #98a2b3;
|
||||
margin-top: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default StyledOnboardingPage;
|
||||
|
||||
@@ -26,9 +26,7 @@ export default function ExpiredTip() {
|
||||
return (
|
||||
<Styled>
|
||||
<div className="title">Magic link expired</div>
|
||||
<p className="desc">
|
||||
Go back to your original Rustchat tab and request a new magic link.
|
||||
</p>
|
||||
<p className="desc">Go back to your original Rustchat tab and request a new magic link.</p>
|
||||
<p className="desc">You can close this window now.</p>
|
||||
</Styled>
|
||||
);
|
||||
|
||||
@@ -8,19 +8,14 @@ import { setAuthData } from "../../app/slices/auth.data";
|
||||
|
||||
import Input from "../../common/component/styled/Input";
|
||||
import Button from "../../common/component/styled/Button";
|
||||
import {
|
||||
useLoginMutation,
|
||||
useCheckInviteTokenValidMutation,
|
||||
} from "../../app/services/auth";
|
||||
import { useLoginMutation, useCheckInviteTokenValidMutation } from "../../app/services/auth";
|
||||
import toast from "react-hot-toast";
|
||||
import ExpiredTip from "./ExpiredTip";
|
||||
|
||||
export default function RegWithUsername() {
|
||||
const { token } = useParams();
|
||||
const [
|
||||
checkTokenInvalid,
|
||||
{ data: isTokenValid, isLoading: checkingToken },
|
||||
] = useCheckInviteTokenValidMutation();
|
||||
const [checkTokenInvalid, { data: isTokenValid, isLoading: checkingToken }] =
|
||||
useCheckInviteTokenValidMutation();
|
||||
const [login, { isLoading, error, isSuccess, data }] = useLoginMutation();
|
||||
// const navigateTo = useNavigate();
|
||||
const dispatch = useDispatch();
|
||||
@@ -57,7 +52,7 @@ export default function RegWithUsername() {
|
||||
login({
|
||||
token,
|
||||
username,
|
||||
type: "magiclink",
|
||||
type: "magiclink"
|
||||
});
|
||||
// sendMagicLink(email);
|
||||
};
|
||||
@@ -74,8 +69,8 @@ export default function RegWithUsername() {
|
||||
<div className="tips">
|
||||
<h2 className="title">What’s your name</h2>
|
||||
<span className="desc">
|
||||
Enter a name or handle so people know how you’d like to be called.
|
||||
Your name will only be visible to others in spaces you joined.
|
||||
Enter a name or handle so people know how you’d like to be called. Your name will only be
|
||||
visible to others in spaces you joined.
|
||||
</span>
|
||||
</div>
|
||||
<form onSubmit={handleLogin}>
|
||||
|
||||
@@ -7,8 +7,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: 0px 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;
|
||||
|
||||
@@ -70,11 +70,7 @@ export default function Channel({ select = "", updateFilter }) {
|
||||
</li>
|
||||
{channels.map(({ gid, is_public, name }) => {
|
||||
return (
|
||||
<li
|
||||
key={gid}
|
||||
className="channel"
|
||||
onClick={handleClick.bind(null, gid)}
|
||||
>
|
||||
<li key={gid} className="channel" onClick={handleClick.bind(null, gid)}>
|
||||
<ChannelIcon personal={!is_public} />
|
||||
<span className="name">{name}</span>
|
||||
{select == gid && <CheckSign className="check" />}
|
||||
|
||||
@@ -42,20 +42,20 @@ const Styled = styled.div`
|
||||
export const Dates = {
|
||||
today: {
|
||||
title: "Today",
|
||||
duration: 2222,
|
||||
duration: 2222
|
||||
},
|
||||
in7d: {
|
||||
title: "Last 7 Days",
|
||||
title: "Last 7 Days"
|
||||
},
|
||||
in30d: {
|
||||
title: "Last 30 Days",
|
||||
title: "Last 30 Days"
|
||||
},
|
||||
in3m: {
|
||||
title: "Last 3 months",
|
||||
title: "Last 3 months"
|
||||
},
|
||||
in12m: {
|
||||
title: "Last 12 months",
|
||||
},
|
||||
title: "Last 12 months"
|
||||
}
|
||||
};
|
||||
export default function Date({ select = "", updateFilter }) {
|
||||
// const { input, updateInput, contacts } = useFilteredUsers();
|
||||
@@ -75,11 +75,7 @@ export default function Date({ select = "", updateFilter }) {
|
||||
</li>
|
||||
{Object.entries(Dates).map(([_key, { title }]) => {
|
||||
return (
|
||||
<li
|
||||
key={title}
|
||||
className="date"
|
||||
onClick={handleClick.bind(null, _key)}
|
||||
>
|
||||
<li key={title} className="date" onClick={handleClick.bind(null, _key)}>
|
||||
{title}
|
||||
{select == _key && <CheckSign className="check" />}
|
||||
</li>
|
||||
|
||||
@@ -64,20 +64,13 @@ export default function From({ select = "", updateFilter }) {
|
||||
<Search embed={true} value={input} updateSearchValue={updateInput} />
|
||||
</div>
|
||||
<ul className="list">
|
||||
<li
|
||||
className="contact none"
|
||||
onClick={handleClick.bind(null, undefined)}
|
||||
>
|
||||
<li className="contact none" onClick={handleClick.bind(null, undefined)}>
|
||||
Anyone
|
||||
{!select && <CheckSign className="check" />}
|
||||
</li>
|
||||
{contacts.map(({ uid }) => {
|
||||
return (
|
||||
<li
|
||||
key={uid}
|
||||
className="contact"
|
||||
onClick={handleClick.bind(null, uid)}
|
||||
>
|
||||
<li key={uid} className="contact" onClick={handleClick.bind(null, uid)}>
|
||||
<Contact uid={uid} interactive={true} />
|
||||
{select == uid && <CheckSign className="check" />}
|
||||
</li>
|
||||
|
||||
@@ -54,32 +54,32 @@ const Styled = styled.div`
|
||||
export const FileTypes = {
|
||||
doc: {
|
||||
title: "Documents",
|
||||
icon: <IconDoc className="icon" />,
|
||||
icon: <IconDoc className="icon" />
|
||||
},
|
||||
pdf: {
|
||||
title: "PDFs",
|
||||
icon: <IconPdf className="icon" />,
|
||||
icon: <IconPdf className="icon" />
|
||||
},
|
||||
image: {
|
||||
title: "Images",
|
||||
icon: <IconImage className="icon" />,
|
||||
icon: <IconImage className="icon" />
|
||||
},
|
||||
audio: {
|
||||
title: "Audio",
|
||||
icon: <IconAudio className="icon" />,
|
||||
icon: <IconAudio className="icon" />
|
||||
},
|
||||
video: {
|
||||
title: "Videos",
|
||||
icon: <IconVideo className="icon" />,
|
||||
icon: <IconVideo className="icon" />
|
||||
},
|
||||
code: {
|
||||
title: "Code Snippets",
|
||||
icon: <IconCode className="icon" />,
|
||||
icon: <IconCode className="icon" />
|
||||
},
|
||||
unkown: {
|
||||
title: "Unkown Files",
|
||||
icon: <IconUnkown className="icon" />,
|
||||
},
|
||||
icon: <IconUnkown className="icon" />
|
||||
}
|
||||
};
|
||||
export default function Type({ select = "", updateFilter }) {
|
||||
// const { input, updateInput, contacts } = useFilteredUsers();
|
||||
@@ -99,11 +99,7 @@ export default function Type({ select = "", updateFilter }) {
|
||||
</li>
|
||||
{Object.entries(FileTypes).map(([type, { title, icon }]) => {
|
||||
return (
|
||||
<li
|
||||
key={title}
|
||||
className="type"
|
||||
onClick={handleClick.bind(null, type)}
|
||||
>
|
||||
<li key={title} className="type" onClick={handleClick.bind(null, type)}>
|
||||
{icon} {title}
|
||||
{select == type && <CheckSign className="check" />}
|
||||
</li>
|
||||
|
||||
@@ -47,7 +47,7 @@ export default function Filter({ filter, updateFilter }) {
|
||||
channel: false,
|
||||
date: false,
|
||||
from: false,
|
||||
type: false,
|
||||
type: false
|
||||
});
|
||||
const toggleFilterVisible = (obj) => {
|
||||
setFiltersVisible((prev) => {
|
||||
@@ -58,7 +58,7 @@ export default function Filter({ filter, updateFilter }) {
|
||||
updateFilter(data);
|
||||
let _key = Object.keys(data)[0];
|
||||
let tmp = {
|
||||
[_key]: false,
|
||||
[_key]: false
|
||||
};
|
||||
console.log("wtffff", tmp);
|
||||
toggleFilterVisible(tmp);
|
||||
@@ -72,7 +72,7 @@ export default function Filter({ filter, updateFilter }) {
|
||||
channel: channelVisible,
|
||||
date: dateVisible,
|
||||
type: typeVisible,
|
||||
from: fromVisible,
|
||||
from: fromVisible
|
||||
} = filtersVisible;
|
||||
return (
|
||||
<Styled>
|
||||
@@ -81,20 +81,14 @@ export default function Filter({ filter, updateFilter }) {
|
||||
onClickOutside={toggleFilterVisible.bind(null, { from: false })}
|
||||
visible={fromVisible}
|
||||
placement="bottom-start"
|
||||
content={
|
||||
<FilterFrom select={filter.from} updateFilter={handleUpdateFilter} />
|
||||
}
|
||||
content={<FilterFrom select={filter.from} updateFilter={handleUpdateFilter} />}
|
||||
>
|
||||
<div
|
||||
className={`filter ${from && "selected"}`}
|
||||
onClick={toggleFilterVisible.bind(null, { from: true })}
|
||||
>
|
||||
{from && (
|
||||
<Avatar
|
||||
className="avatar"
|
||||
name={contactMap[from].name}
|
||||
url={contactMap[from].avatar}
|
||||
/>
|
||||
<Avatar className="avatar" name={contactMap[from].name} url={contactMap[from].avatar} />
|
||||
)}
|
||||
<span className="txt">From {from && contactMap[from].name}</span>
|
||||
<ArrowDown className="arrow" />
|
||||
@@ -105,20 +99,13 @@ export default function Filter({ filter, updateFilter }) {
|
||||
onClickOutside={toggleFilterVisible.bind(null, { channel: false })}
|
||||
visible={channelVisible}
|
||||
placement="bottom-start"
|
||||
content={
|
||||
<FilterChannel
|
||||
select={filter.channel}
|
||||
updateFilter={handleUpdateFilter}
|
||||
/>
|
||||
}
|
||||
content={<FilterChannel select={filter.channel} updateFilter={handleUpdateFilter} />}
|
||||
>
|
||||
<div
|
||||
className={`filter ${channel && "selected"}`}
|
||||
onClick={toggleFilterVisible.bind(null, { channel: true })}
|
||||
>
|
||||
<span className="txt">
|
||||
{channel ? `In ${channelMap[channel].name}` : `Channel`}
|
||||
</span>
|
||||
<span className="txt">{channel ? `In ${channelMap[channel].name}` : `Channel`}</span>
|
||||
<ArrowDown className="arrow" />
|
||||
</div>
|
||||
</Tippy>
|
||||
@@ -127,9 +114,7 @@ export default function Filter({ filter, updateFilter }) {
|
||||
onClickOutside={toggleFilterVisible.bind(null, { type: false })}
|
||||
visible={typeVisible}
|
||||
placement="bottom-start"
|
||||
content={
|
||||
<FilterType select={filter.type} updateFilter={handleUpdateFilter} />
|
||||
}
|
||||
content={<FilterType select={filter.type} updateFilter={handleUpdateFilter} />}
|
||||
>
|
||||
<div
|
||||
className={`filter ${type && "selected"}`}
|
||||
@@ -144,9 +129,7 @@ export default function Filter({ filter, updateFilter }) {
|
||||
onClickOutside={toggleFilterVisible.bind(null, { date: false })}
|
||||
visible={dateVisible}
|
||||
placement="bottom-start"
|
||||
content={
|
||||
<FilterDate select={filter.date} updateFilter={handleUpdateFilter} />
|
||||
}
|
||||
content={<FilterDate select={filter.date} updateFilter={handleUpdateFilter} />}
|
||||
>
|
||||
<div
|
||||
className={`filter ${date && "selected"}`}
|
||||
|
||||
@@ -23,11 +23,7 @@ const Styled = styled.div`
|
||||
background-position: 8px center;
|
||||
}
|
||||
`;
|
||||
export default function Search({
|
||||
value = "",
|
||||
updateSearchValue = null,
|
||||
embed = false,
|
||||
}) {
|
||||
export default function Search({ value = "", updateSearchValue = null, embed = false }) {
|
||||
const handleChange = (evt) => {
|
||||
if (updateSearchValue) {
|
||||
updateSearchValue(evt.target.value);
|
||||
@@ -35,12 +31,7 @@ export default function Search({
|
||||
};
|
||||
return (
|
||||
<Styled className={embed ? "embed" : ""}>
|
||||
<input
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
className="search"
|
||||
placeholder="Search..."
|
||||
/>
|
||||
<input value={value} onChange={handleChange} className="search" placeholder="Search..." />
|
||||
</Styled>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -43,18 +43,10 @@ export default function View({ view = Views.item }) {
|
||||
};
|
||||
return (
|
||||
<Styled className={view}>
|
||||
<li
|
||||
className="view item"
|
||||
data-view={Views.item}
|
||||
onClick={handleChangeView}
|
||||
>
|
||||
<li className="view item" data-view={Views.item} onClick={handleChangeView}>
|
||||
<IconList />
|
||||
</li>
|
||||
<li
|
||||
className="view grid"
|
||||
data-view={Views.grid}
|
||||
onClick={handleChangeView}
|
||||
>
|
||||
<li className="view grid" data-view={Views.grid} onClick={handleChangeView}>
|
||||
<IconGrid />
|
||||
</li>
|
||||
</Styled>
|
||||
|
||||
@@ -17,16 +17,13 @@ const checkFilter = (data, filter, channelMessage) => {
|
||||
type: typeFilter,
|
||||
date: timeFilter,
|
||||
from: fromFilter,
|
||||
channel: channelFilter,
|
||||
channel: channelFilter
|
||||
} = filter;
|
||||
const name = properties ? properties.name : "";
|
||||
if (fromFilter && fromFilter != from_uid) {
|
||||
selected = false;
|
||||
}
|
||||
if (
|
||||
channelFilter &&
|
||||
channelMessage[channelFilter].findIndex((id) => id == mid) == -1
|
||||
) {
|
||||
if (channelFilter && channelMessage[channelFilter].findIndex((id) => id == mid) == -1) {
|
||||
selected = false;
|
||||
}
|
||||
if (nameFilter) {
|
||||
@@ -46,7 +43,7 @@ function ResourceManagement({ fileMessages }) {
|
||||
return {
|
||||
message: store.message,
|
||||
channelMessage: store.channelMessage,
|
||||
view: store.ui.fileListView,
|
||||
view: store.ui.fileListView
|
||||
};
|
||||
});
|
||||
|
||||
@@ -72,7 +69,7 @@ function ResourceManagement({ fileMessages }) {
|
||||
// options
|
||||
fitWidth: true,
|
||||
gutter,
|
||||
itemSelector: ".file_box",
|
||||
itemSelector: ".file_box"
|
||||
// columnWidth: 200
|
||||
});
|
||||
} else {
|
||||
|
||||
@@ -12,10 +12,7 @@ import SentTip from "./SentTip";
|
||||
|
||||
export default function SendMagicLinkPage() {
|
||||
const [sent, setSent] = useState(false);
|
||||
const [
|
||||
sendMagicLink,
|
||||
{ isSuccess, isLoading, error },
|
||||
] = useSendMagicLinkMutation();
|
||||
const [sendMagicLink, { isSuccess, isLoading, error }] = useSendMagicLinkMutation();
|
||||
|
||||
const navigateTo = useNavigate();
|
||||
// const dispatch = useDispatch();
|
||||
@@ -73,11 +70,7 @@ export default function SendMagicLinkPage() {
|
||||
) : (
|
||||
<>
|
||||
<div className="tips">
|
||||
<img
|
||||
src={`${BASE_URL}/resource/organization/logo`}
|
||||
alt="logo"
|
||||
className="logo"
|
||||
/>
|
||||
<img src={`${BASE_URL}/resource/organization/logo`} alt="logo" className="logo" />
|
||||
<h2 className="title">Login to Rustchat</h2>
|
||||
<span className="desc">Please enter your Email</span>
|
||||
</div>
|
||||
|
||||
@@ -8,8 +8,7 @@ const StyledWrapper = styled.div`
|
||||
max-width: 440px;
|
||||
padding: 32px 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: 0px 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;
|
||||
|
||||
@@ -52,16 +52,14 @@ import Input from "../../common/component/styled/Input";
|
||||
import Button from "../../common/component/styled/Button";
|
||||
import {
|
||||
useGetThirdPartySecretQuery,
|
||||
useUpdateThirdPartySecretMutation,
|
||||
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();
|
||||
const [updateSecret, { data: updatedSecret, isSuccess, isLoading }] =
|
||||
useUpdateThirdPartySecretMutation();
|
||||
console.log("secret", data);
|
||||
useEffect(() => {
|
||||
if (isSuccess) {
|
||||
@@ -83,18 +81,13 @@ export default function APIConfig() {
|
||||
content={
|
||||
<StyledConfirm>
|
||||
<div className="tip">
|
||||
Are you sure to update API secret? Previous secret will be
|
||||
invalided
|
||||
Are you sure to update API secret? Previous secret will be invalided
|
||||
</div>
|
||||
<div className="btns">
|
||||
<Button onClick={hideAll} className="cancel small">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
disabled={isLoading}
|
||||
className="small danger"
|
||||
onClick={updateSecret}
|
||||
>
|
||||
<Button disabled={isLoading} className="small danger" onClick={updateSecret}>
|
||||
Yes
|
||||
</Button>
|
||||
</div>
|
||||
@@ -104,8 +97,8 @@ export default function APIConfig() {
|
||||
<Button>Update Secret</Button>
|
||||
</Tippy>
|
||||
<div className="tip">
|
||||
Tip: The security key agreed between the rustchat server and the
|
||||
third-party app is used to encrypt the communication data.{" "}
|
||||
Tip: The security key agreed between the rustchat server and the third-party app is used to
|
||||
encrypt the communication data.{" "}
|
||||
</div>
|
||||
</Styled>
|
||||
);
|
||||
|
||||
@@ -69,11 +69,7 @@ export default function LogoutConfirmModal({ closeModal }) {
|
||||
<label htmlFor="clear_cb" className="txt">
|
||||
Clear local data
|
||||
</label>
|
||||
<Checkbox
|
||||
name="clear_cb"
|
||||
checked={clearLocal}
|
||||
onChange={handleCheck}
|
||||
/>
|
||||
<Checkbox name="clear_cb" checked={clearLocal} onChange={handleCheck} />
|
||||
</div>
|
||||
</StyledConfirm>
|
||||
</Modal>
|
||||
|
||||
@@ -101,21 +101,18 @@ const EditModalInfo = {
|
||||
name: {
|
||||
label: "Username",
|
||||
title: "Change your username",
|
||||
intro: "Enter a new username.",
|
||||
intro: "Enter a new username."
|
||||
},
|
||||
email: {
|
||||
label: "Email",
|
||||
title: "Change your email",
|
||||
intro: "Enter a new email.",
|
||||
},
|
||||
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 [uploadAvatar, { isSuccess: uploadSuccess }] = useUpdateAvatarMutation();
|
||||
const loginUser = useSelector((store) => {
|
||||
return store.contacts.byId[store.authData.uid];
|
||||
});
|
||||
@@ -177,8 +174,7 @@ export default function MyAccount() {
|
||||
<div className="danger">
|
||||
<h4 className="head">Account Removal</h4>
|
||||
<div className="desc">
|
||||
Disabling your account means you can recover it at any time after
|
||||
taking this action.
|
||||
Disabling your account means you can recover it at any time after taking this action.
|
||||
</div>
|
||||
<button className="btn">Delete Account</button>
|
||||
</div>
|
||||
@@ -191,9 +187,7 @@ export default function MyAccount() {
|
||||
closeModal={closeBasicEditModal}
|
||||
/>
|
||||
)}
|
||||
{passwordModal && (
|
||||
<UpdatePasswordModal closeModal={togglePasswordModal} />
|
||||
)}
|
||||
{passwordModal && <UpdatePasswordModal closeModal={togglePasswordModal} />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,10 +17,7 @@ export default function Notifications() {
|
||||
return (
|
||||
<StyledWrapper>
|
||||
<Label>Notification Setting:</Label>
|
||||
<StyledToggle
|
||||
data-checked={status == "granted"}
|
||||
onClick={handleEnableNotify}
|
||||
/>
|
||||
<StyledToggle data-checked={status == "granted"} onClick={handleEnableNotify} />
|
||||
</StyledWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useSelector } from "react-redux";
|
||||
import {
|
||||
useGetServerQuery,
|
||||
useUpdateServerMutation,
|
||||
useUpdateLogoMutation,
|
||||
useUpdateLogoMutation
|
||||
} from "../../app/services/server";
|
||||
import LogoUploader from "../../common/component/AvatarUploader";
|
||||
import Input from "../../common/component/styled/Input";
|
||||
@@ -136,8 +136,8 @@ export default function Overview() {
|
||||
{isAdmin && (
|
||||
<div className="upload">
|
||||
<div className="tip">
|
||||
Minimum size is 128x128, We recommend at least 512x512 for the
|
||||
server. Max size limited to 5M.
|
||||
Minimum size is 128x128, We recommend at least 512x512 for the server. Max size
|
||||
limited to 5M.
|
||||
</div>
|
||||
{/* <button className="btn">Upload Image</button> */}
|
||||
</div>
|
||||
@@ -170,9 +170,7 @@ export default function Overview() {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{changed && (
|
||||
<SaveTip saveHandler={handleUpdate} resetHandler={handleReset} />
|
||||
)}
|
||||
{changed && <SaveTip saveHandler={handleUpdate} resetHandler={handleReset} />}
|
||||
{/* <button onClick={handleUpdate} className="btn">update</button> */}
|
||||
</StyledWrapper>
|
||||
);
|
||||
|
||||
@@ -28,7 +28,7 @@ export default function ProfileBasicEditModal({
|
||||
value = "",
|
||||
title = "Change your username",
|
||||
intro = "Enter a new username and your existing password.",
|
||||
closeModal,
|
||||
closeModal
|
||||
}) {
|
||||
const [input, setInput] = useState(value);
|
||||
// const dispatch = useDispatch();
|
||||
@@ -56,9 +56,7 @@ export default function ProfileBasicEditModal({
|
||||
<Button className="cancel" onClick={closeModal}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={handleUpdate}>
|
||||
{isLoading ? "Updating" : `Done`}
|
||||
</Button>
|
||||
<Button onClick={handleUpdate}>{isLoading ? "Updating" : `Done`}</Button>
|
||||
</>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -2,10 +2,7 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import styled from "styled-components";
|
||||
import Input from "../../common/component/styled/Input";
|
||||
import {
|
||||
useUpdatePasswordMutation,
|
||||
useGetCredentialsQuery,
|
||||
} from "../../app/services/auth";
|
||||
import { useUpdatePasswordMutation, useGetCredentialsQuery } from "../../app/services/auth";
|
||||
import StyledModal from "../../common/component/styled/Modal";
|
||||
import Button from "../../common/component/styled/Button";
|
||||
const StyledEdit = styled(StyledModal)`
|
||||
@@ -30,13 +27,10 @@ export default function ProfileBasicEditModal({ closeModal }) {
|
||||
const [input, setInput] = useState({
|
||||
current: "",
|
||||
newPassword: "",
|
||||
confirmPassword: "",
|
||||
confirmPassword: ""
|
||||
});
|
||||
// const dispatch = useDispatch();
|
||||
const [
|
||||
updatePassword,
|
||||
{ isLoading, isSuccess },
|
||||
] = useUpdatePasswordMutation();
|
||||
const [updatePassword, { isLoading, isSuccess }] = useUpdatePasswordMutation();
|
||||
const handleChange = (evt) => {
|
||||
const { type } = evt.target.dataset;
|
||||
setInput((prev) => {
|
||||
|
||||
@@ -7,14 +7,7 @@ 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 { changed, reset, values, setValues, toggleEnable, updateConfig } = useConfig("agora");
|
||||
const handleUpdate = () => {
|
||||
// const { token_url, description } = values;
|
||||
updateConfig(values);
|
||||
@@ -34,7 +27,7 @@ export default function ConfigAgora() {
|
||||
app_certificate,
|
||||
rtm_key,
|
||||
rtm_secret,
|
||||
enabled = false,
|
||||
enabled = false
|
||||
} = values ?? {};
|
||||
return (
|
||||
<StyledContainer>
|
||||
|
||||
@@ -8,14 +8,7 @@ import SaveTip from "../../../common/component/SaveTip";
|
||||
import useConfig from "../../../common/hook/useConfig";
|
||||
|
||||
export default function ConfigFirebase() {
|
||||
const {
|
||||
values,
|
||||
toggleEnable,
|
||||
updateConfig,
|
||||
setValues,
|
||||
reset,
|
||||
changed,
|
||||
} = useConfig("firebase");
|
||||
const { values, toggleEnable, updateConfig, setValues, reset, changed } = useConfig("firebase");
|
||||
const handleUpdate = () => {
|
||||
// const { token_url, description } = values;
|
||||
updateConfig(values);
|
||||
@@ -28,8 +21,7 @@ export default function ConfigFirebase() {
|
||||
});
|
||||
};
|
||||
// if (!values) return null;
|
||||
const { token_url, project_id, private_key, client_email, enabled = false } =
|
||||
values ?? {};
|
||||
const { token_url, project_id, private_key, client_email, enabled = false } = values ?? {};
|
||||
return (
|
||||
<StyledContainer>
|
||||
<div className="inputs">
|
||||
|
||||
@@ -15,17 +15,15 @@ export default function Logins() {
|
||||
changed: clientIdChanged,
|
||||
clientId,
|
||||
updateClientId,
|
||||
updateClientIdToServer,
|
||||
updateClientIdToServer
|
||||
} = useGoogleAuthConfig();
|
||||
const {
|
||||
config: githubAuthConfig,
|
||||
changed: githubChanged,
|
||||
updateGithubAuthConfigToServer,
|
||||
updateGithubAuthConfig,
|
||||
updateGithubAuthConfig
|
||||
} = useGithubAuthConfig();
|
||||
const { values, updateConfig, setValues, reset, changed } = useConfig(
|
||||
"login"
|
||||
);
|
||||
const { values, updateConfig, setValues, reset, changed } = useConfig("login");
|
||||
const handleUpdate = async () => {
|
||||
const { google } = values;
|
||||
if (changed) {
|
||||
@@ -70,8 +68,7 @@ export default function Logins() {
|
||||
});
|
||||
};
|
||||
if (!values) return null;
|
||||
const { google, magic_link, github, metamask, password, oidc = [] } =
|
||||
values ?? {};
|
||||
const { google, magic_link, github, metamask, password, oidc = [] } = values ?? {};
|
||||
const valuesChanged = clientIdChanged || changed || githubChanged;
|
||||
|
||||
return (
|
||||
@@ -97,9 +94,7 @@ export default function Logins() {
|
||||
<div className="txt">
|
||||
<Label>Magic Link</Label>
|
||||
</div>
|
||||
<span className="desc">
|
||||
Allows members login with Magic Link.
|
||||
</span>
|
||||
<span className="desc">Allows members login with Magic Link.</span>
|
||||
</div>
|
||||
<Toggle
|
||||
onClick={handleToggle.bind(null, { magic_link: !magic_link })}
|
||||
@@ -191,9 +186,7 @@ export default function Logins() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{valuesChanged && (
|
||||
<SaveTip saveHandler={handleUpdate} resetHandler={reset} />
|
||||
)}
|
||||
{valuesChanged && <SaveTip saveHandler={handleUpdate} resetHandler={reset} />}
|
||||
</StyledContainer>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,14 +20,7 @@ import toast from "react-hot-toast";
|
||||
export default function ConfigSMTP() {
|
||||
const [testEmail, setTestEmail] = useState("");
|
||||
const [sendTestEmail, { isSuccess, isError }] = useSendTestEmailMutation();
|
||||
const {
|
||||
reset,
|
||||
updateConfig,
|
||||
values,
|
||||
setValues,
|
||||
changed,
|
||||
toggleEnable,
|
||||
} = useConfig("smtp");
|
||||
const { reset, updateConfig, values, setValues, changed, toggleEnable } = useConfig("smtp");
|
||||
|
||||
const handleUpdate = () => {
|
||||
// const { token_url, description } = values;
|
||||
@@ -49,7 +42,7 @@ export default function ConfigSMTP() {
|
||||
sendTestEmail({
|
||||
to: testEmail,
|
||||
subject: "test title",
|
||||
content: "test content",
|
||||
content: "test content"
|
||||
});
|
||||
};
|
||||
useEffect(() => {
|
||||
@@ -62,8 +55,7 @@ export default function ConfigSMTP() {
|
||||
}, [isSuccess, isError]);
|
||||
|
||||
// if (!values) return null;
|
||||
const { host, port, from, username, password, enabled = false } =
|
||||
values ?? {};
|
||||
const { host, port, from, username, password, enabled = false } = values ?? {};
|
||||
console.log("values", values);
|
||||
return (
|
||||
<StyledContainer>
|
||||
|
||||
+20
-20
@@ -16,20 +16,20 @@ const navs = [
|
||||
{
|
||||
name: "overview",
|
||||
title: "Overview",
|
||||
component: <Overview />,
|
||||
component: <Overview />
|
||||
},
|
||||
{
|
||||
name: "members",
|
||||
title: "Members",
|
||||
component: <ManageMembers />,
|
||||
admin: true,
|
||||
},
|
||||
admin: true
|
||||
}
|
||||
// {
|
||||
// name: "notification",
|
||||
// title: "Notification",
|
||||
// component: <Notifications />,
|
||||
// },
|
||||
],
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "User",
|
||||
@@ -37,9 +37,9 @@ const navs = [
|
||||
{
|
||||
name: "my_account",
|
||||
title: "My Account",
|
||||
component: <MyAccount />,
|
||||
},
|
||||
],
|
||||
component: <MyAccount />
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Configuration",
|
||||
@@ -47,30 +47,30 @@ const navs = [
|
||||
{
|
||||
name: "firebase",
|
||||
title: "Firebase",
|
||||
component: <ConfigFirebase />,
|
||||
component: <ConfigFirebase />
|
||||
},
|
||||
{
|
||||
name: "agora",
|
||||
title: "Agora",
|
||||
component: <ConfigAgora />,
|
||||
component: <ConfigAgora />
|
||||
},
|
||||
{
|
||||
name: "smtp",
|
||||
title: "SMTP",
|
||||
component: <ConfigSMTP />,
|
||||
component: <ConfigSMTP />
|
||||
},
|
||||
{
|
||||
name: "social_login",
|
||||
title: "Login Methods",
|
||||
component: <Logins />,
|
||||
component: <Logins />
|
||||
},
|
||||
{
|
||||
name: "api",
|
||||
title: "Third-party APP",
|
||||
component: <APIConfig />,
|
||||
},
|
||||
component: <APIConfig />
|
||||
}
|
||||
],
|
||||
admin: true,
|
||||
admin: true
|
||||
},
|
||||
{
|
||||
title: "About",
|
||||
@@ -78,20 +78,20 @@ const navs = [
|
||||
{
|
||||
name: "faq",
|
||||
title: "FAQ",
|
||||
component: <FAQ />,
|
||||
component: <FAQ />
|
||||
},
|
||||
{
|
||||
name: "terms",
|
||||
title: "Terms & Privacy",
|
||||
component: "Terms & Privacy",
|
||||
component: "Terms & Privacy"
|
||||
},
|
||||
{
|
||||
name: "feedback",
|
||||
title: "Feedback",
|
||||
component: "feedback",
|
||||
},
|
||||
],
|
||||
},
|
||||
component: "feedback"
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
const useNavs = () => {
|
||||
const loginUser = useSelector((store) => {
|
||||
|
||||
@@ -30,10 +30,7 @@ export default function DeleteConfirmModal({ id, closeModal }) {
|
||||
description="Are you sure want to delete this channel?"
|
||||
buttons={
|
||||
<>
|
||||
<Button
|
||||
onClick={closeModal.bind(null, undefined)}
|
||||
className="cancel"
|
||||
>
|
||||
<Button onClick={closeModal.bind(null, undefined)} className="cancel">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={handleDelete} className="danger">
|
||||
|
||||
@@ -4,7 +4,7 @@ import toast from "react-hot-toast";
|
||||
import {
|
||||
useGetChannelQuery,
|
||||
useUpdateChannelMutation,
|
||||
useUpdateIconMutation,
|
||||
useUpdateIconMutation
|
||||
} from "../../app/services/channel";
|
||||
import AvatarUploader from "../../common/component/AvatarUploader";
|
||||
import Input from "../../common/component/styled/Input";
|
||||
@@ -46,7 +46,7 @@ export default function Overview({ id = 0 }) {
|
||||
const { loginUser, channel } = useSelector((store) => {
|
||||
return {
|
||||
loginUser: store.contacts.byId[store.authData.uid],
|
||||
channel: store.channels.byId[id],
|
||||
channel: store.channels.byId[id]
|
||||
};
|
||||
});
|
||||
const { data, refetch } = useGetChannelQuery(id);
|
||||
@@ -102,12 +102,7 @@ export default function Overview({ id = 0 }) {
|
||||
console.log("channel icon", channel);
|
||||
return (
|
||||
<StyledWrapper>
|
||||
<AvatarUploader
|
||||
type="channel"
|
||||
url={channel?.icon}
|
||||
name={name}
|
||||
uploadImage={updateIcon}
|
||||
/>
|
||||
<AvatarUploader type="channel" url={channel?.icon} name={name} uploadImage={updateIcon} />
|
||||
<div className="inputs">
|
||||
<div className="input">
|
||||
<Label htmlFor="name">Channel Name</Label>
|
||||
@@ -136,9 +131,7 @@ export default function Overview({ id = 0 }) {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{changed && (
|
||||
<SaveTip saveHandler={handleUpdate} resetHandler={handleReset} />
|
||||
)}
|
||||
{changed && <SaveTip saveHandler={handleUpdate} resetHandler={handleReset} />}
|
||||
{/* <button onClick={handleUpdate} className="btn">update</button> */}
|
||||
</StyledWrapper>
|
||||
);
|
||||
|
||||
@@ -12,7 +12,7 @@ export default function ChannelSetting() {
|
||||
return {
|
||||
loginUid: store.authData.uid,
|
||||
isAdmin: store.contacts.byId[store.authData.uid]?.is_admin,
|
||||
channel: store.channels.byId[cid],
|
||||
channel: store.channels.byId[cid]
|
||||
};
|
||||
});
|
||||
const navigate = useNavigate();
|
||||
@@ -52,22 +52,18 @@ export default function ChannelSetting() {
|
||||
dangers={[
|
||||
canLeave && {
|
||||
title: "Leave Channel",
|
||||
handler: toggleLeaveConfrim,
|
||||
handler: toggleLeaveConfrim
|
||||
},
|
||||
canDelete && {
|
||||
title: "Delete Channel",
|
||||
handler: toggleDeleteConfrim,
|
||||
},
|
||||
handler: toggleDeleteConfrim
|
||||
}
|
||||
]}
|
||||
>
|
||||
{currNav.component}
|
||||
</StyledSettingContainer>
|
||||
{deleteConfirm && (
|
||||
<DeleteConfirmModal closeModal={toggleDeleteConfrim} id={cid} />
|
||||
)}
|
||||
{leaveConfirm && (
|
||||
<LeaveChannel closeModal={toggleLeaveConfrim} id={cid} />
|
||||
)}
|
||||
{deleteConfirm && <DeleteConfirmModal closeModal={toggleDeleteConfrim} id={cid} />}
|
||||
{leaveConfirm && <LeaveChannel closeModal={toggleLeaveConfrim} id={cid} />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,13 +8,13 @@ const useNavs = (channelId) => {
|
||||
{
|
||||
name: "overview",
|
||||
title: "Overview",
|
||||
component: <Overview id={channelId} />,
|
||||
component: <Overview id={channelId} />
|
||||
},
|
||||
{
|
||||
name: "members",
|
||||
title: "Members",
|
||||
component: <ManageMembers cid={channelId} />,
|
||||
},
|
||||
component: <ManageMembers cid={channelId} />
|
||||
}
|
||||
// {
|
||||
// name: "permissions",
|
||||
// title: "Permissions",
|
||||
@@ -27,8 +27,8 @@ const useNavs = (channelId) => {
|
||||
// name: "integrations",
|
||||
// title: "Integrations",
|
||||
// },
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
// {
|
||||
// title: "User Management",
|
||||
// items: [
|
||||
|
||||
Reference in New Issue
Block a user