From e3f3c6877d7d8460ef10128eea1278d263796eb2 Mon Sep 17 00:00:00 2001 From: Johnny Niklasson Date: Fri, 22 Mar 2024 12:09:01 +0100 Subject: [PATCH] added search-dropdown in add user modal (#162) --- src/pages/TeamDetail/TeamDetail.tsx | 108 ++++++++++++++++++---------- src/services/teamMembers.ts | 37 +++++++++- 2 files changed, 105 insertions(+), 40 deletions(-) diff --git a/src/pages/TeamDetail/TeamDetail.tsx b/src/pages/TeamDetail/TeamDetail.tsx index 476268f6..6e7a15ba 100644 --- a/src/pages/TeamDetail/TeamDetail.tsx +++ b/src/pages/TeamDetail/TeamDetail.tsx @@ -29,7 +29,6 @@ import { Divider, Tabs, Button, - Input, Dropdown, Tag, Link, @@ -40,6 +39,7 @@ import { XCircle } from 'react-feather' import FormattedTableColumn from '../../components/FormattedTableColumn' import SidebarModal from '../../components/SidebarModal/SidebarModal' import DeleteLink from '../../components/DeleteLink/DeleteLink' +import { fetchUserSearchData, User } from '../../services/teamMembers' interface UserInfo { name?: string @@ -83,11 +83,14 @@ const SHARED_BUCKETS_TAB = { ], } -const defaultEmail = { - key: 'add-user-email', +const defaultSelectedUserDropdown = { + key: 'add-selected-user', error: false, - errorMessage: `Ugyldig epost`, - value: '', + errorMessage: `Ugyldig navn`, +} +const defaultSelectedUser = { + id: 'search', + title: 'Søk ...', } const defaultAddUserKey = 'add-user-selected-group' @@ -104,7 +107,9 @@ const TeamDetail = () => { const { setBreadcrumbTeamDetailDisplayName } = useContext(DaplaCtrlContext) const [error, setError] = useState() const [loadingTeamData, setLoadingTeamData] = useState(true) + const [loadingUsers, setLoadingUsers] = useState(false) const [teamDetailData, setTeamDetailData] = useState() + const [userData, setUserData] = useState() const [teamDetailTableTitle, setTeamDetailTableTitle] = useState(TEAM_USERS_TAB.title) const [teamDetailTableHeaderColumns, setTeamDetailTableHeaderColumns] = useState( TEAM_USERS_TAB.columns @@ -113,7 +118,8 @@ const TeamDetail = () => { // Add users to team const [openAddUserSidebarModal, setOpenAddUserSidebarModal] = useState(false) - const [email, setEmail] = useState(defaultEmail) + const [selectedUserDropdown, setSelectedUserDropdown] = useState(defaultSelectedUserDropdown) + const [selectedUser, setSelectedUser] = useState(defaultSelectedUser) const [selectedGroupAddUser, setSelectedGroupAddUser] = useState({ ...defaultSelectedGroup, key: defaultAddUserKey, @@ -281,6 +287,31 @@ const TeamDetail = () => { } }, [prepTeamData]) + const getUsersAutoCompleteData = () => { + if (userData) return + setLoadingUsers(true) + fetchUserSearchData() + .then((users) => { + const filteredUsers = users.filter( + (allUsers) => + !(teamDetailData?.team as Team).users?.some( + (teamUsers) => allUsers.principal_name === teamUsers.principal_name + ) + ) + setUserData(filteredUsers) + }) + .catch((error) => { + setError(error as ApiError) + }) + .finally(() => setLoadingUsers(false)) + } + + useEffect(() => { + if (openAddUserSidebarModal) { + getUsersAutoCompleteData() + } + }, [openAddUserSidebarModal]) + const handleTabClick = (tab: string) => setActiveTab(tab) const renderErrorAlert = () => { @@ -330,6 +361,11 @@ const TeamDetail = () => { } } + const handleAddUser = (item: DropdownItems) => { + setSelectedUserDropdown({ ...selectedUserDropdown, key: `${defaultSelectedUserDropdown.key}-${item.id}` }) + setSelectedUser(item) + } + const removeDuplicateDropdownItems = (items: DropdownItems[]) => { return items.reduce((acc: DropdownItems[], dropdownItem: DropdownItems) => { const ids = acc.map((obj) => obj.id) @@ -379,20 +415,20 @@ const TeamDetail = () => { } const handleAddUserOnSubmit = () => { - if (email.value === '') setEmail({ ...email, error: true }) + const isSelectedUserValid = selectedUser.id !== 'search' + if (!isSelectedUserValid) setSelectedUserDropdown({ ...selectedUserDropdown, error: true }) if (!teamGroupTags.length) setTeamGroupTagsError({ ...teamGroupTagsError, error: true, }) - if (email.value !== '' && teamGroupTags.length) { - setEmail({ ...email, key: `add-user-${email.value}` }) + if (isSelectedUserValid && teamGroupTags.length) { setAddUserToTeamErrors([]) setShowAddUserSpinner(true) addUserToGroups( teamGroupTags.map((group) => group.id), - email.value + selectedUser.id ) .then((response) => { const errorsList = getErrorList(response) @@ -402,7 +438,7 @@ const TeamDetail = () => { setOpenAddUserSidebarModal(false) setTeamGroupTags([]) // Reset fields with their respective keys; re-initializes component - setEmail({ ...defaultEmail }) + setSelectedUserDropdown({ ...defaultSelectedUserDropdown }) setSelectedGroupAddUser({ ...defaultSelectedGroup, key: defaultAddUserKey }) } }) @@ -540,13 +576,6 @@ const TeamDetail = () => { ) } - const isUserInputValid = (value?: string) => { - const regEx = /^[\w-]+@ssb\.no$/ - const userVal = value || email.value - const testUser = userVal.match(regEx) - return !!testUser - } - const teamModalHeader = teamDetailData ? { modalType: 'Medlem', @@ -572,27 +601,28 @@ const TeamDetail = () => { modalBodyTitle: 'Legg person til teamet', modalBody: ( <> - - setEmail({ - ...email, - error: !isUserInputValid(), - }) - } - handleChange={(value: string) => - setEmail({ - ...email, - value, - error: email.error ? !isUserInputValid(value) : false, - }) - } - /> + {!loadingUsers ? ( + { + return { + id: principal_name, + title: formatDisplayName(display_name), + } + })} + onSelect={(item: DropdownItems) => handleAddUser(item)} + error={selectedUserDropdown.error} + errorMessage={selectedUserDropdown.errorMessage} + searchable + /> + ) : ( +
+ +
+ )} => { + const usersUrl = new URL(`${USERS_URL}`, window.location.origin) + const selects = ['display_name', 'principal_name', 'section_name'] + + usersUrl.searchParams.append('select', selects.join(',')) + + try { + const allUsersData = await fetchAPIData(usersUrl.toString()) + + if (!allUsersData) throw new ApiError(500, 'No json data returned') + if (!allUsersData._embedded || !allUsersData._embedded.users) throw new ApiError(500, 'Did not receive users data') + + const prepData = allUsersData._embedded.users.map((user: User) => { + const prepUserData = { + ...user, + ...user._embedded, + } + delete prepUserData._embedded + return prepUserData + }) + delete prepData._embedded + + return prepData + } catch (error) { + if (error instanceof ApiError) { + console.error('Failed to fetch user search data:', error) + throw error + } else { + const apiError = new ApiError(500, 'An unexpected error occurred') + console.error('Failed to fetch user search data:', apiError) + throw apiError + } + } +}