Skip to content

Commit

Permalink
prepare to create Data Explorer 2 UI package (#162)
Browse files Browse the repository at this point in the history
With the goal of extracting the entire DE2 UI into a shared module, this does a little prep work. Specifically, all the non-standard (i.e. Breadbox incompatible) API calls have been abstracted into a React context that is provided by the new DeprecatedDataExplorerApiProvider.

This will make it easy to identify all the places where a deprecated endpoint is being relied upon. We can then incrementally update everything to leverage Breadbox APIs instead.
  • Loading branch information
rcreasi authored Jan 8, 2025
1 parent 99474b7 commit 86537a2
Show file tree
Hide file tree
Showing 72 changed files with 1,236 additions and 1,051 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React, { useCallback, useEffect, useState } from "react";
import {
ContextSelector,
fetchContextLabels,
fetchContext,
isNegatedContext,
isV2Context,
negateContext,
persistLegacyListAsContext,
PlotConfigSelect,
useDeprecatedDataExplorerApi,
} from "@depmap/data-explorer-2";
import { DepMap, enabledFeatures } from "@depmap/globals";
import { DataExplorerContext } from "@depmap/types";
Expand Down Expand Up @@ -41,6 +41,7 @@ const ContextEnabledDropdown = ({
defaultNone: boolean;
onListSelect: LegacyCellLineListsDropdownProps["onListSelect"];
}) => {
const api = useDeprecatedDataExplorerApi();
const [isLoading, setIsLoading] = useState(!defaultNone);
const [value, setValue] = useState<DataExplorerContext | null>(null);

Expand All @@ -54,7 +55,7 @@ const ContextEnabledDropdown = ({
}

if (context && hash) {
const labels = await fetchContextLabels(context);
const labels = await api.evaluateLegacyContext(context);

onListSelect({
name: context.name,
Expand All @@ -65,7 +66,7 @@ const ContextEnabledDropdown = ({
onListSelect({ name: "", lines: new Set() });
}
},
[defaultNone, onListSelect]
[api, defaultNone, onListSelect]
);

useEffect(() => {
Expand All @@ -78,7 +79,10 @@ const ContextEnabledDropdown = ({
const selectedContextHash = getSelectedContextHash();

if (selectedList && selectedList !== "None") {
const [hash, context] = await persistLegacyListAsContext(selectedList);
const [hash, context] = await persistLegacyListAsContext(
api,
selectedList
);
setSelectedCellLineListName("None");
handleChange(context, hash);
}
Expand All @@ -105,7 +109,7 @@ const ContextEnabledDropdown = ({

setIsLoading(false);
})();
}, [value, defaultNone, handleChange]);
}, [api, value, defaultNone, handleChange]);

const handleClickCreateContext = () => {
DepMap.saveNewContext({ context_type: "depmap_model" }, null, handleChange);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,20 @@ import {
DatasetMetadataSelector,
DimensionSelect,
PlotConfigSelect,
useDeprecatedDataExplorerApi,
} from "@depmap/data-explorer-2";
import styles from "../styles/cell_line_selector.scss";

interface Props {
onChange: (
sliceId: string | null,
valueType: "continuous" | "categorical"
valueType: "continuous" | "categorical",
api: ReturnType<typeof useDeprecatedDataExplorerApi>
) => void;
}

function DataColumnSelect({ onChange }: Props) {
const api = useDeprecatedDataExplorerApi();
const [valueType, setValueType] = useState<
"continuous" | "categorical" | null
>(null);
Expand All @@ -29,7 +32,7 @@ function DataColumnSelect({ onChange }: Props) {
value={valueType}
onChange={(nextValueType) => {
setValueType(nextValueType as "continuous" | "categorical");
onChange(null, nextValueType as "continuous" | "categorical");
onChange(null, nextValueType as "continuous" | "categorical", api);
setValue(null);
}}
options={{
Expand All @@ -46,7 +49,7 @@ function DataColumnSelect({ onChange }: Props) {
value={null}
onChange={(dimension) => {
const sliceId = convertDimensionToSliceId(dimension);
onChange(sliceId, valueType);
onChange(sliceId, valueType, api);
}}
/>
)}
Expand All @@ -63,9 +66,9 @@ function DataColumnSelect({ onChange }: Props) {
partialOrCompleteSliceId &&
partialOrCompleteSliceId.split("/").length === 4
) {
onChange(partialOrCompleteSliceId, valueType);
onChange(partialOrCompleteSliceId, valueType, api);
} else {
onChange(null, valueType);
onChange(null, valueType, api);
}
}}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* eslint-disable */
import * as React from "react";
import { fetchMetadataColumn } from "@depmap/data-explorer-2";
import { Link } from "@depmap/interactive";
import { Button } from "react-bootstrap";
import { CellData } from "../models/cellLines";
Expand Down Expand Up @@ -206,14 +205,14 @@ export class LongTableCellLineSelector extends React.Component<
<strong>Add a data column</strong>
<br />
<DataColumnSelect
onChange={(sliceId, valueType) => {
onChange={(sliceId, valueType, api) => {
if (!sliceId) {
this.setState({
vector: undefined,
vectorId: undefined,
});
} else {
fetchMetadataColumn(sliceId).then((metadataColumn) => {
api.fetchMetadataColumn(sliceId).then((metadataColumn) => {
this.setState({
vector: {
cellLines: Object.keys(metadataColumn.indexed_values),
Expand Down
36 changes: 8 additions & 28 deletions frontend/packages/@depmap/data-explorer-2/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,17 @@ export { default as ContextBuilderModal } from "./src/components/ContextBuilder/
export { default as ContextManager } from "./src/components/ContextManager";
export { default as DatasetMetadataSelector } from "./src/components/DatasetMetadataSelector";

export {
fetchAnalysisResult,
fetchAssociations,
fetchContext,
fetchContextLabels,
fetchCorrelation,
fetchDatasetDetails,
fetchDatasetsByIndexType,
fetchDatasetsMatchingContextIncludingEntities,
fetchDimensionLabels,
fetchDimensionLabelsOfDataset,
fetchDimensionLabelsToDatasetsMapping,
fetchGeneTeaEnrichment,
fetchGeneTeaTermContext,
fetchLinearRegression,
fetchMetadataColumn,
fetchMetadataSlices,
fetchPlotDimensions,
fetchWaterfall,
persistContext,
} from "./src/api";

export type {
GeneTeaEnrichedTerms,
GeneTeaTermContext,
MetadataSlices,
} from "./src/api";

export {
DataExplorerApiProvider,
useDataExplorerApi,
} from "./src/contexts/DataExplorerApiContext";

export {
DeprecatedDataExplorerApiProvider,
DeprecatedDataExplorerApiResponse,
useDeprecatedDataExplorerApi,
} from "./src/contexts/DeprecatedDataExplorerApiContext";

export {
DataExplorerSettingsProvider,
useDataExplorerSettings,
Expand All @@ -58,6 +36,8 @@ export {
saveContextToLocalStorageAndPersist,
} from "./src/utils/context";

export { fetchContext, persistContext } from "./src/utils/context-storage";

export {
capitalize,
convertDimensionToSliceId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import React, {
} from "react";
import { get_values } from "json-logic-js";
import { isPartialSliceId } from "../../utils/misc";
import { fetchDimensionLabels, fetchUniqueValuesOrRange } from "../../api";
import { useDeprecatedDataExplorerApi } from "../../contexts/DeprecatedDataExplorerApiContext";
import {
Expr,
floor,
Expand Down Expand Up @@ -68,6 +68,7 @@ function Comparison({
slice_type,
shouldShowValidation,
}: Props) {
const api = useDeprecatedDataExplorerApi();
const [summary, setSummary] = useState<Summary | null>(null);
const [, forceRender] = useState<null>();
const ref = useRef<HTMLDivElement | null>(null);
Expand Down Expand Up @@ -135,14 +136,14 @@ function Comparison({

try {
if (slice_id === "entity_label") {
const data = await fetchDimensionLabels(slice_type);
const data = await api.fetchDimensionLabels(slice_type);
const labels = data.labels.sort(collator.compare);
setSummary({
value_type: "categorical",
unique_values: labels,
});
} else {
const fetchedOptions = await fetchUniqueValuesOrRange(slice_id);
const fetchedOptions = await api.fetchUniqueValuesOrRange(slice_id);
if (mounted) {
setSummary(fetchedOptions);
}
Expand All @@ -158,7 +159,7 @@ function Comparison({
return () => {
mounted = false;
};
}, [slice_type, slice_id]);
}, [api, slice_type, slice_id]);

useEffect(() => {
if (summary && summary.value_type === "continuous") {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import React, { createContext, useContext, useEffect, useState } from "react";
import { fetchMetadataSlices, MetadataSlices } from "../../api";
import {
DeprecatedDataExplorerApiResponse,
useDeprecatedDataExplorerApi,
} from "../../contexts/DeprecatedDataExplorerApiContext";

type MetadataSlices = DeprecatedDataExplorerApiResponse["fetchMetadataSlices"];

const ContextBuilderContext = createContext({
metadataSlices: {} as MetadataSlices,
Expand All @@ -17,6 +22,7 @@ export const ContextBuilderContextProvider = ({
dimension_type: string | undefined;
children: React.ReactNode;
}) => {
const api = useDeprecatedDataExplorerApi();
const [isLoading, setIsLoading] = useState(true);
const [metadataSlices, setMetadataSlices] = useState<MetadataSlices>({});

Expand All @@ -25,13 +31,13 @@ export const ContextBuilderContextProvider = ({
if (dimension_type) {
setIsLoading(true);

const slices = await fetchMetadataSlices(dimension_type);
const slices = await api.fetchMetadataSlices(dimension_type);
setMetadataSlices(slices);

setIsLoading(false);
}
})();
}, [dimension_type]);
}, [api, dimension_type]);

return (
<ContextBuilderContext.Provider
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { useEffect, useState } from "react";
import { ContextSummaryResponse, fetchContextSummary } from "../../../api";
import {
DeprecatedDataExplorerApiResponse,
useDeprecatedDataExplorerApi,
} from "../../../contexts/DeprecatedDataExplorerApiContext";
import { isCompleteExpression, isPartialSliceId } from "../../../utils/misc";
import {
Expr,
Expand Down Expand Up @@ -42,13 +45,16 @@ export const useEvaluatedExpressionResult = (
slice_type: string,
expr: Expr
) => {
const [result, setResult] = useState<ContextSummaryResponse | null>(null);
const api = useDeprecatedDataExplorerApi();
const [result, setResult] = useState<
DeprecatedDataExplorerApiResponse["fetchContextSummary"] | null
>(null);

// TODO: re-implement this by calling the other endpoint
useEffect(() => {
(async () => {
if (isCompleteExpression(expr)) {
const fetchedResult = await fetchContextSummary({
const fetchedResult = await api.fetchContextSummary({
context_type: slice_type,
expr: normalizeExpr(expr),
});
Expand All @@ -58,7 +64,7 @@ export const useEvaluatedExpressionResult = (
setResult(null);
}
})();
}, [expr, slice_type]);
}, [api, expr, slice_type]);

return result;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useRef, useEffect } from "react";
import cx from "classnames";
import { get_values } from "json-logic-js";
import { ContextSummaryResponse } from "../../api";
import { DeprecatedDataExplorerApiResponse } from "../../contexts/DeprecatedDataExplorerApiContext";
import { getDimensionTypeLabel, pluralize } from "../../utils/misc";
import AnyAllSelect from "./AnyAllSelect";
import { Expr, getOperator } from "./contextBuilderUtils";
Expand All @@ -17,7 +17,7 @@ interface Props {
dispatch: React.Dispatch<ContextBuilderReducerAction>;
slice_type: string;
shouldShowValidation: boolean;
result: ContextSummaryResponse | null;
result: DeprecatedDataExplorerApiResponse["fetchContextSummary"] | null;
editInCellLineSelector: (
modelNamesOrIDs: string[],
shouldUseModelNames: boolean
Expand All @@ -30,7 +30,7 @@ function Result({
isTopLevel,
slice_type,
}: {
result: ContextSummaryResponse;
result: DeprecatedDataExplorerApiResponse["fetchContextSummary"];
isTopLevel: boolean;
slice_type: string;
}) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import React, { useEffect, useMemo, useState } from "react";
import { DataExplorerDatasetDescriptor } from "@depmap/types";
import { capitalize, getDimensionTypeLabel } from "../../utils/misc";
import { fetchDatasetsByIndexType, MetadataSlices } from "../../api";
import {
DeprecatedDataExplorerApiResponse,
useDeprecatedDataExplorerApi,
} from "../../contexts/DeprecatedDataExplorerApiContext";
import SliceLabelSelector from "../SliceLabelSelector";
import PlotConfigSelect from "../PlotConfigSelect";
import { ContextBuilderReducerAction } from "./contextBuilderReducer";
Expand Down Expand Up @@ -59,7 +62,9 @@ const extractDatasetIdFromSlice = (
return decodeURIComponent(match.replace("slice/", "").slice(0, -1));
};

const getMetadataLookupTable = (slices: MetadataSlices) => {
const getMetadataLookupTable = (
slices: DeprecatedDataExplorerApiResponse["fetchMetadataSlices"]
) => {
const out: Record<string, string> = {};

Object.entries(slices).forEach(([key, value]) => {
Expand All @@ -83,6 +88,8 @@ function Variable({
slice_type,
shouldShowValidation,
}: Props) {
const api = useDeprecatedDataExplorerApi();

const [datasets, setDatasets] = useState<
DataExplorerDatasetDescriptor[] | null
>(null);
Expand All @@ -94,7 +101,7 @@ function Variable({

(async () => {
try {
const data = await fetchDatasetsByIndexType();
const data = await api.fetchDatasetsByIndexType();
const fetchedDatasets = data?.[slice_type] || [];
if (mounted) {
setDatasets(fetchedDatasets);
Expand All @@ -107,7 +114,7 @@ function Variable({
return () => {
mounted = false;
};
}, [slice_type]);
}, [api, slice_type]);

const continuousDatasetSliceLookupTable = useMemo(
() =>
Expand Down
Loading

0 comments on commit 86537a2

Please sign in to comment.