UNPKG

coveo-search-ui

Version:

Coveo JavaScript Search Framework

173 lines (148 loc) 6.14 kB
import { RankingInfoTable } from './RankingInfoTable'; import { MetaDataTable } from './MetaDataTable'; import { IComponentBindings } from '../Base/ComponentBindings'; import { IAttributeChangedEventArg } from '../../models/Model'; import { $$ } from '../../utils/Dom'; import { ModalBox } from '../../ExternalModulesShim'; import { QueryStateModel, ResultListEvents, DomUtils, Logger } from '../../Core'; import { RelevanceInspectorTabs } from './RelevanceInspectorTabs'; import 'styling/_RelevanceInspector'; import { ExecutionReport } from './ExecutionReport'; import { AvailableFieldsTable } from './AvailableFieldsTable'; import agGridModule = require('ag-grid/main'); import { debounce } from 'underscore'; import { IDisplayedNewResultEventArgs } from '../../events/ResultListEvents'; import { InlineRankingInfo } from './InlineRankingInfo'; export interface IRelevanceInspectorConstructor { new (element: HTMLElement, bindings: IComponentBindings): RelevanceInspector; } export interface IRelevanceInspectorTab { gridOptions: agGridModule.GridOptions; } export class RelevanceInspector { private opened = false; private activeTab: string; private tabs: Record<string, IRelevanceInspectorTab>; private modalBoxModule = ModalBox; constructor(public element: HTMLElement, public bindings: IComponentBindings) { $$(this.element).text('Relevance Inspector'); $$(this.element).addClass('coveo-button coveo-relevance-inspector'); $$(this.bindings.root).on( this.bindings.queryStateModel.getEventName(QueryStateModel.eventTypes.changeOne + QueryStateModel.attributesEnum.debug), (e, args: IAttributeChangedEventArg) => this.toggleFromState(args.value) ); $$(this.element).on('click', () => this.open()); $$(this.bindings.root).on(ResultListEvents.newResultDisplayed, (e, args: IDisplayedNewResultEventArgs) => this.handleNewResultDisplayed(args) ); this.bindings.queryStateModel.get(QueryStateModel.attributesEnum.debug) ? this.show() : this.hide(); } public get modalBox() { return this.modalBoxModule; } public set modalBox(modalBoxModule) { this.modalBoxModule = modalBoxModule; } public hide() { $$(this.element).addClass('coveo-hidden'); } public show() { $$(this.element).removeClass('coveo-hidden'); } public async open() { if (this.opened) { return; } this.opened = true; const content = $$('div'); const animation = DomUtils.getBasicLoadingAnimation(); content.append(animation); this.modalBox.open(content.el, this.modalBoxOptions); const rows = await this.buildTabs(); if (rows) { animation.remove(); content.append(rows.el); } else { this.modalBox.close(); } } private handleNewResultDisplayed(args: IDisplayedNewResultEventArgs) { if (this.bindings.queryStateModel.get(QueryStateModel.attributesEnum.debug)) { $$(args.item).addClass('coveo-with-inline-ranking-info'); if ($$(args.item).hasClass('coveo-table-layout')) { $$(args.item).append(new InlineRankingInfo(args.result).build().el); } else { $$(args.item).prepend(new InlineRankingInfo(args.result).build().el); } } } private get modalBoxOptions() { return { title: 'Relevance Inspector', titleClose: false, overlayClose: true, sizeMod: 'big', className: 'relevance-inspector-modal', validation: () => { this.opened = false; return true; }, body: document.getElementsByClassName('CoveoSearchInterface')[0] // Will return undefined if no CoveoSearchInterface is present }; } private toggleFromState(stateValue: number) { stateValue != 0 ? this.show() : this.hide(); this.modalBox.close(); } private async buildTabs() { const lastResults = this.bindings.queryController.getLastResults().results; if (!lastResults || lastResults.length == 0) { new Logger(this).error( 'Could not open Relevance Inspector because there is no results to display. Please execute a query beforehand', lastResults ); return; } if (!lastResults[0].rankingInfo) { new Logger(this).error( 'Could not open Relevance Inspector because there is no ranking info returned on the results. Please execute a query in debug mode beforehad', lastResults ); return; } const container = $$('div'); const rankingInfoTable = new RankingInfoTable(lastResults, this.bindings); const metadataTable = new MetaDataTable(lastResults, this.bindings); const executionReport = new ExecutionReport(this.bindings.queryController.getLastResults(), this.bindings); const availableFields = new AvailableFieldsTable(this.bindings); this.tabs = { relevanceInspectorRankingInfo: rankingInfoTable, relevanceInspectorMetadata: metadataTable, relevanceInspectorExecutionReport: executionReport, relevanceInspectorAvailableFields: availableFields }; const inspectorTabs = new RelevanceInspectorTabs(tabChangedTo => { this.activeTab = tabChangedTo; this.resize(); }); const debouncedResize = debounce(() => this.resize(), 100); window.addEventListener('resize', debouncedResize); inspectorTabs.addSection('Ranking Information', await rankingInfoTable.build(), 'relevanceInspectorRankingInfo'); inspectorTabs.addSection('Metadata', await metadataTable.build(), 'relevanceInspectorMetadata'); inspectorTabs.addSection('Execution Report', await executionReport.build(), 'relevanceInspectorExecutionReport'); inspectorTabs.addSection('Available Fields', await availableFields.build(), 'relevanceInspectorAvailableFields'); inspectorTabs.select('relevanceInspectorRankingInfo'); container.append(inspectorTabs.navigationSection.el); container.append(inspectorTabs.tabContentSection.el); return container; } private resize() { if (!this.activeTab) { return; } if (!this.tabs[this.activeTab]) { return; } this.tabs[this.activeTab].gridOptions.api.sizeColumnsToFit(); } }