datajunction-ui 0.0.1-a45 → 0.0.1-a45.dev5
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/package.json +3 -1
- package/src/app/components/NodeListActions.jsx +69 -0
- package/src/app/components/__tests__/NodeListActions.test.jsx +94 -0
- package/src/app/icons/CommitIcon.jsx +45 -0
- package/src/app/icons/DiffIcon.jsx +63 -0
- package/src/app/index.tsx +5 -0
- package/src/app/pages/NamespacePage/index.jsx +2 -6
- package/src/app/pages/NodePage/NodeHistory.jsx +150 -172
- package/src/app/pages/NodePage/RevisionDiff.jsx +200 -0
- package/src/app/pages/NodePage/__tests__/NodePage.test.jsx +2 -8
- package/src/app/pages/NodePage/__tests__/RevisionDiff.test.jsx +179 -0
- package/src/app/pages/NodePage/__tests__/__snapshots__/NodePage.test.jsx.snap +0 -100
- package/src/app/services/__tests__/DJService.test.jsx +51 -0
- package/src/index.tsx +1 -0
- package/src/mocks/mockNodes.jsx +47 -0
- package/src/styles/index.css +89 -0
- package/src/app/components/DeleteNode.jsx +0 -55
- package/src/app/components/__tests__/DeleteNode.test.jsx +0 -53
|
@@ -1,223 +1,201 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react';
|
|
2
|
-
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter';
|
|
3
|
-
import { foundation } from 'react-syntax-highlighter/src/styles/hljs';
|
|
4
2
|
import * as React from 'react';
|
|
3
|
+
import DiffIcon from '../../icons/DiffIcon';
|
|
4
|
+
import { labelize } from '../../../utils/form';
|
|
5
|
+
import CommitIcon from '../../icons/CommitIcon';
|
|
5
6
|
|
|
6
7
|
export default function NodeHistory({ node, djClient }) {
|
|
7
8
|
const [history, setHistory] = useState([]);
|
|
8
|
-
const [revisions, setRevisions] = useState([]);
|
|
9
9
|
|
|
10
10
|
useEffect(() => {
|
|
11
11
|
const fetchData = async () => {
|
|
12
12
|
if (node) {
|
|
13
13
|
const data = await djClient.history('node', node.name);
|
|
14
|
-
|
|
15
|
-
setHistory(data);
|
|
16
|
-
setRevisions(revisions);
|
|
14
|
+
setHistory(data.reverse());
|
|
17
15
|
}
|
|
18
16
|
};
|
|
19
17
|
fetchData().catch(console.error);
|
|
20
18
|
}, [djClient, node]);
|
|
21
19
|
|
|
22
20
|
const eventData = event => {
|
|
21
|
+
const standard = (
|
|
22
|
+
<>
|
|
23
|
+
<a href={'#'} className={'highlight-svg'} title="Browse Details">
|
|
24
|
+
<CommitIcon /> Details
|
|
25
|
+
</a>
|
|
26
|
+
</>
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
if (event.activity_type === 'update' && event.entity_type === 'node') {
|
|
30
|
+
return (
|
|
31
|
+
<>
|
|
32
|
+
<a href={`/nodes/${event.node}/revisions/${event.details.version}`}>
|
|
33
|
+
<span className={`badge version`}>{event.details.version}</span>
|
|
34
|
+
</a>
|
|
35
|
+
<a
|
|
36
|
+
href={`/nodes/${event.node}/revisions/${event.details.version}`}
|
|
37
|
+
className={'highlight-svg'}
|
|
38
|
+
title="View Diff"
|
|
39
|
+
>
|
|
40
|
+
<DiffIcon /> Diff
|
|
41
|
+
</a>
|
|
42
|
+
</>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
return '';
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const eventDescription = event => {
|
|
49
|
+
if (event.activity_type === 'create' && event.entity_type === 'node') {
|
|
50
|
+
return (
|
|
51
|
+
<div className="history-left">
|
|
52
|
+
<b style={{ textTransform: 'capitalize' }}>{event.activity_type}</b>{' '}
|
|
53
|
+
{event.entity_type}{' '}
|
|
54
|
+
<b>
|
|
55
|
+
<a href={'/nodes/' + event.entity_name}>{event.entity_name}</a>
|
|
56
|
+
</b>
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
if (event.activity_type === 'create' && event.entity_type === 'link') {
|
|
61
|
+
return (
|
|
62
|
+
<div className="history-left">
|
|
63
|
+
<b style={{ textTransform: 'capitalize' }}>{event.activity_type}</b>{' '}
|
|
64
|
+
{event.entity_type} from{' '}
|
|
65
|
+
<b>
|
|
66
|
+
<a href={'/nodes/' + event.entity_name}>{event.entity_name}</a>
|
|
67
|
+
</b>{' '}
|
|
68
|
+
to{' '}
|
|
69
|
+
<b>
|
|
70
|
+
<a href={'/nodes/' + event.details.dimension}>
|
|
71
|
+
{event.details.dimension}
|
|
72
|
+
</a>
|
|
73
|
+
</b>
|
|
74
|
+
</div>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
if (event.activity_type === 'update' && event.entity_type === 'node') {
|
|
78
|
+
return (
|
|
79
|
+
<div className="history-left">
|
|
80
|
+
<b style={{ textTransform: 'capitalize' }}>{event.activity_type}</b>{' '}
|
|
81
|
+
{event.entity_type}{' '}
|
|
82
|
+
<b>
|
|
83
|
+
<a href={'/nodes/' + event.entity_name}>{event.entity_name}</a>
|
|
84
|
+
</b>
|
|
85
|
+
</div>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
if (event.activity_type === 'tag' && event.entity_type === 'node') {
|
|
89
|
+
return (
|
|
90
|
+
<div className="history-left">
|
|
91
|
+
Add tag{event.details.tags.length > 1 ? 's' : ''}{' '}
|
|
92
|
+
{event.details.tags.map(tag => (
|
|
93
|
+
<span className={'badge version'}>
|
|
94
|
+
<a href={`/tags/${tag}`}>{tag}</a>
|
|
95
|
+
</span>
|
|
96
|
+
))}
|
|
97
|
+
</div>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
if (event.activity_type === 'create' && event.entity_type === 'partition') {
|
|
101
|
+
return (
|
|
102
|
+
<div className="history-left">
|
|
103
|
+
Set <b>{event.details.partition.type_} partition</b> on{' '}
|
|
104
|
+
<a href={'/nodes/' + event.node}>{event.details.column}</a>
|
|
105
|
+
</div>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
23
109
|
if (
|
|
24
110
|
event.activity_type === 'set_attribute' &&
|
|
25
111
|
event.entity_type === 'column_attribute'
|
|
26
112
|
) {
|
|
27
|
-
return
|
|
28
|
-
|
|
29
|
-
<
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
Set{' '}
|
|
36
|
-
<span className={`badge partition_value`}>
|
|
37
|
-
{event.details.column}
|
|
38
|
-
</span>{' '}
|
|
39
|
-
as{' '}
|
|
40
|
-
<span className={`badge partition_value_highlight`}>
|
|
41
|
-
{attr.name}
|
|
42
|
-
</span>
|
|
43
|
-
</div>
|
|
44
|
-
))
|
|
45
|
-
.reduce((prev, curr) => [prev, <br />, curr], []);
|
|
113
|
+
return (
|
|
114
|
+
<div className="history-left">
|
|
115
|
+
<b>Set column attributes</b> on{' '}
|
|
116
|
+
<b>
|
|
117
|
+
<a href={'/nodes/' + event.node}>{event.node}</a>
|
|
118
|
+
</b>
|
|
119
|
+
</div>
|
|
120
|
+
);
|
|
46
121
|
}
|
|
47
|
-
|
|
122
|
+
|
|
123
|
+
if (event.entity_type === 'materialization') {
|
|
48
124
|
return (
|
|
49
|
-
<div
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
aria-label="HistoryCreateLink"
|
|
53
|
-
aria-hidden="false"
|
|
54
|
-
>
|
|
55
|
-
Linked{' '}
|
|
56
|
-
<span className={`badge partition_value`}>
|
|
57
|
-
{event.details.column}
|
|
58
|
-
</span>{' '}
|
|
59
|
-
to
|
|
60
|
-
<span className={`badge partition_value_highlight`}>
|
|
61
|
-
{event.details.dimension}
|
|
125
|
+
<div className="history-left">
|
|
126
|
+
<span style={{ textTransform: 'capitalize' }}>
|
|
127
|
+
{event.activity_type}
|
|
62
128
|
</span>{' '}
|
|
63
|
-
|
|
64
|
-
<
|
|
65
|
-
{event.
|
|
66
|
-
</
|
|
129
|
+
<b>{event.entity_type}</b>{' '}
|
|
130
|
+
<a href={`/nodes/${event.node}/materializations`}>
|
|
131
|
+
{event.entity_name}
|
|
132
|
+
</a>
|
|
67
133
|
</div>
|
|
68
134
|
);
|
|
69
135
|
}
|
|
136
|
+
|
|
70
137
|
if (
|
|
71
|
-
event.activity_type === '
|
|
72
|
-
event.entity_type === '
|
|
138
|
+
event.activity_type === 'status_change' &&
|
|
139
|
+
event.entity_type === 'node'
|
|
73
140
|
) {
|
|
74
141
|
return (
|
|
75
|
-
<div
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
Initialized materialization{' '}
|
|
82
|
-
<span className={`badge partition_value`}>
|
|
83
|
-
{event.details.materialization}
|
|
84
|
-
</span>
|
|
142
|
+
<div className="history-left">
|
|
143
|
+
<b style={{ textTransform: 'capitalize' }}>
|
|
144
|
+
{labelize(event.activity_type)}
|
|
145
|
+
</b>{' '}
|
|
146
|
+
on <a href={`/nodes/${event.node}`}>{event.node}</a> from{' '}
|
|
147
|
+
<b>{event.pre.status}</b> to <b>{event.post.status}</b>
|
|
85
148
|
</div>
|
|
86
149
|
);
|
|
87
150
|
}
|
|
151
|
+
|
|
88
152
|
if (
|
|
89
153
|
event.activity_type === 'create' &&
|
|
90
154
|
event.entity_type === 'availability'
|
|
91
155
|
) {
|
|
92
156
|
return (
|
|
93
|
-
<div
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
aria-label="HistoryCreateAvailability"
|
|
97
|
-
aria-hidden="false"
|
|
98
|
-
>
|
|
99
|
-
Materialized at{' '}
|
|
100
|
-
<span className={`badge partition_value_highlight`}>
|
|
157
|
+
<div className="history-left">
|
|
158
|
+
Materialized table{' '}
|
|
159
|
+
<code>
|
|
101
160
|
{event.post.catalog}.{event.post.schema_}.{event.post.table}
|
|
102
|
-
</
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
</span>{' '}
|
|
107
|
-
to
|
|
108
|
-
<span className={`badge partition_value`}>
|
|
109
|
-
{event.post.max_temporal_partition}
|
|
110
|
-
</span>
|
|
161
|
+
</code>{' '}
|
|
162
|
+
with partitions between {event.post.min_temporal_partition} and{' '}
|
|
163
|
+
{event.post.max_temporal_partition} available for{' '}
|
|
164
|
+
<a href={'/nodes/' + event.node}>{event.node}</a>.
|
|
111
165
|
</div>
|
|
112
166
|
);
|
|
113
167
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
event.entity_type === 'node'
|
|
117
|
-
) {
|
|
118
|
-
const expr = (
|
|
119
|
-
<div>
|
|
120
|
-
Caused by a change in upstream{' '}
|
|
121
|
-
<a href={`/nodes/${event.details['upstream_node']}`}>
|
|
122
|
-
{event.details['upstream_node']}
|
|
123
|
-
</a>
|
|
124
|
-
</div>
|
|
125
|
-
);
|
|
168
|
+
|
|
169
|
+
if (event.activity_type === 'create' && event.entity_type === 'backfill') {
|
|
126
170
|
return (
|
|
127
|
-
<div
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
>
|
|
133
|
-
Status changed from{' '}
|
|
134
|
-
<span className={`status__${event.pre['status']}`}>
|
|
135
|
-
{event.pre['status']}
|
|
136
|
-
</span>{' '}
|
|
137
|
-
to{' '}
|
|
138
|
-
<span className={`status__${event.post['status']}`}>
|
|
139
|
-
{event.post['status']}
|
|
140
|
-
</span>{' '}
|
|
141
|
-
{event.details['upstream_node'] !== undefined ? expr : ''}
|
|
171
|
+
<div className="history-left">
|
|
172
|
+
Backfill created for materialization {event.details.materialization}{' '}
|
|
173
|
+
for partition {event.details.partition.column_name} from{' '}
|
|
174
|
+
{event.details.partition.range[0]} to{' '}
|
|
175
|
+
{event.details.partition.range[1]}
|
|
142
176
|
</div>
|
|
143
177
|
);
|
|
144
178
|
}
|
|
145
|
-
return (
|
|
146
|
-
<div key={event.id}>
|
|
147
|
-
{JSON.stringify(event.details) === '{}'
|
|
148
|
-
? ''
|
|
149
|
-
: JSON.stringify(event.details)}
|
|
150
|
-
</div>
|
|
151
|
-
);
|
|
152
179
|
};
|
|
153
180
|
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
className={`history_type__${event.activity_type} badge node_type`}
|
|
160
|
-
>
|
|
161
|
-
{event.activity_type}
|
|
162
|
-
</span>
|
|
163
|
-
</td>
|
|
164
|
-
<td>{event.entity_type}</td>
|
|
165
|
-
<td>{event.entity_name}</td>
|
|
166
|
-
<td>{event.user ? event.user : 'unknown'}</td>
|
|
167
|
-
<td>{event.created_at}</td>
|
|
168
|
-
<td>{eventData(event)}</td>
|
|
169
|
-
</tr>
|
|
170
|
-
));
|
|
171
|
-
};
|
|
181
|
+
const removeTagNodeEventsWithoutTags = event =>
|
|
182
|
+
event.activity_type !== 'tag' ||
|
|
183
|
+
(event.activity_type === 'tag' &&
|
|
184
|
+
event.entity_type === 'node' &&
|
|
185
|
+
event.details.tags.length > 0);
|
|
172
186
|
|
|
173
|
-
const revisionsTable = revisions => {
|
|
174
|
-
return revisions.map(revision => (
|
|
175
|
-
<tr key={revision.version}>
|
|
176
|
-
<td className="text-start">
|
|
177
|
-
<span className={`badge node_type__source`}>{revision.version}</span>
|
|
178
|
-
</td>
|
|
179
|
-
<td>{revision.display_name}</td>
|
|
180
|
-
<td>{revision.description}</td>
|
|
181
|
-
<td>
|
|
182
|
-
<SyntaxHighlighter
|
|
183
|
-
language="sql"
|
|
184
|
-
style={foundation}
|
|
185
|
-
wrapLongLines={true}
|
|
186
|
-
>
|
|
187
|
-
{revision.query}
|
|
188
|
-
</SyntaxHighlighter>
|
|
189
|
-
</td>
|
|
190
|
-
<td>{revision.tags}</td>
|
|
191
|
-
</tr>
|
|
192
|
-
));
|
|
193
|
-
};
|
|
194
187
|
return (
|
|
195
|
-
<
|
|
196
|
-
|
|
197
|
-
<
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
<
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
</table>
|
|
208
|
-
<table className="card-inner-table table" aria-label="Activity">
|
|
209
|
-
<thead className="fs-7 fw-bold text-gray-400 border-bottom-0">
|
|
210
|
-
<tr>
|
|
211
|
-
<th className="text-start">Activity</th>
|
|
212
|
-
<th>Type</th>
|
|
213
|
-
<th>Name</th>
|
|
214
|
-
<th>User</th>
|
|
215
|
-
<th>Timestamp</th>
|
|
216
|
-
<th>Details</th>
|
|
217
|
-
</tr>
|
|
218
|
-
</thead>
|
|
219
|
-
<tbody>{tableData(history)}</tbody>
|
|
220
|
-
</table>
|
|
221
|
-
</div>
|
|
188
|
+
<ul className="history-border" role="list" aria-label="Activity">
|
|
189
|
+
{history.filter(removeTagNodeEventsWithoutTags).map(event => (
|
|
190
|
+
<li key={`history-row-${event.id}`} className="history">
|
|
191
|
+
{eventDescription(event)}
|
|
192
|
+
<div className={'history-small'}>
|
|
193
|
+
done by <a href="#">{event.user ? event.user : 'unknown'}</a> on{' '}
|
|
194
|
+
{new Date(Date.parse(event.created_at)).toLocaleString()}
|
|
195
|
+
</div>
|
|
196
|
+
<div className="history-right">{eventData(event)}</div>
|
|
197
|
+
</li>
|
|
198
|
+
))}
|
|
199
|
+
</ul>
|
|
222
200
|
);
|
|
223
201
|
}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { useContext, useEffect, useState } from 'react';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { diffLines, formatLines } from 'unidiff';
|
|
4
|
+
import { parseDiff, Diff, Hunk } from 'react-diff-view';
|
|
5
|
+
|
|
6
|
+
import { useParams } from 'react-router-dom';
|
|
7
|
+
import DJClientContext from '../../providers/djclient';
|
|
8
|
+
import NamespaceHeader from '../../components/NamespaceHeader';
|
|
9
|
+
import { labelize } from '../../../utils/form';
|
|
10
|
+
import DiffIcon from '../../icons/DiffIcon';
|
|
11
|
+
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter';
|
|
12
|
+
import { foundation } from 'react-syntax-highlighter/src/styles/hljs';
|
|
13
|
+
import sql from 'react-syntax-highlighter/dist/cjs/languages/hljs/sql';
|
|
14
|
+
|
|
15
|
+
SyntaxHighlighter.registerLanguage('sql', sql);
|
|
16
|
+
foundation.hljs['padding'] = '2rem';
|
|
17
|
+
|
|
18
|
+
export default function RevisionDiff() {
|
|
19
|
+
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
20
|
+
const [revisions, setRevisions] = useState([]);
|
|
21
|
+
|
|
22
|
+
const { name, revision } = useParams();
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
const fetchData = async () => {
|
|
26
|
+
const revisions = await djClient.revisions(name);
|
|
27
|
+
setRevisions(revisions);
|
|
28
|
+
};
|
|
29
|
+
fetchData().catch(console.error);
|
|
30
|
+
}, [djClient, name]);
|
|
31
|
+
|
|
32
|
+
const thisRevision = revisions
|
|
33
|
+
.map((rev, idx) => [idx, rev])
|
|
34
|
+
.filter((rev, idx) => {
|
|
35
|
+
return rev[1].version === revision;
|
|
36
|
+
});
|
|
37
|
+
const prevRevision = revisions.filter(
|
|
38
|
+
(rev, idx) => idx + 1 === thisRevision[0][0],
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const EMPTY_HUNKS = [];
|
|
42
|
+
|
|
43
|
+
const revisionDiff = (older, newer) => {
|
|
44
|
+
const diffObj = {};
|
|
45
|
+
const fields = [
|
|
46
|
+
'display_name',
|
|
47
|
+
'version',
|
|
48
|
+
'query',
|
|
49
|
+
'mode',
|
|
50
|
+
'status',
|
|
51
|
+
'description',
|
|
52
|
+
'columns',
|
|
53
|
+
// 'catalog',
|
|
54
|
+
'schema',
|
|
55
|
+
'table',
|
|
56
|
+
'updated_at',
|
|
57
|
+
];
|
|
58
|
+
if (older) {
|
|
59
|
+
for (const key of fields) {
|
|
60
|
+
if (older[key] && (key !== 'columns' || older.type === 'cube')) {
|
|
61
|
+
diffObj[key] = {};
|
|
62
|
+
diffObj[key].diffText = formatLines(
|
|
63
|
+
diffLines(
|
|
64
|
+
older
|
|
65
|
+
? key === 'columns'
|
|
66
|
+
? older[key].map(col => col.name).join('\n')
|
|
67
|
+
: older[key].toString()
|
|
68
|
+
: '',
|
|
69
|
+
newer
|
|
70
|
+
? key === 'columns'
|
|
71
|
+
? newer[key].map(col => col.name).join('\n')
|
|
72
|
+
: newer[key].toString()
|
|
73
|
+
: '',
|
|
74
|
+
),
|
|
75
|
+
{
|
|
76
|
+
context: 5000,
|
|
77
|
+
},
|
|
78
|
+
);
|
|
79
|
+
const [diff] = parseDiff(diffObj[key].diffText, {
|
|
80
|
+
nearbySequences: 'zip',
|
|
81
|
+
});
|
|
82
|
+
diffObj[key].diff = diff;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return diffObj;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const diffObjects = revisionDiff(
|
|
90
|
+
prevRevision[0],
|
|
91
|
+
thisRevision[0] ? thisRevision[0][1] : thisRevision[0],
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<div className="node__header">
|
|
96
|
+
<NamespaceHeader
|
|
97
|
+
namespace={(prevRevision[0] ? prevRevision[0].name : '')
|
|
98
|
+
.split('.')
|
|
99
|
+
.slice(0, -1)
|
|
100
|
+
.join('.')}
|
|
101
|
+
/>
|
|
102
|
+
<div className="card">
|
|
103
|
+
<div className="card-header">
|
|
104
|
+
<h3
|
|
105
|
+
className="card-title align-items-start flex-column"
|
|
106
|
+
style={{ display: 'inline-block' }}
|
|
107
|
+
>
|
|
108
|
+
<span
|
|
109
|
+
className="card-label fw-bold text-gray-800"
|
|
110
|
+
role="dialog"
|
|
111
|
+
aria-hidden="false"
|
|
112
|
+
aria-label="DisplayName"
|
|
113
|
+
>
|
|
114
|
+
<a
|
|
115
|
+
href={'/nodes/' + prevRevision[0]?.name}
|
|
116
|
+
className=""
|
|
117
|
+
role="dialog"
|
|
118
|
+
aria-hidden="false"
|
|
119
|
+
aria-label="NodeName"
|
|
120
|
+
>
|
|
121
|
+
{prevRevision[0]?.name}
|
|
122
|
+
</a>{' '}
|
|
123
|
+
<span
|
|
124
|
+
className={
|
|
125
|
+
'node_type__' + prevRevision[0]?.type + ' badge node_type'
|
|
126
|
+
}
|
|
127
|
+
role="dialog"
|
|
128
|
+
aria-hidden="false"
|
|
129
|
+
aria-label="NodeType"
|
|
130
|
+
>
|
|
131
|
+
{prevRevision[0]?.type}
|
|
132
|
+
</span>
|
|
133
|
+
</span>
|
|
134
|
+
</h3>
|
|
135
|
+
<div>
|
|
136
|
+
<span
|
|
137
|
+
className="rounded-pill badge version"
|
|
138
|
+
style={{ marginLeft: '0.5rem', fontSize: '16px' }}
|
|
139
|
+
>
|
|
140
|
+
{prevRevision[0]?.version}
|
|
141
|
+
</span>
|
|
142
|
+
<DiffIcon />
|
|
143
|
+
<span
|
|
144
|
+
className="rounded-pill badge version"
|
|
145
|
+
style={{ marginLeft: '0.3rem', fontSize: '16px' }}
|
|
146
|
+
>
|
|
147
|
+
{thisRevision[0] ? thisRevision[0][1].version : ''}
|
|
148
|
+
</span>{' '}
|
|
149
|
+
</div>
|
|
150
|
+
{Object.keys(diffObjects).map(field => {
|
|
151
|
+
return (
|
|
152
|
+
<div className="diff">
|
|
153
|
+
<h4>
|
|
154
|
+
{labelize(field)}{' '}
|
|
155
|
+
<small className="no-change-banner">
|
|
156
|
+
{diffObjects[field]?.diff.hunks.length > 0
|
|
157
|
+
? ''
|
|
158
|
+
: 'no change'}
|
|
159
|
+
</small>
|
|
160
|
+
</h4>
|
|
161
|
+
{diffObjects[field]?.diff.hunks.length > 0 ? (
|
|
162
|
+
<Diff
|
|
163
|
+
viewType="split"
|
|
164
|
+
diffType=""
|
|
165
|
+
hunks={diffObjects[field]?.diff.hunks || EMPTY_HUNKS}
|
|
166
|
+
tokens={diffObjects[field]?.tokens}
|
|
167
|
+
>
|
|
168
|
+
{hunks =>
|
|
169
|
+
hunks.map(hunk => <Hunk key={hunk.content} hunk={hunk} />)
|
|
170
|
+
}
|
|
171
|
+
</Diff>
|
|
172
|
+
) : (
|
|
173
|
+
<div className="no-change">
|
|
174
|
+
{prevRevision[0] ? (
|
|
175
|
+
field === 'query' ? (
|
|
176
|
+
<>
|
|
177
|
+
<SyntaxHighlighter
|
|
178
|
+
language="sql"
|
|
179
|
+
style={foundation}
|
|
180
|
+
wrapLongLines={true}
|
|
181
|
+
>
|
|
182
|
+
{prevRevision[0].query}
|
|
183
|
+
</SyntaxHighlighter>
|
|
184
|
+
</>
|
|
185
|
+
) : (
|
|
186
|
+
prevRevision[0][field].toString()
|
|
187
|
+
)
|
|
188
|
+
) : (
|
|
189
|
+
''
|
|
190
|
+
)}
|
|
191
|
+
</div>
|
|
192
|
+
)}
|
|
193
|
+
</div>
|
|
194
|
+
);
|
|
195
|
+
})}
|
|
196
|
+
</div>
|
|
197
|
+
</div>
|
|
198
|
+
</div>
|
|
199
|
+
);
|
|
200
|
+
}
|
|
@@ -501,15 +501,9 @@ describe('<NodePage />', () => {
|
|
|
501
501
|
'node',
|
|
502
502
|
mocks.mockMetricNode.name,
|
|
503
503
|
);
|
|
504
|
-
expect(djClient.DataJunctionAPI.revisions).toHaveBeenCalledWith(
|
|
505
|
-
mocks.mockMetricNode.name,
|
|
506
|
-
);
|
|
507
504
|
expect(
|
|
508
|
-
screen.getByRole('
|
|
509
|
-
).
|
|
510
|
-
expect(screen.getByRole('table', { name: 'Activity' })).toHaveTextContent(
|
|
511
|
-
'ActivityTypeNameUserTimestampDetailscreatenodedefault.avg_repair_priceunknown2023-08-21T16:48:56.950482+00:00',
|
|
512
|
-
);
|
|
505
|
+
screen.getByRole('list', { name: 'Activity' }),
|
|
506
|
+
).toBeInTheDocument();
|
|
513
507
|
screen
|
|
514
508
|
.queryAllByRole('cell', {
|
|
515
509
|
name: 'HistoryAttribute',
|