UNPKG

@atlaskit/global-search

Version:

A cross-product search component (batteries included)

503 lines (423 loc) 24.3 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.JiraQuickSearchContainer = void 0; var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized")); var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _taggedTemplateLiteral2 = _interopRequireDefault(require("@babel/runtime/helpers/taggedTemplateLiteral")); var _react = _interopRequireDefault(require("react")); var _reactIntl = require("react-intl"); var _styledComponents = _interopRequireDefault(require("styled-components")); var _theme = require("@atlaskit/theme"); var _analytics = require("@atlaskit/analytics"); var _analyticsNext = require("@atlaskit/analytics-next"); var _StickyFooter = _interopRequireDefault(require("../common/StickyFooter")); var _ScreenCounter = require("../../util/ScreenCounter"); var _types = require("../../api/types"); var _QuickSearchContainer = require("../common/QuickSearchContainer"); var _messages = require("../../messages"); var _SearchResults = _interopRequireDefault(require("../common/SearchResults")); var _NoResultsState = _interopRequireDefault(require("./NoResultsState")); var _JiraAdvancedSearch = _interopRequireDefault(require("./JiraAdvancedSearch")); var _JiraSearchResultsMapper = require("./JiraSearchResultsMapper"); var _SearchResultsUtil = require("../SearchResultsUtil"); var _Result = require("../../model/Result"); var _ResultList = require("../ResultList"); var _performanceNow = _interopRequireDefault(require("../../util/performance-now")); var _analyticsEventHelper = require("../../util/analytics-event-helper"); var _AdvancedIssueSearchLink = _interopRequireDefault(require("./AdvancedIssueSearchLink")); var _experimentUtils = require("../../util/experiment-utils"); var _modelParameters = require("../../util/model-parameters"); var _FeaturesProvider = require("../FeaturesProvider"); var _JiraItemMapper = require("../../api/JiraItemMapper"); var _searchResultsUtils = require("../../util/search-results-utils"); var _templateObject, _templateObject2; function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } var JIRA_RESULT_LIMIT = 6; var JIRA_PREQUERY_RESULT_LIMIT = 10; var NoResultsAdvancedSearchContainer = _styledComponents.default.div(_templateObject || (_templateObject = (0, _taggedTemplateLiteral2.default)(["\n margin-top: ", "px;\n"])), 4 * (0, _theme.gridSize)()); var BeforePreQueryStateContainer = _styledComponents.default.div(_templateObject2 || (_templateObject2 = (0, _taggedTemplateLiteral2.default)(["\n margin-top: ", "px;\n"])), (0, _theme.gridSize)()); var containsQuery = function containsQuery(string, query) { return string.toLowerCase().indexOf(query.toLowerCase()) > -1; }; var getRecentItemMatches = function getRecentItemMatches(query, recentItems) { if (!recentItems) { return []; } var issueKeyMatches = recentItems.objects.filter(function (result) { return result.objectKey && containsQuery(result.objectKey, query); }); var titleMatches = recentItems.objects.filter(function (result) { return containsQuery(result.name, query); }); return issueKeyMatches.concat(titleMatches).slice(0, _JiraSearchResultsMapper.MAX_RECENT_RESULTS_TO_SHOW); }; var mergeSearchResultsWithRecentItems = function mergeSearchResultsWithRecentItems(searchResults, recentItems) { var defaultSearchResults = { objects: [], containers: [], people: [] }; var results = _objectSpread(_objectSpread({}, defaultSearchResults), searchResults); return { objects: (0, _searchResultsUtils.appendListWithoutDuplication)(recentItems, results.objects), containers: results.containers, people: results.people }; }; /** * NOTE: This component is only consumed internally as such avoid using optional props * i.e. instead of "propX?: something" use "propX: something | undefined" * * This improves type safety and prevent us from accidentally forgetting a parameter. */ var SCOPES = [_types.Scope.JiraIssue, _types.Scope.JiraBoardProjectFilter]; var LOGGER_NAME = 'AK.GlobalSearch.JiraQuickSearchContainer'; /** * Container/Stateful Component that handles the data fetching and state handling when the user interacts with Search. */ var JiraQuickSearchContainer = /*#__PURE__*/function (_React$Component) { (0, _inherits2.default)(JiraQuickSearchContainer, _React$Component); var _super = _createSuper(JiraQuickSearchContainer); function JiraQuickSearchContainer() { var _this; (0, _classCallCheck2.default)(this, JiraQuickSearchContainer); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _super.call.apply(_super, [this].concat(args)); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "state", { selectedAdvancedSearchType: _SearchResultsUtil.JiraEntityTypes.Issues }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "screenCounters", { preQueryScreenCounter: new _ScreenCounter.SearchScreenCounter(), postQueryScreenCounter: new _ScreenCounter.SearchScreenCounter() }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "handleSearchSubmit", function (event, searchSessionId) { var _this$props$onAdvance = _this.props.onAdvancedSearch, onAdvancedSearch = _this$props$onAdvance === void 0 ? function () {} : _this$props$onAdvance; var target = event.target; var query = target.value; var defaultPrevented = false; onAdvancedSearch(Object.assign({}, event, { preventDefault: function preventDefault() { defaultPrevented = true; event.preventDefault(); event.stopPropagation(); }, stopPropagation: function stopPropagation() {} }), _this.state.selectedAdvancedSearchType, query, searchSessionId); if (!defaultPrevented) { (0, _SearchResultsUtil.redirectToJiraAdvancedSearch)(_this.state.selectedAdvancedSearchType, query); } }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "handleAdvancedSearch", function (event, entity, query, searchSessionId, analyticsData, isLoading) { var _this$props = _this.props, referralContextIdentifiers = _this$props.referralContextIdentifiers, _this$props$onAdvance2 = _this$props.onAdvancedSearch, onAdvancedSearch = _this$props$onAdvance2 === void 0 ? function () {} : _this$props$onAdvance2; var eventData = _objectSpread(_objectSpread({ resultId: _SearchResultsUtil.ADVANCED_JIRA_SEARCH_RESULT_ID }, analyticsData), {}, { query: query, // queryversion is missing contentType: entity, type: _Result.AnalyticsType.AdvancedSearchJira, isLoading: isLoading }); (0, _analyticsEventHelper.fireSelectedAdvancedSearch)(eventData, searchSessionId, referralContextIdentifiers, _this.props.createAnalyticsEvent); onAdvancedSearch(event, entity, query, searchSessionId); }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "getPreQueryDisplayedResults", function (recentItems, searchSessionId) { var features = _this.props.features; return (0, _JiraSearchResultsMapper.mapRecentResultsToUIGroups)(recentItems, searchSessionId, features, _this.props.appPermission); }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "getPostQueryDisplayedResults", function (searchResults, latestSearchQuery, recentItems, isLoading, searchSessionId) { var features = _this.props.features; if (features.isInFasterSearchExperiment) { var currentSearchResults = isLoading || !searchResults ? {} : searchResults; var recentResults = getRecentItemMatches(latestSearchQuery, recentItems); var mergedRecentSearchResults = mergeSearchResultsWithRecentItems(currentSearchResults, recentResults); return (0, _JiraSearchResultsMapper.mapSearchResultsToUIGroups)(mergedRecentSearchResults, searchSessionId, features, _this.props.appPermission, latestSearchQuery); } return (0, _JiraSearchResultsMapper.mapSearchResultsToUIGroups)(searchResults, searchSessionId, features, _this.props.appPermission, latestSearchQuery); }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "getSearchResultsComponent", function (_ref) { var retrySearch = _ref.retrySearch, latestSearchQuery = _ref.latestSearchQuery, isError = _ref.isError, searchResults = _ref.searchResults, isLoading = _ref.isLoading, recentItems = _ref.recentItems, keepPreQueryState = _ref.keepPreQueryState, searchSessionId = _ref.searchSessionId, searchMore = _ref.searchMore, currentFilters = _ref.currentFilters, onFilterChanged = _ref.onFilterChanged; var query = latestSearchQuery; var _this$props2 = _this.props, referralContextIdentifiers = _this$props2.referralContextIdentifiers, _this$props2$onAdvanc = _this$props2.onAdvancedSearch, onAdvancedSearch = _this$props2$onAdvanc === void 0 ? function () {} : _this$props2$onAdvanc, appPermission = _this$props2.appPermission, features = _this$props2.features, isJiraPeopleProfilesEnabled = _this$props2.isJiraPeopleProfilesEnabled; return /*#__PURE__*/_react.default.createElement(_SearchResults.default, (0, _extends2.default)({ query: query, isPreQuery: !query, isError: isError, isLoading: isLoading, retrySearch: retrySearch, keepPreQueryState: features.isInFasterSearchExperiment ? false : keepPreQueryState, searchSessionId: searchSessionId }, _this.screenCounters, { referralContextIdentifiers: referralContextIdentifiers, searchMore: searchMore, currentFilters: currentFilters, onFilterChanged: onFilterChanged, renderNoRecentActivity: function renderNoRecentActivity() { return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedHTMLMessage, _messages.messages.jira_no_recent_activity_body), /*#__PURE__*/_react.default.createElement(NoResultsAdvancedSearchContainer, null, /*#__PURE__*/_react.default.createElement(_JiraAdvancedSearch.default, { appPermission: appPermission, query: query, analyticsData: { resultsCount: 0, wasOnNoResultsScreen: true }, onClick: function onClick(mouseEvent, entity) { return _this.handleAdvancedSearch(mouseEvent, entity, query, searchSessionId, { resultsCount: 0, wasOnNoResultsScreen: true }, isLoading); }, isJiraPeopleProfilesEnabled: isJiraPeopleProfilesEnabled }))); }, renderAdvancedSearchGroup: function renderAdvancedSearchGroup(analyticsData) { return /*#__PURE__*/_react.default.createElement(_StickyFooter.default, { style: { marginTop: "".concat(2 * (0, _theme.gridSize)(), "px") } }, /*#__PURE__*/_react.default.createElement(_JiraAdvancedSearch.default, { appPermission: appPermission, analyticsData: analyticsData, query: query, onClick: function onClick(mouseEvent, entity) { return _this.handleAdvancedSearch(mouseEvent, entity, query, searchSessionId, analyticsData, isLoading); }, isJiraPeopleProfilesEnabled: isJiraPeopleProfilesEnabled })); }, renderBeforePreQueryState: function renderBeforePreQueryState() { return /*#__PURE__*/_react.default.createElement(BeforePreQueryStateContainer, null, /*#__PURE__*/_react.default.createElement(_AdvancedIssueSearchLink.default, { onClick: function onClick(_ref2) { var event = _ref2.event; return onAdvancedSearch(event, _SearchResultsUtil.JiraEntityTypes.Issues, query, searchSessionId); } })); }, getPreQueryGroups: function getPreQueryGroups() { return _this.getPreQueryDisplayedResults(recentItems, searchSessionId); }, getPostQueryGroups: function getPostQueryGroups() { return _this.getPostQueryDisplayedResults(searchResults, latestSearchQuery, recentItems, isLoading, searchSessionId); }, renderNoResult: function renderNoResult() { return /*#__PURE__*/_react.default.createElement(_NoResultsState.default, { query: query, onAdvancedSearch: function onAdvancedSearch(mouseEvent, entity) { return _this.handleAdvancedSearch(mouseEvent, entity, query, searchSessionId, { resultsCount: 0, wasOnNoResultsScreen: true }, isLoading); }, isJiraPeopleProfilesEnabled: isJiraPeopleProfilesEnabled }); } })); }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "getRecentlyInteractedPeople", function () { /* the following code is temporarily feature flagged for performance reasons and will be shortly reinstated. https://product-fabric.atlassian.net/browse/QS-459 */ if (_this.props.features.disableJiraPreQueryPeopleSearch) { return Promise.resolve([]); } else { var peoplePromise = _this.props.peopleSearchClient.getRecentPeople(); return (0, _SearchResultsUtil.handlePromiseError)(peoplePromise, [], function (error) { return _this.props.logger.safeError(LOGGER_NAME, 'error in recently interacted people promise', error); }); } }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "getJiraRecentItems", function () { var features = _this.props.features; return _this.props.crossProductSearchClient.getRecentItems({ context: 'jira', modelParams: [], resultLimit: (0, _experimentUtils.getJiraMaxObjects)(features.abTest, JIRA_PREQUERY_RESULT_LIMIT), mapItemToResult: function mapItemToResult(_, item) { return (0, _JiraItemMapper.mapJiraItemToResult)(_Result.AnalyticsType.RecentJira)(item); } }).then(function (xpRecentResults) { var objects = xpRecentResults.results[_types.Scope.JiraIssue]; var containers = xpRecentResults.results[_types.Scope.JiraBoardProjectFilter]; return { objects: objects ? objects.items : [], containers: containers ? containers.items : [], people: [] }; }).catch(function (error) { _this.props.logger.safeError(LOGGER_NAME, 'error in recent Jira items promise', error); return { objects: [], containers: [], people: [] }; }); }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "canSearchUsers", function () { /* the following code is temporarily feature flagged for performance reasons and will be shortly reinstated. https://product-fabric.atlassian.net/browse/QS-459 */ if (_this.props.features.disableJiraPreQueryPeopleSearch) { return Promise.resolve(false); } else { return (0, _SearchResultsUtil.handlePromiseError)(_this.props.jiraClient.canSearchUsers(), false, function (error) { return _this.props.logger.safeError(LOGGER_NAME, 'error fetching browse user permission', error); }); } }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "getRecentItems", function () { return { eagerRecentItemsPromise: _this.getJiraRecentItems().then(function (results) { return { results: results }; }), lazyLoadedRecentItemsPromise: Promise.all([_this.getRecentlyInteractedPeople(), _this.canSearchUsers()]).then(function (_ref3) { var _ref4 = (0, _slicedToArray2.default)(_ref3, 2), people = _ref4[0], canSearchUsers = _ref4[1]; return { people: canSearchUsers ? people : [] }; }) }; }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "getSearchResults", function (query, sessionId, startTime, queryVersion) { var features = _this.props.features; var referrerId = _this.props.referralContextIdentifiers && _this.props.referralContextIdentifiers.searchReferrerId; var crossProductSearchPromise = _this.props.crossProductSearchClient.search({ query: query, sessionId: sessionId, referrerId: referrerId, scopes: SCOPES, modelParams: (0, _modelParameters.buildJiraModelParams)(queryVersion, _this.props.referralContextIdentifiers && _this.props.referralContextIdentifiers.currentContainerId), resultLimit: (0, _experimentUtils.getJiraMaxObjects)(features.abTest, JIRA_RESULT_LIMIT) }); var searchPeoplePromise = Promise.resolve([]); var mapPromiseToPerformanceTime = function mapPromiseToPerformanceTime(p) { return p.then(function () { return (0, _performanceNow.default)() - startTime; }); }; return Promise.all([crossProductSearchPromise, searchPeoplePromise, mapPromiseToPerformanceTime(crossProductSearchPromise), mapPromiseToPerformanceTime(searchPeoplePromise), _this.canSearchUsers()]).then(function (_ref5) { var _ref6 = (0, _slicedToArray2.default)(_ref5, 5), xpsearchResults = _ref6[0], peopleResults = _ref6[1], crossProductSearchElapsedMs = _ref6[2], peopleElapsedMs = _ref6[3], canSearchPeople = _ref6[4]; var objects = xpsearchResults.results[_types.Scope.JiraIssue]; var containers = xpsearchResults.results[_types.Scope.JiraBoardProjectFilter]; var objectItems = objects ? objects.items : []; _this.highlightMatchingFirstResult(query, objectItems); return { results: { objects: objectItems, containers: containers ? containers.items : [], people: canSearchPeople ? peopleResults : [] }, timings: { crossProductSearchElapsedMs: crossProductSearchElapsedMs, peopleElapsedMs: peopleElapsedMs }, abTest: xpsearchResults.abTest }; }); }); return _this; } (0, _createClass2.default)(JiraQuickSearchContainer, [{ key: "highlightMatchingFirstResult", value: function highlightMatchingFirstResult(query, issueResults) { if (issueResults && issueResults.length > 0 && typeof issueResults[0].objectKey === 'string' && (issueResults[0].objectKey.toLowerCase() === query.toLowerCase() || !!+query && issueResults[0].objectKey.toLowerCase().endsWith("".concat(-query)))) { this.setState({ selectedResultId: (0, _ResultList.getUniqueResultId)(issueResults[0]) }); } } }, { key: "handleSelectedResultIdChanged", value: function handleSelectedResultIdChanged(newSelectedId) { this.setState({ selectedResultId: newSelectedId }); } }, { key: "render", value: function render() { var _this2 = this; var _this$props3 = this.props, linkComponent = _this$props3.linkComponent, createAnalyticsEvent = _this$props3.createAnalyticsEvent, logger = _this$props3.logger, features = _this$props3.features, referralContextIdentifiers = _this$props3.referralContextIdentifiers, isJiraPeopleProfilesEnabled = _this$props3.isJiraPeopleProfilesEnabled; var selectedResultId = this.state.selectedResultId; return /*#__PURE__*/_react.default.createElement(_QuickSearchContainer.BaseJiraQuickSearchContainerJira, { placeholder: this.props.intl.formatMessage(_messages.messages.jira_search_placeholder), linkComponent: linkComponent, getPreQueryDisplayedResults: function getPreQueryDisplayedResults(recentItems, searchSessionId) { return _this2.getPreQueryDisplayedResults(recentItems, searchSessionId); }, getPostQueryDisplayedResults: this.getPostQueryDisplayedResults, getSearchResultsComponent: this.getSearchResultsComponent, getRecentItems: this.getRecentItems, getSearchResults: this.getSearchResults, handleSearchSubmit: this.handleSearchSubmit // @ts-ignore , createAnalyticsEvent: createAnalyticsEvent, logger: logger, selectedResultId: selectedResultId, onSelectedResultIdChanged: function onSelectedResultIdChanged(newId) { return _this2.handleSelectedResultIdChanged(newId); }, referralContextIdentifiers: referralContextIdentifiers, product: "jira", features: features, advancedSearchId: _SearchResultsUtil.ADVANCED_JIRA_SEARCH_RESULT_ID, isJiraPeopleProfilesEnabled: isJiraPeopleProfilesEnabled }); } }]); return JiraQuickSearchContainer; }(_react.default.Component); exports.JiraQuickSearchContainer = JiraQuickSearchContainer; var JiraQuickSearchContainerWithIntl = (0, _reactIntl.injectIntl)((0, _analytics.withAnalytics)(JiraQuickSearchContainer, {}, {})); var _default = (0, _FeaturesProvider.injectFeatures)((0, _analyticsNext.withAnalyticsEvents)()(JiraQuickSearchContainerWithIntl)); exports.default = _default;