diff --git a/assets/js/index.js b/assets/js/index.js index 27b0c0bb2ac..b333cde4044 100644 --- a/assets/js/index.js +++ b/assets/js/index.js @@ -68,71 +68,176 @@ if(main && scrollBtn) { observer.observe(main); } -function handleSearch(inputSelector) { - const searchConfig = { - inputSelector: inputSelector, - typesenseCollectionName: 'docsearch', - typesenseServerConfig: { - nodes: [{ - host: 'cgnvrk0xwyj9576lp-1.a1.typesense.net', - port: '443', - protocol: 'https' - }], - apiKey: 'GHQK6od8KfpvTEh4YpA113gUc2dU5fGR' - }, - typesenseSearchParams: { - query_by: 'hierarchy.lvl0,hierarchy.lvl1,url_without_anchor', - query_by_weight: '100,50,1', - sort_by: "_text_match:desc,item_priority:desc", - prioritize_token_position: true, - group_by: "url_without_anchor", - group_limit: 1 - }, - autocompleteOptions: { - autoselect: false, - debug: false, - hint: false - } - }; +// Inkeep START - const search = docsearch(searchConfig); +const INKEEP_API_KEY = "b17e5b4e252d7ce29b48a48a3dcba6fcfdc045680e8ea576"; +const INKEEP_INTEGRATION_ID = "cm3ogfzp4003f29brrf16r6gm"; +const INKEEP_ORGANIZATION_ID = "org_yjUXfeVC1tTVMIoY"; - let opened = false; - search.autocomplete.on('autocomplete:shown', (e, a, b, c) => { - opened = true; - }); - search.autocomplete.on('autocomplete:closed', () => { - opened = false; - }); - let cursorUsed = false; - // we can't detect the cursor changing to an empty auto complete entry, - // so the only case where getting to search results via Enter will work is - // text typed followed by Enter. - search.autocomplete.on('autocomplete:cursorchanged', (event, suggestion) => { - cursorUsed = true; - }); - // search.autocomplete.on('keydown', (e) => { - // if (opened && !cursorUsed && e.key === 'Enter' && search.input[0].value !== '') { - // const query = encodeURIComponent(search.input[0].value); - // window.location = `${window.location.origin}/search?query=${query}`; - // } - // }); +// Get the button element +const inkeepButton = document.getElementById("chatButton"); + +// Create a new div element to hold the Inkeep modal and set its id and position +const inkeepDiv = document.createElement("div"); +inkeepDiv.id = "inkeepModal"; +inkeepDiv.style.position = "absolute"; +document.body.appendChild(inkeepDiv); + +const handleClose = () => { +inkeepWidget.render({ + ...config, + isOpen: false, +}); +}; + +const handleOpen = () => { +inkeepWidget.render({ + ...config, + isOpen: true, +}); } -handleSearch('.navbar-nav .td-search-input'); -handleSearch('.td-sidebar__search .td-search-input'); +const config = { +componentType: "CustomTrigger", // required +targetElement: inkeepDiv, // required +properties: { + isOpen: false, // required + onClose: handleClose, // required + onOpen: undefined, + baseSettings: { + apiKey: INKEEP_API_KEY, + integrationId: INKEEP_INTEGRATION_ID, + organizationId: INKEEP_ORGANIZATION_ID, + primaryBrandColor: "#000000", + organizationDisplayName: "Viam AI Bot", + //... optional base settings + }, + modalSettings: { + // optional InkeepModalSettings + }, + searchSettings: { + // optional InkeepSearchSettings + }, + aiChatSettings: { + chatSubjectName: "Viam", + botAvatarSrcUrl: "https://cdn.prod.website-files.com/62fba5686b6d47fe2a1ed2a6/62fba8f4a8ca05f38a2b497f_viam-logo-webclip.png", + botAvatarDarkSrcUrl: "https://storage.googleapis.com/organization-image-assets/viam-botAvatarDarkSrcUrl-1721328398594.svg", + getHelpCallToActions: [ + { + name: "Email", + url: "mailto:support@viam.com", + icon: { + builtIn: "IoMail" + } + }, + { + name: "Discord", + url: "https://discord.gg/viam", + icon: { + builtIn: "FaDiscord" + } + } + ], + quickQuestions: [ + "How to install lightweight version microcontroller?", + "How to deploy a person detection model?", + "How can I ingest data from machines?", + "How to query sensor data with third-party tools?", + ], + }, +}, +}; -// Userflow START -!function(){var e="undefined"==typeof window?{}:window,r=e.userflow;if(!r){var t="https://js.userflow.com/",n=null;r=e.userflow={_stubbed:!0,load:function(){return n||(n=new Promise((function(r,o){var s=document.createElement("script");s.async=!0;var a=e.USERFLOWJS_ENV_VARS||{};"es2020"===(a.USERFLOWJS_BROWSER_TARGET||function(e){for(var r=[[/Edg\//,/Edg\/(\d+)/,80],[/OPR\//,/OPR\/(\d+)/,67],[/Chrome\//,/Chrome\/(\d+)/,80],[/Safari\//,/Version\/(\d+)/,14],[/Firefox\//,/Firefox\/(\d+)/,74]],t=0;t=a)return"es2020";break}}return"legacy"}(navigator.userAgent))?(s.type="module",s.src=a.USERFLOWJS_ES2020_URL||t+"es2020/userflow.js"):s.src=a.USERFLOWJS_LEGACY_URL||t+"legacy/userflow.js",s.onload=function(){r()},s.onerror=function(){document.head.removeChild(s),n=null;var e=new Error("Could not load Userflow.js");console.error(e.message),o(e)},document.head.appendChild(s)}))),n}};var o=e.USERFLOWJS_QUEUE=e.USERFLOWJS_QUEUE||[],s=function(e){r[e]=function(){var t=Array.prototype.slice.call(arguments);r.load(),o.push([e,null,t])}},a=function(e){r[e]=function(){var t,n=Array.prototype.slice.call(arguments);r.load();var s=new Promise((function(e,r){t={resolve:e,reject:r}}));return o.push([e,t,n]),s}},u=function(e,t){r[e]=function(){return t}};s("_setTargetEnv"),s("closeResourceCenter"),s("init"),s("off"),s("on"),s("prepareAudio"),s("registerCustomInput"),s("remount"),s("reset"),s("setBaseZIndex"),s("setCustomInputSelector"),s("setCustomNavigate"),s("setCustomScrollIntoView"),s("setInferenceAttributeFilter"),s("setInferenceAttributeNames"),s("setInferenceClassNameFilter"),s("setResourceCenterLauncherHidden"),s("setScrollPadding"),s("setShadowDomEnabled"),s("setPageTrackingDisabled"),s("setUrlFilter"),s("openResourceCenter"),s("toggleResourceCenter"),a("endAll"),a("endAllFlows"),a("endChecklist"),a("group"),a("identify"),a("identifyAnonymous"),a("start"),a("startFlow"),a("startWalk"),a("track"),a("updateGroup"),a("updateUser"),u("getResourceCenterState",null),u("isIdentified",!1)}}(); +// Embed the widget using the `Inkeep.embed()` function. +const inkeepWidget = Inkeep().embed(config); -userflow.init("ct_dybdwc2fkna4lmih2zyqb6eune"); -userflow.setResourceCenterLauncherHidden(true); +// Add event listener to open the Inkeep modal when the button is clicked +inkeepButton.addEventListener("click", handleOpen); -async function initAndClick() { - // unclear why it needs to be called twice but otherwise you need to click the button twice. - await userflow.identifyAnonymous({}); - await userflow.identifyAnonymous({}); - userflow.openResourceCenter() -} +// Create an HTML element that the Inkeep widget will be inserted into. +const nav = document.querySelector("nav"); +const sidebar = document.getElementById("mobile-search"); + +const inkeepNavDiv = document.createElement("div"); +inkeepNavDiv.id = "navSearchBar"; +nav.appendChild(inkeepNavDiv); + +const inkeepSidebarDiv = document.createElement("div"); +inkeepSidebarDiv.id = "sideSearchBar"; +sidebar && sidebar.prepend(inkeepSidebarDiv); + +// Function for initializating the widget. +const addInkeepWidget = ({ + targetElement, + stylesheetUrls, + isShortcutKeyEnabled, +}) => { + // Embed the widget using the `Inkeep.embed()` function. + const inkeepWidget = Inkeep().embed({ + componentType: "SearchBar", + targetElement, + properties: { + baseSettings: { + apiKey: INKEEP_API_KEY, + integrationId: INKEEP_INTEGRATION_ID, + organizationId: INKEEP_ORGANIZATION_ID, + primaryBrandColor: "#000000", // your brand color, widget color scheme is derived from this + organizationDisplayName: "Viam AI Bot", + // ...optional settings + theme: { + stylesheetUrls, + // ...optional settings + }, + }, + modalSettings: { + // optional settings + isShortcutKeyEnabled, + }, + searchSettings: { + // optional settings + }, + aiChatSettings: { + chatSubjectName: "Viam", + botAvatarSrcUrl: "https://cdn.prod.website-files.com/62fba5686b6d47fe2a1ed2a6/62fba8f4a8ca05f38a2b497f_viam-logo-webclip.png", + botAvatarDarkSrcUrl: "https://storage.googleapis.com/organization-image-assets/viam-botAvatarDarkSrcUrl-1721328398594.svg", + getHelpCallToActions: [ + { + name: "Email", + url: "mailto:support@viam.com", + icon: { + builtIn: "IoMail" + } + }, + { + name: "Discord", + url: "https://discord.gg/viam", + icon: { + builtIn: "FaDiscord" + } + } + ], + quickQuestions: [ + "How to install lightweight version microcontroller?", + "How to deploy a person detection model?", + "How can I ingest data from machines?", + "How to query sensor data with third-party tools?", + ], + }, + }, + }); +}; + +sidebar && + addInkeepWidget({ + targetElement: document.getElementById("sideSearchBar"), + // stylesheetUrls: ['/path/to/stylesheets'], // optional + isShortcutKeyEnabled: false, + }); + +addInkeepWidget({ + targetElement: document.getElementById("navSearchBar"), +// stylesheetUrls: ['/path/to/stylesheets'], // optional + isShortcutKeyEnabled: true, +}); -// Userflow END +// Inkeep END \ No newline at end of file diff --git a/assets/js/search-results.js b/assets/js/search-results.js deleted file mode 100644 index 93b7170bc81..00000000000 --- a/assets/js/search-results.js +++ /dev/null @@ -1,72 +0,0 @@ -const { TypesenseInstantSearchAdapter, instantsearch } = window; -const observer = lozad(); - -const indexName = 'docsearch'; -const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({ - server: { - apiKey: "GHQK6od8KfpvTEh4YpA113gUc2dU5fGR", - nodes: [ - { - host: "cgnvrk0xwyj9576lp-1.a1.typesense.net", - port: "443", - protocol: "https", - }, - ], - cacheSearchResultsForSeconds: 2 * 60, - }, - additionalSearchParameters: { - query_by: 'hierarchy.lvl0,hierarchy.lvl1,url_without_anchor', - query_by_weight: '100,50,1', - sort_by: "_text_match:desc,item_priority:desc", - prioritize_token_position: true, - group_by: "url_without_anchor", - group_limit: 1, - }, -}); - -const searchClient = typesenseInstantsearchAdapter.searchClient; - -const search = instantsearch({ - indexName: indexName, - searchClient, -}); - -search.addWidgets([ - instantsearch.widgets.hits({ - container: "#hits", - templates: { - item: ` -
- -
-
{{hierarchy.lvl0}}
-
-

{{#helpers.highlight}}{ "attribute": "hierarchy.lvl1", "highlightedTagName": "mark" }{{/helpers.highlight}}

-
-
-
-
- `, - }, - }), - instantsearch.widgets.configure({ - hitsPerPage: 12, - }), - instantsearch.widgets.pagination({ - container: "#pagination", - }), - instantsearch.widgets.searchBox({ - container: '#search-box', - }), -]); - -search.start(); - -const urlParams = new URLSearchParams(window.location.search); -const query = urlParams.get('query'); - -search.setUiState({ - [indexName]: { - query: query - } -}); diff --git a/assets/js/search.js b/assets/js/search.js deleted file mode 100644 index c8875509cf5..00000000000 --- a/assets/js/search.js +++ /dev/null @@ -1,26 +0,0 @@ -(function($) { - - 'use strict'; - - var Search = { - init: function() { - $(document).ready(function() { - $(document).on('keypress', '.navbar-nav .td-search-input', function(e) { - if (e.keyCode === 13) { - e.preventDefault(); - return; - } - }); - $(document).on('keypress', '.td-sidebar__search .td-search-input', function(e) { - if (e.keyCode === 13) { - e.preventDefault(); - return; - } - }); - }); - }, - }; - - Search.init(); - -}(jQuery)); \ No newline at end of file diff --git a/assets/scss/_styles_project.scss b/assets/scss/_styles_project.scss index 411c789b2c8..54b8d8ca7bc 100644 --- a/assets/scss/_styles_project.scss +++ b/assets/scss/_styles_project.scss @@ -1847,12 +1847,29 @@ a.ais-Pagination-link:hover { min-height: 90%; } -// Helper to allow search to link to tabs -.search-helper { +// Search START + +#sideSearchBar { display: none; + max-width: 100%; + width: 100%; } +@media (max-width: 992px) { + + #navSearchBar { + display: none; + } + + #sideSearchBar { + display: unset; + } + +} + +// Search END + // styling for model list from registry .searchhitsbox { @@ -2156,18 +2173,6 @@ h3.body-header[style] { margin-right: 1rem; } -.algolia-autocomplete .typesense-docsearch-suggestion--subcategory-column { - display: none !important; - float:left; - width:0 !important; - padding-left:0; - padding:0px; -} - -.algolia-autocomplete .typesense-docsearch-suggestion--content { - width: 100% !important; -} - // Front page styling START .frontpage h2 { diff --git a/layouts/docs/search.html b/layouts/docs/search.html index 8840f4b051f..b8136ac6d84 100644 --- a/layouts/docs/search.html +++ b/layouts/docs/search.html @@ -53,9 +53,5 @@

{{ .Title }}

- {{ $jsSearchResults := resources.Get "js/search-results.js" }} - {{ $jsSearchResults := $jsSearchResults | minify }} - - diff --git a/layouts/partials/hooks/head-end.html b/layouts/partials/hooks/head-end.html index 801c62b4490..138a96e7acb 100644 --- a/layouts/partials/hooks/head-end.html +++ b/layouts/partials/hooks/head-end.html @@ -1,4 +1,3 @@ - {{ end }} + + + + {{ $jsLozad := resources.Get "js/lozad.js" }} @@ -103,7 +110,7 @@ integrity='sha512-ZA/RPrAo88DlwRnnoNVqKINnQNcWERzRK03PDaA4GIJiVZvGFIWQbdWCsUebMZfkWohnfngsDjXzU6PokO4jGw==' crossorigin='anonymous' {{ printf "onload='renderMathInElement(%s, %s);'" (( .Site.Params.katex.html_dom_element | default "document.body" ) | safeJS ) ( printf "%s" ( $.Site.Params.katex.options | jsonify )) | safeHTMLAttr }}> {{ end }} - + {{ $jsIndex := resources.Get "js/index.js" }} {{ $jsPrismViam := resources.Get "js/prism.js" }} diff --git a/layouts/partials/sidebar-tree.html b/layouts/partials/sidebar-tree.html index 6108e4480b5..039786ccd51 100644 --- a/layouts/partials/sidebar-tree.html +++ b/layouts/partials/sidebar-tree.html @@ -3,18 +3,16 @@ {{ $shouldDelayActive := ge (len .Site.Pages) $sidebarCacheLimit -}}
{{ if not .Site.Params.ui.sidebar_search_disable -}} - {{ else -}}
- +
{{ end -}}