@atlaskit/link-datasource 1.12.3 → 1.13.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.
Files changed (116) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/cjs/analytics/constants.js +1 -1
  3. package/dist/cjs/services/useBasicFilterAGG.js +40 -82
  4. package/dist/cjs/services/utils.js +1 -1
  5. package/dist/cjs/ui/issue-like-table/draggable-table-heading.js +0 -12
  6. package/dist/cjs/ui/issue-like-table/styled.js +1 -1
  7. package/dist/cjs/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.js +94 -0
  8. package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +24 -13
  9. package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/index.js +3 -1
  10. package/dist/cjs/ui/jira-issues-modal/basic-filters/utils/isClauseTooComplex.js +93 -0
  11. package/dist/cjs/ui/jira-issues-modal/basic-filters/utils/isQueryTooComplex.js +146 -0
  12. package/dist/cjs/ui/jira-issues-modal/basic-filters/utils/transformers.js +15 -3
  13. package/dist/cjs/ui/jira-issues-modal/jira-search-container/buildJQL.js +3 -2
  14. package/dist/cjs/ui/jira-issues-modal/jira-search-container/index.js +23 -9
  15. package/dist/cjs/ui/jira-issues-modal/jira-search-container/messages.js +5 -0
  16. package/dist/cjs/ui/jira-issues-modal/mode-switcher/index.js +28 -16
  17. package/dist/es2019/analytics/constants.js +1 -1
  18. package/dist/es2019/services/useBasicFilterAGG.js +30 -53
  19. package/dist/es2019/services/utils.js +1 -1
  20. package/dist/es2019/ui/issue-like-table/draggable-table-heading.js +0 -12
  21. package/dist/es2019/ui/issue-like-table/styled.js +16 -4
  22. package/dist/es2019/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.js +52 -0
  23. package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +15 -7
  24. package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/index.js +3 -1
  25. package/dist/es2019/ui/jira-issues-modal/basic-filters/utils/isClauseTooComplex.js +77 -0
  26. package/dist/es2019/ui/jira-issues-modal/basic-filters/utils/isQueryTooComplex.js +105 -0
  27. package/dist/es2019/ui/jira-issues-modal/basic-filters/utils/transformers.js +14 -2
  28. package/dist/es2019/ui/jira-issues-modal/jira-search-container/buildJQL.js +2 -1
  29. package/dist/es2019/ui/jira-issues-modal/jira-search-container/index.js +15 -4
  30. package/dist/es2019/ui/jira-issues-modal/jira-search-container/messages.js +5 -0
  31. package/dist/es2019/ui/jira-issues-modal/mode-switcher/index.js +19 -9
  32. package/dist/esm/analytics/constants.js +1 -1
  33. package/dist/esm/services/useBasicFilterAGG.js +41 -83
  34. package/dist/esm/services/utils.js +1 -1
  35. package/dist/esm/ui/issue-like-table/draggable-table-heading.js +0 -12
  36. package/dist/esm/ui/issue-like-table/styled.js +1 -1
  37. package/dist/esm/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.js +87 -0
  38. package/dist/esm/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +24 -13
  39. package/dist/esm/ui/jira-issues-modal/basic-filters/ui/index.js +3 -1
  40. package/dist/esm/ui/jira-issues-modal/basic-filters/utils/isClauseTooComplex.js +86 -0
  41. package/dist/esm/ui/jira-issues-modal/basic-filters/utils/isQueryTooComplex.js +140 -0
  42. package/dist/esm/ui/jira-issues-modal/basic-filters/utils/transformers.js +12 -2
  43. package/dist/esm/ui/jira-issues-modal/jira-search-container/buildJQL.js +2 -1
  44. package/dist/esm/ui/jira-issues-modal/jira-search-container/index.js +23 -9
  45. package/dist/esm/ui/jira-issues-modal/jira-search-container/messages.js +5 -0
  46. package/dist/esm/ui/jira-issues-modal/mode-switcher/index.js +29 -17
  47. package/dist/types/services/useBasicFilterAGG.d.ts +9 -1
  48. package/dist/types/services/utils.d.ts +1 -1
  49. package/dist/types/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.d.ts +18 -0
  50. package/dist/types/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.d.ts +2 -1
  51. package/dist/types/ui/jira-issues-modal/basic-filters/ui/index.d.ts +2 -1
  52. package/dist/types/ui/jira-issues-modal/basic-filters/utils/isClauseTooComplex.d.ts +2 -0
  53. package/dist/types/ui/jira-issues-modal/basic-filters/utils/isQueryTooComplex.d.ts +1 -0
  54. package/dist/types/ui/jira-issues-modal/basic-filters/utils/transformers.d.ts +3 -1
  55. package/dist/types/ui/jira-issues-modal/jira-search-container/buildJQL.d.ts +1 -0
  56. package/dist/types/ui/jira-issues-modal/jira-search-container/index.d.ts +1 -0
  57. package/dist/types/ui/jira-issues-modal/jira-search-container/messages.d.ts +5 -0
  58. package/dist/types/ui/jira-issues-modal/mode-switcher/index.d.ts +2 -0
  59. package/dist/types-ts4.5/services/useBasicFilterAGG.d.ts +9 -1
  60. package/dist/types-ts4.5/services/utils.d.ts +1 -1
  61. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.d.ts +18 -0
  62. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.d.ts +2 -1
  63. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/ui/index.d.ts +2 -1
  64. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/utils/isClauseTooComplex.d.ts +2 -0
  65. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/utils/isQueryTooComplex.d.ts +1 -0
  66. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/utils/transformers.d.ts +3 -1
  67. package/dist/types-ts4.5/ui/jira-issues-modal/jira-search-container/buildJQL.d.ts +1 -0
  68. package/dist/types-ts4.5/ui/jira-issues-modal/jira-search-container/index.d.ts +1 -0
  69. package/dist/types-ts4.5/ui/jira-issues-modal/jira-search-container/messages.d.ts +5 -0
  70. package/dist/types-ts4.5/ui/jira-issues-modal/mode-switcher/index.d.ts +2 -0
  71. package/package.json +1 -2
  72. package/dist/cjs/ui/jira-issues-modal/basic-filters/hooks/useFieldValues.js +0 -75
  73. package/dist/cjs/ui/jira-issues-modal/basic-filters/hooks/useIsComplexQuery.js +0 -12
  74. package/dist/cjs/ui/jira-issues-modal/basic-filters/mocks/fieldValuesEmptyResponse.js +0 -20
  75. package/dist/cjs/ui/jira-issues-modal/basic-filters/mocks/fieldValuesExpectedResponseForAssignees.js +0 -155
  76. package/dist/cjs/ui/jira-issues-modal/basic-filters/mocks/fieldValuesStandardResponseForProjects.js +0 -82
  77. package/dist/cjs/ui/jira-issues-modal/basic-filters/mocks/fieldValuesStandardResponseForStatuses.js +0 -87
  78. package/dist/cjs/ui/jira-issues-modal/basic-filters/mocks/fieldValuesStandardResponseForTypes.js +0 -97
  79. package/dist/cjs/ui/jira-issues-modal/basic-filters/mocks/hydrateJqlEmptyResponse.js +0 -18
  80. package/dist/cjs/ui/jira-issues-modal/basic-filters/mocks/hydrateJqlStandardResponse.js +0 -111
  81. package/dist/es2019/ui/jira-issues-modal/basic-filters/hooks/useFieldValues.js +0 -39
  82. package/dist/es2019/ui/jira-issues-modal/basic-filters/hooks/useIsComplexQuery.js +0 -6
  83. package/dist/es2019/ui/jira-issues-modal/basic-filters/mocks/fieldValuesEmptyResponse.js +0 -14
  84. package/dist/es2019/ui/jira-issues-modal/basic-filters/mocks/fieldValuesExpectedResponseForAssignees.js +0 -149
  85. package/dist/es2019/ui/jira-issues-modal/basic-filters/mocks/fieldValuesStandardResponseForProjects.js +0 -76
  86. package/dist/es2019/ui/jira-issues-modal/basic-filters/mocks/fieldValuesStandardResponseForStatuses.js +0 -81
  87. package/dist/es2019/ui/jira-issues-modal/basic-filters/mocks/fieldValuesStandardResponseForTypes.js +0 -91
  88. package/dist/es2019/ui/jira-issues-modal/basic-filters/mocks/hydrateJqlEmptyResponse.js +0 -12
  89. package/dist/es2019/ui/jira-issues-modal/basic-filters/mocks/hydrateJqlStandardResponse.js +0 -105
  90. package/dist/esm/ui/jira-issues-modal/basic-filters/hooks/useFieldValues.js +0 -68
  91. package/dist/esm/ui/jira-issues-modal/basic-filters/hooks/useIsComplexQuery.js +0 -6
  92. package/dist/esm/ui/jira-issues-modal/basic-filters/mocks/fieldValuesEmptyResponse.js +0 -14
  93. package/dist/esm/ui/jira-issues-modal/basic-filters/mocks/fieldValuesExpectedResponseForAssignees.js +0 -149
  94. package/dist/esm/ui/jira-issues-modal/basic-filters/mocks/fieldValuesStandardResponseForProjects.js +0 -76
  95. package/dist/esm/ui/jira-issues-modal/basic-filters/mocks/fieldValuesStandardResponseForStatuses.js +0 -81
  96. package/dist/esm/ui/jira-issues-modal/basic-filters/mocks/fieldValuesStandardResponseForTypes.js +0 -91
  97. package/dist/esm/ui/jira-issues-modal/basic-filters/mocks/hydrateJqlEmptyResponse.js +0 -12
  98. package/dist/esm/ui/jira-issues-modal/basic-filters/mocks/hydrateJqlStandardResponse.js +0 -105
  99. package/dist/types/ui/jira-issues-modal/basic-filters/hooks/useFieldValues.d.ts +0 -12
  100. package/dist/types/ui/jira-issues-modal/basic-filters/hooks/useIsComplexQuery.d.ts +0 -3
  101. package/dist/types/ui/jira-issues-modal/basic-filters/mocks/fieldValuesEmptyResponse.d.ts +0 -3
  102. package/dist/types/ui/jira-issues-modal/basic-filters/mocks/fieldValuesExpectedResponseForAssignees.d.ts +0 -17
  103. package/dist/types/ui/jira-issues-modal/basic-filters/mocks/fieldValuesStandardResponseForProjects.d.ts +0 -8
  104. package/dist/types/ui/jira-issues-modal/basic-filters/mocks/fieldValuesStandardResponseForStatuses.d.ts +0 -8
  105. package/dist/types/ui/jira-issues-modal/basic-filters/mocks/fieldValuesStandardResponseForTypes.d.ts +0 -8
  106. package/dist/types/ui/jira-issues-modal/basic-filters/mocks/hydrateJqlEmptyResponse.d.ts +0 -3
  107. package/dist/types/ui/jira-issues-modal/basic-filters/mocks/hydrateJqlStandardResponse.d.ts +0 -29
  108. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/hooks/useFieldValues.d.ts +0 -12
  109. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/hooks/useIsComplexQuery.d.ts +0 -3
  110. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/mocks/fieldValuesEmptyResponse.d.ts +0 -3
  111. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/mocks/fieldValuesExpectedResponseForAssignees.d.ts +0 -17
  112. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/mocks/fieldValuesStandardResponseForProjects.d.ts +0 -8
  113. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/mocks/fieldValuesStandardResponseForStatuses.d.ts +0 -8
  114. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/mocks/fieldValuesStandardResponseForTypes.d.ts +0 -8
  115. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/mocks/hydrateJqlEmptyResponse.d.ts +0 -3
  116. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/mocks/hydrateJqlStandardResponse.d.ts +0 -29
@@ -0,0 +1,105 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import mergeWith from 'lodash/mergeWith';
3
+ import { AbstractJastVisitor, COMPOUND_OPERATOR_AND, COMPOUND_OPERATOR_OR, JastBuilder, OPERATOR_EQUALS, OPERATOR_GT_EQUALS, OPERATOR_IN, OPERATOR_LIKE } from '@atlaskit/jql-ast';
4
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
5
+ import { ALLOWED_ORDER_BY_KEYS } from '../../jira-search-container';
6
+ import { isClauseTooComplex } from './isClauseTooComplex';
7
+ import { isValidJql } from './index';
8
+
9
+ // Map of field keys to their respective clauses in the Jast
10
+
11
+ const allowedFields = [
12
+ // basic filter fields
13
+ 'assignee', 'issuetype', 'project', 'status',
14
+ // search input fields
15
+ 'text', 'summary', 'key',
16
+ // orderby field
17
+ 'created'];
18
+ const fallbackOperators = [OPERATOR_IN];
19
+ const fieldSpecificOperators = {
20
+ text: [OPERATOR_LIKE, OPERATOR_EQUALS],
21
+ summary: [OPERATOR_LIKE, OPERATOR_EQUALS],
22
+ key: [OPERATOR_EQUALS],
23
+ created: [OPERATOR_GT_EQUALS],
24
+ project: [OPERATOR_IN, OPERATOR_EQUALS],
25
+ issuetype: [OPERATOR_IN, OPERATOR_EQUALS],
26
+ status: [OPERATOR_IN, OPERATOR_EQUALS],
27
+ assignee: [OPERATOR_IN, OPERATOR_EQUALS]
28
+ };
29
+ class JqlClauseCollectingVisitorError extends Error {}
30
+
31
+ /**
32
+ * Rather than having to navigate the entire tree structure ourself, we extend AbstractJastVisitor
33
+ * class and implement visitor functions for node types that we wish to process.
34
+ * A list of available visitor can be viewed in packages/jql/jql-ast/src/types/api/jast-visitor.ts
35
+ * more info - https://atlaskit.atlassian.com/packages/jql/jql-ast/docs/traversing-the-ast
36
+ * */
37
+ class JqlClauseCollectingVisitor extends AbstractJastVisitor {
38
+ constructor() {
39
+ super();
40
+ _defineProperty(this, "visitNotClause", () => {
41
+ throw new JqlClauseCollectingVisitorError('Visited an unsupported node while traversing the AST');
42
+ });
43
+ _defineProperty(this, "visitOrderByField", orderByField => {
44
+ var _orderByField$field$v;
45
+ const fieldValue = (_orderByField$field$v = orderByField.field.value) === null || _orderByField$field$v === void 0 ? void 0 : _orderByField$field$v.toLowerCase();
46
+ if (fieldValue && !ALLOWED_ORDER_BY_KEYS.includes(fieldValue)) {
47
+ throw new JqlClauseCollectingVisitorError(`query with order by field '${fieldValue}' is not supported`);
48
+ }
49
+ return {};
50
+ });
51
+ _defineProperty(this, "visitCompoundClause", compoundClause => {
52
+ const clauseMap = {};
53
+ const operator = compoundClause.operator.value;
54
+ if (operator === COMPOUND_OPERATOR_AND) {
55
+ return compoundClause.clauses.reduce((result, clause) => this.aggregateResult(clause.accept(this), result), clauseMap);
56
+ }
57
+ if (operator === COMPOUND_OPERATOR_OR) {
58
+ // this is delt with in isClauseTooComplex
59
+ return this.aggregateResult({
60
+ text: [compoundClause]
61
+ }, clauseMap);
62
+ }
63
+ throw new JqlClauseCollectingVisitorError(`Compound clauses using the operator '${operator}' is not supported`);
64
+ });
65
+ _defineProperty(this, "visitTerminalClause", terminalClause => {
66
+ var _terminalClause$opera;
67
+ const fieldName = terminalClause.field.value.toLowerCase();
68
+ if (!allowedFields.includes(fieldName)) {
69
+ throw new JqlClauseCollectingVisitorError(`Field with name '${fieldName}' of type ${terminalClause.clauseType} is not supported`);
70
+ }
71
+ const operator = (_terminalClause$opera = terminalClause.operator) === null || _terminalClause$opera === void 0 ? void 0 : _terminalClause$opera.value;
72
+ const allowedOperators = fieldSpecificOperators[fieldName] || fallbackOperators;
73
+ if (operator && !allowedOperators.includes(operator.toLowerCase())) {
74
+ throw new JqlClauseCollectingVisitorError(`Field with name '${fieldName}' using operator ${operator} is not supported`);
75
+ }
76
+ return {
77
+ [terminalClause.field.value.toLowerCase()]: [terminalClause]
78
+ };
79
+ });
80
+ }
81
+ aggregateResult(aggregate, nextResult) {
82
+ return mergeWith(aggregate, nextResult, (destValue, srcValue) => srcValue.concat(destValue !== null && destValue !== void 0 ? destValue : []));
83
+ }
84
+ defaultResult() {
85
+ return {};
86
+ }
87
+ }
88
+ export const isQueryTooComplex = jql => {
89
+ if (!getBooleanFF('platform.linking-platform.datasource.show-jlol-basic-filters') || !jql) {
90
+ return false;
91
+ }
92
+ if (!isValidJql(jql)) {
93
+ return true;
94
+ }
95
+ const jast = new JastBuilder().build(jql);
96
+ try {
97
+ const jqlClauseCollectingVisitor = new JqlClauseCollectingVisitor();
98
+ const clauseMap = jast.query ? jast.query.accept(jqlClauseCollectingVisitor) : {}; // jast.query is defined as void | Query, hence the fallback
99
+
100
+ const hasAnyKeyWithComplexClause = Object.entries(clauseMap).some(([key, clauses]) => isClauseTooComplex(clauses, key));
101
+ return hasAnyKeyWithComplexClause;
102
+ } catch (error) {
103
+ return true;
104
+ }
105
+ };
@@ -29,7 +29,7 @@ function mapNodeToOption({
29
29
  ...baseProps,
30
30
  optionType: 'avatarLabel',
31
31
  avatar: user.picture,
32
- isSquare: true
32
+ isSquare: false
33
33
  };
34
34
  }
35
35
  if (group) {
@@ -83,9 +83,21 @@ export function mapHydrateResponseData({
83
83
  });
84
84
  return transformedHydrateResponseData;
85
85
  }
86
- export function mapFieldValuesResponseData({
86
+ export function mapFieldValuesToFilterOptions({
87
87
  data
88
88
  }) {
89
89
  var _data$jira2, _data$jira2$jqlBuilde, _data$jira2$jqlBuilde2, _data$jira2$jqlBuilde3;
90
90
  return (data === null || data === void 0 ? void 0 : (_data$jira2 = data.jira) === null || _data$jira2 === void 0 ? void 0 : (_data$jira2$jqlBuilde = _data$jira2.jqlBuilder) === null || _data$jira2$jqlBuilde === void 0 ? void 0 : (_data$jira2$jqlBuilde2 = _data$jira2$jqlBuilde.fieldValues) === null || _data$jira2$jqlBuilde2 === void 0 ? void 0 : (_data$jira2$jqlBuilde3 = _data$jira2$jqlBuilde2.edges) === null || _data$jira2$jqlBuilde3 === void 0 ? void 0 : _data$jira2$jqlBuilde3.map(edge => edge.node ? mapNodeToOption(edge.node) : null).filter(isNonNullSelectOption)) || [];
91
+ }
92
+ export function mapFieldValuesToTotalCount({
93
+ data
94
+ }) {
95
+ var _data$jira3, _data$jira3$jqlBuilde, _data$jira3$jqlBuilde2;
96
+ return (data === null || data === void 0 ? void 0 : (_data$jira3 = data.jira) === null || _data$jira3 === void 0 ? void 0 : (_data$jira3$jqlBuilde = _data$jira3.jqlBuilder) === null || _data$jira3$jqlBuilde === void 0 ? void 0 : (_data$jira3$jqlBuilde2 = _data$jira3$jqlBuilde.fieldValues) === null || _data$jira3$jqlBuilde2 === void 0 ? void 0 : _data$jira3$jqlBuilde2.totalCount) || 0;
97
+ }
98
+ export function mapFieldValuesToPageCursor({
99
+ data
100
+ }) {
101
+ var _data$jira4, _data$jira4$jqlBuilde, _data$jira4$jqlBuilde2, _data$jira4$jqlBuilde3;
102
+ return data === null || data === void 0 ? void 0 : (_data$jira4 = data.jira) === null || _data$jira4 === void 0 ? void 0 : (_data$jira4$jqlBuilde = _data$jira4.jqlBuilder) === null || _data$jira4$jqlBuilde === void 0 ? void 0 : (_data$jira4$jqlBuilde2 = _data$jira4$jqlBuilde.fieldValues) === null || _data$jira4$jqlBuilde2 === void 0 ? void 0 : (_data$jira4$jqlBuilde3 = _data$jira4$jqlBuilde2.pageInfo) === null || _data$jira4$jqlBuilde3 === void 0 ? void 0 : _data$jira4$jqlBuilde3.endCursor;
91
103
  }
@@ -1,6 +1,7 @@
1
1
  import { COMPOUND_OPERATOR_AND, COMPOUND_OPERATOR_OR, creators, JastBuilder, OPERATOR_EQUALS, OPERATOR_GT_EQUALS, OPERATOR_IN, OPERATOR_LIKE, ORDER_BY_DIRECTION_ASC, ORDER_BY_DIRECTION_DESC, print } from '@atlaskit/jql-ast';
2
2
  const fuzzySearchRegExp = /^"(.+)"$/;
3
3
  const jiraIssueKeyRegExp = /[A-Z]+-\d+/;
4
+ export const fuzzyCharacter = '*';
4
5
  const constructTerminalClause = (field, operator, value) => creators.terminalClause(creators.field(field), creators.operator(operator), creators.valueOperand(value));
5
6
  export const buildJQL = input => {
6
7
  /**
@@ -22,7 +23,7 @@ export const buildJQL = input => {
22
23
  return '';
23
24
  }
24
25
  if (trimmedRawSearch) {
25
- const fuzzy = !trimmedRawSearch.match(fuzzySearchRegExp) ? '*' : '';
26
+ const fuzzy = !trimmedRawSearch.match(fuzzySearchRegExp) ? fuzzyCharacter : '';
26
27
  const basicSearch = trimmedRawSearch.replace(/['"?*]+/g, '');
27
28
  const text = constructTerminalClause('text', OPERATOR_LIKE, `${basicSearch}${fuzzy}`);
28
29
  const summary = constructTerminalClause('summary', OPERATOR_LIKE, `${basicSearch}${fuzzy}`);
@@ -1,10 +1,11 @@
1
1
  /** @jsx jsx */
2
- import React, { useCallback, useMemo, useState } from 'react';
2
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
3
3
  import { css, jsx } from '@emotion/react';
4
4
  import { useIntl } from 'react-intl-next';
5
5
  import { getBooleanFF } from '@atlaskit/platform-feature-flags';
6
6
  import { useDatasourceAnalyticsEvents } from '../../../analytics';
7
7
  import { BasicFilters } from '../basic-filters';
8
+ import { isQueryTooComplex } from '../basic-filters/utils/isQueryTooComplex';
8
9
  import { BasicSearchInput } from '../basic-search-input';
9
10
  import { JiraJQLEditor } from '../jql-editor';
10
11
  import { ModeSwitcher } from '../mode-switcher';
@@ -17,6 +18,7 @@ const inputContainerStyles = css({
17
18
  minHeight: '60px'
18
19
  });
19
20
  const DEFAULT_JQL_QUERY = 'created >= -30d order by created DESC';
21
+ export const ALLOWED_ORDER_BY_KEYS = ['key', 'summary', 'assignee', 'status', 'created'];
20
22
  const JiraSearchMethodSwitcher = ModeSwitcher;
21
23
  export const JiraSearchContainer = props => {
22
24
  const {
@@ -36,6 +38,7 @@ export const JiraSearchContainer = props => {
36
38
  const [basicSearchTerm, setBasicSearchTerm] = useState('');
37
39
  const [currentSearchMethod, setCurrentSearchMethod] = useState(initialSearchMethod);
38
40
  const [jql, setJql] = useState(initialJql || DEFAULT_JQL_QUERY);
41
+ const [isComplexQuery, setIsComplexQuery] = useState(false);
39
42
  const [orderKey, setOrderKey] = useState();
40
43
  const [orderDirection, setOrderDirection] = useState();
41
44
  const {
@@ -63,7 +66,7 @@ export const JiraSearchContainer = props => {
63
66
  const order = hasOrder ? (_fragments$at3 = fragments.at(-1)) === null || _fragments$at3 === void 0 ? void 0 : _fragments$at3.split(' ').at(-1) : undefined;
64
67
 
65
68
  // TODO: confirm if these are the only order keys we want to preserve - existing whiteboard logic
66
- if (key && ['key', 'summary', 'assignee', 'status'].includes(key)) {
69
+ if (key && ALLOWED_ORDER_BY_KEYS.includes(key)) {
67
70
  setOrderKey(key);
68
71
  setOrderDirection(order);
69
72
  }
@@ -73,6 +76,7 @@ export const JiraSearchContainer = props => {
73
76
  onSearch({
74
77
  jql
75
78
  }, currentSearchMethod);
79
+ setIsComplexQuery(isQueryTooComplex(jql));
76
80
  if (currentSearchMethod === 'basic') {
77
81
  fireEvent('ui.form.submitted.basicSearch', {});
78
82
  } else if (currentSearchMethod === 'jql') {
@@ -85,6 +89,10 @@ export const JiraSearchContainer = props => {
85
89
  }
86
90
  return false;
87
91
  }, []);
92
+ useEffect(() => {
93
+ setIsComplexQuery(isQueryTooComplex(jql));
94
+ // eslint-disable-next-line react-hooks/exhaustive-deps
95
+ }, []);
88
96
  return jsx("div", {
89
97
  css: inputContainerStyles
90
98
  }, currentSearchMethod === 'basic' && jsx(React.Fragment, null, jsx(BasicSearchInput, {
@@ -93,7 +101,8 @@ export const JiraSearchContainer = props => {
93
101
  onSearch: handleSearch,
94
102
  searchTerm: basicSearchTerm
95
103
  }), showBasicFilters && jsx(BasicFilters, {
96
- jql: jql
104
+ jql: jql,
105
+ cloudId: cloudId || ''
97
106
  })), currentSearchMethod === 'jql' && jsx(JiraJQLEditor, {
98
107
  cloudId: cloudId || '',
99
108
  isSearching: isSearching,
@@ -108,7 +117,9 @@ export const JiraSearchContainer = props => {
108
117
  value: 'jql'
109
118
  }, {
110
119
  label: formatMessage(modeSwitcherMessages.basicTextSearchLabel),
111
- value: 'basic'
120
+ value: 'basic',
121
+ disabled: isComplexQuery,
122
+ tooltipText: isComplexQuery ? formatMessage(modeSwitcherMessages.basicModeSwitchDisabledTooltipText) : ''
112
123
  }]
113
124
  }));
114
125
  };
@@ -4,5 +4,10 @@ export const modeSwitcherMessages = defineMessages({
4
4
  id: 'linkDataSource.jira-issues.configmodal.basicModeText',
5
5
  description: 'Display text for basic text search toggle button',
6
6
  defaultMessage: 'Basic'
7
+ },
8
+ basicModeSwitchDisabledTooltipText: {
9
+ id: 'linkDataSource.jira-issues.configmodal.basicModeSwitchDisabledTooltipText',
10
+ description: 'Display tooltip text when basic mode switch is disabled',
11
+ defaultMessage: "You can't switch to basic for this query."
7
12
  }
8
13
  });
@@ -1,7 +1,9 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
1
2
  /** @jsx jsx */
2
3
  import React from 'react';
3
4
  import { css, jsx } from '@emotion/react';
4
- import { N0, N20, N30A, N700 } from '@atlaskit/theme/colors';
5
+ import { N0, N20, N30A, N60, N700 } from '@atlaskit/theme/colors';
6
+ import Tooltip from '@atlaskit/tooltip';
5
7
  const modeSwitcherStyles = css({
6
8
  alignItems: 'center',
7
9
  background: `var(--ds-background-neutral, ${N20})`,
@@ -44,8 +46,12 @@ const modeSwitcherLabelSelectedStyles = css({
44
46
  }
45
47
  });
46
48
  const modeSwitcherLabelDisabledStyles = css({
49
+ color: `var(--ds-text-disabled, ${N60})`
50
+ });
51
+ const modeSwitcherDisabledStyles = css({
47
52
  ':hover': {
48
- cursor: 'not-allowed'
53
+ cursor: 'not-allowed',
54
+ background: 'transparent'
49
55
  }
50
56
  });
51
57
  const compactModeSwitcherLabelStyles = css({
@@ -69,22 +75,26 @@ export const ModeSwitcher = props => {
69
75
  disabled: isDisabled
70
76
  }, options.map(({
71
77
  value,
72
- label
78
+ label,
79
+ disabled: isOptionDisabled,
80
+ tooltipText
73
81
  }) => {
74
82
  const isSelected = value === selectedOptionValue;
75
- return jsx("label", {
83
+ return jsx(Tooltip, {
84
+ content: tooltipText
85
+ }, tooltipProps => jsx("label", _extends({}, tooltipProps, {
76
86
  key: value,
77
- css: [modeSwitcherLabelStyles, isCompact && compactModeSwitcherLabelStyles, isSelected && modeSwitcherLabelSelectedStyles, isDisabled && modeSwitcherLabelDisabledStyles],
87
+ css: [modeSwitcherLabelStyles, isCompact && compactModeSwitcherLabelStyles, isSelected && modeSwitcherLabelSelectedStyles, isDisabled && modeSwitcherDisabledStyles, isOptionDisabled && [modeSwitcherLabelDisabledStyles, modeSwitcherDisabledStyles]],
78
88
  "data-testid": `mode-toggle-${value}`
79
- }, label, jsx("input", {
89
+ }), label, jsx("input", {
80
90
  "aria-checked": isSelected,
81
- "aria-disabled": isDisabled,
91
+ "aria-disabled": isOptionDisabled,
82
92
  checked: isSelected,
83
93
  css: modeInputStyles,
84
- disabled: isDisabled,
94
+ disabled: isOptionDisabled,
85
95
  onChange: handleModeChange,
86
96
  type: "radio",
87
97
  value: value
88
- }));
98
+ })));
89
99
  })) : null;
90
100
  };
@@ -1,5 +1,5 @@
1
1
  export var EVENT_CHANNEL = 'media';
2
2
  export var packageMetaData = {
3
3
  packageName: "@atlaskit/link-datasource",
4
- packageVersion: "1.12.3"
4
+ packageVersion: "1.13.0"
5
5
  };
@@ -2,7 +2,7 @@ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
2
  import _regeneratorRuntime from "@babel/runtime/regenerator";
3
3
  import { useCallback, useMemo } from 'react';
4
4
  import { useSmartLinkContext } from '@atlaskit/link-provider';
5
- import { getBaseUrl } from '@atlaskit/linking-common';
5
+ import { getBaseUrl, request } from '@atlaskit/linking-common';
6
6
  import { fieldValuesQuery, hydrateJQLQuery } from './utils';
7
7
  var getGraphqlUrl = function getGraphqlUrl(envKey, baseUrlOverride) {
8
8
  var baseUrl = baseUrlOverride || getBaseUrl(envKey);
@@ -12,97 +12,55 @@ export var useBasicFilterAGG = function useBasicFilterAGG() {
12
12
  var _useSmartLinkContext = useSmartLinkContext(),
13
13
  client = _useSmartLinkContext.connections.client;
14
14
  var gatewayGraphqlUrl = getGraphqlUrl(client.envKey, client.baseUrlOverride);
15
- var aggHeaders = useMemo(function () {
16
- return new Headers({
17
- 'Content-Type': 'application/json',
18
- 'X-ExperimentalApi': 'JiraJqlBuilder'
19
- });
20
- }, []);
21
- var getHydratedJQL = useCallback( /*#__PURE__*/function () {
22
- var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(cloudId, jql) {
23
- var body, request, response;
15
+ var requestCall = useCallback( /*#__PURE__*/function () {
16
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(body) {
24
17
  return _regeneratorRuntime.wrap(function _callee$(_context) {
25
18
  while (1) switch (_context.prev = _context.next) {
26
19
  case 0:
27
- body = JSON.stringify({
28
- variables: {
29
- cloudId: cloudId,
30
- jql: jql
31
- },
32
- operationName: 'hydrate',
33
- query: hydrateJQLQuery
34
- });
35
- request = new Request(gatewayGraphqlUrl, {
36
- method: 'POST',
37
- headers: aggHeaders,
38
- body: body
39
- });
40
- _context.prev = 2;
41
- _context.next = 5;
42
- return fetch(request);
43
- case 5:
44
- response = _context.sent;
45
- return _context.abrupt("return", response.json());
46
- case 9:
47
- _context.prev = 9;
48
- _context.t0 = _context["catch"](2);
49
- throw new Error(_context.t0);
50
- case 12:
20
+ return _context.abrupt("return", request('post', gatewayGraphqlUrl, body, {
21
+ 'X-ExperimentalApi': 'JiraJqlBuilder'
22
+ }, [200, 201, 202, 203, 204]));
23
+ case 1:
51
24
  case "end":
52
25
  return _context.stop();
53
26
  }
54
- }, _callee, null, [[2, 9]]);
27
+ }, _callee);
55
28
  }));
56
- return function (_x, _x2) {
29
+ return function (_x) {
57
30
  return _ref.apply(this, arguments);
58
31
  };
59
- }(), [gatewayGraphqlUrl, aggHeaders]);
60
- var getFieldValues = useCallback( /*#__PURE__*/function () {
61
- var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(cloudId, jql, jqlTerm, searchString, pageCursor) {
62
- var body, request, response;
63
- return _regeneratorRuntime.wrap(function _callee2$(_context2) {
64
- while (1) switch (_context2.prev = _context2.next) {
65
- case 0:
66
- body = JSON.stringify({
67
- variables: {
68
- cloudId: cloudId,
69
- jql: jql,
70
- first: 10,
71
- jqlTerm: jqlTerm,
72
- searchString: searchString,
73
- after: pageCursor
74
- },
75
- operationName: 'fieldValues',
76
- query: fieldValuesQuery
77
- });
78
- request = new Request(gatewayGraphqlUrl, {
79
- method: 'POST',
80
- headers: aggHeaders,
81
- body: body
82
- });
83
- _context2.prev = 2;
84
- _context2.next = 5;
85
- return fetch(request);
86
- case 5:
87
- response = _context2.sent;
88
- _context2.next = 8;
89
- return response.json();
90
- case 8:
91
- return _context2.abrupt("return", _context2.sent);
92
- case 11:
93
- _context2.prev = 11;
94
- _context2.t0 = _context2["catch"](2);
95
- throw new Error(_context2.t0);
96
- case 14:
97
- case "end":
98
- return _context2.stop();
99
- }
100
- }, _callee2, null, [[2, 11]]);
101
- }));
102
- return function (_x3, _x4, _x5, _x6, _x7) {
103
- return _ref2.apply(this, arguments);
104
- };
105
- }(), [gatewayGraphqlUrl, aggHeaders]);
32
+ }(), [gatewayGraphqlUrl]);
33
+ var getHydratedJQL = useCallback(function (cloudId, jql) {
34
+ return requestCall({
35
+ variables: {
36
+ cloudId: cloudId,
37
+ jql: jql
38
+ },
39
+ operationName: 'hydrate',
40
+ query: hydrateJQLQuery
41
+ });
42
+ }, [requestCall]);
43
+ var getFieldValues = useCallback(function (_ref2) {
44
+ var cloudId = _ref2.cloudId,
45
+ _ref2$jql = _ref2.jql,
46
+ jql = _ref2$jql === void 0 ? '' : _ref2$jql,
47
+ jqlTerm = _ref2.jqlTerm,
48
+ _ref2$searchString = _ref2.searchString,
49
+ searchString = _ref2$searchString === void 0 ? '' : _ref2$searchString,
50
+ pageCursor = _ref2.pageCursor;
51
+ return requestCall({
52
+ variables: {
53
+ cloudId: cloudId,
54
+ jql: jql,
55
+ first: 10,
56
+ jqlTerm: jqlTerm,
57
+ searchString: searchString,
58
+ after: pageCursor
59
+ },
60
+ operationName: 'fieldValues',
61
+ query: fieldValuesQuery
62
+ });
63
+ }, [requestCall]);
106
64
  return useMemo(function () {
107
65
  return {
108
66
  getHydratedJQL: getHydratedJQL,
@@ -1,2 +1,2 @@
1
1
  export var hydrateJQLQuery = "query hydrate($cloudId: ID!, $jql: String!) {\n jira {\n jqlBuilder(cloudId: $cloudId) {\n hydrateJqlQuery(query: $jql) {\n ... on JiraJqlHydratedQuery {\n fields {\n ... on JiraJqlQueryHydratedField {\n jqlTerm\n values {\n ... on JiraJqlQueryHydratedValue {\n values {\n ... on JiraJqlProjectFieldValue {\n jqlTerm\n displayName\n project {\n avatar {\n small\n }\n }\n }\n ... on JiraJqlStatusFieldValue {\n jqlTerm\n displayName\n statusCategory {\n colorName\n }\n }\n ... on JiraJqlIssueTypeFieldValue {\n jqlTerm\n displayName\n issueTypes {\n avatar {\n small\n }\n }\n }\n ... on JiraJqlUserFieldValue {\n jqlTerm\n displayName\n user {\n picture\n }\n }\n ... on JiraJqlGroupFieldValue {\n jqlTerm\n displayName\n group {\n name\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n}";
2
- export var fieldValuesQuery = "query fieldValues($cloudId: ID!, $first: Int = 10, $jqlTerm: String!, $jql: String!, $searchString: String!, $after: String, $projectOptions: JiraProjectOptions) {\n jira {\n jqlBuilder(cloudId: $cloudId) {\n fieldValues(\n first: $first\n jqlTerm: $jqlTerm\n jqlContext: $jql\n searchString: $searchString\n after: $after\n ) {\n totalCount\n pageInfo {\n endCursor\n }\n edges {\n node {\n jqlTerm\n displayName\n ... on JiraJqlProjectFieldValue {\n project {\n avatar {\n small\n }\n }\n }\n ... on JiraJqlIssueTypeFieldValue {\n issueTypes {\n avatar {\n small\n }\n }\n }\n ... on JiraJqlStatusFieldValue {\n statusCategory {\n colorName\n }\n }\n ... on JiraJqlUserFieldValue {\n user {\n picture\n }\n }\n ... on JiraJqlGroupFieldValue {\n group {\n name\n }\n }\n }\n }\n }\n }\n }\n}";
2
+ export var fieldValuesQuery = "query fieldValues($cloudId: ID!, $first: Int = 10, $jqlTerm: String!, $jql: String!, $searchString: String!, $after: String) {\n jira {\n jqlBuilder(cloudId: $cloudId) {\n fieldValues(\n first: $first\n jqlTerm: $jqlTerm\n jqlContext: $jql\n searchString: $searchString\n after: $after\n ) {\n totalCount\n pageInfo {\n endCursor\n }\n edges {\n node {\n jqlTerm\n displayName\n ... on JiraJqlProjectFieldValue {\n project {\n avatar {\n small\n }\n }\n }\n ... on JiraJqlIssueTypeFieldValue {\n issueTypes {\n avatar {\n small\n }\n }\n }\n ... on JiraJqlStatusFieldValue {\n statusCategory {\n colorName\n }\n }\n ... on JiraJqlUserFieldValue {\n user {\n picture\n }\n }\n ... on JiraJqlGroupFieldValue {\n group {\n name\n }\n }\n }\n }\n }\n }\n }\n}";
@@ -14,17 +14,6 @@ import { offsetFromPointer } from '@atlaskit/pragmatic-drag-and-drop/util/offset
14
14
  import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/util/set-custom-native-drag-preview';
15
15
  import { TableHeading } from './styled';
16
16
  import { COLUMN_MIN_WIDTH } from './index';
17
- var tableHeadingStatusStyles = {
18
- idle: css({
19
- ':hover': {
20
- background: "var(--ds-surface-hovered, #091E4224)"
21
- }
22
- }),
23
- dragging: css({
24
- background: "var(--ds-background-disabled, #091E4224)",
25
- color: "var(--ds-text-disabled, #091E424F)"
26
- })
27
- };
28
17
  var verticallyAlignedStyles = css({
29
18
  display: 'flex',
30
19
  alignItems: 'center',
@@ -267,7 +256,6 @@ export var DraggableTableHeading = function DraggableTableHeading(_ref) {
267
256
  }, [id, index, onWidthChange, state, tableId, width]);
268
257
  return jsx(TableHeading, {
269
258
  ref: mainHeaderCellRef,
270
- css: [tableHeadingStatusStyles[state.type]],
271
259
  "data-testid": "".concat(id, "-column-heading"),
272
260
  style: {
273
261
  width: width,
@@ -5,4 +5,4 @@ import { N40 } from '@atlaskit/theme/colors';
5
5
  export var ScrollableContainerHeight = 590;
6
6
  export var FieldTextFontSize = '14px';
7
7
  export var Table = styled.table(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n width: 100%;\n"])));
8
- export var TableHeading = styled.th(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n position: relative;\n padding-block: ", " ", ";\n line-height: ", ";\n border-bottom: 2px solid ", ";\n & [data-testid='datasource-header-content--container'] {\n margin-top: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n"])), "var(--ds-space-300, 24px)", "var(--ds-space-100, 8px)", "var(--ds-font-lineHeight-300, 16px)", "var(--ds-background-accent-gray-subtler, ".concat(N40, ")"));
8
+ export var TableHeading = styled.th(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n position: relative;\n line-height: ", ";\n border-bottom: 2px solid ", ";\n height: calc(52px - ", " * 2 - 2px);\n vertical-align: bottom;\n\n & [data-testid='datasource-header-content--container'] {\n width: 100%;\n padding: ", " ", ";\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n white-space: normal;\n overflow: hidden;\n max-height: 2.5rem;\n word-wrap: break-word;\n\n &:hover {\n background: ", ";\n border-radius: 3px;\n }\n }\n"])), "var(--ds-font-lineHeight-300, 16px)", "var(--ds-background-accent-gray-subtler, ".concat(N40, ")"), "var(--ds-space-050, 4px)", "var(--ds-space-100, 4px)", "var(--ds-space-050, 2px)", "var(--ds-background-input-hovered, #F7F8F9)");
@@ -0,0 +1,87 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
3
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
4
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
5
+ import { useCallback, useState } from 'react';
6
+ import { useBasicFilterAGG } from '../../../../services/useBasicFilterAGG';
7
+ import { mapFieldValuesToFilterOptions, mapFieldValuesToPageCursor, mapFieldValuesToTotalCount } from '../utils/transformers';
8
+ export var useFilterOptions = function useFilterOptions(_ref) {
9
+ var filterType = _ref.filterType,
10
+ cloudId = _ref.cloudId;
11
+ var _useState = useState([]),
12
+ _useState2 = _slicedToArray(_useState, 2),
13
+ filterOptions = _useState2[0],
14
+ setFilterOptions = _useState2[1];
15
+ var _useState3 = useState(0),
16
+ _useState4 = _slicedToArray(_useState3, 2),
17
+ totalCount = _useState4[0],
18
+ setTotalCount = _useState4[1];
19
+ var _useState5 = useState('empty'),
20
+ _useState6 = _slicedToArray(_useState5, 2),
21
+ status = _useState6[0],
22
+ setStatus = _useState6[1];
23
+ var _useState7 = useState(undefined),
24
+ _useState8 = _slicedToArray(_useState7, 2),
25
+ nextPageCursor = _useState8[0],
26
+ setNextPageCursor = _useState8[1];
27
+ var _useBasicFilterAGG = useBasicFilterAGG(),
28
+ getFieldValues = _useBasicFilterAGG.getFieldValues;
29
+ var fetchFilterOptions = useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
30
+ var _ref3,
31
+ pageCursor,
32
+ searchString,
33
+ response,
34
+ isNewSearch,
35
+ _args = arguments;
36
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
37
+ while (1) switch (_context.prev = _context.next) {
38
+ case 0:
39
+ _ref3 = _args.length > 0 && _args[0] !== undefined ? _args[0] : {}, pageCursor = _ref3.pageCursor, searchString = _ref3.searchString;
40
+ setStatus('loading');
41
+ _context.prev = 2;
42
+ _context.next = 5;
43
+ return getFieldValues({
44
+ cloudId: cloudId,
45
+ jql: '',
46
+ jqlTerm: filterType,
47
+ searchString: searchString,
48
+ pageCursor: pageCursor
49
+ });
50
+ case 5:
51
+ response = _context.sent;
52
+ if (!(response.errors && response.errors.length > 0)) {
53
+ _context.next = 9;
54
+ break;
55
+ }
56
+ setStatus('rejected');
57
+ return _context.abrupt("return");
58
+ case 9:
59
+ isNewSearch = !pageCursor;
60
+ if (isNewSearch) {
61
+ setFilterOptions(mapFieldValuesToFilterOptions(response));
62
+ } else {
63
+ setFilterOptions([].concat(_toConsumableArray(filterOptions), _toConsumableArray(mapFieldValuesToFilterOptions(response))));
64
+ }
65
+ setTotalCount(mapFieldValuesToTotalCount(response));
66
+ setNextPageCursor(mapFieldValuesToPageCursor(response));
67
+ setStatus('resolved');
68
+ _context.next = 19;
69
+ break;
70
+ case 16:
71
+ _context.prev = 16;
72
+ _context.t0 = _context["catch"](2);
73
+ setStatus('rejected');
74
+ case 19:
75
+ case "end":
76
+ return _context.stop();
77
+ }
78
+ }, _callee, null, [[2, 16]]);
79
+ })), [cloudId, filterOptions, filterType, getFieldValues]);
80
+ return {
81
+ filterOptions: filterOptions,
82
+ fetchFilterOptions: fetchFilterOptions,
83
+ totalCount: totalCount,
84
+ pageCursor: nextPageCursor,
85
+ status: status
86
+ };
87
+ };