diff --git a/assets/icons/organisation.svg b/assets/icons/organisation.svg new file mode 100644 index 000000000..a6ca3aa71 --- /dev/null +++ b/assets/icons/organisation.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/components/button/index.tsx b/components/button/index.tsx index 64ab19d44..1f8f12f8b 100644 --- a/components/button/index.tsx +++ b/components/button/index.tsx @@ -16,6 +16,7 @@ const buttonVariants = cva(["button"], { size: { xs: ["button--xs"], sm: ["button--small"], + md: ["button--medium"], lg: ["button--small md:button--large"], }, variant: { @@ -35,41 +36,22 @@ const buttonVariants = cva(["button"], { type IconLabelProps = { icon?: AddIcon; - size?: "xs" | "sm" | "lg"; + size?: "xs" | "sm" | "md" | "lg"; label?: string; iconPosition?: "left" | "right"; - iconSizeBase?: number; }; -const IconLabel: FC = ({ - icon, - label, - size, - iconPosition, - iconSizeBase, -}) => { +const IconLabel: FC = ({ icon, label, size, iconPosition }) => { const Icon = icon; - const { iconSize: contextIconSize } = useContext(SettingsContext); + const { iconSize } = useContext(SettingsContext); return ( <> {iconPosition === "left" && Icon && ( )} @@ -77,20 +59,8 @@ const IconLabel: FC = ({ {iconPosition === "right" && Icon && ( )} @@ -101,7 +71,6 @@ const IconLabel: FC = ({ type ButtonProps = VariantProps & { icon?: AddIcon; iconPosition?: "left" | "right"; - iconSize?: number; label?: string; }; @@ -113,7 +82,6 @@ const Button: FC< className, icon, iconPosition, - iconSize, label, children, ...rest @@ -126,7 +94,6 @@ const Button: FC< > > = ({ diff --git a/components/layout/hero/index.tsx b/components/layout/hero/index.tsx index a23b5ab85..f9812e818 100644 --- a/components/layout/hero/index.tsx +++ b/components/layout/hero/index.tsx @@ -3,6 +3,10 @@ import useTranslation from "next-translate/useTranslation"; import { FC, useState } from "react"; import ArrowRightIcon from "@/assets/icons/arrow-right.svg"; +import ConceptIcon from "@/assets/icons/data.svg"; +import DiamondIcon from "@/assets/icons/diamond.svg"; +import SpecificationIcon from "@/assets/icons/list-block.svg"; +import OrganisationIcon from "@/assets/icons/organisation.svg"; import { ButtonLink } from "@/components/button"; import { CustomImage } from "@/components/custom-image"; import { Container } from "@/components/layout/container"; @@ -10,6 +14,7 @@ import { Heading } from "@/components/typography/heading"; import { Preamble } from "@/components/typography/preamble"; import { SearchInput } from "@/features/search/search-input"; import { ImageFragment } from "@/graphql/__generated__/operations"; +import { AddIcon } from "@/types/global"; import { checkLang } from "@/utilities"; interface HeroProps { @@ -25,6 +30,31 @@ interface SearchProps { placeholder: string; } +interface HeroButtonProps { + href: string; + label: string; + lang: string; + icon: AddIcon; +} + +const HeroButton = ({ href, label, lang, icon }: HeroButtonProps) => { + const CenterIcon = icon; + return ( + + + + {label} + + + + ); +}; + export const Hero: FC = ({ heading, preamble, @@ -63,24 +93,71 @@ export const Hero: FC = ({
{heading && ( - + {checkLang(heading)} )} {preamble && ( - + {preamble} )} {search && ( -
+
+
+
+ + + +
+
+ + + +
+
= ({ ariaLabel={search.placeholder} />
-
- - - - -
)}
diff --git a/features/entryscape/organisation-page/index.tsx b/features/entryscape/organisation-page/index.tsx index 572b31ea2..fa284c5c4 100644 --- a/features/entryscape/organisation-page/index.tsx +++ b/features/entryscape/organisation-page/index.tsx @@ -4,8 +4,8 @@ import useTranslation from "next-translate/useTranslation"; import React, { FC, useContext, useEffect, useState } from "react"; import ArrowRightIcon from "@/assets/icons/arrow-right.svg"; +import DataIcon from "@/assets/icons/data.svg"; import DiamondIcon from "@/assets/icons/diamond.svg"; -import HoldingHandsIcon from "@/assets/icons/holding-hands.svg"; import ListBlockIcon from "@/assets/icons/list-block.svg"; import QuestionCircleIcon from "@/assets/icons/question-circle.svg"; import { Button, ButtonLink } from "@/components/button"; @@ -173,7 +173,7 @@ export const OrganisationPage: FC = () => {
- = ({ }) => { const { t } = useTranslation(); const { iconSize } = useContext(SettingsContext); - const [showFilter, setShowFilter] = useState(false); + const [showFilter, setShowFilter] = useState(true); const [showFilterInfo, setShowFilterInfo] = useState(false); const [inputFilter, setInputFilter] = useState({}); const ref = useRef(null); @@ -152,6 +150,14 @@ export const SearchFilters: FC = ({ }; }, [showFilter]); + useEffect(() => { + if (window.innerWidth < 600) { + setShowFilter(false); + } else { + setShowFilter(true); + } + }, []); + const selected = (key: string, facetValue: SearchFacetValue) => { return search.facetSelected(key, facetValue.resource); }; @@ -175,17 +181,24 @@ export const SearchFilters: FC = ({ setShowFilter(!showFilter); } - const MobileButton = ({ className }: { className?: string }) => { + const ToggleFilterButton = ({ className }: { className?: string }) => { return (
+ {/* Mobile clear filters button */} + {search.request.facetValues && + search.request.facetValues.length >= 2 && ( + )}
diff --git a/features/search/search-filters/search-checkbox-filter/index.tsx b/features/search/search-filters/search-checkbox-filter/index.tsx index d414600d1..da53390a7 100644 --- a/features/search/search-filters/search-checkbox-filter/index.tsx +++ b/features/search/search-filters/search-checkbox-filter/index.tsx @@ -52,8 +52,8 @@ export function SearchCheckboxFilter({ />
); diff --git a/features/search/search-filters/search-filter/index.tsx b/features/search/search-filters/search-filter/index.tsx index b2181738e..ce0cb1f46 100644 --- a/features/search/search-filters/search-filter/index.tsx +++ b/features/search/search-filters/search-filter/index.tsx @@ -1,10 +1,11 @@ import FocusTrap from "focus-trap-react"; import useTranslation from "next-translate/useTranslation"; -import { FC, PropsWithChildren, useContext, useEffect, useState } from "react"; +import { FC, PropsWithChildren, useEffect, useState } from "react"; import ChevronDownIcon from "@/assets/icons/chevron-down.svg"; +import ChevronUpIcon from "@/assets/icons/chevron-up.svg"; +import { Button } from "@/components/button"; import { useClickOutside } from "@/hooks/use-click-outside"; -import { SettingsContext } from "@/providers/settings-provider"; export interface SearchFilterProps { title: string | null; @@ -20,7 +21,6 @@ export const SearchFilter: FC> = ({ }) => { const [open, setOpen] = useState(false); const [trapFocus, setTrapFocus] = useState(false); - const { iconSize } = useContext(SettingsContext); const ref = useClickOutside(() => handleOpen(false)); const { t } = useTranslation("common"); @@ -42,7 +42,10 @@ export const SearchFilter: FC> = ({ ref={ref} onKeyDown={(ev) => ev.key === "Escape" && handleOpen(false)} > - + className={ + open + ? "active" + : "bg-white hover:bg-transparent focus-visible:bg-transparent" + } + icon={open ? ChevronUpIcon : ChevronDownIcon} + iconPosition="right" + /> +
{children}
diff --git a/features/search/search-filters/search-select-filter/index.tsx b/features/search/search-filters/search-select-filter/index.tsx index cf29becaa..6ea7eaaa5 100644 --- a/features/search/search-filters/search-select-filter/index.tsx +++ b/features/search/search-filters/search-select-filter/index.tsx @@ -47,7 +47,7 @@ export const SearchSelectFilter: FC = ({ >
{ * Initial load of search results and facets */ initialLoad = async () => { - const loadTasks = [this.doSearch(false, true, false, true)]; + const loadTasks = [this.doSearch(false, false, false, true)]; if (this.state.fetchAllFacetsOnMount) { loadTasks.push(this.fetchAllFacets()); diff --git a/styles/base.css b/styles/base.css index e0baccc39..aac70c5a9 100644 --- a/styles/base.css +++ b/styles/base.css @@ -107,7 +107,7 @@ body { group-hover:bg-brown-800 group-hover:bg-whiteOpaque5 group-focus:bg-whiteOpaque5 [&_path]:fill-brown-600; } .button--secondary.active { - @apply bg-brown-600 text-white [&_path]:fill-white [&_svg]:rotate-180; + @apply bg-brown-600 text-white [&_path]:fill-white; } .button--light { @apply bg-brown-200 text-brown-600 hover:bg-textSecondary focus-visible:bg-textSecondary hover:text-brown-100 focus-visible:text-brown-100 @@ -134,6 +134,9 @@ body { @apply gap-sm px-md py-[0.125rem] text-sm; } .button--small { + @apply gap-sm px-md py-sm text-sm; + } + .button--medium { @apply gap-sm px-md py-[0.375rem] text-sm; } .button--large { diff --git a/types/entrystore-js.d.ts b/types/entrystore-js.d.ts index d36ae8d26..b9ae04401 100644 --- a/types/entrystore-js.d.ts +++ b/types/entrystore-js.d.ts @@ -37,10 +37,11 @@ declare module "@entryscape/entrystore-js" { facetLimit(_limit: number): this; // Search field methods + or(_fields: { [key: string]: string }): this; title(_val: string | string[], _modifier?: boolean | string): this; description(_val: string | string[], _modifier?: boolean | string): this; + tagLiteral(_val: string | string[], _modifier?: boolean | string): this; all(_val: string | string[], _modifier?: boolean | string): this; - // Property search methods literalProperty( _predicate: string, diff --git a/utilities/entrystore/entrystore-helpers.ts b/utilities/entrystore/entrystore-helpers.ts index f6ed25b01..012acf82a 100644 --- a/utilities/entrystore/entrystore-helpers.ts +++ b/utilities/entrystore/entrystore-helpers.ts @@ -5,8 +5,6 @@ import { Metadata, MetadataValue, } from "@entryscape/entrystore-js"; -// @ts-expect-error no types -import lucene from "lucene"; import { Translate } from "next-translate"; import { SettingsUtil } from "@/env"; @@ -263,28 +261,6 @@ export const resourcesSearch = (resources: string[], es: any): Promise => { }); }; -export function luceneFriendlyQuery(query: string): string { - if (query === "AND" || query === "NOT" || query === "OR") return "*"; - try { - const ast = lucene.parse(query); - let q = lucene.toString(ast); - q = q - .replace(/\\~ /g, "~") - .replace(/\+-/g, "") - .replace(/ NOT -/g, " NOT ") - .replace(/ AND NOT /g, "+NOT+") - .replace(/ OR NOT /g, "+NOT+") - .replace(/ OR /g, "+OR+") - .replace(/ AND /g, "+AND+") - .replace(/ NOT /g, "+-"); - if (q.indexOf('"') === -1) q = q.replace(/ /g, "+AND+"); - return q || "*"; - } catch { - // eslint-disable-next-line no-useless-escape - return query.replace(/[\!\*\-\+\&\|\(\)\[\]\{\}\^\\~\?\:\"]/g, "").trim(); - } -} - // ============================================================================ // Formatting Helpers // ============================================================================ diff --git a/utilities/entrystore/entrystore.service.ts b/utilities/entrystore/entrystore.service.ts index 2bd8c9a79..07cbe6331 100644 --- a/utilities/entrystore/entrystore.service.ts +++ b/utilities/entrystore/entrystore.service.ts @@ -43,7 +43,6 @@ import { import { DCATData } from "../dcat-utils"; import { parseEmail, - luceneFriendlyQuery, termsPathResolver, specsPathResolver, } from "./entrystore-helpers"; @@ -154,9 +153,8 @@ export class EntrystoreService { entry?: Entry, ): Promise { const hits: SearchHit[] = []; - let query = luceneFriendlyQuery(request.query || "*"); + const query = request.query; const lang = request.language || "sv"; - const esQuery = this.entryStore.newSolrQuery(); esQuery.publicRead(true); @@ -291,11 +289,15 @@ export class EntrystoreService { .publicRead(true) .list(); - query = luceneFriendlyQuery(query); - // Set query text if (query) { - esQuery.all(`${query}`); + // This is a bit of a hack to make search work for sentences and partial words + esQuery.or({ + title: query, + description: query, + "tag.literal": query, + all: query, + }); } try { diff --git a/yarn.lock b/yarn.lock index 982ec4ebc..2e7e100ca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6921,7 +6921,6 @@ __metadata: https-proxy-agent: "npm:^5.0.1" husky: "npm:^8.0.3" lint-staged: "npm:^15.2.0" - lucene: "npm:^2.1.1" meilisearch: "npm:^0.27.0" next: "npm:13.5.1" next-absolute-url: "npm:^1.2.2" @@ -10941,13 +10940,6 @@ __metadata: languageName: node linkType: hard -"lucene@npm:^2.1.1": - version: 2.1.1 - resolution: "lucene@npm:2.1.1" - checksum: 10/9e5b922bb4aa35a22534b186c924a498deaf153813c0c2ed2dd7a4a27806ec25feea2e0b3691f3ae7b39826522af3c411aa24645646e0175ac18f4537add289e - languageName: node - linkType: hard - "make-error@npm:^1, make-error@npm:^1.1.1": version: 1.3.6 resolution: "make-error@npm:1.3.6"