diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d0b12056..dd6b54d0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,9 @@ You can also check the # Unreleased -Nothing yet. +- Features + - Made it possible to sort the cube search results and filter by draft + datasets when looking for a cube to merge # [5.0.1] - 2024-11-26 diff --git a/app/browser/dataset-browse.tsx b/app/browser/dataset-browse.tsx index 6a9c4ba50..0bb85ae8d 100644 --- a/app/browser/dataset-browse.tsx +++ b/app/browser/dataset-browse.tsx @@ -199,22 +199,7 @@ export const SearchDatasetControls = ({ onSetOrder, } = browseState; - const order = stateOrder || SearchCubeResultOrder.CreatedDesc; - const options = [ - { - value: SearchCubeResultOrder.Score, - label: t({ id: "dataset.order.relevance", message: `Relevance` }), - }, - { - value: SearchCubeResultOrder.TitleAsc, - label: t({ id: "dataset.order.title", message: `Title` }), - }, - { - value: SearchCubeResultOrder.CreatedDesc, - label: t({ id: "dataset.order.newest", message: `Newest` }), - }, - ]; - + const order = stateOrder ?? SearchCubeResultOrder.CreatedDesc; const isSearching = search !== "" && search !== undefined; const onToggleIncludeDrafts = useEvent(async () => { @@ -228,56 +213,121 @@ export const SearchDatasetControls = ({ return ( - - {cubes.length > 0 && ( - - )} - - + - - - - { - onSetOrder(e.target.value as SearchCubeResultOrder); - }} + onChange={onSetOrder} + disableScore={isSearching} /> ); }; +export const SearchDatasetResultsCount = ({ + cubes, +}: { + cubes: SearchCubeResult[]; +}) => { + return ( + + {cubes.length > 0 && ( + + )} + + ); +}; + +export const SearchDatasetDraftsControl = ({ + checked, + onChange, +}: { + checked: boolean; + onChange: (value: boolean) => void; +}) => { + return ( + onChange(!checked)} + /> + ); +}; + +export const SearchDatasetSortControl = ({ + value, + onChange, + disableScore, +}: { + value: SearchCubeResultOrder; + onChange: (order: SearchCubeResultOrder) => void; + disableScore?: boolean; +}) => { + const options = useMemo(() => { + const options = [ + { + value: SearchCubeResultOrder.Score, + label: t({ id: "dataset.order.relevance", message: "Relevance" }), + }, + { + value: SearchCubeResultOrder.TitleAsc, + label: t({ id: "dataset.order.title", message: "Title" }), + }, + { + value: SearchCubeResultOrder.CreatedDesc, + label: t({ id: "dataset.order.newest", message: "Newest" }), + }, + ]; + + return disableScore + ? options.filter((o) => o.value !== SearchCubeResultOrder.Score) + : options; + }, [disableScore]); + + return ( + + + { + onChange(e.target.value as SearchCubeResultOrder); + }} + /> + + ); +}; + type NavItemTheme = { activeBg: string; activeTextColor: string; @@ -980,7 +1030,7 @@ export const DatasetResults = ({ } return ( - <> +
{cubes.map(({ cube, highlightedTitle, highlightedDescription }) => ( ))} - +
); }; @@ -1002,10 +1052,11 @@ const useResultStyles = makeStyles((theme: Theme) => ({ color: theme.palette.grey[700], textAlign: "left", padding: `${theme.spacing(4)} 0`, - borderTopColor: theme.palette.grey[300], - borderTopStyle: "solid", - borderTopWidth: 1, boxShadow: "none", + + "&:not(:first-child)": { + borderTop: `1px solid ${theme.palette.grey[300]}`, + }, }, titleClickable: { diff --git a/app/components/form.tsx b/app/components/form.tsx index 3f7d74b7e..67f1a28ec 100644 --- a/app/components/form.tsx +++ b/app/components/form.tsx @@ -548,6 +548,7 @@ export const MinimalisticSelect = (props: MinimalisticSelectProps) => { onChange, smaller = false, disabled, + sx, ...rest } = props; @@ -559,21 +560,6 @@ export const MinimalisticSelect = (props: MinimalisticSelectProps) => { )} { {...props} style={{ ...props.style, - right: 12, transition: "transform 0.1s", }} > )} + sx={{ + borderColor: "transparent", + fontSize: smaller ? ["0.625rem", "0.75rem", "0.75rem"] : "inherit", + lineHeight: "normal !important", + backgroundColor: "transparent", + p: 0, + pl: 1, + ":focus": { + outline: "none", + borderColor: "primary.main", + }, + "& .MuiInput-input": { + paddingRight: "1.25rem !important", + }, + ...sx, + }} {...rest} > {options.map((opt) => ( diff --git a/app/configurator/components/add-dataset-dialog.tsx b/app/configurator/components/add-dataset-dialog.tsx index 3b51d8a91..16d247495 100644 --- a/app/configurator/components/add-dataset-dialog.tsx +++ b/app/configurator/components/add-dataset-dialog.tsx @@ -50,9 +50,16 @@ import uniq from "lodash/uniq"; import { FormEvent, useCallback, useEffect, useMemo, useState } from "react"; import { useClient } from "urql"; -import { DatasetResults, PartialSearchCube } from "@/browser/dataset-browse"; +import { + DatasetResults, + PartialSearchCube, + SearchDatasetDraftsControl, + SearchDatasetResultsCount, + SearchDatasetSortControl, +} from "@/browser/dataset-browse"; import { FirstTenRowsCaption } from "@/browser/dataset-preview"; import { getEnabledChartTypes } from "@/charts"; +import Flex from "@/components/flex"; import { Error as ErrorHint, Loading } from "@/components/hint"; import Tag from "@/components/tag"; import { @@ -95,6 +102,7 @@ import SvgIcRemove from "@/icons/components/IcRemove"; import SvgIcSearch from "@/icons/components/IcSearch"; import { useLocale } from "@/locales/use-locale"; import { useEventEmitter } from "@/utils/eventEmitter"; +import useEvent from "@/utils/use-event"; import useLocalState from "@/utils/use-local-state"; const DialogCloseButton = (props: IconButtonProps) => { @@ -604,10 +612,15 @@ export const DatasetDialog = ({ state, ...props }: { state: ConfiguratorStateConfiguringChart } & DialogProps) => { - const [query, setQuery] = useState(""); const locale = useLocale(); const classes = useStyles(); + const [query, setQuery] = useState(""); + const [order, setOrder] = useState( + SearchCubeResultOrder.Score + ); + const [includeDrafts, setIncludeDrafts] = useState(false); + const commonQueryVariables = { sourceType: state.dataSource.type, sourceUrl: state.dataSource.url, @@ -615,8 +628,9 @@ export const DatasetDialog = ({ }; const activeChartConfig = state.chartConfigs.find( - (x) => x.key === state.activeChartKey + (chartConfig) => chartConfig.key === state.activeChartKey ); + if (!activeChartConfig) { throw Error("Could not find active chart config"); } @@ -724,9 +738,9 @@ export const DatasetDialog = ({ sourceType: state.dataSource.type, sourceUrl: state.dataSource.url, locale, - query: query, - order: SearchCubeResultOrder.Score, - includeDrafts: false, + query, + order, + includeDrafts, fetchDimensionTermsets: true, filters: [ selectedTemporalDimension @@ -752,13 +766,13 @@ export const DatasetDialog = ({ const currentComponents = cubesComponentQuery.data?.dataCubesComponents; - const handleSubmit = (ev: FormEvent) => { - ev.preventDefault(); + const handleSubmit = useEvent((e: FormEvent) => { + e.preventDefault(); const formData = Object.fromEntries( - new FormData(ev.currentTarget).entries() + new FormData(e.currentTarget).entries() ); setQuery(formData.search as string); - }; + }); const handleClose: DialogProps["onClose"] = useEventCallback((ev, reason) => { props.onClose?.(ev, reason); @@ -887,14 +901,13 @@ export const DatasetDialog = ({ display="flex" alignItems="center" component="form" - gap="0.25rem" - mb="1.5rem" + gap="0.5rem" + mb="1rem" onSubmit={handleSubmit} > @@ -919,17 +932,17 @@ export const DatasetDialog = ({ }} input={ } - id="select-multiple-chip" - label="Chip" + style={{ width: "100%" }} /> } - sx={{ minWidth: 300 }} renderValue={(selected) => cubeComponentTermsets.fetching || cubesComponentQuery.fetching ? ( @@ -976,11 +989,29 @@ export const DatasetDialog = ({ ))} - + + + + + + + + {selectedSearchDimensions?.length === 0 ? ( @@ -989,7 +1020,7 @@ export const DatasetDialog = ({ ) : ( { return ( diff --git a/app/configurator/components/layout-configurator.tsx b/app/configurator/components/layout-configurator.tsx index df4bf0b17..fa39f3fb0 100644 --- a/app/configurator/components/layout-configurator.tsx +++ b/app/configurator/components/layout-configurator.tsx @@ -240,7 +240,6 @@ const LayoutSharedFiltersConfigurator = () => { - {/* TODO: allow TemporalOrdinalDimensions to work here */} {timeRange && combinedTemporalDimension.values.length ? ( <>