Files
OpenPipe-llm/app/src/utils/hooks.ts
2023-08-12 00:03:06 -07:00

188 lines
5.0 KiB
TypeScript

import { useRouter } from "next/router";
import { type RefObject, useCallback, useEffect, useRef, useState } from "react";
import { api } from "~/utils/api";
import { NumberParam, useQueryParams } from "use-query-params";
import { useAppStore } from "~/state/store";
export const useExperiments = () => {
const selectedProjectId = useAppStore((state) => state.selectedProjectId);
return api.experiments.list.useQuery(
{ projectId: selectedProjectId ?? "" },
{ enabled: !!selectedProjectId },
);
};
export const useExperiment = () => {
const router = useRouter();
const experiment = api.experiments.get.useQuery(
{ id: router.query.id as string },
{ enabled: !!router.query.id },
);
return experiment;
};
export const useExperimentAccess = () => {
return useExperiment().data?.access ?? { canView: false, canModify: false };
};
export const useDatasets = () => {
const selectedProjectId = useAppStore((state) => state.selectedProjectId);
return api.datasets.list.useQuery(
{ projectId: selectedProjectId ?? "" },
{ enabled: !!selectedProjectId },
);
};
export const useDataset = () => {
const router = useRouter();
const dataset = api.datasets.get.useQuery(
{ id: router.query.id as string },
{ enabled: !!router.query.id },
);
return dataset;
};
export const useDatasetEntries = () => {
const dataset = useDataset();
const { page, pageSize } = usePageParams();
return api.datasetEntries.list.useQuery(
{ datasetId: dataset.data?.id ?? "", page, pageSize },
{ enabled: dataset.data?.id != null },
);
};
type AsyncFunction<T extends unknown[], U> = (...args: T) => Promise<U>;
export function useHandledAsyncCallback<T extends unknown[], U>(
callback: AsyncFunction<T, U>,
deps: React.DependencyList,
) {
const [loading, setLoading] = useState(0);
const [error, setError] = useState<Error | null>(null);
const wrappedCallback = useCallback((...args: T) => {
setLoading((loading) => loading + 1);
setError(null);
callback(...args)
.catch((error) => {
setError(error as Error);
console.error(error);
})
.finally(() => {
setLoading((loading) => loading - 1);
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, deps);
return [wrappedCallback, loading > 0, error] as const;
}
// Have to do this ugly thing to convince Next not to try to access `navigator`
// on the server side at build time, when it isn't defined.
export const useModifierKeyLabel = () => {
const [label, setLabel] = useState("");
useEffect(() => {
setLabel(navigator?.platform?.startsWith("Mac") ? "⌘" : "Ctrl");
}, []);
return label;
};
interface Dimensions {
left: number;
top: number;
right: number;
bottom: number;
width: number;
height: number;
x: number;
y: number;
}
// get dimensions of an element
export const useElementDimensions = (): [RefObject<HTMLElement>, Dimensions | undefined] => {
const ref = useRef<HTMLElement>(null);
const [dimensions, setDimensions] = useState<Dimensions | undefined>();
useEffect(() => {
if (ref.current) {
const observer = new ResizeObserver((entries) => {
entries.forEach((entry) => {
setDimensions(entry.contentRect);
});
});
const observedRef = ref.current;
observer.observe(observedRef);
// Cleanup the observer on component unmount
return () => {
if (observedRef) {
observer.unobserve(observedRef);
}
};
}
}, []);
return [ref, dimensions];
};
export const usePageParams = () => {
const [pageParams, setPageParams] = useQueryParams({
page: NumberParam,
pageSize: NumberParam,
});
const { page, pageSize } = pageParams;
return { page: page || 1, pageSize: pageSize || 10, setPageParams };
};
export const useScenarios = () => {
const experiment = useExperiment();
const { page, pageSize } = usePageParams();
return api.scenarios.list.useQuery(
{ experimentId: experiment.data?.id ?? "", page, pageSize },
{ enabled: experiment.data?.id != null },
);
};
export const useScenario = (scenarioId: string) => {
return api.scenarios.get.useQuery({ id: scenarioId });
};
export const useVisibleScenarioIds = () => useScenarios().data?.scenarios.map((s) => s.id) ?? [];
export const useSelectedProject = () => {
const selectedProjectId = useAppStore((state) => state.selectedProjectId);
return api.projects.get.useQuery(
{ id: selectedProjectId ?? "" },
{ enabled: !!selectedProjectId },
);
};
export const useScenarioVars = () => {
const experiment = useExperiment();
return api.scenarioVars.list.useQuery(
{ experimentId: experiment.data?.id ?? "" },
{ enabled: experiment.data?.id != null },
);
};
export const useLoggedCalls = () => {
const selectedProjectId = useAppStore((state) => state.selectedProjectId);
const { page, pageSize } = usePageParams();
return api.loggedCalls.list.useQuery(
{ projectId: selectedProjectId ?? "", page, pageSize },
{ enabled: !!selectedProjectId },
);
};