@atlaskit/editor-plugin-metrics 3.2.0 → 3.2.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 +8 -0
- package/dist/cjs/metricsPlugin.js +2 -3
- package/dist/cjs/pm-plugins/main.js +47 -28
- package/dist/cjs/pm-plugins/utils/check-tr-action-type.js +159 -0
- package/dist/es2019/metricsPlugin.js +2 -3
- package/dist/es2019/pm-plugins/main.js +45 -26
- package/dist/es2019/pm-plugins/utils/check-tr-action-type.js +152 -0
- package/dist/esm/metricsPlugin.js +2 -3
- package/dist/esm/pm-plugins/main.js +47 -28
- package/dist/esm/pm-plugins/utils/check-tr-action-type.js +152 -0
- package/dist/types/pm-plugins/main.d.ts +2 -0
- package/dist/types/pm-plugins/utils/check-tr-action-type.d.ts +18 -0
- package/dist/types-ts4.5/pm-plugins/main.d.ts +2 -0
- package/dist/types-ts4.5/pm-plugins/utils/check-tr-action-type.d.ts +18 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-metrics
|
|
2
2
|
|
|
3
|
+
## 3.2.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#114961](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/114961)
|
|
8
|
+
[`f31ba30a89a05`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/f31ba30a89a05) -
|
|
9
|
+
ED-26301 Add logic to exclude transactions that shouldn't increment totalActionCount
|
|
10
|
+
|
|
3
11
|
## 3.2.0
|
|
4
12
|
|
|
5
13
|
### Minor Changes
|
|
@@ -78,14 +78,13 @@ var metricsPlugin = exports.metricsPlugin = function metricsPlugin(_ref) {
|
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
-
|
|
82
|
-
newTr.setMeta(_main.metricsKey, {
|
|
81
|
+
tr.setMeta(_main.metricsKey, {
|
|
83
82
|
intentToStartEditTime: performance.now(),
|
|
84
83
|
shouldStartTimer: shouldStartTimer,
|
|
85
84
|
newSelection: newSelection,
|
|
86
85
|
shouldPersistActiveSession: shouldPersistActiveSession
|
|
87
86
|
});
|
|
88
|
-
return
|
|
87
|
+
return tr;
|
|
89
88
|
};
|
|
90
89
|
}
|
|
91
90
|
},
|
|
@@ -7,12 +7,12 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
exports.metricsKey = exports.initialPluginState = exports.createPlugin = void 0;
|
|
8
8
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
9
|
var _bindEventListener = require("bind-event-listener");
|
|
10
|
-
var _steps = require("@atlaskit/adf-schema/steps");
|
|
11
10
|
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
12
|
-
var _utils = require("@atlaskit/editor-common/utils");
|
|
13
11
|
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
12
|
+
var _transform = require("@atlaskit/editor-prosemirror/transform");
|
|
14
13
|
var _activeSessionTimer = require("./utils/active-session-timer");
|
|
15
14
|
var _analytics = require("./utils/analytics");
|
|
15
|
+
var _checkTrActionType = require("./utils/check-tr-action-type");
|
|
16
16
|
var _isNonTextUndo = require("./utils/is-non-text-undo");
|
|
17
17
|
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; }
|
|
18
18
|
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; }
|
|
@@ -46,7 +46,7 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
|
|
|
46
46
|
},
|
|
47
47
|
// eslint-disable-next-line @typescript-eslint/max-params
|
|
48
48
|
apply: function apply(tr, pluginState, oldState, newState) {
|
|
49
|
-
var _meta$shouldPersistAc;
|
|
49
|
+
var _meta$shouldPersistAc, _tr$steps;
|
|
50
50
|
if (tr.getMeta('isRemote') || tr.getMeta('replaceDocument')) {
|
|
51
51
|
return pluginState;
|
|
52
52
|
}
|
|
@@ -59,20 +59,16 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
|
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
61
|
var shouldPersistActiveSession = (_meta$shouldPersistAc = meta === null || meta === void 0 ? void 0 : meta.shouldPersistActiveSession) !== null && _meta$shouldPersistAc !== void 0 ? _meta$shouldPersistAc : pluginState.shouldPersistActiveSession;
|
|
62
|
-
var
|
|
63
|
-
return
|
|
64
|
-
|
|
65
|
-
});
|
|
66
|
-
};
|
|
67
|
-
var docChangedWithoutAnalytics = tr.docChanged && canIgnoreTr();
|
|
62
|
+
var hasDocChanges = tr.steps.length > 0 && ((_tr$steps = tr.steps) === null || _tr$steps === void 0 ? void 0 : _tr$steps.some(function (step) {
|
|
63
|
+
return step instanceof _transform.ReplaceStep || step instanceof _transform.ReplaceAroundStep || step instanceof _transform.AddMarkStep;
|
|
64
|
+
}));
|
|
68
65
|
var intentToStartEditTime = (meta === null || meta === void 0 ? void 0 : meta.intentToStartEditTime) || pluginState.intentToStartEditTime;
|
|
69
66
|
var now = performance.now();
|
|
70
|
-
if (!intentToStartEditTime) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
67
|
+
if (!intentToStartEditTime && !hasDocChanges && !tr.storedMarksSet) {
|
|
68
|
+
return pluginState;
|
|
69
|
+
}
|
|
70
|
+
if (!intentToStartEditTime && (hasDocChanges || tr.storedMarksSet)) {
|
|
71
|
+
intentToStartEditTime = now;
|
|
76
72
|
}
|
|
77
73
|
|
|
78
74
|
// Start active session timer if intentToStartEditTime is set and shouldStartTimer is true
|
|
@@ -87,32 +83,55 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
|
|
|
87
83
|
}) : _objectSpread(_objectSpread({}, initialPluginState.actionTypeCount), {}, {
|
|
88
84
|
undoCount: undoCount
|
|
89
85
|
});
|
|
90
|
-
if (
|
|
86
|
+
if (hasDocChanges) {
|
|
91
87
|
timer.startTimer();
|
|
92
88
|
var actionTypeCount = pluginState.actionTypeCount,
|
|
93
89
|
timeOfLastTextInput = pluginState.timeOfLastTextInput,
|
|
94
90
|
totalActionCount = pluginState.totalActionCount,
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
var
|
|
100
|
-
var
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
91
|
+
previousTrType = pluginState.previousTrType;
|
|
92
|
+
if ((0, _checkTrActionType.shouldSkipTr)(tr)) {
|
|
93
|
+
return pluginState;
|
|
94
|
+
}
|
|
95
|
+
var trType = (0, _checkTrActionType.checkTrActionType)(tr);
|
|
96
|
+
var shouldNotIncrementActionCount = false;
|
|
97
|
+
var shouldSetTimeOfLastTextInput = false;
|
|
98
|
+
var isTextInput = false;
|
|
99
|
+
if (trType) {
|
|
100
|
+
var _trType$extraData, _previousTrType$extra;
|
|
101
|
+
var isNotNewStatus = trType.type === _checkTrActionType.ActionType.UPDATING_STATUS && (previousTrType === null || previousTrType === void 0 ? void 0 : previousTrType.type) === _checkTrActionType.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);
|
|
102
|
+
var isAddingTextToListNode = trType.type === _checkTrActionType.ActionType.TEXT_INPUT && !!previousTrType && [_checkTrActionType.ActionType.UPDATING_NEW_LIST_TYPE_ITEM, _checkTrActionType.ActionType.INSERTING_NEW_LIST_TYPE_NODE].includes(previousTrType.type);
|
|
103
|
+
var isAddingNewListItemAfterTextInput = !!previousTrType && previousTrType.type === _checkTrActionType.ActionType.TEXT_INPUT && [_checkTrActionType.ActionType.UPDATING_NEW_LIST_TYPE_ITEM].includes(trType.type);
|
|
104
|
+
|
|
105
|
+
// Check if tr is textInput and only increment textInputCount if previous action was not textInput
|
|
106
|
+
isTextInput = [_checkTrActionType.ActionType.TEXT_INPUT, _checkTrActionType.ActionType.EMPTY_LINE_ADDED_OR_DELETED].includes(trType.type);
|
|
107
|
+
|
|
108
|
+
// timeOfLastTextInput should be set if tr includes continuous text input on the same node
|
|
109
|
+
shouldSetTimeOfLastTextInput = [_checkTrActionType.ActionType.TEXT_INPUT, _checkTrActionType.ActionType.EMPTY_LINE_ADDED_OR_DELETED, _checkTrActionType.ActionType.UPDATING_NEW_LIST_TYPE_ITEM, _checkTrActionType.ActionType.INSERTING_NEW_LIST_TYPE_NODE, _checkTrActionType.ActionType.UPDATING_STATUS].includes(trType.type) || isNotNewStatus;
|
|
110
|
+
|
|
111
|
+
// Should not increase action count if tr is text input,
|
|
112
|
+
// empty line added or deleted, updating new list item or is updating same status node
|
|
113
|
+
|
|
114
|
+
shouldNotIncrementActionCount = isTextInput || isNotNewStatus || isAddingTextToListNode || isAddingNewListItemAfterTextInput;
|
|
115
|
+
}
|
|
116
|
+
var newTextInputCount = isTextInput ? actionTypeCount.textInputCount + 1 : actionTypeCount.textInputCount;
|
|
117
|
+
var newTotalActionCount = totalActionCount + 1;
|
|
118
|
+
if (timeOfLastTextInput && shouldNotIncrementActionCount) {
|
|
104
119
|
newTotalActionCount = totalActionCount;
|
|
105
120
|
}
|
|
121
|
+
if (timeOfLastTextInput && isTextInput && previousTrType && [_checkTrActionType.ActionType.TEXT_INPUT, _checkTrActionType.ActionType.EMPTY_LINE_ADDED_OR_DELETED, _checkTrActionType.ActionType.UPDATING_NEW_LIST_TYPE_ITEM, _checkTrActionType.ActionType.INSERTING_NEW_LIST_TYPE_NODE].includes(previousTrType.type)) {
|
|
122
|
+
newTextInputCount = actionTypeCount.textInputCount;
|
|
123
|
+
}
|
|
106
124
|
var newPluginState = _objectSpread(_objectSpread({}, pluginState), {}, {
|
|
107
|
-
activeSessionTime:
|
|
125
|
+
activeSessionTime: now - intentToStartEditTime,
|
|
108
126
|
totalActionCount: newTotalActionCount,
|
|
109
|
-
timeOfLastTextInput:
|
|
127
|
+
timeOfLastTextInput: shouldSetTimeOfLastTextInput ? now : undefined,
|
|
110
128
|
contentSizeChanged: pluginState.contentSizeChanged + (newState.doc.content.size - oldState.doc.content.size),
|
|
111
129
|
actionTypeCount: _objectSpread(_objectSpread({}, newActionTypeCount), {}, {
|
|
112
130
|
textInputCount: newTextInputCount
|
|
113
131
|
}),
|
|
114
132
|
intentToStartEditTime: intentToStartEditTime,
|
|
115
|
-
shouldPersistActiveSession: shouldPersistActiveSession
|
|
133
|
+
shouldPersistActiveSession: shouldPersistActiveSession,
|
|
134
|
+
previousTrType: trType
|
|
116
135
|
});
|
|
117
136
|
return newPluginState;
|
|
118
137
|
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.shouldSkipTr = exports.checkTrActionType = exports.ActionType = void 0;
|
|
8
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
9
|
+
var _steps = require("@atlaskit/adf-schema/steps");
|
|
10
|
+
var _transform = require("@atlaskit/editor-prosemirror/transform");
|
|
11
|
+
var ActionType = exports.ActionType = /*#__PURE__*/function (ActionType) {
|
|
12
|
+
ActionType["TEXT_INPUT"] = "textInput";
|
|
13
|
+
ActionType["EMPTY_LINE_ADDED_OR_DELETED"] = "emptyLineAddedOrDeleted";
|
|
14
|
+
ActionType["INSERTED_FROM_TYPE_AHEAD"] = "insertedFromTypeAhead";
|
|
15
|
+
ActionType["INSERTING_NEW_LIST_TYPE_NODE"] = "insertingNewListTypeNode";
|
|
16
|
+
ActionType["UPDATING_NEW_LIST_TYPE_ITEM"] = "updatingNewListItem";
|
|
17
|
+
ActionType["ADDING_LINK"] = "addingLink";
|
|
18
|
+
ActionType["UPDATING_STATUS"] = "updatingStatus";
|
|
19
|
+
return ActionType;
|
|
20
|
+
}({});
|
|
21
|
+
var isTextInput = function isTextInput(step) {
|
|
22
|
+
var _ref = step,
|
|
23
|
+
content = _ref.slice.content,
|
|
24
|
+
from = _ref.from,
|
|
25
|
+
to = _ref.to;
|
|
26
|
+
var node = content.firstChild;
|
|
27
|
+
var isAddingCharacter = from === to && content.childCount === 1 && !!node && !!node.text && node.text.length === 1;
|
|
28
|
+
var isDeletingCharacter = to - from === 1 && content.childCount === 0;
|
|
29
|
+
return isAddingCharacter || isDeletingCharacter;
|
|
30
|
+
};
|
|
31
|
+
var isEmptyLineAddedOrDeleted = function isEmptyLineAddedOrDeleted(step) {
|
|
32
|
+
var _ref2 = step,
|
|
33
|
+
content = _ref2.slice.content,
|
|
34
|
+
from = _ref2.from,
|
|
35
|
+
to = _ref2.to;
|
|
36
|
+
var isEmptyLineDeleted = to - from === 2 && content.size === 0;
|
|
37
|
+
if (isEmptyLineDeleted) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
var isEmptyLineAdded = false;
|
|
41
|
+
content.forEach(function (node) {
|
|
42
|
+
isEmptyLineAdded = node.type.name === 'paragraph' && node.content.size === 0;
|
|
43
|
+
});
|
|
44
|
+
return isEmptyLineAdded;
|
|
45
|
+
};
|
|
46
|
+
var isUpdatingListTypeNode = function isUpdatingListTypeNode(step) {
|
|
47
|
+
var slice = step.slice;
|
|
48
|
+
var childCount = slice.content.childCount;
|
|
49
|
+
if (childCount < 1) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
var isListTypeNode = false;
|
|
53
|
+
slice.content.forEach(function (node) {
|
|
54
|
+
isListTypeNode = ['decisionList', 'decisionItem', 'bulletList', 'listItem', 'orderedList', 'taskList', 'taskItem'].includes(node.type.name);
|
|
55
|
+
});
|
|
56
|
+
if (!isListTypeNode) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
return childCount === 1 ? ActionType.INSERTING_NEW_LIST_TYPE_NODE : ActionType.UPDATING_NEW_LIST_TYPE_ITEM;
|
|
60
|
+
};
|
|
61
|
+
var isUpdatingStatus = function isUpdatingStatus(step) {
|
|
62
|
+
var slice = step.slice;
|
|
63
|
+
var firstChild = slice.content.firstChild;
|
|
64
|
+
if (!firstChild) {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
return firstChild.type.name === 'status' && firstChild.attrs.localId;
|
|
68
|
+
};
|
|
69
|
+
var isAddingLink = function isAddingLink(tr) {
|
|
70
|
+
var hasLinkStep = tr.steps.some(function (step) {
|
|
71
|
+
return step instanceof _steps.LinkMetaStep;
|
|
72
|
+
});
|
|
73
|
+
var hasReplaceStep = tr.steps.some(function (step) {
|
|
74
|
+
return step instanceof _transform.ReplaceStep;
|
|
75
|
+
});
|
|
76
|
+
return hasLinkStep && !hasReplaceStep;
|
|
77
|
+
};
|
|
78
|
+
var isTypeAheadRelatedTr = function isTypeAheadRelatedTr(tr) {
|
|
79
|
+
var _tr$getMeta;
|
|
80
|
+
if (((_tr$getMeta = tr.getMeta('typeAheadPlugin$')) === null || _tr$getMeta === void 0 ? void 0 : _tr$getMeta.action) === 'INSERT_RAW_QUERY') {
|
|
81
|
+
return 'INSERT_RAW_QUERY';
|
|
82
|
+
}
|
|
83
|
+
if (!tr.getMeta('appendedTransaction')) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
var insertTypeAheadStep = tr.steps.find(function (step) {
|
|
87
|
+
return step instanceof _steps.InsertTypeAheadStep;
|
|
88
|
+
});
|
|
89
|
+
var replaceStep = tr.steps.find(function (step) {
|
|
90
|
+
return step instanceof _transform.ReplaceStep;
|
|
91
|
+
});
|
|
92
|
+
if (!insertTypeAheadStep || !replaceStep) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
return insertTypeAheadStep instanceof _steps.InsertTypeAheadStep && insertTypeAheadStep.stage;
|
|
96
|
+
};
|
|
97
|
+
var shouldSkipTr = exports.shouldSkipTr = function shouldSkipTr(tr) {
|
|
98
|
+
var resolvingLink = isAddingLink(tr);
|
|
99
|
+
if (resolvingLink) {
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
var typeAheadRelatedTr = isTypeAheadRelatedTr(tr);
|
|
103
|
+
if (typeAheadRelatedTr) {
|
|
104
|
+
return typeAheadRelatedTr !== 'INSERTING_ITEM';
|
|
105
|
+
} else {
|
|
106
|
+
return tr.getMeta('appendedTransaction');
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
var checkTrActionType = exports.checkTrActionType = function checkTrActionType(tr) {
|
|
110
|
+
if (tr.getMeta('input_rule_plugin_transaction')) {
|
|
111
|
+
return {
|
|
112
|
+
type: ActionType.INSERTING_NEW_LIST_TYPE_NODE
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
var stepsLength = tr.steps.length;
|
|
116
|
+
if (stepsLength <= 0) {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
if (isAddingLink(tr)) {
|
|
120
|
+
return {
|
|
121
|
+
type: ActionType.ADDING_LINK
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
var _tr$steps = (0, _slicedToArray2.default)(tr.steps, 1),
|
|
125
|
+
firstStep = _tr$steps[0];
|
|
126
|
+
var isReplaceStep = firstStep instanceof _transform.ReplaceStep;
|
|
127
|
+
var isReplaceAroundStep = firstStep instanceof _transform.ReplaceAroundStep;
|
|
128
|
+
if (!isReplaceStep && !isReplaceAroundStep) {
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
if (isReplaceStep) {
|
|
132
|
+
if (isTextInput(firstStep)) {
|
|
133
|
+
return {
|
|
134
|
+
type: ActionType.TEXT_INPUT
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
if (isEmptyLineAddedOrDeleted(firstStep)) {
|
|
138
|
+
return {
|
|
139
|
+
type: ActionType.EMPTY_LINE_ADDED_OR_DELETED
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
var statusId = isUpdatingStatus(firstStep);
|
|
143
|
+
if (statusId) {
|
|
144
|
+
return {
|
|
145
|
+
type: ActionType.UPDATING_STATUS,
|
|
146
|
+
extraData: {
|
|
147
|
+
statusId: statusId
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
var updatingListTypeNode = isUpdatingListTypeNode(firstStep);
|
|
153
|
+
if (updatingListTypeNode) {
|
|
154
|
+
return {
|
|
155
|
+
type: updatingListTypeNode
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
return undefined;
|
|
159
|
+
};
|
|
@@ -68,14 +68,13 @@ export const metricsPlugin = ({
|
|
|
68
68
|
});
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
-
|
|
72
|
-
newTr.setMeta(metricsKey, {
|
|
71
|
+
tr.setMeta(metricsKey, {
|
|
73
72
|
intentToStartEditTime: performance.now(),
|
|
74
73
|
shouldStartTimer,
|
|
75
74
|
newSelection,
|
|
76
75
|
shouldPersistActiveSession
|
|
77
76
|
});
|
|
78
|
-
return
|
|
77
|
+
return tr;
|
|
79
78
|
}
|
|
80
79
|
},
|
|
81
80
|
getSharedState(editorState) {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { bind } from 'bind-event-listener';
|
|
2
|
-
import { AnalyticsStep } from '@atlaskit/adf-schema/steps';
|
|
3
2
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
4
|
-
import { isTextInput } from '@atlaskit/editor-common/utils';
|
|
5
3
|
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
+
import { AddMarkStep, ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
|
|
6
5
|
import { ActiveSessionTimer } from './utils/active-session-timer';
|
|
7
6
|
import { getAnalyticsPayload } from './utils/analytics';
|
|
7
|
+
import { ActionType, checkTrActionType, shouldSkipTr } from './utils/check-tr-action-type';
|
|
8
8
|
import { isNonTextUndo } from './utils/is-non-text-undo';
|
|
9
9
|
export const metricsKey = new PluginKey('metricsPlugin');
|
|
10
10
|
export const initialPluginState = {
|
|
@@ -37,7 +37,7 @@ export const createPlugin = api => {
|
|
|
37
37
|
},
|
|
38
38
|
// eslint-disable-next-line @typescript-eslint/max-params
|
|
39
39
|
apply(tr, pluginState, oldState, newState) {
|
|
40
|
-
var _meta$shouldPersistAc;
|
|
40
|
+
var _meta$shouldPersistAc, _tr$steps;
|
|
41
41
|
if (tr.getMeta('isRemote') || tr.getMeta('replaceDocument')) {
|
|
42
42
|
return pluginState;
|
|
43
43
|
}
|
|
@@ -51,18 +51,14 @@ export const createPlugin = api => {
|
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
53
|
const shouldPersistActiveSession = (_meta$shouldPersistAc = meta === null || meta === void 0 ? void 0 : meta.shouldPersistActiveSession) !== null && _meta$shouldPersistAc !== void 0 ? _meta$shouldPersistAc : pluginState.shouldPersistActiveSession;
|
|
54
|
-
const
|
|
55
|
-
const docChangedWithoutAnalytics = tr.docChanged && canIgnoreTr();
|
|
54
|
+
const hasDocChanges = tr.steps.length > 0 && ((_tr$steps = tr.steps) === null || _tr$steps === void 0 ? void 0 : _tr$steps.some(step => step instanceof ReplaceStep || step instanceof ReplaceAroundStep || step instanceof AddMarkStep));
|
|
56
55
|
let intentToStartEditTime = (meta === null || meta === void 0 ? void 0 : meta.intentToStartEditTime) || pluginState.intentToStartEditTime;
|
|
57
56
|
const now = performance.now();
|
|
58
|
-
if (!intentToStartEditTime) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
...pluginState
|
|
64
|
-
};
|
|
65
|
-
}
|
|
57
|
+
if (!intentToStartEditTime && !hasDocChanges && !tr.storedMarksSet) {
|
|
58
|
+
return pluginState;
|
|
59
|
+
}
|
|
60
|
+
if (!intentToStartEditTime && (hasDocChanges || tr.storedMarksSet)) {
|
|
61
|
+
intentToStartEditTime = now;
|
|
66
62
|
}
|
|
67
63
|
|
|
68
64
|
// Start active session timer if intentToStartEditTime is set and shouldStartTimer is true
|
|
@@ -79,36 +75,59 @@ export const createPlugin = api => {
|
|
|
79
75
|
...initialPluginState.actionTypeCount,
|
|
80
76
|
undoCount
|
|
81
77
|
};
|
|
82
|
-
if (
|
|
78
|
+
if (hasDocChanges) {
|
|
83
79
|
timer.startTimer();
|
|
84
80
|
const {
|
|
85
81
|
actionTypeCount,
|
|
86
82
|
timeOfLastTextInput,
|
|
87
83
|
totalActionCount,
|
|
88
|
-
|
|
84
|
+
previousTrType
|
|
89
85
|
} = pluginState;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
let
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
86
|
+
if (shouldSkipTr(tr)) {
|
|
87
|
+
return pluginState;
|
|
88
|
+
}
|
|
89
|
+
const trType = checkTrActionType(tr);
|
|
90
|
+
let shouldNotIncrementActionCount = false;
|
|
91
|
+
let shouldSetTimeOfLastTextInput = false;
|
|
92
|
+
let isTextInput = false;
|
|
93
|
+
if (trType) {
|
|
94
|
+
var _trType$extraData, _previousTrType$extra;
|
|
95
|
+
const isNotNewStatus = trType.type === ActionType.UPDATING_STATUS && (previousTrType === null || previousTrType === void 0 ? void 0 : previousTrType.type) === ActionType.UPDATING_STATUS && (trType === null || trType === void 0 ? void 0 : (_trType$extraData = trType.extraData) === null || _trType$extraData === void 0 ? void 0 : _trType$extraData.statusId) === (previousTrType === null || previousTrType === void 0 ? void 0 : (_previousTrType$extra = previousTrType.extraData) === null || _previousTrType$extra === void 0 ? void 0 : _previousTrType$extra.statusId);
|
|
96
|
+
const isAddingTextToListNode = trType.type === ActionType.TEXT_INPUT && !!previousTrType && [ActionType.UPDATING_NEW_LIST_TYPE_ITEM, ActionType.INSERTING_NEW_LIST_TYPE_NODE].includes(previousTrType.type);
|
|
97
|
+
const isAddingNewListItemAfterTextInput = !!previousTrType && previousTrType.type === ActionType.TEXT_INPUT && [ActionType.UPDATING_NEW_LIST_TYPE_ITEM].includes(trType.type);
|
|
98
|
+
|
|
99
|
+
// Check if tr is textInput and only increment textInputCount if previous action was not textInput
|
|
100
|
+
isTextInput = [ActionType.TEXT_INPUT, ActionType.EMPTY_LINE_ADDED_OR_DELETED].includes(trType.type);
|
|
101
|
+
|
|
102
|
+
// timeOfLastTextInput should be set if tr includes continuous text input on the same node
|
|
103
|
+
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;
|
|
104
|
+
|
|
105
|
+
// Should not increase action count if tr is text input,
|
|
106
|
+
// empty line added or deleted, updating new list item or is updating same status node
|
|
107
|
+
|
|
108
|
+
shouldNotIncrementActionCount = isTextInput || isNotNewStatus || isAddingTextToListNode || isAddingNewListItemAfterTextInput;
|
|
109
|
+
}
|
|
110
|
+
let newTextInputCount = isTextInput ? actionTypeCount.textInputCount + 1 : actionTypeCount.textInputCount;
|
|
111
|
+
let newTotalActionCount = totalActionCount + 1;
|
|
112
|
+
if (timeOfLastTextInput && shouldNotIncrementActionCount) {
|
|
98
113
|
newTotalActionCount = totalActionCount;
|
|
99
114
|
}
|
|
115
|
+
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)) {
|
|
116
|
+
newTextInputCount = actionTypeCount.textInputCount;
|
|
117
|
+
}
|
|
100
118
|
const newPluginState = {
|
|
101
119
|
...pluginState,
|
|
102
|
-
activeSessionTime:
|
|
120
|
+
activeSessionTime: now - intentToStartEditTime,
|
|
103
121
|
totalActionCount: newTotalActionCount,
|
|
104
|
-
timeOfLastTextInput:
|
|
122
|
+
timeOfLastTextInput: shouldSetTimeOfLastTextInput ? now : undefined,
|
|
105
123
|
contentSizeChanged: pluginState.contentSizeChanged + (newState.doc.content.size - oldState.doc.content.size),
|
|
106
124
|
actionTypeCount: {
|
|
107
125
|
...newActionTypeCount,
|
|
108
126
|
textInputCount: newTextInputCount
|
|
109
127
|
},
|
|
110
128
|
intentToStartEditTime,
|
|
111
|
-
shouldPersistActiveSession
|
|
129
|
+
shouldPersistActiveSession,
|
|
130
|
+
previousTrType: trType
|
|
112
131
|
};
|
|
113
132
|
return newPluginState;
|
|
114
133
|
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { InsertTypeAheadStep, LinkMetaStep } from '@atlaskit/adf-schema/steps';
|
|
2
|
+
import { ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
|
|
3
|
+
export let ActionType = /*#__PURE__*/function (ActionType) {
|
|
4
|
+
ActionType["TEXT_INPUT"] = "textInput";
|
|
5
|
+
ActionType["EMPTY_LINE_ADDED_OR_DELETED"] = "emptyLineAddedOrDeleted";
|
|
6
|
+
ActionType["INSERTED_FROM_TYPE_AHEAD"] = "insertedFromTypeAhead";
|
|
7
|
+
ActionType["INSERTING_NEW_LIST_TYPE_NODE"] = "insertingNewListTypeNode";
|
|
8
|
+
ActionType["UPDATING_NEW_LIST_TYPE_ITEM"] = "updatingNewListItem";
|
|
9
|
+
ActionType["ADDING_LINK"] = "addingLink";
|
|
10
|
+
ActionType["UPDATING_STATUS"] = "updatingStatus";
|
|
11
|
+
return ActionType;
|
|
12
|
+
}({});
|
|
13
|
+
const isTextInput = step => {
|
|
14
|
+
const {
|
|
15
|
+
slice: {
|
|
16
|
+
content
|
|
17
|
+
},
|
|
18
|
+
from,
|
|
19
|
+
to
|
|
20
|
+
} = step;
|
|
21
|
+
const node = content.firstChild;
|
|
22
|
+
const isAddingCharacter = from === to && content.childCount === 1 && !!node && !!node.text && node.text.length === 1;
|
|
23
|
+
const isDeletingCharacter = to - from === 1 && content.childCount === 0;
|
|
24
|
+
return isAddingCharacter || isDeletingCharacter;
|
|
25
|
+
};
|
|
26
|
+
const isEmptyLineAddedOrDeleted = step => {
|
|
27
|
+
const {
|
|
28
|
+
slice: {
|
|
29
|
+
content
|
|
30
|
+
},
|
|
31
|
+
from,
|
|
32
|
+
to
|
|
33
|
+
} = step;
|
|
34
|
+
const isEmptyLineDeleted = to - from === 2 && content.size === 0;
|
|
35
|
+
if (isEmptyLineDeleted) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
let isEmptyLineAdded = false;
|
|
39
|
+
content.forEach(node => {
|
|
40
|
+
isEmptyLineAdded = node.type.name === 'paragraph' && node.content.size === 0;
|
|
41
|
+
});
|
|
42
|
+
return isEmptyLineAdded;
|
|
43
|
+
};
|
|
44
|
+
const isUpdatingListTypeNode = step => {
|
|
45
|
+
const {
|
|
46
|
+
slice
|
|
47
|
+
} = step;
|
|
48
|
+
const childCount = slice.content.childCount;
|
|
49
|
+
if (childCount < 1) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
let isListTypeNode = false;
|
|
53
|
+
slice.content.forEach(node => {
|
|
54
|
+
isListTypeNode = ['decisionList', 'decisionItem', 'bulletList', 'listItem', 'orderedList', 'taskList', 'taskItem'].includes(node.type.name);
|
|
55
|
+
});
|
|
56
|
+
if (!isListTypeNode) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
return childCount === 1 ? ActionType.INSERTING_NEW_LIST_TYPE_NODE : ActionType.UPDATING_NEW_LIST_TYPE_ITEM;
|
|
60
|
+
};
|
|
61
|
+
const isUpdatingStatus = step => {
|
|
62
|
+
const {
|
|
63
|
+
slice
|
|
64
|
+
} = step;
|
|
65
|
+
const firstChild = slice.content.firstChild;
|
|
66
|
+
if (!firstChild) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
return firstChild.type.name === 'status' && firstChild.attrs.localId;
|
|
70
|
+
};
|
|
71
|
+
const isAddingLink = tr => {
|
|
72
|
+
const hasLinkStep = tr.steps.some(step => step instanceof LinkMetaStep);
|
|
73
|
+
const hasReplaceStep = tr.steps.some(step => step instanceof ReplaceStep);
|
|
74
|
+
return hasLinkStep && !hasReplaceStep;
|
|
75
|
+
};
|
|
76
|
+
const isTypeAheadRelatedTr = tr => {
|
|
77
|
+
var _tr$getMeta;
|
|
78
|
+
if (((_tr$getMeta = tr.getMeta('typeAheadPlugin$')) === null || _tr$getMeta === void 0 ? void 0 : _tr$getMeta.action) === 'INSERT_RAW_QUERY') {
|
|
79
|
+
return 'INSERT_RAW_QUERY';
|
|
80
|
+
}
|
|
81
|
+
if (!tr.getMeta('appendedTransaction')) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
const insertTypeAheadStep = tr.steps.find(step => step instanceof InsertTypeAheadStep);
|
|
85
|
+
const replaceStep = tr.steps.find(step => step instanceof ReplaceStep);
|
|
86
|
+
if (!insertTypeAheadStep || !replaceStep) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
return insertTypeAheadStep instanceof InsertTypeAheadStep && insertTypeAheadStep.stage;
|
|
90
|
+
};
|
|
91
|
+
export const shouldSkipTr = tr => {
|
|
92
|
+
const resolvingLink = isAddingLink(tr);
|
|
93
|
+
if (resolvingLink) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
const typeAheadRelatedTr = isTypeAheadRelatedTr(tr);
|
|
97
|
+
if (typeAheadRelatedTr) {
|
|
98
|
+
return typeAheadRelatedTr !== 'INSERTING_ITEM';
|
|
99
|
+
} else {
|
|
100
|
+
return tr.getMeta('appendedTransaction');
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
export const checkTrActionType = tr => {
|
|
104
|
+
if (tr.getMeta('input_rule_plugin_transaction')) {
|
|
105
|
+
return {
|
|
106
|
+
type: ActionType.INSERTING_NEW_LIST_TYPE_NODE
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
const stepsLength = tr.steps.length;
|
|
110
|
+
if (stepsLength <= 0) {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
if (isAddingLink(tr)) {
|
|
114
|
+
return {
|
|
115
|
+
type: ActionType.ADDING_LINK
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
const [firstStep] = tr.steps;
|
|
119
|
+
const isReplaceStep = firstStep instanceof ReplaceStep;
|
|
120
|
+
const isReplaceAroundStep = firstStep instanceof ReplaceAroundStep;
|
|
121
|
+
if (!isReplaceStep && !isReplaceAroundStep) {
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
if (isReplaceStep) {
|
|
125
|
+
if (isTextInput(firstStep)) {
|
|
126
|
+
return {
|
|
127
|
+
type: ActionType.TEXT_INPUT
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
if (isEmptyLineAddedOrDeleted(firstStep)) {
|
|
131
|
+
return {
|
|
132
|
+
type: ActionType.EMPTY_LINE_ADDED_OR_DELETED
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
const statusId = isUpdatingStatus(firstStep);
|
|
136
|
+
if (statusId) {
|
|
137
|
+
return {
|
|
138
|
+
type: ActionType.UPDATING_STATUS,
|
|
139
|
+
extraData: {
|
|
140
|
+
statusId
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const updatingListTypeNode = isUpdatingListTypeNode(firstStep);
|
|
146
|
+
if (updatingListTypeNode) {
|
|
147
|
+
return {
|
|
148
|
+
type: updatingListTypeNode
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return undefined;
|
|
152
|
+
};
|
|
@@ -72,14 +72,13 @@ export var metricsPlugin = function metricsPlugin(_ref) {
|
|
|
72
72
|
});
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
|
-
|
|
76
|
-
newTr.setMeta(metricsKey, {
|
|
75
|
+
tr.setMeta(metricsKey, {
|
|
77
76
|
intentToStartEditTime: performance.now(),
|
|
78
77
|
shouldStartTimer: shouldStartTimer,
|
|
79
78
|
newSelection: newSelection,
|
|
80
79
|
shouldPersistActiveSession: shouldPersistActiveSession
|
|
81
80
|
});
|
|
82
|
-
return
|
|
81
|
+
return tr;
|
|
83
82
|
};
|
|
84
83
|
}
|
|
85
84
|
},
|
|
@@ -2,12 +2,12 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
|
2
2
|
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; }
|
|
3
3
|
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; }
|
|
4
4
|
import { bind } from 'bind-event-listener';
|
|
5
|
-
import { AnalyticsStep } from '@atlaskit/adf-schema/steps';
|
|
6
5
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
7
|
-
import { isTextInput } from '@atlaskit/editor-common/utils';
|
|
8
6
|
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
7
|
+
import { AddMarkStep, ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
|
|
9
8
|
import { ActiveSessionTimer } from './utils/active-session-timer';
|
|
10
9
|
import { getAnalyticsPayload } from './utils/analytics';
|
|
10
|
+
import { ActionType, checkTrActionType, shouldSkipTr } from './utils/check-tr-action-type';
|
|
11
11
|
import { isNonTextUndo } from './utils/is-non-text-undo';
|
|
12
12
|
export var metricsKey = new PluginKey('metricsPlugin');
|
|
13
13
|
export var initialPluginState = {
|
|
@@ -39,7 +39,7 @@ export var createPlugin = function createPlugin(api) {
|
|
|
39
39
|
},
|
|
40
40
|
// eslint-disable-next-line @typescript-eslint/max-params
|
|
41
41
|
apply: function apply(tr, pluginState, oldState, newState) {
|
|
42
|
-
var _meta$shouldPersistAc;
|
|
42
|
+
var _meta$shouldPersistAc, _tr$steps;
|
|
43
43
|
if (tr.getMeta('isRemote') || tr.getMeta('replaceDocument')) {
|
|
44
44
|
return pluginState;
|
|
45
45
|
}
|
|
@@ -52,20 +52,16 @@ export var createPlugin = function createPlugin(api) {
|
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
54
|
var shouldPersistActiveSession = (_meta$shouldPersistAc = meta === null || meta === void 0 ? void 0 : meta.shouldPersistActiveSession) !== null && _meta$shouldPersistAc !== void 0 ? _meta$shouldPersistAc : pluginState.shouldPersistActiveSession;
|
|
55
|
-
var
|
|
56
|
-
return
|
|
57
|
-
|
|
58
|
-
});
|
|
59
|
-
};
|
|
60
|
-
var docChangedWithoutAnalytics = tr.docChanged && canIgnoreTr();
|
|
55
|
+
var hasDocChanges = tr.steps.length > 0 && ((_tr$steps = tr.steps) === null || _tr$steps === void 0 ? void 0 : _tr$steps.some(function (step) {
|
|
56
|
+
return step instanceof ReplaceStep || step instanceof ReplaceAroundStep || step instanceof AddMarkStep;
|
|
57
|
+
}));
|
|
61
58
|
var intentToStartEditTime = (meta === null || meta === void 0 ? void 0 : meta.intentToStartEditTime) || pluginState.intentToStartEditTime;
|
|
62
59
|
var now = performance.now();
|
|
63
|
-
if (!intentToStartEditTime) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
60
|
+
if (!intentToStartEditTime && !hasDocChanges && !tr.storedMarksSet) {
|
|
61
|
+
return pluginState;
|
|
62
|
+
}
|
|
63
|
+
if (!intentToStartEditTime && (hasDocChanges || tr.storedMarksSet)) {
|
|
64
|
+
intentToStartEditTime = now;
|
|
69
65
|
}
|
|
70
66
|
|
|
71
67
|
// Start active session timer if intentToStartEditTime is set and shouldStartTimer is true
|
|
@@ -80,32 +76,55 @@ export var createPlugin = function createPlugin(api) {
|
|
|
80
76
|
}) : _objectSpread(_objectSpread({}, initialPluginState.actionTypeCount), {}, {
|
|
81
77
|
undoCount: undoCount
|
|
82
78
|
});
|
|
83
|
-
if (
|
|
79
|
+
if (hasDocChanges) {
|
|
84
80
|
timer.startTimer();
|
|
85
81
|
var actionTypeCount = pluginState.actionTypeCount,
|
|
86
82
|
timeOfLastTextInput = pluginState.timeOfLastTextInput,
|
|
87
83
|
totalActionCount = pluginState.totalActionCount,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
var
|
|
93
|
-
var
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
84
|
+
previousTrType = pluginState.previousTrType;
|
|
85
|
+
if (shouldSkipTr(tr)) {
|
|
86
|
+
return pluginState;
|
|
87
|
+
}
|
|
88
|
+
var trType = checkTrActionType(tr);
|
|
89
|
+
var shouldNotIncrementActionCount = false;
|
|
90
|
+
var shouldSetTimeOfLastTextInput = false;
|
|
91
|
+
var isTextInput = false;
|
|
92
|
+
if (trType) {
|
|
93
|
+
var _trType$extraData, _previousTrType$extra;
|
|
94
|
+
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);
|
|
95
|
+
var isAddingTextToListNode = trType.type === ActionType.TEXT_INPUT && !!previousTrType && [ActionType.UPDATING_NEW_LIST_TYPE_ITEM, ActionType.INSERTING_NEW_LIST_TYPE_NODE].includes(previousTrType.type);
|
|
96
|
+
var isAddingNewListItemAfterTextInput = !!previousTrType && previousTrType.type === ActionType.TEXT_INPUT && [ActionType.UPDATING_NEW_LIST_TYPE_ITEM].includes(trType.type);
|
|
97
|
+
|
|
98
|
+
// Check if tr is textInput and only increment textInputCount if previous action was not textInput
|
|
99
|
+
isTextInput = [ActionType.TEXT_INPUT, ActionType.EMPTY_LINE_ADDED_OR_DELETED].includes(trType.type);
|
|
100
|
+
|
|
101
|
+
// timeOfLastTextInput should be set if tr includes continuous text input on the same node
|
|
102
|
+
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;
|
|
103
|
+
|
|
104
|
+
// Should not increase action count if tr is text input,
|
|
105
|
+
// empty line added or deleted, updating new list item or is updating same status node
|
|
106
|
+
|
|
107
|
+
shouldNotIncrementActionCount = isTextInput || isNotNewStatus || isAddingTextToListNode || isAddingNewListItemAfterTextInput;
|
|
108
|
+
}
|
|
109
|
+
var newTextInputCount = isTextInput ? actionTypeCount.textInputCount + 1 : actionTypeCount.textInputCount;
|
|
110
|
+
var newTotalActionCount = totalActionCount + 1;
|
|
111
|
+
if (timeOfLastTextInput && shouldNotIncrementActionCount) {
|
|
97
112
|
newTotalActionCount = totalActionCount;
|
|
98
113
|
}
|
|
114
|
+
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)) {
|
|
115
|
+
newTextInputCount = actionTypeCount.textInputCount;
|
|
116
|
+
}
|
|
99
117
|
var newPluginState = _objectSpread(_objectSpread({}, pluginState), {}, {
|
|
100
|
-
activeSessionTime:
|
|
118
|
+
activeSessionTime: now - intentToStartEditTime,
|
|
101
119
|
totalActionCount: newTotalActionCount,
|
|
102
|
-
timeOfLastTextInput:
|
|
120
|
+
timeOfLastTextInput: shouldSetTimeOfLastTextInput ? now : undefined,
|
|
103
121
|
contentSizeChanged: pluginState.contentSizeChanged + (newState.doc.content.size - oldState.doc.content.size),
|
|
104
122
|
actionTypeCount: _objectSpread(_objectSpread({}, newActionTypeCount), {}, {
|
|
105
123
|
textInputCount: newTextInputCount
|
|
106
124
|
}),
|
|
107
125
|
intentToStartEditTime: intentToStartEditTime,
|
|
108
|
-
shouldPersistActiveSession: shouldPersistActiveSession
|
|
126
|
+
shouldPersistActiveSession: shouldPersistActiveSession,
|
|
127
|
+
previousTrType: trType
|
|
109
128
|
});
|
|
110
129
|
return newPluginState;
|
|
111
130
|
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
|
+
import { InsertTypeAheadStep, LinkMetaStep } from '@atlaskit/adf-schema/steps';
|
|
3
|
+
import { ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
|
|
4
|
+
export var ActionType = /*#__PURE__*/function (ActionType) {
|
|
5
|
+
ActionType["TEXT_INPUT"] = "textInput";
|
|
6
|
+
ActionType["EMPTY_LINE_ADDED_OR_DELETED"] = "emptyLineAddedOrDeleted";
|
|
7
|
+
ActionType["INSERTED_FROM_TYPE_AHEAD"] = "insertedFromTypeAhead";
|
|
8
|
+
ActionType["INSERTING_NEW_LIST_TYPE_NODE"] = "insertingNewListTypeNode";
|
|
9
|
+
ActionType["UPDATING_NEW_LIST_TYPE_ITEM"] = "updatingNewListItem";
|
|
10
|
+
ActionType["ADDING_LINK"] = "addingLink";
|
|
11
|
+
ActionType["UPDATING_STATUS"] = "updatingStatus";
|
|
12
|
+
return ActionType;
|
|
13
|
+
}({});
|
|
14
|
+
var isTextInput = function isTextInput(step) {
|
|
15
|
+
var _ref = step,
|
|
16
|
+
content = _ref.slice.content,
|
|
17
|
+
from = _ref.from,
|
|
18
|
+
to = _ref.to;
|
|
19
|
+
var node = content.firstChild;
|
|
20
|
+
var isAddingCharacter = from === to && content.childCount === 1 && !!node && !!node.text && node.text.length === 1;
|
|
21
|
+
var isDeletingCharacter = to - from === 1 && content.childCount === 0;
|
|
22
|
+
return isAddingCharacter || isDeletingCharacter;
|
|
23
|
+
};
|
|
24
|
+
var isEmptyLineAddedOrDeleted = function isEmptyLineAddedOrDeleted(step) {
|
|
25
|
+
var _ref2 = step,
|
|
26
|
+
content = _ref2.slice.content,
|
|
27
|
+
from = _ref2.from,
|
|
28
|
+
to = _ref2.to;
|
|
29
|
+
var isEmptyLineDeleted = to - from === 2 && content.size === 0;
|
|
30
|
+
if (isEmptyLineDeleted) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
var isEmptyLineAdded = false;
|
|
34
|
+
content.forEach(function (node) {
|
|
35
|
+
isEmptyLineAdded = node.type.name === 'paragraph' && node.content.size === 0;
|
|
36
|
+
});
|
|
37
|
+
return isEmptyLineAdded;
|
|
38
|
+
};
|
|
39
|
+
var isUpdatingListTypeNode = function isUpdatingListTypeNode(step) {
|
|
40
|
+
var slice = step.slice;
|
|
41
|
+
var childCount = slice.content.childCount;
|
|
42
|
+
if (childCount < 1) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
var isListTypeNode = false;
|
|
46
|
+
slice.content.forEach(function (node) {
|
|
47
|
+
isListTypeNode = ['decisionList', 'decisionItem', 'bulletList', 'listItem', 'orderedList', 'taskList', 'taskItem'].includes(node.type.name);
|
|
48
|
+
});
|
|
49
|
+
if (!isListTypeNode) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
return childCount === 1 ? ActionType.INSERTING_NEW_LIST_TYPE_NODE : ActionType.UPDATING_NEW_LIST_TYPE_ITEM;
|
|
53
|
+
};
|
|
54
|
+
var isUpdatingStatus = function isUpdatingStatus(step) {
|
|
55
|
+
var slice = step.slice;
|
|
56
|
+
var firstChild = slice.content.firstChild;
|
|
57
|
+
if (!firstChild) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
return firstChild.type.name === 'status' && firstChild.attrs.localId;
|
|
61
|
+
};
|
|
62
|
+
var isAddingLink = function isAddingLink(tr) {
|
|
63
|
+
var hasLinkStep = tr.steps.some(function (step) {
|
|
64
|
+
return step instanceof LinkMetaStep;
|
|
65
|
+
});
|
|
66
|
+
var hasReplaceStep = tr.steps.some(function (step) {
|
|
67
|
+
return step instanceof ReplaceStep;
|
|
68
|
+
});
|
|
69
|
+
return hasLinkStep && !hasReplaceStep;
|
|
70
|
+
};
|
|
71
|
+
var isTypeAheadRelatedTr = function isTypeAheadRelatedTr(tr) {
|
|
72
|
+
var _tr$getMeta;
|
|
73
|
+
if (((_tr$getMeta = tr.getMeta('typeAheadPlugin$')) === null || _tr$getMeta === void 0 ? void 0 : _tr$getMeta.action) === 'INSERT_RAW_QUERY') {
|
|
74
|
+
return 'INSERT_RAW_QUERY';
|
|
75
|
+
}
|
|
76
|
+
if (!tr.getMeta('appendedTransaction')) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
var insertTypeAheadStep = tr.steps.find(function (step) {
|
|
80
|
+
return step instanceof InsertTypeAheadStep;
|
|
81
|
+
});
|
|
82
|
+
var replaceStep = tr.steps.find(function (step) {
|
|
83
|
+
return step instanceof ReplaceStep;
|
|
84
|
+
});
|
|
85
|
+
if (!insertTypeAheadStep || !replaceStep) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
return insertTypeAheadStep instanceof InsertTypeAheadStep && insertTypeAheadStep.stage;
|
|
89
|
+
};
|
|
90
|
+
export var shouldSkipTr = function shouldSkipTr(tr) {
|
|
91
|
+
var resolvingLink = isAddingLink(tr);
|
|
92
|
+
if (resolvingLink) {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
var typeAheadRelatedTr = isTypeAheadRelatedTr(tr);
|
|
96
|
+
if (typeAheadRelatedTr) {
|
|
97
|
+
return typeAheadRelatedTr !== 'INSERTING_ITEM';
|
|
98
|
+
} else {
|
|
99
|
+
return tr.getMeta('appendedTransaction');
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
export var checkTrActionType = function checkTrActionType(tr) {
|
|
103
|
+
if (tr.getMeta('input_rule_plugin_transaction')) {
|
|
104
|
+
return {
|
|
105
|
+
type: ActionType.INSERTING_NEW_LIST_TYPE_NODE
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
var stepsLength = tr.steps.length;
|
|
109
|
+
if (stepsLength <= 0) {
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
if (isAddingLink(tr)) {
|
|
113
|
+
return {
|
|
114
|
+
type: ActionType.ADDING_LINK
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
var _tr$steps = _slicedToArray(tr.steps, 1),
|
|
118
|
+
firstStep = _tr$steps[0];
|
|
119
|
+
var isReplaceStep = firstStep instanceof ReplaceStep;
|
|
120
|
+
var isReplaceAroundStep = firstStep instanceof ReplaceAroundStep;
|
|
121
|
+
if (!isReplaceStep && !isReplaceAroundStep) {
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
if (isReplaceStep) {
|
|
125
|
+
if (isTextInput(firstStep)) {
|
|
126
|
+
return {
|
|
127
|
+
type: ActionType.TEXT_INPUT
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
if (isEmptyLineAddedOrDeleted(firstStep)) {
|
|
131
|
+
return {
|
|
132
|
+
type: ActionType.EMPTY_LINE_ADDED_OR_DELETED
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
var statusId = isUpdatingStatus(firstStep);
|
|
136
|
+
if (statusId) {
|
|
137
|
+
return {
|
|
138
|
+
type: ActionType.UPDATING_STATUS,
|
|
139
|
+
extraData: {
|
|
140
|
+
statusId: statusId
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
var updatingListTypeNode = isUpdatingListTypeNode(firstStep);
|
|
146
|
+
if (updatingListTypeNode) {
|
|
147
|
+
return {
|
|
148
|
+
type: updatingListTypeNode
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return undefined;
|
|
152
|
+
};
|
|
@@ -3,6 +3,7 @@ import { type ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
|
3
3
|
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
4
4
|
import { PluginKey, Selection } from '@atlaskit/editor-prosemirror/state';
|
|
5
5
|
import { type MetricsPlugin } from '../metricsPluginType';
|
|
6
|
+
import { type TrActionType } from './utils/check-tr-action-type';
|
|
6
7
|
export declare const metricsKey: PluginKey<any>;
|
|
7
8
|
export type MetricsState = {
|
|
8
9
|
intentToStartEditTime?: number;
|
|
@@ -14,6 +15,7 @@ export type MetricsState = {
|
|
|
14
15
|
timeOfLastTextInput?: number;
|
|
15
16
|
shouldPersistActiveSession?: boolean;
|
|
16
17
|
initialContent?: Fragment;
|
|
18
|
+
previousTrType?: TrActionType;
|
|
17
19
|
};
|
|
18
20
|
export type ActionByType = {
|
|
19
21
|
textInputCount: number;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ReadonlyTransaction } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
+
export declare enum ActionType {
|
|
3
|
+
TEXT_INPUT = "textInput",
|
|
4
|
+
EMPTY_LINE_ADDED_OR_DELETED = "emptyLineAddedOrDeleted",
|
|
5
|
+
INSERTED_FROM_TYPE_AHEAD = "insertedFromTypeAhead",
|
|
6
|
+
INSERTING_NEW_LIST_TYPE_NODE = "insertingNewListTypeNode",
|
|
7
|
+
UPDATING_NEW_LIST_TYPE_ITEM = "updatingNewListItem",
|
|
8
|
+
ADDING_LINK = "addingLink",
|
|
9
|
+
UPDATING_STATUS = "updatingStatus"
|
|
10
|
+
}
|
|
11
|
+
export declare const shouldSkipTr: (tr: ReadonlyTransaction) => boolean;
|
|
12
|
+
export type TrActionType = {
|
|
13
|
+
type: ActionType;
|
|
14
|
+
extraData?: {
|
|
15
|
+
statusId?: string;
|
|
16
|
+
};
|
|
17
|
+
} | undefined;
|
|
18
|
+
export declare const checkTrActionType: (tr: ReadonlyTransaction) => TrActionType;
|
|
@@ -3,6 +3,7 @@ import { type ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
|
3
3
|
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
4
4
|
import { PluginKey, Selection } from '@atlaskit/editor-prosemirror/state';
|
|
5
5
|
import { type MetricsPlugin } from '../metricsPluginType';
|
|
6
|
+
import { type TrActionType } from './utils/check-tr-action-type';
|
|
6
7
|
export declare const metricsKey: PluginKey<any>;
|
|
7
8
|
export type MetricsState = {
|
|
8
9
|
intentToStartEditTime?: number;
|
|
@@ -14,6 +15,7 @@ export type MetricsState = {
|
|
|
14
15
|
timeOfLastTextInput?: number;
|
|
15
16
|
shouldPersistActiveSession?: boolean;
|
|
16
17
|
initialContent?: Fragment;
|
|
18
|
+
previousTrType?: TrActionType;
|
|
17
19
|
};
|
|
18
20
|
export type ActionByType = {
|
|
19
21
|
textInputCount: number;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ReadonlyTransaction } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
+
export declare enum ActionType {
|
|
3
|
+
TEXT_INPUT = "textInput",
|
|
4
|
+
EMPTY_LINE_ADDED_OR_DELETED = "emptyLineAddedOrDeleted",
|
|
5
|
+
INSERTED_FROM_TYPE_AHEAD = "insertedFromTypeAhead",
|
|
6
|
+
INSERTING_NEW_LIST_TYPE_NODE = "insertingNewListTypeNode",
|
|
7
|
+
UPDATING_NEW_LIST_TYPE_ITEM = "updatingNewListItem",
|
|
8
|
+
ADDING_LINK = "addingLink",
|
|
9
|
+
UPDATING_STATUS = "updatingStatus"
|
|
10
|
+
}
|
|
11
|
+
export declare const shouldSkipTr: (tr: ReadonlyTransaction) => boolean;
|
|
12
|
+
export type TrActionType = {
|
|
13
|
+
type: ActionType;
|
|
14
|
+
extraData?: {
|
|
15
|
+
statusId?: string;
|
|
16
|
+
};
|
|
17
|
+
} | undefined;
|
|
18
|
+
export declare const checkTrActionType: (tr: ReadonlyTransaction) => TrActionType;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-metrics",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.1",
|
|
4
4
|
"description": "Metrics plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@atlaskit/adf-schema": "^47.2.1",
|
|
28
|
-
"@atlaskit/editor-common": "^99.
|
|
28
|
+
"@atlaskit/editor-common": "^99.19.0",
|
|
29
29
|
"@atlaskit/editor-plugin-analytics": "^1.12.0",
|
|
30
30
|
"@atlaskit/editor-plugin-block-controls": "^2.27.0",
|
|
31
31
|
"@atlaskit/editor-prosemirror": "7.0.0",
|