rip out some users context

This commit is contained in:
Nate Kelley 2025-03-12 14:28:32 -06:00
parent 55ffb94fe2
commit 7eaee18f09
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
13 changed files with 82 additions and 137 deletions

View File

@ -11,12 +11,15 @@ import {
deleteUserFavorite,
updateUserFavorites,
getUserList,
getUserList_server
getUserList_server,
inviteUser
} from './requests';
import { useMemoizedFn } from '@/hooks';
import { QueryClient, useQueryClient } from '@tanstack/react-query';
import { queryKeys } from '@/api/query_keys';
import type { UserRequestUserListPayload } from '@/api/request_interfaces/user/interfaces';
import { useBusterNotifications } from '@/context/BusterNotifications';
import { useCreateOrganization } from '../organizations/queryRequests';
export const useGetMyUserInfo = () => {
return useQuery({
@ -115,7 +118,7 @@ export const useDeleteUserFavorite = () => {
mutationFn: deleteUserFavorite,
onMutate: (params) => {
queryClient.setQueryData(queryKeys.favoritesGetList.queryKey, (prev) => {
return prev?.filter((fav) => fav.id !== params.id);
return prev?.filter((fav) => !params.some((p) => p.id === fav.id));
});
},
onSettled: () => {
@ -161,3 +164,38 @@ export const prefetchGetUserList = async (
});
return queryClient;
};
export const useInviteUser = () => {
const { openSuccessMessage } = useBusterNotifications();
return useMutation({
mutationFn: inviteUser,
onSuccess: () => {
openSuccessMessage('Invites sent');
// queryClient.invalidateQueries(queryKeys.userGetUserList);
}
});
};
export const useCreateUserOrganization = () => {
const { data: userResponse, refetch: refetchUserResponse } = useGetMyUserInfo();
const { mutateAsync: createOrganization } = useCreateOrganization();
const { mutateAsync: updateUserInfo } = useUpdateUser();
const onCreateUserOrganization = useMemoizedFn(
async ({ name, company }: { name: string; company: string }) => {
const alreadyHasOrganization = !!userResponse?.organizations?.[0];
if (!alreadyHasOrganization) await createOrganization({ name: company });
if (userResponse)
await updateUserInfo({
userId: userResponse.user.id,
name
});
await refetchUserResponse();
}
);
return onCreateUserOrganization;
};

View File

@ -14,7 +14,9 @@ import type { UserRequestUserListPayload } from '@/api/request_interfaces/user/i
const favoritesGetList = queryOptions<BusterUserFavorite[]>({
queryKey: ['users', 'favorites', 'list'] as const,
staleTime: 1000 * 60 * 60 // 1 hour
staleTime: 1000 * 60 * 60, // 1 hour,
initialData: [],
initialDataUpdatedAt: 0
});
const userGetUserMyself = queryOptions<BusterUserResponse>({

View File

@ -7,10 +7,10 @@ export interface UsersFavoritePostPayload {
name: string;
}
export interface UserFavoriteDeletePayload {
export type UserFavoriteDeletePayload = {
id: string;
asset_type: ShareAssetType;
}
}[];
export interface UserUpdateFavoritesPayload {
favorites: string[]; // Array of favorite ids

View File

@ -11,11 +11,12 @@ import { BusterRoutes } from '@/routes/busterRoutes';
import { useBusterNotifications } from '@/context/BusterNotifications';
import { Button } from '@/components/ui/buttons';
import { Input } from '@/components/ui/inputs';
import { useCreateUserOrganization } from '@/api/buster_rest/users';
export const NewUserController = () => {
const [started, setStarted] = useState(false);
const onChangePage = useAppLayoutContextSelector((s) => s.onChangePage);
const onCreateUserOrganization = useUserConfigContextSelector((s) => s.onCreateUserOrganization);
const onCreateUserOrganization = useCreateUserOrganization();
const user = useUserConfigContextSelector((s) => s.user);
const userOrganizations = useUserConfigContextSelector((s) => s.userOrganizations);
const { openInfoMessage } = useBusterNotifications();

View File

@ -7,6 +7,11 @@ import { Button } from '@/components/ui/buttons';
import { cn } from '@/lib/classMerge';
import { Star } from '@/components/ui/icons';
import { cva } from 'class-variance-authority';
import {
useAddUserFavorite,
useDeleteUserFavorite,
useGetUserFavorites
} from '@/api/buster_rest/users';
const favoriteStarVariants = cva('transition-colors', {
variants: {
@ -32,11 +37,9 @@ export const FavoriteStar: React.FC<{
className?: string;
iconStyle?: 'default' | 'tertiary';
}> = React.memo(({ title: name, id, type, className = '', iconStyle = 'default' }) => {
const userFavorites = useUserConfigContextSelector((state) => state.userFavorites);
const removeItemFromFavorite = useUserConfigContextSelector(
(state) => state.removeItemFromFavorite
);
const addItemToFavorite = useUserConfigContextSelector((state) => state.addItemToFavorite);
const { data: userFavorites } = useGetUserFavorites();
const { mutateAsync: removeItemFromFavorite } = useDeleteUserFavorite();
const { mutateAsync: addItemToFavorite } = useAddUserFavorite();
const isFavorited = useMemo(() => {
return userFavorites?.some((favorite) => favorite.id === id || favorite.collection_id === id);
@ -52,10 +55,12 @@ export const FavoriteStar: React.FC<{
name
});
await removeItemFromFavorite({
await removeItemFromFavorite([
{
asset_type: type,
id
});
}
]);
});
const tooltipText = isFavorited ? 'Remove from favorites' : 'Add to favorites';

View File

@ -1,23 +1,18 @@
import React, { useMemo } from 'react';
import { useMemoizedFn } from '@/hooks';
import { AppModal } from '@/components/ui/modal';
import { useUserConfigContextSelector } from '@/context/Users';
import { TagInput } from '@/components/ui/inputs/InputTagInput';
import { useInviteUser } from '@/api/buster_rest/users';
export const InvitePeopleModal: React.FC<{
open: boolean;
onClose: () => void;
}> = React.memo(({ open, onClose }) => {
const [emails, setEmails] = React.useState<string[]>([]);
const [inviting, setInviting] = React.useState<boolean>(false);
const inviteUsers = useUserConfigContextSelector((state) => state.inviteUsers);
const isAdmin = useUserConfigContextSelector((state) => state.isAdmin);
const userTeams = useUserConfigContextSelector((state) => state.userTeams);
const { mutateAsync: inviteUsers, isPending: inviting } = useInviteUser();
const handleInvite = useMemoizedFn(async () => {
setInviting(true);
await inviteUsers(emails);
setInviting(false);
await inviteUsers({ emails });
onClose();
});

View File

@ -18,6 +18,7 @@ import { SupportModal } from '../modal/SupportModal';
import { InvitePeopleModal } from '../modal/InvitePeopleModal';
import { useMemoizedFn } from '@/hooks';
import { SidebarUserFooter } from './SidebarUserFooter/SidebarUserFooter';
import { useGetUserFavorites } from '@/api/buster_rest';
const topItems: ISidebarList = {
items: [
@ -106,7 +107,7 @@ const tryGroup = (onClickInvitePeople: () => void, onClickLeaveFeedback: () => v
export const SidebarPrimary = React.memo(() => {
const isAdmin = useUserConfigContextSelector((x) => x.isAdmin);
const favorites = useUserConfigContextSelector((state) => state.userFavorites);
const { data: favorites } = useGetUserFavorites();
const currentRoute = useAppLayoutContextSelector((x) => x.currentRoute);
const onToggleSupportModal = useAppLayoutContextSelector((s) => s.onToggleSupportModal);
const onToggleInviteModal = useAppLayoutContextSelector((s) => s.onToggleInviteModal);

View File

@ -1,9 +1,8 @@
import { useMemoizedFn } from '@/hooks';
import type { IBusterMetric } from '@/api/asset_interfaces/metric';
import { useUserConfigContextSelector } from '@/context/Users';
import { useBusterNotifications } from '@/context/BusterNotifications';
import { useUpdateMetricConfig } from './useMetricUpdateConfig';
import { useGetUserFavorites } from '@/api/buster_rest/users';
export const useUpdateMetricAssosciations = ({
getMetricMemoized,
updateMetricMutation
@ -11,8 +10,7 @@ export const useUpdateMetricAssosciations = ({
getMetricMemoized: ({ metricId }: { metricId?: string }) => IBusterMetric;
updateMetricMutation: ReturnType<typeof useUpdateMetricConfig>['updateMetricMutation'];
}) => {
const userFavorites = useUserConfigContextSelector((state) => state.userFavorites);
const refreshFavoritesList = useUserConfigContextSelector((x) => x.refreshFavoritesList);
const { data: userFavorites, refetch: refreshFavoritesList } = useGetUserFavorites();
const { openConfirmModal } = useBusterNotifications();

View File

@ -2,29 +2,15 @@
import type { BusterUserResponse } from '@/api/asset_interfaces/users';
import React, { PropsWithChildren } from 'react';
import { useFavoriteProvider } from './useFavoriteProvider';
import { useGetMyUserInfo } from '@/api/buster_rest/users';
import { useSupabaseContext } from '../Supabase';
import { createContext, useContextSelector } from 'use-context-selector';
import { useUserOrganization } from './useUserOrganization';
import { useInviteUser } from './useInviteUser';
import { checkIfUserIsAdmin } from '@/lib/user';
export const useUserConfigProvider = ({ userInfo }: { userInfo: BusterUserResponse | null }) => {
const isAnonymousUser = useSupabaseContext((state) => state.isAnonymousUser);
const { data: userResponseData, refetch: refetchUserResponse } = useGetMyUserInfo();
const { data: userResponseData } = useGetMyUserInfo();
const userResponse = userResponseData || userInfo;
const favoriteConfig = useFavoriteProvider();
const inviteUsers = useInviteUser();
const { onCreateUserOrganization } = useUserOrganization({
userResponse,
refetchUserResponse
});
const user = userResponse?.user;
const userTeams = userResponse?.teams || [];
const userOrganizations = userResponse?.organizations?.[0];
@ -35,16 +21,13 @@ export const useUserConfigProvider = ({ userInfo }: { userInfo: BusterUserRespon
const isAdmin = checkIfUserIsAdmin(userResponse);
return {
onCreateUserOrganization,
userTeams,
user,
userRole,
isAdmin,
userOrganizations,
isUserRegistered,
isAnonymousUser,
...inviteUsers,
...favoriteConfig
isAnonymousUser
};
};

View File

@ -1,31 +0,0 @@
import { useMemoizedFn } from '@/hooks';
import type { BusterUserFavorite } from '@/api/asset_interfaces/users';
import isEmpty from 'lodash/isEmpty';
import {
useAddUserFavorite,
useDeleteUserFavorite,
useGetUserFavorites
} from '@/api/buster_rest/users';
const DEFAULT_FAVORITES: BusterUserFavorite[] = [];
export const useFavoriteProvider = () => {
const { data: userFavorites, refetch: refreshFavoritesList } = useGetUserFavorites();
const { mutate: addItemToFavorite } = useAddUserFavorite();
const { mutate: removeItemFromFavorite } = useDeleteUserFavorite();
const bulkEditFavorites = useMemoizedFn(async (favorites: string[]) => {
// return updateFavorites({ favorites });
alert('TODO - feature not implemented yet');
});
return {
bulkEditFavorites,
refreshFavoritesList,
userFavorites: isEmpty(userFavorites) ? DEFAULT_FAVORITES : userFavorites!,
addItemToFavorite,
removeItemFromFavorite
};
};

View File

@ -1,18 +0,0 @@
import { useMemoizedFn } from '@/hooks';
import { timeout } from '@/lib';
import { useBusterNotifications } from '../BusterNotifications';
import { inviteUser as inviteUserRest } from '@/api/buster_rest';
export const useInviteUser = () => {
const { openSuccessMessage } = useBusterNotifications();
const inviteUsers = useMemoizedFn(async (emails: string[], team_ids?: string[]) => {
await inviteUserRest({ emails, team_ids });
await timeout(100);
openSuccessMessage('Invites sent');
});
return {
inviteUsers
};
};

View File

@ -1,34 +0,0 @@
import { useMemoizedFn } from '@/hooks';
import type { BusterUserResponse } from '@/api/asset_interfaces/users';
import { useCreateOrganization, useUpdateUser } from '@/api/buster_rest';
export const useUserOrganization = ({
userResponse,
refetchUserResponse
}: {
userResponse: BusterUserResponse | null | undefined;
refetchUserResponse: () => Promise<unknown>;
}) => {
const { mutateAsync: createOrganization } = useCreateOrganization();
const { mutateAsync: updateUserInfo } = useUpdateUser();
const onCreateUserOrganization = useMemoizedFn(
async ({ name, company }: { name: string; company: string }) => {
const alreadyHasOrganization = !!userResponse?.organizations?.[0];
if (!alreadyHasOrganization) await createOrganization({ name: company });
if (userResponse)
await updateUserInfo({
userId: userResponse.user.id,
name
});
await refetchUserResponse();
}
);
return {
onCreateUserOrganization
};
};

View File

@ -6,12 +6,17 @@ import { BusterListSelectedOptionPopupContainer } from '@/components/ui/list';
import { Dropdown, DropdownItems } from '@/components/ui/dropdown';
import { Button } from '@/components/ui/buttons';
import { useBusterMetricsIndividualContextSelector } from '@/context/Metrics';
import { useUserConfigContextSelector } from '@/context/Users';
import { useMemoizedFn } from '@/hooks';
import { SaveToCollectionsDropdown } from '@/components/features/dropdowns/SaveToCollectionsDropdown';
import { useBusterNotifications } from '@/context/BusterNotifications';
import { ASSET_ICONS } from '@/components/features/config/assetIcons';
import { useDeleteMetric } from '@/api/buster_rest/metrics';
import {
useAddUserFavorite,
useDeleteUserFavorite,
useGetUserFavorites
} from '@/api/buster_rest/users';
import { ShareAssetType } from '@/api/asset_interfaces/share';
export const ChatSelectedOptionPopup: React.FC<{
selectedRowKeys: string[];
@ -137,8 +142,8 @@ const ThreeDotButton: React.FC<{
selectedRowKeys: string[];
onSelectChange: (selectedRowKeys: string[]) => void;
}> = ({ selectedRowKeys, onSelectChange }) => {
const bulkEditFavorites = useUserConfigContextSelector((state) => state.bulkEditFavorites);
const userFavorites = useUserConfigContextSelector((state) => state.userFavorites);
const { mutateAsync: removeUserFavorite } = useDeleteUserFavorite();
const { data: userFavorites } = useGetUserFavorites();
const dropdownOptions: DropdownItems = [
{
@ -156,10 +161,10 @@ const ThreeDotButton: React.FC<{
icon: <Xmark />,
value: 'remove-from-favorites',
onClick: async () => {
const allFavorites: string[] = userFavorites
.map((f) => f.id)
.filter((id) => !selectedRowKeys.includes(id));
bulkEditFavorites(allFavorites);
const allFavorites: Parameters<typeof removeUserFavorite>[0] = userFavorites
.filter((f) => !selectedRowKeys.includes(f.id))
.map((f) => ({ id: f.id, asset_type: ShareAssetType.METRIC }));
await removeUserFavorite(allFavorites);
}
}
];