@atlaskit/global-search
Version:
A cross-product search component (batteries included)
503 lines (423 loc) • 24.3 kB
JavaScript
;
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;