Skip to content

Commit

Permalink
Bug fixes for Query Performance Toast (#5048)
Browse files Browse the repository at this point in the history
  • Loading branch information
CamronStaley authored Nov 6, 2024
1 parent e5f51f7 commit 4e4bb1a
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ const NumericFieldFilter = ({ color, modal, named = true, path }: Props) => {
const [showRange, setShowRange] = React.useState(!isGroup);
const field = fos.useAssertedRecoilValue(fos.field(path));
const queryPerformance = useRecoilValue(fos.queryPerformance);
const hasBounds = useRecoilValue(state.hasBounds({ path, modal }));
const hasBounds = useRecoilValue(
state.hasBounds({ path, modal, shouldCalculate: !queryPerformance })
);

if (!queryPerformance && named && !hasBounds) {
return null;
Expand Down Expand Up @@ -87,6 +89,7 @@ const NumericFieldFilter = ({ color, modal, named = true, path }: Props) => {
color: theme.text.secondary,
borderRadius: "8px",
border: "1px solid " + theme.secondary.main,
height: "30px",
}}
>
Filter by {name}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ export const FLOAT_NONFINITES: Nonfinite[] = ["inf", "ninf", "nan"];
export const hasBounds = selectorFamily({
key: "hasBounds",
get:
(params: { path: string; modal: boolean }) =>
(params: { path: string; modal: boolean; shouldCalculate: boolean }) =>
({ get }) => {
return Boolean(get(boundsAtom(params))?.every((b) => b !== null));
const shouldCalculate = params.shouldCalculate ?? true;
return shouldCalculate
? Boolean(get(boundsAtom(params))?.every((b) => b !== null))
: Boolean(false);
},
});

Expand Down
38 changes: 29 additions & 9 deletions app/packages/core/src/components/QueryPerformanceToast.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,50 @@
import { Toast } from "@fiftyone/components";
import { QP_MODE } from "@fiftyone/core";
import { QP_MODE, QP_MODE_SUMMARY } from "@fiftyone/core";
import { getBrowserStorageEffectForKey } from "@fiftyone/state";
import { Box, Button, Typography } from "@mui/material";
import { Bolt } from "@mui/icons-material";
import React, { useEffect, useState } from "react";
import { createPortal } from "react-dom";
import { atom, useRecoilState } from "recoil";
import { atom, useRecoilState, useRecoilValue } from "recoil";
import { useTheme } from "@fiftyone/components";
import * as atoms from "@fiftyone/state/src/recoil/atoms";
import * as fos from "@fiftyone/state";

const SHOWN_FOR = 5000;
const SHOWN_FOR = 10000;

const hideQueryPerformanceToast = atom({
key: "hideQueryPerformanceToast",
default: false,
effects: [
getBrowserStorageEffectForKey("hideQueryPerformanceToast", {
valueClass: "boolean",
sessionStorage: true,
}),
],
});

const QueryPerformanceToast = ({
onClick = () => window.open(QP_MODE, "_blank")?.focus(),
onClick = (isFrameFilter: boolean) => {
const link = isFrameFilter ? QP_MODE_SUMMARY : QP_MODE;
window.open(link, "_blank")?.focus();
},
onDispatch = (event) => {
console.debug(event);
},
text = "View Documentation",
}) => {
const [path, setPath] = useState("");
const indexed = useRecoilValue(fos.pathHasIndexes(path));
const [shown, setShown] = useState(false);
const [disabled, setDisabled] = useRecoilState(hideQueryPerformanceToast);
const element = document.getElementById("queryPerformance");
const theme = useTheme();
const frameFields = useRecoilValue(atoms.frameFields);

useEffect(() => {
const listen = (event) => {
onDispatch(event);
setPath(event.path);
setShown(true);
};
window.addEventListener("queryperformance", listen);
Expand All @@ -48,6 +59,11 @@ const QueryPerformanceToast = ({
return null;
}

// don't show the toast if the path is already indexed
if (path && indexed) {
return null;
}

return createPortal(
<Toast
duration={SHOWN_FOR}
Expand All @@ -57,14 +73,18 @@ const QueryPerformanceToast = ({
horizontal: "center",
backgroundColor: theme.custom.toastBackgroundColor,
}}
primary={(setOpen) => {
primary={() => {
return (
<Button
variant="contained"
size="small"
onClick={() => {
onClick();
setOpen(false);
onClick(
frameFields.some((frame) =>
path.includes(`frames.${frame.path}`)
)
);
setShown(false);
}}
sx={{
marginLeft: "auto",
Expand All @@ -77,7 +97,7 @@ const QueryPerformanceToast = ({
</Button>
);
}}
secondary={(setOpen) => {
secondary={() => {
return (
<div>
<Button
Expand All @@ -87,7 +107,7 @@ const QueryPerformanceToast = ({
size="small"
onClick={() => {
setDisabled(true);
setOpen(false);
setShown(false);
}}
style={{ marginLeft: "auto", color: theme.text.secondary }} // Right align the button
>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,51 +1,9 @@
import * as fos from "@fiftyone/state";
import { count, pathColor } from "@fiftyone/state";
import React, { Suspense, useEffect } from "react";
import { pathColor } from "@fiftyone/state";
import React from "react";
import { useRecoilValue } from "recoil";
import FilterItem from "./FilterItem";
import useFilterData from "./useFilterData";

const LABEL_TAGS = "_label_tags";
const TIMEOUT = 5000;

class QueryPerformanceToast extends Event {
path?: string;
constructor(path?: string) {
super("queryperformance");
this.path = path;
}
}

const QueryPerformanceDispatcher = ({ path }: { path: string }) => {
useEffect(() => {
const timeout = setTimeout(() => {
window.dispatchEvent(new QueryPerformanceToast(path));
}, TIMEOUT);

return () => clearTimeout(timeout);
}, [path]);
return null;
};

const QueryPerformanceSubscriber = ({ path }: { path: string }) => {
useRecoilValue(count({ extended: false, modal: false, path }));
return null;
};

const QueryPerformance = ({ path }: { path: string }) => {
const queryPerformance = useRecoilValue(fos.queryPerformance);

if (queryPerformance || path === LABEL_TAGS || !path) {
return null;
}

return (
<Suspense fallback={<QueryPerformanceDispatcher path={path} />}>
<QueryPerformanceSubscriber path={path} />
</Suspense>
);
};

const FilterablePathEntries = ({
modal,
path,
Expand All @@ -61,12 +19,9 @@ const FilterablePathEntries = ({

return (
<>
{!modal && <QueryPerformance path={path} />}
<>
{data.map(({ color: _, ...props }) => (
<FilterItem key={props.path} color={color} {...events} {...props} />
))}
</>
{data.map(({ color: _, ...props }) => (
<FilterItem key={props.path} color={color} {...events} {...props} />
))}
</>
);
};
Expand Down
3 changes: 3 additions & 0 deletions app/packages/core/src/utils/links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ export const FRAME_FILTERING_DISABLED =
export const QP_MODE =
"https://docs.voxel51.com/user_guide/app.html#query-performance";

export const QP_MODE_SUMMARY =
"https://docs.voxel51.com/user_guide/using_datasets.html#summary-fields";

export const NAME_COLORSCALE = "https://plotly.com/python/colorscales/";

export const OBJECT_PATCHES =
Expand Down
41 changes: 39 additions & 2 deletions app/packages/utilities/src/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ export interface FetchFunction {
): Promise<R>;
}

class QueryPerformanceToast extends Event {
path?: string;
constructor(path?: string) {
super("queryperformance");
this.path = path;
}
}

const TIMEOUT = 5000;

export const getFetchFunction = () => {
return fetchFunctionSingleton;
};
Expand Down Expand Up @@ -122,16 +132,28 @@ export const setFetchFunction = (
})
: fetch;

let timeoutId = undefined;
const filterPath = getFirstFilterPath(body);
if (filterPath) {
timeoutId = setTimeout(() => {
window.dispatchEvent(new QueryPerformanceToast(filterPath));
}, TIMEOUT);
}

const response = await fetchCall(url, {
method: method,
cache: "no-cache",
headers,
mode: "cors",
body: body ? JSON.stringify(body) : null,
signal: controller.signal,
referrerPolicy: 'same-origin',
referrerPolicy: "same-origin",
});

if (timeoutId) {
clearTimeout(timeoutId);
}

if (response.status >= 400) {
const errorMetadata = {
code: response.status,
Expand Down Expand Up @@ -272,7 +294,7 @@ export const getEventSource = (
method: "POST",
signal,
body: JSON.stringify(body),
referrerPolicy: 'same-origin',
referrerPolicy: "same-origin",
async onopen(response) {
if (response.ok) {
events.onopen && events.onopen();
Expand Down Expand Up @@ -408,3 +430,18 @@ const pollingEventSource = (
);
});
};

const getFirstFilterPath = (requestBody: any) => {
if (requestBody && requestBody.query) {
if (requestBody.query.includes("paginateSamplesQuery")) {
const pathsArray = requestBody?.variables?.filters;
const paths = pathsArray ? Object.keys(pathsArray) : [];
return paths.length > 0 ? paths[0] : undefined;
}
if (requestBody.query.includes("lightningQuery")) {
const paths = requestBody?.variables?.input?.paths;
return paths && paths.length > 0 ? paths[0].path : undefined;
}
}
return undefined;
};

0 comments on commit 4e4bb1a

Please sign in to comment.