diff --git a/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx b/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx index 0653ddbf2..c0f5bf0b0 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx @@ -9,6 +9,7 @@ import type React from "react"; import { useCallback, useEffect, useMemo, useState } from "react"; import { activeChathatUIAtom, activeChatIdAtom } from "@/atoms/chats/ui.atoms"; import { llmPreferencesAtom } from "@/atoms/llm-config/llm-config-query.atoms"; +import { myAccessAtom } from "@/atoms/members/members-query.atoms"; import { activeSearchSpaceIdAtom } from "@/atoms/search-spaces/search-space-query.atoms"; import { ChatPanelContainer } from "@/components/chat/ChatPanel/ChatPanelContainer"; import { DashboardBreadcrumb } from "@/components/dashboard-breadcrumb"; @@ -17,7 +18,6 @@ import { AppSidebarProvider } from "@/components/sidebar/AppSidebarProvider"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Separator } from "@/components/ui/separator"; import { SidebarInset, SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"; -import { myAccessAtom } from "@/atoms/members/members-query.atoms"; import { cn } from "@/lib/utils"; export function DashboardClientLayout({ diff --git a/surfsense_web/app/dashboard/[search_space_id]/team/page.tsx b/surfsense_web/app/dashboard/[search_space_id]/team/page.tsx index 1b0082186..49e1de2ab 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/team/page.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/team/page.tsx @@ -46,14 +46,21 @@ import { motion } from "motion/react"; import { useParams, useRouter } from "next/navigation"; import { useCallback, useMemo, useState } from "react"; import { toast } from "sonner"; -import { updateMemberMutationAtom, deleteMemberMutationAtom } from "@/atoms/members/members-mutation.atoms"; -import { myAccessAtom } from "@/atoms/members/members-query.atoms"; -import { createInviteMutationAtom, deleteInviteMutationAtom } from '@/atoms/invites/invites-mutation.atoms'; -import type { DeleteInviteRequest } from '@/contracts/types/invites.types'; -import type { UpdateMembershipRequest, DeleteMembershipRequest} from "@/contracts/types/members.types"; +import { + createInviteMutationAtom, + deleteInviteMutationAtom, +} from "@/atoms/invites/invites-mutation.atoms"; +import { + deleteMemberMutationAtom, + updateMemberMutationAtom, +} from "@/atoms/members/members-mutation.atoms"; +import { membersAtom, myAccessAtom } from "@/atoms/members/members-query.atoms"; import { permissionsAtom } from "@/atoms/permissions/permissions-query.atoms"; -import { membersAtom } from "@/atoms/members/members-query.atoms"; -import { invitesApiService } from '@/lib/apis/invites-api.service'; +import { + createRoleMutationAtom, + deleteRoleMutationAtom, + updateRoleMutationAtom, +} from "@/atoms/roles/roles-mutation.atoms"; import { AlertDialog, AlertDialogAction, @@ -109,21 +116,26 @@ import { } from "@/components/ui/table"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Textarea } from "@/components/ui/textarea"; +import type { + CreateInviteRequest, + DeleteInviteRequest, + Invite, +} from "@/contracts/types/invites.types"; +import type { + DeleteMembershipRequest, + Membership, + UpdateMembershipRequest, +} from "@/contracts/types/members.types"; import type { CreateRoleRequest, DeleteRoleRequest, Role, UpdateRoleRequest, } from "@/contracts/types/roles.types"; -import { - type Invite, - type CreateInviteRequest, -} from "@/contracts/types/invites.types"; -import type { Membership } from "@/contracts/types/members.types"; +import { invitesApiService } from "@/lib/apis/invites-api.service"; import { rolesApiService } from "@/lib/apis/roles-api.service"; import { cacheKeys } from "@/lib/query-client/cache-keys"; import { cn } from "@/lib/utils"; -import { createRoleMutationAtom, deleteRoleMutationAtom, updateRoleMutationAtom } from "@/atoms/roles/roles-mutation.atoms"; // Animation variants const fadeInUp = { @@ -165,7 +177,11 @@ export default function TeamManagementPage() { [access] ); - const { data: members = [], isLoading: membersLoading, refetch: fetchMembers } = useAtomValue(membersAtom); + const { + data: members = [], + isLoading: membersLoading, + refetch: fetchMembers, + } = useAtomValue(membersAtom); const { mutateAsync: createRole } = useAtomValue(createRoleMutationAtom); const { mutateAsync: updateRole } = useAtomValue(updateRoleMutationAtom); @@ -189,7 +205,7 @@ export default function TeamManagementPage() { ); const handleCreateInvite = useCallback( - async (inviteData: CreateInviteRequest['data']) => { + async (inviteData: CreateInviteRequest["data"]) => { const request: CreateInviteRequest = { search_space_id: searchSpaceId, data: inviteData, @@ -243,12 +259,11 @@ export default function TeamManagementPage() { role_id: roleId, }, }; - return await updateMember(request) as Membership; + return (await updateMember(request)) as Membership; }, [updateMember, searchSpaceId] ); - const handleRemoveMember = useCallback( async (membershipId: number) => { const request: DeleteMembershipRequest = { @@ -257,7 +272,7 @@ export default function TeamManagementPage() { }; await deleteMember(request); - return true + return true; }, [deleteMember, searchSpaceId] ); @@ -1077,7 +1092,7 @@ function CreateInviteDialog({ searchSpaceId, }: { roles: Role[]; - onCreateInvite: (data: CreateInviteRequest['data']) => Promise; + onCreateInvite: (data: CreateInviteRequest["data"]) => Promise; searchSpaceId: number; }) { const [open, setOpen] = useState(false); @@ -1092,7 +1107,7 @@ function CreateInviteDialog({ const handleCreate = async () => { setCreating(true); try { - const data: CreateInviteRequest['data'] = {}; + const data: CreateInviteRequest["data"] = {}; if (name) data.name = name; if (roleId && roleId !== "default") data.role_id = Number(roleId); if (maxUses) data.max_uses = Number(maxUses); diff --git a/surfsense_web/app/invite/[invite_code]/page.tsx b/surfsense_web/app/invite/[invite_code]/page.tsx index 293015744..30e93c022 100644 --- a/surfsense_web/app/invite/[invite_code]/page.tsx +++ b/surfsense_web/app/invite/[invite_code]/page.tsx @@ -1,7 +1,7 @@ "use client"; -import { useAtomValue } from "jotai"; import { useQuery } from "@tanstack/react-query"; +import { useAtomValue } from "jotai"; import { AlertCircle, ArrowRight, @@ -21,8 +21,6 @@ import { useParams, useRouter } from "next/navigation"; import { use, useCallback, useEffect, useState } from "react"; import { toast } from "sonner"; import { acceptInviteMutationAtom } from "@/atoms/invites/invites-mutation.atoms"; -import { invitesApiService } from "@/lib/apis/invites-api.service"; -import { cacheKeys } from "@/lib/query-client/cache-keys"; import { Button } from "@/components/ui/button"; import { Card, @@ -32,8 +30,10 @@ import { CardHeader, CardTitle, } from "@/components/ui/card"; +import type { AcceptInviteResponse } from "@/contracts/types/invites.types"; +import { invitesApiService } from "@/lib/apis/invites-api.service"; import { getBearerToken } from "@/lib/auth-utils"; -import { AcceptInviteResponse } from "@/contracts/types/invites.types"; +import { cacheKeys } from "@/lib/query-client/cache-keys"; export default function InviteAcceptPage() { const params = useParams(); @@ -41,9 +41,9 @@ export default function InviteAcceptPage() { const inviteCode = params.invite_code as string; const { data: inviteInfo = null, isLoading: loading } = useQuery({ - queryKey: cacheKeys.invites.info(inviteCode), - enabled: !!inviteCode, - staleTime: 5 * 60 * 1000, + queryKey: cacheKeys.invites.info(inviteCode), + enabled: !!inviteCode, + staleTime: 5 * 60 * 1000, queryFn: async () => { if (!inviteCode) return null; return invitesApiService.getInviteInfo({ diff --git a/surfsense_web/atoms/invites/invites-mutation.atoms.ts b/surfsense_web/atoms/invites/invites-mutation.atoms.ts index 2a82a8f15..f2acb6e4a 100644 --- a/surfsense_web/atoms/invites/invites-mutation.atoms.ts +++ b/surfsense_web/atoms/invites/invites-mutation.atoms.ts @@ -1,14 +1,14 @@ import { atomWithMutation } from "jotai-tanstack-query"; +import { toast } from "sonner"; +import type { + AcceptInviteRequest, + CreateInviteRequest, + DeleteInviteRequest, + UpdateInviteRequest, +} from "@/contracts/types/invites.types"; import { invitesApiService } from "@/lib/apis/invites-api.service"; import { cacheKeys } from "@/lib/query-client/cache-keys"; import { queryClient } from "@/lib/query-client/client"; -import type { - CreateInviteRequest, - UpdateInviteRequest, - DeleteInviteRequest, - AcceptInviteRequest, -} from "@/contracts/types/invites.types"; -import { toast } from "sonner"; /** * Mutation atom for creating an invite diff --git a/surfsense_web/atoms/members/members-mutation.atoms.ts b/surfsense_web/atoms/members/members-mutation.atoms.ts index 0851a71e5..d01d3b489 100644 --- a/surfsense_web/atoms/members/members-mutation.atoms.ts +++ b/surfsense_web/atoms/members/members-mutation.atoms.ts @@ -1,12 +1,12 @@ import { atomWithMutation } from "jotai-tanstack-query"; import { toast } from "sonner"; import type { - UpdateMembershipRequest, - UpdateMembershipResponse, DeleteMembershipRequest, DeleteMembershipResponse, LeaveSearchSpaceRequest, LeaveSearchSpaceResponse, + UpdateMembershipRequest, + UpdateMembershipResponse, } from "@/contracts/types/members.types"; import { membersApiService } from "@/lib/apis/members-api.service"; import { cacheKeys } from "@/lib/query-client/cache-keys"; diff --git a/surfsense_web/lib/apis/invites-api.service.ts b/surfsense_web/lib/apis/invites-api.service.ts index e7c3a8426..b5954e5f6 100644 --- a/surfsense_web/lib/apis/invites-api.service.ts +++ b/surfsense_web/lib/apis/invites-api.service.ts @@ -1,28 +1,28 @@ import { - type CreateInviteRequest, - type CreateInviteResponse, - type GetInvitesRequest, - type GetInvitesResponse, - type UpdateInviteRequest, - type UpdateInviteResponse, - type DeleteInviteRequest, - type DeleteInviteResponse, - type GetInviteInfoRequest, - type GetInviteInfoResponse, type AcceptInviteRequest, type AcceptInviteResponse, - createInviteRequest, - createInviteResponse, - getInvitesRequest, - getInvitesResponse, - updateInviteRequest, - updateInviteResponse, - deleteInviteRequest, - deleteInviteResponse, - getInviteInfoRequest, - getInviteInfoResponse, acceptInviteRequest, acceptInviteResponse, + type CreateInviteRequest, + type CreateInviteResponse, + createInviteRequest, + createInviteResponse, + type DeleteInviteRequest, + type DeleteInviteResponse, + deleteInviteRequest, + deleteInviteResponse, + type GetInviteInfoRequest, + type GetInviteInfoResponse, + type GetInvitesRequest, + type GetInvitesResponse, + getInviteInfoRequest, + getInviteInfoResponse, + getInvitesRequest, + getInvitesResponse, + type UpdateInviteRequest, + type UpdateInviteResponse, + updateInviteRequest, + updateInviteResponse, } from "@/contracts/types/invites.types"; import { ValidationError } from "@/lib/error"; import { baseApiService } from "./base-api.service"; @@ -33,10 +33,10 @@ class InvitesApiService { */ createInvite = async (request: CreateInviteRequest) => { const parsedRequest = createInviteRequest.safeParse(request); - + if (!parsedRequest.success) { console.error("Invalid request:", parsedRequest.error); - + const errorMessage = parsedRequest.error.errors.map((err) => err.message).join(", "); throw new ValidationError(`Invalid request: ${errorMessage}`); } @@ -55,18 +55,18 @@ class InvitesApiService { */ getInvites = async (request: GetInvitesRequest) => { const parsedRequest = getInvitesRequest.safeParse(request); - + if (!parsedRequest.success) { console.error("Invalid request:", parsedRequest.error); - + const errorMessage = parsedRequest.error.errors.map((err) => err.message).join(", "); throw new ValidationError(`Invalid request: ${errorMessage}`); } return baseApiService.get( - `/api/v1/searchspaces/${parsedRequest.data.search_space_id}/invites`, - getInvitesResponse - ); + `/api/v1/searchspaces/${parsedRequest.data.search_space_id}/invites`, + getInvitesResponse + ); }; /** @@ -74,21 +74,21 @@ class InvitesApiService { */ updateInvite = async (request: UpdateInviteRequest) => { const parsedRequest = updateInviteRequest.safeParse(request); - + if (!parsedRequest.success) { console.error("Invalid request:", parsedRequest.error); - + const errorMessage = parsedRequest.error.errors.map((err) => err.message).join(", "); throw new ValidationError(`Invalid request: ${errorMessage}`); } return baseApiService.put( - `/api/v1/searchspaces/${parsedRequest.data.search_space_id}/invites/${parsedRequest.data.invite_id}`, - updateInviteResponse, - { - body: parsedRequest.data.data, - } - ); + `/api/v1/searchspaces/${parsedRequest.data.search_space_id}/invites/${parsedRequest.data.invite_id}`, + updateInviteResponse, + { + body: parsedRequest.data.data, + } + ); }; /** @@ -96,18 +96,18 @@ class InvitesApiService { */ deleteInvite = async (request: DeleteInviteRequest) => { const parsedRequest = deleteInviteRequest.safeParse(request); - + if (!parsedRequest.success) { console.error("Invalid request:", parsedRequest.error); - + const errorMessage = parsedRequest.error.errors.map((err) => err.message).join(", "); throw new ValidationError(`Invalid request: ${errorMessage}`); } return baseApiService.delete( - `/api/v1/searchspaces/${parsedRequest.data.search_space_id}/invites/${parsedRequest.data.invite_id}`, - deleteInviteResponse - ); + `/api/v1/searchspaces/${parsedRequest.data.search_space_id}/invites/${parsedRequest.data.invite_id}`, + deleteInviteResponse + ); }; /** @@ -115,18 +115,18 @@ class InvitesApiService { */ getInviteInfo = async (request: GetInviteInfoRequest) => { const parsedRequest = getInviteInfoRequest.safeParse(request); - + if (!parsedRequest.success) { console.error("Invalid request:", parsedRequest.error); - + const errorMessage = parsedRequest.error.errors.map((err) => err.message).join(", "); throw new ValidationError(`Invalid request: ${errorMessage}`); } return baseApiService.get( - `/api/v1/invites/${parsedRequest.data.invite_code}/info`, - getInviteInfoResponse - ); + `/api/v1/invites/${parsedRequest.data.invite_code}/info`, + getInviteInfoResponse + ); }; /** @@ -134,21 +134,17 @@ class InvitesApiService { */ acceptInvite = async (request: AcceptInviteRequest) => { const parsedRequest = acceptInviteRequest.safeParse(request); - + if (!parsedRequest.success) { console.error("Invalid request:", parsedRequest.error); - + const errorMessage = parsedRequest.error.errors.map((err) => err.message).join(", "); throw new ValidationError(`Invalid request: ${errorMessage}`); } - return baseApiService.post( - `/api/v1/invites/accept`, - acceptInviteResponse, - { - body: parsedRequest.data, - } - ); + return baseApiService.post(`/api/v1/invites/accept`, acceptInviteResponse, { + body: parsedRequest.data, + }); }; } diff --git a/surfsense_web/lib/apis/members-api.service.ts b/surfsense_web/lib/apis/members-api.service.ts index 10bb5da6a..1dc39ad3b 100644 --- a/surfsense_web/lib/apis/members-api.service.ts +++ b/surfsense_web/lib/apis/members-api.service.ts @@ -1,24 +1,24 @@ import { - type GetMembersRequest, - type GetMembersResponse, - type UpdateMembershipRequest, - type UpdateMembershipResponse, type DeleteMembershipRequest, type DeleteMembershipResponse, - type LeaveSearchSpaceRequest, - type LeaveSearchSpaceResponse, + deleteMembershipRequest, + deleteMembershipResponse, + type GetMembersRequest, + type GetMembersResponse, type GetMyAccessRequest, type GetMyAccessResponse, getMembersRequest, getMembersResponse, - updateMembershipRequest, - updateMembershipResponse, - deleteMembershipRequest, - deleteMembershipResponse, - leaveSearchSpaceRequest, - leaveSearchSpaceResponse, getMyAccessRequest, getMyAccessResponse, + type LeaveSearchSpaceRequest, + type LeaveSearchSpaceResponse, + leaveSearchSpaceRequest, + leaveSearchSpaceResponse, + type UpdateMembershipRequest, + type UpdateMembershipResponse, + updateMembershipRequest, + updateMembershipResponse, } from "@/contracts/types/members.types"; import { ValidationError } from "@/lib/error"; import { baseApiService } from "./base-api.service"; @@ -39,7 +39,7 @@ class MembersApiService { return baseApiService.get( `/api/v1/searchspaces/${parsedRequest.data.search_space_id}/members`, - getMembersResponse, + getMembersResponse ); }; @@ -61,7 +61,7 @@ class MembersApiService { updateMembershipResponse, { body: parsedRequest.data.data, - }, + } ); }; @@ -80,7 +80,7 @@ class MembersApiService { return baseApiService.delete( `/api/v1/searchspaces/${parsedRequest.data.search_space_id}/members/${parsedRequest.data.membership_id}`, - deleteMembershipResponse, + deleteMembershipResponse ); }; @@ -99,7 +99,7 @@ class MembersApiService { return baseApiService.delete( `/api/v1/searchspaces/${parsedRequest.data.search_space_id}/members/me`, - leaveSearchSpaceResponse, + leaveSearchSpaceResponse ); }; @@ -118,7 +118,7 @@ class MembersApiService { return baseApiService.get( `/api/v1/searchspaces/${parsedRequest.data.search_space_id}/my-access`, - getMyAccessResponse, + getMyAccessResponse ); }; } diff --git a/surfsense_web/lib/query-client/cache-keys.ts b/surfsense_web/lib/query-client/cache-keys.ts index be7fa13da..a8eecb605 100644 --- a/surfsense_web/lib/query-client/cache-keys.ts +++ b/surfsense_web/lib/query-client/cache-keys.ts @@ -1,10 +1,10 @@ import type { GetChatsRequest } from "@/contracts/types/chat.types"; import type { GetDocumentsRequest } from "@/contracts/types/document.types"; import type { GetLLMConfigsRequest } from "@/contracts/types/llm-config.types"; +import type { GetMembersRequest } from "@/contracts/types/members.types"; import type { GetPodcastsRequest } from "@/contracts/types/podcast.types"; import type { GetRolesRequest } from "@/contracts/types/roles.types"; import type { GetSearchSpacesRequest } from "@/contracts/types/search-space.types"; -import type { GetMembersRequest } from "@/contracts/types/members.types"; export const cacheKeys = { chats: {