diff --git a/web/src/api/buster-rest/permission_groups/responseInterfaces.ts b/web/src/api/buster-rest/permission_groups/responseInterfaces.ts index 82c7553c1..80462d658 100644 --- a/web/src/api/buster-rest/permission_groups/responseInterfaces.ts +++ b/web/src/api/buster-rest/permission_groups/responseInterfaces.ts @@ -5,7 +5,7 @@ export interface GetPermissionGroupResponse { name: string; organization_id: string; updated_at: string; - updated_by: string; //THIS IS THE USER ID + updated_by: string; } export interface CreatePermissionGroupResponse extends GetPermissionGroupResponse {} diff --git a/web/src/app/app/_components/Lists/index.ts b/web/src/app/app/_components/Lists/index.ts index 8b4fad323..7e10590ab 100644 --- a/web/src/app/app/_components/Lists/index.ts +++ b/web/src/app/app/_components/Lists/index.ts @@ -1,2 +1,3 @@ export * from './StatusBadgeIndicator'; export * from './FavoriteStar'; +export * from './ListEmptyState'; diff --git a/web/src/app/app/datasets/[datasetId]/permissions/overview/_PermissionOverview/PermissionOverview.tsx b/web/src/app/app/datasets/[datasetId]/permissions/overview/_PermissionOverview/PermissionOverview.tsx index 5e49542a4..636fc0d6c 100644 --- a/web/src/app/app/datasets/[datasetId]/permissions/overview/_PermissionOverview/PermissionOverview.tsx +++ b/web/src/app/app/datasets/[datasetId]/permissions/overview/_PermissionOverview/PermissionOverview.tsx @@ -13,7 +13,6 @@ export const PermissionOverview: React.FC<{ datasetId: string; }> = React.memo(({ datasetId }) => { const { data: datasetPermissionsOverview } = useGetDatasetPermissionsOverview(datasetId); - console.log(datasetPermissionsOverview); const { filteredItems, searchText, handleSearchChange } = useDebounceSearch({ items: datasetPermissionsOverview?.users || [], diff --git a/web/src/app/app/layout.tsx b/web/src/app/app/layout.tsx index 14c88eb29..8a085e519 100644 --- a/web/src/app/app/layout.tsx +++ b/web/src/app/app/layout.tsx @@ -12,8 +12,7 @@ import { ClientRedirect } from './_components/ClientRedirect'; import { AppLayoutClient } from './layoutClient'; export default async function Layout({ - children, - ...rest + children }: Readonly<{ children: React.ReactNode; }>) { diff --git a/web/src/app/app/settings/permission-groups/ListPermissionGroupsComponent.tsx b/web/src/app/app/settings/permission-groups/ListPermissionGroupsComponent.tsx new file mode 100644 index 000000000..90bf5ba6f --- /dev/null +++ b/web/src/app/app/settings/permission-groups/ListPermissionGroupsComponent.tsx @@ -0,0 +1,68 @@ +import { + BusterInfiniteList, + BusterListColumn, + BusterListRowItem, + EmptyStateList, + InfiniteListContainer +} from '@/components/list'; +import { Card } from 'antd'; +import React, { useMemo, useState } from 'react'; +import { Text } from '@/components/text'; +import { BusterRoutes, createBusterRoute } from '@/routes'; +import { ListUserItem } from '../../_components/ListContent'; +import { GetPermissionGroupResponse } from '@/api/buster-rest'; +import { ListEmptyState } from '../../_components/Lists/ListEmptyState'; + +export const ListPermissionGroupsComponent: React.FC<{ + permissionGroups: GetPermissionGroupResponse[]; + isFetched: boolean; +}> = React.memo(({ permissionGroups, isFetched }) => { + const columns: BusterListColumn[] = useMemo( + () => [ + { + title: 'Name', + dataIndex: 'name' + } + ], + [] + ); + + const permissionGroupsRows: BusterListRowItem[] = useMemo(() => { + return permissionGroups.reduce((acc, permissionGroup) => { + const rowItem: BusterListRowItem = { + id: permissionGroup.id, + data: permissionGroup, + link: createBusterRoute({ + route: BusterRoutes.SETTINGS_PERMISSION_GROUPS_ID_USERS, + permissionGroupId: permissionGroup.id + }) + }; + acc.push(rowItem); + return acc; + }, []); + }, [permissionGroups]); + + return ( + + // } + > + } + /> + + ); +}); + +ListPermissionGroupsComponent.displayName = 'ListPermissionGroupsComponent'; diff --git a/web/src/app/app/settings/permission-groups/[permissionGroupId]/dataset-groups/page.tsx b/web/src/app/app/settings/permission-groups/[permissionGroupId]/dataset-groups/page.tsx new file mode 100644 index 000000000..c94bbe4b8 --- /dev/null +++ b/web/src/app/app/settings/permission-groups/[permissionGroupId]/dataset-groups/page.tsx @@ -0,0 +1,3 @@ +export default function Page() { + return
Dataset Groups
; +} 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 new file mode 100644 index 000000000..bc6961f43 --- /dev/null +++ b/web/src/app/app/settings/permission-groups/[permissionGroupId]/datasets/page.tsx @@ -0,0 +1,3 @@ +export default function Page() { + return
Datasets
; +} diff --git a/web/src/app/app/settings/permission-groups/[permissionGroupId]/users/page.tsx b/web/src/app/app/settings/permission-groups/[permissionGroupId]/users/page.tsx new file mode 100644 index 000000000..6f68f3aea --- /dev/null +++ b/web/src/app/app/settings/permission-groups/[permissionGroupId]/users/page.tsx @@ -0,0 +1,3 @@ +export default function Page() { + return
Users
; +} diff --git a/web/src/app/app/settings/permission-groups/page.tsx b/web/src/app/app/settings/permission-groups/page.tsx index 3e040394d..3e71a35ac 100644 --- a/web/src/app/app/settings/permission-groups/page.tsx +++ b/web/src/app/app/settings/permission-groups/page.tsx @@ -1,14 +1,62 @@ -import { SettingsEmptyState } from '../_SettingsEmptyState'; +'use client'; +import React, { useState } from 'react'; import { SettingsPageHeader } from '../_SettingsPageHeader'; +import { PermissionSearch, NewPermissionGroupModal } from '@appComponents/PermissionComponents'; +import { useDebounceSearch } from '@/hooks/useDebounceSearch'; +import { useListAllPermissionGroups } from '@/api/buster-rest'; +import { ListPermissionGroupsComponent } from './ListPermissionGroupsComponent'; +import { useMemoizedFn } from 'ahooks'; +import { Button } from 'antd'; +import { AppMaterialIcons } from '@/components'; export default function Page() { + const { data: permissionGroups, isFetched, refetch } = useListAllPermissionGroups(); + const [isNewPermissionGroupModalOpen, setIsNewPermissionGroupModalOpen] = useState(false); + + const { filteredItems, handleSearchChange, searchText } = useDebounceSearch({ + items: permissionGroups || [], + searchPredicate: (item, searchText) => + item.name.toLowerCase().includes(searchText.toLowerCase()) + }); + + const onCloseNewPermissionGroupModal = useMemoizedFn(() => { + setIsNewPermissionGroupModalOpen(false); + refetch(); + }); + + const onOpenNewPermissionGroupModal = useMemoizedFn(() => { + setIsNewPermissionGroupModalOpen(true); + }); + return ( -
- +
+
+ +
+ + +
+
+ +
+ +
+
+ + - -
+ ); } diff --git a/web/src/app/app/settings/users/SearchUsers.tsx b/web/src/app/app/settings/users/SearchUsers.tsx deleted file mode 100644 index f6d51e20b..000000000 --- a/web/src/app/app/settings/users/SearchUsers.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React, { useState, useTransition } from 'react'; -import { SearchInput } from '@/components/inputs'; - -export const SearchUsers: React.FC<{ - onChange: (value: string) => void; -}> = React.memo(({ onChange }) => { - return ( -
- -
- ); -}); - -SearchUsers.displayName = 'SearchUsers'; diff --git a/web/src/app/app/settings/users/layout.tsx b/web/src/app/app/settings/users/layout.tsx deleted file mode 100644 index 227516f0b..000000000 --- a/web/src/app/app/settings/users/layout.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from 'react'; - -export default function Layout({ children }: { children: React.ReactNode }) { - return <>{children}; -} diff --git a/web/src/app/app/settings/users/page.tsx b/web/src/app/app/settings/users/page.tsx index 0bd72a2fa..b68fabb2e 100644 --- a/web/src/app/app/settings/users/page.tsx +++ b/web/src/app/app/settings/users/page.tsx @@ -2,18 +2,18 @@ import React from 'react'; import { SettingsPageHeader } from '../_SettingsPageHeader'; -import { SearchUsers } from './SearchUsers'; import { useDebounceSearch } from '@/hooks/useDebounceSearch'; import { useGetOrganizationUsers } from '@/api/buster-rest'; import { useUserConfigContextSelector } from '@/context/Users'; import { ListUsersComponent } from './ListUsersComponent'; +import { PermissionSearch } from '../../_components/PermissionComponents'; export default function Page() { const userOrganization = useUserConfigContextSelector((x) => x.userOrganizations); const firstOrganizationId = userOrganization?.id! || ''; const { data: users, isFetched } = useGetOrganizationUsers(firstOrganizationId); - const { filteredItems, handleSearchChange } = useDebounceSearch({ + const { filteredItems, handleSearchChange, searchText } = useDebounceSearch({ items: users || [], searchPredicate: (item, searchText) => item.email.includes(searchText) || item.name.includes(searchText) @@ -27,7 +27,11 @@ export default function Page() { description="Manage your organization's users and their permissions" type="alternate" /> - + diff --git a/web/src/routes/busterRoutes/busterAppRoutes.ts b/web/src/routes/busterRoutes/busterAppRoutes.ts index b444d7ff3..5819b7f3c 100644 --- a/web/src/routes/busterRoutes/busterAppRoutes.ts +++ b/web/src/routes/busterRoutes/busterAppRoutes.ts @@ -29,7 +29,9 @@ export enum BusterAppRoutes { SETTINGS_DATASOURCES_ADD = '/app/settings/datasources/add', SETTINGS_INTEGRATIONS = '/app/settings/integrations', SETTINGS_PERMISSION_GROUPS = '/app/settings/permission-groups', - SETTINGS_PERMISSION_GROUPS_ID = '/app/settings/permission-groups/:permissionGroupId', + SETTINGS_PERMISSION_GROUPS_ID_USERS = '/app/settings/permission-groups/:permissionGroupId/users', + SETTINGS_PERMISSION_GROUPS_ID_DATASET_GROUPS = '/app/settings/permission-groups/:permissionGroupId/dataset-groups', + SETTINGS_PERMISSION_GROUPS_ID_DATASETS = '/app/settings/permission-groups/:permissionGroupId/datasets', SETTINGS_API_KEYS = '/app/settings/api-keys', SETTINGS_EMBEDS = '/app/settings/embeds', SETTINGS_BILLING = '/app/settings/billing', @@ -86,8 +88,16 @@ export type BusterAppRoutesWithArgs = { [BusterAppRoutes.SETTINGS_PERMISSION_GROUPS]: { route: BusterAppRoutes.SETTINGS_PERMISSION_GROUPS; }; - [BusterAppRoutes.SETTINGS_PERMISSION_GROUPS_ID]: { - route: BusterAppRoutes.SETTINGS_PERMISSION_GROUPS_ID; + [BusterAppRoutes.SETTINGS_PERMISSION_GROUPS_ID_USERS]: { + route: BusterAppRoutes.SETTINGS_PERMISSION_GROUPS_ID_USERS; + permissionGroupId: string; + }; + [BusterAppRoutes.SETTINGS_PERMISSION_GROUPS_ID_DATASET_GROUPS]: { + route: BusterAppRoutes.SETTINGS_PERMISSION_GROUPS_ID_DATASET_GROUPS; + permissionGroupId: string; + }; + [BusterAppRoutes.SETTINGS_PERMISSION_GROUPS_ID_DATASETS]: { + route: BusterAppRoutes.SETTINGS_PERMISSION_GROUPS_ID_DATASETS; permissionGroupId: string; }; [BusterAppRoutes.SETTINGS_API_KEYS]: { route: BusterAppRoutes.SETTINGS_API_KEYS };