Merge pull request #33 from buster-so/dallin/bus-902-permission-list-bugfixes

Dallin/bus 902 permission list bugfixes
This commit is contained in:
dal 2025-01-15 09:12:13 -08:00 committed by GitHub
commit 32197d2a05
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
30 changed files with 285 additions and 189 deletions

View File

@ -67,7 +67,8 @@ pub async fn list_assets(
.eq(users::id)
.and(dataset_permissions::dataset_id.eq(dataset_id))
.and(dataset_permissions::permission_type.eq("user"))
.and(dataset_permissions::deleted_at.is_null())),
.and(dataset_permissions::deleted_at.is_null())
.and(dataset_permissions::organization_id.eq(organization_id))),
)
.inner_join(
users_to_organizations::table.on(users_to_organizations::user_id.eq(users::id)),
@ -78,7 +79,6 @@ pub async fn list_assets(
"dataset_permissions.id IS NOT NULL",
),
))
.filter(dataset_permissions::organization_id.eq(organization_id))
.filter(users_to_organizations::organization_id.eq(organization_id))
.load::<(User, bool)>(&mut *conn)
.await
@ -107,7 +107,8 @@ pub async fn list_assets(
.eq(permission_groups::id)
.and(dataset_permissions::dataset_id.eq(dataset_id))
.and(dataset_permissions::permission_type.eq("permission_group"))
.and(dataset_permissions::deleted_at.is_null())),
.and(dataset_permissions::deleted_at.is_null())
.and(dataset_permissions::organization_id.eq(organization_id))),
)
.select((
permission_groups::all_columns,
@ -116,7 +117,6 @@ pub async fn list_assets(
),
))
.filter(permission_groups::deleted_at.is_null())
.filter(dataset_permissions::organization_id.eq(organization_id))
.filter(permission_groups::organization_id.eq(organization_id))
.load::<(PermissionGroup, bool)>(&mut *conn)
.await
@ -145,7 +145,8 @@ pub async fn list_assets(
.eq(dataset_groups::id)
.and(dataset_permissions::dataset_id.eq(dataset_id))
.and(dataset_permissions::permission_type.eq("dataset_group"))
.and(dataset_permissions::deleted_at.is_null())),
.and(dataset_permissions::deleted_at.is_null())
.and(dataset_permissions::organization_id.eq(organization_id))),
)
.select((
dataset_groups::all_columns,
@ -154,7 +155,6 @@ pub async fn list_assets(
),
))
.filter(dataset_groups::organization_id.eq(organization_id))
.filter(dataset_permissions::organization_id.eq(organization_id))
.filter(dataset_groups::deleted_at.is_null())
.load::<(DatasetGroup, bool)>(&mut *conn)
.await

View File

@ -6,8 +6,10 @@ import {
getDatasetGroup,
updateDatasetGroup
} from './requests';
import { updateDatasetDatasetGroups } from '../datasets';
import { useQueryClient } from '@tanstack/react-query';
import { useMemoizedFn } from 'ahooks';
import { LIST_DATASET_GROUPS_QUERY_KEY } from '../datasets/permissions/config';
export const useListDatasetGroups = () => {
const queryFn = useMemoizedFn(() => listDatasetGroups());
@ -24,13 +26,9 @@ export const useDeleteDatasetGroup = () => {
queryClient.invalidateQueries({ queryKey: ['dataset_groups'] });
return res;
});
const onSuccess = useMemoizedFn(() => {
queryClient.invalidateQueries({ queryKey: ['dataset_groups'] });
});
return useCreateReactMutation({
mutationFn,
onSuccess
mutationFn
});
};
@ -59,19 +57,18 @@ export const useCreateDatasetGroup = (datasetId?: string) => {
const queryClient = useQueryClient();
const mutationFn = useMemoizedFn(async (data: Parameters<typeof createDatasetGroup>[0]) => {
const res = await createDatasetGroup(data);
queryClient.invalidateQueries({ queryKey: ['dataset_groups'] });
if (datasetId) {
queryClient.invalidateQueries({ queryKey: ['dataset_groups', datasetId] });
queryClient.invalidateQueries({ queryKey: ['list_dataset_groups', datasetId] });
await updateDatasetDatasetGroups({
dataset_id: datasetId,
groups: [{ id: res.id, assigned: true }]
});
queryClient.invalidateQueries({ queryKey: [LIST_DATASET_GROUPS_QUERY_KEY, datasetId] });
queryClient.invalidateQueries({ queryKey: ['dataset_groups'] });
}
return res;
});
const onSuccess = useMemoizedFn(() => {
queryClient.invalidateQueries({ queryKey: ['dataset_groups'] });
});
return useCreateReactMutation({
mutationFn,
onSuccess
mutationFn
});
};

View File

@ -1,8 +1,8 @@
import { mainApi } from '../../buster';
import { ListDatasetGroupsResponse } from '../datasets';
import { DatasetGroup } from './responseInterfaces';
export const listDatasetGroups = async () => {
return mainApi.get<ListDatasetGroupsResponse[]>(`/dataset_groups`).then((res) => res.data);
return mainApi.get<DatasetGroup[]>(`/dataset_groups`).then((res) => res.data);
};
export const createDatasetGroup = async (data: { name: string }) => {

View File

@ -1 +1,4 @@
export const GET_PERMISSIONS_OVERVIEW = (datasetId: string) => `/datasets/${datasetId}/overview`;
//QUERY KEYS
export const LIST_DATASET_GROUPS_QUERY_KEY = 'list_dataset_groups';

View File

@ -1,3 +1,4 @@
export * from './requests';
export * from './queryRequests';
export * from './responseInterfaces';
export * from './config';

View File

@ -2,19 +2,23 @@ import { useCreateReactQuery, useCreateReactMutation } from '@/api/createReactQu
import {
getDatasetPermissionsOverview,
listDatasetDatasetGroups,
listPermissionGroups,
listPermissionUsers,
updateDatasetGroups,
updatePermissionGroups,
updatePermissionUsers
listIndividualDatasetPermissionGroups,
updateDatasetPermissionGroups,
updateDatasetDatasetGroups,
updateDatasetPermissionUsers,
listDatasetPermissionUsers
} from './requests';
import { useMemoizedFn } from 'ahooks';
import { QueryClient, useQueryClient } from '@tanstack/react-query';
import { getDatasetPermissionsOverview_server } from './serverRequests';
import { ListPermissionUsersResponse } from './responseInterfaces';
import { PERMISSION_GROUP_QUERY_KEY } from '../../permission_groups';
import { LIST_DATASET_GROUPS_QUERY_KEY } from './config';
export const useGetDatasetPermissionsOverview = (dataset_id: string) => {
const queryFn = useMemoizedFn(() => getDatasetPermissionsOverview({ dataset_id }));
const queryFn = useMemoizedFn(() => {
return getDatasetPermissionsOverview({ dataset_id });
});
return useCreateReactQuery({
queryKey: ['dataset_permissions_overview', dataset_id],
@ -34,27 +38,55 @@ export const prefetchGetDatasetPermissionsOverview = async (
return queryClient;
};
export const useListPermissionGroups = (dataset_id: string) => {
const queryFn = useMemoizedFn(() => listPermissionGroups({ dataset_id }));
export const useDatasetListPermissionGroups = (dataset_id: string) => {
const queryFn = useMemoizedFn(() => {
return listIndividualDatasetPermissionGroups({ dataset_id });
});
return useCreateReactQuery({
queryKey: ['list_permission_groups', dataset_id],
queryKey: [PERMISSION_GROUP_QUERY_KEY, dataset_id],
queryFn,
staleTime: 1000 * 5 // 5 seconds
});
};
export const useListDatasetDatasetGroups = (dataset_id: string) => {
export const useDatasetUpdatePermissionGroups = (dataset_id: string) => {
const queryClient = useQueryClient();
const mutationFn = useMemoizedFn((groups: { id: string; assigned: boolean }[]) => {
const keyedChanges: Record<string, { id: string; assigned: boolean }> = {};
groups.forEach(({ id, assigned }) => {
keyedChanges[id] = { id, assigned };
});
queryClient.setQueryData(
[PERMISSION_GROUP_QUERY_KEY, dataset_id],
(oldData: ListPermissionUsersResponse[]) => {
return oldData?.map((group) => {
const updatedGroup = keyedChanges[group.id];
if (updatedGroup) return { ...group, assigned: updatedGroup.assigned };
return group;
});
}
);
return updateDatasetPermissionGroups({ dataset_id, groups });
});
return useCreateReactMutation({
mutationFn
});
};
export const useDatasetListDatasetGroups = (dataset_id: string) => {
const queryFn = useMemoizedFn(() => listDatasetDatasetGroups({ dataset_id }));
return useCreateReactQuery({
queryKey: ['list_dataset_groups', dataset_id],
queryKey: [LIST_DATASET_GROUPS_QUERY_KEY, dataset_id],
queryFn
});
};
export const useListPermissionUsers = (dataset_id: string) => {
const queryFn = useMemoizedFn(() => listPermissionUsers({ dataset_id }));
export const useDatasetListPermissionUsers = (dataset_id: string) => {
const queryFn = useMemoizedFn(() => listDatasetPermissionUsers({ dataset_id }));
return useCreateReactQuery({
queryKey: ['list_permission_users', dataset_id],
@ -62,7 +94,7 @@ export const useListPermissionUsers = (dataset_id: string) => {
});
};
export const useUpdatePermissionGroups = (dataset_id: string) => {
export const useDatasetUpdateDatasetGroups = (dataset_id: string) => {
const queryClient = useQueryClient();
const mutationFn = useMemoizedFn((groups: { id: string; assigned: boolean }[]) => {
const keyedChanges: Record<string, { id: string; assigned: boolean }> = {};
@ -70,7 +102,7 @@ export const useUpdatePermissionGroups = (dataset_id: string) => {
keyedChanges[id] = { id, assigned };
});
queryClient.setQueryData(
['list_permission_groups', dataset_id],
[LIST_DATASET_GROUPS_QUERY_KEY, dataset_id],
(oldData: ListPermissionUsersResponse[]) => {
return oldData?.map((group) => {
const updatedGroup = keyedChanges[group.id];
@ -79,8 +111,7 @@ export const useUpdatePermissionGroups = (dataset_id: string) => {
});
}
);
return updatePermissionGroups({ dataset_id, groups });
return updateDatasetDatasetGroups({ dataset_id, groups });
});
return useCreateReactMutation({
@ -88,32 +119,7 @@ export const useUpdatePermissionGroups = (dataset_id: string) => {
});
};
export const useUpdateDatasetGroups = (dataset_id: string) => {
const queryClient = useQueryClient();
const mutationFn = useMemoizedFn((groups: { id: string; assigned: boolean }[]) => {
const keyedChanges: Record<string, { id: string; assigned: boolean }> = {};
groups.forEach(({ id, assigned }) => {
keyedChanges[id] = { id, assigned };
});
queryClient.setQueryData(
['list_dataset_groups', dataset_id],
(oldData: ListPermissionUsersResponse[]) => {
return oldData?.map((group) => {
const updatedGroup = keyedChanges[group.id];
if (updatedGroup) return { ...group, assigned: updatedGroup.assigned };
return group;
});
}
);
return updateDatasetGroups({ dataset_id, groups });
});
return useCreateReactMutation({
mutationFn
});
};
export const useUpdatePermissionUsers = (dataset_id: string) => {
export const useDatasetUpdatePermissionUsers = (dataset_id: string) => {
const queryClient = useQueryClient();
const mutationFn = useMemoizedFn((users: { id: string; assigned: boolean }[]) => {
const keyedChanges: Record<string, { id: string; assigned: boolean }> = {};
@ -130,7 +136,7 @@ export const useUpdatePermissionUsers = (dataset_id: string) => {
});
}
);
return updatePermissionUsers({ dataset_id, users });
return updateDatasetPermissionUsers({ dataset_id, users });
});
return useCreateReactMutation({

View File

@ -7,7 +7,7 @@ import {
} from './responseInterfaces';
import * as config from './config';
export const listPermissionGroups = async ({
export const listIndividualDatasetPermissionGroups = async ({
dataset_id
}: {
dataset_id: string;
@ -23,7 +23,7 @@ export const listDatasetDatasetGroups = async ({
return await mainApi.get(`/datasets/${dataset_id}/dataset_groups`).then((res) => res.data);
};
export const listPermissionUsers = async ({
export const listDatasetPermissionUsers = async ({
dataset_id
}: {
dataset_id: string;
@ -31,7 +31,7 @@ export const listPermissionUsers = async ({
return await mainApi.get(`/datasets/${dataset_id}/users`).then((res) => res.data);
};
export const updatePermissionUsers = async ({
export const updateDatasetPermissionUsers = async ({
dataset_id,
users
}: {
@ -44,7 +44,7 @@ export const updatePermissionUsers = async ({
return await mainApi.put(`/datasets/${dataset_id}/users`, users);
};
export const updatePermissionGroups = async ({
export const updateDatasetPermissionGroups = async ({
dataset_id,
groups
}: {
@ -59,7 +59,7 @@ export const updatePermissionGroups = async ({
return await mainApi.put(`/datasets/${dataset_id}/permission_groups`, groups);
};
export const updateDatasetGroups = async ({
export const updateDatasetDatasetGroups = async ({
dataset_id,
groups
}: {

View File

@ -113,7 +113,6 @@ export const useDeployDataset = () => {
mutationFn,
onSuccess: (data, variables, context) => {
queryClient.invalidateQueries({ queryKey: ['datasets', {}] });
console.log(variables, context);
}
});
};

View File

@ -9,3 +9,4 @@ export * from './api_keys';
export * from './sql';
export * from './datasets';
export * from './dataset_groups';
export * from './permission_groups';

View File

@ -0,0 +1 @@
export const PERMISSION_GROUP_QUERY_KEY = 'permission_groups';

View File

@ -1,2 +1,4 @@
export * from './requests';
export * from './responseInterfaces';
export * from './queryRequests';
export * from './config';

View File

@ -1,19 +1,70 @@
import { useCreateReactQuery, useCreateReactMutation } from '@/api/createReactQuery';
import {
getPermissionGroup,
listPermissionGroups,
createPermissionGroup,
deletePermissionGroup,
updatePermissionGroup
listAllPermissionGroups,
updatePermissionGroups
} from './requests';
import { useMemoizedFn } from 'ahooks';
import { useQueryClient } from '@tanstack/react-query';
import { useMemo } from 'react';
import { GetPermissionGroupResponse } from './responseInterfaces';
import isEmpty from 'lodash/isEmpty';
import { PERMISSION_GROUP_QUERY_KEY } from './config';
import { ListPermissionGroupsResponse, updateDatasetPermissionGroups } from '../datasets';
export const useListPermissionGroups = () => {
export const useListAllPermissionGroups = () => {
return useCreateReactQuery({
queryKey: ['permission_groups'],
queryFn: listPermissionGroups
queryFn: listAllPermissionGroups
});
};
export const useCreatePermissionGroup = () => {
const queryClient = useQueryClient();
const mutationFn = useMemoizedFn(
async ({
name,
dataset_id
}: Parameters<typeof createPermissionGroup>[0] & { dataset_id?: string }) => {
const res = await createPermissionGroup({ name });
if (dataset_id && res?.id) {
await updateDatasetPermissionGroups({
dataset_id,
groups: [{ id: res.id, assigned: true }]
});
}
queryClient.setQueryData(
[PERMISSION_GROUP_QUERY_KEY],
(oldData: GetPermissionGroupResponse[]) => (isEmpty(oldData) ? [res] : [...oldData, res])
);
if (dataset_id) {
queryClient.setQueryData(
[PERMISSION_GROUP_QUERY_KEY, dataset_id],
(oldData: ListPermissionGroupsResponse[]) => {
const newItem: ListPermissionGroupsResponse = {
id: res.id,
name: res.name,
assigned: !!dataset_id
};
if (isEmpty(oldData)) {
return [newItem];
}
return [...oldData, newItem];
}
);
}
return res;
}
);
return useCreateReactMutation({
mutationFn
});
};
@ -25,25 +76,13 @@ export const useGetPermissionGroup = (permissionGroupId: string) => {
});
};
export const useCreatePermissionGroup = (dataset_id?: string) => {
const queryClient = useQueryClient();
return useCreateReactMutation({
mutationFn: createPermissionGroup,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['permission_groups'] });
if (dataset_id) {
queryClient.invalidateQueries({ queryKey: ['list_permission_groups', dataset_id] });
}
}
});
};
export const useDeletePermissionGroup = () => {
const queryClient = useQueryClient();
return useCreateReactMutation({
mutationFn: deletePermissionGroup,
onSuccess: () => {
onSuccess: (data, variables, context) => {
queryClient.invalidateQueries({ queryKey: ['permission_groups'] });
//TODO delete the permission group from the dataset
}
});
};
@ -51,9 +90,9 @@ export const useDeletePermissionGroup = () => {
export const useUpdatePermissionGroup = () => {
const queryClient = useQueryClient();
return useCreateReactMutation({
mutationFn: updatePermissionGroup,
mutationFn: updatePermissionGroups,
onSuccess: (data, varaiables, context) => {
// queryClient.invalidateQueries({ queryKey: ['permission_groups'] });
// TODO update the permission group in the dataset
}
});
};

View File

@ -1,8 +1,10 @@
import { mainApi } from '../../buster';
import { GetPermissionGroupResponse } from './responseInterfaces';
import { CreatePermissionGroupResponse, GetPermissionGroupResponse } from './responseInterfaces';
export const listPermissionGroups = async (): Promise<GetPermissionGroupResponse[]> => {
return await mainApi.get(`/permission_groups`).then((res) => res.data);
export const listAllPermissionGroups = async (): Promise<GetPermissionGroupResponse[]> => {
return await mainApi
.get<GetPermissionGroupResponse[]>(`/permission_groups`)
.then((res) => res.data);
};
export const getPermissionGroup = async ({
@ -13,7 +15,7 @@ export const getPermissionGroup = async ({
return await mainApi.get(`/permission_groups/${id}`).then((res) => res.data);
};
export const updatePermissionGroup = async ({
export const updatePermissionGroups = async ({
id,
data
}: {
@ -27,6 +29,12 @@ export const deletePermissionGroup = async ({ id }: { id: string }): Promise<voi
return await mainApi.delete(`/permission_groups/${id}`).then((res) => res.data);
};
export const createPermissionGroup = async (data: { name: string }): Promise<void> => {
return await mainApi.post(`/permission_groups`, data).then((res) => res.data);
export const createPermissionGroup = async ({
name
}: {
name: string;
}): Promise<CreatePermissionGroupResponse> => {
return await mainApi
.post<CreatePermissionGroupResponse>(`/permission_groups`, { name })
.then((res) => res.data);
};

View File

@ -1 +1,11 @@
export interface GetPermissionGroupResponse {}
export interface GetPermissionGroupResponse {
created_at: string;
created_by: string;
id: string;
name: string;
organization_id: string;
updated_at: string;
updated_by: string; //THIS IS THE USER ID
}
export interface CreatePermissionGroupResponse extends GetPermissionGroupResponse {}

View File

@ -51,7 +51,7 @@ export const ThreadControllerChart: React.FC<{
};
}
return isTable && !loading && !chartErrorMessage
return isTable && !loading && !chartErrorMessage && (selectedData?.length ?? 0) > 0
? {
maxHeight: 'calc(100% - 20px)'
}
@ -59,7 +59,7 @@ export const ThreadControllerChart: React.FC<{
height: '100%',
maxHeight: '600px'
};
}, [isTable, chartOnlyView, loading, chartErrorMessage]);
}, [isTable, chartOnlyView, loading, chartErrorMessage, selectedData?.length]);
return (
<div className={`${className} flex h-full w-full flex-col space-y-2.5 overflow-hidden`}>

View File

@ -1,7 +1,6 @@
import { useUpdateDatasetGroups } from '@/api/busterv2';
import { useDatasetUpdateDatasetGroups } from '@/api/busterv2';
import { AppMaterialIcons } from '@/components';
import { BusterListSelectedOptionPopupContainer } from '@/components/list';
import { useCollectionsContextSelector } from '@/context/Collections';
import { useMemoizedFn } from 'ahooks';
import { Button, Dropdown } from 'antd';
import { MenuProps } from 'antd/lib';
@ -50,7 +49,7 @@ const PermissionDatasetGroupAssignButton: React.FC<{
onSelectChange: (selectedRowKeys: string[]) => void;
datasetId: string;
}> = ({ selectedRowKeys, onSelectChange, datasetId }) => {
const { mutateAsync: updateDatasetGroups } = useUpdateDatasetGroups(datasetId);
const { mutateAsync: updateDatasetGroups } = useDatasetUpdateDatasetGroups(datasetId);
const onAssignClick = useMemoizedFn(async (assigned: boolean) => {
try {

View File

@ -1,4 +1,4 @@
import { useListDatasetGroups } from '@/api/busterv2';
import { useDatasetListDatasetGroups, useListDatasetGroups } from '@/api/busterv2';
import React, { useState } from 'react';
import { useDebounceSearch } from '../useDebounceSearch';
import { useMemoizedFn } from 'ahooks';
@ -12,7 +12,8 @@ import { NewDatasetGroupModal } from './NewPermissionDatasetGroupModal';
export const PermissionDatasetGroups: React.FC<{
datasetId: string;
}> = React.memo(({ datasetId }) => {
const { data: datasetGroups, isFetched: isDatasetGroupsFetched } = useListDatasetGroups();
const { data: datasetGroups, isFetched: isDatasetGroupsFetched } =
useDatasetListDatasetGroups(datasetId);
const [isNewDatasetGroupModalOpen, setIsNewDatasetGroupModalOpen] = useState(false);
const { filteredItems, searchText, handleSearchChange } = useDebounceSearch({

View File

@ -1,4 +1,4 @@
import { ListDatasetGroupsResponse, useUpdateDatasetGroups } from '@/api/busterv2';
import { ListDatasetGroupsResponse, useDatasetUpdateDatasetGroups } from '@/api/busterv2';
import { BusterListColumn, BusterListRowItem } from '@/components/list';
import { BusterInfiniteList } from '@/components/list/BusterInfiniteList';
import { useMemoizedFn } from 'ahooks';
@ -12,7 +12,7 @@ export const PermissionListDatasetGroupContainer: React.FC<{
datasetId: string;
}> = ({ filteredPermissionGroups, datasetId }) => {
const { styles, cx } = useStyles();
const { mutateAsync: updateDatasetGroups } = useUpdateDatasetGroups(datasetId);
const { mutateAsync: updateDatasetGroups } = useDatasetUpdateDatasetGroups(datasetId);
const [selectedRowKeys, setSelectedRowKeys] = useState<string[]>([]);
const numberOfPermissionGroups = filteredPermissionGroups.length;
@ -116,7 +116,7 @@ export const PermissionListDatasetGroupContainer: React.FC<{
showSelectAll={false}
selectedRowKeys={selectedRowKeys}
onSelectChange={setSelectedRowKeys}
emptyState={<div className="py-12">No teams found</div>}
emptyState={<div className="py-12">No dataset groups found</div>}
/>
</div>

View File

@ -1,10 +1,9 @@
import { useCreatePermissionGroup } from '@/api/busterv2/permission_groups/queryRequests';
import { AppModal } from '@/components';
import { useCreatePermissionGroup } from '@/api/busterv2/permission_groups';
import { AppModal } from '@/components/modal';
import { useMemoizedFn } from 'ahooks';
import React, { useEffect, useMemo, useRef } from 'react';
import { Input, InputRef } from 'antd';
import { useBusterNotifications } from '@/context/BusterNotifications';
interface NewPermissionGroupModalProps {
isOpen: boolean;
onClose: () => void;
@ -13,7 +12,7 @@ interface NewPermissionGroupModalProps {
export const NewPermissionGroupModal: React.FC<NewPermissionGroupModalProps> = React.memo(
({ isOpen, onClose, datasetId }) => {
const { mutateAsync, isPending } = useCreatePermissionGroup(datasetId);
const { mutateAsync, isPending } = useCreatePermissionGroup();
const inputRef = useRef<InputRef>(null);
const { openInfoMessage } = useBusterNotifications();
@ -25,7 +24,8 @@ export const NewPermissionGroupModal: React.FC<NewPermissionGroupModalProps> = R
return;
}
await mutateAsync({
name: inputValue
name: inputValue,
dataset_id: datasetId
});
onClose();
});
@ -61,7 +61,12 @@ export const NewPermissionGroupModal: React.FC<NewPermissionGroupModalProps> = R
return (
<AppModal open={isOpen} onClose={onClose} header={header} footer={footer}>
<Input ref={inputRef} placeholder="Name of permission group" />
<Input
ref={inputRef}
placeholder="Name of permission group"
autoFocus
onPressEnter={onCreateNewPermissionGroup}
/>
</AppModal>
);
}

View File

@ -1,4 +1,7 @@
import { ListPermissionGroupsResponse, useUpdatePermissionGroups } from '@/api/busterv2/datasets';
import {
ListPermissionGroupsResponse,
useDatasetUpdatePermissionGroups
} from '@/api/busterv2/datasets';
import { BusterListColumn, BusterListRowItem } from '@/components/list';
import { BusterInfiniteList } from '@/components/list/BusterInfiniteList';
import { useMemoizedFn } from 'ahooks';
@ -12,7 +15,7 @@ export const PermissionListPermissionGroupContainer: React.FC<{
datasetId: string;
}> = React.memo(({ filteredPermissionGroups, datasetId }) => {
const { styles, cx } = useStyles();
const { mutateAsync: updatePermissionGroups } = useUpdatePermissionGroups(datasetId);
const { mutateAsync: updatePermissionGroups } = useDatasetUpdatePermissionGroups(datasetId);
const [selectedRowKeys, setSelectedRowKeys] = useState<string[]>([]);
const numberOfPermissionGroups = filteredPermissionGroups.length;
@ -118,7 +121,7 @@ export const PermissionListPermissionGroupContainer: React.FC<{
onSelectChange={setSelectedRowKeys}
emptyState={
<div className="py-12">
<Text type="tertiary">No teams found</Text>
<Text type="tertiary">No permission groups found</Text>
</div>
}
/>

View File

@ -5,18 +5,18 @@ import { useMemoizedFn } from 'ahooks';
import { Button } from 'antd';
import { AppMaterialIcons } from '@/components';
import { PermissionListPermissionGroupContainer } from './PermissionListPermissionGroupContainer';
import { useListPermissionGroups } from '@/api/busterv2/datasets';
import { NewPermissionGroupModal } from './NewPermissionGroupModal';
import { useDebounceSearch } from '../useDebounceSearch';
import { useDatasetListPermissionGroups } from '@/api/busterv2';
export const PermissionPermissionGroup: React.FC<{
datasetId: string;
}> = React.memo(({ datasetId }) => {
const { data: permissionGroups, isFetched: isPermissionGroupsFetched } =
useListPermissionGroups(datasetId);
useDatasetListPermissionGroups(datasetId);
const [isNewPermissionGroupModalOpen, setIsNewPermissionGroupModalOpen] = useState(false);
const { filteredItems, searchText, handleSearchChange, isPending } = useDebounceSearch({
const { filteredItems, searchText, handleSearchChange } = useDebounceSearch({
items: permissionGroups || [],
searchPredicate: (item, searchText) => item.name.toLowerCase().includes(searchText)
});

View File

@ -1,7 +1,7 @@
import {
ListPermissionGroupsResponse,
ListPermissionUsersResponse,
useUpdatePermissionUsers
useDatasetUpdatePermissionUsers
} from '@/api/busterv2/datasets';
import { BusterUserAvatar } from '@/components';
import { BusterListColumn, BusterListRowItem } from '@/components/list';
@ -17,7 +17,7 @@ export const PermissionListUsersContainer: React.FC<{
datasetId: string;
}> = React.memo(({ filteredPermissionUsers, datasetId }) => {
const { styles, cx } = useStyles();
const { mutateAsync: updatePermissionUsers } = useUpdatePermissionUsers(datasetId);
const { mutateAsync: updatePermissionUsers } = useDatasetUpdatePermissionUsers(datasetId);
const [selectedRowKeys, setSelectedRowKeys] = useState<string[]>([]);
const numberOfPermissionUsers = filteredPermissionUsers.length;
@ -123,7 +123,7 @@ export const PermissionListUsersContainer: React.FC<{
onSelectChange={setSelectedRowKeys}
emptyState={
<div className="py-12">
<Text type="tertiary">No teams found</Text>
<Text type="tertiary">No users found</Text>
</div>
}
/>

View File

@ -1,7 +1,7 @@
import React from 'react';
import { HeaderExplanation } from '../HeaderExplanation';
import { PermissionSearch } from '../PermissionSearch';
import { useListPermissionUsers } from '@/api/busterv2';
import { useDatasetListPermissionUsers } from '@/api/busterv2';
import { useDebounceSearch } from '../useDebounceSearch';
import { Button } from 'antd';
import { AppMaterialIcons } from '@/components/icons';
@ -14,7 +14,7 @@ export const PermissionUsers: React.FC<{
}> = React.memo(({ datasetId }) => {
const onToggleInviteModal = useAppLayoutContextSelector((x) => x.onToggleInviteModal);
const { data: permissionUsers, isFetched: isPermissionUsersFetched } =
useListPermissionUsers(datasetId);
useDatasetListPermissionUsers(datasetId);
const { searchText, handleSearchChange, filteredItems } = useDebounceSearch({
items: permissionUsers || [],

View File

@ -152,7 +152,6 @@ export const useBusterChartJSLegend = ({
});
const onLegendItemFocus = useMemoizedFn((item: BusterChartLegendItem) => {
// console.log('onLegendItemFocus', item);
alert('TODO');
});

View File

@ -30,7 +30,9 @@ export const NoChartData: React.FC<{
return (
<div
className={busterChartsTwMerge('flex h-full w-full items-center justify-center', className)}>
<Text className={busterChartsTwMerge()}>{noDataText}</Text>
<Text type="tertiary" className={busterChartsTwMerge()}>
{noDataText}
</Text>
</div>
);
};

View File

@ -1,5 +1,5 @@
import React from 'react';
import { useMemoizedFn, useUpdateEffect } from 'ahooks';
import { useMemoizedFn } from 'ahooks';
import { BusterListProps } from '../BusterList';
import { getAllIdsInSection } from '../BusterList/helpers';
import { useEffect, useMemo, useRef, useCallback } from 'react';
@ -19,8 +19,8 @@ export const BusterInfiniteList: React.FC<BusterInfiniteListProps> = ({
onSelectChange,
emptyState,
showHeader = true,
columnHeaderVariant,
contextMenu,
columnRowVariant = 'containerized',
showSelectAll = true,
onScrollEnd,
loadingNewContent,
@ -68,9 +68,18 @@ export const BusterInfiniteList: React.FC<BusterInfiniteListProps> = ({
selectedRowKeys,
onSelectChange: onSelectChange ? onSelectChangePreflight : undefined,
onSelectSectionChange: onSelectChange ? onSelectSectionChange : undefined,
onContextMenuClick: undefined
onContextMenuClick: undefined,
columnRowVariant
};
}, [columns, rows, onSelectChange, onSelectSectionChange, contextMenu, selectedRowKeys]);
}, [
columns,
rows,
onSelectChange,
columnRowVariant,
onSelectSectionChange,
contextMenu,
selectedRowKeys
]);
// Add scroll handler
const handleScroll = useCallback(() => {

View File

@ -1,7 +1,7 @@
import { useMemoizedFn } from 'ahooks';
import get from 'lodash/get';
import React, { useMemo } from 'react';
import { BusterListRow, BusterListColumn, BusterListRowItem } from './interfaces';
import { BusterListRow, BusterListColumn, BusterListRowItem, BusterListProps } from './interfaces';
import Link from 'next/link';
import { CheckboxColumn } from './CheckboxColumn';
import { createStyles } from 'antd-style';
@ -17,63 +17,60 @@ export const BusterListRowComponent = React.memo(
onSelectChange?: (v: boolean, id: string) => void;
onContextMenuClick?: (e: React.MouseEvent<HTMLDivElement>, id: string) => void;
style?: React.CSSProperties;
columnRowVariant: BusterListProps['columnRowVariant'];
}
>(({ style, row, columns, onSelectChange, checked, onContextMenuClick }, ref) => {
const { styles, cx } = useStyles();
const link = row.link;
// const router = useRouter();
>(
(
{ style, columnRowVariant, row, columns, onSelectChange, checked, onContextMenuClick },
ref
) => {
const { styles, cx } = useStyles();
const link = row.link;
const onClick = useMemoizedFn(() => {
// if (link) {
// const isLocalLink = link.startsWith('/');
// if (isLocalLink) {
// router.push(link);
// } else {
// window.open(link, '_blank');
// }
// }
row.onClick?.();
});
const onContextMenu = useMemoizedFn((e: React.MouseEvent<HTMLDivElement>) => {
onContextMenuClick?.(e, row.id);
});
const onContextMenu = useMemoizedFn((e: React.MouseEvent<HTMLDivElement>) => {
onContextMenuClick?.(e, row.id);
});
const onChange = useMemoizedFn((checked: boolean) => {
onSelectChange?.(checked, row.id);
});
const onChange = useMemoizedFn((checked: boolean) => {
onSelectChange?.(checked, row.id);
});
return (
<LinkWrapper href={link}>
<div
onClick={onClick}
style={style}
onContextMenu={onContextMenu}
className={cx(styles.row, 'group flex items-center', checked ? 'checked' : '', {
clickable: !!(link || row.onClick)
})}
ref={ref}>
{!!onSelectChange ? (
<CheckboxColumn checkStatus={checked ? 'checked' : 'unchecked'} onChange={onChange} />
) : (
<div className="pl-2.5"></div>
)}
{columns.map((column, columnIndex) => (
<BusterListCellComponent
key={column.dataIndex}
data={get(row.data, column.dataIndex)}
row={row}
render={column.render}
isFirstCell={columnIndex === 0}
isLastCell={columnIndex === columns.length - 1}
width={column.width}
onSelectChange={onSelectChange}
/>
))}
</div>
</LinkWrapper>
);
}),
return (
<LinkWrapper href={link}>
<div
onClick={row.onClick}
style={style}
onContextMenu={onContextMenu}
className={cx(
styles.row,
'group flex items-center',
checked ? 'checked' : '',
columnRowVariant,
{ clickable: !!(link || row.onClick) }
)}
ref={ref}>
{!!onSelectChange ? (
<CheckboxColumn checkStatus={checked ? 'checked' : 'unchecked'} onChange={onChange} />
) : (
<div className="pl-2.5"></div>
)}
{columns.map((column, columnIndex) => (
<BusterListCellComponent
key={column.dataIndex}
data={get(row.data, column.dataIndex)}
row={row}
render={column.render}
isFirstCell={columnIndex === 0}
isLastCell={columnIndex === columns.length - 1}
width={column.width}
onSelectChange={onSelectChange}
/>
))}
</div>
</LinkWrapper>
);
}
),
(prevProps, nextProps) => {
return prevProps.checked === nextProps.checked && prevProps.row.id === nextProps.row.id;
}
@ -151,6 +148,14 @@ export const useStyles = createStyles(({ css, token }) => ({
background-color: ${token.colorPrimaryBgHover};
}
}
&.containerized {
background-color: ${token.colorBgContainer};
&:last-child {
border-bottom: 0px;
}
}
`,
cell: css`
color: ${token.colorText};

View File

@ -1,5 +1,5 @@
import React from 'react';
import { BusterListRow, BusterListColumn } from './interfaces';
import { BusterListRow, BusterListColumn, BusterListProps } from './interfaces';
import { BusterListSectionComponent } from './BusterListSectionComponent';
import { BusterListRowComponent } from './BusterListRowComponent';
@ -15,6 +15,7 @@ export const BusterListRowComponentSelector = React.forwardRef<
selectedRowKeys?: string[];
rows: BusterListRow[];
style?: React.CSSProperties;
columnRowVariant: BusterListProps['columnRowVariant'];
}
>(
(
@ -26,7 +27,8 @@ export const BusterListRowComponentSelector = React.forwardRef<
onSelectChange,
onSelectSectionChange,
selectedRowKeys,
onContextMenuClick
onContextMenuClick,
columnRowVariant
},
ref
) => {
@ -55,6 +57,7 @@ export const BusterListRowComponentSelector = React.forwardRef<
checked={!!selectedRowKeys?.includes(row.id)}
ref={ref}
onContextMenuClick={onContextMenuClick}
columnRowVariant={columnRowVariant}
/>
);
}

View File

@ -8,7 +8,7 @@ import type {
import React from 'react';
export interface BusterListProps {
columns: BusterListColumn[];
columnHeaderVariant?: 'default' | 'gray';
columnRowVariant?: 'default' | 'containerized';
rows: BusterListRow[];
onSelectChange?: (selectedRowKeys: string[]) => void;
emptyState?: undefined | React.ReactNode;

View File

@ -3,6 +3,7 @@ import { createClient } from '@/context/Supabase/server';
import { redirect } from 'next/navigation';
import { BusterRoutes, createBusterRoute } from '@/routes/busterRoutes/busterRoutes';
import Cookies from 'js-cookie';
import { QueryClient } from '@tanstack/react-query';
//TODO use google one click: https://supabase.com/docs/guides/auth/social-login/auth-google#google-pre-built
@ -142,6 +143,7 @@ export const useBusterSupabaseAuthMethods = () => {
'use server';
const supabase = await createClient();
const queryClient = new QueryClient();
const { error } = await supabase.auth.signOut();
@ -153,6 +155,7 @@ export const useBusterSupabaseAuthMethods = () => {
Object.keys(Cookies.get()).forEach((cookieName) => {
Cookies.remove(cookieName);
});
queryClient.clear();
}, 650);
return redirect(