From 8ffc99530a18406c8689ce22120a736462bf3f6c Mon Sep 17 00:00:00 2001 From: yankovs Date: Sun, 24 Sep 2023 14:07:59 +0300 Subject: [PATCH 1/3] Initial query result commit --- mwdb/web/src/commons/ui/ButtonDropdown.tsx | 34 +++ .../Actions/QueryResultAddTagAction.tsx | 61 ++++++ .../Actions/QueryResultHashesAction.tsx | 34 +++ .../Actions/QueryResultJsonAction.tsx | 32 +++ .../Actions/QueryResultRemoveTagAction.tsx | 61 ++++++ .../RecentView/Views/QueryResultOptions.tsx | 36 ++++ .../RecentView/Views/RecentView.tsx | 196 +++++++++--------- .../RecentView/Views/RecentViewList.tsx | 6 + .../RecentView/common/QueryContext.tsx | 18 ++ .../RecentView/common/ResultOptionItem.tsx | 42 ++++ mwdb/web/src/styles/index.css | 15 ++ 11 files changed, 442 insertions(+), 93 deletions(-) create mode 100644 mwdb/web/src/commons/ui/ButtonDropdown.tsx create mode 100644 mwdb/web/src/components/RecentView/Actions/QueryResultAddTagAction.tsx create mode 100644 mwdb/web/src/components/RecentView/Actions/QueryResultHashesAction.tsx create mode 100644 mwdb/web/src/components/RecentView/Actions/QueryResultJsonAction.tsx create mode 100644 mwdb/web/src/components/RecentView/Actions/QueryResultRemoveTagAction.tsx create mode 100644 mwdb/web/src/components/RecentView/Views/QueryResultOptions.tsx create mode 100644 mwdb/web/src/components/RecentView/common/QueryContext.tsx create mode 100644 mwdb/web/src/components/RecentView/common/ResultOptionItem.tsx diff --git a/mwdb/web/src/commons/ui/ButtonDropdown.tsx b/mwdb/web/src/commons/ui/ButtonDropdown.tsx new file mode 100644 index 000000000..779da046b --- /dev/null +++ b/mwdb/web/src/commons/ui/ButtonDropdown.tsx @@ -0,0 +1,34 @@ +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { IconProp } from "@fortawesome/fontawesome-svg-core"; + +type Props = { + title?: string; + color?: string; + icon?: IconProp; + elements: JSX.Element[]; +}; + +export function ButtonDropdown(props: Props) { + if (!props.elements.length) return
; + return ( +
+ +
    + {props.elements} +
+
+ ); +} diff --git a/mwdb/web/src/components/RecentView/Actions/QueryResultAddTagAction.tsx b/mwdb/web/src/components/RecentView/Actions/QueryResultAddTagAction.tsx new file mode 100644 index 000000000..7304bcdf5 --- /dev/null +++ b/mwdb/web/src/components/RecentView/Actions/QueryResultAddTagAction.tsx @@ -0,0 +1,61 @@ +import { useContext, useState } from "react"; + +import { faTag } from "@fortawesome/free-solid-svg-icons"; + +import { Capability, ObjectData } from "@mwdb-web/types/types"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { QueryContext } from "../common/QueryContext"; +import { APIContext } from "@mwdb-web/commons/api"; +import { ConfirmationModal } from "@mwdb-web/commons/ui"; +import { AuthContext } from "@mwdb-web/commons/auth"; +import { useViewAlert } from "@mwdb-web/commons/hooks"; +import { ResultOptionItem } from "../common/ResultOptionItem"; + +export function AddTagAction() { + const api = useContext(APIContext); + const auth = useContext(AuthContext); + const { items } = useContext(QueryContext); + + const { setAlert } = useViewAlert(); + + const [tag, setTag] = useState(""); + const [modalOpen, setIsModalOpen] = useState(false); + + + function addTag() { + items.forEach(async (e: ObjectData) => { + await api.addObjectTag(e.id, tag) + .catch((err) => setAlert({ error: `Error adding tag to object ${e.id}: ${err}` })) + }); + setIsModalOpen(false); + } + + return ( + <> + {auth.hasCapability(Capability.addingTags) ? ( + setIsModalOpen(true)} + > + setIsModalOpen(false)} + onCancel={() => setIsModalOpen(false)} + onConfirm={addTag} + > +
+ setTag(e.target.value)} + /> +
+
+
+ ) : []} + + ); +} diff --git a/mwdb/web/src/components/RecentView/Actions/QueryResultHashesAction.tsx b/mwdb/web/src/components/RecentView/Actions/QueryResultHashesAction.tsx new file mode 100644 index 000000000..8e21a3017 --- /dev/null +++ b/mwdb/web/src/components/RecentView/Actions/QueryResultHashesAction.tsx @@ -0,0 +1,34 @@ +import { useContext, useEffect, useState } from "react"; + +import { QueryContext } from "../common/QueryContext"; +import { ResultOptionItem } from "../common/ResultOptionItem"; +import { ObjectData } from "@mwdb-web/types/types"; + + +export function QueryResultHashesAction() { + const { items } = useContext(QueryContext); + const [url, setUrl] = useState(""); + + function generateName() { + return `hashes_${new Date().toJSON().slice(0, 19)}`; + } + + async function generateUrl() { + const hashes = items.map((item: ObjectData) => item.sha256); + const data = new Blob([JSON.stringify(hashes, null, '\t')], { type: 'application/json' }) + setUrl(window.URL.createObjectURL(data)); + } + + useEffect(() => { + generateUrl(); + }, []) + + return ( + + ); +} diff --git a/mwdb/web/src/components/RecentView/Actions/QueryResultJsonAction.tsx b/mwdb/web/src/components/RecentView/Actions/QueryResultJsonAction.tsx new file mode 100644 index 000000000..a3f1701da --- /dev/null +++ b/mwdb/web/src/components/RecentView/Actions/QueryResultJsonAction.tsx @@ -0,0 +1,32 @@ +import { useContext, useEffect, useState } from "react"; + +import { QueryContext } from "../common/QueryContext"; +import { ResultOptionItem } from "../common/ResultOptionItem"; + + +export function QueryResultJsonAction() { + const { items } = useContext(QueryContext); + const [url, setUrl] = useState(""); + + function generateName() { + return `file_data_${new Date().toJSON().slice(0, 19)}`; + } + + async function generateUrl() { + const data = new Blob([JSON.stringify(items, null, '\t')], { type: 'application/json' }) + setUrl(window.URL.createObjectURL(data)); + } + + useEffect(() => { + generateUrl(); + }, []) + + return ( + + ); +} diff --git a/mwdb/web/src/components/RecentView/Actions/QueryResultRemoveTagAction.tsx b/mwdb/web/src/components/RecentView/Actions/QueryResultRemoveTagAction.tsx new file mode 100644 index 000000000..4272f0fe1 --- /dev/null +++ b/mwdb/web/src/components/RecentView/Actions/QueryResultRemoveTagAction.tsx @@ -0,0 +1,61 @@ +import { useContext, useState } from "react"; + +import { faTag } from "@fortawesome/free-solid-svg-icons"; + +import { Capability, ObjectData } from "@mwdb-web/types/types"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { QueryContext } from "../common/QueryContext"; +import { APIContext } from "@mwdb-web/commons/api"; +import { ConfirmationModal } from "@mwdb-web/commons/ui"; +import { AuthContext } from "@mwdb-web/commons/auth"; +import { useViewAlert } from "@mwdb-web/commons/hooks"; +import { ResultOptionItem } from "../common/ResultOptionItem"; + +export function RemoveTagAction() { + const api = useContext(APIContext); + const auth = useContext(AuthContext); + const { items } = useContext(QueryContext); + + const { setAlert } = useViewAlert(); + + const [tag, setTag] = useState(""); + const [modalOpen, setIsModalOpen] = useState(false); + + + function addTag() { + items.forEach(async (e: ObjectData) => { + await api.removeObjectTag(e.id, tag) + .catch((err) => setAlert({ error: `Error removing tag from object ${e.id}: ${err}` })) + }); + setIsModalOpen(false); + } + + return ( + <> + {auth.hasCapability(Capability.removingTags) ? ( + setIsModalOpen(true)} + > + setIsModalOpen(false)} + onCancel={() => setIsModalOpen(false)} + onConfirm={addTag} + > +
+ setTag(e.target.value)} + /> +
+
+
+ ) : []} + + ); +} diff --git a/mwdb/web/src/components/RecentView/Views/QueryResultOptions.tsx b/mwdb/web/src/components/RecentView/Views/QueryResultOptions.tsx new file mode 100644 index 000000000..97fd227a5 --- /dev/null +++ b/mwdb/web/src/components/RecentView/Views/QueryResultOptions.tsx @@ -0,0 +1,36 @@ +import { faExclamationCircle, faMagnifyingGlass, faQuestionCircle } from "@fortawesome/free-solid-svg-icons"; +import { ButtonDropdown } from "@mwdb-web/commons/ui/ButtonDropdown"; +import { ObjectType } from "@mwdb-web/types/types"; +import { QueryResultHashesAction } from "../Actions/QueryResultHashesAction"; +import { useContext } from "react"; +import { QueryContext } from "../common/QueryContext"; +import { QueryResultJsonAction } from "../Actions/QueryResultJsonAction"; +import { AddTagAction } from "../Actions/QueryResultAddTagAction"; +import { RemoveTagAction } from "../Actions/QueryResultRemoveTagAction"; + +type Props = { + type: ObjectType, + query: string, + elements?: JSX.Element[], +}; + +export function QueryResultOptions(props: Props) { + const { items } = useContext(QueryContext); + return ( +
+ {props.query && items && items.length > 0 && +
+ , + , + , + , + ]} + /> +
} +
+ ); +} \ No newline at end of file diff --git a/mwdb/web/src/components/RecentView/Views/RecentView.tsx b/mwdb/web/src/components/RecentView/Views/RecentView.tsx index 2be9609d2..61ae1102e 100644 --- a/mwdb/web/src/components/RecentView/Views/RecentView.tsx +++ b/mwdb/web/src/components/RecentView/Views/RecentView.tsx @@ -10,6 +10,9 @@ import { QuickQuery } from "../common/QuickQuery"; import { ObjectType } from "@mwdb-web/types/types"; import { AxiosError } from "axios"; import { isEmpty } from "lodash"; +import { Extendable } from "@mwdb-web/commons/plugins"; +import { QueryResultOptions } from "./QueryResultOptions"; +import { QueryContextProvider } from "../common/QueryContext"; type Props = { type: ObjectType; @@ -177,104 +180,111 @@ export function RecentView(props: Props) { } return ( - -
-
{ - ev.preventDefault(); - setCurrentQuery(queryInput); - }} - > -
-
- { - ev.preventDefault(); - setCurrentQuery(""); - }} - /> -
- setQueryInput(evt.target.value)} - /> -
-
- -
-
+ + +
+ { + ev.preventDefault(); + setCurrentQuery(queryInput); + }} + > +
+
{ - setSearchParams( - (prev) => { - return { - q: prev.get("q") || "", - count: countingEnabled - ? "0" - : "1", - }; - }, - { replace: true } - ); + value="X" + onClick={(ev) => { + ev.preventDefault(); + setCurrentQuery(""); }} />
- - ? - + setQueryInput(evt.target.value)} + /> +
+
+ +
+
+ { + setSearchParams( + (prev) => { + return { + q: prev.get("q") || "", + count: countingEnabled + ? "0" + : "1", + }; + }, + { replace: true } + ); + }} + /> +
+ + ? + +
+
+
+ {queryError ? queryErrorMessage : objectCountMessage} + setCurrentQuery(query)} + addToQuery={addToQuery} + setQueryError={setQueryError} + /> +
+ + + +
-
-
- {queryError ? queryErrorMessage : objectCountMessage} - setCurrentQuery(query)} - addToQuery={addToQuery} - setQueryError={setQueryError} - /> -
- - -
- + + +
+ + ); } diff --git a/mwdb/web/src/components/RecentView/Views/RecentViewList.tsx b/mwdb/web/src/components/RecentView/Views/RecentViewList.tsx index be1ed0279..7c87546b5 100644 --- a/mwdb/web/src/components/RecentView/Views/RecentViewList.tsx +++ b/mwdb/web/src/components/RecentView/Views/RecentViewList.tsx @@ -10,6 +10,7 @@ import { ObjectType, } from "@mwdb-web/types/types"; import { AxiosError } from "axios"; +import { QueryContext } from "../common/QueryContext"; type Elements = ObjectData[] | BlobData[] | ConfigData[]; @@ -83,6 +84,7 @@ type Props = { export function RecentViewList(props: Props) { const api = useContext(APIContext); + const { setItems } = useContext(QueryContext); const [listState, listDispatch] = useReducer(listStateReducer, { pageToLoad: 0, loadedPages: 0, @@ -103,6 +105,10 @@ export function RecentViewList(props: Props) { } }, [props.query, props.disallowEmpty, api.remote]); + useEffect(() => { + setItems(listState.elements); + }, [listState.elements]) + // Load page on request (pageToLoad != loadedPages) useEffect(() => { let cancelled = false; diff --git a/mwdb/web/src/components/RecentView/common/QueryContext.tsx b/mwdb/web/src/components/RecentView/common/QueryContext.tsx new file mode 100644 index 000000000..a805b3678 --- /dev/null +++ b/mwdb/web/src/components/RecentView/common/QueryContext.tsx @@ -0,0 +1,18 @@ +import { BlobData, ConfigData, ObjectData } from "@mwdb-web/types/types"; +import { ReactNode, createContext, useMemo, useState } from "react"; + +interface Props { + children?: ReactNode; +} +type Objects = ObjectData[] | ConfigData[] | BlobData[]; + +export const QueryContext = createContext(null); +export function QueryContextProvider({ children }: Props) { + const [items, setItems] = useState(null); + + return ( + + {children} + + ); +} \ No newline at end of file diff --git a/mwdb/web/src/components/RecentView/common/ResultOptionItem.tsx b/mwdb/web/src/components/RecentView/common/ResultOptionItem.tsx new file mode 100644 index 000000000..c09ba0d70 --- /dev/null +++ b/mwdb/web/src/components/RecentView/common/ResultOptionItem.tsx @@ -0,0 +1,42 @@ +import { ReactNode, useMemo } from "react"; + +type Props = { + key: string; + url?: string; + size?: string; + title: string; + action?: () => void; + children?: ReactNode; + limit?: () => boolean; + download?: string | (() => string); +}; + +function resolveDownload(download: string | (() => string)): string { + if (typeof download === "string") { + return download; + } + return download(); +} + +export function ResultOptionItem({ children, ...props }: Props) { + const isLimit = useMemo(() => { + if (props.limit) return props.limit(); + return false; + }, [props.limit]) + + return ( +
  • + {!isLimit ? ( + + {props.title} + {children} + ) : [] + } +
  • + ); +} diff --git a/mwdb/web/src/styles/index.css b/mwdb/web/src/styles/index.css index 1bfa7dd72..a0f87ab2c 100644 --- a/mwdb/web/src/styles/index.css +++ b/mwdb/web/src/styles/index.css @@ -151,6 +151,21 @@ div.quick-query-bar { margin-bottom: 6pt; } +div.query-options { + margin-left: auto; + column-gap: 10px; + display: inline-flex; +} + +ul.button-menu { + min-width: 0; + width: 100%; +} + +ul.button-menu li { + text-align: center; +} + .sidenav .nav-link { border-left: #eee solid; } From 0b38128a5d13abb96634896b61d56ee4c864ca47 Mon Sep 17 00:00:00 2001 From: yankovs Date: Mon, 25 Sep 2023 16:26:03 +0300 Subject: [PATCH 2/3] Move result location, rename & simplify --- .../Actions/QueryResultAddTagAction.tsx | 19 +- .../Actions/QueryResultHashesAction.tsx | 4 +- .../Actions/QueryResultJsonAction.tsx | 4 +- .../Actions/QueryResultRemoveTagAction.tsx | 19 +- .../RecentView/Views/QueryResultOptions.tsx | 4 +- .../RecentView/Views/RecentView.tsx | 181 +++++++++--------- .../RecentView/Views/RecentViewList.tsx | 6 +- ...ueryContext.tsx => QueryResultContext.tsx} | 8 +- .../RecentView/common/ResultOptionItem.tsx | 19 +- mwdb/web/src/styles/index.css | 1 - 10 files changed, 130 insertions(+), 135 deletions(-) rename mwdb/web/src/components/RecentView/common/{QueryContext.tsx => QueryResultContext.tsx} (60%) diff --git a/mwdb/web/src/components/RecentView/Actions/QueryResultAddTagAction.tsx b/mwdb/web/src/components/RecentView/Actions/QueryResultAddTagAction.tsx index 7304bcdf5..afcd3d180 100644 --- a/mwdb/web/src/components/RecentView/Actions/QueryResultAddTagAction.tsx +++ b/mwdb/web/src/components/RecentView/Actions/QueryResultAddTagAction.tsx @@ -1,10 +1,7 @@ import { useContext, useState } from "react"; -import { faTag } from "@fortawesome/free-solid-svg-icons"; - import { Capability, ObjectData } from "@mwdb-web/types/types"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { QueryContext } from "../common/QueryContext"; +import { QueryResultContext } from "../common/QueryResultContext"; import { APIContext } from "@mwdb-web/commons/api"; import { ConfirmationModal } from "@mwdb-web/commons/ui"; import { AuthContext } from "@mwdb-web/commons/auth"; @@ -14,7 +11,7 @@ import { ResultOptionItem } from "../common/ResultOptionItem"; export function AddTagAction() { const api = useContext(APIContext); const auth = useContext(AuthContext); - const { items } = useContext(QueryContext); + const { items } = useContext(QueryResultContext); const { setAlert } = useViewAlert(); @@ -35,7 +32,7 @@ export function AddTagAction() { {auth.hasCapability(Capability.addingTags) ? ( setIsModalOpen(true)} > setIsModalOpen(false)} onConfirm={addTag} > -
    - setTag(e.target.value)} - /> -
    + setTag(e.target.value)} + />
    ) : []} diff --git a/mwdb/web/src/components/RecentView/Actions/QueryResultHashesAction.tsx b/mwdb/web/src/components/RecentView/Actions/QueryResultHashesAction.tsx index 8e21a3017..d888f8a0e 100644 --- a/mwdb/web/src/components/RecentView/Actions/QueryResultHashesAction.tsx +++ b/mwdb/web/src/components/RecentView/Actions/QueryResultHashesAction.tsx @@ -1,12 +1,12 @@ import { useContext, useEffect, useState } from "react"; -import { QueryContext } from "../common/QueryContext"; +import { QueryResultContext } from "../common/QueryResultContext"; import { ResultOptionItem } from "../common/ResultOptionItem"; import { ObjectData } from "@mwdb-web/types/types"; export function QueryResultHashesAction() { - const { items } = useContext(QueryContext); + const { items } = useContext(QueryResultContext); const [url, setUrl] = useState(""); function generateName() { diff --git a/mwdb/web/src/components/RecentView/Actions/QueryResultJsonAction.tsx b/mwdb/web/src/components/RecentView/Actions/QueryResultJsonAction.tsx index a3f1701da..1f1734671 100644 --- a/mwdb/web/src/components/RecentView/Actions/QueryResultJsonAction.tsx +++ b/mwdb/web/src/components/RecentView/Actions/QueryResultJsonAction.tsx @@ -1,11 +1,11 @@ import { useContext, useEffect, useState } from "react"; -import { QueryContext } from "../common/QueryContext"; +import { QueryResultContext } from "../common/QueryResultContext"; import { ResultOptionItem } from "../common/ResultOptionItem"; export function QueryResultJsonAction() { - const { items } = useContext(QueryContext); + const { items } = useContext(QueryResultContext); const [url, setUrl] = useState(""); function generateName() { diff --git a/mwdb/web/src/components/RecentView/Actions/QueryResultRemoveTagAction.tsx b/mwdb/web/src/components/RecentView/Actions/QueryResultRemoveTagAction.tsx index 4272f0fe1..86c1fb410 100644 --- a/mwdb/web/src/components/RecentView/Actions/QueryResultRemoveTagAction.tsx +++ b/mwdb/web/src/components/RecentView/Actions/QueryResultRemoveTagAction.tsx @@ -1,10 +1,7 @@ import { useContext, useState } from "react"; -import { faTag } from "@fortawesome/free-solid-svg-icons"; - import { Capability, ObjectData } from "@mwdb-web/types/types"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { QueryContext } from "../common/QueryContext"; +import { QueryResultContext } from "../common/QueryResultContext"; import { APIContext } from "@mwdb-web/commons/api"; import { ConfirmationModal } from "@mwdb-web/commons/ui"; import { AuthContext } from "@mwdb-web/commons/auth"; @@ -14,7 +11,7 @@ import { ResultOptionItem } from "../common/ResultOptionItem"; export function RemoveTagAction() { const api = useContext(APIContext); const auth = useContext(AuthContext); - const { items } = useContext(QueryContext); + const { items } = useContext(QueryResultContext); const { setAlert } = useViewAlert(); @@ -35,7 +32,7 @@ export function RemoveTagAction() { {auth.hasCapability(Capability.removingTags) ? ( setIsModalOpen(true)} > setIsModalOpen(false)} onConfirm={addTag} > -
    - setTag(e.target.value)} - /> -
    + setTag(e.target.value)} + />
    ) : []} diff --git a/mwdb/web/src/components/RecentView/Views/QueryResultOptions.tsx b/mwdb/web/src/components/RecentView/Views/QueryResultOptions.tsx index 97fd227a5..40008f859 100644 --- a/mwdb/web/src/components/RecentView/Views/QueryResultOptions.tsx +++ b/mwdb/web/src/components/RecentView/Views/QueryResultOptions.tsx @@ -3,7 +3,7 @@ import { ButtonDropdown } from "@mwdb-web/commons/ui/ButtonDropdown"; import { ObjectType } from "@mwdb-web/types/types"; import { QueryResultHashesAction } from "../Actions/QueryResultHashesAction"; import { useContext } from "react"; -import { QueryContext } from "../common/QueryContext"; +import { QueryResultContext } from "../common/QueryResultContext"; import { QueryResultJsonAction } from "../Actions/QueryResultJsonAction"; import { AddTagAction } from "../Actions/QueryResultAddTagAction"; import { RemoveTagAction } from "../Actions/QueryResultRemoveTagAction"; @@ -15,7 +15,7 @@ type Props = { }; export function QueryResultOptions(props: Props) { - const { items } = useContext(QueryContext); + const { items } = useContext(QueryResultContext); return (
    {props.query && items && items.length > 0 && diff --git a/mwdb/web/src/components/RecentView/Views/RecentView.tsx b/mwdb/web/src/components/RecentView/Views/RecentView.tsx index 61ae1102e..bc3a47caf 100644 --- a/mwdb/web/src/components/RecentView/Views/RecentView.tsx +++ b/mwdb/web/src/components/RecentView/Views/RecentView.tsx @@ -12,7 +12,7 @@ import { AxiosError } from "axios"; import { isEmpty } from "lodash"; import { Extendable } from "@mwdb-web/commons/plugins"; import { QueryResultOptions } from "./QueryResultOptions"; -import { QueryContextProvider } from "../common/QueryContext"; +import { QueryResultContextProvider } from "../common/QueryResultContext"; type Props = { type: ObjectType; @@ -180,99 +180,102 @@ export function RecentView(props: Props) { } return ( - - -
    -
    { - ev.preventDefault(); - setCurrentQuery(queryInput); - }} - > -
    -
    + +
    + { + ev.preventDefault(); + setCurrentQuery(queryInput); + }} + > +
    +
    + { + ev.preventDefault(); + setCurrentQuery(""); + }} + /> +
    + setQueryInput(evt.target.value)} + /> +
    +
    + +
    +
    { - ev.preventDefault(); - setCurrentQuery(""); + className={`btn btn-outline-info rounded-0 shadow-none ${ + searchParams.get("count") === "1" + ? "active" + : "" + }`} + value="Count" + onClick={() => { + setSearchParams( + (prev) => { + return { + q: prev.get("q") || "", + count: countingEnabled + ? "0" + : "1", + }; + }, + { replace: true } + ); }} />
    - setQueryInput(evt.target.value)} - /> -
    -
    - -
    -
    - { - setSearchParams( - (prev) => { - return { - q: prev.get("q") || "", - count: countingEnabled - ? "0" - : "1", - }; - }, - { replace: true } - ); - }} - /> -
    - - ? - -
    + + ? +
    -
    - {queryError ? queryErrorMessage : objectCountMessage} - +
    + {queryError ? queryErrorMessage : objectCountMessage} + setCurrentQuery(query)} + addToQuery={addToQuery} + setQueryError={setQueryError} + /> +
    + + +
    + + setCurrentQuery(query)} - addToQuery={addToQuery} - setQueryError={setQueryError} /> -
    - - - -
    -
    - + +
    -
    - - + +
    +
    ); } diff --git a/mwdb/web/src/components/RecentView/Views/RecentViewList.tsx b/mwdb/web/src/components/RecentView/Views/RecentViewList.tsx index 7c87546b5..b77fe1e8c 100644 --- a/mwdb/web/src/components/RecentView/Views/RecentViewList.tsx +++ b/mwdb/web/src/components/RecentView/Views/RecentViewList.tsx @@ -10,7 +10,7 @@ import { ObjectType, } from "@mwdb-web/types/types"; import { AxiosError } from "axios"; -import { QueryContext } from "../common/QueryContext"; +import { QueryResultContext } from "../common/QueryResultContext"; type Elements = ObjectData[] | BlobData[] | ConfigData[]; @@ -84,7 +84,7 @@ type Props = { export function RecentViewList(props: Props) { const api = useContext(APIContext); - const { setItems } = useContext(QueryContext); + const { setItems } = useContext(QueryResultContext); const [listState, listDispatch] = useReducer(listStateReducer, { pageToLoad: 0, loadedPages: 0, @@ -107,7 +107,7 @@ export function RecentViewList(props: Props) { useEffect(() => { setItems(listState.elements); - }, [listState.elements]) + }, [listState.elements]); // Load page on request (pageToLoad != loadedPages) useEffect(() => { diff --git a/mwdb/web/src/components/RecentView/common/QueryContext.tsx b/mwdb/web/src/components/RecentView/common/QueryResultContext.tsx similarity index 60% rename from mwdb/web/src/components/RecentView/common/QueryContext.tsx rename to mwdb/web/src/components/RecentView/common/QueryResultContext.tsx index a805b3678..3c408de79 100644 --- a/mwdb/web/src/components/RecentView/common/QueryContext.tsx +++ b/mwdb/web/src/components/RecentView/common/QueryResultContext.tsx @@ -6,13 +6,13 @@ interface Props { } type Objects = ObjectData[] | ConfigData[] | BlobData[]; -export const QueryContext = createContext(null); -export function QueryContextProvider({ children }: Props) { +export const QueryResultContext = createContext(null); +export function QueryResultContextProvider({ children }: Props) { const [items, setItems] = useState(null); return ( - + {children} - + ); } \ No newline at end of file diff --git a/mwdb/web/src/components/RecentView/common/ResultOptionItem.tsx b/mwdb/web/src/components/RecentView/common/ResultOptionItem.tsx index c09ba0d70..f1984d23f 100644 --- a/mwdb/web/src/components/RecentView/common/ResultOptionItem.tsx +++ b/mwdb/web/src/components/RecentView/common/ResultOptionItem.tsx @@ -27,15 +27,18 @@ export function ResultOptionItem({ children, ...props }: Props) { return (
  • {!isLimit ? ( - - {props.title} + <> + + {props.title} + {children} - ) : [] + ) : [] }
  • ); diff --git a/mwdb/web/src/styles/index.css b/mwdb/web/src/styles/index.css index a0f87ab2c..698e1ce28 100644 --- a/mwdb/web/src/styles/index.css +++ b/mwdb/web/src/styles/index.css @@ -152,7 +152,6 @@ div.quick-query-bar { } div.query-options { - margin-left: auto; column-gap: 10px; display: inline-flex; } From 77c93b0eeede3b630ba7612a4d82b23f7cd80926 Mon Sep 17 00:00:00 2001 From: yankovs Date: Tue, 26 Sep 2023 14:34:33 +0300 Subject: [PATCH 3/3] Add karton reanalyze option --- mwdb/web/src/commons/ui/ButtonDropdown.tsx | 2 +- .../Actions/QueryResultAddTagAction.tsx | 47 +++++++++--------- .../QueryResultKartonReanalyzeAction.tsx | 47 ++++++++++++++++++ .../Actions/QueryResultRemoveTagAction.tsx | 49 +++++++++---------- .../RecentView/Views/QueryResultOptions.tsx | 2 + .../RecentView/common/ResultOptionItem.tsx | 8 ++- 6 files changed, 104 insertions(+), 51 deletions(-) create mode 100644 mwdb/web/src/components/RecentView/Actions/QueryResultKartonReanalyzeAction.tsx diff --git a/mwdb/web/src/commons/ui/ButtonDropdown.tsx b/mwdb/web/src/commons/ui/ButtonDropdown.tsx index 779da046b..69e1f0fd0 100644 --- a/mwdb/web/src/commons/ui/ButtonDropdown.tsx +++ b/mwdb/web/src/commons/ui/ButtonDropdown.tsx @@ -11,7 +11,7 @@ type Props = { export function ButtonDropdown(props: Props) { if (!props.elements.length) return
    ; return ( -
    +