/* eslint-disable no-underscore-dangle */ import * as Mousetrap from 'mousetrap' import { Controller } from '@hotwired/stimulus' import { Turbo } from '@hotwired/turbo-rails' import { autocomplete } from '@algolia/autocomplete-js' import URI from 'urijs' import debouncePromise from '../helpers/debounce_promise' /** * The search controller is used in three places. * 1. Global search (on the top navbar) and can search through multiple resources. * 2. Resource search (on the Index page on top of the table panel) and will search one resource * 3. belongs_to field. This requires a bit more cleanup because the user will not navigate away from the page. * It will replace the id and label in some fields on the page and also needs a "clear" button which clears the information so the user can submit the form without a value. */ export default class extends Controller { static targets = [ 'autocomplete', 'button', 'hiddenId', 'visibleLabel', 'clearValue', 'clearButton', ]; debouncedFetch = debouncePromise(fetch, this.searchDebounce); get dataset() { return this.autocompleteTarget.dataset } get searchDebounce() { return window.Avo.configuration.search_debounce } get translationKeys() { let keys try { keys = JSON.parse(this.dataset.translationKeys) } catch (error) { keys = {} } return keys } get isBelongsToSearch() { return this.dataset.viaAssociation === 'belongs_to' } get isGlobalSearch() { return this.dataset.searchResource === 'global' } searchUrl(query) { const url = URI() let params = { q: query } let segments = [ window.Avo.configuration.root_path, 'avo_api', this.dataset.searchResource, 'search', ] if (this.isGlobalSearch) { segments = [window.Avo.configuration.root_path, 'avo_api', 'search'] } if (this.isBelongsToSearch) { // eslint-disable-next-line camelcase params = { ...params, via_association: this.dataset.viaAssociation } } return url.segment(segments).search(params).toString() } handleOnSelect({ item }) { if (this.isBelongsToSearch) { this.hiddenIdTarget.setAttribute('value', item._id) this.buttonTarget.setAttribute('value', item._label) document.querySelector('.aa-DetachedOverlay').remove() if (this.hasClearButtonTarget) { this.clearButtonTarget.classList.remove('hidden') } } else { Turbo.visit(item._url, { action: 'advance' }) } } addSource(resourceName, data) { const that = this return { sourceId: resourceName, getItems: () => data.results, onSelect: that.handleOnSelect.bind(that), templates: { header() { return `${data.header.toUpperCase()} ${data.help}` }, item({ item, createElement }) { let element = '' if (item._avatar) { let classes switch (item._avatar_type) { default: case 'circle': classes = 'rounded-full' break case 'rounded': classes = 'rounded' break } element += `` } element += `