mirror of https://github.com/buster-so/buster.git
permission groups components
This commit is contained in:
parent
1495ae4533
commit
e5a1455b9e
|
@ -1,4 +1,5 @@
|
|||
import React, { lazy, useMemo, useState } from 'react';
|
||||
import type React from 'react';
|
||||
import { lazy, useMemo, useState } from 'react';
|
||||
import { useGetDatasets } from '@/api/buster_rest/datasets';
|
||||
import { useIsUserAdmin } from '@/api/buster_rest/users/useGetUserInfo';
|
||||
import { AppPageLayout } from '@/components/ui/layouts/AppPageLayout';
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, { lazy, useMemo, useState } from 'react';
|
||||
import type React from 'react';
|
||||
import { lazy, useMemo, useState } from 'react';
|
||||
import { useGetUserDatasets } from '@/api/buster_rest/users/permissions';
|
||||
import { PermissionSearchAndListWrapper } from '@/components/features/permissions';
|
||||
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
import type React from 'react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useGetPermissionGroupDatasetGroups } from '@/api/buster_rest/permission_groups';
|
||||
import {
|
||||
NewDatasetGroupModal,
|
||||
PermissionSearchAndListWrapper,
|
||||
} from '@/components/features/permissions';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
import { Plus } from '@/components/ui/icons';
|
||||
import { useDebounceSearch } from '@/hooks/useDebounceSearch';
|
||||
import { useMemoizedFn } from '@/hooks/useMemoizedFn';
|
||||
import { PermissionGroupDatasetGroupsListContainer } from './PermissionGroupDatasetsListContainer';
|
||||
|
||||
export const PermissionGroupDatasetGroupsController: React.FC<{
|
||||
permissionGroupId: string;
|
||||
}> = ({ permissionGroupId }) => {
|
||||
const { data } = useGetPermissionGroupDatasetGroups(permissionGroupId);
|
||||
const [isNewDatasetGroupModalOpen, setIsNewDatasetGroupModalOpen] = useState(false);
|
||||
|
||||
const { filteredItems, handleSearchChange, searchText } = useDebounceSearch({
|
||||
items: data || [],
|
||||
searchPredicate: (item, searchText) =>
|
||||
item.name.toLowerCase().includes(searchText.toLowerCase()),
|
||||
});
|
||||
|
||||
const onCloseNewDatasetGroupModal = useMemoizedFn(() => {
|
||||
setIsNewDatasetGroupModalOpen(false);
|
||||
});
|
||||
|
||||
const onOpenNewDatasetGroupModal = useMemoizedFn(() => {
|
||||
setIsNewDatasetGroupModalOpen(true);
|
||||
});
|
||||
|
||||
const NewDatasetGroupButton: React.ReactNode = useMemo(() => {
|
||||
return (
|
||||
<Button prefix={<Plus />} onClick={onOpenNewDatasetGroupModal}>
|
||||
New dataset group
|
||||
</Button>
|
||||
);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<PermissionSearchAndListWrapper
|
||||
searchText={searchText}
|
||||
handleSearchChange={handleSearchChange}
|
||||
searchPlaceholder="Search by permission group name..."
|
||||
searchChildren={NewDatasetGroupButton}
|
||||
>
|
||||
<PermissionGroupDatasetGroupsListContainer
|
||||
filteredDatasetGroups={filteredItems}
|
||||
permissionGroupId={permissionGroupId}
|
||||
/>
|
||||
</PermissionSearchAndListWrapper>
|
||||
|
||||
<NewDatasetGroupModal
|
||||
isOpen={isNewDatasetGroupModalOpen}
|
||||
onClose={onCloseNewDatasetGroupModal}
|
||||
datasetId={null}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,36 @@
|
|||
import React from 'react';
|
||||
import { useUpdatePermissionGroupDatasetGroups } from '@/api/buster_rest/permission_groups';
|
||||
import { PermissionAssignedButton } from '@/components/features/permissions';
|
||||
import { BusterListSelectedOptionPopupContainer } from '@/components/ui/list';
|
||||
import { useMemoizedFn } from '@/hooks/useMemoizedFn';
|
||||
|
||||
export const PermissionGroupDatasetGroupSelectedPopup: React.FC<{
|
||||
selectedRowKeys: string[];
|
||||
onSelectChange: (selectedRowKeys: string[]) => void;
|
||||
permissionGroupId: string;
|
||||
}> = React.memo(({ selectedRowKeys, onSelectChange, permissionGroupId }) => {
|
||||
const { mutateAsync: updatePermissionGroupDatasetGroups } =
|
||||
useUpdatePermissionGroupDatasetGroups(permissionGroupId);
|
||||
|
||||
const onSelectAssigned = useMemoizedFn(async (params: { id: string; assigned: boolean }[]) => {
|
||||
await updatePermissionGroupDatasetGroups(params);
|
||||
});
|
||||
|
||||
return (
|
||||
<BusterListSelectedOptionPopupContainer
|
||||
selectedRowKeys={selectedRowKeys}
|
||||
onSelectChange={onSelectChange}
|
||||
buttons={[
|
||||
<PermissionAssignedButton
|
||||
key="assign"
|
||||
text="assigned"
|
||||
selectedRowKeys={selectedRowKeys}
|
||||
onSelectChange={onSelectChange}
|
||||
onUpdate={onSelectAssigned}
|
||||
/>,
|
||||
]}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
PermissionGroupDatasetGroupSelectedPopup.displayName = 'PermissionGroupDatasetGroupSelectedPopup';
|
|
@ -0,0 +1,142 @@
|
|||
import React, { useMemo, useState } from 'react';
|
||||
import type { GetPermissionGroupDatasetGroupsResponse } from '@/api/asset_interfaces';
|
||||
import { useUpdatePermissionGroupDatasetGroups } from '@/api/buster_rest/permission_groups';
|
||||
import { PermissionAssignedCell } from '@/components/features/permissions';
|
||||
import {
|
||||
type BusterListColumn,
|
||||
type BusterListRowItem,
|
||||
createListItem,
|
||||
EmptyStateList,
|
||||
InfiniteListContainer,
|
||||
} from '@/components/ui/list';
|
||||
import { BusterInfiniteList } from '@/components/ui/list/BusterInfiniteList';
|
||||
import { useMemoizedFn } from '@/hooks/useMemoizedFn';
|
||||
import { PermissionGroupDatasetGroupSelectedPopup } from './PermissionGroupDatasetSelectedPopup';
|
||||
|
||||
export const PermissionGroupDatasetGroupsListContainer: React.FC<{
|
||||
filteredDatasetGroups: GetPermissionGroupDatasetGroupsResponse[];
|
||||
permissionGroupId: string;
|
||||
}> = React.memo(({ filteredDatasetGroups, permissionGroupId }) => {
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState<string[]>([]);
|
||||
const { mutateAsync: updatePermissionGroupDatasetGroups } =
|
||||
useUpdatePermissionGroupDatasetGroups(permissionGroupId);
|
||||
|
||||
const onSelectAssigned = useMemoizedFn(async (params: { id: string; assigned: boolean }) => {
|
||||
await updatePermissionGroupDatasetGroups([params]);
|
||||
});
|
||||
|
||||
const columns: BusterListColumn<GetPermissionGroupDatasetGroupsResponse>[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
},
|
||||
{
|
||||
title: 'Assigned',
|
||||
dataIndex: 'assigned',
|
||||
width: 130 + 85,
|
||||
render: (assigned: boolean, datasetGroup: GetPermissionGroupDatasetGroupsResponse) => {
|
||||
return (
|
||||
<div className="flex justify-end">
|
||||
<PermissionAssignedCell
|
||||
id={datasetGroup.id}
|
||||
assigned={assigned}
|
||||
text="assigned"
|
||||
onSelect={onSelectAssigned}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
[]
|
||||
);
|
||||
|
||||
const { cannotQueryPermissionDatasetGroups, canQueryPermissionDatasetGroups } = useMemo(() => {
|
||||
const createPermissionGroupDatasetGroupListItem =
|
||||
createListItem<GetPermissionGroupDatasetGroupsResponse>();
|
||||
const result: {
|
||||
cannotQueryPermissionDatasetGroups: BusterListRowItem<GetPermissionGroupDatasetGroupsResponse>[];
|
||||
canQueryPermissionDatasetGroups: BusterListRowItem<GetPermissionGroupDatasetGroupsResponse>[];
|
||||
} = filteredDatasetGroups.reduce<{
|
||||
cannotQueryPermissionDatasetGroups: BusterListRowItem<GetPermissionGroupDatasetGroupsResponse>[];
|
||||
canQueryPermissionDatasetGroups: BusterListRowItem<GetPermissionGroupDatasetGroupsResponse>[];
|
||||
}>(
|
||||
(acc, permissionGroupDatasetGroup) => {
|
||||
const permissionGroupDatasetGroupItem: BusterListRowItem<GetPermissionGroupDatasetGroupsResponse> =
|
||||
createPermissionGroupDatasetGroupListItem({
|
||||
id: permissionGroupDatasetGroup.id,
|
||||
data: permissionGroupDatasetGroup,
|
||||
link: {
|
||||
to: '/app/settings/permission-groups/$permissionGroupId/users',
|
||||
params: {
|
||||
permissionGroupId: permissionGroupDatasetGroup.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
if (permissionGroupDatasetGroup.assigned) {
|
||||
acc.canQueryPermissionDatasetGroups.push(permissionGroupDatasetGroupItem);
|
||||
} else {
|
||||
acc.cannotQueryPermissionDatasetGroups.push(permissionGroupDatasetGroupItem);
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
cannotQueryPermissionDatasetGroups: [],
|
||||
canQueryPermissionDatasetGroups: [],
|
||||
}
|
||||
);
|
||||
return result;
|
||||
}, [filteredDatasetGroups]);
|
||||
|
||||
const rows: BusterListRowItem<GetPermissionGroupDatasetGroupsResponse>[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
id: 'header-assigned',
|
||||
data: null,
|
||||
hidden: canQueryPermissionDatasetGroups.length === 0,
|
||||
rowSection: {
|
||||
title: 'Assigned',
|
||||
secondaryTitle: canQueryPermissionDatasetGroups.length.toString(),
|
||||
},
|
||||
},
|
||||
...canQueryPermissionDatasetGroups,
|
||||
{
|
||||
id: 'header-not-assigned',
|
||||
data: null,
|
||||
hidden: cannotQueryPermissionDatasetGroups.length === 0,
|
||||
rowSection: {
|
||||
title: 'Not assigned',
|
||||
secondaryTitle: cannotQueryPermissionDatasetGroups.length.toString(),
|
||||
},
|
||||
},
|
||||
...cannotQueryPermissionDatasetGroups,
|
||||
],
|
||||
[canQueryPermissionDatasetGroups, cannotQueryPermissionDatasetGroups]
|
||||
);
|
||||
|
||||
return (
|
||||
<InfiniteListContainer
|
||||
popupNode={
|
||||
<PermissionGroupDatasetGroupSelectedPopup
|
||||
selectedRowKeys={selectedRowKeys}
|
||||
onSelectChange={setSelectedRowKeys}
|
||||
permissionGroupId={permissionGroupId}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<BusterInfiniteList
|
||||
columns={columns}
|
||||
rows={rows}
|
||||
showHeader={false}
|
||||
showSelectAll={false}
|
||||
useRowClickSelectChange={false}
|
||||
selectedRowKeys={selectedRowKeys}
|
||||
onSelectChange={setSelectedRowKeys}
|
||||
emptyState={useMemo(() => <EmptyStateList text="No dataset groups found" />, [])}
|
||||
/>
|
||||
</InfiniteListContainer>
|
||||
);
|
||||
});
|
||||
|
||||
PermissionGroupDatasetGroupsListContainer.displayName = 'PermissionGroupDatasetGroupsListContainer';
|
|
@ -0,0 +1 @@
|
|||
export * from './PermissionGroupDatasetGroupsController';
|
|
@ -0,0 +1,38 @@
|
|||
import React from 'react';
|
||||
import { useUpdatePermissionGroupDatasets } from '@/api/buster_rest/permission_groups';
|
||||
import { PermissionAssignedButton } from '@/components/features/permissions';
|
||||
import { BusterListSelectedOptionPopupContainer } from '@/components/ui/list';
|
||||
import { useMemoizedFn } from '@/hooks/useMemoizedFn';
|
||||
|
||||
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,61 @@
|
|||
import type React from 'react';
|
||||
import { lazy, useMemo, useState } from 'react';
|
||||
import { useGetPermissionGroupDatasets } from '@/api/buster_rest/permission_groups';
|
||||
import { PermissionSearchAndListWrapper } from '@/components/features/permissions';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
import { Plus } from '@/components/ui/icons';
|
||||
import { useDebounceSearch } from '@/hooks/useDebounceSearch';
|
||||
import { useMemoizedFn } from '@/hooks/useMemoizedFn';
|
||||
import { PermissionGroupDatasetsListContainer } from './PermissionGroupDatasetsListContainer';
|
||||
|
||||
const NewDatasetModal = lazy(() =>
|
||||
import('@/components/features/modals/NewDatasetModal').then((mod) => ({
|
||||
default: mod.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 prefix={<Plus />} 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 React, { useMemo, useState } from 'react';
|
||||
import type { GetPermissionGroupDatasetsResponse } from '@/api/asset_interfaces';
|
||||
import { useUpdatePermissionGroupDatasets } from '@/api/buster_rest/permission_groups';
|
||||
import { PermissionAssignedCell } from '@/components/features/permissions';
|
||||
import {
|
||||
type BusterListColumn,
|
||||
type BusterListRowItem,
|
||||
createListItem,
|
||||
EmptyStateList,
|
||||
InfiniteListContainer,
|
||||
} from '@/components/ui/list';
|
||||
import { BusterInfiniteList } from '@/components/ui/list/BusterInfiniteList';
|
||||
import { useMemoizedFn } from '@/hooks/useMemoizedFn';
|
||||
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<GetPermissionGroupDatasetsResponse>[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
},
|
||||
{
|
||||
title: 'Assigned',
|
||||
dataIndex: 'assigned',
|
||||
width: 130 + 85,
|
||||
render: (assigned, dataset: GetPermissionGroupDatasetsResponse) => {
|
||||
return (
|
||||
<div className="flex justify-end">
|
||||
<PermissionAssignedCell
|
||||
id={dataset.id}
|
||||
assigned={assigned}
|
||||
text="assigned"
|
||||
onSelect={onSelectAssigned}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
[]
|
||||
);
|
||||
|
||||
const { cannotQueryPermissionUsers, canQueryPermissionUsers } = useMemo(() => {
|
||||
const createPermissionGroupDatasetListItem =
|
||||
createListItem<GetPermissionGroupDatasetsResponse>();
|
||||
const result: {
|
||||
cannotQueryPermissionUsers: BusterListRowItem<GetPermissionGroupDatasetsResponse>[];
|
||||
canQueryPermissionUsers: BusterListRowItem<GetPermissionGroupDatasetsResponse>[];
|
||||
} = filteredDatasets.reduce<{
|
||||
cannotQueryPermissionUsers: BusterListRowItem<GetPermissionGroupDatasetsResponse>[];
|
||||
canQueryPermissionUsers: BusterListRowItem<GetPermissionGroupDatasetsResponse>[];
|
||||
}>(
|
||||
(acc, dataset) => {
|
||||
const datasetItem: BusterListRowItem<GetPermissionGroupDatasetsResponse> =
|
||||
createPermissionGroupDatasetListItem({
|
||||
id: dataset.id,
|
||||
data: dataset,
|
||||
link: {
|
||||
to: '/app/settings/datasets/$datasetId',
|
||||
params: {
|
||||
datasetId: dataset.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
if (dataset.assigned) {
|
||||
acc.canQueryPermissionUsers.push(datasetItem);
|
||||
} else {
|
||||
acc.cannotQueryPermissionUsers.push(datasetItem);
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
cannotQueryPermissionUsers: [],
|
||||
canQueryPermissionUsers: [],
|
||||
}
|
||||
);
|
||||
return result;
|
||||
}, [filteredDatasets]);
|
||||
|
||||
const rows: BusterListRowItem<GetPermissionGroupDatasetsResponse>[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
id: 'header-assigned',
|
||||
data: null,
|
||||
hidden: canQueryPermissionUsers.length === 0,
|
||||
rowSection: {
|
||||
title: 'Assigned',
|
||||
secondaryTitle: canQueryPermissionUsers.length.toString(),
|
||||
},
|
||||
},
|
||||
...canQueryPermissionUsers,
|
||||
{
|
||||
id: 'header-not-assigned',
|
||||
data: null,
|
||||
hidden: cannotQueryPermissionUsers.length === 0,
|
||||
rowSection: {
|
||||
title: 'Not assigned',
|
||||
secondaryTitle: cannotQueryPermissionUsers.length.toString(),
|
||||
},
|
||||
},
|
||||
...cannotQueryPermissionUsers,
|
||||
],
|
||||
[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={useMemo(() => <EmptyStateList text="No dataset groups found" />, [])}
|
||||
/>
|
||||
</InfiniteListContainer>
|
||||
);
|
||||
});
|
||||
|
||||
PermissionGroupDatasetsListContainer.displayName = 'PermissionGroupUsersListContainer';
|
|
@ -0,0 +1 @@
|
|||
export * from './PermissionGroupDatasetsController';
|
|
@ -0,0 +1,44 @@
|
|||
import type React from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import { useGetPermissionGroupUsers } from '@/api/buster_rest/permission_groups';
|
||||
import { PermissionSearchAndListWrapper } from '@/components/features/permissions';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
import { Plus } from '@/components/ui/icons';
|
||||
import { useInviteModalStore } from '@/context/GlobalStore/useInviteModalStore';
|
||||
import { useDebounceSearch } from '@/hooks/useDebounceSearch';
|
||||
import { PermissionGroupUsersListContainer } from './PermissionGroupUsersListContainer';
|
||||
|
||||
export const PermissionGroupUsersController: React.FC<{
|
||||
permissionGroupId: string;
|
||||
}> = ({ permissionGroupId }) => {
|
||||
const { data } = useGetPermissionGroupUsers(permissionGroupId);
|
||||
const { toggleInviteModal } = useInviteModalStore();
|
||||
|
||||
const { filteredItems, handleSearchChange, searchText } = useDebounceSearch({
|
||||
items: data || [],
|
||||
searchPredicate: (item, searchText) =>
|
||||
item.email.includes(searchText) || item.name.includes(searchText),
|
||||
});
|
||||
|
||||
const NewUserButton: React.ReactNode = useMemo(() => {
|
||||
return (
|
||||
<Button prefix={<Plus />} onClick={() => toggleInviteModal(true)}>
|
||||
Invite user
|
||||
</Button>
|
||||
);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<PermissionSearchAndListWrapper
|
||||
searchText={searchText}
|
||||
handleSearchChange={handleSearchChange}
|
||||
searchPlaceholder="Search by user name or email..."
|
||||
searchChildren={NewUserButton}
|
||||
>
|
||||
<PermissionGroupUsersListContainer
|
||||
filteredUsers={filteredItems}
|
||||
permissionGroupId={permissionGroupId}
|
||||
/>
|
||||
</PermissionSearchAndListWrapper>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,145 @@
|
|||
import React, { useMemo, useState } from 'react';
|
||||
import type { GetPermissionGroupUsersResponse } from '@/api/asset_interfaces';
|
||||
import { useUpdatePermissionGroupUsers } from '@/api/buster_rest/permission_groups';
|
||||
import { ListUserItem } from '@/components/features/list/ListUserItem';
|
||||
import { PermissionAssignedCell } from '@/components/features/permissions';
|
||||
import {
|
||||
type BusterListColumn,
|
||||
type BusterListRowItem,
|
||||
createListItem,
|
||||
EmptyStateList,
|
||||
InfiniteListContainer,
|
||||
} from '@/components/ui/list';
|
||||
import { BusterInfiniteList } from '@/components/ui/list/BusterInfiniteList';
|
||||
import { useMemoizedFn } from '@/hooks/useMemoizedFn';
|
||||
import { PermissionGroupUsersSelectedPopup } from './PermissionGroupUsersSelectedPopup';
|
||||
|
||||
export const PermissionGroupUsersListContainer: React.FC<{
|
||||
filteredUsers: GetPermissionGroupUsersResponse[];
|
||||
permissionGroupId: string;
|
||||
}> = React.memo(({ filteredUsers, permissionGroupId }) => {
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState<string[]>([]);
|
||||
const { mutateAsync: updatePermissionGroupUsers } =
|
||||
useUpdatePermissionGroupUsers(permissionGroupId);
|
||||
|
||||
const onSelectAssigned = useMemoizedFn(async (params: { id: string; assigned: boolean }) => {
|
||||
await updatePermissionGroupUsers([params]);
|
||||
});
|
||||
|
||||
const columns: BusterListColumn<GetPermissionGroupUsersResponse>[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
render: (name: string, user: GetPermissionGroupUsersResponse) => {
|
||||
return <ListUserItem name={name} email={user.email} avatarURL={user.avatar_url} />;
|
||||
},
|
||||
},
|
||||
{
|
||||
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 createPermissionGroupUserListItem = createListItem<GetPermissionGroupUsersResponse>();
|
||||
const result: {
|
||||
cannotQueryPermissionUsers: BusterListRowItem<GetPermissionGroupUsersResponse>[];
|
||||
canQueryPermissionUsers: BusterListRowItem<GetPermissionGroupUsersResponse>[];
|
||||
} = filteredUsers.reduce<{
|
||||
cannotQueryPermissionUsers: BusterListRowItem<GetPermissionGroupUsersResponse>[];
|
||||
canQueryPermissionUsers: BusterListRowItem<GetPermissionGroupUsersResponse>[];
|
||||
}>(
|
||||
(acc, user) => {
|
||||
const userItem: BusterListRowItem<GetPermissionGroupUsersResponse> =
|
||||
createPermissionGroupUserListItem({
|
||||
id: user.id,
|
||||
data: user,
|
||||
link: {
|
||||
to: '/app/settings/users/$userId',
|
||||
params: {
|
||||
userId: user.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
if (user.assigned) {
|
||||
acc.canQueryPermissionUsers.push(userItem);
|
||||
} else {
|
||||
acc.cannotQueryPermissionUsers.push(userItem);
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
cannotQueryPermissionUsers: [],
|
||||
canQueryPermissionUsers: [],
|
||||
}
|
||||
);
|
||||
return result;
|
||||
}, [filteredUsers]);
|
||||
|
||||
const rows: BusterListRowItem<GetPermissionGroupUsersResponse>[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
id: 'header-assigned',
|
||||
data: null,
|
||||
hidden: canQueryPermissionUsers.length === 0,
|
||||
rowSection: {
|
||||
title: 'Assigned',
|
||||
secondaryTitle: canQueryPermissionUsers.length.toString(),
|
||||
},
|
||||
},
|
||||
...canQueryPermissionUsers,
|
||||
{
|
||||
id: 'header-not-assigned',
|
||||
data: null,
|
||||
hidden: cannotQueryPermissionUsers.length === 0,
|
||||
rowSection: {
|
||||
title: 'Not assigned',
|
||||
secondaryTitle: cannotQueryPermissionUsers.length.toString(),
|
||||
},
|
||||
},
|
||||
...cannotQueryPermissionUsers,
|
||||
],
|
||||
[canQueryPermissionUsers, cannotQueryPermissionUsers]
|
||||
);
|
||||
|
||||
return (
|
||||
<InfiniteListContainer
|
||||
popupNode={
|
||||
<PermissionGroupUsersSelectedPopup
|
||||
selectedRowKeys={selectedRowKeys}
|
||||
onSelectChange={setSelectedRowKeys}
|
||||
permissionGroupId={permissionGroupId}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<BusterInfiniteList
|
||||
columns={columns}
|
||||
rows={rows}
|
||||
showHeader={false}
|
||||
showSelectAll={false}
|
||||
useRowClickSelectChange={false}
|
||||
selectedRowKeys={selectedRowKeys}
|
||||
onSelectChange={setSelectedRowKeys}
|
||||
emptyState={useMemo(() => <EmptyStateList text="No dataset groups found" />, [])}
|
||||
/>
|
||||
</InfiniteListContainer>
|
||||
);
|
||||
});
|
||||
|
||||
PermissionGroupUsersListContainer.displayName = 'PermissionGroupUsersListContainer';
|
|
@ -0,0 +1,31 @@
|
|||
import React from 'react';
|
||||
import { useUpdatePermissionGroupUsers } from '@/api/buster_rest/permission_groups';
|
||||
import { PermissionAssignedButton } from '@/components/features/permissions';
|
||||
import { BusterListSelectedOptionPopupContainer } from '@/components/ui/list';
|
||||
|
||||
export const PermissionGroupUsersSelectedPopup: React.FC<{
|
||||
selectedRowKeys: string[];
|
||||
onSelectChange: (selectedRowKeys: string[]) => void;
|
||||
permissionGroupId: string;
|
||||
}> = React.memo(({ selectedRowKeys, onSelectChange, permissionGroupId }) => {
|
||||
const { mutateAsync: updatePermissionGroupUsers } =
|
||||
useUpdatePermissionGroupUsers(permissionGroupId);
|
||||
|
||||
return (
|
||||
<BusterListSelectedOptionPopupContainer
|
||||
selectedRowKeys={selectedRowKeys}
|
||||
onSelectChange={onSelectChange}
|
||||
buttons={[
|
||||
<PermissionAssignedButton
|
||||
key="assign"
|
||||
text="assigned"
|
||||
selectedRowKeys={selectedRowKeys}
|
||||
onSelectChange={onSelectChange}
|
||||
onUpdate={updatePermissionGroupUsers}
|
||||
/>,
|
||||
]}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
PermissionGroupUsersSelectedPopup.displayName = 'PermissionGroupUsersSelectedPopup';
|
|
@ -0,0 +1 @@
|
|||
export * from './PermissionGroupUsersController';
|
|
@ -1,13 +1,9 @@
|
|||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import { createFileRoute } from '@tanstack/react-router';
|
||||
|
||||
export const Route = createFileRoute(
|
||||
'/app/_settings/_permissions/settings/datasets/$datasetId',
|
||||
)({
|
||||
export const Route = createFileRoute('/app/_settings/_permissions/settings/datasets/$datasetId')({
|
||||
component: RouteComponent,
|
||||
})
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
return (
|
||||
<div>Hello "/app/_settings/_permissions/settings/datasets/$datasetId"!</div>
|
||||
)
|
||||
return <div>Hello "/app/_settings/_permissions/settings/datasets/$datasetId"!</div>;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import { createFileRoute } from '@tanstack/react-router';
|
||||
|
||||
export const Route = createFileRoute(
|
||||
'/app/_settings/_permissions/settings/datasets/',
|
||||
)({
|
||||
export const Route = createFileRoute('/app/_settings/_permissions/settings/datasets/')({
|
||||
component: RouteComponent,
|
||||
})
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
return <div>Hello "/app/_settings/_permissions/settings/datasets/"!</div>
|
||||
return <div>Hello "/app/_settings/_permissions/settings/datasets/"!</div>;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import { createFileRoute } from '@tanstack/react-router';
|
||||
|
||||
export const Route = createFileRoute(
|
||||
'/app/_settings/_permissions/settings/datasets',
|
||||
)({
|
||||
export const Route = createFileRoute('/app/_settings/_permissions/settings/datasets')({
|
||||
component: RouteComponent,
|
||||
})
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
return <div>Hello "/app/_settings/_permissions/settings/datasets"!</div>
|
||||
return <div>Hello "/app/_settings/_permissions/settings/datasets"!</div>;
|
||||
}
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
import { createFileRoute } from '@tanstack/react-router';
|
||||
import { prefetchPermissionGroupDatasetGroups } from '@/api/buster_rest/permission_groups';
|
||||
import { PermissionGroupDatasetGroupsController } from '@/controllers/PermissionGroupsControllers/PermissionGroupDatasetGroupsController';
|
||||
|
||||
export const Route = createFileRoute(
|
||||
'/app/_settings/_permissions/settings/permission-groups/$permissionGroupId/dataset-groups'
|
||||
)({
|
||||
component: RouteComponent,
|
||||
loader: async ({ context, params }) => {
|
||||
const { permissionGroupId } = params;
|
||||
const { queryClient } = context;
|
||||
await prefetchPermissionGroupDatasetGroups(permissionGroupId, queryClient);
|
||||
},
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
return (
|
||||
<div>
|
||||
Hello
|
||||
"/app/_settings/_permissions/settings/permission-groups/permissionGroupId/dataset-groups"!
|
||||
</div>
|
||||
);
|
||||
const { permissionGroupId } = Route.useParams();
|
||||
return <PermissionGroupDatasetGroupsController permissionGroupId={permissionGroupId} />;
|
||||
}
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
import { createFileRoute } from '@tanstack/react-router';
|
||||
import { prefetchPermissionGroupDatasets } from '@/api/buster_rest/permission_groups';
|
||||
import { PermissionGroupDatasetsController } from '@/controllers/PermissionGroupsControllers/PermissionGroupDatasetsController';
|
||||
|
||||
export const Route = createFileRoute(
|
||||
'/app/_settings/_permissions/settings/permission-groups/$permissionGroupId/datasets'
|
||||
)({
|
||||
component: RouteComponent,
|
||||
loader: async ({ context, params }) => {
|
||||
const { permissionGroupId } = params;
|
||||
const { queryClient } = context;
|
||||
await prefetchPermissionGroupDatasets(permissionGroupId, queryClient);
|
||||
},
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
return (
|
||||
<div>
|
||||
Hello "/app/_settings/_permissions/settings/permission-groups/permissionGroupId/datasets"!
|
||||
</div>
|
||||
);
|
||||
const { permissionGroupId } = Route.useParams();
|
||||
return <PermissionGroupDatasetsController permissionGroupId={permissionGroupId} />;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { createFileRoute } from '@tanstack/react-router';
|
||||
import { PermissionGroupUsersController } from '@/controllers/PermissionGroupsControllers/PermissionGroupUsersController';
|
||||
|
||||
export const Route = createFileRoute(
|
||||
'/app/_settings/_permissions/settings/permission-groups/$permissionGroupId/users'
|
||||
|
@ -7,9 +8,6 @@ export const Route = createFileRoute(
|
|||
});
|
||||
|
||||
function RouteComponent() {
|
||||
return (
|
||||
<div>
|
||||
Hello "/app/_settings/_permissions/settings/permission-groups/permissionGroupId/users"!
|
||||
</div>
|
||||
);
|
||||
const { permissionGroupId } = Route.useParams();
|
||||
return <PermissionGroupUsersController permissionGroupId={permissionGroupId} />;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { createFileRoute } from '@tanstack/react-router';
|
||||
import { prefetchAllPermissionGroups } from '@/api/buster_rest/permission_groups';
|
||||
import { ListPermissionGroupsController } from '@/controllers/PermissionGroupsControllers/ListPermissionGroupsController';
|
||||
|
||||
export const Route = createFileRoute('/app/_settings/_permissions/settings/permission-groups/')({
|
||||
|
|
Loading…
Reference in New Issue