Merge pull request 'feat(ui): waiting for necessary queries before dropping clan loader' (#4479) from ui/refine-initial-loading into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4479
This commit is contained in:
@@ -3,7 +3,7 @@ import { A } from "@solidjs/router";
|
||||
import { Accordion } from "@kobalte/core/accordion";
|
||||
import Icon from "../Icon/Icon";
|
||||
import { Typography } from "@/src/components/Typography/Typography";
|
||||
import { For, Suspense } from "solid-js";
|
||||
import { For } from "solid-js";
|
||||
import { MachineStatus } from "@/src/components/MachineStatus/MachineStatus";
|
||||
import { buildMachinePath, useClanURI } from "@/src/hooks/clan";
|
||||
import { useMachinesQuery } from "@/src/queries/queries";
|
||||
@@ -89,21 +89,19 @@ export const SidebarBody = (props: SidebarProps) => {
|
||||
</Accordion.Trigger>
|
||||
</Accordion.Header>
|
||||
<Accordion.Content class="content">
|
||||
<Suspense fallback={"Loading..."}>
|
||||
<nav>
|
||||
<For each={Object.entries(machineList.data || {})}>
|
||||
{([id, machine]) => (
|
||||
<MachineRoute
|
||||
clanURI={clanURI}
|
||||
machineID={id}
|
||||
name={machine.name || id}
|
||||
status="Not Installed"
|
||||
serviceCount={0}
|
||||
/>
|
||||
)}
|
||||
</For>
|
||||
</nav>
|
||||
</Suspense>
|
||||
<nav>
|
||||
<For each={Object.entries(machineList.data || {})}>
|
||||
{([id, machine]) => (
|
||||
<MachineRoute
|
||||
clanURI={clanURI}
|
||||
machineID={id}
|
||||
name={machine.name || id}
|
||||
status="Not Installed"
|
||||
serviceCount={0}
|
||||
/>
|
||||
)}
|
||||
</For>
|
||||
</nav>
|
||||
</Accordion.Content>
|
||||
</Accordion.Item>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { DropdownMenu } from "@kobalte/core/dropdown-menu";
|
||||
import { useNavigate } from "@solidjs/router";
|
||||
import { Typography } from "../Typography/Typography";
|
||||
import { createSignal, For, Suspense } from "solid-js";
|
||||
import { useAllClanDetailsQuery } from "@/src/queries/queries";
|
||||
import { useClanListQuery } from "@/src/queries/queries";
|
||||
import { navigateToClan, useClanURI } from "@/src/hooks/clan";
|
||||
import { clanURIs } from "@/src/stores/clan";
|
||||
|
||||
@@ -15,7 +15,7 @@ export const SidebarHeader = () => {
|
||||
|
||||
// get information about the current active clan
|
||||
const clanURI = useClanURI();
|
||||
const allClans = useAllClanDetailsQuery(clanURIs());
|
||||
const allClans = useClanListQuery(clanURIs());
|
||||
|
||||
const activeClan = () => allClans.find(({ data }) => data?.uri === clanURI);
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ export const callApi = <K extends OperationNames>(
|
||||
|
||||
const op_key = backendOpts?.op_key ?? crypto.randomUUID();
|
||||
|
||||
let req: BackendSendType<OperationNames> = {
|
||||
const req: BackendSendType<OperationNames> = {
|
||||
body: args,
|
||||
header: {
|
||||
...backendOpts,
|
||||
|
||||
@@ -3,8 +3,12 @@ import { callApi, SuccessData } from "../hooks/api";
|
||||
import { encodeBase64 } from "@/src/hooks/clan";
|
||||
|
||||
export type ClanDetails = SuccessData<"get_clan_details">;
|
||||
export type ClanDetailsWithURI = ClanDetails & { uri: string };
|
||||
|
||||
export type ListMachines = SuccessData<"list_machines">;
|
||||
|
||||
export type MachinesQueryResult = UseQueryResult<ListMachines>;
|
||||
export type ClanListQueryResult = UseQueryResult<ClanDetailsWithURI>[];
|
||||
|
||||
export const useMachinesQuery = (clanURI: string) =>
|
||||
useQuery<ListMachines>(() => ({
|
||||
@@ -48,7 +52,7 @@ export const useClanDetailsQuery = (clanURI: string) =>
|
||||
},
|
||||
}));
|
||||
|
||||
export const useAllClanDetailsQuery = (clanURIs: string[]) =>
|
||||
export const useClanListQuery = (clanURIs: string[]): ClanListQueryResult =>
|
||||
useQueries(() => ({
|
||||
queries: clanURIs.map((clanURI) => ({
|
||||
queryKey: ["clans", encodeBase64(clanURI), "details"],
|
||||
|
||||
@@ -15,9 +15,14 @@ import {
|
||||
useClanURI,
|
||||
} from "@/src/hooks/clan";
|
||||
import { CubeScene } from "@/src/scene/cubes";
|
||||
import { MachinesQueryResult, useMachinesQuery } from "@/src/queries/queries";
|
||||
import {
|
||||
ClanListQueryResult,
|
||||
MachinesQueryResult,
|
||||
useClanListQuery,
|
||||
useMachinesQuery,
|
||||
} from "@/src/queries/queries";
|
||||
import { callApi } from "@/src/hooks/api";
|
||||
import { store, setStore } from "@/src/stores/clan";
|
||||
import { store, setStore, clanURIs } from "@/src/stores/clan";
|
||||
import { produce } from "solid-js/store";
|
||||
import { Button } from "@/src/components/Button/Button";
|
||||
import { Splash } from "@/src/scene/splash";
|
||||
@@ -42,10 +47,12 @@ export const Clan: Component<RouteSectionProps> = (props) => {
|
||||
interface CreateFormValues extends FieldValues {
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface MockProps {
|
||||
onClose: () => void;
|
||||
onSubmit: (formValues: CreateFormValues) => void;
|
||||
}
|
||||
|
||||
const MockCreateMachine = (props: MockProps) => {
|
||||
let container: Node;
|
||||
|
||||
@@ -173,7 +180,26 @@ const ClanSceneController = (props: RouteSectionProps) => {
|
||||
|
||||
return (
|
||||
<SceneDataProvider clanURI={clanURI}>
|
||||
{({ query }) => {
|
||||
{({ clansQuery, machinesQuery }) => {
|
||||
// a combination of the individual clan details query status and the machines query status
|
||||
// the cube scene needs the machines query, the sidebar needs the clans query and machines query results
|
||||
// so we wait on both before removing the loader to avoid any loading artefacts
|
||||
const isLoading = (): boolean => {
|
||||
// check the machines query first
|
||||
if (machinesQuery.isLoading) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// otherwise iterate the clans query and return early if we find a queries that is still loading
|
||||
for (const query of clansQuery) {
|
||||
if (query.isLoading) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Show when={showModal()}>
|
||||
@@ -217,7 +243,7 @@ const ClanSceneController = (props: RouteSectionProps) => {
|
||||
ghost
|
||||
onClick={() => {
|
||||
console.log("Refetching API");
|
||||
query.refetch();
|
||||
machinesQuery.refetch();
|
||||
}}
|
||||
>
|
||||
Refetch API
|
||||
@@ -225,7 +251,9 @@ const ClanSceneController = (props: RouteSectionProps) => {
|
||||
</div>
|
||||
{/* TODO: Add minimal display time */}
|
||||
<div
|
||||
class={cx({ "fade-out": !query.isLoading && loadingCooldown() })}
|
||||
class={cx({
|
||||
"fade-out": !machinesQuery.isLoading && loadingCooldown(),
|
||||
})}
|
||||
>
|
||||
<Splash />
|
||||
</div>
|
||||
@@ -233,8 +261,8 @@ const ClanSceneController = (props: RouteSectionProps) => {
|
||||
<CubeScene
|
||||
selectedIds={selectedIds}
|
||||
onSelect={onMachineSelect}
|
||||
isLoading={query.isLoading}
|
||||
cubesQuery={query}
|
||||
isLoading={isLoading()}
|
||||
cubesQuery={machinesQuery}
|
||||
onCreate={onCreate}
|
||||
sceneStore={() => {
|
||||
const clanURI = useClanURI();
|
||||
@@ -268,10 +296,14 @@ const ClanSceneController = (props: RouteSectionProps) => {
|
||||
|
||||
const SceneDataProvider = (props: {
|
||||
clanURI: string;
|
||||
children: (sceneData: { query: MachinesQueryResult }) => JSX.Element;
|
||||
children: (sceneData: {
|
||||
clansQuery: ClanListQueryResult;
|
||||
machinesQuery: MachinesQueryResult;
|
||||
}) => JSX.Element;
|
||||
}) => {
|
||||
const clansQuery = useClanListQuery(clanURIs());
|
||||
const machinesQuery = useMachinesQuery(props.clanURI);
|
||||
|
||||
// This component can be used to provide scene data or context if needed
|
||||
return props.children({ query: machinesQuery });
|
||||
return props.children({ clansQuery, machinesQuery });
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user