UNPKG

@appbaseio/reactivesearch-vue

Version:

A Vue UI components library for building search experiences

954 lines (938 loc) 38.4 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var reactivecore = require('@appbaseio/reactivecore'); var constants = require('@appbaseio/reactivecore/lib/utils/constants'); var _transformOn = _interopDefault(require('@vue/babel-helper-vue-transform-on')); var _rollupPluginBabelHelpers = require('./_rollupPluginBabelHelpers-1a877b17.js'); var vue = require('vue'); var VueTypes = _interopDefault(require('vue-types')); var helper = require('@appbaseio/reactivecore/lib/utils/helper'); var vueEmotion = require('@appbaseio/vue-emotion'); var css = require('@emotion/css'); require('polished'); require('./Button-7aee17e3.js'); var vueTypes = require('./vueTypes-adf43075.js'); var Pagination = require('./Pagination-8bda127c.js'); require('@appbaseio/reactivecore/lib/utils/transform'); require('redux'); var index = require('./index-7ca9570e.js'); var ComponentWrapper = require('./ComponentWrapper-3bedbe57.js'); var PreferencesConsumer = require('./PreferencesConsumer-37cab7a0.js'); require('./Title-d513ac26.js'); var ListItem = require('./ListItem-f272f502.js'); var Card = require('./Card-abff695e.js'); var Flex = require('./Flex-f7af0673.js'); var _templateObject; var PoweredByImage = vueEmotion.styled('img')(_templateObject || (_templateObject = _rollupPluginBabelHelpers._taggedTemplateLiteralLoose(["\n\twidth: 110px;\n"]))); var PoweredBy = function PoweredBy() { return vue.createVNode("a", { "href": "https://appbase.io/", "target": "_blank", "rel": "noopener noreferrer" }, [vue.createVNode(PoweredByImage, { "src": "https://cdn.jsdelivr.net/gh/appbaseio/cdn@d2ec210045e59104ee5485841fa17b23fc83f097/appbase/logos/rbc-logo.svg" }, null)]); }; var ResultListWrapper = { name: 'ResultListWrapper', functional: true, render: function render(context) { return vue.createVNode("div", vue.mergeProps({ "className": ListItem.container }, context.$props), [context.$slots["default"]()]); } }; ResultListWrapper.install = function (Vue) { Vue.component(ResultListWrapper.name, ResultListWrapper); }; var ResultCardsWrapper = { name: 'ResultCardsWrapper', functional: true, render: function render(context) { return vue.createVNode("div", vue.mergeProps({ "className": Card.container }, context.$props), [context.$slots["default"]()]); } }; ResultCardsWrapper.install = function (Vue) { Vue.component(ResultCardsWrapper.name, ResultCardsWrapper); }; var _templateObject$1, _templateObject2; var resultStats = css.css(_templateObject$1 || (_templateObject$1 = _rollupPluginBabelHelpers._taggedTemplateLiteralLoose(["\n\tflex-grow: 1;\n\tfont-size: 0.82rem;\n"]))); var sortOptions = css.css(_templateObject2 || (_templateObject2 = _rollupPluginBabelHelpers._taggedTemplateLiteralLoose(["\n\tcolor: #424242;\n\theight: 32px;\n\tfont-size: 0.82rem;\n\tpadding: 0 25px 0 10px;\n\tbackground: url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0Ljk1IDEwIj48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6I2ZmZjt9LmNscy0ye2ZpbGw6IzQ0NDt9PC9zdHlsZT48L2RlZnM+PHRpdGxlPmFycm93czwvdGl0bGU+PHJlY3QgY2xhc3M9ImNscy0xIiB3aWR0aD0iNC45NSIgaGVpZ2h0PSIxMCIvPjxwb2x5Z29uIGNsYXNzPSJjbHMtMiIgcG9pbnRzPSIxLjQxIDQuNjcgMi40OCAzLjE4IDMuNTQgNC42NyAxLjQxIDQuNjciLz48cG9seWdvbiBjbGFzcz0iY2xzLTIiIHBvaW50cz0iMy41NCA1LjMzIDIuNDggNi44MiAxLjQxIDUuMzMgMy41NCA1LjMzIi8+PC9zdmc+)\n\t\tno-repeat 95% 50%;\n\tbackground-color: #fff;\n\t-moz-appearance: none;\n\t-webkit-appearance: none;\n\tappearance: none;\n\t-webkit-border-radius: 0;\n\tborder-radius: 0;\n\tborder: 0;\n\toutline: 1px solid #ddd;\n\toutline-offset: -1px;\n"]))); var recordImpressions = reactivecore.Actions.recordImpressions; var isEqual = reactivecore.helper.isEqual; var debounce = function debounce(method, delay) { clearTimeout(method._tId); // eslint-disable-next-line method._tId = setTimeout(function () { method(); }, delay); }; var ImpressionTracker = { name: 'ImpressionTracker', inject: ['$$store'], props: { hits: vueTypes.types.hits }, created: function created() { // Represents the list of hits returned by the query this.currentHits = []; // An array of hits objects // An object to track the recorded impressions // It can have the values in following shape // { "hit_id": { "index": "test" }} this.trackedIds = {}; // An object to know the the un-tracked impression i.e not recorded by BE // It can have the values in following shape // { "query_id": [{ "id": "hit_id", "index": "test"}]} this.waitingToBeTracked = {}; }, mounted: function mounted() { this.setCurrentHits(this.hits); // Add scroll events to track the impressions if (window) { window.addEventListener('scroll', this.tracker); } }, destroy: function destroy() { // Clear the interval this.clearTrackerInterval(); }, watch: { hits: function hits(newVal, oldVal) { if (newVal && newVal !== oldVal) { // Only compare hit ids for performance reasons var prevHitIds = oldVal.map(function (hit) { return hit._id; }); var currentHitIds = newVal.map(function (hit) { return hit._id; }); if (!isEqual(currentHitIds, prevHitIds)) { this.setCurrentHits(newVal); } } } }, methods: { inViewPort: function inViewPort(el) { var rect = el.getBoundingClientRect(); return rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth); }, setCurrentHits: function setCurrentHits(hits) { this.currentHits = hits; // Reset the tracked Ids for new hits this.trackedIds = {}; if (hits && hits.length) { this.tracker(); // Run the tracker function on an interval of 1s to track the impressions for // non-scroll views for e.g on tab change this.setTrackerInterval(); } }, recordImpression: function recordImpression() { var _this = this; if (Object.keys(this.waitingToBeTracked).length) { var unTrackedHits = _rollupPluginBabelHelpers._extends({}, this.waitingToBeTracked); Object.keys(unTrackedHits).forEach(function (queryId) { if (unTrackedHits[queryId] && unTrackedHits[queryId].length) { _this.trackImpressions(queryId, unTrackedHits[queryId]); // Removed tracked impressions from waiting list delete _this.waitingToBeTracked[queryId]; } }); } }, addToWaitingList: function addToWaitingList(hitObject) { var queryId = this.getQueryId(); if (hitObject && queryId) { var impression = { id: hitObject._id, index: hitObject._index }; // Check if query id already present in waiting list if (this.waitingToBeTracked[queryId]) { this.waitingToBeTracked[queryId].push(impression); } else { this.waitingToBeTracked[queryId] = [impression]; } } }, tracker: function tracker() { var _this2 = this; if (!this.getHitIds().length) { this.clearTrackerInterval(); return; } // only run at client-side if (window && document) { this.getHitIds().forEach(function (id) { var element = document.getElementById(id); if (element) { if (_this2.inViewPort(element)) { // Add the hit id in the list of tracked ids var hitObject = _this2.currentHits.find(function (hit) { return hit._id === id; }); _this2.trackedIds[id] = true; // Add hit to waiting list to be recorded _this2.addToWaitingList(hitObject); } } }); } debounce(this.recordImpression, 300); }, setTrackerInterval: function setTrackerInterval() { this.intervalID = setInterval(this.tracker, 1000); }, clearTrackerInterval: function clearTrackerInterval() { if (this.intervalID) { clearInterval(this.intervalID); // Reset interval ID this.intervalID = null; } }, getQueryId: function getQueryId() { var state = this.$$store ? this.$$store.getState() : null; return state ? state.analytics.searchId : null; }, getHitIds: function getHitIds() { var _this3 = this; return this.currentHits.map(function (hit) { return hit._id; }).filter(function (id) { return !_this3.trackedIds[id]; }); } }, render: function render() { return this.$slots["default"](); } }; var mapDispatchToProps = { trackImpressions: recordImpressions }; var ImpressionTracker$1 = index.connect(function () { return null; }, mapDispatchToProps)(ImpressionTracker); function _isSlot(s) { return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !vue.isVNode(s); } var setQueryOptions = reactivecore.Actions.setQueryOptions, updateQuery = reactivecore.Actions.updateQuery, loadMore = reactivecore.Actions.loadMore, setValue = reactivecore.Actions.setValue, updateComponentProps = reactivecore.Actions.updateComponentProps, setDefaultQuery = reactivecore.Actions.setDefaultQuery, recordResultClick = reactivecore.Actions.recordResultClick; var isEqual$1 = reactivecore.helper.isEqual, getQueryOptions = reactivecore.helper.getQueryOptions, getClassName = reactivecore.helper.getClassName, parseHits = reactivecore.helper.parseHits, getCompositeAggsQuery = reactivecore.helper.getCompositeAggsQuery, getResultStats = reactivecore.helper.getResultStats, extractQueryFromCustomQuery = reactivecore.helper.extractQueryFromCustomQuery, getOptionsForCustomQuery = reactivecore.helper.getOptionsForCustomQuery; var ReactiveList = { name: 'ReactiveList', components: { ResultListWrapper: ResultListWrapper, ResultCardsWrapper: ResultCardsWrapper }, data: function data() { var currentPageState = 0; var defaultPage = this.defaultPage || -1; if (defaultPage >= 0) { currentPageState = defaultPage; } else if (this.currentPage) { currentPageState = Math.max(this.currentPage - 1, 0); } this.__state = { from: currentPageState * this.size, currentPageState: currentPageState }; return this.__state; }, created: function created() { var _this = this; // no support for pagination and aggregationField together if (this.pagination && this.aggregationField) { console.warn('Pagination is not supported when aggregationField is present. The list will be rendered with infinite scroll'); } var defaultPage = this.defaultPage || -1; if (defaultPage >= 0) { this.currentPageState = defaultPage; this.from = this.currentPageState * this.$props.size; } this.internalComponent = this.$props.componentId + "__internal"; this.sortOptionIndex = 0; if (this.defaultSortOption && this.sortOptions && Array.isArray(this.sortOptions)) { this.sortOptionIndex = this.sortOptions.findIndex(function (s) { return s.label === _this.defaultSortOption; }); } if (this.urlSortOption) { this.sortOptionIndex = this.$props.sortOptions.findIndex(function (s) { return s.label === _this.urlSortOption; }) || 0; } this.updateComponentProps(this.componentId, { from: this.from }, constants.componentTypes.reactiveList); this.updateComponentProps(this.internalComponent, { from: this.from }, constants.componentTypes.reactiveList); }, props: { currentPage: VueTypes.number, includeFields: vueTypes.types.includeFields, // component props className: vueTypes.types.string, componentId: vueTypes.types.stringRequired, compoundClause: vueTypes.types.compoundClause, dataField: vueTypes.types.string, vectorDataField: vueTypes.types.string, aggregationField: vueTypes.types.string, aggregationSize: VueTypes.number, defaultQuery: vueTypes.types.func, defaultSortOption: vueTypes.types.string, excludeFields: vueTypes.types.excludeFields, innerClass: vueTypes.types.style, listClass: VueTypes.string.def(''), loader: vueTypes.types.title, render: vueTypes.types.func, renderItem: vueTypes.types.func, renderNoResults: VueTypes.any.def('No Results found.'), renderError: vueTypes.types.title, renderResultStats: vueTypes.types.func, pages: VueTypes.number.def(5), pagination: VueTypes.bool.def(false), infiniteScroll: VueTypes.bool.def(true), paginationAt: VueTypes.oneOf(['top', 'bottom', 'both']).def('bottom'), react: vueTypes.types.react, scrollOnChange: VueTypes.bool.def(true), showResultStats: VueTypes.bool.def(true), showEndPage: VueTypes.bool.def(false), size: VueTypes.number.def(10), candidates: VueTypes.number.def(10), sortBy: vueTypes.types.sortBy, sortOptions: vueTypes.types.sortOptions, URLParams: VueTypes.bool.def(false), prevLabel: vueTypes.types.string, nextLabel: vueTypes.types.string, distinctField: vueTypes.types.string, distinctFieldConfig: vueTypes.types.props, index: VueTypes.string, endpoint: vueTypes.types.endpointConfig }, computed: { shouldRenderPagination: function shouldRenderPagination() { return this.pagination && !this.aggregationField; }, totalPages: function totalPages() { return Math.ceil(this.total / this.$props.size) || 0; }, hasPageChangeListener: function hasPageChangeListener() { return this.$attrs && this.$attrs.pageChange; }, hasResultStatsListener: function hasResultStatsListener() { return this.$attrs && this.$attrs.resultStats; }, stats: function stats() { return _rollupPluginBabelHelpers._extends({}, getResultStats(this), { currentPage: this.currentPageState, displayedResults: this.data.length }); }, hasCustomRender: function hasCustomRender() { return index.hasCustomRenderer(this); }, showInfiniteScroll: function showInfiniteScroll() { // Pagination has higher priority then infinite scroll return this.infiniteScroll && !this.shouldRenderPagination; }, data: function data() { var results = parseHits(this.hits) || []; var parsedPromotedResults = parseHits(this.promotedResults) || []; var filteredResults = results; if (parsedPromotedResults.length) { var ids = parsedPromotedResults.map(function (item) { return item._id; }).filter(Boolean); if (ids) { filteredResults = filteredResults.filter(function (item) { return !ids.includes(item._id); }); } filteredResults = [].concat(parsedPromotedResults, filteredResults); } return helper.withClickIds(filteredResults); } }, watch: { sortOptions: function sortOptions(newVal, oldVal) { if (!isEqual$1(oldVal, newVal)) { this.updateQueryOptions(this.$props); } }, sortBy: function sortBy(newVal, oldVal) { if (oldVal !== newVal) { this.updateQueryOptions(this.$props); } }, size: function size(newVal, oldVal) { if (oldVal !== newVal) { this.updateQueryOptions(this.$props); } }, dataField: function dataField(newVal, oldVal) { if (oldVal !== newVal) { this.updateQueryOptions(this.$props); } }, includeFields: function includeFields(newVal, oldVal) { if (oldVal !== newVal) { this.updateQueryOptions(this.$props); } }, excludeFields: function excludeFields(newVal, oldVal) { if (oldVal !== newVal) { this.updateQueryOptions(this.$props); } }, defaultQuery: function defaultQuery(newVal, oldVal) { if (!index.isQueryIdentical(newVal, oldVal, null, this.$props)) { var options = getQueryOptions(this.$props); options.from = 0; this.$defaultQuery = newVal(null, this.$props); var query = extractQueryFromCustomQuery(this.$defaultQuery); var queryOptions = getOptionsForCustomQuery(this.$defaultQuery); if (queryOptions) { options = _rollupPluginBabelHelpers._extends({}, options, queryOptions); } // Update calculated default query in store index.updateDefaultQuery(this.componentId, this.setDefaultQuery, this.$props); this.setQueryOptions(this.$props.componentId, _rollupPluginBabelHelpers._extends({}, options, this.getAggsQuery()), !query); this.updateQuery({ componentId: this.internalComponent, query: query }, true); // reset page because of query change this.currentPageState = 0; this.from = 0; } }, promotedResults: function promotedResults(newVal, oldVal) { if (!isEqual$1(newVal, oldVal)) { this.$emit('data', this.getData()); } }, hidden: function hidden(newVal, oldVal) { if (!isEqual$1(newVal, oldVal)) { this.$emit('data', this.getData()); } }, time: function time(newVal, oldVal) { if (!isEqual$1(newVal, oldVal)) { this.$emit('data', this.getData()); } }, hits: function hits(newVal, oldVal) { this.$emit('data', this.getData()); if (this.shouldRenderPagination) { // called when page is changed if (this.isLoading && (oldVal || newVal)) { if (this.hasPageChangeListener) { this.$emit('pageChange', this.currentPageState + 1, this.totalPages); this.$emit('page-change', this.currentPageState + 1, this.totalPages); } else if (this.scrollOnChange) { window.scrollTo(0, 0); } } } else if (oldVal && newVal) { if (oldVal.length !== newVal.length || newVal.length === this.$props.total) { if (newVal.length < oldVal.length) { // query has changed if (this.scrollOnChange) { window.scrollTo(0, 0); } this.from = 0; } } } }, rawData: function rawData(newVal, oldVal) { if (!isEqual$1(newVal, oldVal)) { this.$emit('data', this.getData()); } }, currentPage: function currentPage(newVal, oldVal) { if (oldVal !== newVal && newVal > 0 && newVal <= this.totalPages) { this.setPage(newVal - 1); } }, infiniteScroll: function infiniteScroll(newVal, oldVal) { if (newVal !== oldVal) { if (newVal && !this.pagination) { window.addEventListener('scroll', this.scrollHandler); } else { window.removeEventListener('scroll', this.scrollHandler); } } }, pagination: function pagination(newVal, oldVal) { if (newVal !== oldVal) { if (!newVal && this.infiniteScroll) { window.addEventListener('scroll', this.scrollHandler); } else { window.removeEventListener('scroll', this.scrollHandler); } } // handle window url history change (on native back and forth interactions) }, defaultPage: function defaultPage(newVal, oldVal) { if (this.currentPageState !== newVal && oldVal !== newVal) { this.setPage(newVal >= 0 ? newVal : 0); } }, isLoading: function isLoading(newVal, oldVal) { if (newVal !== oldVal) { this.$emit('loading', newVal); } } }, mounted: function mounted() { if (this.defaultPage < 0 && this.currentPage > 0) { this.setPageURL(this.$props.componentId, this.currentPage, this.$props.componentId, false, this.URLParams); } var options = getQueryOptions(this.$props); options.from = this.$data.from; if (this.sortOptions && this.sortOptions[this.sortOptionIndex]) { var _ref; var sortField = this.sortOptions[this.sortOptionIndex].dataField; var sortBy = this.sortOptions[this.sortOptionIndex].sortBy; options.sort = [(_ref = {}, _ref[sortField] = { order: sortBy }, _ref)]; // To handle sort options for RS API this.updateComponentProps(this.componentId, { dataField: sortField, sortBy: sortBy }, constants.componentTypes.reactiveList); } else if (this.$props.sortBy) { var _ref2; options.sort = [(_ref2 = {}, _ref2[this.$props.dataField] = { order: this.$props.sortBy }, _ref2)]; } // Override sort query with defaultQuery's sort if defined this.$defaultQuery = null; if (this.$props.defaultQuery) { this.$defaultQuery = this.$props.defaultQuery(); options = _rollupPluginBabelHelpers._extends({}, options, getOptionsForCustomQuery(this.$defaultQuery)); // Update calculated default query in store index.updateDefaultQuery(this.componentId, this.setDefaultQuery, this.$props); } // execute is set to false at the time of mount var query = extractQueryFromCustomQuery(this.$defaultQuery); var execute = false; this.setQueryOptions(this.$props.componentId, _rollupPluginBabelHelpers._extends({}, options, this.getAggsQuery()), execute); if (this.$defaultQuery) { this.updateQuery({ componentId: this.internalComponent, query: query }, execute); } else { this.updateQuery({ componentId: this.internalComponent, query: null }, execute); } // query will be executed here if (this.showInfiniteScroll) { window.addEventListener('scroll', this.scrollHandler); } }, beforeUnmount: function beforeUnmount() { if (this.showInfiniteScroll) { window.removeEventListener('scroll', this.scrollHandler); } }, render: function render() { var _this2 = this; var hits = this.$data.hits; var results = parseHits(hits) || []; return vue.createVNode("div", { "style": this.$props.style, "class": this.$props.className }, [this.isLoading && this.shouldRenderPagination && this.showInfiniteScroll && (this.$slots.loader || this.$props.loader), this.renderErrorComponent(), vue.createVNode(Flex.Flex, { "labelPosition": this.sortOptions ? 'right' : 'left', "class": getClassName(this.$props.innerClass, 'resultsInfo') }, { "default": function _default() { return [_this2.sortOptions ? _this2.renderSortOptions() : null, _this2.$props.showResultStats && results.length ? _this2.renderStats() : null]; } }), !this.isLoading && hits && hits.length === 0 ? this.renderNoResult() : null, this.shouldRenderPagination && (this.$props.paginationAt === 'top' || this.$props.paginationAt === 'both') ? vue.createVNode(Pagination.Pagination, { "pages": this.$props.pages, "totalPages": this.totalPages, "currentPage": this.currentPageState, "setPage": this.setPage, "innerClass": this.$props.innerClass, "prevLabel": this.$props.prevLabel, "nextLabel": this.$props.nextLabel }, null) : null, this.renderResults(), this.isLoading && !this.shouldRenderPagination ? this.$slots.loader || this.$props.loader || vue.createVNode("div", { "style": { textAlign: 'center', margin: '20px 0', color: '#666' } }, [vue.createTextVNode("Loading...")]) : null, this.shouldRenderPagination && (this.$props.paginationAt === 'bottom' || this.$props.paginationAt === 'both') ? vue.createVNode(Pagination.Pagination, { "pages": this.$props.pages, "totalPages": Math.ceil(this.$data.total / this.$props.size), "currentPage": this.currentPageState, "setPage": this.setPage, "showEndPage": this.$props.showEndPage, "innerClass": this.$props.innerClass, "prevLabel": this.$props.prevLabel, "nextLabel": this.$props.nextLabel }, null) : null, this.url.endsWith('appbase.io') && results.length ? vue.createVNode(Flex.Flex, { "direction": "row-reverse", "class": getClassName(this.$props.innerClass, 'poweredBy') }, { "default": function _default() { return [vue.createVNode(PoweredBy, null, null)]; } }) : null]); }, methods: { renderErrorComponent: function renderErrorComponent() { var renderError = this.$slots.renderError || this.$props.renderError; if (renderError && this.error && !this.isLoading) { return index.isFunction(renderError) ? renderError(this.error) : renderError; } return null; }, renderResults: function renderResults() { var _this3 = this; var size = this.$props.size; var renderItem = this.$slots.renderItem || this.$props.renderItem; var element = this.hasCustomRender ? this.getComponent() : vue.createVNode("div", { "class": this.$props.listClass + " " + getClassName(this.$props.innerClass, 'list') }, [this.data.map(function (item, index) { return renderItem({ item: item, count: _this3.currentPageState * size + index + 1, triggerClickAnalytics: function triggerClickAnalytics() { return _this3.triggerClickAnalytics(_this3.currentPageState * size + index); } }); })]); // If analytics is set to true then render with impression tracker return this.analytics ? vue.createVNode(ImpressionTracker$1, { "hits": this.data }, _isSlot(element) ? element : { "default": function _default() { return [element]; } }) : element; }, updateQueryOptions: function updateQueryOptions(props) { var options = getQueryOptions(props); options.from = this.$data.from; if (props.sortOptions && Array.isArray(props.sortOptions)) { var sortOptionIndex = props.defaultSortOption ? props.sortOptions.findIndex(function (s) { return s.label === props.defaultSortOption; }) : 0; if (props.sortOptions[sortOptionIndex]) { var _ref3; options.sort = [(_ref3 = {}, _ref3[props.sortOptions[sortOptionIndex].dataField] = { order: props.sortOptions[sortOptionIndex].sortBy }, _ref3)]; } } else if (props.sortBy) { var _ref4; options.sort = [(_ref4 = {}, _ref4[props.dataField] = { order: props.sortBy }, _ref4)]; } this.setQueryOptions(this.$props.componentId, _rollupPluginBabelHelpers._extends({}, options, this.getAggsQuery()), true); }, getAggsQuery: function getAggsQuery() { var _this$$props = this.$props, size = _this$$props.size, aggregationField = _this$$props.aggregationField; var afterKey = this.$data.afterKey; var queryOptions = { size: size }; if (aggregationField) { queryOptions.aggs = getCompositeAggsQuery({ props: this.$props, after: afterKey || null, showTopHits: true }).aggs; } return queryOptions; }, scrollHandler: function scrollHandler() { if (!this.isLoading && window.innerHeight + window.pageYOffset + 300 >= document.body.scrollHeight) { this.loadMore(); } }, loadMore: function loadMore() { if (this.aggregationField && !this.afterKey) return; if (this.hits && !this.shouldRenderPagination && this.total > this.hits.length) { var value = this.$data.from + this.$props.size; // If current hits length is less than the current from then it means // that there are no results present. // It can happen because of many reasons some of them are: // 1. Using the `collapse` query to remove results // 2. Shard failure // In above cases infinite scroll should not load more results that can // cause the resetting of the `from` value if (this.hits.length < value) { return; } var options = _rollupPluginBabelHelpers._extends({}, getQueryOptions(this.$props), this.getAggsQuery()); this.from = value; // Update default query to support pagination for aggregationField index.updateDefaultQuery(this.componentId, this.setDefaultQuery, this.$props); this.loadMoreAction(this.$props.componentId, _rollupPluginBabelHelpers._extends({}, options, { from: value }), true, !!this.aggregationField); } }, setPage: function setPage(page) { // pageClick will be called every time a pagination button is clicked if (page !== this.currentPageState) { this.$emit('pageClick', page + 1); this.$emit('page-click', page + 1); var value = this.$props.size * page; var options = getQueryOptions(this.$props); options.from = this.$data.from; this.from = value; this.currentPageState = page; this.loadMoreAction(this.$props.componentId, _rollupPluginBabelHelpers._extends({}, options, { from: value }), false); this.setPageURL(this.$props.componentId, page + 1, this.$props.componentId, false, this.URLParams); } }, renderStats: function renderStats() { var renderResultStats = this.$slots.renderResultStats || this.$props.renderResultStats; if (renderResultStats && this.$data.total) { return renderResultStats(this.stats); } if (this.stats.numberOfResults) { return vue.createVNode("p", { "class": resultStats + " " + getClassName(this.$props.innerClass, 'resultStats') }, [this.stats.numberOfResults, vue.createTextVNode(" results found in "), this.stats.time || 0, vue.createTextVNode("ms")]); } return null; }, renderNoResult: function renderNoResult() { var renderNoResults = this.$slots.renderNoResults || this.$props.renderNoResults; if (this.$slots.renderNoResults) { return index.isFunction(renderNoResults) ? renderNoResults() : renderNoResults; } return vue.createVNode("p", { "class": getClassName(this.$props.innerClass, 'noResults') || null }, [index.isFunction(renderNoResults) ? renderNoResults() : renderNoResults]); }, handleSortChange: function handleSortChange(e) { var index = e.target.value; if (this.sortOptions && this.sortOptions[index]) { var _ref5; // This fixes issue #371 (where sorting a multi-result page with infinite loader breaks) var options = getQueryOptions(this.$props); options.from = 0; var sortField = this.sortOptions[index].dataField; var sortBy = this.sortOptions[index].sortBy; options.sort = [(_ref5 = {}, _ref5[sortField] = { order: sortBy }, _ref5)]; this.sortOptionIndex = index; // To handle sort options for RS API this.updateComponentProps(this.componentId, { dataField: sortField, sortBy: sortBy }, constants.componentTypes.reactiveList); this.setQueryOptions(this.$props.componentId, options, true); this.setPage(0); this.currentPageState = 0; this.from = 0; var sortOption = this.$props.sortOptions[this.sortOptionIndex] ? this.$props.sortOptions[this.sortOptionIndex].label : null; this.setPageURL(this.$props.componentId + "sortOption", sortOption, this.$props.componentId + "sortOption", false, this.$props.URLParams); } }, triggerClickAnalytics: function triggerClickAnalytics(searchPosition, documentId) { var docId = documentId; if (!docId) { var _this$getData = this.getData(), data = _this$getData.data; var hitData = data.find(function (hit) { return hit._click_id === searchPosition; }); if (hitData && hitData._id) { docId = hitData._id; } } this.recordResultClick(searchPosition, docId); }, renderSortOptions: function renderSortOptions() { return vue.createVNode("select", vue.mergeProps(_transformOn({ change: this.handleSortChange }), { "class": sortOptions + " " + getClassName(this.$props.innerClass, 'sortOptions'), "name": "sort-options", "aria-label": "Sort options", "value": this.sortOptionIndex }), [this.sortOptions.map(function (sort, index) { return vue.createVNode("option", { "key": sort.label, "value": index }, [sort.label]); })]); }, withClickIds: function withClickIds(results) { var _this$getAllData = this.getAllData(), base = _this$getAllData.base; return results.map(function (result, index) { return _rollupPluginBabelHelpers._extends({}, result, { _click_id: base + index }); }); }, // Shape of the object to be returned in onData & render getAllData: function getAllData() { var size = this.size, promotedResults = this.promotedResults, aggregationData = this.aggregationData, customData = this.customData, currentPage = this.currentPage, hits = this.hits; var results = parseHits(hits) || []; var parsedPromotedResults = parseHits(promotedResults) || []; var base = currentPage * size; return { results: results, customData: customData || {}, promotedResults: parsedPromotedResults, aggregationData: aggregationData, loadMore: this.loadMore, base: base, triggerClickAnalytics: this.triggerClickAnalytics }; }, getData: function getData() { var _this$getAllData2 = this.getAllData(), promotedResults = _this$getAllData2.promotedResults, aggregationData = _this$getAllData2.aggregationData, customData = _this$getAllData2.customData; return { data: this.data, aggregationData: this.withClickIds(aggregationData || []), promotedData: this.withClickIds(promotedResults || []), rawData: this.rawData, resultStats: this.stats, customData: customData }; }, getComponent: function getComponent() { var error = this.error, isLoading = this.isLoading; var data = _rollupPluginBabelHelpers._extends({ error: error, loading: isLoading || false, loadMore: this.loadMore, triggerClickAnalytics: this.triggerClickAnalytics, setPage: this.setPage }, this.getData()); return index.getComponent(data, this); } } }; var mapStateToProps = function mapStateToProps(state, props) { return { defaultPage: state.selectedValues[props.componentId] && state.selectedValues[props.componentId].value - 1, urlSortOption: state.selectedValues[props.componentId + "sortOption"] && state.selectedValues[props.componentId + "sortOption"].value, hits: state.hits[props.componentId] && state.hits[props.componentId].hits, rawData: state.rawData[props.componentId], aggregationData: state.compositeAggregations[props.componentId], promotedResults: state.promotedResults[props.componentId], customData: state.customData[props.componentId], time: state.hits[props.componentId] && state.hits[props.componentId].time, total: state.hits[props.componentId] && state.hits[props.componentId].total, hidden: state.hits[props.componentId] && state.hits[props.componentId].hidden, analytics: state.config && state.config.analytics, url: state.config.url, error: state.error[props.componentId], afterKey: state.aggregations[props.componentId] && state.aggregations[props.componentId][props.aggregationField] && state.aggregations[props.componentId][props.aggregationField].after_key, componentProps: state.props[props.componentId], isLoading: state.isLoading[props.componentId] }; }; var mapDispatchtoProps = { loadMoreAction: loadMore, setPageURL: setValue, setQueryOptions: setQueryOptions, updateQuery: updateQuery, updateComponentProps: updateComponentProps, setDefaultQuery: setDefaultQuery, recordResultClick: recordResultClick }; // Only used for SSR ReactiveList.generateQueryOptions = function (props) { var options = getQueryOptions(props); var size = props.size, dataField = props.dataField, defaultSortOption = props.defaultSortOption, sortOptionsNew = props.sortOptions, currentPage = props.currentPage, sortBy = props.sortBy; options.from = currentPage ? (currentPage - 1) * (size || 10) : 0; options.size = size || 10; var getSortOption = function getSortOption() { var _ref7; if (defaultSortOption) { var sortOption = sortOptionsNew.find(function (option) { return option.label === defaultSortOption; }); if (sortOption) { var _ref6; return _ref6 = {}, _ref6[sortOption.dataField] = { order: sortOption.sortBy }, _ref6; } } return _ref7 = {}, _ref7[sortOptionsNew[0].dataField] = { order: sortOptionsNew[0].sortBy }, _ref7; }; if (sortOptionsNew) { options.sort = [getSortOption()]; } else if (sortBy) { var _ref8; options.sort = [(_ref8 = {}, _ref8[dataField] = { order: sortBy }, _ref8)]; } return options; }; ReactiveList.hasInternalComponent = function () { return true; }; var RLConnected = PreferencesConsumer.PreferencesConsumer(ComponentWrapper.ComponentWrapper(index.connect(mapStateToProps, mapDispatchtoProps)(ReactiveList), { componentType: constants.componentTypes.reactiveList, internalComponent: ReactiveList.hasInternalComponent() })); RLConnected.name = ReactiveList.name; RLConnected.generateQueryOptions = ReactiveList.generateQueryOptions; RLConnected.hasInternalComponent = ReactiveList.hasInternalComponent; RLConnected.install = function (Vue) { Vue.component(RLConnected.name, RLConnected); Vue.component(ResultListWrapper.name, ResultListWrapper); Vue.component(ResultCardsWrapper.name, ResultCardsWrapper); }; // Add componentType for SSR RLConnected.componentType = constants.componentTypes.reactiveList; exports.RLConnected = RLConnected; exports.default = RLConnected;