mirror of https://github.com/buster-so/buster.git
add datasets to permission groups page
This commit is contained in:
parent
2f47b45b41
commit
aba1cef762
|
@ -72,7 +72,7 @@ export const getPermissionGroupDatasets = async ({
|
||||||
id
|
id
|
||||||
}: {
|
}: {
|
||||||
id: string;
|
id: string;
|
||||||
}): Promise<GetPermissionGroupDatasetsResponse> => {
|
}): Promise<GetPermissionGroupDatasetsResponse[]> => {
|
||||||
return await mainApi.get(`/permission_groups/${id}/datasets`).then((res) => res.data);
|
return await mainApi.get(`/permission_groups/${id}/datasets`).then((res) => res.data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ export interface GetPermissionGroupUsersResponse {
|
||||||
export interface GetPermissionGroupDatasetsResponse {
|
export interface GetPermissionGroupDatasetsResponse {
|
||||||
id: string;
|
id: string;
|
||||||
assigned: boolean;
|
assigned: boolean;
|
||||||
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GetPermissionGroupDatasetGroupsResponse {
|
export interface GetPermissionGroupDatasetGroupsResponse {
|
||||||
|
|
|
@ -10,7 +10,7 @@ export const PermissionSearchAndListWrapper: React.FC<{
|
||||||
}> = React.memo(
|
}> = React.memo(
|
||||||
({ children, searchText, handleSearchChange, searchChildren, searchPlaceholder }) => {
|
({ children, searchText, handleSearchChange, searchChildren, searchPlaceholder }) => {
|
||||||
return (
|
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">
|
<div className="flex items-center justify-between">
|
||||||
<PermissionSearch
|
<PermissionSearch
|
||||||
searchText={searchText}
|
searchText={searchText}
|
||||||
|
@ -19,7 +19,7 @@ export const PermissionSearchAndListWrapper: React.FC<{
|
||||||
/>
|
/>
|
||||||
{searchChildren}
|
{searchChildren}
|
||||||
</div>
|
</div>
|
||||||
{children}
|
<div className="">{children}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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';
|
|
@ -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} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
|
@ -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';
|
|
@ -1,3 +1,17 @@
|
||||||
export default function Page() {
|
import { prefetchPermissionGroupDatasets } from '@/api/buster-rest';
|
||||||
return <div>Datasets</div>;
|
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>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,4 @@
|
||||||
import {
|
import { GetPermissionGroupUsersResponse, useUpdatePermissionGroupUsers } from '@/api/buster-rest';
|
||||||
BusterUserDatasetGroup,
|
|
||||||
GetPermissionGroupUsersResponse,
|
|
||||||
useUpdatePermissionGroupUsers,
|
|
||||||
useUpdateUserDatasetGroups
|
|
||||||
} from '@/api/buster-rest';
|
|
||||||
import { PermissionAssignedCell } from '@/app/app/_components/PermissionComponents';
|
import { PermissionAssignedCell } from '@/app/app/_components/PermissionComponents';
|
||||||
import {
|
import {
|
||||||
BusterInfiniteList,
|
BusterInfiniteList,
|
||||||
|
@ -15,8 +10,6 @@ import {
|
||||||
import { BusterRoutes, createBusterRoute } from '@/routes';
|
import { BusterRoutes, createBusterRoute } from '@/routes';
|
||||||
import { useMemoizedFn } from 'ahooks';
|
import { useMemoizedFn } from 'ahooks';
|
||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import pluralize from 'pluralize';
|
|
||||||
import { Text } from '@/components/text';
|
|
||||||
import { ListUserItem } from '@/app/app/_components/ListContent';
|
import { ListUserItem } from '@/app/app/_components/ListContent';
|
||||||
import { PermissionGroupUsersSelectedPopup } from './PermissionGroupUsersSelectedPopup';
|
import { PermissionGroupUsersSelectedPopup } from './PermissionGroupUsersSelectedPopup';
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue