@atlaskit/editor-plugin-metrics 3.3.1 → 3.4.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.
Files changed (92) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/cjs/metricsPlugin.js +20 -11
  3. package/dist/cjs/pm-plugins/main.js +22 -99
  4. package/dist/cjs/pm-plugins/utils/analytics.js +22 -28
  5. package/dist/cjs/pm-plugins/utils/check-tr-actions/check-tr-action-type.js +90 -0
  6. package/dist/cjs/pm-plugins/utils/check-tr-actions/tr-checks/check-content-moved.js +26 -0
  7. package/dist/cjs/pm-plugins/utils/check-tr-actions/tr-checks/check-deleting-content.js +20 -0
  8. package/dist/cjs/pm-plugins/utils/check-tr-actions/tr-checks/check-empty-line-added-or-deleted.js +29 -0
  9. package/dist/cjs/pm-plugins/utils/check-tr-actions/tr-checks/check-list-type-node-changed.js +37 -0
  10. package/dist/cjs/pm-plugins/utils/check-tr-actions/tr-checks/check-mark-changed.js +16 -0
  11. package/dist/cjs/pm-plugins/utils/check-tr-actions/tr-checks/check-node-attribute-changed.js +103 -0
  12. package/dist/cjs/pm-plugins/utils/check-tr-actions/tr-checks/check-status-changed.js +22 -0
  13. package/dist/cjs/pm-plugins/utils/check-tr-actions/tr-checks/check-table-column-resized.js +60 -0
  14. package/dist/cjs/pm-plugins/utils/check-tr-actions/tr-checks/check-text-input.js +23 -0
  15. package/dist/cjs/pm-plugins/utils/check-tr-actions/types.js +23 -0
  16. package/dist/cjs/pm-plugins/utils/get-new-plugin-state.js +103 -0
  17. package/dist/cjs/pm-plugins/utils/is-safe-insert.js +37 -0
  18. package/dist/cjs/pm-plugins/utils/should-skip-tr.js +52 -0
  19. package/dist/es2019/metricsPlugin.js +9 -1
  20. package/dist/es2019/pm-plugins/main.js +22 -109
  21. package/dist/es2019/pm-plugins/utils/analytics.js +11 -19
  22. package/dist/es2019/pm-plugins/utils/check-tr-actions/check-tr-action-type.js +81 -0
  23. package/dist/es2019/pm-plugins/utils/check-tr-actions/tr-checks/check-content-moved.js +20 -0
  24. package/dist/es2019/pm-plugins/utils/check-tr-actions/tr-checks/check-deleting-content.js +17 -0
  25. package/dist/es2019/pm-plugins/utils/check-tr-actions/tr-checks/check-empty-line-added-or-deleted.js +26 -0
  26. package/dist/es2019/pm-plugins/utils/check-tr-actions/tr-checks/check-list-type-node-changed.js +23 -0
  27. package/dist/es2019/pm-plugins/utils/check-tr-actions/tr-checks/check-mark-changed.js +10 -0
  28. package/dist/es2019/pm-plugins/utils/check-tr-actions/tr-checks/check-node-attribute-changed.js +71 -0
  29. package/dist/es2019/pm-plugins/utils/check-tr-actions/tr-checks/check-status-changed.js +18 -0
  30. package/dist/es2019/pm-plugins/utils/check-tr-actions/tr-checks/check-table-column-resized.js +53 -0
  31. package/dist/es2019/pm-plugins/utils/check-tr-actions/tr-checks/check-text-input.js +20 -0
  32. package/dist/es2019/pm-plugins/utils/check-tr-actions/types.js +17 -0
  33. package/dist/es2019/pm-plugins/utils/get-new-plugin-state.js +101 -0
  34. package/dist/es2019/pm-plugins/utils/is-safe-insert.js +28 -0
  35. package/dist/es2019/pm-plugins/utils/should-skip-tr.js +38 -0
  36. package/dist/esm/metricsPlugin.js +20 -11
  37. package/dist/esm/pm-plugins/main.js +21 -98
  38. package/dist/esm/pm-plugins/utils/analytics.js +21 -27
  39. package/dist/esm/pm-plugins/utils/check-tr-actions/check-tr-action-type.js +83 -0
  40. package/dist/esm/pm-plugins/utils/check-tr-actions/tr-checks/check-content-moved.js +20 -0
  41. package/dist/esm/pm-plugins/utils/check-tr-actions/tr-checks/check-deleting-content.js +14 -0
  42. package/dist/esm/pm-plugins/utils/check-tr-actions/tr-checks/check-empty-line-added-or-deleted.js +23 -0
  43. package/dist/esm/pm-plugins/utils/check-tr-actions/tr-checks/check-list-type-node-changed.js +31 -0
  44. package/dist/esm/pm-plugins/utils/check-tr-actions/tr-checks/check-mark-changed.js +10 -0
  45. package/dist/esm/pm-plugins/utils/check-tr-actions/tr-checks/check-node-attribute-changed.js +96 -0
  46. package/dist/esm/pm-plugins/utils/check-tr-actions/tr-checks/check-status-changed.js +16 -0
  47. package/dist/esm/pm-plugins/utils/check-tr-actions/tr-checks/check-table-column-resized.js +54 -0
  48. package/dist/esm/pm-plugins/utils/check-tr-actions/tr-checks/check-text-input.js +17 -0
  49. package/dist/esm/pm-plugins/utils/check-tr-actions/types.js +17 -0
  50. package/dist/esm/pm-plugins/utils/get-new-plugin-state.js +96 -0
  51. package/dist/esm/pm-plugins/utils/is-safe-insert.js +30 -0
  52. package/dist/esm/pm-plugins/utils/should-skip-tr.js +46 -0
  53. package/dist/types/metricsPluginType.d.ts +2 -2
  54. package/dist/types/pm-plugins/main.d.ts +4 -1
  55. package/dist/types/pm-plugins/utils/analytics.d.ts +1 -7
  56. package/dist/types/pm-plugins/utils/check-tr-actions/check-tr-action-type.d.ts +3 -0
  57. package/dist/types/pm-plugins/utils/check-tr-actions/tr-checks/check-content-moved.d.ts +3 -0
  58. package/dist/types/pm-plugins/utils/check-tr-actions/tr-checks/check-deleting-content.d.ts +3 -0
  59. package/dist/types/pm-plugins/utils/check-tr-actions/tr-checks/check-empty-line-added-or-deleted.d.ts +3 -0
  60. package/dist/types/pm-plugins/utils/check-tr-actions/tr-checks/check-list-type-node-changed.d.ts +3 -0
  61. package/dist/types/pm-plugins/utils/check-tr-actions/tr-checks/check-mark-changed.d.ts +3 -0
  62. package/dist/types/pm-plugins/utils/check-tr-actions/tr-checks/check-node-attribute-changed.d.ts +4 -0
  63. package/dist/types/pm-plugins/utils/check-tr-actions/tr-checks/check-status-changed.d.ts +3 -0
  64. package/dist/types/pm-plugins/utils/check-tr-actions/tr-checks/check-table-column-resized.d.ts +3 -0
  65. package/dist/types/pm-plugins/utils/check-tr-actions/tr-checks/check-text-input.d.ts +3 -0
  66. package/dist/types/pm-plugins/utils/check-tr-actions/types.d.ts +44 -0
  67. package/dist/types/pm-plugins/utils/get-new-plugin-state.d.ts +56 -0
  68. package/dist/types/pm-plugins/utils/is-safe-insert.d.ts +3 -0
  69. package/dist/types/pm-plugins/utils/should-skip-tr.d.ts +2 -0
  70. package/dist/types-ts4.5/metricsPluginType.d.ts +2 -3
  71. package/dist/types-ts4.5/pm-plugins/main.d.ts +4 -1
  72. package/dist/types-ts4.5/pm-plugins/utils/analytics.d.ts +1 -7
  73. package/dist/types-ts4.5/pm-plugins/utils/check-tr-actions/check-tr-action-type.d.ts +3 -0
  74. package/dist/types-ts4.5/pm-plugins/utils/check-tr-actions/tr-checks/check-content-moved.d.ts +3 -0
  75. package/dist/types-ts4.5/pm-plugins/utils/check-tr-actions/tr-checks/check-deleting-content.d.ts +3 -0
  76. package/dist/types-ts4.5/pm-plugins/utils/check-tr-actions/tr-checks/check-empty-line-added-or-deleted.d.ts +3 -0
  77. package/dist/types-ts4.5/pm-plugins/utils/check-tr-actions/tr-checks/check-list-type-node-changed.d.ts +3 -0
  78. package/dist/types-ts4.5/pm-plugins/utils/check-tr-actions/tr-checks/check-mark-changed.d.ts +3 -0
  79. package/dist/types-ts4.5/pm-plugins/utils/check-tr-actions/tr-checks/check-node-attribute-changed.d.ts +4 -0
  80. package/dist/types-ts4.5/pm-plugins/utils/check-tr-actions/tr-checks/check-status-changed.d.ts +3 -0
  81. package/dist/types-ts4.5/pm-plugins/utils/check-tr-actions/tr-checks/check-table-column-resized.d.ts +3 -0
  82. package/dist/types-ts4.5/pm-plugins/utils/check-tr-actions/tr-checks/check-text-input.d.ts +3 -0
  83. package/dist/types-ts4.5/pm-plugins/utils/check-tr-actions/types.d.ts +44 -0
  84. package/dist/types-ts4.5/pm-plugins/utils/get-new-plugin-state.d.ts +56 -0
  85. package/dist/types-ts4.5/pm-plugins/utils/is-safe-insert.d.ts +3 -0
  86. package/dist/types-ts4.5/pm-plugins/utils/should-skip-tr.d.ts +2 -0
  87. package/package.json +12 -6
  88. package/dist/cjs/pm-plugins/utils/check-tr-action-type.js +0 -312
  89. package/dist/es2019/pm-plugins/utils/check-tr-action-type.js +0 -271
  90. package/dist/esm/pm-plugins/utils/check-tr-action-type.js +0 -305
  91. package/dist/types/pm-plugins/utils/check-tr-action-type.d.ts +0 -38
  92. package/dist/types-ts4.5/pm-plugins/utils/check-tr-action-type.d.ts +0 -38
@@ -6,9 +6,9 @@ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
6
6
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
7
7
  import { ActiveSessionTimer } from './utils/active-session-timer';
8
8
  import { getAnalyticsPayload } from './utils/analytics';
9
- import { ActionType, checkTrActionType, shouldSkipTr } from './utils/check-tr-action-type';
10
- import { isNonTextUndo } from './utils/is-non-text-undo';
9
+ import { getNewPluginState } from './utils/get-new-plugin-state';
11
10
  import { isTrWithDocChanges } from './utils/is-tr-with-doc-changes';
11
+ import { shouldSkipTr } from './utils/should-skip-tr';
12
12
  export var metricsKey = new PluginKey('metricsPlugin');
13
13
  export var initialPluginState = {
14
14
  intentToStartEditTime: undefined,
@@ -24,9 +24,12 @@ export var initialPluginState = {
24
24
  nodeAttributeChangeCount: 0,
25
25
  contentMovedCount: 0,
26
26
  nodeDeletionCount: 0,
27
- undoCount: 0
27
+ undoCount: 0,
28
+ markChangeCount: 0,
29
+ contentDeletedCount: 0
28
30
  },
29
- repeatedActionCount: 0
31
+ repeatedActionCount: 0,
32
+ safeInsertCount: 0
30
33
  };
31
34
  export var createPlugin = function createPlugin(api) {
32
35
  var timer = new ActiveSessionTimer(api);
@@ -41,6 +44,7 @@ export var createPlugin = function createPlugin(api) {
41
44
  // eslint-disable-next-line @typescript-eslint/max-params
42
45
  apply: function apply(tr, pluginState, oldState, newState) {
43
46
  var _meta$shouldPersistAc;
47
+ // Return if transaction is remote or replaceDocument is set
44
48
  if (tr.getMeta('isRemote') || tr.getMeta('replaceDocument')) {
45
49
  return pluginState;
46
50
  }
@@ -56,127 +60,46 @@ export var createPlugin = function createPlugin(api) {
56
60
  var hasDocChanges = isTrWithDocChanges(tr);
57
61
  var intentToStartEditTime = (meta === null || meta === void 0 ? void 0 : meta.intentToStartEditTime) || pluginState.intentToStartEditTime;
58
62
  var now = performance.now();
63
+ // If there is no intentToStartEditTime and there are no doc changes, return the plugin state
59
64
  if (!intentToStartEditTime && !hasDocChanges && !tr.storedMarksSet) {
60
65
  return pluginState;
61
66
  }
67
+
68
+ // Set intentToStartEditTime if it is not set and there are doc changes or marks are set
62
69
  if (!intentToStartEditTime && (hasDocChanges || tr.storedMarksSet)) {
63
70
  intentToStartEditTime = now;
64
71
  }
65
72
 
66
- // Start active session timer if intentToStartEditTime is set and shouldStartTimer is true
67
- // shouldPersistActiveSession is set to true when dragging block controls and when insert menu is open
73
+ // Start active session timer if intentToStartEditTime is defined, shouldStartTimer is true and shouldPersistActiveSession is false
74
+ // shouldPersistActiveSession is true when dragging block controls and when insert menu is open as user is interacting with the editor without making doc changes
68
75
  // Timer should start when menu closes or dragging stops
69
76
  if (intentToStartEditTime && meta !== null && meta !== void 0 && meta.shouldStartTimer && !pluginState.shouldPersistActiveSession) {
70
77
  timer.startTimer();
71
78
  }
72
- var undoCount = isNonTextUndo(tr) ? 1 : 0;
73
- var newActionTypeCount = pluginState.actionTypeCount ? _objectSpread(_objectSpread({}, pluginState.actionTypeCount), {}, {
74
- undoCount: pluginState.actionTypeCount.undoCount + undoCount
75
- }) : _objectSpread(_objectSpread({}, initialPluginState.actionTypeCount), {}, {
76
- undoCount: undoCount
77
- });
78
79
  if (hasDocChanges) {
79
80
  timer.startTimer();
80
- var actionTypeCount = pluginState.actionTypeCount,
81
- timeOfLastTextInput = pluginState.timeOfLastTextInput,
82
- totalActionCount = pluginState.totalActionCount,
83
- previousTrType = pluginState.previousTrType;
84
81
  if (shouldSkipTr(tr)) {
85
82
  return pluginState;
86
83
  }
87
- var trType = checkTrActionType(tr);
88
- var shouldNotIncrementActionCount = false;
89
- var shouldSetTimeOfLastTextInput = false;
90
- var isTextInput = false;
91
- if (trType) {
92
- var _trType$extraData, _previousTrType$extra;
93
- var isNotNewStatus = trType.type === ActionType.UPDATING_STATUS && (previousTrType === null || previousTrType === void 0 ? void 0 : previousTrType.type) === ActionType.UPDATING_STATUS && (trType === null || trType === void 0 || (_trType$extraData = trType.extraData) === null || _trType$extraData === void 0 ? void 0 : _trType$extraData.statusId) === (previousTrType === null || previousTrType === void 0 || (_previousTrType$extra = previousTrType.extraData) === null || _previousTrType$extra === void 0 ? void 0 : _previousTrType$extra.statusId);
94
- var isAddingTextToListNode = trType.type === ActionType.TEXT_INPUT && !!previousTrType && [ActionType.UPDATING_NEW_LIST_TYPE_ITEM, ActionType.INSERTING_NEW_LIST_TYPE_NODE].includes(previousTrType.type);
95
- var isAddingNewListItemAfterTextInput = !!previousTrType && previousTrType.type === ActionType.TEXT_INPUT && [ActionType.UPDATING_NEW_LIST_TYPE_ITEM].includes(trType.type);
96
-
97
- // Check if tr is textInput and only increment textInputCount if previous action was not textInput
98
- isTextInput = [ActionType.TEXT_INPUT, ActionType.EMPTY_LINE_ADDED_OR_DELETED].includes(trType.type);
99
-
100
- // timeOfLastTextInput should be set if tr includes continuous text input on the same node
101
- shouldSetTimeOfLastTextInput = [ActionType.TEXT_INPUT, ActionType.EMPTY_LINE_ADDED_OR_DELETED, ActionType.UPDATING_NEW_LIST_TYPE_ITEM, ActionType.INSERTING_NEW_LIST_TYPE_NODE, ActionType.UPDATING_STATUS].includes(trType.type) || isNotNewStatus;
102
-
103
- // Should not increase action count if tr is text input,
104
- // empty line added or deleted, updating new list item or is updating same status node
105
-
106
- shouldNotIncrementActionCount = isTextInput || isNotNewStatus || isAddingTextToListNode || isAddingNewListItemAfterTextInput;
107
- }
108
- var newTextInputCount = isTextInput ? actionTypeCount.textInputCount + 1 : actionTypeCount.textInputCount;
109
- var newTotalActionCount = totalActionCount + 1;
110
- if (timeOfLastTextInput && shouldNotIncrementActionCount) {
111
- newTotalActionCount = totalActionCount;
112
- }
113
- if (timeOfLastTextInput && isTextInput && previousTrType && [ActionType.TEXT_INPUT, ActionType.EMPTY_LINE_ADDED_OR_DELETED, ActionType.UPDATING_NEW_LIST_TYPE_ITEM, ActionType.INSERTING_NEW_LIST_TYPE_NODE].includes(previousTrType.type)) {
114
- newTextInputCount = actionTypeCount.textInputCount;
115
- }
116
- var newNodeAttrCount = actionTypeCount.nodeAttributeChangeCount;
117
- var newRepeatedActionCount = pluginState.repeatedActionCount;
118
- if ((trType === null || trType === void 0 ? void 0 : trType.type) === ActionType.CHANGING_ATTRS) {
119
- newNodeAttrCount = newNodeAttrCount + 1;
120
- if ((previousTrType === null || previousTrType === void 0 ? void 0 : previousTrType.type) === ActionType.CHANGING_ATTRS) {
121
- var _trType$extraData2 = trType.extraData,
122
- newAttr = _trType$extraData2.attr,
123
- newFrom = _trType$extraData2.from,
124
- newTo = _trType$extraData2.to;
125
- var _previousTrType$extra2 = previousTrType.extraData,
126
- prevAttr = _previousTrType$extra2.attr,
127
- prevFrom = _previousTrType$extra2.from,
128
- prevTo = _previousTrType$extra2.to;
129
- newRepeatedActionCount = newAttr === prevAttr && newFrom === prevFrom && newTo === prevTo ? newRepeatedActionCount + 1 : newRepeatedActionCount;
130
- }
131
- }
132
- var newPluginState = _objectSpread(_objectSpread({}, pluginState), {}, {
133
- activeSessionTime: now - intentToStartEditTime,
134
- totalActionCount: newTotalActionCount,
135
- timeOfLastTextInput: shouldSetTimeOfLastTextInput ? now : undefined,
136
- contentSizeChanged: pluginState.contentSizeChanged + (newState.doc.content.size - oldState.doc.content.size),
137
- actionTypeCount: _objectSpread(_objectSpread({}, newActionTypeCount), {}, {
138
- textInputCount: newTextInputCount,
139
- nodeAttributeChangeCount: newNodeAttrCount
140
- }),
84
+ var newPluginState = getNewPluginState({
85
+ now: now,
141
86
  intentToStartEditTime: intentToStartEditTime,
142
87
  shouldPersistActiveSession: shouldPersistActiveSession,
143
- previousTrType: trType,
144
- repeatedActionCount: newRepeatedActionCount
88
+ tr: tr,
89
+ pluginState: pluginState,
90
+ oldState: oldState,
91
+ newState: newState
145
92
  });
146
93
  return newPluginState;
147
94
  }
148
95
  return _objectSpread(_objectSpread({}, pluginState), {}, {
149
96
  lastSelection: (meta === null || meta === void 0 ? void 0 : meta.newSelection) || pluginState.lastSelection,
150
97
  intentToStartEditTime: intentToStartEditTime,
151
- actionTypeCount: newActionTypeCount,
152
98
  shouldPersistActiveSession: shouldPersistActiveSession
153
99
  });
154
100
  }
155
101
  },
156
102
  view: function view(_view) {
157
- var _api$blockControls;
158
- var handleIsDraggingChanged = api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.onChange(function (_ref) {
159
- var nextSharedState = _ref.nextSharedState,
160
- prevSharedState = _ref.prevSharedState;
161
- if (nextSharedState) {
162
- api === null || api === void 0 || api.core.actions.execute(function (_ref2) {
163
- var tr = _ref2.tr;
164
- if (!(prevSharedState !== null && prevSharedState !== void 0 && prevSharedState.isDragging) && nextSharedState.isDragging) {
165
- api === null || api === void 0 || api.metrics.commands.handleIntentToStartEdit({
166
- shouldStartTimer: false,
167
- shouldPersistActiveSession: true
168
- })({
169
- tr: tr
170
- });
171
- } else if (prevSharedState !== null && prevSharedState !== void 0 && prevSharedState.isDragging && !nextSharedState.isDragging) {
172
- api === null || api === void 0 || api.metrics.commands.startActiveSessionTimer()({
173
- tr: tr
174
- });
175
- }
176
- return tr;
177
- });
178
- }
179
- });
180
103
  var fireAnalyticsEvent = function fireAnalyticsEvent() {
181
104
  var pluginState = metricsKey.getState(_view.state);
182
105
  if (!pluginState) {
@@ -187,7 +110,8 @@ export var createPlugin = function createPlugin(api) {
187
110
  pluginState: pluginState
188
111
  });
189
112
  if (pluginState && pluginState.totalActionCount > 0 && pluginState.activeSessionTime > 0) {
190
- api === null || api === void 0 || api.analytics.actions.fireAnalyticsEvent(payloadToSend, undefined, {
113
+ var _api$analytics;
114
+ api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.fireAnalyticsEvent(payloadToSend, undefined, {
191
115
  immediate: true
192
116
  });
193
117
  }
@@ -203,7 +127,6 @@ export var createPlugin = function createPlugin(api) {
203
127
  fireAnalyticsEvent();
204
128
  timer.cleanupTimer();
205
129
  unbindBeforeUnload();
206
- handleIsDraggingChanged === null || handleIsDraggingChanged === void 0 || handleIsDraggingChanged();
207
130
  }
208
131
  };
209
132
  },
@@ -4,37 +4,30 @@ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbol
4
4
  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; }
5
5
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
6
6
  import { getNodeChanges } from './get-node-changes';
7
- export var getPayloadAttributes = function getPayloadAttributes(_ref) {
8
- var pluginState = _ref.pluginState,
9
- contentSizeChanged = _ref.contentSizeChanged;
10
- return {
11
- efficiency: {
12
- totalActiveTime: pluginState.activeSessionTime,
13
- totalActionCount: pluginState.totalActionCount,
14
- actionByTypeCount: pluginState.actionTypeCount
15
- },
16
- effectiveness: {
17
- undoCount: pluginState.actionTypeCount.undoCount,
18
- repeatedActionCount: pluginState.repeatedActionCount,
19
- safeInsertCount: 0
20
- },
21
- contentSizeChanged: contentSizeChanged
22
- };
23
- };
24
- export var getAnalyticsPayload = function getAnalyticsPayload(_ref2) {
7
+ export var getAnalyticsPayload = function getAnalyticsPayload(_ref) {
25
8
  var _pluginState$actionTy;
26
- var currentContent = _ref2.currentContent,
27
- pluginState = _ref2.pluginState;
9
+ var currentContent = _ref.currentContent,
10
+ pluginState = _ref.pluginState;
28
11
  var nodeChanges = getNodeChanges({
29
12
  currentContent: currentContent,
30
13
  pluginState: pluginState
31
14
  });
15
+ var getActionCountByTypeSum = function getActionCountByTypeSum() {
16
+ var actionCountByTypeSum = 0;
17
+ Object.entries(pluginState.actionTypeCount).forEach(function (_ref2) {
18
+ var _ref3 = _slicedToArray(_ref2, 2),
19
+ _actionType = _ref3[0],
20
+ count = _ref3[1];
21
+ actionCountByTypeSum += count;
22
+ });
23
+ return pluginState.totalActionCount - actionCountByTypeSum;
24
+ };
32
25
  var nodeInsertionCount = 0;
33
26
  var nodeDeletionCount = 0;
34
- Object.entries(nodeChanges).forEach(function (_ref3) {
35
- var _ref4 = _slicedToArray(_ref3, 2),
36
- _ = _ref4[0],
37
- change = _ref4[1];
27
+ Object.entries(nodeChanges).forEach(function (_ref4) {
28
+ var _ref5 = _slicedToArray(_ref4, 2),
29
+ _ = _ref5[0],
30
+ change = _ref5[1];
38
31
  if (change > 0) {
39
32
  nodeInsertionCount += change;
40
33
  } else if (change < 0) {
@@ -47,17 +40,18 @@ export var getAnalyticsPayload = function getAnalyticsPayload(_ref2) {
47
40
  actionSubjectId: ACTION_SUBJECT_ID.ACTIVITY,
48
41
  attributes: {
49
42
  efficiency: {
50
- totalActiveTime: pluginState.activeSessionTime,
43
+ totalActiveTime: pluginState.activeSessionTime / 1000,
51
44
  totalActionCount: pluginState.totalActionCount,
52
45
  actionByTypeCount: _objectSpread(_objectSpread({}, (_pluginState$actionTy = pluginState.actionTypeCount) !== null && _pluginState$actionTy !== void 0 ? _pluginState$actionTy : {}), {}, {
53
46
  nodeDeletionCount: nodeDeletionCount,
54
- nodeInsertionCount: nodeInsertionCount
47
+ nodeInsertionCount: nodeInsertionCount,
48
+ other: getActionCountByTypeSum()
55
49
  })
56
50
  },
57
51
  effectiveness: {
58
52
  undoCount: pluginState.actionTypeCount.undoCount,
59
53
  repeatedActionCount: pluginState.repeatedActionCount,
60
- safeInsertCount: 0
54
+ safeInsertCount: pluginState.safeInsertCount
61
55
  },
62
56
  contentSizeChanged: pluginState.contentSizeChanged
63
57
  },
@@ -0,0 +1,83 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import { ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
3
+ import { checkContentPastedOrMoved } from './tr-checks/check-content-moved';
4
+ import { checkDeletingContent } from './tr-checks/check-deleting-content';
5
+ import { checkEmptyLineAddedOrDeleted } from './tr-checks/check-empty-line-added-or-deleted';
6
+ import { checkListTypeNodeChanged } from './tr-checks/check-list-type-node-changed';
7
+ import { checkMarkChanged } from './tr-checks/check-mark-changed';
8
+ import { checkNodeAttributeChanged } from './tr-checks/check-node-attribute-changed';
9
+ import { checkStatusChanged } from './tr-checks/check-status-changed';
10
+ import { checkTableColumnResized } from './tr-checks/check-table-column-resized';
11
+ import { checkTextInput } from './tr-checks/check-text-input';
12
+ export var checkTrActionType = function checkTrActionType(tr) {
13
+ var stepsLength = tr.steps.length;
14
+ if (stepsLength <= 0) {
15
+ return undefined;
16
+ }
17
+ var contentPastedOrMoved = checkContentPastedOrMoved(tr);
18
+ if (contentPastedOrMoved) {
19
+ return contentPastedOrMoved;
20
+ }
21
+
22
+ // Resized column data is either AttrStep or BatchAttrsStep, so we want to check it first
23
+ var resizedColumnData = checkTableColumnResized(tr);
24
+ if (resizedColumnData) {
25
+ return resizedColumnData;
26
+ }
27
+
28
+ // Since we are looking at editor actions, we want to look at the first step only
29
+ var _tr$steps = _slicedToArray(tr.steps, 1),
30
+ firstStep = _tr$steps[0];
31
+ var isReplaceStep = firstStep instanceof ReplaceStep;
32
+ var isReplaceAroundStep = firstStep instanceof ReplaceAroundStep;
33
+
34
+ // Check if mark is added or removed, this is for text formatting changes
35
+ var marksChanged = checkMarkChanged(firstStep);
36
+ if (marksChanged) {
37
+ return marksChanged;
38
+ }
39
+
40
+ // Return early if it's not a replace step or replace around step as following checks are for these steps only
41
+ if (!(isReplaceStep || isReplaceAroundStep)) {
42
+ return undefined;
43
+ }
44
+ if (isReplaceStep) {
45
+ // Check if tr is text input as we want to ignore continuous typing actions
46
+ var textInput = checkTextInput(firstStep);
47
+ if (textInput) {
48
+ return textInput;
49
+ }
50
+
51
+ // Check if tr is adding/ removing empty lines as we want to ignore continuous typing actions
52
+ var emptyLineAddedOrDeleted = checkEmptyLineAddedOrDeleted(firstStep);
53
+ if (emptyLineAddedOrDeleted) {
54
+ return emptyLineAddedOrDeleted;
55
+ }
56
+
57
+ //Check if tr is removing content
58
+ var isDeletingContent = checkDeletingContent(firstStep);
59
+ if (isDeletingContent) {
60
+ return isDeletingContent;
61
+ }
62
+
63
+ // Status nodes save status content in attributes and a new transaction is fired each keypress
64
+ // Check if tr is updating status so we can handle actionCount correctly
65
+ var status = checkStatusChanged(firstStep);
66
+ if (status) {
67
+ return status;
68
+ }
69
+ }
70
+
71
+ // Check if tr is updating list type node because we want to ignore continuous typing actions and adding new list items
72
+ var updatingListTypeNode = checkListTypeNodeChanged(firstStep);
73
+ if (updatingListTypeNode) {
74
+ return updatingListTypeNode;
75
+ }
76
+
77
+ // Check if tr is updating node attributes so we can track nodeAttributeChangeCount
78
+ var nodeAttributeChange = checkNodeAttributeChanged(tr, firstStep);
79
+ if (nodeAttributeChange) {
80
+ return nodeAttributeChange;
81
+ }
82
+ return undefined;
83
+ };
@@ -0,0 +1,20 @@
1
+ import { metricsKey } from '../../../main';
2
+ import { ActionType } from '../types';
3
+ var UI_EVENT = 'uiEvent';
4
+ var PASTE_EVENT = 'paste';
5
+ export var checkContentPastedOrMoved = function checkContentPastedOrMoved(tr) {
6
+ var _tr$getMeta;
7
+ var isContentMoved = (_tr$getMeta = tr.getMeta(metricsKey)) === null || _tr$getMeta === void 0 ? void 0 : _tr$getMeta.contentMoved;
8
+ var isContentPasted = tr.getMeta(UI_EVENT) === PASTE_EVENT;
9
+ if (isContentMoved) {
10
+ return {
11
+ type: ActionType.MOVING_CONTENT
12
+ };
13
+ }
14
+ if (isContentPasted) {
15
+ return {
16
+ type: ActionType.PASTING_CONTENT
17
+ };
18
+ }
19
+ return undefined;
20
+ };
@@ -0,0 +1,14 @@
1
+ import { ActionType } from '../types';
2
+ export var checkDeletingContent = function checkDeletingContent(step) {
3
+ var _ref = step,
4
+ content = _ref.slice.content,
5
+ from = _ref.from,
6
+ to = _ref.to;
7
+ var isDeletingContent = to !== from && content.childCount === 0;
8
+ if (!isDeletingContent) {
9
+ return undefined;
10
+ }
11
+ return {
12
+ type: ActionType.DELETING_CONTENT
13
+ };
14
+ };
@@ -0,0 +1,23 @@
1
+ import { ActionType } from '../types';
2
+ export var checkEmptyLineAddedOrDeleted = function checkEmptyLineAddedOrDeleted(step) {
3
+ var _ref = step,
4
+ content = _ref.slice.content,
5
+ from = _ref.from,
6
+ to = _ref.to;
7
+ var isEmptyLineDeleted = to - from === 2 && content.size === 0;
8
+ if (isEmptyLineDeleted) {
9
+ return {
10
+ type: ActionType.EMPTY_LINE_ADDED_OR_DELETED
11
+ };
12
+ }
13
+ var isEmptyLineAdded = false;
14
+ content.forEach(function (node) {
15
+ isEmptyLineAdded = node.type.name === 'paragraph' && node.content.size === 0;
16
+ });
17
+ if (!isEmptyLineAdded) {
18
+ return undefined;
19
+ }
20
+ return {
21
+ type: ActionType.EMPTY_LINE_ADDED_OR_DELETED
22
+ };
23
+ };
@@ -0,0 +1,31 @@
1
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, 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 o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
2
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
3
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
4
+ import { ActionType } from '../types';
5
+ export var checkListTypeNodeChanged = function checkListTypeNodeChanged(step) {
6
+ var content = step.slice.content;
7
+ var childCount = content.childCount;
8
+ if (childCount < 1) {
9
+ return undefined;
10
+ }
11
+ var _iterator = _createForOfIteratorHelper(content.content),
12
+ _step;
13
+ try {
14
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
15
+ var node = _step.value;
16
+ var isListTypeNode = ['decisionList', 'decisionItem', 'bulletList', 'listItem', 'orderedList', 'taskList', 'taskItem'].includes(node.type.name);
17
+ if (isListTypeNode) {
18
+ return childCount === 1 ? {
19
+ type: ActionType.INSERTING_NEW_LIST_TYPE_NODE
20
+ } : {
21
+ type: ActionType.UPDATING_NEW_LIST_TYPE_ITEM
22
+ };
23
+ }
24
+ }
25
+ } catch (err) {
26
+ _iterator.e(err);
27
+ } finally {
28
+ _iterator.f();
29
+ }
30
+ return undefined;
31
+ };
@@ -0,0 +1,10 @@
1
+ import { AddMarkStep, RemoveMarkStep } from '@atlaskit/editor-prosemirror/transform';
2
+ import { ActionType } from '../types';
3
+ export var checkMarkChanged = function checkMarkChanged(step) {
4
+ if (!(step instanceof AddMarkStep || step instanceof RemoveMarkStep)) {
5
+ return undefined;
6
+ }
7
+ return {
8
+ type: ActionType.CHANGING_MARK
9
+ };
10
+ };
@@ -0,0 +1,96 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, 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 o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
3
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
4
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
5
+ import { ActionType } from '../types';
6
+ var compareAttributes = function compareAttributes(prevAttr, newAttr) {
7
+ var allKeys = new Set([].concat(_toConsumableArray(Object.keys(prevAttr)), _toConsumableArray(Object.keys(newAttr))));
8
+ var _iterator = _createForOfIteratorHelper(allKeys),
9
+ _step;
10
+ try {
11
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
12
+ var key = _step.value;
13
+ var prevValue = prevAttr[key];
14
+ var newValue = newAttr[key];
15
+ if (prevValue !== newValue && key !== 'localId') {
16
+ return key;
17
+ }
18
+ }
19
+ } catch (err) {
20
+ _iterator.e(err);
21
+ } finally {
22
+ _iterator.f();
23
+ }
24
+ return undefined;
25
+ };
26
+ var compareMarks = function compareMarks(prevMarks, newMarks) {
27
+ if (!prevMarks && !newMarks) {
28
+ return undefined;
29
+ }
30
+ var previousMarksArr = new Map(prevMarks.map(function (mark) {
31
+ return [mark.type.name, mark.attrs];
32
+ }));
33
+ var newMarksArr = new Map(newMarks.map(function (mark) {
34
+ return [mark.type.name, mark.attrs];
35
+ }));
36
+ var allMarks = new Set([].concat(_toConsumableArray(previousMarksArr.keys()), _toConsumableArray(newMarksArr.keys())));
37
+ var _iterator2 = _createForOfIteratorHelper(allMarks),
38
+ _step2;
39
+ try {
40
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
41
+ var key = _step2.value;
42
+ var previousValue = previousMarksArr.get(key);
43
+ var newValue = newMarksArr.get(key);
44
+ if (JSON.stringify(previousValue) !== JSON.stringify(newValue)) {
45
+ return key;
46
+ }
47
+ }
48
+ } catch (err) {
49
+ _iterator2.e(err);
50
+ } finally {
51
+ _iterator2.f();
52
+ }
53
+ return undefined;
54
+ };
55
+ export var checkNodeAttributeChanged = function checkNodeAttributeChanged(tr, step) {
56
+ var _ref = step,
57
+ slice = _ref.slice,
58
+ from = _ref.from,
59
+ to = _ref.to;
60
+ var oldNode = tr.docs[0].nodeAt(from);
61
+ var newNode = slice.content.firstChild;
62
+ if (!oldNode || !newNode) {
63
+ return undefined;
64
+ }
65
+ if (oldNode.type.name !== newNode.type.name) {
66
+ return undefined;
67
+ }
68
+
69
+ // We need to compare the attributes of the node
70
+ var changedAttr = compareAttributes(oldNode.attrs, newNode.attrs);
71
+ if (changedAttr) {
72
+ return {
73
+ type: ActionType.CHANGING_ATTRS,
74
+ extraData: {
75
+ attr: changedAttr,
76
+ from: from,
77
+ to: to
78
+ }
79
+ };
80
+ }
81
+
82
+ // For some changes, we need to compare the marks of the node
83
+ // e.g. Media Border, Links
84
+ var changedMarks = compareMarks(oldNode.marks, newNode.marks);
85
+ if (changedMarks) {
86
+ return {
87
+ type: ActionType.CHANGING_ATTRS,
88
+ extraData: {
89
+ attr: changedMarks,
90
+ from: from,
91
+ to: to
92
+ }
93
+ };
94
+ }
95
+ return undefined;
96
+ };
@@ -0,0 +1,16 @@
1
+ import { ActionType } from '../types';
2
+ export var checkStatusChanged = function checkStatusChanged(step) {
3
+ var slice = step.slice;
4
+ var firstChild = slice.content.firstChild;
5
+ if (!firstChild) {
6
+ return undefined;
7
+ }
8
+
9
+ // Get statusId so that we can track whether edits are performed on same status node
10
+ return firstChild.type.name === 'status' ? {
11
+ type: ActionType.UPDATING_STATUS,
12
+ extraData: {
13
+ statusId: firstChild.attrs.localId
14
+ }
15
+ } : undefined;
16
+ };
@@ -0,0 +1,54 @@
1
+ import { BatchAttrsStep } from '@atlaskit/adf-schema/steps';
2
+ import { AttrStep } from '@atlaskit/editor-prosemirror/transform';
3
+ import { ActionType } from '../types';
4
+ export var checkTableColumnResized = function checkTableColumnResized(tr) {
5
+ var COL_WIDTH_ATTR = 'colwidth';
6
+ var steps = tr.steps;
7
+
8
+ // Find the step that is changing the column width
9
+ var resizingColumnStep = steps.find(function (step) {
10
+ return step instanceof AttrStep || step instanceof BatchAttrsStep;
11
+ });
12
+ if (!resizingColumnStep) {
13
+ return undefined;
14
+ }
15
+ var pos;
16
+
17
+ // Find the position of the first column in the step that is being resized
18
+ if (resizingColumnStep instanceof BatchAttrsStep) {
19
+ if (resizingColumnStep.data.length === 0) {
20
+ return undefined;
21
+ }
22
+ var _resizingColumnStep$d = resizingColumnStep.data[0],
23
+ attrs = _resizingColumnStep$d.attrs,
24
+ nodeType = _resizingColumnStep$d.nodeType,
25
+ position = _resizingColumnStep$d.position;
26
+ if (['tableHeader', 'tableCell'].includes(nodeType) && attrs !== null && attrs !== void 0 && attrs[COL_WIDTH_ATTR]) {
27
+ pos = position;
28
+ }
29
+ } else if (resizingColumnStep instanceof AttrStep && resizingColumnStep.attr === COL_WIDTH_ATTR) {
30
+ pos = resizingColumnStep.pos;
31
+ }
32
+ if (!pos) {
33
+ return undefined;
34
+ }
35
+
36
+ // Find the range of the table that is being resized
37
+ var $pos = tr.doc.resolve(pos);
38
+ var blockRange = $pos.blockRange();
39
+ if (!blockRange) {
40
+ return undefined;
41
+ }
42
+ var from = blockRange.start;
43
+ var to = from + blockRange.parent.content.size;
44
+
45
+ // Use to and from position of table to check whether column width of same table is being resized
46
+ return {
47
+ type: ActionType.CHANGING_ATTRS,
48
+ extraData: {
49
+ attr: COL_WIDTH_ATTR,
50
+ from: from,
51
+ to: to
52
+ }
53
+ };
54
+ };
@@ -0,0 +1,17 @@
1
+ import { ActionType } from '../types';
2
+ export var checkTextInput = function checkTextInput(step) {
3
+ var _ref = step,
4
+ content = _ref.slice.content,
5
+ from = _ref.from,
6
+ to = _ref.to;
7
+ var node = content.firstChild;
8
+ var isAddingCharacter = from === to && content.childCount === 1 && !!node && !!node.text && node.text.length === 1;
9
+ var isDeletingCharacter = to - from === 1 && content.childCount === 0;
10
+ var isTextInput = isAddingCharacter || isDeletingCharacter;
11
+ if (!isTextInput) {
12
+ return undefined;
13
+ }
14
+ return {
15
+ type: ActionType.TEXT_INPUT
16
+ };
17
+ };
@@ -0,0 +1,17 @@
1
+ export var ActionType = /*#__PURE__*/function (ActionType) {
2
+ ActionType["TEXT_INPUT"] = "textInput";
3
+ ActionType["EMPTY_LINE_ADDED_OR_DELETED"] = "emptyLineAddedOrDeleted";
4
+ ActionType["INSERTED_FROM_TYPE_AHEAD"] = "insertedFromTypeAhead";
5
+ ActionType["INSERTING_NEW_LIST_TYPE_NODE"] = "insertingNewListTypeNode";
6
+ ActionType["UPDATING_NEW_LIST_TYPE_ITEM"] = "updatingNewListItem";
7
+ ActionType["ADDING_LINK"] = "addingLink";
8
+ ActionType["UPDATING_STATUS"] = "updatingStatus";
9
+ ActionType["CHANGING_MARK"] = "changingMark";
10
+ ActionType["CHANGING_ATTRS"] = "changingAttrs";
11
+ ActionType["MOVING_CONTENT"] = "contentMoved";
12
+ ActionType["PASTING_CONTENT"] = "contentPasted";
13
+ ActionType["DELETING_CONTENT"] = "deletingContent";
14
+ ActionType["SAFE_INSERT"] = "safeInsert";
15
+ ActionType["UNDO"] = "undo";
16
+ return ActionType;
17
+ }({});