Skip to content
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

fix: Group and User management (CM-436) #9825

Merged
merged 6 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions webui/react/src/components/CreateGroupModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ const EDIT_VALUES: Messages = {
interface Props {
group?: V1GroupSearchResult;
groupRoles?: UserRole[];
onClose?: () => void;
onSuccess?: () => void;
}

const CreateGroupModalComponent: React.FC<Props> = ({ onClose, group, groupRoles }: Props) => {
const CreateGroupModalComponent: React.FC<Props> = ({ onSuccess, group, groupRoles }: Props) => {
const idPrefix = useId();
const [form] = Form.useForm();
const { rbacEnabled } = useObservable(determinedStore.info);
Expand Down Expand Up @@ -124,7 +124,7 @@ const CreateGroupModalComponent: React.FC<Props> = ({ onClose, group, groupRoles
}
openToast({ severity: 'Confirm', title: messages.API_SUCCESS_MESSAGE });
form.resetFields();
onClose?.();
onSuccess?.();
} catch (e) {
openToast({ severity: 'Error', title: messages.API_FAILURE_MESSAGE });
handleError(e, { silent: true, type: ErrorType.Input });
Expand Down
6 changes: 3 additions & 3 deletions webui/react/src/components/CreateUserModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ interface Props {
user?: DetailedUser;
viewOnly?: boolean;
userRoles?: Loadable<UserRole[]>;
onClose?: () => void;
onSuccess?: () => void;
}

interface FormInputs {
Expand All @@ -71,7 +71,7 @@ interface FormInputs {
}

const CreateUserModalComponent: React.FC<Props> = ({
onClose,
onSuccess,
user,
userRoles,
viewOnly,
Expand Down Expand Up @@ -149,7 +149,7 @@ const CreateUserModalComponent: React.FC<Props> = ({
});
form.resetFields();
}
onClose?.();
onSuccess?.();
} catch (e) {
openToast({
severity: 'Error',
Expand Down
6 changes: 3 additions & 3 deletions webui/react/src/components/DeleteGroupModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@ export const MODAL_HEADER = 'Delete Group';

interface Props {
group: V1GroupSearchResult;
onClose?: () => void;
onSuccess?: () => void;
}

const DeleteGroupModalComponent: React.FC<Props> = ({ onClose, group }: Props) => {
const DeleteGroupModalComponent: React.FC<Props> = ({ onSuccess, group }: Props) => {
const { openToast } = useToast();

const handleSubmit = async () => {
if (!group.group.groupId) return;
try {
await deleteGroup({ groupId: group.group.groupId });
openToast({ severity: 'Confirm', title: API_SUCCESS_MESSAGE });
onClose?.();
onSuccess?.();
} catch (e) {
openToast({ severity: 'Error', title: 'error deleting group' });
handleError(e, { silent: true, type: ErrorType.Input });
Expand Down
38 changes: 32 additions & 6 deletions webui/react/src/pages/Admin/GroupManagement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ interface DropdownProps {
fetchGroups: () => void;
group: V1GroupSearchResult;
availabeUsers: DetailedUser[];
onGroupsUpdate: () => void;
}

const MenuKey = {
Expand All @@ -59,6 +60,7 @@ const GroupActionDropdown = ({
expanded,
fetchGroups,
fetchGroup,
onGroupsUpdate,
group,
availabeUsers,
}: DropdownProps) => {
Expand Down Expand Up @@ -109,13 +111,17 @@ const GroupActionDropdown = ({
<Button icon={<Icon name="overflow-vertical" size="small" title="Action menu" />} />
</Dropdown>
<AddUsersToGroupModal.Component group={group} users={availabeUsers} onClose={onFinishEdit} />
<EditGroupModal.Component group={group} groupRoles={groupRoles} onClose={onFinishEdit} />
<DeleteGroupModal.Component group={group} onClose={fetchGroups} />
<EditGroupModal.Component group={group} groupRoles={groupRoles} onSuccess={onFinishEdit} />
<DeleteGroupModal.Component group={group} onSuccess={onGroupsUpdate} />
</div>
);
};

const GroupManagement: React.FC = () => {
interface Props {
onGroupsUpdate: () => void;
}

const GroupManagement: React.FC<Props> = ({ onGroupsUpdate }: Props) => {
const { rbacEnabled } = useObservable(determinedStore.info);
const [groups, setGroups] = useState<V1GroupSearchResult[]>([]);
const [groupUsers, setGroupUsers] = useState<V1GroupDetails[]>([]);
Expand All @@ -135,6 +141,12 @@ const GroupManagement: React.FC = () => {

const fetchGroups = useCallback(async (): Promise<void> => {
if (!('tableLimit' in settings) || !('tableOffset' in settings)) return;
if (settings.tableOffset > 0 && settings.tableOffset === total) {
// handle when last group is deleted on a page
updateSettings({
tableOffset: settings.tableOffset - settings.tableLimit,
});
}
johnkim-det marked this conversation as resolved.
Show resolved Hide resolved
try {
const response = await getGroups(
{
Expand All @@ -154,7 +166,7 @@ const GroupManagement: React.FC = () => {
} finally {
setIsLoading(false);
}
}, [settings]);
}, [settings, total, updateSettings]);

const fetchGroup = useCallback(
async (groupId: number): Promise<void> => {
Expand Down Expand Up @@ -251,6 +263,11 @@ const GroupManagement: React.FC = () => {
[groupUsers, canModifyGroups, RemoveUserFromGroupModal],
);

const handleGroupsUpdate = useCallback(() => {
fetchGroups();
onGroupsUpdate();
}, [fetchGroups, onGroupsUpdate]);

const columns = useMemo(() => {
const actionRenderer = (_: string, record: V1GroupSearchResult) => {
const userGroup = groupUsers.find((gr) => gr.groupId === record.group.groupId);
Expand All @@ -267,6 +284,7 @@ const GroupManagement: React.FC = () => {
fetchGroup={fetchGroup}
fetchGroups={fetchGroups}
group={record}
onGroupsUpdate={handleGroupsUpdate}
/>
) : null;
};
Expand Down Expand Up @@ -303,7 +321,15 @@ const GroupManagement: React.FC = () => {
width: DEFAULT_COLUMN_WIDTHS['action'],
},
];
}, [canModifyGroups, expandedKeys, fetchGroup, fetchGroups, groupUsers, users]);
}, [
canModifyGroups,
expandedKeys,
fetchGroup,
fetchGroups,
groupUsers,
users,
handleGroupsUpdate,
]);

const table = useMemo(() => {
return settings ? (
Expand Down Expand Up @@ -348,7 +374,7 @@ const GroupManagement: React.FC = () => {
title="Groups">
{canViewGroups && <div className={css.usersTable}>{table}</div>}
</Section>
<CreateGroupModal.Component onClose={fetchGroups} />
<CreateGroupModal.Component onSuccess={handleGroupsUpdate} />
{groupResult && (
<RemoveUserFromGroupModal.Component
fetchGroups={fetchGroups}
Expand Down
2 changes: 1 addition & 1 deletion webui/react/src/pages/Admin/UserManagement.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const Container: React.FC = () => {
<SettingsProvider>
<HelmetProvider>
<BrowserRouter>
<UserManagement />;
<UserManagement onUserCreate={() => {}} />;
</BrowserRouter>
</HelmetProvider>
</SettingsProvider>
Expand Down
18 changes: 14 additions & 4 deletions webui/react/src/pages/Admin/UserManagement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ const UserActionDropdown = ({ fetchUsers, user, groups, userManagementEnabled }:
<Dropdown menu={menuItems} placement="bottomRight" onClick={handleDropdown}>
<Button icon={<Icon name="overflow-vertical" size="small" title="Action menu" />} />
</Dropdown>
<ViewUserModal.Component user={user} userRoles={userRoles} viewOnly onClose={fetchUsers} />
<EditUserModal.Component user={user} userRoles={userRoles} onClose={fetchUsers} />
<ViewUserModal.Component user={user} userRoles={userRoles} viewOnly onSuccess={fetchUsers} />
<EditUserModal.Component user={user} userRoles={userRoles} onSuccess={fetchUsers} />
<ManageGroupsModal.Component
groupOptions={groups}
user={user}
Expand Down Expand Up @@ -207,7 +207,12 @@ const columnSettings = {
};

const userManagementSettings = userSettings.get(UserManagementSettings, 'user-management');
const UserManagement: React.FC = () => {

interface Props {
onUserCreate: () => void;
}

const UserManagement: React.FC<Props> = ({ onUserCreate }: Props) => {
const [selectedUserIds, setSelectedUserIds] = useState<React.Key[]>([]);
const [refresh, setRefresh] = useState<Record<string, never>>({});
const [nameFilter, setNameFilter] = useState<string>('');
Expand All @@ -228,6 +233,11 @@ const UserManagement: React.FC = () => {
[],
);

const handleUserCreate = () => {
onUserCreate();
fetchUsers();
};

const userResponse = useAsync(async () => {
try {
const params = {
Expand Down Expand Up @@ -560,7 +570,7 @@ const UserManagement: React.FC = () => {
<SkeletonTable columns={columns.length} />
)}
</Section>
<CreateUserModal.Component onClose={fetchUsers} />
<CreateUserModal.Component onSuccess={handleUserCreate} />
<ChangeUserStatusModal.Component
clearTableSelection={clearTableSelection}
fetchUsers={fetchUsers}
Expand Down
16 changes: 12 additions & 4 deletions webui/react/src/pages/Admin/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const SettingsContent: React.FC = () => {
const getGroupTotal = useCallback(async () => {
const response = await getGroups(
{
limit: 1,
limit: 0,
offset: 0,
},
{ signal: canceler.current.signal },
Expand All @@ -65,6 +65,14 @@ const SettingsContent: React.FC = () => {
[navigate],
);

const handleUserCreate = () => {
userStore.fetchUsers();
};

const handleGroupsUpdate = useCallback(() => {
getGroupTotal();
}, [getGroupTotal]);
johnkim-det marked this conversation as resolved.
Show resolved Hide resolved

const tabItems: PivotProps['items'] = useMemo(() => {
const items: PivotProps['items'] = [];

Expand All @@ -73,7 +81,7 @@ const SettingsContent: React.FC = () => {
_: () => null,
Loaded: (users) => {
items.push({
children: <UserManagement />,
children: <UserManagement onUserCreate={handleUserCreate} />,
key: TAB_KEYS[TabType.UserManagement],
label: `${TabType.UserManagement} (${users.length})`,
});
Expand All @@ -83,14 +91,14 @@ const SettingsContent: React.FC = () => {

if (rbacEnabled) {
items.push({
children: <GroupManagement />,
children: <GroupManagement onGroupsUpdate={handleGroupsUpdate} />,
key: TAB_KEYS[TabType.GroupManagement],
label: `${TabType.GroupManagement} ${totalGroup !== undefined ? `(${totalGroup})` : ''}`,
});
}

return items;
}, [canAdministrateUsers, rbacEnabled, totalGroup, loadableUsers]);
}, [canAdministrateUsers, rbacEnabled, totalGroup, loadableUsers, handleGroupsUpdate]);

return (
<Pivot
Expand Down
Loading