@atlaskit/editor-plugin-mentions
Version:
Mentions plugin for @atlaskit/editor-core
198 lines (197 loc) • 9.12 kB
JavaScript
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
import _inherits from "@babel/runtime/helpers/inherits";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _regeneratorRuntime from "@babel/runtime/regenerator";
function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(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 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) { _defineProperty(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; }
import { NodeDataProvider } from '@atlaskit/node-data-provider/node-data-provider';
var getAppType = function getAppType(userType) {
return userType === 'APP' || userType === 'AGENT' ? 'agent' : 'user';
};
var enrichMentionNodeData = function enrichMentionNodeData(mention, data) {
var _data$appType;
return _objectSpread(_objectSpread({}, data), {}, {
appType: (_data$appType = data === null || data === void 0 ? void 0 : data.appType) !== null && _data$appType !== void 0 ? _data$appType : getAppType(mention.userType)
});
};
var toMentionNode = function toMentionNode(_ref) {
var id = _ref.id,
userType = _ref.userType;
return {
attrs: {
id: id,
// NodeDataProvider uses an ADF node internally, so normalize the runtime-only value.
userType: userType === 'AGENT' ? 'APP' : userType
},
type: 'mention'
};
};
var isMentionNode = function isMentionNode(node) {
return node.type === 'mention' && node.attrs !== undefined && 'id' in node.attrs && typeof node.attrs.id === 'string';
};
/**
* Page-scoped data provider for mention avatars.
*
* Products inject their resolution strategy so this package remains independent
* of Jira and Confluence APIs. Reuse the instance for the lifetime of a renderer
* or editor rather than creating one for every mention.
*
* Deterministic products can supply `resolveMentionNodeData` to return an
* SSR-safe avatar URL synchronously. It must return the same value on the server
* and the client's first render to preserve hydration parity.
*
* Network-backed products supply `fetchMentionNodeData`. Calls made in the same
* microtask are combined and account IDs are deduplicated before the fetcher is
* invoked. A Relay adapter can query `users(accountIds:)`, then map each user's
* `picture` and app type to a `MentionNodeData` record keyed by account ID. The
* resolved result is cached by the underlying `NodeDataProvider`.
*/
export var MentionNodeDataProvider = /*#__PURE__*/function (_NodeDataProvider) {
function MentionNodeDataProvider(fetchMentionNodeData) {
var _this;
var resolveMentionNodeData = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
_classCallCheck(this, MentionNodeDataProvider);
_this = _callSuper(this, MentionNodeDataProvider);
_defineProperty(_this, "name", 'mentionNodeDataProvider');
_defineProperty(_this, "queuedFetches", []);
_defineProperty(_this, "isFlushScheduled", false);
_this.fetchMentionNodeData = fetchMentionNodeData;
_this.resolveMentionNodeData = resolveMentionNodeData;
return _this;
}
_inherits(MentionNodeDataProvider, _NodeDataProvider);
return _createClass(MentionNodeDataProvider, [{
key: "isNodeSupported",
value: function isNodeSupported(node) {
return isMentionNode(node) && node.attrs.userType !== 'SPECIAL';
}
}, {
key: "nodeDataKey",
value: function nodeDataKey(node) {
return node.attrs.id;
}
}, {
key: "fetchNodesData",
value: function () {
var _fetchNodesData = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(nodes) {
var accountIds, dataByAccountId;
return _regeneratorRuntime.wrap(function (_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
accountIds = Array.from(new Set(nodes.map(function (_ref2) {
var attrs = _ref2.attrs;
return attrs.id;
})));
_context.next = 1;
return this.enqueueFetch(accountIds);
case 1:
dataByAccountId = _context.sent;
return _context.abrupt("return", nodes.map(function (_ref3) {
var attrs = _ref3.attrs;
return enrichMentionNodeData(attrs, dataByAccountId[attrs.id]);
}));
case 2:
case "end":
return _context.stop();
}
}, _callee, this);
}));
function fetchNodesData(_x) {
return _fetchNodesData.apply(this, arguments);
}
return fetchNodesData;
}()
}, {
key: "getMentionData",
value: function getMentionData(mention, callback) {
var _this$resolveMentionN;
var resolvedData = (_this$resolveMentionN = this.resolveMentionNodeData) === null || _this$resolveMentionN === void 0 ? void 0 : _this$resolveMentionN.call(this, mention);
if (resolvedData) {
callback({
data: enrichMentionNodeData(mention, resolvedData)
});
return;
}
this.getData(toMentionNode(mention), callback);
}
}, {
key: "getMentionDataFromCache",
value: function getMentionDataFromCache(mention) {
var _this$resolveMentionN2, _this$getNodeDataFrom;
var resolvedData = (_this$resolveMentionN2 = this.resolveMentionNodeData) === null || _this$resolveMentionN2 === void 0 ? void 0 : _this$resolveMentionN2.call(this, mention);
if (resolvedData) {
return enrichMentionNodeData(mention, resolvedData);
}
var data = (_this$getNodeDataFrom = this.getNodeDataFromCache(toMentionNode(mention))) === null || _this$getNodeDataFrom === void 0 ? void 0 : _this$getNodeDataFrom.data;
return data ? enrichMentionNodeData(mention, data) : undefined;
}
}, {
key: "enqueueFetch",
value: function enqueueFetch(accountIds) {
var _this2 = this;
var result = new Promise(function (resolve, reject) {
_this2.queuedFetches.push({
accountIds: accountIds,
reject: reject,
resolve: resolve
});
});
if (!this.isFlushScheduled) {
this.isFlushScheduled = true;
void Promise.resolve().then(function () {
return _this2.flushFetches();
});
}
return result;
}
}, {
key: "flushFetches",
value: function () {
var _flushFetches = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
var queuedFetches, accountIds, data, _t;
return _regeneratorRuntime.wrap(function (_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
this.isFlushScheduled = false;
queuedFetches = this.queuedFetches;
this.queuedFetches = [];
accountIds = Array.from(new Set(queuedFetches.flatMap(function (request) {
return request.accountIds;
})));
_context2.prev = 1;
_context2.next = 2;
return this.fetchMentionNodeData(accountIds);
case 2:
data = _context2.sent;
queuedFetches.forEach(function (_ref4) {
var resolve = _ref4.resolve;
return resolve(data);
});
_context2.next = 4;
break;
case 3:
_context2.prev = 3;
_t = _context2["catch"](1);
queuedFetches.forEach(function (_ref5) {
var reject = _ref5.reject;
return reject(_t);
});
case 4:
case "end":
return _context2.stop();
}
}, _callee2, this, [[1, 3]]);
}));
function flushFetches() {
return _flushFetches.apply(this, arguments);
}
return flushFetches;
}()
}]);
}(NodeDataProvider);