Skip to content

Commit

Permalink
feat: include wild card search on keywords and research domains in gl…
Browse files Browse the repository at this point in the history
…obal search
  • Loading branch information
dmijatovic committed Nov 12, 2022
1 parent 50f8484 commit d98c1ec
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 49 deletions.
82 changes: 59 additions & 23 deletions database/100-create-api-views.sql
Original file line number Diff line number Diff line change
Expand Up @@ -1157,29 +1157,6 @@ BEGIN
END
$$;


-- Global search
CREATE FUNCTION global_search()
RETURNS TABLE
(name VARCHAR, slug VARCHAR, source TEXT, is_published BOOLEAN )
LANGUAGE plpgsql
STABLE
AS
$$
BEGIN
RETURN QUERY
SELECT software.brand_name as name, software.slug AS slug, 'software' as source, software.is_published
FROM software
UNION
SELECT project.title as name, project.slug AS slug, 'projects' as source, project.is_published
FROM project
UNION
SELECT organisation.name, organisation.slug AS slug, 'organisations' as source, is_published
FROM organisation;
END
$$;


-- TOTAL COUNTS FOR HOMEPAGE
-- software_cnt, project_cnt, organisation_cnt
-- this rpc returns json object instead of array
Expand Down Expand Up @@ -1339,3 +1316,62 @@ BEGIN
;
END
$$;

-- GLOBAL SEARCH
-- we use search_text to concatenate all values to use
CREATE FUNCTION global_search() RETURNS TABLE(
slug VARCHAR,
name VARCHAR,
source TEXT,
is_published BOOLEAN,
search_text TEXT
) LANGUAGE plpgsql STABLE AS
$$
BEGIN RETURN QUERY
-- SOFTWARE search item
SELECT
software_search.slug,
software_search.brand_name AS name,
'software' AS "source",
software_search.is_published,
CONCAT_WS(
' ',
software_search.brand_name,
software_search.short_statement,
software_search.keywords_text
) AS search_text
FROM
software_search()
UNION
-- PROJECT search item
SELECT
project_search.slug,
project_search.title AS name,
'projects' AS "source",
project_search.is_published,
CONCAT_WS(
' ',
project_search.title,
project_search.subtitle,
project_search.keywords_text,
project_search.research_domain_text
) AS search_text
FROM
project_search()
UNION
-- ORGANISATION search item
SELECT
organisation.slug,
organisation."name",
'organisations' AS "source",
TRUE AS is_published,
CONCAT_WS(
' ',
organisation."name",
organisation.website
) AS search_text
FROM
organisation
;
END
$$;
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import logger from '~/utils/logger'
import {createJsonHeaders} from '~/utils/fetchHelpers'

export type GlobalSearchResults = {
slug: string,
name: string,
source: string,
is_published?: boolean,
search_text?: string
} | undefined

/**
*
* @param searchText
Expand All @@ -9,7 +17,7 @@ import {createJsonHeaders} from '~/utils/fetchHelpers'
export async function getGlobalSearch(searchText: string, token: string,) {
try {
// call the function query
const query = `rpc/global_search?name=ilike.*${searchText}*&limit=10`
const query = `rpc/global_search?search_text=ilike.*${searchText}*&limit=30`
let url = `/api/v1/${query}`

const resp = await fetch(url, {
Expand Down

This file was deleted.

40 changes: 21 additions & 19 deletions frontend/components/GlobalSearchAutocomplete/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
import React, {useEffect, useState} from 'react'
import {ClickAwayListener} from '@mui/base'
import {useRouter} from 'next/router'
import {getGlobalSearch} from '~/components/GlobalSearchAutocomplete/globalSearchAutocomplete.api'

import {useAuth} from '~/auth'
import {getGlobalSearch,GlobalSearchResults} from '~/components/GlobalSearchAutocomplete/globalSearchAutocomplete.api'

import EnterkeyIcon from '~/components/icons/enterkey.svg'
import {useDebounce} from '~/utils/useDebounce'

import TerminalIcon from '@mui/icons-material/Terminal'
import ListAltIcon from '@mui/icons-material/ListAlt'
import BusinessIcon from '@mui/icons-material/Business'
Expand Down Expand Up @@ -128,38 +128,40 @@ export default function GlobalSearchAutocomplete(props: Props) {
className={`${props.className} relative z-10 flex w-full xl:w-52 xl:max-w-[320px] focus-within:w-full duration-700`}>
<div className="absolute top-[14px] left-3 pointer-events-none">
{/* Search Icon */}
<svg width="16" height="16" viewBox="0 0 14 14" fill="none"
xmlns="http://www.w3.org/2000/svg">
<svg width="16" height="16" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M5.72217 0.34082C2.86783 0.34082 0.559204 2.64944 0.559204 5.50378C0.559204 8.35812 2.86783 10.6667 5.72217 10.6667C6.74123 10.6667 7.68438 10.3678 8.48397 9.86003L12.2138 13.5899L13.5046 12.2992L9.82216 8.62624C10.4841 7.75783 10.8851 6.68182 10.8851 5.50378C10.8851 2.64944 8.57651 0.34082 5.72217 0.34082ZM5.72217 1.55564C7.90859 1.55564 9.67031 3.31735 9.67031 5.50378C9.67031 7.69021 7.90859 9.45193 5.72217 9.45193C3.53574 9.45193 1.77402 7.69021 1.77402 5.50378C1.77402 3.31735 3.53574 1.55564 5.72217 1.55564Z"
fill="#707070"/>
</svg>
</div>
<input className="px-2 pl-8 py-2 bg-transparent rounded-sm border border-white border-opacity-50 focus:outline-0
w-full focus:bg-white focus:text-black
duration-200"
placeholder="Search or jump to..."
autoComplete="off"
value={inputValue}
onChange={handleChange}
onKeyDown={handleKeyDown}
type="search"
onFocus={focusSearch}
<input className="px-2 pl-8 py-2 bg-transparent rounded-sm border border-white border-opacity-50 focus:outline-0 w-full focus:bg-white focus:text-black duration-200"
placeholder="Search or jump to..."
autoComplete="off"
value={inputValue}
onChange={handleChange}
onKeyDown={handleKeyDown}
type="search"
onFocus={focusSearch}
/>

{isOpen &&
<div
className="shadow-xl absolute top-[50px] w-full left-0 bg-white text-black py-2 rounded">
className="shadow-xl absolute top-[50px] w-full left-0 bg-white text-black py-2 rounded-sm"
style={{
maxHeight: '50vh',
overflow: 'auto'
}}
>
{!hasResults &&
<div className="px-4 py-3 font-normal bg-base-200 mb-2 ">
<span className="animate-pulse">No results...</span>
</div>}
{searchResults.map((item, index) =>
<div key={index}
className={`${selected === index ? 'bg-base-200' : ''} flex gap-2 p-2 cursor-pointer transition justify-between items-center`}
onClick={handleClick}
onMouseEnter={() => setSelected(index)}
onTouchStart={() => setSelected(index)}
className={`${selected === index ? 'bg-base-200' : ''} flex gap-2 p-2 cursor-pointer transition justify-between items-center`}
onClick={handleClick}
onMouseEnter={() => setSelected(index)}
onTouchStart={() => setSelected(index)}
>
<div className="flex gap-3 w-full">
{/*icon*/}
Expand Down

0 comments on commit d98c1ec

Please sign in to comment.