UNPKG

coveo-search-ui

Version:

Coveo JavaScript Search Framework

171 lines (148 loc) 6.29 kB
import { Component } from '../Base/Component'; import { ComponentOptions } from '../Base/ComponentOptions'; import { IFieldOption } from '../Base/IComponentOptions'; import { IComponentBindings } from '../Base/ComponentBindings'; import { SettingsEvents } from '../../events/SettingsEvents'; import { ISettingsPopulateMenuArgs } from '../Settings/Settings'; import { IAnalyticsNoMeta, analyticsActionCauseList } from '../Analytics/AnalyticsActionListMeta'; import { Initialization } from '../Base/Initialization'; import { l } from '../../strings/Strings'; import * as _ from 'underscore'; import { exportGlobally } from '../../GlobalExports'; import 'styling/_ExportToExcel'; import { SVGIcons } from '../../utils/SVGIcons'; import { SearchInterface } from '../SearchInterface/SearchInterface'; import { get } from '../Base/RegisteredNamedMethods'; import * as moment from 'moment'; import { IQuery } from '../../rest/Query'; let createAnchor = () => document.createElement('a'); export function setCreateAnchor(fn: () => HTMLAnchorElement) { createAnchor = fn; } export interface IExportToExcelOptions { numberOfResults?: number; fieldsToInclude?: IFieldOption[]; } /** * The ExportToExcel component renders an item in the {@link Settings} menu to allow the end user to export the current * search results to the Microsoft Excel format (.xlsx). * * @availablesince [November 2015 Release (v1.0.139)](https://docs.coveo.com/en/289/#november-2015-release-v10139) */ export class ExportToExcel extends Component { static ID = 'ExportToExcel'; static doExport = () => { exportGlobally({ ExportToExcel: ExportToExcel }); }; /** * The options for the ExportToExcel * @componentOptions */ static options: IExportToExcelOptions = { /** * Specifies the number of results to include in the resulting Excel file. * * Generating and downloading the Excel file should take a reasonably short amount of time when using the default * value. However, this amount of time will increase exponentially as you set the value higher. * * Consequently, you should avoid setting this value above the default index limit of 1000 search results. * * Note that for HIPAA organizations, the export size limit is 5 MB, and for non-HIPAA organizations, the limit is 25 MB. * * Default value is `100`. Minimum value is `1`. * * @availablesince [February 2016 Release (v1.0.318)](https://docs.coveo.com/en/309/#february-2016-release-v10318) */ numberOfResults: ComponentOptions.buildNumberOption({ defaultValue: 100, min: 1 }), /** * Specifies the fields to include in the CSV output. * * Note that this does not affect top level properties such as the title, clickUri, printableUri and sysUri, for example. * * Default value is `undefined`, meaning all fields will be exported. */ fieldsToInclude: ComponentOptions.buildFieldsOption() }; /** * Creates a new ExportToExcel component. * @param element The HTMLElement on which to instantiate the component. * @param options The options for the ExportToExcel component. * @param bindings The bindings that the component requires to function normally. If not set, these will be * automatically resolved (with a slower execution time). * @param _window The global Window object (used to download the Excel link). */ constructor( public element: HTMLElement, public options: IExportToExcelOptions, public bindings?: IComponentBindings, public _window?: Window ) { super(element, ExportToExcel.ID, bindings); this._window = this._window || window; this.options = ComponentOptions.initComponentOptions(element, ExportToExcel, options); this.bind.onRootElement(SettingsEvents.settingsPopulateMenu, (args: ISettingsPopulateMenuArgs) => { args.menuData.push({ text: l('ExportToExcel'), className: 'coveo-export-to-excel', tooltip: l('ExportToExcelDescription'), onOpen: () => this.download(), svgIcon: SVGIcons.icons.dropdownExport, svgIconClassName: 'coveo-export-to-excel-svg' }); }); } /** * Downloads the Excel representation of the current query. * * Also logs an `exportToExcel` event in the usage analytics. */ public download() { const query = this.buildExcelQuery(); this.logger.debug("Performing query following 'Export to Excel' click"); const endpoint = this.queryController.getEndpoint(); this.usageAnalytics.logCustomEvent<IAnalyticsNoMeta>(analyticsActionCauseList.exportToExcel, {}, this.element); endpoint.fetchBinary(query).then(content => this.downloadExcelFile(content)); } private buildExcelQuery(): IQuery { let query = this.queryController.getLastQuery(); query = _.omit(query, ['numberOfResults', 'fieldsToInclude']); if (this.options.fieldsToInclude) { query.fieldsToInclude = <string[]>this.options.fieldsToInclude; } return { ...query, format: 'xlsx', numberOfResults: this.options.numberOfResults }; } private downloadExcelFile(content: ArrayBuffer) { const blob = new Blob([content], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); const fileName = this.buildExcelFileName(); if (window.navigator.msSaveOrOpenBlob) { window.navigator.msSaveOrOpenBlob(blob, fileName); return; } const url = URL.createObjectURL(blob); const a = createAnchor(); a.href = url; a.download = fileName; a.click(); URL.revokeObjectURL(url); } private buildExcelFileName() { const utc = moment().utc(); const year = utc.format('YYYY'); const month = utc.format('MM'); const day = utc.format('DD'); const hour = utc.format('HH'); const minute = utc.format('mm'); const second = utc.format('ss'); return `query--${year}-${month}-${day}--${hour}-${minute}-${second}.xlsx`; } static create(element: HTMLElement, options?: IExportToExcelOptions, root?: HTMLElement): ExportToExcel { return new ExportToExcel(element, options, (<SearchInterface>get(root, SearchInterface)).getBindings()); } } Initialization.registerAutoCreateComponent(ExportToExcel);