Skip to content

Commit

Permalink
FIX-2424 Column filter search params (equinor#2443)
Browse files Browse the repository at this point in the history
  • Loading branch information
eliasbruvik authored May 27, 2024
1 parent ed9f75d commit 4c02ad3
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
Typography
} from "@equinor/eds-core-react";
import { Checkbox } from "@mui/material";
import { Table } from "@tanstack/react-table";
import { Column, Table } from "@tanstack/react-table";
import {
activeId,
calculateColumnWidth,
Expand All @@ -21,7 +21,16 @@ import { Button } from "components/StyledComponents/Button";
import OperationContext from "contexts/operationContext";
import { UserTheme } from "contexts/operationStateReducer";
import { useLocalStorageState } from "hooks/useLocalStorageState";
import { ChangeEvent, useContext, useState } from "react";
import { debounce } from "lodash";
import {
ChangeEvent,
useCallback,
useContext,
useEffect,
useState
} from "react";
import { useSearchParams } from "react-router-dom";
import { checkIsUrlTooLong } from "routes/utils/checkIsUrlTooLong";
import styled from "styled-components";
import { Colors } from "styles/Colors";
import {
Expand All @@ -32,6 +41,8 @@ import { Draggable, DummyDrop } from "../../StyledComponents/DragDropTable";

const lastId = "dummyLastId";

type FilterValues = Record<string, string>;

export const ColumnOptionsMenu = (props: {
table: Table<any>;
checkableRows: boolean;
Expand Down Expand Up @@ -62,11 +73,20 @@ export const ColumnOptionsMenu = (props: {
const [, saveOrderToStorage] = useLocalStorageState<string[]>(
viewId + STORAGE_CONTENTTABLE_ORDER_KEY
);
const [filterValues, setFilterValues] = useState<{ [key: string]: string }>(
{}
);
const [searchParams, setSearchParams] = useSearchParams();
const [filterValues, setFilterValues] = useState<FilterValues>({});
const isCompactMode = theme === UserTheme.Compact;

useEffect(() => {
const filterString = searchParams.get("filter");
const initialFilter = JSON.parse(filterString);
const bothEmpty =
!initialFilter && Object.entries(filterValues).length === 0;
if (filterString !== JSON.stringify(filterValues) && !bothEmpty) {
setInitialFilter(initialFilter);
}
}, [searchParams]);

const drop = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();
if (
Expand Down Expand Up @@ -134,8 +154,70 @@ export const ColumnOptionsMenu = (props: {
column.setFilterValue(null);
});
setFilterValues({});
searchParams.delete("filter");
setSearchParams(searchParams);
};

const setInitialFilter = useCallback(
debounce((filterValues: FilterValues) => {
// Make sure we remove previous filters
table.getAllLeafColumns().map((column) => {
column.setFilterValue(null);
});
if (!filterValues) {
setFilterValues({});
} else {
Object.entries(filterValues).forEach(([key, value]) => {
const column = table
.getAllLeafColumns()
.find((col) => col.id === key);
column.setFilterValue(value);
});
setFilterValues(filterValues);
}
}, 50),
[]
);

const onChangeColumnFilter = (
e: ChangeEvent<HTMLInputElement>,
column: Column<any, unknown>
) => {
const newValue = e.target.value || null; // If the value is "", we use null instead. Otherwise, other filter functions will not be applied.
const newFilterValues = {
...filterValues,
[column.id]: newValue
};
if (!newValue) {
delete newFilterValues[column.id];
}
setFilterValues(newFilterValues);
// Debounce updating the column filter and search params to reduce re-renders
updateColumnFilter(newValue, column);
updateFilterSearchParams(newFilterValues);
};

const updateColumnFilter = useCallback(
debounce((value: string, column: Column<any, unknown>) => {
column.setFilterValue(value);
}, 500),
[]
);

const updateFilterSearchParams = useCallback(
debounce((filterValues: FilterValues) => {
const newSearchParams = createColumnFilterSearchParams(
searchParams,
filterValues
);
if (checkIsUrlTooLong(location.pathname, newSearchParams)) {
newSearchParams.delete("filter"); // Remove filter from the URL if it takes too much space. The filter will still be applied, but not in the URL.
}
setSearchParams(newSearchParams);
}, 500),
[]
);

return (
<>
<Button
Expand Down Expand Up @@ -233,13 +315,9 @@ export const ColumnOptionsMenu = (props: {
(column.columnDef.meta as { type: ContentType })
?.type === ContentType.Component
}
onChange={(e: ChangeEvent<HTMLInputElement>) => {
column.setFilterValue(e.target.value || null); // If the value is "", we use null instead. Otherwise, other filter functions will not be applied.
setFilterValues({
...filterValues,
[column.id]: e.target.value
});
}}
onChange={(e: ChangeEvent<HTMLInputElement>) =>
onChangeColumnFilter(e, column)
}
style={{ minWidth: "100px", maxHeight: "25px" }}
/>
</EdsProvider>
Expand Down Expand Up @@ -337,3 +415,15 @@ const StyledMenu = styled(Menu)<{ colors: Colors }>`
padding: 4px;
}
`;

export const createColumnFilterSearchParams = (
currentSearchParams: URLSearchParams,
filterValues: FilterValues
): URLSearchParams => {
if (Object.entries(filterValues).length === 0) {
currentSearchParams.delete("filter");
} else {
currentSearchParams.set("filter", JSON.stringify(filterValues));
}
return currentSearchParams;
};
10 changes: 8 additions & 2 deletions Src/WitsmlExplorer.Frontend/components/Sidebar/LogTypeItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
WITSML_INDEX_TYPE_DATE_TIME,
WITSML_INDEX_TYPE_MD
} from "components/Constants";
import { createColumnFilterSearchParams } from "components/ContentViews/table/ColumnOptionsMenu";
import {
getContextMenuPosition,
preventContextMenuPropagation
Expand Down Expand Up @@ -29,7 +30,7 @@ import Wellbore, {
calculateObjectNodeId as calculateWellboreObjectNodeId
} from "models/wellbore";
import { Fragment, MouseEvent, useContext } from "react";
import { useParams } from "react-router-dom";
import { useParams, useSearchParams } from "react-router-dom";
import { RouterLogType } from "routes/routerConstants";
import {
getLogObjectViewPath,
Expand All @@ -48,6 +49,7 @@ export default function LogTypeItem({
wellboreUid
}: LogTypeItemProps) {
const { dispatchOperation } = useContext(OperationContext);
const [searchParams] = useSearchParams();
const { servers } = useGetServers();
const { connectedServer } = useConnectedServer();
const { wellbore } = useGetWellbore(connectedServer, wellUid, wellboreUid);
Expand Down Expand Up @@ -200,7 +202,11 @@ export default function LogTypeItem({
labelText={subLogsNodeName(log.name)}
key={getMultipleLogsNode(log.name)}
nodeId={getMultipleLogsNode(log.name)}
to={getNavPath(getLogTypeGroup(logType))}
to={`${getNavPath(
getLogTypeGroup(logType)
)}?${createColumnFilterSearchParams(searchParams, {
name: log.name
})}`}
selected={
calculateMultipleLogsNode(
{ wellUid: urlWellUid, uid: urlWellboreUid },
Expand Down
12 changes: 9 additions & 3 deletions Src/WitsmlExplorer.Frontend/hooks/useGetMnemonics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ export function useGetMnemonics(
const [mnemonics, setMnemonics] = useState<string[]>(null);
const { connectedServer } = useConnectedServer();

const updateMnemonics = (newMnemonics: string[]) => {
if (JSON.stringify(newMnemonics) !== JSON.stringify(mnemonics)) {
setMnemonics(newMnemonics);
}
};

useEffect(() => {
if (!isFethingLogCurveInfoList) {
if (mnemonicsSearchParams) {
Expand All @@ -35,11 +41,11 @@ export function useGetMnemonics(
) {
sendMissingMnemonicsWarning(connectedServer.url, missingMnemonics);
}
setMnemonics(newMnemonics);
updateMnemonics(newMnemonics);
} else if (location?.state?.mnemonics) {
setMnemonics(JSON.parse(location.state.mnemonics));
updateMnemonics(JSON.parse(location.state.mnemonics));
} else {
setMnemonics(getExistingMnemonics(logCurveInfoList));
updateMnemonics(getExistingMnemonics(logCurveInfoList));
}
}
}, [
Expand Down

0 comments on commit 4c02ad3

Please sign in to comment.