@atlaskit/link-datasource 0.31.2 → 0.32.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 +12 -0
- package/dist/cjs/analytics/constants.js +8 -0
- package/dist/cjs/analytics/generated/analytics.types.js +5 -0
- package/dist/cjs/analytics/generated/create-event-payload.js +46 -0
- package/dist/cjs/analytics/generated/use-analytics-events.js +32 -0
- package/dist/cjs/analytics/index.js +18 -0
- package/dist/cjs/ui/common/error-state/access-required.js +12 -3
- package/dist/cjs/ui/common/error-state/loading-error.js +20 -11
- package/dist/cjs/ui/common/error-state/modal-loading-error.js +21 -12
- package/dist/cjs/ui/common/error-state/no-results.js +48 -41
- package/dist/cjs/ui/datasource-table-view/datasourceTableView.js +7 -19
- package/dist/cjs/ui/issue-like-table/column-picker/index.js +2 -4
- package/dist/cjs/ui/issue-like-table/drag-column-preview.js +37 -0
- package/dist/cjs/ui/issue-like-table/draggable-table-heading.js +60 -25
- package/dist/cjs/ui/issue-like-table/empty-state/index.js +6 -1
- package/dist/cjs/ui/issue-like-table/index.js +102 -71
- package/dist/cjs/ui/issue-like-table/styled.js +2 -1
- package/dist/cjs/ui/jira-issues-modal/jira-search-container/index.js +8 -0
- package/dist/cjs/ui/jira-issues-modal/modal/index.js +43 -15
- package/dist/cjs/ui/table-footer/index.js +10 -7
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/analytics/constants.js +1 -0
- package/dist/es2019/analytics/generated/analytics.types.js +1 -0
- package/dist/es2019/analytics/generated/create-event-payload.js +28 -0
- package/dist/es2019/analytics/generated/use-analytics-events.js +24 -0
- package/dist/es2019/analytics/index.js +3 -0
- package/dist/es2019/ui/common/error-state/access-required.js +10 -0
- package/dist/es2019/ui/common/error-state/loading-error.js +10 -0
- package/dist/es2019/ui/common/error-state/modal-loading-error.js +10 -0
- package/dist/es2019/ui/common/error-state/no-results.js +8 -0
- package/dist/es2019/ui/datasource-table-view/datasourceTableView.js +8 -20
- package/dist/es2019/ui/issue-like-table/column-picker/index.js +1 -3
- package/dist/es2019/ui/issue-like-table/drag-column-preview.js +46 -0
- package/dist/es2019/ui/issue-like-table/draggable-table-heading.js +53 -18
- package/dist/es2019/ui/issue-like-table/empty-state/index.js +6 -1
- package/dist/es2019/ui/issue-like-table/index.js +86 -43
- package/dist/es2019/ui/issue-like-table/styled.js +18 -0
- package/dist/es2019/ui/jira-issues-modal/jira-search-container/index.js +9 -0
- package/dist/es2019/ui/jira-issues-modal/modal/index.js +43 -13
- package/dist/es2019/ui/table-footer/index.js +11 -11
- package/dist/es2019/version.json +1 -1
- package/dist/esm/analytics/constants.js +1 -0
- package/dist/esm/analytics/generated/analytics.types.js +1 -0
- package/dist/esm/analytics/generated/create-event-payload.js +38 -0
- package/dist/esm/analytics/generated/use-analytics-events.js +23 -0
- package/dist/esm/analytics/index.js +5 -0
- package/dist/esm/ui/common/error-state/access-required.js +9 -0
- package/dist/esm/ui/common/error-state/loading-error.js +9 -0
- package/dist/esm/ui/common/error-state/modal-loading-error.js +9 -0
- package/dist/esm/ui/common/error-state/no-results.js +7 -0
- package/dist/esm/ui/datasource-table-view/datasourceTableView.js +8 -20
- package/dist/esm/ui/issue-like-table/column-picker/index.js +2 -4
- package/dist/esm/ui/issue-like-table/drag-column-preview.js +29 -0
- package/dist/esm/ui/issue-like-table/draggable-table-heading.js +60 -25
- package/dist/esm/ui/issue-like-table/empty-state/index.js +6 -1
- package/dist/esm/ui/issue-like-table/index.js +102 -71
- package/dist/esm/ui/issue-like-table/styled.js +2 -1
- package/dist/esm/ui/jira-issues-modal/jira-search-container/index.js +8 -0
- package/dist/esm/ui/jira-issues-modal/modal/index.js +43 -14
- package/dist/esm/ui/table-footer/index.js +10 -7
- package/dist/esm/version.json +1 -1
- package/dist/types/analytics/constants.d.ts +1 -0
- package/dist/types/analytics/generated/analytics.types.d.ts +49 -0
- package/dist/types/analytics/generated/create-event-payload.d.ts +27 -0
- package/dist/types/analytics/generated/use-analytics-events.d.ts +3 -0
- package/dist/types/analytics/index.d.ts +4 -0
- package/dist/types/ui/common/error-state/access-required.d.ts +0 -1
- package/dist/types/ui/common/error-state/loading-error.d.ts +0 -1
- package/dist/types/ui/common/error-state/modal-loading-error.d.ts +0 -1
- package/dist/types/ui/common/error-state/no-results.d.ts +0 -1
- package/dist/types/ui/issue-like-table/column-picker/index.d.ts +1 -1
- package/dist/types/ui/issue-like-table/column-picker/types.d.ts +0 -1
- package/dist/types/ui/issue-like-table/drag-column-preview.d.ts +7 -0
- package/dist/types/ui/issue-like-table/draggable-table-heading.d.ts +2 -3
- package/dist/types/ui/issue-like-table/index.d.ts +1 -1
- package/dist/types/ui/issue-like-table/types.d.ts +5 -0
- package/dist/types/ui/jira-issues-modal/modal/index.d.ts +3 -1
- package/dist/types-ts4.5/analytics/constants.d.ts +1 -0
- package/dist/types-ts4.5/analytics/generated/analytics.types.d.ts +49 -0
- package/dist/types-ts4.5/analytics/generated/create-event-payload.d.ts +31 -0
- package/dist/types-ts4.5/analytics/generated/use-analytics-events.d.ts +7 -0
- package/dist/types-ts4.5/analytics/index.d.ts +8 -0
- package/dist/types-ts4.5/ui/common/error-state/access-required.d.ts +0 -1
- package/dist/types-ts4.5/ui/common/error-state/loading-error.d.ts +0 -1
- package/dist/types-ts4.5/ui/common/error-state/modal-loading-error.d.ts +0 -1
- package/dist/types-ts4.5/ui/common/error-state/no-results.d.ts +0 -1
- package/dist/types-ts4.5/ui/issue-like-table/column-picker/index.d.ts +1 -1
- package/dist/types-ts4.5/ui/issue-like-table/column-picker/types.d.ts +0 -1
- package/dist/types-ts4.5/ui/issue-like-table/drag-column-preview.d.ts +7 -0
- package/dist/types-ts4.5/ui/issue-like-table/draggable-table-heading.d.ts +2 -3
- package/dist/types-ts4.5/ui/issue-like-table/index.d.ts +1 -1
- package/dist/types-ts4.5/ui/issue-like-table/types.d.ts +5 -0
- package/dist/types-ts4.5/ui/jira-issues-modal/modal/index.d.ts +3 -1
- package/package.json +7 -2
|
@@ -3,30 +3,42 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
|
3
3
|
import { css, jsx } from '@emotion/react';
|
|
4
4
|
import styled from '@emotion/styled';
|
|
5
5
|
import invariant from 'tiny-invariant';
|
|
6
|
+
import Heading from '@atlaskit/heading';
|
|
6
7
|
import { Skeleton } from '@atlaskit/linking-common';
|
|
7
8
|
import { extractClosestEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/addon/closest-edge';
|
|
8
9
|
import { reorderWithEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/util/reorder-with-edge';
|
|
9
10
|
import { autoScroller } from '@atlaskit/pragmatic-drag-and-drop-react-beautiful-dnd-autoscroll';
|
|
10
11
|
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/adapter/element';
|
|
11
12
|
import { combine } from '@atlaskit/pragmatic-drag-and-drop/util/combine';
|
|
13
|
+
import { N40 } from '@atlaskit/theme/colors';
|
|
12
14
|
import { ColumnPicker } from './column-picker';
|
|
15
|
+
import { DragColumnPreview } from './drag-column-preview';
|
|
13
16
|
import { DraggableTableHeading } from './draggable-table-heading';
|
|
14
17
|
import TableEmptyState from './empty-state';
|
|
15
18
|
import { fallbackRenderType } from './render-type';
|
|
16
19
|
import { Table, TableHeading } from './styled';
|
|
17
20
|
import { useIsOnScreen } from './useIsOnScreen';
|
|
21
|
+
const tableSidePadding = "var(--ds-space-200, 16px)";
|
|
18
22
|
const tableHeadStyles = css({
|
|
19
23
|
background: "var(--ds-surface, #FFF)",
|
|
20
|
-
|
|
24
|
+
position: 'sticky',
|
|
25
|
+
top: 0,
|
|
26
|
+
zIndex: 10
|
|
21
27
|
});
|
|
22
|
-
const ColumnPickerHeader = styled.
|
|
28
|
+
const ColumnPickerHeader = styled.th`
|
|
23
29
|
width: 40px;
|
|
24
|
-
padding-block: ${"var(--ds-space-100, 8px)"};
|
|
25
30
|
position: sticky;
|
|
26
|
-
right:
|
|
31
|
+
right: calc(-1 * ${tableSidePadding});
|
|
27
32
|
background-color: ${"var(--ds-surface, #FFF)"};
|
|
28
|
-
|
|
29
|
-
|
|
33
|
+
border-bottom: 2px solid ${`var(--ds-background-accent-gray-subtler, ${N40})`}; /* It is required to have solid (not half-transparent) color because of this gradient business bellow */
|
|
34
|
+
background: linear-gradient(
|
|
35
|
+
90deg,
|
|
36
|
+
rgba(255, 255, 255, 0) 0%,
|
|
37
|
+
${"var(--ds-surface, #FFF)"} 10%
|
|
38
|
+
);
|
|
39
|
+
vertical-align: middle; /* Keeps dropdown button in the middle */
|
|
40
|
+
&:last-of-type {
|
|
41
|
+
padding-right: ${tableSidePadding};
|
|
30
42
|
}
|
|
31
43
|
`;
|
|
32
44
|
const truncatedCellStyles = css({
|
|
@@ -34,11 +46,22 @@ const truncatedCellStyles = css({
|
|
|
34
46
|
textOverflow: 'ellipsis',
|
|
35
47
|
whiteSpace: 'nowrap'
|
|
36
48
|
});
|
|
37
|
-
const
|
|
38
|
-
|
|
49
|
+
const scrollableContainerStyles = css({
|
|
50
|
+
overflow: 'auto',
|
|
51
|
+
padding: `0 ${tableSidePadding} 0 ${tableSidePadding}`,
|
|
52
|
+
boxSizing: 'border-box'
|
|
39
53
|
});
|
|
40
|
-
const
|
|
41
|
-
|
|
54
|
+
const tableStyles = css({
|
|
55
|
+
// These styles are needed to prevent thead bottom border from scrolling away.
|
|
56
|
+
// This happens because it is sticky. https://stackoverflow.com/questions/50361698/border-style-do-not-work-with-sticky-position-element
|
|
57
|
+
borderCollapse: 'separate',
|
|
58
|
+
borderSpacing: 0
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// By default tbody and thead have border-bottom: 2px ...
|
|
62
|
+
// This removes it, because for header we handle it via `th` styling and footer supply bottom border
|
|
63
|
+
const noDefaultBorderStyles = css({
|
|
64
|
+
borderBottom: 0
|
|
42
65
|
});
|
|
43
66
|
function extractIndex(data) {
|
|
44
67
|
const {
|
|
@@ -69,7 +92,6 @@ const BASE_WIDTH = 8;
|
|
|
69
92
|
function getColumnWidth(key, type) {
|
|
70
93
|
const keyBasedWidth = {
|
|
71
94
|
assignee: BASE_WIDTH * 22,
|
|
72
|
-
key: BASE_WIDTH * 10,
|
|
73
95
|
labels: BASE_WIDTH * 22,
|
|
74
96
|
priority: BASE_WIDTH * 8,
|
|
75
97
|
status: BASE_WIDTH * 18,
|
|
@@ -98,11 +120,11 @@ export const IssueLikeDataTableView = ({
|
|
|
98
120
|
visibleColumnKeys,
|
|
99
121
|
onVisibleColumnKeysChange,
|
|
100
122
|
status,
|
|
101
|
-
hasNextPage
|
|
123
|
+
hasNextPage,
|
|
124
|
+
scrollableContainerHeight
|
|
102
125
|
}) => {
|
|
103
126
|
const tableId = useMemo(() => Symbol('unique-id'), []);
|
|
104
127
|
const [lastRowElement, setLastRowElement] = useState(null);
|
|
105
|
-
const [isDragPreview, setIsDragPreview] = useState(false);
|
|
106
128
|
const [hasFullSchema, setHasFullSchema] = useState(false);
|
|
107
129
|
const isBottomOfTableVisibleRaw = useIsOnScreen(lastRowElement);
|
|
108
130
|
const containerRef = useRef(null);
|
|
@@ -135,7 +157,7 @@ export const IssueLikeDataTableView = ({
|
|
|
135
157
|
};
|
|
136
158
|
})
|
|
137
159
|
}), [visibleSortedColumns]);
|
|
138
|
-
const headColumns = visibleSortedColumns.map(({
|
|
160
|
+
const headColumns = useMemo(() => visibleSortedColumns.map(({
|
|
139
161
|
key,
|
|
140
162
|
title,
|
|
141
163
|
type
|
|
@@ -144,7 +166,7 @@ export const IssueLikeDataTableView = ({
|
|
|
144
166
|
content: title,
|
|
145
167
|
shouldTruncate: true,
|
|
146
168
|
maxWidth: getColumnWidth(key, type)
|
|
147
|
-
}));
|
|
169
|
+
})), [visibleSortedColumns]);
|
|
148
170
|
useEffect(() => {
|
|
149
171
|
if (isBottomOfTableVisibleRaw && hasNextPage && status === 'resolved') {
|
|
150
172
|
void onNextPage({
|
|
@@ -152,37 +174,41 @@ export const IssueLikeDataTableView = ({
|
|
|
152
174
|
});
|
|
153
175
|
}
|
|
154
176
|
}, [isBottomOfTableVisibleRaw, status, hasNextPage, onNextPage]);
|
|
155
|
-
|
|
156
|
-
if (items.length > 0 && containerRef.current) {
|
|
157
|
-
const containerEl = containerRef.current;
|
|
158
|
-
invariant(containerEl);
|
|
159
|
-
dndPreviewHeight = containerEl.offsetHeight;
|
|
160
|
-
}
|
|
177
|
+
const hasData = items.length > 0;
|
|
161
178
|
|
|
162
179
|
// This variable contains initial Y mouse coordinate, so we can restrict
|
|
163
180
|
// autoScroller in X axis only
|
|
164
181
|
const initialAutoScrollerClientY = useRef();
|
|
165
182
|
useEffect(() => {
|
|
166
|
-
if (!onVisibleColumnKeysChange) {
|
|
183
|
+
if (!onVisibleColumnKeysChange || !hasData) {
|
|
167
184
|
return;
|
|
168
185
|
}
|
|
169
186
|
return combine(monitorForElements({
|
|
170
187
|
onDragStart: ({
|
|
171
188
|
location
|
|
172
189
|
}) => {
|
|
190
|
+
var _containerRef$current;
|
|
173
191
|
initialAutoScrollerClientY.current = location.current.input.clientY;
|
|
174
192
|
autoScroller.start({
|
|
175
|
-
input:
|
|
193
|
+
input: {
|
|
194
|
+
...location.current.input,
|
|
195
|
+
clientY:
|
|
196
|
+
// The goal is to have clientY the same and in the middle of the scrollable area
|
|
197
|
+
// Since clientY is taken from to of the viewport we need to plus that in order to get
|
|
198
|
+
// middle of the scrollable area in reference to the viewport
|
|
199
|
+
(initialAutoScrollerClientY.current || 0) + (((_containerRef$current = containerRef.current) === null || _containerRef$current === void 0 ? void 0 : _containerRef$current.offsetHeight) || 0) / 2
|
|
200
|
+
},
|
|
176
201
|
behavior: 'container-only'
|
|
177
202
|
});
|
|
178
203
|
},
|
|
179
204
|
onDrag: ({
|
|
180
205
|
location
|
|
181
206
|
}) => {
|
|
207
|
+
var _containerRef$current2;
|
|
182
208
|
autoScroller.updateInput({
|
|
183
209
|
input: {
|
|
184
210
|
...location.current.input,
|
|
185
|
-
clientY: initialAutoScrollerClientY.current || 0
|
|
211
|
+
clientY: (initialAutoScrollerClientY.current || 0) + (((_containerRef$current2 = containerRef.current) === null || _containerRef$current2 === void 0 ? void 0 : _containerRef$current2.offsetHeight) || 0) / 2
|
|
186
212
|
}
|
|
187
213
|
});
|
|
188
214
|
},
|
|
@@ -190,7 +216,6 @@ export const IssueLikeDataTableView = ({
|
|
|
190
216
|
source,
|
|
191
217
|
location
|
|
192
218
|
}) {
|
|
193
|
-
initialAutoScrollerClientY.current = null;
|
|
194
219
|
autoScroller.stop();
|
|
195
220
|
if (location.current.dropTargets.length === 0) {
|
|
196
221
|
return;
|
|
@@ -220,7 +245,7 @@ export const IssueLikeDataTableView = ({
|
|
|
220
245
|
}
|
|
221
246
|
}
|
|
222
247
|
}));
|
|
223
|
-
}, [visibleColumnKeys, onVisibleColumnKeysChange, tableId]);
|
|
248
|
+
}, [visibleColumnKeys, onVisibleColumnKeysChange, tableId, hasData]);
|
|
224
249
|
const tableRows = useMemo(() => items.map((newRowData, rowIndex) => ({
|
|
225
250
|
key: `${identityColumnKey && newRowData[identityColumnKey] && newRowData[identityColumnKey].data || rowIndex}`,
|
|
226
251
|
cells: visibleSortedColumns.map(({
|
|
@@ -242,9 +267,7 @@ export const IssueLikeDataTableView = ({
|
|
|
242
267
|
}),
|
|
243
268
|
ref: rowIndex === items.length - 1 ? el => setLastRowElement(el) : undefined
|
|
244
269
|
})), [identityColumnKey, renderItem, items, visibleSortedColumns]);
|
|
245
|
-
const rows = [...tableRows, ...(status === 'loading' ? [loadingRow] : [])];
|
|
246
|
-
const setIsDragPreviewOn = useCallback(() => setIsDragPreview(true), [setIsDragPreview]);
|
|
247
|
-
const setIsDragPreviewOff = useCallback(() => setIsDragPreview(false), [setIsDragPreview]);
|
|
270
|
+
const rows = useMemo(() => [...tableRows, ...(status === 'loading' ? [loadingRow] : [])], [loadingRow, status, tableRows]);
|
|
248
271
|
const onSelectedColumnKeysChange = useCallback(newSelectedColumnKeys => {
|
|
249
272
|
onVisibleColumnKeysChange === null || onVisibleColumnKeysChange === void 0 ? void 0 : onVisibleColumnKeysChange(newSelectedColumnKeys);
|
|
250
273
|
}, [onVisibleColumnKeysChange]);
|
|
@@ -261,32 +284,50 @@ export const IssueLikeDataTableView = ({
|
|
|
261
284
|
}, [hasFullSchema, onLoadDatasourceDetails]);
|
|
262
285
|
return jsx("div", {
|
|
263
286
|
ref: containerRef,
|
|
264
|
-
css:
|
|
287
|
+
css: scrollableContainerHeight ? scrollableContainerStyles : null,
|
|
288
|
+
style: scrollableContainerHeight ? {
|
|
289
|
+
maxHeight: `${scrollableContainerHeight}px`
|
|
290
|
+
} : undefined
|
|
265
291
|
}, jsx(Table, {
|
|
266
|
-
css:
|
|
292
|
+
css: tableStyles,
|
|
267
293
|
"data-testid": testId
|
|
268
294
|
}, jsx("thead", {
|
|
269
295
|
"data-testid": testId && `${testId}--head`,
|
|
270
|
-
css: tableHeadStyles
|
|
296
|
+
css: [noDefaultBorderStyles, tableHeadStyles]
|
|
271
297
|
}, jsx("tr", null, headColumns.map(({
|
|
272
298
|
key,
|
|
273
299
|
content,
|
|
274
300
|
maxWidth
|
|
275
301
|
}, cellIndex) => {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
302
|
+
if (onVisibleColumnKeysChange && hasData) {
|
|
303
|
+
var _containerRef$current3;
|
|
304
|
+
const previewRows = tableRows.map(({
|
|
305
|
+
cells
|
|
306
|
+
}) => {
|
|
307
|
+
const cell = cells.find(({
|
|
308
|
+
key: cellKey
|
|
309
|
+
}) => cellKey === key);
|
|
310
|
+
if (cell) {
|
|
311
|
+
return cell.content;
|
|
312
|
+
}
|
|
313
|
+
}).slice(0, 5);
|
|
314
|
+
const dragPreview = jsx(DragColumnPreview, {
|
|
315
|
+
title: jsx(Heading, {
|
|
316
|
+
level: "h400"
|
|
317
|
+
}, content),
|
|
318
|
+
rows: previewRows
|
|
319
|
+
});
|
|
280
320
|
return jsx(DraggableTableHeading, {
|
|
281
321
|
tableId: tableId,
|
|
282
322
|
key: key,
|
|
283
323
|
id: key,
|
|
284
324
|
index: cellIndex,
|
|
285
325
|
maxWidth: maxWidth,
|
|
286
|
-
dndPreviewHeight:
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
326
|
+
dndPreviewHeight: ((_containerRef$current3 = containerRef.current) === null || _containerRef$current3 === void 0 ? void 0 : _containerRef$current3.offsetHeight) || 0,
|
|
327
|
+
dragPreview: dragPreview
|
|
328
|
+
}, jsx(Heading, {
|
|
329
|
+
level: "h400"
|
|
330
|
+
}, content));
|
|
290
331
|
} else {
|
|
291
332
|
return jsx(TableHeading, {
|
|
292
333
|
key: key,
|
|
@@ -294,15 +335,17 @@ export const IssueLikeDataTableView = ({
|
|
|
294
335
|
style: {
|
|
295
336
|
maxWidth
|
|
296
337
|
}
|
|
297
|
-
}, jsx(
|
|
338
|
+
}, jsx(Heading, {
|
|
339
|
+
level: "h400"
|
|
340
|
+
}, content));
|
|
298
341
|
}
|
|
299
|
-
}), onVisibleColumnKeysChange && jsx(ColumnPickerHeader, null, jsx(ColumnPicker, {
|
|
342
|
+
}), onVisibleColumnKeysChange && hasData && jsx(ColumnPickerHeader, null, jsx(ColumnPicker, {
|
|
300
343
|
columns: hasFullSchema ? orderedColumns : [],
|
|
301
344
|
selectedColumnKeys: hasFullSchema ? visibleColumnKeys : [],
|
|
302
|
-
isDatasourceLoading: status === 'loading',
|
|
303
345
|
onSelectedColumnKeysChange: onSelectedColumnKeysChange,
|
|
304
346
|
onOpen: handlePickerOpen
|
|
305
347
|
})))), jsx("tbody", {
|
|
348
|
+
css: noDefaultBorderStyles,
|
|
306
349
|
"data-testid": testId && `${testId}--body`
|
|
307
350
|
}, rows.map(({
|
|
308
351
|
key,
|
|
@@ -1,11 +1,29 @@
|
|
|
1
1
|
import styled from '@emotion/styled';
|
|
2
|
+
import { N40 } from '@atlaskit/theme/colors';
|
|
2
3
|
export const Table = styled.table`
|
|
3
4
|
width: 100%;
|
|
4
5
|
`;
|
|
5
6
|
export const TableHeading = styled.th`
|
|
7
|
+
cursor: grab;
|
|
6
8
|
position: relative;
|
|
7
9
|
padding-block: ${"var(--ds-space-100, 8px)"};
|
|
8
10
|
line-height: ${"var(--ds-font-lineHeight-300, 24px)"};
|
|
11
|
+
border-bottom: 2px solid ${`var(--ds-background-accent-gray-subtler, ${N40})`};
|
|
12
|
+
.ProseMirror & h5,
|
|
13
|
+
& h5 {
|
|
14
|
+
margin-top: 0;
|
|
15
|
+
overflow: hidden;
|
|
16
|
+
text-overflow: ellipsis;
|
|
17
|
+
white-space: nowrap;
|
|
18
|
+
line-height: 24px; /* Is needed to keep overall height consistent with or without drag handle icon present */
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
&:hover .issue-like-table-drag-handle {
|
|
22
|
+
width: 24px;
|
|
23
|
+
}
|
|
24
|
+
&:hover .issue-like-table-drag-handle-spacer {
|
|
25
|
+
width: 0px;
|
|
26
|
+
}
|
|
9
27
|
`;
|
|
10
28
|
export const EmptyStateTableHeading = styled(TableHeading)`
|
|
11
29
|
&:first-child {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import React, { useState } from 'react';
|
|
3
3
|
import { css, jsx } from '@emotion/react';
|
|
4
4
|
import { useIntl } from 'react-intl-next';
|
|
5
|
+
import { useDatasourceAnalyticsEvents } from '../../../analytics';
|
|
5
6
|
import { BasicSearchInput } from '../basic-search-input';
|
|
6
7
|
import { JiraJQLEditor } from '../jql-editor';
|
|
7
8
|
import { ModeSwitcher } from '../mode-switcher';
|
|
@@ -34,6 +35,9 @@ export const JiraSearchContainer = props => {
|
|
|
34
35
|
const [jql, setJql] = useState(initialJql || DEFAULT_JQL_QUERY);
|
|
35
36
|
const [orderKey, setOrderKey] = useState();
|
|
36
37
|
const [orderDirection, setOrderDirection] = useState();
|
|
38
|
+
const {
|
|
39
|
+
fireEvent
|
|
40
|
+
} = useDatasourceAnalyticsEvents();
|
|
37
41
|
const onSearchModeChange = searchMode => {
|
|
38
42
|
setCurrentSearchMode(searchMode);
|
|
39
43
|
};
|
|
@@ -65,6 +69,11 @@ export const JiraSearchContainer = props => {
|
|
|
65
69
|
onSearch({
|
|
66
70
|
jql
|
|
67
71
|
});
|
|
72
|
+
if (currentSearchMode === basicModeValue) {
|
|
73
|
+
fireEvent('ui.form.submitted.basicSearch', {});
|
|
74
|
+
} else if (currentSearchMode === jqlModeValue) {
|
|
75
|
+
fireEvent('ui.jqlEditor.searched', {});
|
|
76
|
+
}
|
|
68
77
|
};
|
|
69
78
|
return jsx("div", {
|
|
70
79
|
css: inputContainerStyles
|
|
@@ -3,11 +3,14 @@ import _extends from "@babel/runtime/helpers/extends";
|
|
|
3
3
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
4
4
|
import { css, jsx } from '@emotion/react';
|
|
5
5
|
import { FormattedMessage, FormattedNumber, useIntl } from 'react-intl-next';
|
|
6
|
+
import { withAnalyticsContext } from '@atlaskit/analytics-next';
|
|
6
7
|
import Button from '@atlaskit/button/standard-button';
|
|
7
8
|
import Modal, { ModalBody, ModalFooter, ModalHeader, ModalTitle, ModalTransition } from '@atlaskit/modal-dialog';
|
|
8
|
-
import { B400, N0, N800 } from '@atlaskit/theme/colors';
|
|
9
|
+
import { B400, N0, N40, N800 } from '@atlaskit/theme/colors';
|
|
10
|
+
import { useDatasourceAnalyticsEvents } from '../../../analytics';
|
|
9
11
|
import { useDatasourceTableState } from '../../../hooks/useDatasourceTableState';
|
|
10
12
|
import { getAvailableJiraSites } from '../../../services/getAvailableJiraSites';
|
|
13
|
+
import { name as packageName, version as packageVersion } from '../../../version.json';
|
|
11
14
|
import { AccessRequired } from '../../common/error-state/access-required';
|
|
12
15
|
import { ModalLoadingError } from '../../common/error-state/modal-loading-error';
|
|
13
16
|
import { NoResults } from '../../common/error-state/no-results';
|
|
@@ -23,8 +26,9 @@ const dropdownContainerStyles = css({
|
|
|
23
26
|
});
|
|
24
27
|
const contentContainerStyles = css({
|
|
25
28
|
display: 'grid',
|
|
26
|
-
|
|
27
|
-
overflow: 'auto'
|
|
29
|
+
maxHeight: '420px',
|
|
30
|
+
overflow: 'auto',
|
|
31
|
+
borderBottom: `2px solid ${`var(--ds-background-accent-gray-subtler, ${N40})`}`
|
|
28
32
|
});
|
|
29
33
|
const placeholderSmartLinkStyles = css({
|
|
30
34
|
backgroundColor: `var(--ds-surface-raised, ${N0})`,
|
|
@@ -41,7 +45,7 @@ const issueCountStyles = css({
|
|
|
41
45
|
const smartLinkContainerStyles = css({
|
|
42
46
|
paddingLeft: '1px'
|
|
43
47
|
});
|
|
44
|
-
export const
|
|
48
|
+
export const PlainJiraIssuesConfigModal = props => {
|
|
45
49
|
const {
|
|
46
50
|
datasourceId,
|
|
47
51
|
parameters: initialParameters,
|
|
@@ -77,11 +81,17 @@ export const JiraIssuesConfigModal = props => {
|
|
|
77
81
|
const {
|
|
78
82
|
formatMessage
|
|
79
83
|
} = useIntl();
|
|
84
|
+
const {
|
|
85
|
+
fireEvent
|
|
86
|
+
} = useDatasourceAnalyticsEvents();
|
|
80
87
|
const selectedJiraSite = useMemo(() => availableSites.find(jiraSite => jiraSite.cloudId === cloudId) || availableSites[0], [availableSites, cloudId]);
|
|
81
88
|
const resolvedWithNoResults = status === 'resolved' && !responseItems.length;
|
|
82
89
|
const jqlUrl = selectedJiraSite && jql && `${selectedJiraSite.url}/issues/?jql=${encodeURI(jql)}`;
|
|
83
90
|
const isInsertDisabled = !isParametersSet || status === 'rejected' || status === 'unauthorized' || status === 'loading' || resolvedWithNoResults;
|
|
84
91
|
const shouldShowIssueCount = !!totalCount && totalCount !== 1 && currentViewMode === 'issue';
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
fireEvent('screen.datasourceModalDialog.viewed', {});
|
|
94
|
+
}, [fireEvent]);
|
|
85
95
|
useEffect(() => {
|
|
86
96
|
const newVisibleColumnKeys = !initialVisibleColumnKeys || (initialVisibleColumnKeys || []).length === 0 ? defaultVisibleColumnKeys : initialVisibleColumnKeys;
|
|
87
97
|
setVisibleColumnKeys(newVisibleColumnKeys);
|
|
@@ -90,9 +100,12 @@ export const JiraIssuesConfigModal = props => {
|
|
|
90
100
|
const fetchSiteDisplayNames = async () => {
|
|
91
101
|
const jiraSites = await getAvailableJiraSites();
|
|
92
102
|
setAvailableSites(jiraSites);
|
|
103
|
+
fireEvent('ui.modal.ready.datasource', {
|
|
104
|
+
instancesCount: jiraSites.length
|
|
105
|
+
});
|
|
93
106
|
};
|
|
94
107
|
void fetchSiteDisplayNames();
|
|
95
|
-
}, []);
|
|
108
|
+
}, [fireEvent]);
|
|
96
109
|
useEffect(() => {
|
|
97
110
|
if (!cloudId && selectedJiraSite) {
|
|
98
111
|
setCloudId(selectedJiraSite.cloudId);
|
|
@@ -159,7 +172,9 @@ export const JiraIssuesConfigModal = props => {
|
|
|
159
172
|
const handleViewModeChange = selectedMode => {
|
|
160
173
|
setCurrentViewMode(selectedMode);
|
|
161
174
|
};
|
|
162
|
-
const issueLikeDataTableView = useMemo(() => jsx(
|
|
175
|
+
const issueLikeDataTableView = useMemo(() => jsx("div", {
|
|
176
|
+
css: contentContainerStyles
|
|
177
|
+
}, jsx(IssueLikeDataTableView, {
|
|
163
178
|
testId: "jira-jql-datasource-table",
|
|
164
179
|
status: status,
|
|
165
180
|
columns: columns,
|
|
@@ -169,7 +184,7 @@ export const JiraIssuesConfigModal = props => {
|
|
|
169
184
|
onNextPage: onNextPage,
|
|
170
185
|
onLoadDatasourceDetails: loadDatasourceDetails,
|
|
171
186
|
onVisibleColumnKeysChange: setVisibleColumnKeys
|
|
172
|
-
}), [columns, defaultVisibleColumnKeys, hasNextPage, loadDatasourceDetails, onNextPage, responseItems, status, visibleColumnKeys]);
|
|
187
|
+
})), [columns, defaultVisibleColumnKeys, hasNextPage, loadDatasourceDetails, onNextPage, responseItems, status, visibleColumnKeys]);
|
|
173
188
|
const renderCountModeContent = useCallback(() => {
|
|
174
189
|
const url = selectedJiraSite === null || selectedJiraSite === void 0 ? void 0 : selectedJiraSite.url;
|
|
175
190
|
if (status === 'unauthorized') {
|
|
@@ -205,9 +220,11 @@ export const JiraIssuesConfigModal = props => {
|
|
|
205
220
|
return jsx(NoResults, null);
|
|
206
221
|
} else if (status === 'empty' || !columns.length) {
|
|
207
222
|
// persist the empty state when making the initial /data request which contains the columns
|
|
208
|
-
return jsx(
|
|
223
|
+
return jsx("div", {
|
|
224
|
+
css: contentContainerStyles
|
|
225
|
+
}, jsx(EmptyState, {
|
|
209
226
|
testId: `jira-jql-datasource-modal--empty-state`
|
|
210
|
-
});
|
|
227
|
+
}));
|
|
211
228
|
}
|
|
212
229
|
const firstIssueUrl = retrieveUrlForSmartCardRender();
|
|
213
230
|
if (responseItems.length === 1 && firstIssueUrl) {
|
|
@@ -250,9 +267,7 @@ export const JiraIssuesConfigModal = props => {
|
|
|
250
267
|
isSearching: status === 'loading',
|
|
251
268
|
parameters: parameters,
|
|
252
269
|
onSearch: onSearch
|
|
253
|
-
}), jsx("div", {
|
|
254
|
-
css: contentContainerStyles
|
|
255
|
-
}, currentViewMode === 'count' ? renderCountModeContent() : renderIssuesModeContent())), jsx(ModalFooter, null, shouldShowIssueCount && jsx("div", {
|
|
270
|
+
}), currentViewMode === 'count' ? renderCountModeContent() : renderIssuesModeContent()), jsx(ModalFooter, null, shouldShowIssueCount && jsx("div", {
|
|
256
271
|
"data-testid": "jira-jql-datasource-modal-total-issues-count",
|
|
257
272
|
css: issueCountStyles
|
|
258
273
|
}, jsx(FormattedNumber, {
|
|
@@ -270,4 +285,19 @@ export const JiraIssuesConfigModal = props => {
|
|
|
270
285
|
isDisabled: isInsertDisabled,
|
|
271
286
|
testId: 'jira-jql-datasource-modal--insert-button'
|
|
272
287
|
}, jsx(FormattedMessage, modalMessages.insertIssuesButtonText)))));
|
|
273
|
-
};
|
|
288
|
+
};
|
|
289
|
+
const analyticsContextAttributes = {
|
|
290
|
+
dataProvider: 'jira-issues'
|
|
291
|
+
};
|
|
292
|
+
const analyticsContextData = {
|
|
293
|
+
packageName,
|
|
294
|
+
packageVersion,
|
|
295
|
+
source: 'datasourceConfigModal'
|
|
296
|
+
};
|
|
297
|
+
const contextData = {
|
|
298
|
+
...analyticsContextData,
|
|
299
|
+
attributes: {
|
|
300
|
+
...analyticsContextAttributes
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
export const JiraIssuesConfigModal = withAnalyticsContext(contextData)(PlainJiraIssuesConfigModal);
|
|
@@ -11,20 +11,18 @@ import { N0, N40, N800, N90 } from '@atlaskit/theme/colors';
|
|
|
11
11
|
import { footerMessages } from './messages';
|
|
12
12
|
import { SyncInfo } from './sync-info';
|
|
13
13
|
const FooterWrapper = styled.div`
|
|
14
|
+
padding: 0 ${"var(--ds-space-200, 16px)"};
|
|
15
|
+
box-sizing: border-box;
|
|
16
|
+
background: ${`var(--ds-background-input, ${N0})`};
|
|
17
|
+
`;
|
|
18
|
+
const TopBorderWrapper = styled.div`
|
|
14
19
|
display: flex;
|
|
20
|
+
box-sizing: border-box;
|
|
15
21
|
justify-content: space-between;
|
|
16
|
-
width: 100%;
|
|
17
22
|
padding: ${"var(--ds-space-250, 20px)"} 0;
|
|
18
|
-
|
|
19
|
-
bottom: 0;
|
|
20
|
-
background: ${`var(--ds-background-input, ${N0})`};
|
|
21
|
-
border-top-style: solid;
|
|
22
|
-
border-top-color: ${`var(--ds-background-neutral, ${N40})`};
|
|
23
|
-
margin-top: -2px;
|
|
24
|
-
align-self: center;
|
|
23
|
+
border-top: 2px solid ${`var(--ds-background-accent-gray-subtler, ${N40})`};
|
|
25
24
|
`;
|
|
26
25
|
const IssueCounterWrapper = styled.div`
|
|
27
|
-
margin-left: 10px;
|
|
28
26
|
display: flex;
|
|
29
27
|
align-self: center;
|
|
30
28
|
color: ${`var(--ds-text-accent-gray, ${N800})`};
|
|
@@ -55,7 +53,9 @@ export const TableFooter = ({
|
|
|
55
53
|
// ensure correct positioning since 'justify-content: space-between' is used).
|
|
56
54
|
return onRefresh || showIssueCount ? jsx(FooterWrapper, {
|
|
57
55
|
"data-testid": "table-footer"
|
|
58
|
-
}, jsx(
|
|
56
|
+
}, jsx(TopBorderWrapper, null, jsx(IssueCounterWrapper, {
|
|
57
|
+
"data-testid": 'issue-count-wrapper'
|
|
58
|
+
}, showIssueCount && jsx(Heading, {
|
|
59
59
|
testId: "issue-count",
|
|
60
60
|
level: "h400"
|
|
61
61
|
}, jsx(FormattedNumber, {
|
|
@@ -76,5 +76,5 @@ export const TableFooter = ({
|
|
|
76
76
|
}),
|
|
77
77
|
isDisabled: isLoading,
|
|
78
78
|
testId: "refresh-button"
|
|
79
|
-
})))) : null;
|
|
79
|
+
}))))) : null;
|
|
80
80
|
};
|
package/dist/es2019/version.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export var EVENT_CHANNEL = 'media';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
|
+
/**
|
|
3
|
+
* THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
|
|
4
|
+
*
|
|
5
|
+
* Generates Typescript types for analytics events from analytics.spec.yaml
|
|
6
|
+
*
|
|
7
|
+
* @codegen <<SignedSource::819168596ba17484cadda969f8ecf82d>>
|
|
8
|
+
* @codegenCommand yarn workspace @atlassian/analytics-tooling run analytics:codegen link-datasource
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
var createEventPayload = function createEventPayload(eventKey) {
|
|
12
|
+
for (var _len = arguments.length, _ref = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
13
|
+
_ref[_key - 1] = arguments[_key];
|
|
14
|
+
}
|
|
15
|
+
var attributes = _ref[0];
|
|
16
|
+
var _eventKey$split = eventKey.split('.'),
|
|
17
|
+
_eventKey$split2 = _slicedToArray(_eventKey$split, 4),
|
|
18
|
+
eventType = _eventKey$split2[0],
|
|
19
|
+
actionSubject = _eventKey$split2[1],
|
|
20
|
+
action = _eventKey$split2[2],
|
|
21
|
+
actionSubjectId = _eventKey$split2[3];
|
|
22
|
+
if (eventType === 'screen') {
|
|
23
|
+
return {
|
|
24
|
+
eventType: eventType,
|
|
25
|
+
name: actionSubject,
|
|
26
|
+
action: 'viewed',
|
|
27
|
+
attributes: attributes
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
eventType: eventType,
|
|
32
|
+
actionSubject: actionSubject,
|
|
33
|
+
action: action,
|
|
34
|
+
actionSubjectId: actionSubjectId,
|
|
35
|
+
attributes: attributes
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
export default createEventPayload;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
|
|
3
|
+
*
|
|
4
|
+
* Generates Typescript types for analytics events from analytics.spec.yaml
|
|
5
|
+
*
|
|
6
|
+
* @codegen <<SignedSource::415836762b378b7d79f3aff4ba051c14>>
|
|
7
|
+
* @codegenCommand yarn workspace @atlassian/analytics-tooling run analytics:codegen link-datasource
|
|
8
|
+
*/
|
|
9
|
+
import { useCallback } from 'react';
|
|
10
|
+
import { useAnalyticsEvents as useAnalyticsNextEvents } from '@atlaskit/analytics-next';
|
|
11
|
+
import { EVENT_CHANNEL } from '../constants';
|
|
12
|
+
import createEventPayload from './create-event-payload';
|
|
13
|
+
export var useAnalyticsEvents = function useAnalyticsEvents() {
|
|
14
|
+
var _useAnalyticsNextEven = useAnalyticsNextEvents(),
|
|
15
|
+
createAnalyticsEvent = _useAnalyticsNextEven.createAnalyticsEvent;
|
|
16
|
+
var fireEvent = useCallback(function () {
|
|
17
|
+
var event = createAnalyticsEvent(createEventPayload.apply(void 0, arguments));
|
|
18
|
+
event.fire(EVENT_CHANNEL);
|
|
19
|
+
}, [createAnalyticsEvent]);
|
|
20
|
+
return {
|
|
21
|
+
fireEvent: fireEvent
|
|
22
|
+
};
|
|
23
|
+
};
|
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
/** @jsx jsx */
|
|
2
|
+
import { useEffect } from 'react';
|
|
2
3
|
import { jsx } from '@emotion/react';
|
|
3
4
|
import { useIntl } from 'react-intl-next';
|
|
4
5
|
import EmptyState from '@atlaskit/empty-state';
|
|
6
|
+
import { useDatasourceAnalyticsEvents } from '../../../analytics';
|
|
5
7
|
import { AccessRequiredSVG } from './access-required-svg';
|
|
6
8
|
import { loadingErrorMessages } from './messages';
|
|
7
9
|
export var AccessRequired = function AccessRequired(_ref) {
|
|
8
10
|
var siteName = _ref.siteName;
|
|
9
11
|
var _useIntl = useIntl(),
|
|
10
12
|
formatMessage = _useIntl.formatMessage;
|
|
13
|
+
var _useDatasourceAnalyti = useDatasourceAnalyticsEvents(),
|
|
14
|
+
fireEvent = _useDatasourceAnalyti.fireEvent;
|
|
15
|
+
useEffect(function () {
|
|
16
|
+
fireEvent('ui.error.shown', {
|
|
17
|
+
reason: 'access'
|
|
18
|
+
});
|
|
19
|
+
}, [fireEvent]);
|
|
11
20
|
return jsx(EmptyState, {
|
|
12
21
|
header: siteName ? formatMessage(loadingErrorMessages.accessRequiredWithSite, {
|
|
13
22
|
siteName: siteName
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/** @jsx jsx */
|
|
2
|
+
import { useEffect } from 'react';
|
|
2
3
|
import { css, jsx } from '@emotion/react';
|
|
3
4
|
import { FormattedMessage } from 'react-intl-next';
|
|
4
5
|
import Button from '@atlaskit/button/standard-button';
|
|
6
|
+
import { useDatasourceAnalyticsEvents } from '../../../analytics';
|
|
5
7
|
import { LoadingErrorSVG } from './loading-error-svg';
|
|
6
8
|
import { loadingErrorMessages } from './messages';
|
|
7
9
|
var errorContainerStyles = css({
|
|
@@ -24,6 +26,13 @@ var errorDescriptionStyles = css({
|
|
|
24
26
|
});
|
|
25
27
|
export var LoadingError = function LoadingError(_ref) {
|
|
26
28
|
var onRefresh = _ref.onRefresh;
|
|
29
|
+
var _useDatasourceAnalyti = useDatasourceAnalyticsEvents(),
|
|
30
|
+
fireEvent = _useDatasourceAnalyti.fireEvent;
|
|
31
|
+
useEffect(function () {
|
|
32
|
+
fireEvent('ui.error.shown', {
|
|
33
|
+
reason: 'network'
|
|
34
|
+
});
|
|
35
|
+
}, [fireEvent]);
|
|
27
36
|
return jsx("div", {
|
|
28
37
|
css: errorContainerStyles,
|
|
29
38
|
"data-testid": "jira-jql-datasource--loading-error"
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
2
|
/** @jsx jsx */
|
|
3
|
+
import { useEffect } from 'react';
|
|
3
4
|
import { css, jsx } from '@emotion/react';
|
|
4
5
|
import { FormattedMessage } from 'react-intl-next';
|
|
6
|
+
import { useDatasourceAnalyticsEvents } from '../../../analytics';
|
|
5
7
|
import { LoadingErrorSVG } from './loading-error-svg';
|
|
6
8
|
import { loadingErrorMessages } from './messages';
|
|
7
9
|
var errorContainerStyles = css({
|
|
@@ -24,6 +26,13 @@ var errorDescriptionStyles = css({
|
|
|
24
26
|
});
|
|
25
27
|
export var ModalLoadingError = function ModalLoadingError(_ref) {
|
|
26
28
|
var url = _ref.url;
|
|
29
|
+
var _useDatasourceAnalyti = useDatasourceAnalyticsEvents(),
|
|
30
|
+
fireEvent = _useDatasourceAnalyti.fireEvent;
|
|
31
|
+
useEffect(function () {
|
|
32
|
+
fireEvent('ui.error.shown', {
|
|
33
|
+
reason: 'network'
|
|
34
|
+
});
|
|
35
|
+
}, [fireEvent]);
|
|
27
36
|
return jsx("div", {
|
|
28
37
|
css: errorContainerStyles,
|
|
29
38
|
"data-testid": "jira-jql-datasource-modal--loading-error"
|