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 (
- <>
-
-
-
-
-
-
-
- {!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) => (
-