diff --git a/app/client/functions/get-origin.ts b/app/client/functions/get-origin.ts index c14a7aa5..cdc7f56b 100644 --- a/app/client/functions/get-origin.ts +++ b/app/client/functions/get-origin.ts @@ -1,6 +1,6 @@ -import { createIsomorphicFn } from "@tanstack/react-start"; +import { createServerFn } from "@tanstack/react-start"; import { config } from "~/server/core/config"; -export const getOrigin = createIsomorphicFn() - .server(() => config.baseUrl) - .client(() => window.location.origin); +export const getOrigin = createServerFn().handler(() => { + return config.baseUrl; +}); diff --git a/app/client/modules/settings/components/org-members-section.tsx b/app/client/modules/settings/components/org-members-section.tsx index 7eaa4bf7..35f09b69 100644 --- a/app/client/modules/settings/components/org-members-section.tsx +++ b/app/client/modules/settings/components/org-members-section.tsx @@ -2,6 +2,7 @@ import { useMutation, useSuspenseQuery } from "@tanstack/react-query"; import { Shield, ShieldAlert, Trash2 } from "lucide-react"; import { useState } from "react"; import { toast } from "sonner"; +import type { GetOrgMembersResponse } from "~/client/api-client"; import { getOrgMembersOptions, removeOrgMemberMutation, @@ -24,13 +25,17 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "~ import { useOrganizationContext } from "~/client/hooks/use-org-context"; import { cn } from "~/client/lib/utils"; -export function OrgMembersSection() { +type OrgMembersSectionProps = { + initialMembers: GetOrgMembersResponse; +}; + +export function OrgMembersSection({ initialMembers }: OrgMembersSectionProps) { const { activeMember } = useOrganizationContext(); const [memberToRemove, setMemberToRemove] = useState<{ id: string; name: string } | null>(null); - const orgMembersQuery = useSuspenseQuery({ - ...getOrgMembersOptions(), - }); + const { + data: { members }, + } = useSuspenseQuery({ ...getOrgMembersOptions(), initialData: initialMembers }); const updateRole = useMutation({ ...updateMemberRoleMutation(), @@ -53,8 +58,6 @@ export function OrgMembersSection() { }, }); - const members = orgMembersQuery.data.members; - return (
diff --git a/app/client/modules/settings/components/sso/sso-settings-section.tsx b/app/client/modules/settings/components/sso/sso-settings-section.tsx index d9f417fe..fc21100f 100644 --- a/app/client/modules/settings/components/sso/sso-settings-section.tsx +++ b/app/client/modules/settings/components/sso/sso-settings-section.tsx @@ -32,19 +32,25 @@ import { formatDateWithMonth } from "~/client/lib/datetime"; import { getOrigin } from "~/client/functions/get-origin"; import { authClient } from "~/client/lib/auth-client"; import { cn } from "~/client/lib/utils"; +import { useServerFn } from "@tanstack/react-start"; +import type { GetSsoSettingsResponse } from "~/client/api-client"; type InvitationRole = "member" | "admin" | "owner"; -export function SsoSettingsSection() { - const origin = getOrigin(); +type SsoSettingsSectionProps = { + initialSettings: GetSsoSettingsResponse; +}; + +export function SsoSettingsSection({ initialSettings }: SsoSettingsSectionProps) { + const originQuery = useServerFn(getOrigin); + const { data } = useSuspenseQuery({ queryKey: ["app-origin"], queryFn: originQuery }); + const navigate = useNavigate(); const { activeOrganization } = useOrganizationContext(); const [inviteEmail, setInviteEmail] = useState(""); const [inviteRole, setInviteRole] = useState("member"); - const ssoSettingsQuery = useSuspenseQuery({ - ...getSsoSettingsOptions(), - }); + const ssoSettingsQuery = useSuspenseQuery({ ...getSsoSettingsOptions(), initialData: initialSettings }); const updateProviderAutoLinkingMutation = useMutation({ ...updateSsoProviderAutoLinkingMutation(), @@ -195,7 +201,7 @@ export function SsoSettingsSection() { e.currentTarget.select()} /> diff --git a/app/client/modules/settings/routes/settings.tsx b/app/client/modules/settings/routes/settings.tsx index b6b2835f..807afdf3 100644 --- a/app/client/modules/settings/routes/settings.tsx +++ b/app/client/modules/settings/routes/settings.tsx @@ -24,12 +24,15 @@ import { useNavigate, useSearch } from "@tanstack/react-router"; import { SsoSettingsSection } from "../components/sso/sso-settings-section"; import { OrgMembersSection } from "../components/org-members-section"; import { useOrganizationContext } from "~/client/hooks/use-org-context"; +import type { GetOrgMembersResponse, GetSsoSettingsResponse } from "~/client/api-client"; type Props = { appContext: AppContext; + initialMembers: GetOrgMembersResponse; + initialSsoSettings: GetSsoSettingsResponse; }; -export function SettingsPage({ appContext }: Props) { +export function SettingsPage({ appContext, initialMembers, initialSsoSettings }: Props) { const [currentPassword, setCurrentPassword] = useState(""); const [newPassword, setNewPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState(""); @@ -296,7 +299,7 @@ export function SettingsPage({ appContext }: Props) { Manage organization members and roles
- + @@ -309,7 +312,7 @@ export function SettingsPage({ appContext }: Props) { Configure OIDC provider settings
- + diff --git a/app/client/modules/volumes/routes/volumes.tsx b/app/client/modules/volumes/routes/volumes.tsx index ba2f10af..3db76de7 100644 --- a/app/client/modules/volumes/routes/volumes.tsx +++ b/app/client/modules/volumes/routes/volumes.tsx @@ -12,6 +12,7 @@ import { VolumeIcon } from "~/client/components/volume-icon"; import { listVolumesOptions } from "~/client/api-client/@tanstack/react-query.gen"; import type { VolumeStatus } from "~/client/lib/types"; import { useNavigate } from "@tanstack/react-router"; +import { cn } from "~/client/lib/utils"; const getVolumeStatusVariant = (status: VolumeStatus): "success" | "neutral" | "error" | "warning" => { const statusMap = { @@ -119,38 +120,35 @@ export function VolumesPage() { - {hasNoFilteredVolumes ? ( - - -
-

No volumes match your filters.

- -
+ + +
+

No volumes match your filters.

+ +
+
+
+ {filteredVolumes.map((volume) => ( + navigate({ to: `/volumes/${volume.shortId}` })} + > + {volume.name} + + + + + - ) : ( - filteredVolumes.map((volume) => ( - navigate({ to: `/volumes/${volume.shortId}` })} - > - {volume.name} - - - - - - - - )) - )} + ))}
diff --git a/app/routes/(dashboard)/admin/index.tsx b/app/routes/(dashboard)/admin/index.tsx index a44aca04..17c78f53 100644 --- a/app/routes/(dashboard)/admin/index.tsx +++ b/app/routes/(dashboard)/admin/index.tsx @@ -3,7 +3,7 @@ import { type } from "arktype"; import { fetchUser } from "../route"; import type { AppContext } from "~/context"; import { AdminPage } from "~/client/modules/admin/routes/admin-page"; -import { getAdminUsersOptions } from "~/client/api-client/@tanstack/react-query.gen"; +import { getAdminUsersOptions, getRegistrationStatusOptions } from "~/client/api-client/@tanstack/react-query.gen"; export const Route = createFileRoute("/(dashboard)/admin/")({ validateSearch: type({ tab: "string?" }), @@ -15,7 +15,10 @@ export const Route = createFileRoute("/(dashboard)/admin/")({ throw redirect({ to: "/settings" }); } - await context.queryClient.ensureQueryData(getAdminUsersOptions()); + await Promise.all([ + context.queryClient.ensureQueryData({ ...getAdminUsersOptions() }), + context.queryClient.ensureQueryData({ ...getRegistrationStatusOptions() }), + ]); return authContext as AppContext; }, diff --git a/app/routes/(dashboard)/route.tsx b/app/routes/(dashboard)/route.tsx index c9116306..1b4e9ab4 100644 --- a/app/routes/(dashboard)/route.tsx +++ b/app/routes/(dashboard)/route.tsx @@ -5,6 +5,7 @@ import { Layout } from "~/client/components/layout"; import { SIDEBAR_COOKIE_NAME } from "~/client/components/ui/sidebar"; import { authMiddleware } from "~/middleware/auth"; import { auth } from "~/server/lib/auth"; +import { getOrganizationContext } from "~/server/lib/functions/organization-context"; import { authService } from "~/server/modules/auth/auth.service"; export const fetchUser = createServerFn({ method: "GET" }).handler(async () => { @@ -24,8 +25,15 @@ export const Route = createFileRoute("/(dashboard)")({ server: { middleware: [authMiddleware], }, - loader: async () => { - const authContext = await fetchUser(); + loader: async ({ context }) => { + const [authContext] = await Promise.all([ + fetchUser(), + context.queryClient.ensureQueryData({ + queryKey: ["organization-context"], + queryFn: () => getOrganizationContext(), + }), + ]); + return authContext; }, }); diff --git a/app/routes/(dashboard)/settings/index.tsx b/app/routes/(dashboard)/settings/index.tsx index b76fc716..7d3b7d74 100644 --- a/app/routes/(dashboard)/settings/index.tsx +++ b/app/routes/(dashboard)/settings/index.tsx @@ -3,13 +3,21 @@ import { fetchUser } from "../route"; import type { AppContext } from "~/context"; import { SettingsPage } from "~/client/modules/settings/routes/settings"; import { type } from "arktype"; +import { getOrgMembersOptions, getSsoSettingsOptions } from "~/client/api-client/@tanstack/react-query.gen"; +import { getOrigin } from "~/client/functions/get-origin"; export const Route = createFileRoute("/(dashboard)/settings/")({ component: RouteComponent, validateSearch: type({ tab: "string?" }), - loader: async () => { - const authContext = await fetchUser(); - return authContext as AppContext; + loader: async ({ context }) => { + const [authContext, org, members] = await Promise.all([ + fetchUser(), + context.queryClient.ensureQueryData({ ...getSsoSettingsOptions() }), + context.queryClient.ensureQueryData({ ...getOrgMembersOptions() }), + context.queryClient.ensureQueryData({ queryKey: ["app-origin"], queryFn: () => getOrigin() }), + ]); + + return { authContext: authContext as AppContext, org, members }; }, staticData: { breadcrumb: () => [{ label: "Settings" }], @@ -17,6 +25,7 @@ export const Route = createFileRoute("/(dashboard)/settings/")({ }); function RouteComponent() { - const appContext = Route.useLoaderData(); - return ; + const { authContext, org, members } = Route.useLoaderData(); + + return ; }