@atlaskit/mention
Version:
A React component used to display user profiles in a list for 'Mention' functionality
476 lines (467 loc) • 18.7 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.isResolvingMentionProvider = exports.default = exports.MentionResource = exports.HttpError = exports.AbstractResource = exports.AbstractMentionResource = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _utilServiceSupport = require("@atlaskit/util-service-support");
var _types = require("../types");
var _logger = _interopRequireDefault(require("../util/logger"));
var _analytics = require("../util/analytics");
var _debounce = _interopRequireDefault(require("lodash/debounce"));
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; })(); }
var MAX_QUERY_ITEMS = 100;
var MAX_NOTIFIED_ITEMS = 20;
// Re-exporting types to prevent breaking change
// Re-exporting types to prevent breaking change
/**
* Support
*/
var emptySecurityProvider = function emptySecurityProvider() {
return {
params: {},
headers: {}
};
};
var AbstractResource = exports.AbstractResource = /*#__PURE__*/function () {
function AbstractResource() {
(0, _classCallCheck2.default)(this, AbstractResource);
this.changeListeners = new Map();
this.allResultsListeners = new Map();
this.errListeners = new Map();
this.infoListeners = new Map();
this.analyticsListeners = new Map();
}
return (0, _createClass2.default)(AbstractResource, [{
key: "subscribe",
value: function subscribe(key, callback, errCallback, infoCallback, allResultsCallback, analyticsListeners) {
if (callback) {
this.changeListeners.set(key, callback);
}
if (errCallback) {
this.errListeners.set(key, errCallback);
}
if (infoCallback) {
this.infoListeners.set(key, infoCallback);
}
if (allResultsCallback) {
this.allResultsListeners.set(key, allResultsCallback);
}
if (analyticsListeners) {
this.analyticsListeners.set(key, analyticsListeners);
}
}
}, {
key: "unsubscribe",
value: function unsubscribe(key) {
this.changeListeners.delete(key);
this.errListeners.delete(key);
this.infoListeners.delete(key);
this.allResultsListeners.delete(key);
this.analyticsListeners.delete(key);
}
}]);
}();
var AbstractMentionResource = exports.AbstractMentionResource = /*#__PURE__*/function (_ref) {
function AbstractMentionResource() {
(0, _classCallCheck2.default)(this, AbstractMentionResource);
return _callSuper(this, AbstractMentionResource, arguments);
}
(0, _inherits2.default)(AbstractMentionResource, _ref);
return (0, _createClass2.default)(AbstractMentionResource, [{
key: "shouldHighlightMention",
value: function shouldHighlightMention(_mention) {
return false;
}
// eslint-disable-next-line class-methods-use-this
}, {
key: "filter",
value: function filter(query) {
throw new Error("not yet implemented.\nParams: query=".concat(query));
}
// eslint-disable-next-line class-methods-use-this, no-unused-vars
}, {
key: "recordMentionSelection",
value: function recordMentionSelection(_mention) {
// Do nothing
}
}, {
key: "isFiltering",
value: function isFiltering(_query) {
return false;
}
}, {
key: "_notifyListeners",
value: function _notifyListeners(mentionsResult, stats) {
(0, _logger.default)('ak-mention-resource._notifyListeners', mentionsResult && mentionsResult.mentions && mentionsResult.mentions.length, this.changeListeners);
this.changeListeners.forEach(function (listener, key) {
try {
listener(mentionsResult.mentions.slice(0, MAX_NOTIFIED_ITEMS), mentionsResult.query, stats);
} catch (e) {
// ignore error from listener
(0, _logger.default)("error from listener '".concat(key, "', ignoring"), e);
}
});
}
}, {
key: "_notifyAllResultsListeners",
value: function _notifyAllResultsListeners(mentionsResult) {
(0, _logger.default)('ak-mention-resource._notifyAllResultsListeners', mentionsResult && mentionsResult.mentions && mentionsResult.mentions.length, this.changeListeners);
this.allResultsListeners.forEach(function (listener, key) {
try {
listener(mentionsResult.mentions.slice(0, MAX_NOTIFIED_ITEMS), mentionsResult.query);
} catch (e) {
// ignore error from listener
(0, _logger.default)("error from listener '".concat(key, "', ignoring"), e);
}
});
}
}, {
key: "_notifyErrorListeners",
value: function _notifyErrorListeners(error, query) {
this.errListeners.forEach(function (listener, key) {
try {
listener(error, query);
} catch (e) {
// ignore error from listener
(0, _logger.default)("error from listener '".concat(key, "', ignoring"), e);
}
});
}
}, {
key: "_notifyInfoListeners",
value: function _notifyInfoListeners(info) {
this.infoListeners.forEach(function (listener, key) {
try {
listener(info);
} catch (e) {
// ignore error fromr listener
(0, _logger.default)("error from listener '".concat(key, "', ignoring"), e);
}
});
}
}, {
key: "_notifyAnalyticsListeners",
value: function _notifyAnalyticsListeners(event, actionSubject, action, attributes) {
this.analyticsListeners.forEach(function (listener, key) {
try {
listener(event, actionSubject, action, attributes);
} catch (e) {
// ignore error from listener
(0, _logger.default)("error from listener '".concat(key, "', ignoring"), e);
}
});
}
}]);
}(AbstractResource);
/**
* Provides a Javascript API
*/
var MentionResource = exports.MentionResource = /*#__PURE__*/function (_AbstractMentionResou) {
function MentionResource(config) {
var _this;
(0, _classCallCheck2.default)(this, MentionResource);
_this = _callSuper(this, MentionResource);
_this.verifyMentionConfig(config);
_this.config = config;
_this.lastReturnedSearch = 0;
_this.activeSearches = new Set();
_this.productName = config.productName;
_this.shouldEnableInvite = !!config.shouldEnableInvite;
_this.onInviteItemClick = config.onInviteItemClick;
_this.inviteXProductUser = config.inviteXProductUser;
_this.userRole = config.userRole || 'basic';
if (_this.config.debounceTime) {
_this.filter = (0, _debounce.default)(_this.filter, _this.config.debounceTime);
}
return _this;
}
(0, _inherits2.default)(MentionResource, _AbstractMentionResou);
return (0, _createClass2.default)(MentionResource, [{
key: "shouldHighlightMention",
value: function shouldHighlightMention(mention) {
if (this.config.shouldHighlightMention) {
return this.config.shouldHighlightMention(mention);
}
return false;
}
}, {
key: "notify",
value: function notify(searchTime, mentionResult, query) {
if (searchTime > this.lastReturnedSearch) {
this.lastReturnedSearch = searchTime;
this._notifyListeners(mentionResult, {
duration: 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: "notifyError",
value: function notifyError(error, query) {
this._notifyErrorListeners(error, query);
if (query) {
this.activeSearches.delete(query);
}
}
}, {
key: "filter",
value: function () {
var _filter = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(query, contextIdentifier) {
var searchTime, results, searchResponse;
return _regenerator.default.wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
_context.prev = 0;
searchTime = Date.now();
if (query) {
_context.next = 8;
break;
}
_context.next = 5;
return this.initialState(contextIdentifier);
case 5:
results = _context.sent;
_context.next = 13;
break;
case 8:
this.activeSearches.add(query);
searchResponse = this.search(query, contextIdentifier);
_context.next = 12;
return searchResponse.mentions;
case 12:
results = _context.sent;
case 13:
this.notify(searchTime, results, query);
_context.next = 19;
break;
case 16:
_context.prev = 16;
_context.t0 = _context["catch"](0);
this.notifyError(_context.t0, query);
case 19:
case "end":
return _context.stop();
}
}, _callee, this, [[0, 16]]);
}));
function filter(_x, _x2) {
return _filter.apply(this, arguments);
}
return filter;
}()
}, {
key: "isFiltering",
value: function isFiltering(query) {
return this.activeSearches.has(query);
}
}, {
key: "resolveMentionName",
value: function resolveMentionName(id) {
if (!this.config.mentionNameResolver) {
return {
id: id,
name: '',
status: _types.MentionNameStatus.UNKNOWN
};
}
return this.config.mentionNameResolver.lookupName(id);
}
}, {
key: "cacheMentionName",
value: function cacheMentionName(id, mentionName) {
if (!this.config.mentionNameResolver) {
return;
}
this.config.mentionNameResolver.cacheName(id, mentionName);
}
}, {
key: "supportsMentionNameResolving",
value: function supportsMentionNameResolving() {
return !!this.config.mentionNameResolver;
}
}, {
key: "updateActiveSearches",
value: function updateActiveSearches(query) {
this.activeSearches.add(query);
}
}, {
key: "verifyMentionConfig",
value: function verifyMentionConfig(config) {
if (!config.url) {
throw new Error('config.url is a required parameter');
}
if (!config.securityProvider) {
config.securityProvider = emptySecurityProvider;
}
}
}, {
key: "initialState",
value: function initialState(contextIdentifier) {
return this.remoteInitialState(contextIdentifier);
}
/**
* Clear a context object to generate query params by removing empty
* strings, `undefined` and empty values.
*
* @param contextIdentifier the current context identifier
* @returns a safe context for query encoding
*/
}, {
key: "clearContext",
value: function clearContext() {
var contextIdentifier = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return Object.keys(contextIdentifier).filter(function (key) {
return contextIdentifier[key];
}).reduce(function (context, key) {
return _objectSpread((0, _defineProperty2.default)({}, key, contextIdentifier[key]), context);
}, {});
}
}, {
key: "getQueryParams",
value: function getQueryParams(contextIdentifier) {
var configParams = {};
if (this.config.containerId) {
configParams['containerId'] = this.config.containerId;
}
if (this.config.productId) {
configParams['productIdentifier'] = this.config.productId;
}
// if contextParams exist then it will override configParams for containerId
return _objectSpread(_objectSpread({}, configParams), this.clearContext(contextIdentifier));
}
/**
* Returns the initial mention display list before a search is performed for the specified
* container.
*
* @param contextIdentifier
* @returns Promise
*/
}, {
key: "remoteInitialState",
value: (function () {
var _remoteInitialState = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(contextIdentifier) {
var queryParams, options, result;
return _regenerator.default.wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
queryParams = this.getQueryParams(contextIdentifier);
options = {
path: 'bootstrap',
queryParams: queryParams
};
_context2.prev = 2;
_context2.next = 5;
return _utilServiceSupport.utils.requestService(this.config, options);
case 5:
result = _context2.sent;
this._notifyAnalyticsListeners(_analytics.SLI_EVENT_TYPE, _types.SliNames.INITIAL_STATE, _types.Actions.SUCCEEDED);
return _context2.abrupt("return", this.transformServiceResponse(result, ''));
case 10:
_context2.prev = 10;
_context2.t0 = _context2["catch"](2);
this._notifyAnalyticsListeners(_analytics.SLI_EVENT_TYPE, _types.SliNames.INITIAL_STATE, _types.Actions.FAILED);
throw _context2.t0;
case 14:
case "end":
return _context2.stop();
}
}, _callee2, this, [[2, 10]]);
}));
function remoteInitialState(_x3) {
return _remoteInitialState.apply(this, arguments);
}
return remoteInitialState;
}())
}, {
key: "search",
value: function search(query, contextIdentifier) {
return {
mentions: this.remoteSearch(query, contextIdentifier)
};
}
}, {
key: "remoteSearch",
value: function () {
var _remoteSearch = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3(query, contextIdentifier) {
var options, result;
return _regenerator.default.wrap(function _callee3$(_context3) {
while (1) switch (_context3.prev = _context3.next) {
case 0:
options = {
path: 'search',
queryParams: _objectSpread({
query: query,
limit: MAX_QUERY_ITEMS
}, this.getQueryParams(contextIdentifier))
};
_context3.prev = 1;
_context3.next = 4;
return _utilServiceSupport.utils.requestService(this.config, options);
case 4:
result = _context3.sent;
this._notifyAnalyticsListeners(_analytics.SLI_EVENT_TYPE, _types.SliNames.SEARCH, _types.Actions.SUCCEEDED);
return _context3.abrupt("return", this.transformServiceResponse(result, query));
case 9:
_context3.prev = 9;
_context3.t0 = _context3["catch"](1);
this._notifyAnalyticsListeners(_analytics.SLI_EVENT_TYPE, _types.SliNames.SEARCH, _types.Actions.FAILED);
throw _context3.t0;
case 13:
case "end":
return _context3.stop();
}
}, _callee3, this, [[1, 9]]);
}));
function remoteSearch(_x4, _x5) {
return _remoteSearch.apply(this, arguments);
}
return remoteSearch;
}()
}, {
key: "transformServiceResponse",
value: function transformServiceResponse(result, query) {
var mentions = result.mentions.map(function (mention) {
var lozenge;
if ((0, _types.isAppMention)(mention)) {
lozenge = mention.userType;
} else if ((0, _types.isTeamMention)(mention)) {
lozenge = mention.userType;
}
return _objectSpread(_objectSpread({}, mention), {}, {
lozenge: lozenge,
query: query
});
});
return _objectSpread(_objectSpread({}, result), {}, {
mentions: mentions,
query: result.query || query
});
}
}]);
}(AbstractMentionResource);
var HttpError = exports.HttpError = /*#__PURE__*/(0, _createClass2.default)(function HttpError(statusCode, statusMessage) {
(0, _classCallCheck2.default)(this, HttpError);
this.statusCode = statusCode;
this.message = statusMessage;
this.name = 'HttpError';
this.stack = new Error().stack;
});
var isResolvingMentionProvider = exports.isResolvingMentionProvider = function isResolvingMentionProvider(p) {
return !!(p && p.supportsMentionNameResolving && p.supportsMentionNameResolving());
};
var _default = exports.default = MentionResource;