UNPKG

@atlaskit/editor-plugin-annotation

Version:

Annotation plugin for @atlaskit/editor-core

146 lines (143 loc) 7.04 kB
import { AnnotationTypes } from '@atlaskit/adf-schema'; import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics'; import { applyMarkOnRange } from '@atlaskit/editor-common/mark'; import { getRangeInlineNodeNames } from '@atlaskit/editor-common/utils'; import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state'; import { AddMarkStep } from '@atlaskit/editor-prosemirror/transform'; import { fg } from '@atlaskit/platform-feature-flags'; import { getDraftCommandAnalyticsPayload, getPluginState, resolveDraftBookmark } from '../pm-plugins/utils'; const isAnnotationStep = step => step instanceof AddMarkStep && step.mark.type.name === 'annotation'; const addAnnotationMark = (id, supportedBlockNodes) => (transaction, state) => { const inlineCommentState = getPluginState(state); const { bookmark } = inlineCommentState || {}; const annotationMark = state.schema.marks.annotation.create({ id, type: AnnotationTypes.INLINE_COMMENT }); const { from, to, head, isBlockNode } = resolveDraftBookmark(state, bookmark, supportedBlockNodes); let tr = transaction; if (isBlockNode) { tr = tr.addNodeMark(from, annotationMark); // Set selection on the node so that we can display view component tr.setSelection(NodeSelection.create(tr.doc, from)); } else { // Apply the mark only to text node in the range. const tr = applyMarkOnRange(from, to, false, annotationMark, transaction); // The mark may not be applied to the current "head" of the bookmark so determine what was applied // above and use that instead const annotationMarkStep = tr.steps.reverse().find(isAnnotationStep); const headBasedOnMark = from === head ? annotationMarkStep === null || annotationMarkStep === void 0 ? void 0 : annotationMarkStep.from : annotationMarkStep === null || annotationMarkStep === void 0 ? void 0 : annotationMarkStep.to; tr.setSelection(TextSelection.create(tr.doc, headBasedOnMark !== null && headBasedOnMark !== void 0 ? headBasedOnMark : head)); } return tr; }; const addInlineComment = (editorAnalyticsAPI, editorAPI) => (id, supportedBlockNodes) => (transaction, state) => { var _editorAPI$editorView, _pluginState$featureF; let tr = addAnnotationMark(id, supportedBlockNodes)(transaction, state); editorAPI === null || editorAPI === void 0 ? void 0 : (_editorAPI$editorView = editorAPI.editorViewModeEffects) === null || _editorAPI$editorView === void 0 ? void 0 : _editorAPI$editorView.actions.applyViewModeStepAt(tr); // add insert analytics step to transaction tr = addInsertAnalytics(editorAnalyticsAPI)(tr, state); // add close analytics step to transaction tr = addOpenCloseAnalytics(editorAnalyticsAPI)(false, INPUT_METHOD.TOOLBAR)(tr, state); const pluginState = getPluginState(state); const isAutoScrollBugFixEnabled = pluginState === null || pluginState === void 0 ? void 0 : (_pluginState$featureF = pluginState.featureFlagsPluginState) === null || _pluginState$featureF === void 0 ? void 0 : _pluginState$featureF.commentsOnMediaAutoscrollInEditor; if (isAutoScrollBugFixEnabled) { // Explicitly disable scrollIntoView as scrolling is handled by CommentSidebar tr.setMeta('scrollIntoView', false); } return tr; }; const addOpenCloseAnalytics = editorAnalyticsAPI => (drafting, method = INPUT_METHOD.TOOLBAR) => (transaction, state) => { const draftingPayload = getDraftCommandAnalyticsPayload(drafting, method)(state); editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 ? void 0 : editorAnalyticsAPI.attachAnalyticsEvent(draftingPayload)(transaction); return transaction; }; const handleDraftState = editorAnalyticsAPI => (drafting, method = INPUT_METHOD.TOOLBAR) => (transaction, state) => { var _pluginState$featureF2; const tr = addOpenCloseAnalytics(editorAnalyticsAPI)(drafting, method)(transaction, state); const pluginState = getPluginState(state); const isAutoScrollBugFixEnabled = pluginState === null || pluginState === void 0 ? void 0 : (_pluginState$featureF2 = pluginState.featureFlagsPluginState) === null || _pluginState$featureF2 === void 0 ? void 0 : _pluginState$featureF2.commentsOnMediaAutoscrollInEditor; if (isAutoScrollBugFixEnabled) { // Explicitly disable scrollIntoView as scrolling is handled by CommentSidebar tr.setMeta('scrollIntoView', false); } return tr; }; const addInsertAnalytics = editorAnalyticsAPI => (transaction, state) => { const analyticsEvent = { action: ACTION.INSERTED, actionSubject: ACTION_SUBJECT.ANNOTATION, eventType: EVENT_TYPE.TRACK, actionSubjectId: ACTION_SUBJECT_ID.INLINE_COMMENT, attributes: {} }; if (fg('editor_inline_comments_on_inline_nodes')) { const { bookmark } = getPluginState(state) || {}; // When this FF is removed we can move the analytics event creation inside of the // attachAnalyticsEvent and get type inference for the attributes. // @ts-ignore analyticsEvent.attributes.inlineNodeNames = getRangeInlineNodeNames({ doc: state.doc, pos: resolveDraftBookmark(state, bookmark) }); } editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 ? void 0 : editorAnalyticsAPI.attachAnalyticsEvent(analyticsEvent)(transaction); return transaction; }; const addResolveAnalytics = editorAnalyticsAPI => method => (transaction, state) => { const resolvedPayload = { action: ACTION.RESOLVED, actionSubject: ACTION_SUBJECT.ANNOTATION, actionSubjectId: ACTION_SUBJECT_ID.INLINE_COMMENT, eventType: EVENT_TYPE.TRACK, attributes: { method } }; editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 ? void 0 : editorAnalyticsAPI.attachAnalyticsEvent(resolvedPayload)(transaction); return transaction; }; const addPreemptiveGateErrorAnalytics = editorAnalyticsAPI => errorReason => (transaction, state) => { const analyticsEvent = { action: ACTION.ERROR, actionSubject: ACTION_SUBJECT.ANNOTATION, actionSubjectId: ACTION_SUBJECT_ID.INLINE_COMMENT, eventType: EVENT_TYPE.OPERATIONAL, attributes: { errorReason } }; editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 ? void 0 : editorAnalyticsAPI.attachAnalyticsEvent(analyticsEvent)(transaction); return transaction; }; const addDeleteAnalytics = editorAnalyticsAPI => (transaction, state) => { const analyticsEvent = { action: ACTION.DELETED, actionSubject: ACTION_SUBJECT.ANNOTATION, actionSubjectId: ACTION_SUBJECT_ID.INLINE_COMMENT, eventType: EVENT_TYPE.TRACK, attributes: {} }; editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 ? void 0 : editorAnalyticsAPI.attachAnalyticsEvent(analyticsEvent)(transaction); return transaction; }; const _default_1 = { addAnnotationMark, addInlineComment, handleDraftState, addOpenCloseAnalytics, addInsertAnalytics, addResolveAnalytics, addPreemptiveGateErrorAnalytics, addDeleteAnalytics }; export default _default_1;