@atlaskit/jql-editor 6.4.7 → 6.5.0
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 +11 -0
- package/dist/cjs/analytics/util.js +1 -1
- package/dist/cjs/plugins/rich-inline-nodes/nodes/index.js +2 -0
- package/dist/cjs/plugins/rich-inline-nodes/nodes/lozenge-with-avatar/index.js +41 -0
- package/dist/cjs/plugins/rich-inline-nodes/nodes/lozenge-with-avatar/styled.js +105 -0
- package/dist/cjs/plugins/rich-inline-nodes/util/replace-nodes-transaction.js +86 -33
- package/dist/cjs/state/hydration/util.js +6 -6
- package/dist/cjs/state/index.js +40 -31
- package/dist/es2019/analytics/util.js +1 -1
- package/dist/es2019/plugins/rich-inline-nodes/nodes/index.js +2 -0
- package/dist/es2019/plugins/rich-inline-nodes/nodes/lozenge-with-avatar/index.js +32 -0
- package/dist/es2019/plugins/rich-inline-nodes/nodes/lozenge-with-avatar/styled.js +97 -0
- package/dist/es2019/plugins/rich-inline-nodes/util/replace-nodes-transaction.js +63 -15
- package/dist/es2019/state/hydration/util.js +6 -6
- package/dist/es2019/state/index.js +12 -2
- package/dist/esm/analytics/util.js +1 -1
- package/dist/esm/plugins/rich-inline-nodes/nodes/index.js +2 -0
- package/dist/esm/plugins/rich-inline-nodes/nodes/lozenge-with-avatar/index.js +34 -0
- package/dist/esm/plugins/rich-inline-nodes/nodes/lozenge-with-avatar/styled.js +96 -0
- package/dist/esm/plugins/rich-inline-nodes/util/replace-nodes-transaction.js +86 -33
- package/dist/esm/state/hydration/util.js +6 -6
- package/dist/esm/state/index.js +39 -30
- package/dist/types/plugins/rich-inline-nodes/nodes/index.d.ts +2 -0
- package/dist/types/plugins/rich-inline-nodes/nodes/lozenge-with-avatar/index.d.ts +7 -0
- package/dist/types/plugins/rich-inline-nodes/nodes/lozenge-with-avatar/styled.d.ts +18 -0
- package/dist/types/state/index.d.ts +5 -1
- package/dist/types/types.d.ts +1 -1
- package/dist/types/ui/jql-editor/types.d.ts +7 -1
- package/dist/types/ui/types.d.ts +1 -1
- package/dist/types-ts4.5/plugins/rich-inline-nodes/nodes/index.d.ts +2 -0
- package/dist/types-ts4.5/plugins/rich-inline-nodes/nodes/lozenge-with-avatar/index.d.ts +7 -0
- package/dist/types-ts4.5/plugins/rich-inline-nodes/nodes/lozenge-with-avatar/styled.d.ts +18 -0
- package/dist/types-ts4.5/state/index.d.ts +5 -1
- package/dist/types-ts4.5/types.d.ts +1 -1
- package/dist/types-ts4.5/ui/jql-editor/types.d.ts +7 -1
- package/dist/types-ts4.5/ui/types.d.ts +1 -1
- package/package.json +10 -7
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
2
|
+
|
|
3
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
4
|
+
import { css } from '@emotion/react';
|
|
5
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
6
|
+
import styled from '@emotion/styled';
|
|
7
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles -- Ignored via go/DSP-18766
|
|
8
|
+
export const LozengeWithAvatarContainer =
|
|
9
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-styled -- Ignored via go/DSP-18766
|
|
10
|
+
styled.span({
|
|
11
|
+
display: 'inline-flex',
|
|
12
|
+
alignItems: 'baseline',
|
|
13
|
+
paddingLeft: `${"var(--ds-space-025, 2px)"}`,
|
|
14
|
+
borderRadius: "var(--ds-radius-xlarge, 12px)",
|
|
15
|
+
cursor: 'pointer',
|
|
16
|
+
userSelect: 'none'
|
|
17
|
+
},
|
|
18
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-dynamic-styles -- Ignored via go/DSP-18766
|
|
19
|
+
({
|
|
20
|
+
selected,
|
|
21
|
+
error
|
|
22
|
+
}) => {
|
|
23
|
+
if (selected) {
|
|
24
|
+
if (error) {
|
|
25
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
|
|
26
|
+
return css({
|
|
27
|
+
color: "var(--ds-text-inverse, #FFFFFF)",
|
|
28
|
+
backgroundColor: "var(--ds-background-danger-bold, #C9372C)",
|
|
29
|
+
textDecoration: 'wavy underline',
|
|
30
|
+
textDecorationThickness: '1px',
|
|
31
|
+
textDecorationSkipInk: 'none',
|
|
32
|
+
textDecorationColor: "var(--ds-text-inverse, #FFFFFF)"
|
|
33
|
+
});
|
|
34
|
+
} else {
|
|
35
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
|
|
36
|
+
return css({
|
|
37
|
+
color: "var(--ds-text, #292A2E)",
|
|
38
|
+
backgroundColor: "var(--ds-background-selected, #E9F2FE)",
|
|
39
|
+
boxShadow: `0 0 0 1px ${"var(--ds-border-selected, #1868DB)"}`
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
if (error) {
|
|
44
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
|
|
45
|
+
return css({
|
|
46
|
+
color: "var(--ds-text-subtle, #505258)",
|
|
47
|
+
backgroundColor: "var(--ds-background-neutral, #0515240F)",
|
|
48
|
+
textDecoration: 'wavy underline',
|
|
49
|
+
textDecorationThickness: '1px',
|
|
50
|
+
textDecorationSkipInk: 'none',
|
|
51
|
+
textDecorationColor: "var(--ds-text-danger, #AE2E24)",
|
|
52
|
+
'&:hover': {
|
|
53
|
+
backgroundColor: "var(--ds-background-neutral-hovered, #0B120E24)"
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
} else {
|
|
57
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
|
|
58
|
+
return css({
|
|
59
|
+
color: "var(--ds-text-subtle, #505258)",
|
|
60
|
+
backgroundColor: "var(--ds-background-neutral, #0515240F)",
|
|
61
|
+
'&:hover': {
|
|
62
|
+
backgroundColor: "var(--ds-background-neutral-hovered, #0B120E24)"
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles -- Ignored via go/DSP-18766
|
|
70
|
+
export const NameContainer =
|
|
71
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-styled -- Ignored via go/DSP-18766
|
|
72
|
+
styled.span({
|
|
73
|
+
marginLeft: "var(--ds-space-075, 6px)",
|
|
74
|
+
marginRight: "var(--ds-space-100, 8px)",
|
|
75
|
+
// eslint-disable-next-line -- Ignored via go/DSP-18766
|
|
76
|
+
lineHeight: "var(--ds-space-250, 20px)"
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
/* Override Avatar styles to match design spec */
|
|
80
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles -- Ignored via go/DSP-18766
|
|
81
|
+
export const AvatarWrapper =
|
|
82
|
+
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage, @atlaskit/ui-styling-standard/no-styled -- Ignored via go/DSP-18766
|
|
83
|
+
styled.div({
|
|
84
|
+
height: "var(--ds-space-200, 16px)",
|
|
85
|
+
width: "var(--ds-space-200, 16px)",
|
|
86
|
+
alignSelf: 'center',
|
|
87
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors -- Ignored via go/DSP-18766
|
|
88
|
+
'> div span': {
|
|
89
|
+
margin: "var(--ds-space-0, 0px)"
|
|
90
|
+
},
|
|
91
|
+
// Fix fallback avatar icon vertical alignment.
|
|
92
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
|
|
93
|
+
'> div > span:has(> span)': {
|
|
94
|
+
position: 'relative',
|
|
95
|
+
top: '-2px'
|
|
96
|
+
}
|
|
97
|
+
});
|
|
@@ -13,30 +13,40 @@ export const replaceRichInlineNodes = (editorState, hydratedValues) => {
|
|
|
13
13
|
transaction.setMeta('addToHistory', false);
|
|
14
14
|
Object.entries(hydratedValues).forEach(([fieldName, values]) => {
|
|
15
15
|
values.forEach(value => {
|
|
16
|
-
if (
|
|
17
|
-
//
|
|
16
|
+
if (fg('jql-function-arg-hydration')) {
|
|
17
|
+
// Skip deprecated fields
|
|
18
|
+
if (value.type === 'deprecated-field') {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
// When the gate is on, collect both direct value operands and function argument
|
|
22
|
+
// operands for all node types
|
|
23
|
+
const astNodes = [...getValueNodes(ast, fieldName, value.id), ...getFunctionArgumentNodes(ast, fieldName, value.id)];
|
|
24
|
+
replaceAstNodesWithRichInlineNodes(transaction, astNodes, fieldName, value);
|
|
25
|
+
} else if (value.type === 'user' || value.type === 'team' || value.type === 'goal' && FeatureGates.getExperimentValue('anip-1095-goals-in-harmonised-filter', 'isEnabled', false) || value.type === 'project' && FeatureGates.getExperimentValue('atlassian_projects_-_native_integration', 'releaseVersion', -1) >= 1) {
|
|
26
|
+
// Legacy path: direct value operands only, with membersOf fallback for teams.
|
|
18
27
|
let astNodes = getValueNodes(ast, fieldName, value.id);
|
|
19
|
-
|
|
20
|
-
// If not found as direct value and it's a team, try to find in membersOf function arguments
|
|
21
28
|
if (astNodes.length === 0 && value.type === 'team' && fg('jira-membersof-team-support')) {
|
|
22
29
|
astNodes = getMembersOfArgumentNodes(ast, value.id);
|
|
23
30
|
}
|
|
24
|
-
|
|
25
|
-
if (astNode.position) {
|
|
26
|
-
const [from, to] = astNode.position;
|
|
27
|
-
const documentFrom = getDocumentPosition(transaction.doc, from);
|
|
28
|
-
if (!isRichInlineNode(transaction.doc, documentFrom)) {
|
|
29
|
-
const documentTo = getDocumentPosition(transaction.doc, to);
|
|
30
|
-
const node = getRichInlineNode(fieldName, value, astNode.text);
|
|
31
|
-
transaction.replaceWith(documentFrom, documentTo, node);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
});
|
|
31
|
+
replaceAstNodesWithRichInlineNodes(transaction, astNodes, fieldName, value);
|
|
35
32
|
}
|
|
36
33
|
});
|
|
37
34
|
});
|
|
38
35
|
return transaction;
|
|
39
36
|
};
|
|
37
|
+
const replaceAstNodesWithRichInlineNodes = (transaction, astNodes, fieldName, value) => {
|
|
38
|
+
astNodes.forEach(astNode => {
|
|
39
|
+
if (astNode.position) {
|
|
40
|
+
const [from, to] = astNode.position;
|
|
41
|
+
const documentFrom = getDocumentPosition(transaction.doc, from);
|
|
42
|
+
if (!isRichInlineNode(transaction.doc, documentFrom)) {
|
|
43
|
+
const documentTo = getDocumentPosition(transaction.doc, to);
|
|
44
|
+
const node = getRichInlineNode(fieldName, value, astNode.text);
|
|
45
|
+
transaction.replaceWith(documentFrom, documentTo, node);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
};
|
|
40
50
|
const getRichInlineNode = (fieldName, value, text) => {
|
|
41
51
|
switch (value.type) {
|
|
42
52
|
case 'user':
|
|
@@ -71,6 +81,14 @@ const getRichInlineNode = (fieldName, value, text) => {
|
|
|
71
81
|
fieldName
|
|
72
82
|
}, textContent);
|
|
73
83
|
}
|
|
84
|
+
case 'lozengeWithAvatar':
|
|
85
|
+
{
|
|
86
|
+
const textContent = JQLEditorSchema.text(text);
|
|
87
|
+
return JQLEditorSchema.nodes.lozengeWithAvatar.create({
|
|
88
|
+
...value,
|
|
89
|
+
fieldName
|
|
90
|
+
}, textContent);
|
|
91
|
+
}
|
|
74
92
|
default:
|
|
75
93
|
{
|
|
76
94
|
throw new Error(`Unsupported hydrated value type ${value.type}`);
|
|
@@ -93,6 +111,12 @@ const getMembersOfArgumentNodes = (ast, teamId) => {
|
|
|
93
111
|
}
|
|
94
112
|
return ast.query.accept(new FindMembersOfArgumentsVisitor(teamId));
|
|
95
113
|
};
|
|
114
|
+
const getFunctionArgumentNodes = (ast, fieldName, valueId) => {
|
|
115
|
+
if (!ast.query) {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
return ast.query.accept(new FindFunctionArgumentsVisitor(fieldName, valueId));
|
|
119
|
+
};
|
|
96
120
|
|
|
97
121
|
/**
|
|
98
122
|
* Base visitor class for traversing JQL AST to find specific nodes.
|
|
@@ -161,6 +185,30 @@ class FindValuesVisitor extends BaseAstNodeFinder {
|
|
|
161
185
|
}
|
|
162
186
|
}
|
|
163
187
|
|
|
188
|
+
/**
|
|
189
|
+
* Visitor that finds function arguments for a specific field matching a target value id.
|
|
190
|
+
* This visitor is field-aware: it processes clauses for the given field and matches arguments by their raw value.
|
|
191
|
+
*/
|
|
192
|
+
class FindFunctionArgumentsVisitor extends BaseAstNodeFinder {
|
|
193
|
+
constructor(fieldName, targetValueId) {
|
|
194
|
+
super();
|
|
195
|
+
_defineProperty(this, "visitTerminalClause", terminalClause => {
|
|
196
|
+
if (!this.equalsIgnoreCase(terminalClause.field.value, this.fieldName)) {
|
|
197
|
+
return [];
|
|
198
|
+
}
|
|
199
|
+
if (terminalClause.operand === undefined) {
|
|
200
|
+
return [];
|
|
201
|
+
}
|
|
202
|
+
return terminalClause.operand.accept(this);
|
|
203
|
+
});
|
|
204
|
+
_defineProperty(this, "visitFunctionOperand", functionOperand => {
|
|
205
|
+
return functionOperand.arguments.filter(arg => this.equalsIgnoreCase(arg.value.trim(), this.targetValueId));
|
|
206
|
+
});
|
|
207
|
+
this.fieldName = fieldName;
|
|
208
|
+
this.targetValueId = targetValueId.trim();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
164
212
|
/**
|
|
165
213
|
* Visitor that finds membersOf function arguments matching a specific team ID.
|
|
166
214
|
* Used for queries like "assignee in membersOf("id: <uuid>")".
|
|
@@ -59,14 +59,14 @@ export class ValidQueryVisitor extends AbstractJastVisitor {
|
|
|
59
59
|
return `(${listOperand.values.map(value => value.accept(this)).filter(value => !!value).join(', ')})`;
|
|
60
60
|
});
|
|
61
61
|
_defineProperty(this, "visitFunctionOperand", functionOperand => {
|
|
62
|
-
// Only include membersOf function as it has arguments that need hydration
|
|
63
|
-
// Other functions like currentUser() don't have hydratable arguments
|
|
64
62
|
const functionName = functionOperand.function.value.toLowerCase();
|
|
65
|
-
if (functionName !== 'membersof' || !fg('jira-membersof-team-support')) {
|
|
66
|
-
return '';
|
|
67
|
-
}
|
|
68
63
|
const args = functionOperand.arguments.map(arg => arg.text).join(', ');
|
|
69
|
-
|
|
64
|
+
|
|
65
|
+
// The generic gate supersedes the legacy membersOf-specific gate: when
|
|
66
|
+
// jql-function-arg-hydration is on, any function with arguments is included (covering
|
|
67
|
+
// membersOf and all others). Otherwise fall back to the legacy membersOf-only path.
|
|
68
|
+
const shouldIncludeFunction = fg('jql-function-arg-hydration') ? functionOperand.arguments.length > 0 : functionName === 'membersof' && fg('jira-membersof-team-support');
|
|
69
|
+
return shouldIncludeFunction ? `${functionOperand.function.text}(${args})` : '';
|
|
70
70
|
});
|
|
71
71
|
}
|
|
72
72
|
defaultResult() {
|
|
@@ -927,14 +927,24 @@ export const useHydratedGoal = createHook(Store, {
|
|
|
927
927
|
return goal && goal.type === 'goal' ? goal : undefined;
|
|
928
928
|
}
|
|
929
929
|
});
|
|
930
|
+
export const useHydratedLozengeWithAvatar = createHook(Store, {
|
|
931
|
+
selector: (state, {
|
|
932
|
+
id,
|
|
933
|
+
fieldName
|
|
934
|
+
}) => {
|
|
935
|
+
var _state$hydratedValues0;
|
|
936
|
+
const value = (_state$hydratedValues0 = state.hydratedValues[normaliseHydrationKey(fieldName)]) === null || _state$hydratedValues0 === void 0 ? void 0 : _state$hydratedValues0.get(normaliseJqlString(id));
|
|
937
|
+
return value && value.type === 'lozengeWithAvatar' ? value : undefined;
|
|
938
|
+
}
|
|
939
|
+
});
|
|
930
940
|
export const useHydratedDeprecations = createHook(Store, {
|
|
931
941
|
selector: state => {
|
|
932
942
|
const ast = getJastFromState(state.editorState);
|
|
933
943
|
const fieldsInQuery = getFieldNodes(ast);
|
|
934
944
|
const toReturn = [];
|
|
935
945
|
Object.entries(state.hydratedValues).forEach(([fieldName]) => {
|
|
936
|
-
var _state$
|
|
937
|
-
(_state$
|
|
946
|
+
var _state$hydratedValues1;
|
|
947
|
+
(_state$hydratedValues1 = state.hydratedValues[fieldName]) === null || _state$hydratedValues1 === void 0 ? void 0 : _state$hydratedValues1.forEach(value => {
|
|
938
948
|
if (value.type === 'deprecated-field') {
|
|
939
949
|
if (fieldsInQuery.has(value.id.toLowerCase())) {
|
|
940
950
|
toReturn.push(value);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { ANALYTICS_CHANNEL, useJqlPackageAnalytics } from '@atlaskit/jql-editor-common';
|
|
2
2
|
export var useJqlEditorAnalytics = function useJqlEditorAnalytics(analyticsSource) {
|
|
3
|
-
return useJqlPackageAnalytics(analyticsSource, "@atlaskit/jql-editor", "6.4.
|
|
3
|
+
return useJqlPackageAnalytics(analyticsSource, "@atlaskit/jql-editor", "6.4.7", ANALYTICS_CHANNEL);
|
|
4
4
|
};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { goal } from './goal';
|
|
2
|
+
import { lozengeWithAvatar } from './lozenge-with-avatar';
|
|
2
3
|
import { project } from './project';
|
|
3
4
|
import { team } from './team';
|
|
4
5
|
import { user } from './user';
|
|
5
6
|
export var richInlineNodes = {
|
|
7
|
+
lozengeWithAvatar: lozengeWithAvatar,
|
|
6
8
|
user: user,
|
|
7
9
|
team: team,
|
|
8
10
|
project: project,
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import Avatar from '@atlaskit/avatar';
|
|
4
|
+
import { useHydratedLozengeWithAvatar } from '../../../../state';
|
|
5
|
+
import { AvatarWrapper, LozengeWithAvatarContainer, NameContainer } from './styled';
|
|
6
|
+
var LozengeWithAvatar = function LozengeWithAvatar(_ref) {
|
|
7
|
+
var id = _ref.id,
|
|
8
|
+
name = _ref.name,
|
|
9
|
+
fieldName = _ref.fieldName,
|
|
10
|
+
selected = _ref.selected,
|
|
11
|
+
error = _ref.error;
|
|
12
|
+
var _useHydratedLozengeWi = useHydratedLozengeWithAvatar({
|
|
13
|
+
id: id,
|
|
14
|
+
fieldName: fieldName
|
|
15
|
+
}),
|
|
16
|
+
_useHydratedLozengeWi2 = _slicedToArray(_useHydratedLozengeWi, 1),
|
|
17
|
+
lozengeWithAvatar = _useHydratedLozengeWi2[0];
|
|
18
|
+
return /*#__PURE__*/React.createElement(LozengeWithAvatarContainer, {
|
|
19
|
+
selected: selected,
|
|
20
|
+
error: error
|
|
21
|
+
}, /*#__PURE__*/React.createElement(AvatarWrapper, null, /*#__PURE__*/React.createElement(Avatar, {
|
|
22
|
+
src: lozengeWithAvatar === null || lozengeWithAvatar === void 0 ? void 0 : lozengeWithAvatar.avatarUrl,
|
|
23
|
+
borderColor: "transparent",
|
|
24
|
+
size: "xsmall"
|
|
25
|
+
})), /*#__PURE__*/React.createElement(NameContainer, null, name));
|
|
26
|
+
};
|
|
27
|
+
export var lozengeWithAvatar = {
|
|
28
|
+
component: LozengeWithAvatar,
|
|
29
|
+
attrs: {
|
|
30
|
+
id: {},
|
|
31
|
+
name: {},
|
|
32
|
+
fieldName: {}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
2
|
+
|
|
3
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
4
|
+
import { css } from '@emotion/react';
|
|
5
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
6
|
+
import styled from '@emotion/styled';
|
|
7
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles -- Ignored via go/DSP-18766
|
|
8
|
+
export var LozengeWithAvatarContainer =
|
|
9
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-styled -- Ignored via go/DSP-18766
|
|
10
|
+
styled.span({
|
|
11
|
+
display: 'inline-flex',
|
|
12
|
+
alignItems: 'baseline',
|
|
13
|
+
paddingLeft: "var(--ds-space-025, 2px)",
|
|
14
|
+
borderRadius: "var(--ds-radius-xlarge, 12px)",
|
|
15
|
+
cursor: 'pointer',
|
|
16
|
+
userSelect: 'none'
|
|
17
|
+
},
|
|
18
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-dynamic-styles -- Ignored via go/DSP-18766
|
|
19
|
+
function (_ref) {
|
|
20
|
+
var selected = _ref.selected,
|
|
21
|
+
error = _ref.error;
|
|
22
|
+
if (selected) {
|
|
23
|
+
if (error) {
|
|
24
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
|
|
25
|
+
return css({
|
|
26
|
+
color: "var(--ds-text-inverse, #FFFFFF)",
|
|
27
|
+
backgroundColor: "var(--ds-background-danger-bold, #C9372C)",
|
|
28
|
+
textDecoration: 'wavy underline',
|
|
29
|
+
textDecorationThickness: '1px',
|
|
30
|
+
textDecorationSkipInk: 'none',
|
|
31
|
+
textDecorationColor: "var(--ds-text-inverse, #FFFFFF)"
|
|
32
|
+
});
|
|
33
|
+
} else {
|
|
34
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
|
|
35
|
+
return css({
|
|
36
|
+
color: "var(--ds-text, #292A2E)",
|
|
37
|
+
backgroundColor: "var(--ds-background-selected, #E9F2FE)",
|
|
38
|
+
boxShadow: "0 0 0 1px ".concat("var(--ds-border-selected, #1868DB)")
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
if (error) {
|
|
43
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
|
|
44
|
+
return css({
|
|
45
|
+
color: "var(--ds-text-subtle, #505258)",
|
|
46
|
+
backgroundColor: "var(--ds-background-neutral, #0515240F)",
|
|
47
|
+
textDecoration: 'wavy underline',
|
|
48
|
+
textDecorationThickness: '1px',
|
|
49
|
+
textDecorationSkipInk: 'none',
|
|
50
|
+
textDecorationColor: "var(--ds-text-danger, #AE2E24)",
|
|
51
|
+
'&:hover': {
|
|
52
|
+
backgroundColor: "var(--ds-background-neutral-hovered, #0B120E24)"
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
} else {
|
|
56
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
|
|
57
|
+
return css({
|
|
58
|
+
color: "var(--ds-text-subtle, #505258)",
|
|
59
|
+
backgroundColor: "var(--ds-background-neutral, #0515240F)",
|
|
60
|
+
'&:hover': {
|
|
61
|
+
backgroundColor: "var(--ds-background-neutral-hovered, #0B120E24)"
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles -- Ignored via go/DSP-18766
|
|
69
|
+
export var NameContainer =
|
|
70
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-styled -- Ignored via go/DSP-18766
|
|
71
|
+
styled.span({
|
|
72
|
+
marginLeft: "var(--ds-space-075, 6px)",
|
|
73
|
+
marginRight: "var(--ds-space-100, 8px)",
|
|
74
|
+
// eslint-disable-next-line -- Ignored via go/DSP-18766
|
|
75
|
+
lineHeight: "var(--ds-space-250, 20px)"
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
/* Override Avatar styles to match design spec */
|
|
79
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles -- Ignored via go/DSP-18766
|
|
80
|
+
export var AvatarWrapper =
|
|
81
|
+
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage, @atlaskit/ui-styling-standard/no-styled -- Ignored via go/DSP-18766
|
|
82
|
+
styled.div({
|
|
83
|
+
height: "var(--ds-space-200, 16px)",
|
|
84
|
+
width: "var(--ds-space-200, 16px)",
|
|
85
|
+
alignSelf: 'center',
|
|
86
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors -- Ignored via go/DSP-18766
|
|
87
|
+
'> div span': {
|
|
88
|
+
margin: "var(--ds-space-0, 0px)"
|
|
89
|
+
},
|
|
90
|
+
// Fix fallback avatar icon vertical alignment.
|
|
91
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
|
|
92
|
+
'> div > span:has(> span)': {
|
|
93
|
+
position: 'relative',
|
|
94
|
+
top: '-2px'
|
|
95
|
+
}
|
|
96
|
+
});
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
2
1
|
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
3
2
|
import _createClass from "@babel/runtime/helpers/createClass";
|
|
4
3
|
import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
|
|
5
4
|
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
|
|
6
5
|
import _inherits from "@babel/runtime/helpers/inherits";
|
|
7
6
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
7
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
8
8
|
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
9
9
|
function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
|
|
10
10
|
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
|
|
@@ -27,32 +27,42 @@ export var replaceRichInlineNodes = function replaceRichInlineNodes(editorState,
|
|
|
27
27
|
fieldName = _ref2[0],
|
|
28
28
|
values = _ref2[1];
|
|
29
29
|
values.forEach(function (value) {
|
|
30
|
-
if (
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
// If not found as direct value and it's a team, try to find in membersOf function arguments
|
|
35
|
-
if (astNodes.length === 0 && value.type === 'team' && fg('jira-membersof-team-support')) {
|
|
36
|
-
astNodes = getMembersOfArgumentNodes(ast, value.id);
|
|
30
|
+
if (fg('jql-function-arg-hydration')) {
|
|
31
|
+
// Skip deprecated fields
|
|
32
|
+
if (value.type === 'deprecated-field') {
|
|
33
|
+
return;
|
|
37
34
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
});
|
|
35
|
+
// When the gate is on, collect both direct value operands and function argument
|
|
36
|
+
// operands for all node types
|
|
37
|
+
var astNodes = [].concat(_toConsumableArray(getValueNodes(ast, fieldName, value.id)), _toConsumableArray(getFunctionArgumentNodes(ast, fieldName, value.id)));
|
|
38
|
+
replaceAstNodesWithRichInlineNodes(transaction, astNodes, fieldName, value);
|
|
39
|
+
} else if (value.type === 'user' || value.type === 'team' || value.type === 'goal' && FeatureGates.getExperimentValue('anip-1095-goals-in-harmonised-filter', 'isEnabled', false) || value.type === 'project' && FeatureGates.getExperimentValue('atlassian_projects_-_native_integration', 'releaseVersion', -1) >= 1) {
|
|
40
|
+
// Legacy path: direct value operands only, with membersOf fallback for teams.
|
|
41
|
+
var _astNodes = getValueNodes(ast, fieldName, value.id);
|
|
42
|
+
if (_astNodes.length === 0 && value.type === 'team' && fg('jira-membersof-team-support')) {
|
|
43
|
+
_astNodes = getMembersOfArgumentNodes(ast, value.id);
|
|
44
|
+
}
|
|
45
|
+
replaceAstNodesWithRichInlineNodes(transaction, _astNodes, fieldName, value);
|
|
51
46
|
}
|
|
52
47
|
});
|
|
53
48
|
});
|
|
54
49
|
return transaction;
|
|
55
50
|
};
|
|
51
|
+
var replaceAstNodesWithRichInlineNodes = function replaceAstNodesWithRichInlineNodes(transaction, astNodes, fieldName, value) {
|
|
52
|
+
astNodes.forEach(function (astNode) {
|
|
53
|
+
if (astNode.position) {
|
|
54
|
+
var _astNode$position = _slicedToArray(astNode.position, 2),
|
|
55
|
+
from = _astNode$position[0],
|
|
56
|
+
to = _astNode$position[1];
|
|
57
|
+
var documentFrom = getDocumentPosition(transaction.doc, from);
|
|
58
|
+
if (!isRichInlineNode(transaction.doc, documentFrom)) {
|
|
59
|
+
var documentTo = getDocumentPosition(transaction.doc, to);
|
|
60
|
+
var node = getRichInlineNode(fieldName, value, astNode.text);
|
|
61
|
+
transaction.replaceWith(documentFrom, documentTo, node);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
};
|
|
56
66
|
var getRichInlineNode = function getRichInlineNode(fieldName, value, text) {
|
|
57
67
|
switch (value.type) {
|
|
58
68
|
case 'user':
|
|
@@ -83,6 +93,13 @@ var getRichInlineNode = function getRichInlineNode(fieldName, value, text) {
|
|
|
83
93
|
fieldName: fieldName
|
|
84
94
|
}), _textContent3);
|
|
85
95
|
}
|
|
96
|
+
case 'lozengeWithAvatar':
|
|
97
|
+
{
|
|
98
|
+
var _textContent4 = JQLEditorSchema.text(text);
|
|
99
|
+
return JQLEditorSchema.nodes.lozengeWithAvatar.create(_objectSpread(_objectSpread({}, value), {}, {
|
|
100
|
+
fieldName: fieldName
|
|
101
|
+
}), _textContent4);
|
|
102
|
+
}
|
|
86
103
|
default:
|
|
87
104
|
{
|
|
88
105
|
throw new Error("Unsupported hydrated value type ".concat(value.type));
|
|
@@ -105,6 +122,12 @@ var getMembersOfArgumentNodes = function getMembersOfArgumentNodes(ast, teamId)
|
|
|
105
122
|
}
|
|
106
123
|
return ast.query.accept(new FindMembersOfArgumentsVisitor(teamId));
|
|
107
124
|
};
|
|
125
|
+
var getFunctionArgumentNodes = function getFunctionArgumentNodes(ast, fieldName, valueId) {
|
|
126
|
+
if (!ast.query) {
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
return ast.query.accept(new FindFunctionArgumentsVisitor(fieldName, valueId));
|
|
130
|
+
};
|
|
108
131
|
|
|
109
132
|
/**
|
|
110
133
|
* Base visitor class for traversing JQL AST to find specific nodes.
|
|
@@ -191,21 +214,51 @@ var FindValuesVisitor = /*#__PURE__*/function (_BaseAstNodeFinder2) {
|
|
|
191
214
|
return _createClass(FindValuesVisitor);
|
|
192
215
|
}(BaseAstNodeFinder);
|
|
193
216
|
/**
|
|
194
|
-
* Visitor that finds
|
|
195
|
-
*
|
|
217
|
+
* Visitor that finds function arguments for a specific field matching a target value id.
|
|
218
|
+
* This visitor is field-aware: it processes clauses for the given field and matches arguments by their raw value.
|
|
196
219
|
*/
|
|
197
|
-
var
|
|
198
|
-
function
|
|
220
|
+
var FindFunctionArgumentsVisitor = /*#__PURE__*/function (_BaseAstNodeFinder3) {
|
|
221
|
+
function FindFunctionArgumentsVisitor(fieldName, targetValueId) {
|
|
199
222
|
var _this3;
|
|
200
|
-
_classCallCheck(this,
|
|
201
|
-
_this3 = _callSuper(this,
|
|
223
|
+
_classCallCheck(this, FindFunctionArgumentsVisitor);
|
|
224
|
+
_this3 = _callSuper(this, FindFunctionArgumentsVisitor);
|
|
202
225
|
_defineProperty(_this3, "visitTerminalClause", function (terminalClause) {
|
|
226
|
+
if (!_this3.equalsIgnoreCase(terminalClause.field.value, _this3.fieldName)) {
|
|
227
|
+
return [];
|
|
228
|
+
}
|
|
203
229
|
if (terminalClause.operand === undefined) {
|
|
204
230
|
return [];
|
|
205
231
|
}
|
|
206
232
|
return terminalClause.operand.accept(_this3);
|
|
207
233
|
});
|
|
208
234
|
_defineProperty(_this3, "visitFunctionOperand", function (functionOperand) {
|
|
235
|
+
return functionOperand.arguments.filter(function (arg) {
|
|
236
|
+
return _this3.equalsIgnoreCase(arg.value.trim(), _this3.targetValueId);
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
_this3.fieldName = fieldName;
|
|
240
|
+
_this3.targetValueId = targetValueId.trim();
|
|
241
|
+
return _this3;
|
|
242
|
+
}
|
|
243
|
+
_inherits(FindFunctionArgumentsVisitor, _BaseAstNodeFinder3);
|
|
244
|
+
return _createClass(FindFunctionArgumentsVisitor);
|
|
245
|
+
}(BaseAstNodeFinder);
|
|
246
|
+
/**
|
|
247
|
+
* Visitor that finds membersOf function arguments matching a specific team ID.
|
|
248
|
+
* Used for queries like "assignee in membersOf("id: <uuid>")".
|
|
249
|
+
*/
|
|
250
|
+
var FindMembersOfArgumentsVisitor = /*#__PURE__*/function (_BaseAstNodeFinder4) {
|
|
251
|
+
function FindMembersOfArgumentsVisitor(teamId) {
|
|
252
|
+
var _this4;
|
|
253
|
+
_classCallCheck(this, FindMembersOfArgumentsVisitor);
|
|
254
|
+
_this4 = _callSuper(this, FindMembersOfArgumentsVisitor);
|
|
255
|
+
_defineProperty(_this4, "visitTerminalClause", function (terminalClause) {
|
|
256
|
+
if (terminalClause.operand === undefined) {
|
|
257
|
+
return [];
|
|
258
|
+
}
|
|
259
|
+
return terminalClause.operand.accept(_this4);
|
|
260
|
+
});
|
|
261
|
+
_defineProperty(_this4, "visitFunctionOperand", function (functionOperand) {
|
|
209
262
|
var functionName = functionOperand.function.value.toLowerCase();
|
|
210
263
|
|
|
211
264
|
// Only process membersOf function
|
|
@@ -216,18 +269,18 @@ var FindMembersOfArgumentsVisitor = /*#__PURE__*/function (_BaseAstNodeFinder3)
|
|
|
216
269
|
functionOperand.arguments.forEach(function (arg) {
|
|
217
270
|
// Normalize both values by removing extra whitespace for comparison
|
|
218
271
|
// This handles both "id: uuid" and "id:uuid" formats
|
|
219
|
-
var normalizedArgValue =
|
|
220
|
-
var normalizedTeamId =
|
|
221
|
-
if (
|
|
272
|
+
var normalizedArgValue = _this4.normalizeValue(arg.value);
|
|
273
|
+
var normalizedTeamId = _this4.normalizeValue(_this4.teamId);
|
|
274
|
+
if (_this4.equalsIgnoreCase(normalizedArgValue, normalizedTeamId)) {
|
|
222
275
|
matchingArgs.push(arg);
|
|
223
276
|
}
|
|
224
277
|
});
|
|
225
278
|
return matchingArgs;
|
|
226
279
|
});
|
|
227
|
-
|
|
228
|
-
return
|
|
280
|
+
_this4.teamId = teamId;
|
|
281
|
+
return _this4;
|
|
229
282
|
}
|
|
230
|
-
_inherits(FindMembersOfArgumentsVisitor,
|
|
283
|
+
_inherits(FindMembersOfArgumentsVisitor, _BaseAstNodeFinder4);
|
|
231
284
|
return _createClass(FindMembersOfArgumentsVisitor, [{
|
|
232
285
|
key: "normalizeValue",
|
|
233
286
|
value:
|
|
@@ -79,16 +79,16 @@ export var ValidQueryVisitor = /*#__PURE__*/function (_AbstractJastVisitor) {
|
|
|
79
79
|
}).join(', '), ")");
|
|
80
80
|
});
|
|
81
81
|
_defineProperty(_this, "visitFunctionOperand", function (functionOperand) {
|
|
82
|
-
// Only include membersOf function as it has arguments that need hydration
|
|
83
|
-
// Other functions like currentUser() don't have hydratable arguments
|
|
84
82
|
var functionName = functionOperand.function.value.toLowerCase();
|
|
85
|
-
if (functionName !== 'membersof' || !fg('jira-membersof-team-support')) {
|
|
86
|
-
return '';
|
|
87
|
-
}
|
|
88
83
|
var args = functionOperand.arguments.map(function (arg) {
|
|
89
84
|
return arg.text;
|
|
90
85
|
}).join(', ');
|
|
91
|
-
|
|
86
|
+
|
|
87
|
+
// The generic gate supersedes the legacy membersOf-specific gate: when
|
|
88
|
+
// jql-function-arg-hydration is on, any function with arguments is included (covering
|
|
89
|
+
// membersOf and all others). Otherwise fall back to the legacy membersOf-only path.
|
|
90
|
+
var shouldIncludeFunction = fg('jql-function-arg-hydration') ? functionOperand.arguments.length > 0 : functionName === 'membersof' && fg('jira-membersof-team-support');
|
|
91
|
+
return shouldIncludeFunction ? "".concat(functionOperand.function.text, "(").concat(args, ")") : '';
|
|
92
92
|
});
|
|
93
93
|
return _this;
|
|
94
94
|
}
|