-
Notifications
You must be signed in to change notification settings - Fork 361
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add friendly name to list group members response #8413
Changes from 6 commits
2a3693a
2331a7b
8892f3c
9aa365d
dd0f625
609d471
6083e4b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ import Button from "react-bootstrap/Button"; | |
|
||
import {GroupHeader} from "../../../../lib/components/auth/nav"; | ||
import {useAPIWithPagination} from "../../../../lib/hooks/api"; | ||
import {auth} from "../../../../lib/api"; | ||
import {auth, MAX_LISTING_AMOUNT} from "../../../../lib/api"; | ||
import {Paginator} from "../../../../lib/components/pagination"; | ||
import {AttachModal} from "../../../../lib/components/auth/forms"; | ||
import {ConfirmationButton} from "../../../../lib/components/modals"; | ||
|
@@ -19,22 +19,48 @@ import { | |
} from "../../../../lib/components/controls"; | ||
import {useRouter} from "../../../../lib/hooks/router"; | ||
import {Link} from "../../../../lib/components/nav"; | ||
import {resolveDisplayName} from "../../../../lib/utils"; | ||
import {resolveUserDisplayName} from "../../../../lib/utils"; | ||
|
||
|
||
const GroupMemberList = ({ groupId, after, onPaginate }) => { | ||
const [refresh, setRefresh] = useState(false); | ||
const [showAddModal, setShowAddModal] = useState(false); | ||
const [attachError, setAttachError] = useState(null); | ||
|
||
const [allUsers, setAllUsers] = useState([]); | ||
const {results, loading, error, nextPage} = useAPIWithPagination(() => { | ||
return auth.listGroupMembers(groupId, after); | ||
}, [groupId, after, refresh]); | ||
|
||
useEffect(() => { | ||
setAttachError(null); | ||
}, [refresh]); | ||
|
||
const allUsersFromLakeFS = async (resolveUserDisplayNameFN = (user => user.id)) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is too much business logic to be in this file - How about extracting this? |
||
if (allUsers.length > 0) { | ||
return allUsers | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @itaigilo, isn't there some better way to force only one load, with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably - |
||
after = "" | ||
let hasMore = true | ||
let usersList = [] | ||
try { | ||
do { | ||
const results = await auth.listUsers("", after, MAX_LISTING_AMOUNT); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happens after Shouldn't we detect this scenario, and at least warn the user in some way? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I run do-while in order to list all the users with pagination There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check out There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think it's the same case. |
||
usersList = usersList.concat(results.results); | ||
after = results.pagination.next_offset; | ||
hasMore = results.pagination.has_more; | ||
} while (hasMore); | ||
usersList.sort((a, b) => resolveUserDisplayNameFN(a).localeCompare(resolveUserDisplayNameFN(b))); | ||
setAllUsers(usersList); | ||
return usersList; | ||
} catch (error) { | ||
console.error("Error fetching users:", error); | ||
return []; | ||
} | ||
} | ||
const searchUsers = async (prefix, maxResults, resolveUserDisplayNameFN = (user => user.id)) => { | ||
let allUsersList = await allUsersFromLakeFS(resolveUserDisplayNameFN) | ||
let filteredUsers = allUsersList.filter(user => resolveUserDisplayNameFN(user).startsWith(prefix)); | ||
return filteredUsers.slice(0, maxResults); | ||
}; | ||
let content; | ||
if (loading) content = <Loading/>; | ||
else if (error) content= <AlertError error={error}/>; | ||
|
@@ -45,7 +71,7 @@ const GroupMemberList = ({ groupId, after, onPaginate }) => { | |
<DataTable | ||
keyFn={user => user.id} | ||
rowFn={user => [ | ||
<Link href={{pathname: '/auth/users/:userId', params: {userId: user.id}}}>{resolveDisplayName(user)}</Link>, | ||
<Link href={{pathname: '/auth/users/:userId', params: {userId: user.id}}}>{resolveUserDisplayName(user)}</Link>, | ||
<FormattedDate dateValue={user.creation_date}/> | ||
]} | ||
headers={['User ID', 'Created At']} | ||
|
@@ -54,7 +80,7 @@ const GroupMemberList = ({ groupId, after, onPaginate }) => { | |
buttonFn: user => <ConfirmationButton | ||
size="sm" | ||
variant="outline-danger" | ||
msg={<span>Are you sure you{'\''}d like to remove user <strong>{resolveDisplayName(user)}</strong> from group <strong>{groupId}</strong>?</span>} | ||
msg={<span>Are you sure you{'\''}d like to remove user <strong>{resolveUserDisplayName(user)}</strong> from group <strong>{groupId}</strong>?</span>} | ||
onConfirm={() => { | ||
auth.removeUserFromGroup(user.id, groupId) | ||
.catch(error => alert(error)) | ||
|
@@ -75,7 +101,8 @@ const GroupMemberList = ({ groupId, after, onPaginate }) => { | |
filterPlaceholder={'Find User...'} | ||
modalTitle={'Add to Group'} | ||
addText={'Add to Group'} | ||
searchFn={prefix => auth.listUsers(prefix, "", 5).then(res => res.results)} | ||
resolveEntityFN={resolveUserDisplayName} | ||
searchFn={prefix => searchUsers(prefix, 5, resolveUserDisplayName).then(res => res)} | ||
onHide={() => setShowAddModal(false)} | ||
onAttach={(selected) => { | ||
Promise.all(selected.map(user => auth.addUserToGroup(user.id, groupId))) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,12 @@ import { ConfirmationButton } from "../../../../lib/components/modals"; | |
import { useRouter } from "../../../../lib/hooks/router"; | ||
import { Link } from "../../../../lib/components/nav"; | ||
|
||
const resolveGroupDisplayName = (group) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔥 |
||
if(!group) return ""; | ||
if (group?.name?.length) return group.name; | ||
return group.id; | ||
} | ||
|
||
const UserGroupsList = ({ userId, after, onPaginate }) => { | ||
const [refresh, setRefresh] = useState(false); | ||
const [showAddModal, setShowAddModal] = useState(false); | ||
|
@@ -97,6 +103,7 @@ const UserGroupsList = ({ userId, after, onPaginate }) => { | |
searchFn={(prefix) => | ||
auth.listGroups(prefix, "", 5).then((res) => res.results) | ||
} | ||
resolveEntityFN={resolveGroupDisplayName} | ||
onHide={() => setShowAddModal(false)} | ||
onAttach={(selected) => { | ||
Promise.all( | ||
|
@@ -112,7 +119,8 @@ const UserGroupsList = ({ userId, after, onPaginate }) => { | |
.finally(() => { | ||
setShowAddModal(false); | ||
}); | ||
}} | ||
} | ||
} | ||
/> | ||
)} | ||
</> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
Should be
resolveEntityFN
(since we havesearchFn
).I would also put but Fn params next to each other.