From 38b217d65e2df6ebf21c2d7f3e552a754683b2d4 Mon Sep 17 00:00:00 2001 From: Ilya Oleshko Date: Tue, 30 Aug 2022 08:55:19 +0300 Subject: [PATCH] Web: Client: InvitePanel: Added user search, added email validation, added editing for manual added items, fixed invite panel state --- .../src/components/FilesPanels/index.js | 4 +- .../panels/InvitePanel/InviteInput.js | 48 ++++-- .../panels/InvitePanel/StyledInvitePanel.js | 59 +++++++ .../components/panels/InvitePanel/index.js | 89 +++++------ .../components/panels/InvitePanel/items.js | 147 ++++++++++++++++-- .../client/src/store/ContextOptionsStore.js | 9 +- packages/client/src/store/DialogsStore.js | 2 +- packages/client/src/store/UsersStore.js | 6 + packages/common/api/people/index.js | 7 + packages/common/store/SettingsStore.js | 6 +- public/images/check.edit.react.svg | 3 + public/images/cross.edit.react.svg | 10 ++ public/images/info.edit.react.svg | 10 ++ 13 files changed, 315 insertions(+), 85 deletions(-) create mode 100644 public/images/check.edit.react.svg create mode 100644 public/images/cross.edit.react.svg create mode 100644 public/images/info.edit.react.svg diff --git a/packages/client/src/components/FilesPanels/index.js b/packages/client/src/components/FilesPanels/index.js index cf376d152e..a8f0c2bcb5 100644 --- a/packages/client/src/components/FilesPanels/index.js +++ b/packages/client/src/components/FilesPanels/index.js @@ -139,7 +139,7 @@ export default inject( const { uploadPanelVisible } = uploadDataStore; const { isVisible: versionHistoryPanelVisible } = versionHistoryStore; - const { hotkeyPanelVisible, invitePanelVisible } = auth.settingsStore; + const { hotkeyPanelVisible, invitePanelOptions } = auth.settingsStore; return { sharingPanelVisible, @@ -163,7 +163,7 @@ export default inject( createMasterForm, setSelectFileDialogVisible, hotkeyPanelVisible, - invitePanelVisible, + invitePanelVisible: invitePanelOptions.visible, }; } )(observer(Panels)); diff --git a/packages/client/src/components/panels/InvitePanel/InviteInput.js b/packages/client/src/components/panels/InvitePanel/InviteInput.js index a7fb8ed29d..51832f5513 100644 --- a/packages/client/src/components/panels/InvitePanel/InviteInput.js +++ b/packages/client/src/components/panels/InvitePanel/InviteInput.js @@ -1,9 +1,10 @@ -import React, { useState, useCallback, useEffect, useRef } from "react"; - +import React, { useState, useCallback } from "react"; import debounce from "lodash.debounce"; import Avatar from "@docspace/components/avatar"; +import { parseAddresses } from "@docspace/components/utils/email"; + import { StyledInviteInput, StyledInviteInputContainer, @@ -12,12 +13,14 @@ import { SearchItemText, } from "./StyledInvitePanel"; -const InviteInput = ({ onAddUser, getUsersList }) => { +const InviteInput = ({ onAddUser, getUsersByQuery }) => { const [inputValue, setInputValue] = useState(""); const [usersList, setUsersList] = useState([]); const [panelVisible, setPanelVisible] = useState(false); const toUserItem = (email) => { + const emails = parseAddresses(email); + const uid = () => String(Date.now().toString(32) + Math.random().toString(16)).replace( /\./g, @@ -27,19 +30,21 @@ const InviteInput = ({ onAddUser, getUsersList }) => { email, id: uid(), displayName: email, + errors: emails[0].parseErrors, }; }; const searchByTerm = async (value) => { - const users = await getUsersList(); - setUsersList(users); + value = value.trim(); - //const user = toUserItem(value); - //onAddUser && onAddUser(user); + if (value.length > 0) { + const users = await getUsersByQuery(value); + setUsersList(users); + } }; const debouncedSearch = useCallback( - debounce((value) => searchByTerm(value), 1000), + debounce((value) => searchByTerm(value), 500), [] ); @@ -54,11 +59,16 @@ const InviteInput = ({ onAddUser, getUsersList }) => { }; const getItemContent = (item) => { - const { avatarSmall, displayName, email, id } = item; + const { avatar, displayName, email, id } = item; + + const addUser = () => { + onAddUser && onAddUser(item); + setPanelVisible(false); + }; return ( - - + +
{displayName} {email} @@ -68,6 +78,14 @@ const InviteInput = ({ onAddUser, getUsersList }) => { ); }; + const addItem = () => { + const item = toUserItem(inputValue); + + onAddUser && onAddUser(item); + + setPanelVisible(false); + }; + return ( { value={inputValue} /> - {usersList?.map((user) => getItemContent(user))} + {usersList.length ? ( + usersList?.map((user) => getItemContent(user)) + ) : ( + + Add «{inputValue}» + + )} ); diff --git a/packages/client/src/components/panels/InvitePanel/StyledInvitePanel.js b/packages/client/src/components/panels/InvitePanel/StyledInvitePanel.js index 1b79f8c6d4..d62418f600 100644 --- a/packages/client/src/components/panels/InvitePanel/StyledInvitePanel.js +++ b/packages/client/src/components/panels/InvitePanel/StyledInvitePanel.js @@ -6,6 +6,14 @@ import Box from "@docspace/components/box"; import DropDown from "@docspace/components/drop-down"; import DropDownItem from "@docspace/components/drop-down-item"; import Text from "@docspace/components/text"; +import Button from "@docspace/components/button"; +import HelpButton from "@docspace/components/help-button"; + +import CheckIcon from "PUBLIC_DIR/images/check.edit.react.svg"; +import CrossIcon from "PUBLIC_DIR/images/cross.edit.react.svg"; +import DeleteIcon from "PUBLIC_DIR/images/mobile.actions.remove.react.svg"; + +import commonIconsStyles from "@docspace/components/utils/common-icons-style"; import { Base } from "@docspace/components/themes"; @@ -63,6 +71,10 @@ const StyledInviteInput = styled(TextInput)` margin-bottom: 20px; `; +const StyledEditInput = styled(TextInput)` + ${fillAvailableWidth} +`; + const StyledComboBox = styled(ComboBox)` margin-left: auto; @@ -102,6 +114,47 @@ const SearchItemText = styled(Text)` StyledBlock.defaultProps = { theme: Base }; +const StyledEditButton = styled(Button)` + width: 32px; + height: 32px; + padding: 0px; +`; + +const StyledCheckIcon = styled(CheckIcon)` + ${commonIconsStyles} + path { + fill: ${(props) => props.theme.filesEditingWrapper.fill} !important; + } + :hover { + fill: ${(props) => props.theme.filesEditingWrapper.hoverFill} !important; + } +`; + +StyledCheckIcon.defaultProps = { theme: Base }; + +const StyledCrossIcon = styled(CrossIcon)` + ${commonIconsStyles} + path { + fill: ${(props) => props.theme.filesEditingWrapper.fill} !important; + } + :hover { + fill: ${(props) => props.theme.filesEditingWrapper.hoverFill} !important; + } +`; + +const StyledDeleteIcon = styled(DeleteIcon)` + margin-left: auto; + ${commonIconsStyles} + path { + fill: ${(props) => props.theme.filesEditingWrapper.fill} !important; + } + :hover { + fill: ${(props) => props.theme.filesEditingWrapper.hoverFill} !important; + } +`; + +const StyledHelpButton = styled(HelpButton)``; + export { StyledBlock, StyledHeading, @@ -114,4 +167,10 @@ export { StyledDropDown, StyledDropDownItem, SearchItemText, + StyledEditInput, + StyledEditButton, + StyledCheckIcon, + StyledCrossIcon, + StyledHelpButton, + StyledDeleteIcon, }; diff --git a/packages/client/src/components/panels/InvitePanel/index.js b/packages/client/src/components/panels/InvitePanel/index.js index 017b745ba6..4b8a620566 100644 --- a/packages/client/src/components/panels/InvitePanel/index.js +++ b/packages/client/src/components/panels/InvitePanel/index.js @@ -19,43 +19,32 @@ import Items from "./items.js"; import InviteInput from "./InviteInput"; const InvitePanel = ({ - invitePanelVisible, - setInvitePanelVisible, + invitePanelOptions, + setInvitePanelOptions, + visible, t, theme, tReady, - getUsersList, + getUsersByQuery, + getFolderInfo, + folders, }) => { - const testItems = [ - { - email: "test1@gmail.com", - id: "1", - displayName: "Administrator Test1", - avatarSmall: - "/storage/userPhotos/root/66faa6e4-f133-11ea-b126-00ffeec8b4ef_orig_46-46.jpeg?_=1380485370", - }, - { - email: "test2@gmail.com", - id: "2", - displayName: "Administrator Test2", - avatarSmall: - "/storage/userPhotos/root/66faa6e4-f133-11ea-b126-00ffeec8b4ef_orig_46-46.jpeg?_=1380485370", - }, - { - email: "test3@gmail.com", - id: "3", - displayName: "Administrator Test3", - }, - { - email: "test4@gmail.com", - id: "4", - displayName: "Administrator Test4", - }, - ]; + const [items, setItems] = useState([]); + const [selectedRoom, setSelectedRoom] = useState(null); - const [items, setItems] = useState(testItems); + useEffect(() => { + const { id } = invitePanelOptions; + const room = folders.find((folder) => folder.id === id); + if (room) { + setSelectedRoom(room); + } else { + getFolderInfo(id).then((info) => { + setSelectedRoom(info); + }); + } + }, [invitePanelOptions]); - const onClose = () => setInvitePanelVisible(false); + const onClose = () => setInvitePanelOptions({ visible: false }); const onAddUser = (user) => { setItems([...items, user]); @@ -78,17 +67,8 @@ const InvitePanel = ({ return ( - -