Show Documents without the Chat#

The SDK also shows Squirro documents on their own, without the chat: as a read-only documents API, as a document view, and as a search widget.

The Documents API#

sdk.items is the read-only documents API, through the same proxy, for pages that build their own list: sdk.items.search({ text: 'zebrafish' }, { limit: 10 }), sdk.items.getItem(id), and sdk.items.fetchFile(link) for the bytes of the original file of a document.

  • The title and abstract of every result and document, including the result that onOpenItem receives, are plain text: the search highlight tags are removed, and the character references of the abstract, such as &, are decoded. Set them with textContent, never innerHTML, and do not decode them again.

  • A failed request rejects with an ItemsRequestError, which carries the HTTP status and a kind that says what went wrong, such as search-disabled for a proxy without search. A search that the proxy refused for one of its limits also carries the code of the proxy, and its message names the option. On a script-tag page, check error.name === 'ItemsRequestError'. For every kind, see the docs/chat.md and docs/documents.md files in the package.

The Document View#

In React, NeoItemDetail renders the same document view as the overlay, anywhere inside NeoSdkProvider, for example in a side panel of your own:

import { NeoItemDetail } from '@squirro/neo-sdk';

<NeoItemDetail itemId="the-squirro-item-id" pageNumber={2} onClose={() => setOpen(false)} />

It takes these props:

  • itemId, the document to show.

  • pageNumber and highlightFragments, as for sdk.openDocument().

  • onClose, which shows a close button. Escape does not call it.

  • className. Size the component from its parent.

The Search Widget#

NeoItems adds a read-only search box and its results, and a result opens in the same document overlay. It needs ALLOW_SEARCH=1 on the proxy, or allowSearch: true. Without it, the widget says that search is turned off.

For example, to search for a fixed term:

import { NeoItems } from '@squirro/neo-sdk';

<NeoItems query="zebrafish" pageSize={10} className="h-96" />

It takes these props:

  • query, which fills the box and searches. A new value searches again.

  • pageSize, a positive integer, 15 by default.

  • onOpenItem, which receives the result and replaces opening the overlay.

  • strings, to replace its English text.

  • className. Give the widget a height from its parent, since the list scrolls inside it.

To let readers narrow the results, list the facets to filter by, and the orders to offer after Relevance:

<NeoItems
  query="zebrafish"
  filters={[{ field: 'source', label: 'Source' }, { field: 'source_type', label: 'Type' }]}
  sort={[{ label: 'Newest first', field: 'date', order: 'desc' }]}
/>

Each filter is a dropdown of the values of the field, with their counts: 10 by default, and up to 50 with limit. A widget takes at most 8 filters. Values of one field are combined with OR, and the fields with AND. initialFilters picks values up front, and onFiltersChange tells you what the reader picked. The same keys under items in initNeoSdk() set the defaults for every search widget of that instance.

Filter fields are facet names, and an order sorts by date or by one of the filter fields. initialFilters is a convenience for the reader, not access control. For the filter values that cannot match, see the docs/documents.md file in the package.

Because every reader shares the service account, the proxy accepts only searches like the ones that the widget sends, with at most 100 results each and a search text of at most 4,096 characters. itemsQueryLimits on the proxy changes these caps. Keep pageSize at or under the result cap.

Without a Build Step#

On a page without a build step, the same two widgets are the <neo-items> and <neo-item-detail> elements, from the same neo-sdk.js. They take base-url, project-id, auth, the theme attributes, and the theme JSON child exactly like <neo-chat>, and each needs a size:

<script src="/assets/neo-sdk.js" defer></script>

<neo-items id="search" base-url="/api/chat" project-id="YOUR_PROJECT_ID" auth="anonymous" query="zebrafish" page-size="10"></neo-items>

<neo-item-detail
  id="report"
  base-url="/api/chat"
  project-id="YOUR_PROJECT_ID"
  auth="anonymous"
  item-id="the-squirro-item-id"
  page-number="2"
></neo-item-detail>

<style>
  neo-items,
  neo-item-detail {
    display: block;
    height: 600px;
  }
</style>

<script>
  const report = document.getElementById('report');
  report.highlightFragments = ['net revenue'];

  // Change what they show at any time; they follow their attributes.
  document.getElementById('search').setAttribute('query', 'quarterly results');
</script>
  • <neo-items> takes query and page-size, and filters and sort as JSON, for example filters='[{"field":"source","label":"Source"}]'. Set its onOpenItem property to handle a click on a result yourself.

  • <neo-item-detail> takes item-id, which is required, and page-number, a positive integer. The text to highlight is the highlightFragments property, since an attribute cannot hold a list.

  • Changing query, page-size, filters, sort, or item-id later updates the widget in place. A new page-number applies only the next time a document loads.

  • Each element is its own SDK instance. Set pdfViewer as a property on any of them that shows PDF documents.

  • Each element reports a problem as a neo-items-error or neo-item-detail-error event, with the error in event.detail. A <neo-item-detail> without item-id shows nothing until you set one. After any other error, such as a missing project-id, fix it and add the element to the page again.