From aba1cef7629308fac6dfeab08140b0962e5bcf18 Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Wed, 22 Jan 2025 10:26:40 -0700 Subject: [PATCH] add datasets to permission groups page --- .../buster-rest/permission_groups/requests.ts | 2 +- .../permission_groups/responseInterfaces.ts | 1 + .../PermissionSearchAndListWrapper.tsx | 4 +- .../PermissionGroupDatasetSelectedPopup.tsx | 42 +++++ .../PermissionGroupDatasetsController.tsx | 56 +++++++ .../PermissionGroupDatasetsListContainer.tsx | 144 ++++++++++++++++++ .../[permissionGroupId]/datasets/page.tsx | 18 ++- .../PermissionGroupUsersListContainer.tsx | 9 +- 8 files changed, 263 insertions(+), 13 deletions(-) create mode 100644 web/src/app/app/settings/permission-groups/[permissionGroupId]/datasets/PermissionGroupDatasetSelectedPopup.tsx create mode 100644 web/src/app/app/settings/permission-groups/[permissionGroupId]/datasets/PermissionGroupDatasetsController.tsx create mode 100644 web/src/app/app/settings/permission-groups/[permissionGroupId]/datasets/PermissionGroupDatasetsListContainer.tsx diff --git a/web/src/api/buster-rest/permission_groups/requests.ts b/web/src/api/buster-rest/permission_groups/requests.ts index 2b4480dbc..0ff43cc92 100644 --- a/web/src/api/buster-rest/permission_groups/requests.ts +++ b/web/src/api/buster-rest/permission_groups/requests.ts @@ -72,7 +72,7 @@ export const getPermissionGroupDatasets = async ({ id }: { id: string; -}): Promise => { +}): Promise => { return await mainApi.get(`/permission_groups/${id}/datasets`).then((res) => res.data); }; diff --git a/web/src/api/buster-rest/permission_groups/responseInterfaces.ts b/web/src/api/buster-rest/permission_groups/responseInterfaces.ts index 0b354df82..a2896d55b 100644 --- a/web/src/api/buster-rest/permission_groups/responseInterfaces.ts +++ b/web/src/api/buster-rest/permission_groups/responseInterfaces.ts @@ -20,6 +20,7 @@ export interface GetPermissionGroupUsersResponse { export interface GetPermissionGroupDatasetsResponse { id: string; assigned: boolean; + name: string; } export interface GetPermissionGroupDatasetGroupsResponse { diff --git a/web/src/app/app/_components/PermissionComponents/PermissionSearchAndListWrapper.tsx b/web/src/app/app/_components/PermissionComponents/PermissionSearchAndListWrapper.tsx index 3fb2e2475..27b47d40a 100644 --- a/web/src/app/app/_components/PermissionComponents/PermissionSearchAndListWrapper.tsx +++ b/web/src/app/app/_components/PermissionComponents/PermissionSearchAndListWrapper.tsx @@ -10,7 +10,7 @@ export const PermissionSearchAndListWrapper: React.FC<{ }> = React.memo( ({ children, searchText, handleSearchChange, searchChildren, searchPlaceholder }) => { return ( -
+
{searchChildren}
- {children} +
{children}
); } diff --git a/web/src/app/app/settings/permission-groups/[permissionGroupId]/datasets/PermissionGroupDatasetSelectedPopup.tsx b/web/src/app/app/settings/permission-groups/[permissionGroupId]/datasets/PermissionGroupDatasetSelectedPopup.tsx new file mode 100644 index 000000000..13a54f22b --- /dev/null +++ b/web/src/app/app/settings/permission-groups/[permissionGroupId]/datasets/PermissionGroupDatasetSelectedPopup.tsx @@ -0,0 +1,42 @@ +import { + useUpdatePermissionGroupDatasets, + useUpdatePermissionGroupUsers, + useUpdateUserDatasets +} from '@/api/buster-rest'; +import { PermissionAssignedButton } from '@/app/app/_components/PermissionComponents'; +import { BusterListSelectedOptionPopupContainer } from '@/components/list'; +import { useMemoizedFn } from 'ahooks'; +import React from 'react'; + +export const PermissionGroupDatasetSelectedPopup: React.FC<{ + selectedRowKeys: string[]; + onSelectChange: (selectedRowKeys: string[]) => void; + permissionGroupId: string; +}> = React.memo(({ selectedRowKeys, onSelectChange, permissionGroupId }) => { + const { mutateAsync: updatePermissionGroupDatasets } = useUpdatePermissionGroupDatasets(); + + const onSelectAssigned = useMemoizedFn(async (params: { id: string; assigned: boolean }[]) => { + await updatePermissionGroupDatasets({ + permissionGroupId, + data: params + }); + }); + + return ( + + ]} + /> + ); +}); + +PermissionGroupDatasetSelectedPopup.displayName = 'PermissionGroupDatasetSelectedPopup'; diff --git a/web/src/app/app/settings/permission-groups/[permissionGroupId]/datasets/PermissionGroupDatasetsController.tsx b/web/src/app/app/settings/permission-groups/[permissionGroupId]/datasets/PermissionGroupDatasetsController.tsx new file mode 100644 index 000000000..c99d7a041 --- /dev/null +++ b/web/src/app/app/settings/permission-groups/[permissionGroupId]/datasets/PermissionGroupDatasetsController.tsx @@ -0,0 +1,56 @@ +'use client'; + +import { useGetPermissionGroupDatasets } from '@/api/buster-rest'; +import { useDebounceSearch } from '@/hooks/useDebounceSearch'; +import { PermissionSearchAndListWrapper } from '@appComponents/PermissionComponents'; +import React, { useMemo, useState } from 'react'; +import { Button } from 'antd'; +import { AppMaterialIcons } from '@/components/icons'; +import { PermissionGroupDatasetsListContainer } from './PermissionGroupDatasetsListContainer'; +import { useMemoizedFn } from 'ahooks'; +import { NewDatasetModal } from '@/app/app/_components/NewDatasetModal'; + +export const PermissionGroupDatasetsController: React.FC<{ + permissionGroupId: string; +}> = ({ permissionGroupId }) => { + const { data } = useGetPermissionGroupDatasets(permissionGroupId); + const [isNewDatasetModalOpen, setIsNewDatasetModalOpen] = useState(false); + + const { filteredItems, handleSearchChange, searchText } = useDebounceSearch({ + items: data || [], + searchPredicate: (item, searchText) => item.name.includes(searchText) + }); + + const onCloseNewDatasetModal = useMemoizedFn(() => { + setIsNewDatasetModalOpen(false); + }); + + const onOpenNewDatasetModal = useMemoizedFn(() => { + setIsNewDatasetModalOpen(true); + }); + + const NewDatasetButton: React.ReactNode = useMemo(() => { + return ( + + ); + }, []); + + return ( + <> + + + + + + + ); +}; diff --git a/web/src/app/app/settings/permission-groups/[permissionGroupId]/datasets/PermissionGroupDatasetsListContainer.tsx b/web/src/app/app/settings/permission-groups/[permissionGroupId]/datasets/PermissionGroupDatasetsListContainer.tsx new file mode 100644 index 000000000..855a07c10 --- /dev/null +++ b/web/src/app/app/settings/permission-groups/[permissionGroupId]/datasets/PermissionGroupDatasetsListContainer.tsx @@ -0,0 +1,144 @@ +import { + GetPermissionGroupDatasetsResponse, + GetPermissionGroupUsersResponse, + useUpdatePermissionGroupDatasets, + useUpdatePermissionGroupUsers +} from '@/api/buster-rest'; +import { PermissionAssignedCell } from '@/app/app/_components/PermissionComponents'; +import { + BusterInfiniteList, + BusterListColumn, + BusterListRowItem, + EmptyStateList, + InfiniteListContainer +} from '@/components/list'; +import { BusterRoutes, createBusterRoute } from '@/routes'; +import { useMemoizedFn } from 'ahooks'; +import React, { useMemo, useState } from 'react'; +import { ListUserItem } from '@/app/app/_components/ListContent'; +import { PermissionGroupDatasetSelectedPopup } from './PermissionGroupDatasetSelectedPopup'; + +export const PermissionGroupDatasetsListContainer: React.FC<{ + filteredDatasets: GetPermissionGroupDatasetsResponse[]; + permissionGroupId: string; +}> = React.memo(({ filteredDatasets, permissionGroupId }) => { + const [selectedRowKeys, setSelectedRowKeys] = useState([]); + const { mutateAsync: updatePermissionGroupDatasets } = useUpdatePermissionGroupDatasets(); + + const onSelectAssigned = useMemoizedFn(async (params: { id: string; assigned: boolean }) => { + await updatePermissionGroupDatasets({ + permissionGroupId, + data: [params] + }); + }); + + const columns: BusterListColumn[] = useMemo( + () => [ + { + title: 'Name', + dataIndex: 'name' + }, + { + title: 'Assigned', + dataIndex: 'assigned', + width: 130 + 85, + render: (assigned: boolean, permissionGroup: GetPermissionGroupUsersResponse) => { + return ( +
+ +
+ ); + } + } + ], + [] + ); + + const { cannotQueryPermissionUsers, canQueryPermissionUsers } = useMemo(() => { + const result: { + cannotQueryPermissionUsers: BusterListRowItem[]; + canQueryPermissionUsers: BusterListRowItem[]; + } = filteredDatasets.reduce<{ + cannotQueryPermissionUsers: BusterListRowItem[]; + canQueryPermissionUsers: BusterListRowItem[]; + }>( + (acc, dataset) => { + const datasetItem: BusterListRowItem = { + id: dataset.id, + data: dataset, + link: createBusterRoute({ + route: BusterRoutes.APP_SETTINGS_USERS_ID, + userId: dataset.id + }) + }; + if (dataset.assigned) { + acc.canQueryPermissionUsers.push(datasetItem); + } else { + acc.cannotQueryPermissionUsers.push(datasetItem); + } + return acc; + }, + { + cannotQueryPermissionUsers: [] as BusterListRowItem[], + canQueryPermissionUsers: [] as BusterListRowItem[] + } + ); + return result; + }, [filteredDatasets]); + + const rows = useMemo( + () => + [ + { + id: 'header-assigned', + data: {}, + hidden: canQueryPermissionUsers.length === 0, + rowSection: { + title: 'Assigned', + secondaryTitle: canQueryPermissionUsers.length.toString() + } + }, + ...canQueryPermissionUsers, + { + id: 'header-not-assigned', + data: {}, + hidden: cannotQueryPermissionUsers.length === 0, + rowSection: { + title: 'Not Assigned', + secondaryTitle: cannotQueryPermissionUsers.length.toString() + } + }, + ...cannotQueryPermissionUsers + ].filter((row) => !(row as any).hidden), + [canQueryPermissionUsers, cannotQueryPermissionUsers] + ); + + return ( + + }> + } + /> + + ); +}); + +PermissionGroupDatasetsListContainer.displayName = 'PermissionGroupUsersListContainer'; diff --git a/web/src/app/app/settings/permission-groups/[permissionGroupId]/datasets/page.tsx b/web/src/app/app/settings/permission-groups/[permissionGroupId]/datasets/page.tsx index bc6961f43..817ccb341 100644 --- a/web/src/app/app/settings/permission-groups/[permissionGroupId]/datasets/page.tsx +++ b/web/src/app/app/settings/permission-groups/[permissionGroupId]/datasets/page.tsx @@ -1,3 +1,17 @@ -export default function Page() { - return
Datasets
; +import { prefetchPermissionGroupDatasets } from '@/api/buster-rest'; +import { HydrationBoundary, dehydrate } from '@tanstack/react-query'; +import { PermissionGroupDatasetsController } from './PermissionGroupDatasetsController'; + +export default async function Page({ + params: { permissionGroupId } +}: { + params: { permissionGroupId: string }; +}) { + const queryClient = await prefetchPermissionGroupDatasets(permissionGroupId); + + return ( + + + + ); } diff --git a/web/src/app/app/settings/permission-groups/[permissionGroupId]/users/PermissionGroupUsersListContainer.tsx b/web/src/app/app/settings/permission-groups/[permissionGroupId]/users/PermissionGroupUsersListContainer.tsx index 4ae031e1c..75ddd1517 100644 --- a/web/src/app/app/settings/permission-groups/[permissionGroupId]/users/PermissionGroupUsersListContainer.tsx +++ b/web/src/app/app/settings/permission-groups/[permissionGroupId]/users/PermissionGroupUsersListContainer.tsx @@ -1,9 +1,4 @@ -import { - BusterUserDatasetGroup, - GetPermissionGroupUsersResponse, - useUpdatePermissionGroupUsers, - useUpdateUserDatasetGroups -} from '@/api/buster-rest'; +import { GetPermissionGroupUsersResponse, useUpdatePermissionGroupUsers } from '@/api/buster-rest'; import { PermissionAssignedCell } from '@/app/app/_components/PermissionComponents'; import { BusterInfiniteList, @@ -15,8 +10,6 @@ import { import { BusterRoutes, createBusterRoute } from '@/routes'; import { useMemoizedFn } from 'ahooks'; import React, { useMemo, useState } from 'react'; -import pluralize from 'pluralize'; -import { Text } from '@/components/text'; import { ListUserItem } from '@/app/app/_components/ListContent'; import { PermissionGroupUsersSelectedPopup } from './PermissionGroupUsersSelectedPopup';