add datasets to permission groups page

This commit is contained in:
Nate Kelley 2025-01-22 10:26:40 -07:00
parent 2f47b45b41
commit aba1cef762
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
8 changed files with 263 additions and 13 deletions

View File

@ -72,7 +72,7 @@ export const getPermissionGroupDatasets = async ({
id
}: {
id: string;
}): Promise<GetPermissionGroupDatasetsResponse> => {
}): Promise<GetPermissionGroupDatasetsResponse[]> => {
return await mainApi.get(`/permission_groups/${id}/datasets`).then((res) => res.data);
};

View File

@ -20,6 +20,7 @@ export interface GetPermissionGroupUsersResponse {
export interface GetPermissionGroupDatasetsResponse {
id: string;
assigned: boolean;
name: string;
}
export interface GetPermissionGroupDatasetGroupsResponse {

View File

@ -10,7 +10,7 @@ export const PermissionSearchAndListWrapper: React.FC<{
}> = React.memo(
({ children, searchText, handleSearchChange, searchChildren, searchPlaceholder }) => {
return (
<div className="flex h-full flex-col space-y-3 pb-12">
<div className="flex flex-col space-y-3">
<div className="flex items-center justify-between">
<PermissionSearch
searchText={searchText}
@ -19,7 +19,7 @@ export const PermissionSearchAndListWrapper: React.FC<{
/>
{searchChildren}
</div>
{children}
<div className="">{children}</div>
</div>
);
}

View File

@ -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 (
<BusterListSelectedOptionPopupContainer
selectedRowKeys={selectedRowKeys}
onSelectChange={onSelectChange}
buttons={[
<PermissionAssignedButton
key="assign"
text="assigned"
selectedRowKeys={selectedRowKeys}
onSelectChange={onSelectChange}
onUpdate={onSelectAssigned}
/>
]}
/>
);
});
PermissionGroupDatasetSelectedPopup.displayName = 'PermissionGroupDatasetSelectedPopup';

View File

@ -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 (
<Button type="default" icon={<AppMaterialIcons icon="add" />} onClick={onOpenNewDatasetModal}>
New dataset
</Button>
);
}, []);
return (
<>
<PermissionSearchAndListWrapper
searchText={searchText}
handleSearchChange={handleSearchChange}
searchPlaceholder="Search by dataset name..."
searchChildren={NewDatasetButton}>
<PermissionGroupDatasetsListContainer
filteredDatasets={filteredItems}
permissionGroupId={permissionGroupId}
/>
</PermissionSearchAndListWrapper>
<NewDatasetModal open={isNewDatasetModalOpen} onClose={onCloseNewDatasetModal} />
</>
);
};

View File

@ -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<string[]>([]);
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 (
<div className="flex justify-end">
<PermissionAssignedCell
id={permissionGroup.id}
assigned={assigned}
text="assigned"
onSelect={onSelectAssigned}
/>
</div>
);
}
}
],
[]
);
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 (
<InfiniteListContainer
popupNode={
<PermissionGroupDatasetSelectedPopup
selectedRowKeys={selectedRowKeys}
onSelectChange={setSelectedRowKeys}
permissionGroupId={permissionGroupId}
/>
}>
<BusterInfiniteList
columns={columns}
rows={rows}
showHeader={false}
showSelectAll={false}
useRowClickSelectChange={false}
selectedRowKeys={selectedRowKeys}
onSelectChange={setSelectedRowKeys}
emptyState={<EmptyStateList text="No dataset groups found" />}
/>
</InfiniteListContainer>
);
});
PermissionGroupDatasetsListContainer.displayName = 'PermissionGroupUsersListContainer';

View File

@ -1,3 +1,17 @@
export default function Page() {
return <div>Datasets</div>;
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 (
<HydrationBoundary state={dehydrate(queryClient)}>
<PermissionGroupDatasetsController permissionGroupId={permissionGroupId} />
</HydrationBoundary>
);
}

View File

@ -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';