From 2574f9e5c8dca9b2833dc3e8308ca0ded9906162 Mon Sep 17 00:00:00 2001 From: Keegan Kavanagh Date: Fri, 26 Aug 2022 14:43:39 -0700 Subject: [PATCH 1/4] added new search package --- package.json | 3 +- src/assets/lib/bootstrap-2.3.0.css | 4 +- src/assets/stylesheets/_search.less | 1 - src/components/search/InlineSearch.tsx | 265 ------------------------- src/components/search/SearchStyles.tsx | 72 ------- src/components/search/searchUtil.ts | 22 -- src/components/search/useSearch.tsx | 97 --------- src/navigation/PortalifiedSearch.tsx | 3 +- src/pages/index.tsx | 12 +- src/pages/search.tsx | 210 -------------------- 10 files changed, 14 insertions(+), 675 deletions(-) delete mode 100644 src/components/search/InlineSearch.tsx delete mode 100644 src/components/search/SearchStyles.tsx delete mode 100644 src/components/search/searchUtil.ts delete mode 100644 src/components/search/useSearch.tsx delete mode 100644 src/pages/search.tsx diff --git a/package.json b/package.json index 5af71acc..b8acdf39 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ }, "dependencies": { "@reach/router": "^1.2.1", + "@saasquatch/squatch-search": "^0.1.0-1", "@saasquatch/visual-dev": "^1.0.2", "@types/dompurify": "^2.0.2", "anchor-js": "^3.2.2", @@ -51,7 +52,7 @@ "serve": "^11.3.2", "slug": "0.9.1", "swagger-parser": "^3.4.1", - "use-debounce": "^5.1.0", + "use-debounce": "^8.0.3", "webpack": "^4.20.2", "zenscroll": "^3.3.0" }, diff --git a/src/assets/lib/bootstrap-2.3.0.css b/src/assets/lib/bootstrap-2.3.0.css index 5d43bcd2..08a1ccdb 100644 --- a/src/assets/lib/bootstrap-2.3.0.css +++ b/src/assets/lib/bootstrap-2.3.0.css @@ -142,7 +142,7 @@ input[type="submit"] { -webkit-appearance: button; } -label, +/* label, select, button, input[type="button"], @@ -151,7 +151,7 @@ input[type="submit"], input[type="radio"], input[type="checkbox"] { cursor: pointer; -} +} */ input[type="search"] { -webkit-box-sizing: content-box; diff --git a/src/assets/stylesheets/_search.less b/src/assets/stylesheets/_search.less index 8c29975c..af00445e 100644 --- a/src/assets/stylesheets/_search.less +++ b/src/assets/stylesheets/_search.less @@ -30,7 +30,6 @@ } .search-results { - padding-top: 50px; width: 520px; margin: 0 auto; .search-spinner { diff --git a/src/components/search/InlineSearch.tsx b/src/components/search/InlineSearch.tsx deleted file mode 100644 index 4dc4fe34..00000000 --- a/src/components/search/InlineSearch.tsx +++ /dev/null @@ -1,265 +0,0 @@ -import React, { - RefObject, - useCallback, - useEffect, - useRef, - useState, -} from "react"; -import Tippy from "@tippyjs/react/headless"; -import hotkeys from "hotkeys-js"; -import { useHistory } from "react-router"; - -import { useSearch } from "./useSearch"; -import * as Styles from "./SearchStyles"; -import { sanitizeGoogleSearchLink, isBlank } from "./searchUtil"; -import useBrowserEffect from "src/util/useBrowserEffect"; - -export function InlineSearch({ Input = Styles.DefaultInput, sideBar = false }) { - if (typeof document === "undefined") { - return
; - } - const history = useHistory(); - const { query, response, setQuery, cat, setCat, setStartIndex } = useSearch(); - const showTippy = !isBlank(query); - - const [visible, setVisible] = useState(false); - const [selectedIdx, setSelectedIndex] = useState(0); - - const maxResultsSize = response?.items?.length || 0; - - useEffect(() => { - setSelectedIndex(0); - }, [query]); - useBrowserEffect(() => { - hotkeys("esc", function (event, handler) { - // event.preventDefault(); - setVisible(false); - }); - return () => hotkeys.unbind("esc"); - }, [setVisible]); - const inputEl = useRef(null); - const resultsEl = useRef(null); - const contains = useCallback( - (el) => { - if (inputEl.current && inputEl.current.contains(el)) { - return true; - } - if (resultsEl.current && resultsEl.current.contains(el)) { - return true; - } - }, - [inputEl.current, resultsEl.current] - ); - useBrowserEffect(() => { - const handler = (e) => { - const { target } = e; - if (target) { - if (contains(target)) { - // If descendant of the input box of results - // Do nothing - } else { - // If click anywhere else - // Hide the search results if they are open; - setVisible(false); - } - } - }; - - document.documentElement.addEventListener("click", handler); - return () => document.documentElement.removeEventListener("click", handler); - }, [setVisible, contains]); - - const onkeypressed = (evt) => { - var code = evt.charCode || evt.keyCode; - if (code == 27) { - // Escape key -- cancel query - evt.preventDefault(); - setQuery(""); - } else if ( - code === 38 - // && selectedIdx >= -1 - ) { - evt.preventDefault(); - setSelectedIndex(selectedIdx - 1); - } else if ( - code === 40 - // && selectedIdx < maxResultsSize - ) { - evt.preventDefault(); - setSelectedIndex(selectedIdx + 1); - } else if (code === 13) { - // enter key - evt.preventDefault(); - const item = response?.items[selectedIdx]; - const url = sanitizeGoogleSearchLink(item.link); - history.push(url); - evt.target.blur(); - setVisible(false); - } - }; - const hide = useCallback(() => setVisible(false), [setVisible]); - - const delayedHide = useCallback(() => { - // On blur prevents race condition between clicking on a result and hiding the search results - setTimeout(() => { - setVisible(false); - }, 100); - }, [setVisible]); - - return ( - - ( - - {!response && ( -
-

Searching Help Center...

- -
- )} - {response && ( - - {setVisible(false); setQuery("");}} - childRef={resultsEl} - /> - - )} -
- )} - > - setVisible(true)} - onFocus={(e) => setVisible(true)} - // onBlur={(e) => delayedHide()} - onChange={(e) => setQuery(e.target.value)} - autoComplete="off" - ref={inputEl} - /> -
-
- ); -} - -export function InlineResults({ - response, - setStartIndex, - query, - selectedIdx, - close, - childRef, -}: { - response: any; - setStartIndex: (next: number) => void; - query: string; - selectedIdx: number; - close: () => void; - childRef: RefObject; -}) { - const { items, queries, searchInformation } = response; - - // Some pages have `meta` tags via `pagemap.metatags`, and things like ios/android don't. - const getTitle = (item) => { - const sanitize = (title: string) => - title.replace(" | SaaSquatch Documentation", ""); - try { - return sanitize(items.pagemap.metatags[0].title); - } catch (e) {} - return sanitize(item.htmlTitle); - }; - - return ( -
-
- Press Esc to{" "} - { - e.preventDefault(); - close(); - }} - > - close - - . -
- {items && - items - .filter((item) => item) - .map((item, idx) => ( - - `, - }} - /> - - - ))} - {items && ( - - {searchInformation.totalResults} total results found in{" "} - {searchInformation.formattedSearchTime} seconds - - )} - - {queries?.previousPage && ( - setStartIndex(queries.previousPage[0].startIndex)} - > - Previous - - )} - - {queries?.nextPage && ( - setStartIndex(queries.nextPage[0].startIndex)} - > - Next - - )} - - - {!items && isBlank(query) && ( -
-

What are you looking for?

-
- )} - {!items && !isBlank(query) && ( -
-

- No matching Docs! -

-

- Looks like we couldn't find any Help Center page that matches your - search term "{query}" -

-
- )} -
- ); -} diff --git a/src/components/search/SearchStyles.tsx b/src/components/search/SearchStyles.tsx deleted file mode 100644 index 4bb641f3..00000000 --- a/src/components/search/SearchStyles.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import React from "react"; -import styled from "styled-components"; -import { HashLink } from "react-router-hash-link"; - -export const ItemRow = styled(HashLink)` - display: block; - color: #000; - padding: 8px; - margin: 5px 0; - border-bottom: 1px solid #ddd; - - background: ${(props) => (props.selected ? "#e0e0e0" : "white")}; - &:hover { - background: #eee; - } -`; -export const DefaultInput = styled.input` - width: 75%; -`; - -export const ItemTitle = styled.div` - margin: 5px 0; - font-weight: bold; - color: #000; -`; -export const ItemBody = styled.div` - font-size: 0.9em; - color: #444; - word-wrap: break-word; - - br { - /* Hides google's automatic
additions */ - display: none; - } -`; -export const ResultsSummary = styled.p` - color: #333; -`; -export const Pagination = styled.div` - border-top: 1px solid #ccc; -`; - -export const PagerButton = styled.a` - padding-right: 10px; - cursor: pointer; -`; -export const NoResults = styled.div``; - -export const PopOver = styled.div<{ sideBar: boolean }>` - background: #fff; - border: 1px solid #eee; - box-shadow: 0px 0px 28px -6px rgba(0, 0, 0, 1); - border-radius: 5px; - padding: 10px; - z-index: 999; - overflow-y: scroll; - width: ${(props) => (props.sideBar ? "18vw" : "70vw")}; - min-width: 200px; -`; - -export const Inline = styled.div``; - -export const styledLink = styled.a` - color: #357732 !important; - &:hover { - text-decoration: underline !important; - } -`; - -export const Container = styled.div<{ sideBar: boolean }>` - height: ${(props) => (props.sideBar ? "75vh" : "35vh")}; -`; diff --git a/src/components/search/searchUtil.ts b/src/components/search/searchUtil.ts deleted file mode 100644 index 4a4b7ccb..00000000 --- a/src/components/search/searchUtil.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Finds the Query param with the given name. - * - * Straight stolen from: http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript - * - */ -export function getParameterByName(name) { - name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]"); - var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"), - results = regex.exec(window.location.search); - return results === null - ? "" - : decodeURIComponent(results[1].replace(/\+/g, " ")); -} - -export function sanitizeGoogleSearchLink(link) { - return link.replace("https://docs.referralsaasquatch.com", "").replace("https://docs.saasquatch.com", ""); -} - -export function isBlank(str) { - return !str || /^\s*$/.test(str); -} diff --git a/src/components/search/useSearch.tsx b/src/components/search/useSearch.tsx deleted file mode 100644 index 128f8bde..00000000 --- a/src/components/search/useSearch.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import { useEffect, useState } from "react"; -import { useSiteData } from "react-static"; -import { useDebouncedCallback } from "use-debounce"; - -import { getParameterByName } from "components/search/searchUtil"; - -export function useSearch() { - const [response, setResponse] = useState(null); - - // Only run in the browser - const jQuery = require("jquery"); - const { windowDotEnv } = useSiteData(); - - // var categoryFilter = "more:pagemap:metatags-type:jsReference"; - let initialIndex = 0; - try { - initialIndex = parseInt(getParameterByName("startIndex")); - } catch (e) {} - const initialState = { - query: getParameterByName("q"), - cat: getParameterByName("cat"), - startIndex: initialIndex, - }; - const [{ query, cat, startIndex }, setState] = useState(initialState); - function setQuery(newValue: string) { - setState({ - // If you change the query, go back to page 0 - startIndex: 0, - cat, - query: newValue, - }); - } - function setCat(cat: string) { - setState({ - query, - cat, - // If you change the category, go back to page 0 - startIndex: 0, - }); - } - function setStartIndex(startIndex) { - setState({ - query, - cat, - startIndex, - }); - } - // jQuery(".js-search-form input[name=cat]").val([cat]); - let privateQuery; - if (cat && cat.length > 1) { - // privateQuery = query + " more:pagemap:metatags-type:" + cat; - privateQuery = query + " more:pagemap:metatags-docsCategory:" + cat; - } else { - privateQuery = query; - } - let dataObj = { - q: privateQuery, - cx: windowDotEnv.GCSE_CX, - key: windowDotEnv.GCSE_KEY, - format: "json", - start: undefined, - }; - if (startIndex) { - dataObj.start = startIndex; - } - - const debounced = useDebouncedCallback( - // function - (value) => { - jQuery.ajax({ - url: "https://www.googleapis.com/customsearch/v1", - dataType: "jsonp", - jsonp: "callback", - data: value, - // Work with the response - success: function (response) { - setResponse(response); - }, - }); - }, - // delay in ms - 100 - ); - - useEffect(() => { - debounced.callback(dataObj); - }, [query, cat, startIndex]); - - return { - response, - query, - setQuery, - cat, - setCat, - setStartIndex, - }; -} diff --git a/src/navigation/PortalifiedSearch.tsx b/src/navigation/PortalifiedSearch.tsx index af8bce8b..9089bdbf 100644 --- a/src/navigation/PortalifiedSearch.tsx +++ b/src/navigation/PortalifiedSearch.tsx @@ -3,7 +3,6 @@ import ReactDOM from "react-dom"; import { HashLink as Link } from "react-router-hash-link"; import * as Styles from "./NavStyles"; -import { InlineSearch } from "components/search/InlineSearch"; import { modalRoot } from "./NavigationSidebar"; export function PortalifiedSearch() { @@ -47,7 +46,7 @@ class PortalifiedSearchForBrowser extends React.Component { - +
Need to put Search in here from new package
, this.el diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 02fc18e8..9d233a1b 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,8 +1,9 @@ +import { getBreadcrumb, isBlank, Search, useSearch } from "@saasquatch/squatch-search"; +import { SearchProps } from "@saasquatch/squatch-search/dist/components/Search/Search"; import React, { useEffect } from "react"; import styled from "styled-components"; import Meta from "../components/Meta"; -import { InlineSearch } from "../components/search/InlineSearch"; const Hero = styled.div` background: transparent; @@ -26,6 +27,11 @@ export default function render() { // Old old old redirects baced on anchors if (document) legacyAnchors(); }); + const searchProps: SearchProps = { + onGetBreadcrumbs: getBreadcrumb, + onIsBlank: isBlank, + useSearch: useSearch() + } return ( <> @@ -39,8 +45,8 @@ export default function render() { choose a help center section on your left to get started.{" "}

-
- +
+
diff --git a/src/pages/search.tsx b/src/pages/search.tsx deleted file mode 100644 index 3acc620c..00000000 --- a/src/pages/search.tsx +++ /dev/null @@ -1,210 +0,0 @@ -import React from "react"; -import Tippy from "@tippyjs/react/headless"; - -import * as Styles from "../components/search/SearchStyles"; -import Meta from "../components/Meta"; -import { useSearch } from "../components/search/useSearch"; -import { isBlank } from "components/search/searchUtil"; - -export default function render() { - if (typeof document === "undefined") { - return
; - } - const { query, response, setQuery, cat, setCat, setStartIndex } = useSearch(); - - const entry = { - title: "Search results for " + query, - }; - return ( - <> - -
-
-
-

Help Center Search

-
-
- setQuery(e.target.value)} - /> - -
-
- - - - -
-
- - - Back to Help Center - -
- -
-
- {!response && ( -
-

Searching Help Center...

- -
- )} - {response && response.error && ( -
-

{response.error.message}

-
- )} - {response && !response.error && ( - - )} -
-
-
-
- - ); -} - -export type InputComponent = typeof Styles.DefaultInput; - -export function Results({ response, setStartIndex, query }) { - const { items, queries, searchInformation } = response; - - // Some pages have `meta` tags via `pagemap.metatags`, and things like ios/android don't. - const getTitle = (item) => { - try { - return items.pagemap.metatags[0].title; - } catch (e) {} - return item.htmlTitle; - }; - - return ( - <> - {items && - items - .filter((item) => item) - .map((item) => ( -
- -
`, - }} - /> -
-
- -
- ))} - {items && ( -

- {searchInformation.totalResults} total results found in{" "} - {searchInformation.formattedSearchTime} seconds -

- )} - - - {!items && isBlank(query) && ( -
-

What are you looking for?

-
- )} - {!items && !isBlank(query) && ( -
-

- No matching Docs! -

-

- Looks like we couldn't find any Help Center page that matches your - search term "{query}" -

-
- )} - - ); -} From cb9fd09e6064c83e40856ca9f04fb53c20bfde2c Mon Sep 17 00:00:00 2001 From: Noah Clarke Date: Fri, 26 Aug 2022 14:48:27 -0700 Subject: [PATCH 2/4] fix search radio buttons --- src/assets/lib/bootstrap-2.3.0.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/assets/lib/bootstrap-2.3.0.css b/src/assets/lib/bootstrap-2.3.0.css index 08a1ccdb..66cb231f 100644 --- a/src/assets/lib/bootstrap-2.3.0.css +++ b/src/assets/lib/bootstrap-2.3.0.css @@ -1868,7 +1868,7 @@ input.search-query { border-radius: 14px 0 0 14px; } -.form-search input, +/* .form-search input, */ .form-inline input, .form-horizontal input, .form-search textarea, @@ -1902,7 +1902,7 @@ input.search-query { display: none; } -.form-search label, +/* .form-search label, */ .form-inline label, .form-search .btn-group, .form-inline .btn-group { @@ -6381,7 +6381,7 @@ a.badge:focus { filter: alpha(opacity=90); } -..carousel-caption h4, +.carousel-caption h4, .carousel-caption p { line-height: 20px; color: #fff; From 6b67002047cc9ecc66d13ea23641922045189a3c Mon Sep 17 00:00:00 2001 From: Keegan Kavanagh Date: Wed, 31 Aug 2022 11:13:12 -0700 Subject: [PATCH 3/4] search bar working --- package.json | 2 +- src/containers/single/programLibrary.tsx | 2 +- src/navigation/PortalifiedSearch.tsx | 22 +++++++++++++++++----- src/pages/developer/purchase-object.tsx | 1 + src/pages/index.tsx | 6 +++--- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index b8acdf39..c23945c5 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ }, "dependencies": { "@reach/router": "^1.2.1", - "@saasquatch/squatch-search": "^0.1.0-1", + "@saasquatch/squatch-search": "^0.1.0-16", "@saasquatch/visual-dev": "^1.0.2", "@types/dompurify": "^2.0.2", "anchor-js": "^3.2.2", diff --git a/src/containers/single/programLibrary.tsx b/src/containers/single/programLibrary.tsx index 8f498b8d..883d3ad3 100644 --- a/src/containers/single/programLibrary.tsx +++ b/src/containers/single/programLibrary.tsx @@ -37,7 +37,7 @@ const CardContainer = styled.div` row-gap: 24px; `; -const ProgramCard = styled(Card)` +const ProgramCard = styled(Card as any)` max-height: 214px; min-height: 214px; margin-bottom: 0; diff --git a/src/navigation/PortalifiedSearch.tsx b/src/navigation/PortalifiedSearch.tsx index 9089bdbf..ed4a46d0 100644 --- a/src/navigation/PortalifiedSearch.tsx +++ b/src/navigation/PortalifiedSearch.tsx @@ -4,15 +4,26 @@ import { HashLink as Link } from "react-router-hash-link"; import * as Styles from "./NavStyles"; import { modalRoot } from "./NavigationSidebar"; +import { isBlank, Search, SearchProps, useSearch } from "@saasquatch/squatch-search"; +import styled from "styled-components"; export function PortalifiedSearch() { + const searchProps: SearchProps = { + onIsBlank: isBlank, + useSearch: useSearch(), + sidebar: true + } if (typeof document === "undefined") { return
; } - return ; + return ; } -class PortalifiedSearchForBrowser extends React.Component { +const SearchContainer = styled.div` + max-width: 470px; +`; + +class PortalifiedSearchForBrowser extends React.Component { el: HTMLDivElement; constructor(props) { super(props); @@ -33,6 +44,7 @@ class PortalifiedSearchForBrowser extends React.Component { modalRoot.removeChild(this.el); } render() { + const { searchProps } = this.props; return ReactDOM.createPortal( <> @@ -45,9 +57,9 @@ class PortalifiedSearchForBrowser extends React.Component { - -
Need to put Search in here from new package
-
+ + + , this.el ); diff --git a/src/pages/developer/purchase-object.tsx b/src/pages/developer/purchase-object.tsx index f689e9af..4574472a 100644 --- a/src/pages/developer/purchase-object.tsx +++ b/src/pages/developer/purchase-object.tsx @@ -56,6 +56,7 @@ function useSchema(schema) { useEffect(() => { let parser = new $RefParser(); + // @ts-ignore parser .dereference(schema, { resolve: { diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 9d233a1b..766b07d8 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,4 +1,4 @@ -import { getBreadcrumb, isBlank, Search, useSearch } from "@saasquatch/squatch-search"; +import { isBlank, Search, useSearch } from "@saasquatch/squatch-search"; import { SearchProps } from "@saasquatch/squatch-search/dist/components/Search/Search"; import React, { useEffect } from "react"; import styled from "styled-components"; @@ -28,9 +28,9 @@ export default function render() { if (document) legacyAnchors(); }); const searchProps: SearchProps = { - onGetBreadcrumbs: getBreadcrumb, onIsBlank: isBlank, - useSearch: useSearch() + useSearch: useSearch(), + background: true } return ( <> From 72e0c01ff6cfc545ffc628a00469cd035672e943 Mon Sep 17 00:00:00 2001 From: Keegan Kavanagh Date: Wed, 31 Aug 2022 12:56:35 -0700 Subject: [PATCH 4/4] added container for search on main page --- src/pages/index.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 766b07d8..07ca2e06 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -22,6 +22,11 @@ const Sublogo = styled.img` max-width: 250px; `; +const SearchContainerDiv = styled.div` + max-width: 750px; + margin: auto; +` + export default function render() { useEffect(() => { // Old old old redirects baced on anchors @@ -45,9 +50,9 @@ export default function render() { choose a help center section on your left to get started.{" "}

-
+ -
+ );