@atlaskit/mention
Version:
A React component used to display user profiles in a list for 'Mention' functionality
301 lines (295 loc) • 14.5 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _analytics = require("./../util/analytics");
var _utilServiceSupport = require("@atlaskit/util-service-support");
var _types = require("../types");
var _MentionResource2 = _interopRequireDefault(require("./MentionResource"));
var _logger = _interopRequireDefault(require("../util/logger"));
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2.default)(o), (0, _possibleConstructorReturn2.default)(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2.default)(t).constructor) : o.apply(t, e)); }
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
function _superPropGet(t, o, e, r) { var p = (0, _get2.default)((0, _getPrototypeOf2.default)(1 & r ? t.prototype : t), o, e); return 2 & r && "function" == typeof p ? function (t) { return p.apply(e, t); } : p; }
var MAX_QUERY_TEAMS = 20;
/**
* Provides a Javascript API to fetch users and teams
* In future we will have a new endpoint to return both users and teams, we can
* remove this class at this point
*/
var TeamMentionResource = exports.default = /*#__PURE__*/function (_MentionResource) {
function TeamMentionResource(userMentionConfig, teamMentionConfig) {
var _this;
(0, _classCallCheck2.default)(this, TeamMentionResource);
_this = _callSuper(this, TeamMentionResource, [userMentionConfig]);
(0, _defineProperty2.default)(_this, "lastSearchQuery", '');
_this.verifyMentionConfig(teamMentionConfig);
_this.teamMentionConfig = teamMentionConfig;
_this.lastReturnedSearchTeam = 0;
return _this;
}
(0, _inherits2.default)(TeamMentionResource, _MentionResource);
return (0, _createClass2.default)(TeamMentionResource, [{
key: "filter",
value: function filter(query, contextIdentifier) {
this.lastSearchQuery = query;
if (!query) {
return this.remoteInitialStateTeamAndUsers(contextIdentifier);
} else {
this.updateActiveSearches(query);
// both user and team requests start at the same time
var getUserPromise = this.remoteUserSearch(query, contextIdentifier);
var getTeamsPromise = this.remoteTeamSearch(query, contextIdentifier);
return this.handleBothRequests(query, getUserPromise, getTeamsPromise);
}
}
/**
* Returns the initial mention display list before a search is performed for the specified
* container.
*/
}, {
key: "remoteInitialStateTeamAndUsers",
value: (function () {
var _remoteInitialStateTeamAndUsers = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(contextIdentifier) {
var emptyQuery, getUserPromise, queryParams, configHeaders, options, getTeamsPromise;
return _regenerator.default.wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
emptyQuery = '';
getUserPromise = _superPropGet(TeamMentionResource, "remoteInitialState", this, 3)([contextIdentifier]);
queryParams = this.getQueryParamsOfTeamMentionConfig(contextIdentifier);
configHeaders = this.teamMentionConfig.headers;
options = _objectSpread({
path: 'bootstrap',
queryParams: queryParams
}, configHeaders && {
requestInit: {
headers: configHeaders
}
});
getTeamsPromise = _utilServiceSupport.utils.requestService(this.teamMentionConfig, options);
this.handleBothRequests(emptyQuery, getUserPromise, getTeamsPromise);
case 7:
case "end":
return _context.stop();
}
}, _callee, this);
}));
function remoteInitialStateTeamAndUsers(_x) {
return _remoteInitialStateTeamAndUsers.apply(this, arguments);
}
return remoteInitialStateTeamAndUsers;
}()
/**
* Both user and team requests are not blocked together
* If users request arrives first, show users. Show teams when team request arrives.
* If team request arrives first, block waiting for user request, then show both
* If one errors, show the non-erroring one
* If both error, show error
*/
)
}, {
key: "handleBothRequests",
value: (function () {
var _handleBothRequests = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(query, userRequest, teamRequest) {
var _this2 = this;
var searchTime, accumulatedResults, notifyWhenOneRequestDone, userResults, userRequestError, teamRequestError, teamsResult;
return _regenerator.default.wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
searchTime = Date.now();
accumulatedResults = {
mentions: [],
query: query
};
notifyWhenOneRequestDone = function notifyWhenOneRequestDone(results, hasTeamResults) {
// just update UI for the last query string
if (query !== _this2.lastSearchQuery) {
return;
}
accumulatedResults = {
mentions: [].concat((0, _toConsumableArray2.default)(accumulatedResults.mentions), (0, _toConsumableArray2.default)(results.mentions)),
query: query
};
// we need to calculate different `duration` for user and team request.
if (hasTeamResults) {
_this2.notify(searchTime, accumulatedResults, query);
} else {
_superPropGet(TeamMentionResource, "notify", _this2, 3)([searchTime, accumulatedResults, query]);
}
};
userRequestError = null;
teamRequestError = null;
_context2.prev = 5;
_context2.next = 8;
return userRequest;
case 8:
userResults = _context2.sent;
notifyWhenOneRequestDone(userResults, false);
_context2.next = 15;
break;
case 12:
_context2.prev = 12;
_context2.t0 = _context2["catch"](5);
userRequestError = _context2.t0;
case 15:
_context2.prev = 15;
_context2.next = 18;
return teamRequest;
case 18:
teamsResult = _context2.sent;
// update search time after team results returns
notifyWhenOneRequestDone(Array.isArray(teamsResult) ? this.convertTeamResultToMentionResult(teamsResult, query) : teamsResult, true);
_context2.next = 25;
break;
case 22:
_context2.prev = 22;
_context2.t1 = _context2["catch"](15);
teamRequestError = _context2.t1;
case 25:
// both requests fail, show one of errors in UI
if (userRequestError && teamRequestError) {
this.notifyError(userRequestError, query);
(0, _logger.default)('User mention request fails. ', userRequestError);
(0, _logger.default)('Team mention request fails. ', teamRequestError);
}
case 26:
case "end":
return _context2.stop();
}
}, _callee2, this, [[5, 12], [15, 22]]);
}));
function handleBothRequests(_x2, _x3, _x4) {
return _handleBothRequests.apply(this, arguments);
}
return handleBothRequests;
}())
}, {
key: "notify",
value: function notify(searchTime, mentionResult, query) {
if (searchTime > this.lastReturnedSearchTeam) {
this.lastReturnedSearchTeam = searchTime;
this._notifyListeners(mentionResult, {
teamMentionDuration: Date.now() - searchTime
});
} else {
var date = new Date(searchTime).toISOString().substr(17, 6);
(0, _logger.default)('Stale search result, skipping', date, query); // eslint-disable-line no-console, max-len
}
this._notifyAllResultsListeners(mentionResult);
}
}, {
key: "getQueryParamsOfTeamMentionConfig",
value: function getQueryParamsOfTeamMentionConfig(contextIdentifier) {
var configParams = {};
if (this.teamMentionConfig.containerId) {
configParams['containerId'] = this.teamMentionConfig.containerId;
}
if (this.teamMentionConfig.productId) {
configParams['productIdentifier'] = this.teamMentionConfig.productId;
}
// if contextParams exist then it will override configParams for containerId
return _objectSpread(_objectSpread({}, configParams), contextIdentifier);
}
}, {
key: "remoteUserSearch",
value: function remoteUserSearch(query, contextIdentifier) {
return _superPropGet(TeamMentionResource, "remoteSearch", this, 3)([query, contextIdentifier]);
}
}, {
key: "remoteTeamSearch",
value: function () {
var _remoteTeamSearch = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3(query, contextIdentifier) {
var configHeaders, options, teamResult;
return _regenerator.default.wrap(function _callee3$(_context3) {
while (1) switch (_context3.prev = _context3.next) {
case 0:
configHeaders = this.teamMentionConfig.headers;
options = _objectSpread({
path: 'search',
queryParams: _objectSpread({
query: query,
limit: MAX_QUERY_TEAMS
}, this.getQueryParamsOfTeamMentionConfig(contextIdentifier))
}, configHeaders && {
requestInit: {
headers: configHeaders
}
});
_context3.prev = 2;
_context3.next = 5;
return _utilServiceSupport.utils.requestService(this.teamMentionConfig, options);
case 5:
teamResult = _context3.sent;
this._notifyAnalyticsListeners(_analytics.SLI_EVENT_TYPE, _types.SliNames.SEARCH_TEAM, _types.Actions.SUCCEEDED);
return _context3.abrupt("return", this.convertTeamResultToMentionResult(teamResult, query));
case 10:
_context3.prev = 10;
_context3.t0 = _context3["catch"](2);
this._notifyAnalyticsListeners(_analytics.SLI_EVENT_TYPE, _types.SliNames.SEARCH_TEAM, _types.Actions.FAILED);
throw _context3.t0;
case 14:
case "end":
return _context3.stop();
}
}, _callee3, this, [[2, 10]]);
}));
function remoteTeamSearch(_x5, _x6) {
return _remoteTeamSearch.apply(this, arguments);
}
return remoteTeamSearch;
}()
}, {
key: "convertTeamResultToMentionResult",
value: function convertTeamResultToMentionResult(result, query) {
var _this3 = this;
var teamLinkResolver = this.teamMentionConfig.teamLinkResolver;
var mentions = result.map(function (team) {
var teamLink = '';
var defaultTeamLink = "".concat(window.location.origin, "/people/team/").concat(team.id);
if (typeof teamLinkResolver === 'function') {
teamLink = teamLinkResolver(team.id);
}
return {
id: _this3.trimTeamARI(team.id),
avatarUrl: team.smallAvatarImageUrl,
name: team.displayName,
accessLevel: _types.UserAccessLevel[_types.UserAccessLevel.CONTAINER],
userType: _types.UserType[_types.UserType.TEAM],
highlight: team.highlight,
context: {
members: team.members,
includesYou: team.includesYou,
memberCount: team.memberCount,
teamLink: teamLink || defaultTeamLink
}
};
});
return {
mentions: mentions,
query: query
};
}
}, {
key: "trimTeamARI",
value: function trimTeamARI() {
var teamId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
var TEAM_ARI_PREFIX = 'ari:cloud:teams::team/';
var IDENTITY_TEAM_ARI_PREFIX = 'ari:cloud:identity::team/';
return teamId.replace(TEAM_ARI_PREFIX, '').replace(IDENTITY_TEAM_ARI_PREFIX, '');
}
}]);
}(_MentionResource2.default);