@atlaskit/editor-plugin-analytics 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -0
- package/LICENSE.md +13 -0
- package/README.md +7 -0
- package/dist/cjs/analytics-api/attach-payload-into-transaction.js +51 -0
- package/dist/cjs/analytics-api/editor-state-context.js +78 -0
- package/dist/cjs/analytics-api/map-attributes.js +23 -0
- package/dist/cjs/consts.js +12 -0
- package/dist/cjs/index.js +12 -0
- package/dist/cjs/plugin-key.js +9 -0
- package/dist/cjs/plugin.js +187 -0
- package/dist/cjs/undo-redo-input-source.js +27 -0
- package/dist/cjs/version.json +5 -0
- package/dist/es2019/analytics-api/attach-payload-into-transaction.js +43 -0
- package/dist/es2019/analytics-api/editor-state-context.js +72 -0
- package/dist/es2019/analytics-api/map-attributes.js +14 -0
- package/dist/es2019/consts.js +4 -0
- package/dist/es2019/index.js +1 -0
- package/dist/es2019/plugin-key.js +2 -0
- package/dist/es2019/plugin.js +162 -0
- package/dist/es2019/undo-redo-input-source.js +18 -0
- package/dist/es2019/version.json +5 -0
- package/dist/esm/analytics-api/attach-payload-into-transaction.js +43 -0
- package/dist/esm/analytics-api/editor-state-context.js +70 -0
- package/dist/esm/analytics-api/map-attributes.js +16 -0
- package/dist/esm/consts.js +4 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/plugin-key.js +2 -0
- package/dist/esm/plugin.js +179 -0
- package/dist/esm/undo-redo-input-source.js +19 -0
- package/dist/esm/version.json +5 -0
- package/dist/types/analytics-api/attach-payload-into-transaction.d.ts +16 -0
- package/dist/types/analytics-api/editor-state-context.d.ts +8 -0
- package/dist/types/analytics-api/map-attributes.d.ts +2 -0
- package/dist/types/consts.d.ts +3 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/plugin-key.d.ts +2 -0
- package/dist/types/plugin.d.ts +24 -0
- package/dist/types/undo-redo-input-source.d.ts +3 -0
- package/dist/types-ts4.5/analytics-api/attach-payload-into-transaction.d.ts +16 -0
- package/dist/types-ts4.5/analytics-api/editor-state-context.d.ts +8 -0
- package/dist/types-ts4.5/analytics-api/map-attributes.d.ts +2 -0
- package/dist/types-ts4.5/consts.d.ts +3 -0
- package/dist/types-ts4.5/index.d.ts +3 -0
- package/dist/types-ts4.5/plugin-key.d.ts +2 -0
- package/dist/types-ts4.5/plugin.d.ts +26 -0
- package/dist/types-ts4.5/undo-redo-input-source.d.ts +3 -0
- package/package.json +92 -0
- package/report.api.md +70 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { AnalyticsStep } from '@atlaskit/adf-schema/steps';
|
|
2
|
+
import { FabricChannel } from '@atlaskit/analytics-listeners';
|
|
3
|
+
import { ACTION, EVENT_TYPE, fireAnalyticsEvent, getAnalyticsEventsFromTransaction } from '@atlaskit/editor-common/analytics';
|
|
4
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
5
|
+
import { isPerformanceAPIAvailable, measureRender } from '@atlaskit/editor-common/utils';
|
|
6
|
+
import { createAttachPayloadIntoTransaction } from './analytics-api/attach-payload-into-transaction';
|
|
7
|
+
import { analyticsPluginKey } from './plugin-key';
|
|
8
|
+
import { generateUndoRedoInputSoucePayload } from './undo-redo-input-source';
|
|
9
|
+
function createPlugin(options, featureFlags) {
|
|
10
|
+
if (!options || !options.createAnalyticsEvent) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const hasRequiredPerformanceAPIs = isPerformanceAPIAvailable();
|
|
14
|
+
return new SafePlugin({
|
|
15
|
+
key: analyticsPluginKey,
|
|
16
|
+
state: {
|
|
17
|
+
init: () => {
|
|
18
|
+
return {
|
|
19
|
+
...options,
|
|
20
|
+
fireAnalytics: fireAnalyticsEvent(options.createAnalyticsEvent)
|
|
21
|
+
};
|
|
22
|
+
},
|
|
23
|
+
apply: (tr, pluginState, _, state) => {
|
|
24
|
+
if (pluginState.createAnalyticsEvent !== options.createAnalyticsEvent) {
|
|
25
|
+
// When the plugin state is reconfigured, the init function isn't called again
|
|
26
|
+
return {
|
|
27
|
+
...pluginState,
|
|
28
|
+
createAnalyticsEvent: options.createAnalyticsEvent
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
if (featureFlags.catchAllTracking) {
|
|
32
|
+
const analyticsEventWithChannel = getAnalyticsEventsFromTransaction(tr);
|
|
33
|
+
if (analyticsEventWithChannel.length > 0) {
|
|
34
|
+
for (const {
|
|
35
|
+
payload,
|
|
36
|
+
channel
|
|
37
|
+
} of analyticsEventWithChannel) {
|
|
38
|
+
// Measures how much time it takes to update the DOM after each ProseMirror document update
|
|
39
|
+
// that has an analytics event.
|
|
40
|
+
if (hasRequiredPerformanceAPIs && tr.docChanged && payload.action !== ACTION.INSERTED && payload.action !== ACTION.DELETED) {
|
|
41
|
+
const measureName = `${payload.actionSubject}:${payload.action}:${payload.actionSubjectId}`;
|
|
42
|
+
measureRender(
|
|
43
|
+
// NOTE this name could be resulting in misleading data -- where if multiple payloads are
|
|
44
|
+
// received before a render completes -- the measurement value will be inaccurate (this is
|
|
45
|
+
// due to measureRender requiring unique measureNames)
|
|
46
|
+
measureName, ({
|
|
47
|
+
duration,
|
|
48
|
+
distortedDuration
|
|
49
|
+
}) => {
|
|
50
|
+
fireAnalyticsEvent(pluginState.createAnalyticsEvent)({
|
|
51
|
+
payload: extendPayload({
|
|
52
|
+
payload,
|
|
53
|
+
duration,
|
|
54
|
+
distortedDuration
|
|
55
|
+
}),
|
|
56
|
+
channel
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return pluginState;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
const analyticsPlugin = (options, api) => {
|
|
69
|
+
var _api$dependencies$fea;
|
|
70
|
+
const featureFlags = (api === null || api === void 0 ? void 0 : (_api$dependencies$fea = api.dependencies.featureFlags) === null || _api$dependencies$fea === void 0 ? void 0 : _api$dependencies$fea.sharedState.currentState()) || {};
|
|
71
|
+
return {
|
|
72
|
+
name: 'analytics',
|
|
73
|
+
getSharedState: editorState => {
|
|
74
|
+
var _analyticsPluginKey$g;
|
|
75
|
+
if (!editorState) {
|
|
76
|
+
return {
|
|
77
|
+
createAnalyticsEvent: null,
|
|
78
|
+
attachAnalyticsEvent: null
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const {
|
|
82
|
+
createAnalyticsEvent
|
|
83
|
+
} = (_analyticsPluginKey$g = analyticsPluginKey.getState(editorState)) !== null && _analyticsPluginKey$g !== void 0 ? _analyticsPluginKey$g : {};
|
|
84
|
+
return {
|
|
85
|
+
createAnalyticsEvent,
|
|
86
|
+
attachAnalyticsEvent: createAttachPayloadIntoTransaction(editorState.selection)
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
actions: {
|
|
90
|
+
attachAnalyticsEvent: (payload, channel = FabricChannel.editor) => tr => {
|
|
91
|
+
var _api$dependencies$ana, _api$dependencies$ana2;
|
|
92
|
+
const {
|
|
93
|
+
createAnalyticsEvent,
|
|
94
|
+
attachAnalyticsEvent
|
|
95
|
+
} = (_api$dependencies$ana = api === null || api === void 0 ? void 0 : (_api$dependencies$ana2 = api.dependencies.analytics) === null || _api$dependencies$ana2 === void 0 ? void 0 : _api$dependencies$ana2.sharedState.currentState()) !== null && _api$dependencies$ana !== void 0 ? _api$dependencies$ana : {};
|
|
96
|
+
if (!tr || !createAnalyticsEvent || !attachAnalyticsEvent) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
attachAnalyticsEvent({
|
|
100
|
+
tr,
|
|
101
|
+
payload,
|
|
102
|
+
channel
|
|
103
|
+
});
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
pmPlugins() {
|
|
108
|
+
return [{
|
|
109
|
+
name: 'analyticsPlugin',
|
|
110
|
+
plugin: () => createPlugin(options, featureFlags)
|
|
111
|
+
}];
|
|
112
|
+
},
|
|
113
|
+
onEditorViewStateUpdated({
|
|
114
|
+
originalTransaction,
|
|
115
|
+
transactions,
|
|
116
|
+
newEditorState
|
|
117
|
+
}) {
|
|
118
|
+
const pluginState = analyticsPluginKey.getState(newEditorState);
|
|
119
|
+
if (!pluginState || !pluginState.createAnalyticsEvent) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const steps = transactions.reduce((acc, tr) => {
|
|
123
|
+
const payloads = tr.steps.filter(step => step instanceof AnalyticsStep).map(x => x.analyticsEvents).reduce((acc, val) => acc.concat(val), []);
|
|
124
|
+
acc.push(...payloads);
|
|
125
|
+
return acc;
|
|
126
|
+
}, []);
|
|
127
|
+
if (steps.length === 0) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const {
|
|
131
|
+
createAnalyticsEvent
|
|
132
|
+
} = pluginState;
|
|
133
|
+
const undoAnaltyicsEventTransformer = generateUndoRedoInputSoucePayload(originalTransaction);
|
|
134
|
+
steps.forEach(({
|
|
135
|
+
payload,
|
|
136
|
+
channel
|
|
137
|
+
}) => {
|
|
138
|
+
const nextPayload = undoAnaltyicsEventTransformer(payload);
|
|
139
|
+
fireAnalyticsEvent(createAnalyticsEvent)({
|
|
140
|
+
payload: nextPayload,
|
|
141
|
+
channel
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
export function extendPayload({
|
|
148
|
+
payload,
|
|
149
|
+
duration,
|
|
150
|
+
distortedDuration
|
|
151
|
+
}) {
|
|
152
|
+
return {
|
|
153
|
+
...payload,
|
|
154
|
+
attributes: {
|
|
155
|
+
...payload.attributes,
|
|
156
|
+
duration,
|
|
157
|
+
distortedDuration
|
|
158
|
+
},
|
|
159
|
+
eventType: EVENT_TYPE.OPERATIONAL
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
export { analyticsPlugin };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const getUndoRedoInputSource = tr => {
|
|
2
|
+
var _tr$getMeta;
|
|
3
|
+
// TODO: Please, do not copy or use this kind of code below
|
|
4
|
+
return (_tr$getMeta = tr.getMeta('undoRedoPlugin$')) !== null && _tr$getMeta !== void 0 ? _tr$getMeta : null;
|
|
5
|
+
};
|
|
6
|
+
export const generateUndoRedoInputSoucePayload = tr => {
|
|
7
|
+
const undoRedoPluginInputSource = getUndoRedoInputSource(tr);
|
|
8
|
+
return payload => {
|
|
9
|
+
const shouldAddHistoryTriggerMethodAttribute = undoRedoPluginInputSource && ['undid', 'redid'].includes(payload.action);
|
|
10
|
+
return !shouldAddHistoryTriggerMethodAttribute ? payload : {
|
|
11
|
+
...payload,
|
|
12
|
+
attributes: {
|
|
13
|
+
...payload.attributes,
|
|
14
|
+
historyTriggerMethod: undoRedoPluginInputSource
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { AnalyticsStep } from '@atlaskit/adf-schema/steps';
|
|
2
|
+
import { ACTION } from '@atlaskit/editor-common/analytics';
|
|
3
|
+
import { getStateContext } from './editor-state-context';
|
|
4
|
+
import { mapActionSubjectIdToAttributes } from './map-attributes';
|
|
5
|
+
var actionsToIgnore = [ACTION.INVOKED, ACTION.OPENED];
|
|
6
|
+
export var createAttachPayloadIntoTransaction = function createAttachPayloadIntoTransaction(selection) {
|
|
7
|
+
return function (_ref) {
|
|
8
|
+
var payload = _ref.payload,
|
|
9
|
+
tr = _ref.tr,
|
|
10
|
+
channel = _ref.channel;
|
|
11
|
+
return attachPayloadIntoTransaction({
|
|
12
|
+
payload: payload,
|
|
13
|
+
selection: selection,
|
|
14
|
+
tr: tr,
|
|
15
|
+
channel: channel
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// This utils was taken as reference in packages/editor/editor-plugin-ai/src/analytics/utils.ts
|
|
21
|
+
// to create new util attachPayloadIntoTransaction in above file.
|
|
22
|
+
// If you make a change here, please review attachPayloadIntoTransaction in above
|
|
23
|
+
// file and update it as well if needed.
|
|
24
|
+
export var attachPayloadIntoTransaction = function attachPayloadIntoTransaction(_ref2) {
|
|
25
|
+
var payload = _ref2.payload,
|
|
26
|
+
selection = _ref2.selection,
|
|
27
|
+
tr = _ref2.tr,
|
|
28
|
+
channel = _ref2.channel;
|
|
29
|
+
payload = getStateContext(selection, payload);
|
|
30
|
+
payload = mapActionSubjectIdToAttributes(payload);
|
|
31
|
+
var storedMarks = tr.storedMarks;
|
|
32
|
+
var pos = tr.mapping.map(selection.$from.pos, -1);
|
|
33
|
+
tr.step(new AnalyticsStep([{
|
|
34
|
+
payload: payload,
|
|
35
|
+
channel: channel
|
|
36
|
+
}], actionsToIgnore, pos) // We need to create the step based on a position, this prevent split history for relative changes.
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
// When you add a new step all the storedMarks are removed it
|
|
40
|
+
if (storedMarks) {
|
|
41
|
+
tr.setStoredMarks(storedMarks);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { NodeSelection } from 'prosemirror-state';
|
|
2
|
+
import { findParentNode } from 'prosemirror-utils';
|
|
3
|
+
import { ACTION, ACTION_SUBJECT, SELECTION_POSITION, SELECTION_TYPE } from '@atlaskit/editor-common/analytics';
|
|
4
|
+
import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
|
|
5
|
+
export function getSelectionType(selection) {
|
|
6
|
+
var _selection$constructo;
|
|
7
|
+
var type;
|
|
8
|
+
var position;
|
|
9
|
+
if ((selection === null || selection === void 0 ? void 0 : (_selection$constructo = selection.constructor) === null || _selection$constructo === void 0 ? void 0 : _selection$constructo.name) === 'GapCursorSelection') {
|
|
10
|
+
type = SELECTION_TYPE.GAP_CURSOR;
|
|
11
|
+
position = selection.side;
|
|
12
|
+
} else if (selection instanceof CellSelection) {
|
|
13
|
+
type = SELECTION_TYPE.CELL;
|
|
14
|
+
} else if (selection instanceof NodeSelection) {
|
|
15
|
+
type = SELECTION_TYPE.NODE;
|
|
16
|
+
} else if (selection.from !== selection.to) {
|
|
17
|
+
type = SELECTION_TYPE.RANGED;
|
|
18
|
+
} else {
|
|
19
|
+
type = SELECTION_TYPE.CURSOR;
|
|
20
|
+
var from = selection.from,
|
|
21
|
+
$from = selection.$from;
|
|
22
|
+
if (from === $from.start()) {
|
|
23
|
+
position = SELECTION_POSITION.START;
|
|
24
|
+
} else if (from === $from.end()) {
|
|
25
|
+
position = SELECTION_POSITION.END;
|
|
26
|
+
} else {
|
|
27
|
+
position = SELECTION_POSITION.MIDDLE;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
type: type,
|
|
32
|
+
position: position
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export function findInsertLocation(selection) {
|
|
36
|
+
var _selection$$from$doc$ = selection.$from.doc.type,
|
|
37
|
+
schema = _selection$$from$doc$.schema,
|
|
38
|
+
name = _selection$$from$doc$.name;
|
|
39
|
+
if (selection instanceof NodeSelection) {
|
|
40
|
+
return selection.node.type.name;
|
|
41
|
+
}
|
|
42
|
+
if (selection instanceof CellSelection) {
|
|
43
|
+
return schema.nodes.table.name;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Text selection
|
|
47
|
+
var parentNodeInfo = findParentNode(function (node) {
|
|
48
|
+
return node.type !== schema.nodes.paragraph;
|
|
49
|
+
})(selection);
|
|
50
|
+
return parentNodeInfo ? parentNodeInfo.node.type.name : name;
|
|
51
|
+
}
|
|
52
|
+
export function getStateContext(selection, payload) {
|
|
53
|
+
if (!payload.attributes) {
|
|
54
|
+
return payload;
|
|
55
|
+
}
|
|
56
|
+
var _getSelectionType = getSelectionType(selection),
|
|
57
|
+
type = _getSelectionType.type,
|
|
58
|
+
position = _getSelectionType.position;
|
|
59
|
+
payload.attributes.selectionType = type;
|
|
60
|
+
if (position) {
|
|
61
|
+
payload.attributes.selectionPosition = position;
|
|
62
|
+
}
|
|
63
|
+
var insertLocation = findInsertLocation(selection);
|
|
64
|
+
if (payload.action === ACTION.INSERTED && payload.actionSubject === ACTION_SUBJECT.DOCUMENT && payload.attributes) {
|
|
65
|
+
payload.attributes.insertLocation = insertLocation;
|
|
66
|
+
} else {
|
|
67
|
+
payload.attributes.nodeLocation = insertLocation;
|
|
68
|
+
}
|
|
69
|
+
return payload;
|
|
70
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
3
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
4
|
+
import { ACTION, ACTION_SUBJECT } from '@atlaskit/editor-common/analytics';
|
|
5
|
+
export function mapActionSubjectIdToAttributes(payload) {
|
|
6
|
+
var documentInserted = payload.action === ACTION.INSERTED && payload.actionSubject === ACTION_SUBJECT.DOCUMENT;
|
|
7
|
+
var textFormatted = payload.action === ACTION.FORMATTED && payload.actionSubject === ACTION_SUBJECT.TEXT;
|
|
8
|
+
var hasActionSubjectId = !!payload.actionSubjectId;
|
|
9
|
+
if (hasActionSubjectId && (documentInserted || textFormatted)) {
|
|
10
|
+
payload.attributes = _objectSpread(_objectSpread({}, payload.attributes), {}, {
|
|
11
|
+
// @ts-expect-error
|
|
12
|
+
actionSubjectId: payload.actionSubjectId
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
return payload;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { analyticsPlugin } from './plugin';
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
2
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
3
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
4
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
5
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
6
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
7
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
8
|
+
import { AnalyticsStep } from '@atlaskit/adf-schema/steps';
|
|
9
|
+
import { FabricChannel } from '@atlaskit/analytics-listeners';
|
|
10
|
+
import { ACTION, EVENT_TYPE, fireAnalyticsEvent, getAnalyticsEventsFromTransaction } from '@atlaskit/editor-common/analytics';
|
|
11
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
12
|
+
import { isPerformanceAPIAvailable, measureRender } from '@atlaskit/editor-common/utils';
|
|
13
|
+
import { createAttachPayloadIntoTransaction } from './analytics-api/attach-payload-into-transaction';
|
|
14
|
+
import { analyticsPluginKey } from './plugin-key';
|
|
15
|
+
import { generateUndoRedoInputSoucePayload } from './undo-redo-input-source';
|
|
16
|
+
function createPlugin(options, featureFlags) {
|
|
17
|
+
if (!options || !options.createAnalyticsEvent) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
var hasRequiredPerformanceAPIs = isPerformanceAPIAvailable();
|
|
21
|
+
return new SafePlugin({
|
|
22
|
+
key: analyticsPluginKey,
|
|
23
|
+
state: {
|
|
24
|
+
init: function init() {
|
|
25
|
+
return _objectSpread(_objectSpread({}, options), {}, {
|
|
26
|
+
fireAnalytics: fireAnalyticsEvent(options.createAnalyticsEvent)
|
|
27
|
+
});
|
|
28
|
+
},
|
|
29
|
+
apply: function apply(tr, pluginState, _, state) {
|
|
30
|
+
if (pluginState.createAnalyticsEvent !== options.createAnalyticsEvent) {
|
|
31
|
+
// When the plugin state is reconfigured, the init function isn't called again
|
|
32
|
+
return _objectSpread(_objectSpread({}, pluginState), {}, {
|
|
33
|
+
createAnalyticsEvent: options.createAnalyticsEvent
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
if (featureFlags.catchAllTracking) {
|
|
37
|
+
var analyticsEventWithChannel = getAnalyticsEventsFromTransaction(tr);
|
|
38
|
+
if (analyticsEventWithChannel.length > 0) {
|
|
39
|
+
var _iterator = _createForOfIteratorHelper(analyticsEventWithChannel),
|
|
40
|
+
_step;
|
|
41
|
+
try {
|
|
42
|
+
var _loop = function _loop() {
|
|
43
|
+
var _step$value = _step.value,
|
|
44
|
+
payload = _step$value.payload,
|
|
45
|
+
channel = _step$value.channel;
|
|
46
|
+
// Measures how much time it takes to update the DOM after each ProseMirror document update
|
|
47
|
+
// that has an analytics event.
|
|
48
|
+
if (hasRequiredPerformanceAPIs && tr.docChanged && payload.action !== ACTION.INSERTED && payload.action !== ACTION.DELETED) {
|
|
49
|
+
var measureName = "".concat(payload.actionSubject, ":").concat(payload.action, ":").concat(payload.actionSubjectId);
|
|
50
|
+
measureRender(
|
|
51
|
+
// NOTE this name could be resulting in misleading data -- where if multiple payloads are
|
|
52
|
+
// received before a render completes -- the measurement value will be inaccurate (this is
|
|
53
|
+
// due to measureRender requiring unique measureNames)
|
|
54
|
+
measureName, function (_ref) {
|
|
55
|
+
var duration = _ref.duration,
|
|
56
|
+
distortedDuration = _ref.distortedDuration;
|
|
57
|
+
fireAnalyticsEvent(pluginState.createAnalyticsEvent)({
|
|
58
|
+
payload: extendPayload({
|
|
59
|
+
payload: payload,
|
|
60
|
+
duration: duration,
|
|
61
|
+
distortedDuration: distortedDuration
|
|
62
|
+
}),
|
|
63
|
+
channel: channel
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
69
|
+
_loop();
|
|
70
|
+
}
|
|
71
|
+
} catch (err) {
|
|
72
|
+
_iterator.e(err);
|
|
73
|
+
} finally {
|
|
74
|
+
_iterator.f();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return pluginState;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
var analyticsPlugin = function analyticsPlugin(options, api) {
|
|
84
|
+
var _api$dependencies$fea;
|
|
85
|
+
var featureFlags = (api === null || api === void 0 ? void 0 : (_api$dependencies$fea = api.dependencies.featureFlags) === null || _api$dependencies$fea === void 0 ? void 0 : _api$dependencies$fea.sharedState.currentState()) || {};
|
|
86
|
+
return {
|
|
87
|
+
name: 'analytics',
|
|
88
|
+
getSharedState: function getSharedState(editorState) {
|
|
89
|
+
var _analyticsPluginKey$g;
|
|
90
|
+
if (!editorState) {
|
|
91
|
+
return {
|
|
92
|
+
createAnalyticsEvent: null,
|
|
93
|
+
attachAnalyticsEvent: null
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
var _ref2 = (_analyticsPluginKey$g = analyticsPluginKey.getState(editorState)) !== null && _analyticsPluginKey$g !== void 0 ? _analyticsPluginKey$g : {},
|
|
97
|
+
createAnalyticsEvent = _ref2.createAnalyticsEvent;
|
|
98
|
+
return {
|
|
99
|
+
createAnalyticsEvent: createAnalyticsEvent,
|
|
100
|
+
attachAnalyticsEvent: createAttachPayloadIntoTransaction(editorState.selection)
|
|
101
|
+
};
|
|
102
|
+
},
|
|
103
|
+
actions: {
|
|
104
|
+
attachAnalyticsEvent: function attachAnalyticsEvent(payload) {
|
|
105
|
+
var channel = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : FabricChannel.editor;
|
|
106
|
+
return function (tr) {
|
|
107
|
+
var _api$dependencies$ana, _api$dependencies$ana2;
|
|
108
|
+
var _ref3 = (_api$dependencies$ana = api === null || api === void 0 ? void 0 : (_api$dependencies$ana2 = api.dependencies.analytics) === null || _api$dependencies$ana2 === void 0 ? void 0 : _api$dependencies$ana2.sharedState.currentState()) !== null && _api$dependencies$ana !== void 0 ? _api$dependencies$ana : {},
|
|
109
|
+
createAnalyticsEvent = _ref3.createAnalyticsEvent,
|
|
110
|
+
attachAnalyticsEvent = _ref3.attachAnalyticsEvent;
|
|
111
|
+
if (!tr || !createAnalyticsEvent || !attachAnalyticsEvent) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
attachAnalyticsEvent({
|
|
115
|
+
tr: tr,
|
|
116
|
+
payload: payload,
|
|
117
|
+
channel: channel
|
|
118
|
+
});
|
|
119
|
+
return true;
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
pmPlugins: function pmPlugins() {
|
|
124
|
+
return [{
|
|
125
|
+
name: 'analyticsPlugin',
|
|
126
|
+
plugin: function plugin() {
|
|
127
|
+
return createPlugin(options, featureFlags);
|
|
128
|
+
}
|
|
129
|
+
}];
|
|
130
|
+
},
|
|
131
|
+
onEditorViewStateUpdated: function onEditorViewStateUpdated(_ref4) {
|
|
132
|
+
var originalTransaction = _ref4.originalTransaction,
|
|
133
|
+
transactions = _ref4.transactions,
|
|
134
|
+
newEditorState = _ref4.newEditorState;
|
|
135
|
+
var pluginState = analyticsPluginKey.getState(newEditorState);
|
|
136
|
+
if (!pluginState || !pluginState.createAnalyticsEvent) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
var steps = transactions.reduce(function (acc, tr) {
|
|
140
|
+
var payloads = tr.steps.filter(function (step) {
|
|
141
|
+
return step instanceof AnalyticsStep;
|
|
142
|
+
}).map(function (x) {
|
|
143
|
+
return x.analyticsEvents;
|
|
144
|
+
}).reduce(function (acc, val) {
|
|
145
|
+
return acc.concat(val);
|
|
146
|
+
}, []);
|
|
147
|
+
acc.push.apply(acc, _toConsumableArray(payloads));
|
|
148
|
+
return acc;
|
|
149
|
+
}, []);
|
|
150
|
+
if (steps.length === 0) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
var createAnalyticsEvent = pluginState.createAnalyticsEvent;
|
|
154
|
+
var undoAnaltyicsEventTransformer = generateUndoRedoInputSoucePayload(originalTransaction);
|
|
155
|
+
steps.forEach(function (_ref5) {
|
|
156
|
+
var payload = _ref5.payload,
|
|
157
|
+
channel = _ref5.channel;
|
|
158
|
+
var nextPayload = undoAnaltyicsEventTransformer(payload);
|
|
159
|
+
fireAnalyticsEvent(createAnalyticsEvent)({
|
|
160
|
+
payload: nextPayload,
|
|
161
|
+
channel: channel
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
};
|
|
167
|
+
export function extendPayload(_ref6) {
|
|
168
|
+
var payload = _ref6.payload,
|
|
169
|
+
duration = _ref6.duration,
|
|
170
|
+
distortedDuration = _ref6.distortedDuration;
|
|
171
|
+
return _objectSpread(_objectSpread({}, payload), {}, {
|
|
172
|
+
attributes: _objectSpread(_objectSpread({}, payload.attributes), {}, {
|
|
173
|
+
duration: duration,
|
|
174
|
+
distortedDuration: distortedDuration
|
|
175
|
+
}),
|
|
176
|
+
eventType: EVENT_TYPE.OPERATIONAL
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
export { analyticsPlugin };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
3
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
4
|
+
var getUndoRedoInputSource = function getUndoRedoInputSource(tr) {
|
|
5
|
+
var _tr$getMeta;
|
|
6
|
+
// TODO: Please, do not copy or use this kind of code below
|
|
7
|
+
return (_tr$getMeta = tr.getMeta('undoRedoPlugin$')) !== null && _tr$getMeta !== void 0 ? _tr$getMeta : null;
|
|
8
|
+
};
|
|
9
|
+
export var generateUndoRedoInputSoucePayload = function generateUndoRedoInputSoucePayload(tr) {
|
|
10
|
+
var undoRedoPluginInputSource = getUndoRedoInputSource(tr);
|
|
11
|
+
return function (payload) {
|
|
12
|
+
var shouldAddHistoryTriggerMethodAttribute = undoRedoPluginInputSource && ['undid', 'redid'].includes(payload.action);
|
|
13
|
+
return !shouldAddHistoryTriggerMethodAttribute ? payload : _objectSpread(_objectSpread({}, payload), {}, {
|
|
14
|
+
attributes: _objectSpread(_objectSpread({}, payload.attributes), {}, {
|
|
15
|
+
historyTriggerMethod: undoRedoPluginInputSource
|
|
16
|
+
})
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Selection, Transaction } from 'prosemirror-state';
|
|
2
|
+
import { AnalyticsEventPayload } from '@atlaskit/editor-common/analytics';
|
|
3
|
+
type AttachPayloadIntoTransaction = (props: {
|
|
4
|
+
payload: AnalyticsEventPayload;
|
|
5
|
+
selection: Selection;
|
|
6
|
+
tr: Transaction;
|
|
7
|
+
channel: string;
|
|
8
|
+
}) => void;
|
|
9
|
+
export type CreateAttachPayloadIntoTransaction = (props: {
|
|
10
|
+
payload: AnalyticsEventPayload;
|
|
11
|
+
tr: Transaction;
|
|
12
|
+
channel: string;
|
|
13
|
+
}) => void;
|
|
14
|
+
export declare const createAttachPayloadIntoTransaction: (selection: Selection) => CreateAttachPayloadIntoTransaction;
|
|
15
|
+
export declare const attachPayloadIntoTransaction: AttachPayloadIntoTransaction;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Selection } from 'prosemirror-state';
|
|
2
|
+
import { AnalyticsEventPayload, SELECTION_POSITION, SELECTION_TYPE } from '@atlaskit/editor-common/analytics';
|
|
3
|
+
export declare function getSelectionType(selection: Selection): {
|
|
4
|
+
type: SELECTION_TYPE;
|
|
5
|
+
position?: SELECTION_POSITION;
|
|
6
|
+
};
|
|
7
|
+
export declare function findInsertLocation(selection: Selection): string;
|
|
8
|
+
export declare function getStateContext(selection: Selection, payload: AnalyticsEventPayload): AnalyticsEventPayload;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { CreateUIAnalyticsEvent } from '@atlaskit/analytics-next';
|
|
2
|
+
import { AnalyticsEventPayload, EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
|
|
3
|
+
import type { NextEditorPlugin, PerformanceTracking } from '@atlaskit/editor-common/types';
|
|
4
|
+
import type featureFlagsPlugin from '@atlaskit/editor-plugin-feature-flags';
|
|
5
|
+
import { CreateAttachPayloadIntoTransaction } from './analytics-api/attach-payload-into-transaction';
|
|
6
|
+
export interface AnalyticsPluginOptions {
|
|
7
|
+
createAnalyticsEvent?: CreateUIAnalyticsEvent;
|
|
8
|
+
performanceTracking?: PerformanceTracking;
|
|
9
|
+
}
|
|
10
|
+
declare const analyticsPlugin: NextEditorPlugin<'analytics', {
|
|
11
|
+
pluginConfiguration: AnalyticsPluginOptions;
|
|
12
|
+
sharedState: {
|
|
13
|
+
createAnalyticsEvent: CreateUIAnalyticsEvent | null;
|
|
14
|
+
attachAnalyticsEvent: CreateAttachPayloadIntoTransaction | null;
|
|
15
|
+
};
|
|
16
|
+
dependencies: [typeof featureFlagsPlugin];
|
|
17
|
+
actions: EditorAnalyticsAPI;
|
|
18
|
+
}>;
|
|
19
|
+
export declare function extendPayload({ payload, duration, distortedDuration, }: {
|
|
20
|
+
payload: AnalyticsEventPayload;
|
|
21
|
+
duration: number;
|
|
22
|
+
distortedDuration: boolean;
|
|
23
|
+
}): AnalyticsEventPayload<void>;
|
|
24
|
+
export { analyticsPlugin };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Selection, Transaction } from 'prosemirror-state';
|
|
2
|
+
import { AnalyticsEventPayload } from '@atlaskit/editor-common/analytics';
|
|
3
|
+
type AttachPayloadIntoTransaction = (props: {
|
|
4
|
+
payload: AnalyticsEventPayload;
|
|
5
|
+
selection: Selection;
|
|
6
|
+
tr: Transaction;
|
|
7
|
+
channel: string;
|
|
8
|
+
}) => void;
|
|
9
|
+
export type CreateAttachPayloadIntoTransaction = (props: {
|
|
10
|
+
payload: AnalyticsEventPayload;
|
|
11
|
+
tr: Transaction;
|
|
12
|
+
channel: string;
|
|
13
|
+
}) => void;
|
|
14
|
+
export declare const createAttachPayloadIntoTransaction: (selection: Selection) => CreateAttachPayloadIntoTransaction;
|
|
15
|
+
export declare const attachPayloadIntoTransaction: AttachPayloadIntoTransaction;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Selection } from 'prosemirror-state';
|
|
2
|
+
import { AnalyticsEventPayload, SELECTION_POSITION, SELECTION_TYPE } from '@atlaskit/editor-common/analytics';
|
|
3
|
+
export declare function getSelectionType(selection: Selection): {
|
|
4
|
+
type: SELECTION_TYPE;
|
|
5
|
+
position?: SELECTION_POSITION;
|
|
6
|
+
};
|
|
7
|
+
export declare function findInsertLocation(selection: Selection): string;
|
|
8
|
+
export declare function getStateContext(selection: Selection, payload: AnalyticsEventPayload): AnalyticsEventPayload;
|