@atlaskit/link-datasource 0.22.0 → 0.24.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 (37) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cjs/ui/issue-like-table/column-picker/index.js +8 -0
  3. package/dist/cjs/ui/jira-issues-modal/basic-search-input/index.js +12 -2
  4. package/dist/cjs/ui/jira-issues-modal/jira-search-container/index.js +4 -1
  5. package/dist/cjs/ui/jira-issues-modal/jql-editor/index.js +2 -0
  6. package/dist/cjs/ui/jira-issues-modal/modal/index.js +11 -9
  7. package/dist/cjs/ui/jira-issues-modal/modal/messages.js +11 -1
  8. package/dist/cjs/ui/table-footer/index.js +8 -7
  9. package/dist/cjs/ui/table-footer/messages.js +8 -3
  10. package/dist/cjs/version.json +1 -1
  11. package/dist/es2019/ui/issue-like-table/column-picker/index.js +6 -0
  12. package/dist/es2019/ui/jira-issues-modal/basic-search-input/index.js +12 -2
  13. package/dist/es2019/ui/jira-issues-modal/jira-search-container/index.js +3 -0
  14. package/dist/es2019/ui/jira-issues-modal/jql-editor/index.js +2 -0
  15. package/dist/es2019/ui/jira-issues-modal/modal/index.js +11 -9
  16. package/dist/es2019/ui/jira-issues-modal/modal/messages.js +11 -1
  17. package/dist/es2019/ui/table-footer/index.js +9 -8
  18. package/dist/es2019/ui/table-footer/messages.js +8 -3
  19. package/dist/es2019/version.json +1 -1
  20. package/dist/esm/ui/issue-like-table/column-picker/index.js +8 -0
  21. package/dist/esm/ui/jira-issues-modal/basic-search-input/index.js +12 -2
  22. package/dist/esm/ui/jira-issues-modal/jira-search-container/index.js +4 -1
  23. package/dist/esm/ui/jira-issues-modal/jql-editor/index.js +2 -0
  24. package/dist/esm/ui/jira-issues-modal/modal/index.js +11 -9
  25. package/dist/esm/ui/jira-issues-modal/modal/messages.js +11 -1
  26. package/dist/esm/ui/table-footer/index.js +9 -8
  27. package/dist/esm/ui/table-footer/messages.js +8 -3
  28. package/dist/esm/version.json +1 -1
  29. package/dist/types/ui/jira-issues-modal/jira-search-container/index.d.ts +1 -0
  30. package/dist/types/ui/jira-issues-modal/jql-editor/index.d.ts +1 -0
  31. package/dist/types/ui/jira-issues-modal/modal/messages.d.ts +10 -0
  32. package/dist/types/ui/table-footer/messages.d.ts +6 -1
  33. package/dist/types-ts4.5/ui/jira-issues-modal/jira-search-container/index.d.ts +1 -0
  34. package/dist/types-ts4.5/ui/jira-issues-modal/jql-editor/index.d.ts +1 -0
  35. package/dist/types-ts4.5/ui/jira-issues-modal/modal/messages.d.ts +10 -0
  36. package/dist/types-ts4.5/ui/table-footer/messages.d.ts +6 -1
  37. package/package.json +2 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @atlaskit/link-datasource
2
2
 
3
+ ## 0.24.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`108aa0ad121`](https://bitbucket.org/atlassian/atlassian-frontend/commits/108aa0ad121) - [ux] Fix some table bugs such as inconsistency between issue count for modal/table and fix case where user can deselect all fields in the column picker
8
+
9
+ ## 0.23.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [`62465d6399f`](https://bitbucket.org/atlassian/atlassian-frontend/commits/62465d6399f) - [ux] Adding loading spinner to search button and fixed initial search loading state in table
14
+
3
15
  ## 0.22.0
4
16
 
5
17
  ### Minor Changes
@@ -87,6 +87,13 @@ var ColumnPicker = function ColumnPicker(_ref) {
87
87
  onOpen && void onOpen();
88
88
  void sortSelectedColumnsTop();
89
89
  }, [onOpen, sortSelectedColumnsTop]);
90
+
91
+ // If only 1 option is selected, disable it since we don't want user to uncheck everything
92
+ var handleIsOptionDisabled = function handleIsOptionDisabled(option, selectValue) {
93
+ return selectValue.length === 1 && selectValue.some(function (selectedValue) {
94
+ return selectedValue.value === option.value;
95
+ });
96
+ };
90
97
  return (0, _react2.jsx)(_select.PopupSelect, {
91
98
  classNamePrefix: 'column-picker-popup',
92
99
  testId: 'column-picker-popup',
@@ -99,6 +106,7 @@ var ColumnPicker = function ColumnPicker(_ref) {
99
106
  closeMenuOnSelect: false,
100
107
  hideSelectedOptions: false,
101
108
  isMulti: true,
109
+ isOptionDisabled: handleIsOptionDisabled,
102
110
  placeholder: intl.formatMessage(_messages.columnPickerMessages.search),
103
111
  onKeyDown: stopEscapePropagationWhenOpen,
104
112
  "aria-label": "Search for fields",
@@ -16,6 +16,9 @@ var _messages = require("./messages");
16
16
  var searchButtonStyles = (0, _react.css)({
17
17
  marginRight: "var(--ds-space-075, 6px)"
18
18
  });
19
+ var formStyles = (0, _react.css)({
20
+ flex: 1
21
+ });
19
22
  var BasicSearchInput = function BasicSearchInput(_ref) {
20
23
  var isDisabled = _ref.isDisabled,
21
24
  isSearching = _ref.isSearching,
@@ -26,7 +29,14 @@ var BasicSearchInput = function BasicSearchInput(_ref) {
26
29
  testId = _ref$testId === void 0 ? 'jira-jql-datasource-modal--basic-search-input' : _ref$testId;
27
30
  var _useIntl = (0, _reactIntlNext.useIntl)(),
28
31
  formatMessage = _useIntl.formatMessage;
29
- return (0, _react.jsx)(_textfield.default, {
32
+ var handleFormSubmit = function handleFormSubmit(e) {
33
+ e.preventDefault();
34
+ onSearch(searchTerm);
35
+ };
36
+ return (0, _react.jsx)("form", {
37
+ css: formStyles,
38
+ onSubmit: handleFormSubmit
39
+ }, (0, _react.jsx)(_textfield.default, {
30
40
  elemAfterInput: (0, _react.jsx)(_button.LoadingButton, {
31
41
  appearance: "primary",
32
42
  css: searchButtonStyles,
@@ -47,6 +57,6 @@ var BasicSearchInput = function BasicSearchInput(_ref) {
47
57
  placeholder: formatMessage(_messages.basicSearchInputMessages.basicTextSearchLabel),
48
58
  testId: testId,
49
59
  value: searchTerm
50
- });
60
+ }));
51
61
  };
52
62
  exports.BasicSearchInput = BasicSearchInput;
@@ -27,7 +27,8 @@ var inputContainerStyles = (0, _react2.css)({
27
27
  });
28
28
  var DEFAULT_JQL_QUERY = 'created >= -30d order by created DESC';
29
29
  var JiraSearchContainer = function JiraSearchContainer(props) {
30
- var parameters = props.parameters,
30
+ var isSearching = props.isSearching,
31
+ parameters = props.parameters,
31
32
  onSearch = props.onSearch;
32
33
  var _ref = parameters || {},
33
34
  cloudId = _ref.cloudId,
@@ -93,11 +94,13 @@ var JiraSearchContainer = function JiraSearchContainer(props) {
93
94
  return (0, _react2.jsx)("div", {
94
95
  css: inputContainerStyles
95
96
  }, currentSearchMode === basicModeValue && (0, _react2.jsx)(_basicSearchInput.BasicSearchInput, {
97
+ isSearching: isSearching,
96
98
  onChange: handleBasicSearchChange,
97
99
  onSearch: handleSearch,
98
100
  searchTerm: basicSearchTerm
99
101
  }), currentSearchMode === jqlModeValue && (0, _react2.jsx)(_jqlEditor.JiraJQLEditor, {
100
102
  cloudId: cloudId || '',
103
+ isSearching: isSearching,
101
104
  onChange: onQueryChange,
102
105
  onSearch: handleSearch,
103
106
  query: jql
@@ -14,6 +14,7 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
14
14
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
15
15
  var JiraJQLEditor = function JiraJQLEditor(props) {
16
16
  var cloudId = props.cloudId,
17
+ isSearching = props.isSearching,
17
18
  onChange = props.onChange,
18
19
  onSearch = props.onSearch,
19
20
  query = props.query;
@@ -34,6 +35,7 @@ var JiraJQLEditor = function JiraJQLEditor(props) {
34
35
  autocompleteProvider: autocompleteProvider,
35
36
  onSearch: onSearch,
36
37
  onUpdate: onChange,
38
+ isSearching: isSearching,
37
39
  inputRef: inputRef,
38
40
  query: query
39
41
  });
@@ -236,15 +236,16 @@ var JiraIssuesConfigModal = function JiraIssuesConfigModal(props) {
236
236
  }
237
237
  }, [jql, selectedJiraSite === null || selectedJiraSite === void 0 ? void 0 : selectedJiraSite.url, status]);
238
238
  var renderIssuesModeContent = (0, _react.useCallback)(function () {
239
- if (status === 'empty') {
240
- return (0, _react2.jsx)(_issueLikeTable.EmptyState, {
241
- testId: "jira-jql-datasource-modal--empty-state"
239
+ if (status === 'rejected' && jqlUrl) {
240
+ return (0, _react2.jsx)(_modalLoadingError.ModalLoadingError, {
241
+ url: jqlUrl
242
242
  });
243
243
  } else if (resolvedWithNoResults) {
244
244
  return (0, _react2.jsx)(_noResults.NoResults, null);
245
- } else if (status === 'rejected' && jqlUrl) {
246
- return (0, _react2.jsx)(_modalLoadingError.ModalLoadingError, {
247
- url: jqlUrl
245
+ // persist the empty state when making the initial /data request which contains the columns
246
+ } else if (status === 'empty' || !columns.length) {
247
+ return (0, _react2.jsx)(_issueLikeTable.EmptyState, {
248
+ testId: "jira-jql-datasource-modal--empty-state"
248
249
  });
249
250
  }
250
251
  var firstIssueUrl = retrieveUrlForSmartCardRender();
@@ -256,7 +257,7 @@ var JiraIssuesConfigModal = function JiraIssuesConfigModal(props) {
256
257
  }));
257
258
  }
258
259
  return issueLikeDataTableView;
259
- }, [issueLikeDataTableView, jqlUrl, responseItems.length, resolvedWithNoResults, retrieveUrlForSmartCardRender, status]);
260
+ }, [status, columns.length, resolvedWithNoResults, jqlUrl, retrieveUrlForSmartCardRender, responseItems.length, issueLikeDataTableView]);
260
261
  return (0, _react2.jsx)(_reactIntlNext.IntlProvider, {
261
262
  locale: "en"
262
263
  }, (0, _react2.jsx)(_modalDialog.ModalTransition, null, (0, _react2.jsx)(_modalDialog.default, {
@@ -287,6 +288,7 @@ var JiraIssuesConfigModal = function JiraIssuesConfigModal(props) {
287
288
  onOptionValueChange: handleViewModeChange,
288
289
  selectedOptionValue: currentViewMode
289
290
  })), (0, _react2.jsx)(_modalDialog.ModalBody, null, (0, _react2.jsx)(_jiraSearchContainer.JiraSearchContainer, {
291
+ isSearching: status === 'loading',
290
292
  parameters: parameters,
291
293
  onSearch: onSearch
292
294
  }), (0, _react2.jsx)("div", {
@@ -297,8 +299,8 @@ var JiraIssuesConfigModal = function JiraIssuesConfigModal(props) {
297
299
  }, (0, _react2.jsx)(_reactIntlNext.FormattedNumber, {
298
300
  value: totalCount
299
301
  }), ' ', (0, _react2.jsx)(_reactIntlNext.FormattedPlural, {
300
- one: "issue",
301
- other: "issues",
302
+ one: (0, _react2.jsx)(_reactIntlNext.FormattedMessage, _messages.modalMessages.singularIssue),
303
+ other: (0, _react2.jsx)(_reactIntlNext.FormattedMessage, _messages.modalMessages.pluralIssues),
302
304
  value: totalCount
303
305
  })), (0, _react2.jsx)(_standardButton.default, {
304
306
  appearance: "default",
@@ -37,9 +37,19 @@ var modalMessages = (0, _reactIntlNext.defineMessages)({
37
37
  defaultMessage: 'Count view'
38
38
  },
39
39
  issuesCountSmartCardPlaceholderText: {
40
- id: 'linkDataSource.jira-issues.configmodal.issues',
40
+ id: 'linkDataSource.jira-issues.configmodal.placeholder.issues',
41
41
  description: 'Placeholder text that will be placed next to a count of jira issues',
42
42
  defaultMessage: '### Issues'
43
+ },
44
+ singularIssue: {
45
+ id: 'linkDataSource.jira-issues.configmodal.singular.issue',
46
+ description: 'Text that appears after single issue count number.',
47
+ defaultMessage: 'issue'
48
+ },
49
+ pluralIssues: {
50
+ id: 'linkDataSource.jira-issues.configmodal.plural.issues',
51
+ description: 'Text that appears after plural issue count number.',
52
+ defaultMessage: 'issues'
43
53
  }
44
54
  });
45
55
  exports.modalMessages = modalMessages;
@@ -5,7 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.TableFooter = void 0;
8
- var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
9
8
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
9
  var _taggedTemplateLiteral2 = _interopRequireDefault(require("@babel/runtime/helpers/taggedTemplateLiteral"));
11
10
  var _react = require("react");
@@ -46,12 +45,14 @@ var TableFooter = function TableFooter(_ref) {
46
45
  "data-testid": "table-footer"
47
46
  }, (0, _react2.jsx)(IssueCounterWrapper, null, showIssueCount && (0, _react2.jsx)(_heading.default, {
48
47
  testId: "issue-count",
49
- level: 'h400'
50
- }, (0, _react2.jsx)(_reactIntlNext.FormattedMessage, (0, _extends2.default)({}, _messages.footerMessages.issueText, {
51
- values: {
52
- issueCount: issueCount
53
- }
54
- })))), (0, _react2.jsx)(SyncWrapper, null, onRefresh && (0, _react2.jsx)(_react.Fragment, null, (0, _react2.jsx)(SyncTextWrapper, {
48
+ level: "h400"
49
+ }, (0, _react2.jsx)(_reactIntlNext.FormattedNumber, {
50
+ value: issueCount
51
+ }), ' ', (0, _react2.jsx)(_reactIntlNext.FormattedPlural, {
52
+ one: (0, _react2.jsx)(_reactIntlNext.FormattedMessage, _messages.footerMessages.singularIssue),
53
+ other: (0, _react2.jsx)(_reactIntlNext.FormattedMessage, _messages.footerMessages.pluralIssues),
54
+ value: issueCount
55
+ }))), (0, _react2.jsx)(SyncWrapper, null, onRefresh && (0, _react2.jsx)(_react.Fragment, null, (0, _react2.jsx)(SyncTextWrapper, {
55
56
  "data-testid": "sync-text"
56
57
  }, isLoading ? (0, _react2.jsx)(_reactIntlNext.FormattedMessage, _messages.footerMessages.loadingText) : (0, _react2.jsx)(_syncInfo.SyncInfo, {
57
58
  lastSyncTime: lastSyncTime
@@ -6,10 +6,15 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.footerMessages = void 0;
7
7
  var _reactIntlNext = require("react-intl-next");
8
8
  var footerMessages = (0, _reactIntlNext.defineMessages)({
9
- issueText: {
9
+ singularIssue: {
10
10
  id: 'linkDataSource.table-footer.issue',
11
- description: 'Text that appears after issue count number if there is only 1 issue.',
12
- defaultMessage: '{issueCount} {issueCount, plural, one {issue} other {issues}}'
11
+ description: 'Text that appears after single issue count number.',
12
+ defaultMessage: 'issue'
13
+ },
14
+ pluralIssues: {
15
+ id: 'linkDataSource.table-footer.issues',
16
+ description: 'Text that appears after plural issue count number.',
17
+ defaultMessage: 'issues'
13
18
  },
14
19
  loadingText: {
15
20
  id: 'linkDataSource.table-footer.loading',
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/link-datasource",
3
- "version": "0.22.0",
3
+ "version": "0.24.0",
4
4
  "sideEffects": false
5
5
  }
@@ -64,6 +64,11 @@ export const ColumnPicker = ({
64
64
  onOpen && void onOpen();
65
65
  void sortSelectedColumnsTop();
66
66
  }, [onOpen, sortSelectedColumnsTop]);
67
+
68
+ // If only 1 option is selected, disable it since we don't want user to uncheck everything
69
+ const handleIsOptionDisabled = (option, selectValue) => {
70
+ return selectValue.length === 1 && selectValue.some(selectedValue => selectedValue.value === option.value);
71
+ };
67
72
  return jsx(PopupSelect, {
68
73
  classNamePrefix: 'column-picker-popup',
69
74
  testId: 'column-picker-popup',
@@ -76,6 +81,7 @@ export const ColumnPicker = ({
76
81
  closeMenuOnSelect: false,
77
82
  hideSelectedOptions: false,
78
83
  isMulti: true,
84
+ isOptionDisabled: handleIsOptionDisabled,
79
85
  placeholder: intl.formatMessage(columnPickerMessages.search),
80
86
  onKeyDown: stopEscapePropagationWhenOpen,
81
87
  "aria-label": "Search for fields",
@@ -8,6 +8,9 @@ import { basicSearchInputMessages } from './messages';
8
8
  const searchButtonStyles = css({
9
9
  marginRight: "var(--ds-space-075, 6px)"
10
10
  });
11
+ const formStyles = css({
12
+ flex: 1
13
+ });
11
14
  export const BasicSearchInput = ({
12
15
  isDisabled,
13
16
  isSearching,
@@ -19,7 +22,14 @@ export const BasicSearchInput = ({
19
22
  const {
20
23
  formatMessage
21
24
  } = useIntl();
22
- return jsx(Textfield, {
25
+ const handleFormSubmit = e => {
26
+ e.preventDefault();
27
+ onSearch(searchTerm);
28
+ };
29
+ return jsx("form", {
30
+ css: formStyles,
31
+ onSubmit: handleFormSubmit
32
+ }, jsx(Textfield, {
23
33
  elemAfterInput: jsx(LoadingButton, {
24
34
  appearance: "primary",
25
35
  css: searchButtonStyles,
@@ -38,5 +48,5 @@ export const BasicSearchInput = ({
38
48
  placeholder: formatMessage(basicSearchInputMessages.basicTextSearchLabel),
39
49
  testId: testId,
40
50
  value: searchTerm
41
- });
51
+ }));
42
52
  };
@@ -16,6 +16,7 @@ const inputContainerStyles = css({
16
16
  const DEFAULT_JQL_QUERY = 'created >= -30d order by created DESC';
17
17
  export const JiraSearchContainer = props => {
18
18
  const {
19
+ isSearching,
19
20
  parameters,
20
21
  onSearch
21
22
  } = props;
@@ -68,11 +69,13 @@ export const JiraSearchContainer = props => {
68
69
  return jsx("div", {
69
70
  css: inputContainerStyles
70
71
  }, currentSearchMode === basicModeValue && jsx(BasicSearchInput, {
72
+ isSearching: isSearching,
71
73
  onChange: handleBasicSearchChange,
72
74
  onSearch: handleSearch,
73
75
  searchTerm: basicSearchTerm
74
76
  }), currentSearchMode === jqlModeValue && jsx(JiraJQLEditor, {
75
77
  cloudId: cloudId || '',
78
+ isSearching: isSearching,
76
79
  onChange: onQueryChange,
77
80
  onSearch: handleSearch,
78
81
  query: jql
@@ -6,6 +6,7 @@ import { makeGetJqlSuggestionsData } from '../../../services/makeGetJqlSuggestio
6
6
  export const JiraJQLEditor = props => {
7
7
  const {
8
8
  cloudId,
9
+ isSearching,
9
10
  onChange,
10
11
  onSearch,
11
12
  query
@@ -27,6 +28,7 @@ export const JiraJQLEditor = props => {
27
28
  autocompleteProvider: autocompleteProvider,
28
29
  onSearch: onSearch,
29
30
  onUpdate: onChange,
31
+ isSearching: isSearching,
30
32
  inputRef: inputRef,
31
33
  query: query
32
34
  });
@@ -185,15 +185,16 @@ export const JiraIssuesConfigModal = props => {
185
185
  }
186
186
  }, [jql, selectedJiraSite === null || selectedJiraSite === void 0 ? void 0 : selectedJiraSite.url, status]);
187
187
  const renderIssuesModeContent = useCallback(() => {
188
- if (status === 'empty') {
189
- return jsx(EmptyState, {
190
- testId: `jira-jql-datasource-modal--empty-state`
188
+ if (status === 'rejected' && jqlUrl) {
189
+ return jsx(ModalLoadingError, {
190
+ url: jqlUrl
191
191
  });
192
192
  } else if (resolvedWithNoResults) {
193
193
  return jsx(NoResults, null);
194
- } else if (status === 'rejected' && jqlUrl) {
195
- return jsx(ModalLoadingError, {
196
- url: jqlUrl
194
+ // persist the empty state when making the initial /data request which contains the columns
195
+ } else if (status === 'empty' || !columns.length) {
196
+ return jsx(EmptyState, {
197
+ testId: `jira-jql-datasource-modal--empty-state`
197
198
  });
198
199
  }
199
200
  const firstIssueUrl = retrieveUrlForSmartCardRender();
@@ -205,7 +206,7 @@ export const JiraIssuesConfigModal = props => {
205
206
  }));
206
207
  }
207
208
  return issueLikeDataTableView;
208
- }, [issueLikeDataTableView, jqlUrl, responseItems.length, resolvedWithNoResults, retrieveUrlForSmartCardRender, status]);
209
+ }, [status, columns.length, resolvedWithNoResults, jqlUrl, retrieveUrlForSmartCardRender, responseItems.length, issueLikeDataTableView]);
209
210
  return jsx(IntlProvider, {
210
211
  locale: "en"
211
212
  }, jsx(ModalTransition, null, jsx(Modal, {
@@ -236,6 +237,7 @@ export const JiraIssuesConfigModal = props => {
236
237
  onOptionValueChange: handleViewModeChange,
237
238
  selectedOptionValue: currentViewMode
238
239
  })), jsx(ModalBody, null, jsx(JiraSearchContainer, {
240
+ isSearching: status === 'loading',
239
241
  parameters: parameters,
240
242
  onSearch: onSearch
241
243
  }), jsx("div", {
@@ -246,8 +248,8 @@ export const JiraIssuesConfigModal = props => {
246
248
  }, jsx(FormattedNumber, {
247
249
  value: totalCount
248
250
  }), ' ', jsx(FormattedPlural, {
249
- one: "issue",
250
- other: "issues",
251
+ one: jsx(FormattedMessage, modalMessages.singularIssue),
252
+ other: jsx(FormattedMessage, modalMessages.pluralIssues),
251
253
  value: totalCount
252
254
  })), jsx(Button, {
253
255
  appearance: "default",
@@ -31,8 +31,18 @@ export const modalMessages = defineMessages({
31
31
  defaultMessage: 'Count view'
32
32
  },
33
33
  issuesCountSmartCardPlaceholderText: {
34
- id: 'linkDataSource.jira-issues.configmodal.issues',
34
+ id: 'linkDataSource.jira-issues.configmodal.placeholder.issues',
35
35
  description: 'Placeholder text that will be placed next to a count of jira issues',
36
36
  defaultMessage: '### Issues'
37
+ },
38
+ singularIssue: {
39
+ id: 'linkDataSource.jira-issues.configmodal.singular.issue',
40
+ description: 'Text that appears after single issue count number.',
41
+ defaultMessage: 'issue'
42
+ },
43
+ pluralIssues: {
44
+ id: 'linkDataSource.jira-issues.configmodal.plural.issues',
45
+ description: 'Text that appears after plural issue count number.',
46
+ defaultMessage: 'issues'
37
47
  }
38
48
  });
@@ -1,9 +1,8 @@
1
- import _extends from "@babel/runtime/helpers/extends";
2
1
  /** @jsx jsx */
3
2
  import { Fragment, useEffect, useState } from 'react';
4
3
  import { jsx } from '@emotion/react';
5
4
  import styled from '@emotion/styled';
6
- import { FormattedMessage, useIntl } from 'react-intl-next';
5
+ import { FormattedMessage, FormattedNumber, FormattedPlural, useIntl } from 'react-intl-next';
7
6
  import Button from '@atlaskit/button';
8
7
  import Heading from '@atlaskit/heading';
9
8
  import RefreshIcon from '@atlaskit/icon/glyph/refresh';
@@ -57,12 +56,14 @@ export const TableFooter = ({
57
56
  "data-testid": "table-footer"
58
57
  }, jsx(IssueCounterWrapper, null, showIssueCount && jsx(Heading, {
59
58
  testId: "issue-count",
60
- level: 'h400'
61
- }, jsx(FormattedMessage, _extends({}, footerMessages.issueText, {
62
- values: {
63
- issueCount
64
- }
65
- })))), jsx(SyncWrapper, null, onRefresh && jsx(Fragment, null, jsx(SyncTextWrapper, {
59
+ level: "h400"
60
+ }, jsx(FormattedNumber, {
61
+ value: issueCount
62
+ }), ' ', jsx(FormattedPlural, {
63
+ one: jsx(FormattedMessage, footerMessages.singularIssue),
64
+ other: jsx(FormattedMessage, footerMessages.pluralIssues),
65
+ value: issueCount
66
+ }))), jsx(SyncWrapper, null, onRefresh && jsx(Fragment, null, jsx(SyncTextWrapper, {
66
67
  "data-testid": "sync-text"
67
68
  }, isLoading ? jsx(FormattedMessage, footerMessages.loadingText) : jsx(SyncInfo, {
68
69
  lastSyncTime: lastSyncTime
@@ -1,9 +1,14 @@
1
1
  import { defineMessages } from 'react-intl-next';
2
2
  export const footerMessages = defineMessages({
3
- issueText: {
3
+ singularIssue: {
4
4
  id: 'linkDataSource.table-footer.issue',
5
- description: 'Text that appears after issue count number if there is only 1 issue.',
6
- defaultMessage: '{issueCount} {issueCount, plural, one {issue} other {issues}}'
5
+ description: 'Text that appears after single issue count number.',
6
+ defaultMessage: 'issue'
7
+ },
8
+ pluralIssues: {
9
+ id: 'linkDataSource.table-footer.issues',
10
+ description: 'Text that appears after plural issue count number.',
11
+ defaultMessage: 'issues'
7
12
  },
8
13
  loadingText: {
9
14
  id: 'linkDataSource.table-footer.loading',
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/link-datasource",
3
- "version": "0.22.0",
3
+ "version": "0.24.0",
4
4
  "sideEffects": false
5
5
  }
@@ -80,6 +80,13 @@ export var ColumnPicker = function ColumnPicker(_ref) {
80
80
  onOpen && void onOpen();
81
81
  void sortSelectedColumnsTop();
82
82
  }, [onOpen, sortSelectedColumnsTop]);
83
+
84
+ // If only 1 option is selected, disable it since we don't want user to uncheck everything
85
+ var handleIsOptionDisabled = function handleIsOptionDisabled(option, selectValue) {
86
+ return selectValue.length === 1 && selectValue.some(function (selectedValue) {
87
+ return selectedValue.value === option.value;
88
+ });
89
+ };
83
90
  return jsx(PopupSelect, {
84
91
  classNamePrefix: 'column-picker-popup',
85
92
  testId: 'column-picker-popup',
@@ -92,6 +99,7 @@ export var ColumnPicker = function ColumnPicker(_ref) {
92
99
  closeMenuOnSelect: false,
93
100
  hideSelectedOptions: false,
94
101
  isMulti: true,
102
+ isOptionDisabled: handleIsOptionDisabled,
95
103
  placeholder: intl.formatMessage(columnPickerMessages.search),
96
104
  onKeyDown: stopEscapePropagationWhenOpen,
97
105
  "aria-label": "Search for fields",
@@ -8,6 +8,9 @@ import { basicSearchInputMessages } from './messages';
8
8
  var searchButtonStyles = css({
9
9
  marginRight: "var(--ds-space-075, 6px)"
10
10
  });
11
+ var formStyles = css({
12
+ flex: 1
13
+ });
11
14
  export var BasicSearchInput = function BasicSearchInput(_ref) {
12
15
  var isDisabled = _ref.isDisabled,
13
16
  isSearching = _ref.isSearching,
@@ -18,7 +21,14 @@ export var BasicSearchInput = function BasicSearchInput(_ref) {
18
21
  testId = _ref$testId === void 0 ? 'jira-jql-datasource-modal--basic-search-input' : _ref$testId;
19
22
  var _useIntl = useIntl(),
20
23
  formatMessage = _useIntl.formatMessage;
21
- return jsx(Textfield, {
24
+ var handleFormSubmit = function handleFormSubmit(e) {
25
+ e.preventDefault();
26
+ onSearch(searchTerm);
27
+ };
28
+ return jsx("form", {
29
+ css: formStyles,
30
+ onSubmit: handleFormSubmit
31
+ }, jsx(Textfield, {
22
32
  elemAfterInput: jsx(LoadingButton, {
23
33
  appearance: "primary",
24
34
  css: searchButtonStyles,
@@ -39,5 +49,5 @@ export var BasicSearchInput = function BasicSearchInput(_ref) {
39
49
  placeholder: formatMessage(basicSearchInputMessages.basicTextSearchLabel),
40
50
  testId: testId,
41
51
  value: searchTerm
42
- });
52
+ }));
43
53
  };
@@ -16,7 +16,8 @@ var inputContainerStyles = css({
16
16
  });
17
17
  var DEFAULT_JQL_QUERY = 'created >= -30d order by created DESC';
18
18
  export var JiraSearchContainer = function JiraSearchContainer(props) {
19
- var parameters = props.parameters,
19
+ var isSearching = props.isSearching,
20
+ parameters = props.parameters,
20
21
  onSearch = props.onSearch;
21
22
  var _ref = parameters || {},
22
23
  cloudId = _ref.cloudId,
@@ -82,11 +83,13 @@ export var JiraSearchContainer = function JiraSearchContainer(props) {
82
83
  return jsx("div", {
83
84
  css: inputContainerStyles
84
85
  }, currentSearchMode === basicModeValue && jsx(BasicSearchInput, {
86
+ isSearching: isSearching,
85
87
  onChange: handleBasicSearchChange,
86
88
  onSearch: handleSearch,
87
89
  searchTerm: basicSearchTerm
88
90
  }), currentSearchMode === jqlModeValue && jsx(JiraJQLEditor, {
89
91
  cloudId: cloudId || '',
92
+ isSearching: isSearching,
90
93
  onChange: onQueryChange,
91
94
  onSearch: handleSearch,
92
95
  query: jql
@@ -5,6 +5,7 @@ import { makeGetJqlAutocompleteData } from '../../../services/makeGetJqlAutocomp
5
5
  import { makeGetJqlSuggestionsData } from '../../../services/makeGetJqlSuggestionsData';
6
6
  export var JiraJQLEditor = function JiraJQLEditor(props) {
7
7
  var cloudId = props.cloudId,
8
+ isSearching = props.isSearching,
8
9
  onChange = props.onChange,
9
10
  onSearch = props.onSearch,
10
11
  query = props.query;
@@ -25,6 +26,7 @@ export var JiraJQLEditor = function JiraJQLEditor(props) {
25
26
  autocompleteProvider: autocompleteProvider,
26
27
  onSearch: onSearch,
27
28
  onUpdate: onChange,
29
+ isSearching: isSearching,
28
30
  inputRef: inputRef,
29
31
  query: query
30
32
  });
@@ -225,15 +225,16 @@ export var JiraIssuesConfigModal = function JiraIssuesConfigModal(props) {
225
225
  }
226
226
  }, [jql, selectedJiraSite === null || selectedJiraSite === void 0 ? void 0 : selectedJiraSite.url, status]);
227
227
  var renderIssuesModeContent = useCallback(function () {
228
- if (status === 'empty') {
229
- return jsx(EmptyState, {
230
- testId: "jira-jql-datasource-modal--empty-state"
228
+ if (status === 'rejected' && jqlUrl) {
229
+ return jsx(ModalLoadingError, {
230
+ url: jqlUrl
231
231
  });
232
232
  } else if (resolvedWithNoResults) {
233
233
  return jsx(NoResults, null);
234
- } else if (status === 'rejected' && jqlUrl) {
235
- return jsx(ModalLoadingError, {
236
- url: jqlUrl
234
+ // persist the empty state when making the initial /data request which contains the columns
235
+ } else if (status === 'empty' || !columns.length) {
236
+ return jsx(EmptyState, {
237
+ testId: "jira-jql-datasource-modal--empty-state"
237
238
  });
238
239
  }
239
240
  var firstIssueUrl = retrieveUrlForSmartCardRender();
@@ -245,7 +246,7 @@ export var JiraIssuesConfigModal = function JiraIssuesConfigModal(props) {
245
246
  }));
246
247
  }
247
248
  return issueLikeDataTableView;
248
- }, [issueLikeDataTableView, jqlUrl, responseItems.length, resolvedWithNoResults, retrieveUrlForSmartCardRender, status]);
249
+ }, [status, columns.length, resolvedWithNoResults, jqlUrl, retrieveUrlForSmartCardRender, responseItems.length, issueLikeDataTableView]);
249
250
  return jsx(IntlProvider, {
250
251
  locale: "en"
251
252
  }, jsx(ModalTransition, null, jsx(Modal, {
@@ -276,6 +277,7 @@ export var JiraIssuesConfigModal = function JiraIssuesConfigModal(props) {
276
277
  onOptionValueChange: handleViewModeChange,
277
278
  selectedOptionValue: currentViewMode
278
279
  })), jsx(ModalBody, null, jsx(JiraSearchContainer, {
280
+ isSearching: status === 'loading',
279
281
  parameters: parameters,
280
282
  onSearch: onSearch
281
283
  }), jsx("div", {
@@ -286,8 +288,8 @@ export var JiraIssuesConfigModal = function JiraIssuesConfigModal(props) {
286
288
  }, jsx(FormattedNumber, {
287
289
  value: totalCount
288
290
  }), ' ', jsx(FormattedPlural, {
289
- one: "issue",
290
- other: "issues",
291
+ one: jsx(FormattedMessage, modalMessages.singularIssue),
292
+ other: jsx(FormattedMessage, modalMessages.pluralIssues),
291
293
  value: totalCount
292
294
  })), jsx(Button, {
293
295
  appearance: "default",
@@ -31,8 +31,18 @@ export var modalMessages = defineMessages({
31
31
  defaultMessage: 'Count view'
32
32
  },
33
33
  issuesCountSmartCardPlaceholderText: {
34
- id: 'linkDataSource.jira-issues.configmodal.issues',
34
+ id: 'linkDataSource.jira-issues.configmodal.placeholder.issues',
35
35
  description: 'Placeholder text that will be placed next to a count of jira issues',
36
36
  defaultMessage: '### Issues'
37
+ },
38
+ singularIssue: {
39
+ id: 'linkDataSource.jira-issues.configmodal.singular.issue',
40
+ description: 'Text that appears after single issue count number.',
41
+ defaultMessage: 'issue'
42
+ },
43
+ pluralIssues: {
44
+ id: 'linkDataSource.jira-issues.configmodal.plural.issues',
45
+ description: 'Text that appears after plural issue count number.',
46
+ defaultMessage: 'issues'
37
47
  }
38
48
  });
@@ -1,4 +1,3 @@
1
- import _extends from "@babel/runtime/helpers/extends";
2
1
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
2
  import _taggedTemplateLiteral from "@babel/runtime/helpers/taggedTemplateLiteral";
4
3
  var _templateObject, _templateObject2, _templateObject3, _templateObject4;
@@ -6,7 +5,7 @@ var _templateObject, _templateObject2, _templateObject3, _templateObject4;
6
5
  import { Fragment, useEffect, useState } from 'react';
7
6
  import { jsx } from '@emotion/react';
8
7
  import styled from '@emotion/styled';
9
- import { FormattedMessage, useIntl } from 'react-intl-next';
8
+ import { FormattedMessage, FormattedNumber, FormattedPlural, useIntl } from 'react-intl-next';
10
9
  import Button from '@atlaskit/button';
11
10
  import Heading from '@atlaskit/heading';
12
11
  import RefreshIcon from '@atlaskit/icon/glyph/refresh';
@@ -39,12 +38,14 @@ export var TableFooter = function TableFooter(_ref) {
39
38
  "data-testid": "table-footer"
40
39
  }, jsx(IssueCounterWrapper, null, showIssueCount && jsx(Heading, {
41
40
  testId: "issue-count",
42
- level: 'h400'
43
- }, jsx(FormattedMessage, _extends({}, footerMessages.issueText, {
44
- values: {
45
- issueCount: issueCount
46
- }
47
- })))), jsx(SyncWrapper, null, onRefresh && jsx(Fragment, null, jsx(SyncTextWrapper, {
41
+ level: "h400"
42
+ }, jsx(FormattedNumber, {
43
+ value: issueCount
44
+ }), ' ', jsx(FormattedPlural, {
45
+ one: jsx(FormattedMessage, footerMessages.singularIssue),
46
+ other: jsx(FormattedMessage, footerMessages.pluralIssues),
47
+ value: issueCount
48
+ }))), jsx(SyncWrapper, null, onRefresh && jsx(Fragment, null, jsx(SyncTextWrapper, {
48
49
  "data-testid": "sync-text"
49
50
  }, isLoading ? jsx(FormattedMessage, footerMessages.loadingText) : jsx(SyncInfo, {
50
51
  lastSyncTime: lastSyncTime
@@ -1,9 +1,14 @@
1
1
  import { defineMessages } from 'react-intl-next';
2
2
  export var footerMessages = defineMessages({
3
- issueText: {
3
+ singularIssue: {
4
4
  id: 'linkDataSource.table-footer.issue',
5
- description: 'Text that appears after issue count number if there is only 1 issue.',
6
- defaultMessage: '{issueCount} {issueCount, plural, one {issue} other {issues}}'
5
+ description: 'Text that appears after single issue count number.',
6
+ defaultMessage: 'issue'
7
+ },
8
+ pluralIssues: {
9
+ id: 'linkDataSource.table-footer.issues',
10
+ description: 'Text that appears after plural issue count number.',
11
+ defaultMessage: 'issues'
7
12
  },
8
13
  loadingText: {
9
14
  id: 'linkDataSource.table-footer.loading',
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/link-datasource",
3
- "version": "0.22.0",
3
+ "version": "0.24.0",
4
4
  "sideEffects": false
5
5
  }
@@ -1,6 +1,7 @@
1
1
  import { jsx } from '@emotion/react';
2
2
  import { JiraIssueDatasourceParameters, JiraIssueDatasourceParametersQuery } from '../types';
3
3
  export interface SearchContainerProps {
4
+ isSearching?: boolean;
4
5
  onSearch: (query: JiraIssueDatasourceParametersQuery) => void;
5
6
  parameters?: JiraIssueDatasourceParameters;
6
7
  }
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  export interface JiraJQLEditorProps {
3
3
  cloudId: string;
4
+ isSearching?: boolean;
4
5
  onChange?: (query: string) => void;
5
6
  onSearch: (query: string) => void;
6
7
  query: string;
@@ -34,4 +34,14 @@ export declare const modalMessages: {
34
34
  description: string;
35
35
  defaultMessage: string;
36
36
  };
37
+ singularIssue: {
38
+ id: string;
39
+ description: string;
40
+ defaultMessage: string;
41
+ };
42
+ pluralIssues: {
43
+ id: string;
44
+ description: string;
45
+ defaultMessage: string;
46
+ };
37
47
  };
@@ -1,5 +1,10 @@
1
1
  export declare const footerMessages: {
2
- issueText: {
2
+ singularIssue: {
3
+ id: string;
4
+ description: string;
5
+ defaultMessage: string;
6
+ };
7
+ pluralIssues: {
3
8
  id: string;
4
9
  description: string;
5
10
  defaultMessage: string;
@@ -1,6 +1,7 @@
1
1
  import { jsx } from '@emotion/react';
2
2
  import { JiraIssueDatasourceParameters, JiraIssueDatasourceParametersQuery } from '../types';
3
3
  export interface SearchContainerProps {
4
+ isSearching?: boolean;
4
5
  onSearch: (query: JiraIssueDatasourceParametersQuery) => void;
5
6
  parameters?: JiraIssueDatasourceParameters;
6
7
  }
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  export interface JiraJQLEditorProps {
3
3
  cloudId: string;
4
+ isSearching?: boolean;
4
5
  onChange?: (query: string) => void;
5
6
  onSearch: (query: string) => void;
6
7
  query: string;
@@ -34,4 +34,14 @@ export declare const modalMessages: {
34
34
  description: string;
35
35
  defaultMessage: string;
36
36
  };
37
+ singularIssue: {
38
+ id: string;
39
+ description: string;
40
+ defaultMessage: string;
41
+ };
42
+ pluralIssues: {
43
+ id: string;
44
+ description: string;
45
+ defaultMessage: string;
46
+ };
37
47
  };
@@ -1,5 +1,10 @@
1
1
  export declare const footerMessages: {
2
- issueText: {
2
+ singularIssue: {
3
+ id: string;
4
+ description: string;
5
+ defaultMessage: string;
6
+ };
7
+ pluralIssues: {
3
8
  id: string;
4
9
  description: string;
5
10
  defaultMessage: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/link-datasource",
3
- "version": "0.22.0",
3
+ "version": "0.24.0",
4
4
  "description": "UI Components to support linking platform dataset feature",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -35,7 +35,7 @@
35
35
  "@atlaskit/icon-object": "^6.3.0",
36
36
  "@atlaskit/image": "^1.1.0",
37
37
  "@atlaskit/link-client-extension": "^1.2.0",
38
- "@atlaskit/linking-common": "^2.14.0",
38
+ "@atlaskit/linking-common": "^2.15.0",
39
39
  "@atlaskit/linking-types": "^6.0.0",
40
40
  "@atlaskit/lozenge": "^11.4.0",
41
41
  "@atlaskit/modal-dialog": "^12.6.0",
@@ -63,7 +63,6 @@
63
63
  "react-intl-next": "npm:react-intl@^5.18.1"
64
64
  },
65
65
  "devDependencies": {
66
- "@atlaskit/code": "^14.6.0",
67
66
  "@atlaskit/link-provider": "^1.6.0",
68
67
  "@atlaskit/link-test-helpers": "^4.0.0",
69
68
  "@atlaskit/ssr": "*",