datajunction-ui 0.0.1-a46 → 0.0.1-a46.dev3
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/Makefile +0 -5
- package/package.json +2 -2
- package/src/app/pages/NodePage/AddBackfillPopover.jsx +51 -46
- package/src/app/pages/NodePage/AddMaterializationPopover.jsx +24 -33
- package/src/app/pages/NodePage/MaterializationConfigField.jsx +31 -38
- package/src/app/pages/NodePage/NodeMaterializationTab.jsx +110 -179
- package/src/app/pages/NodePage/__tests__/AddBackfillPopover.test.jsx +3 -13
- package/src/app/pages/NodePage/__tests__/NodePage.test.jsx +5 -12
- package/src/app/pages/NodePage/__tests__/__snapshots__/NodePage.test.jsx.snap +191 -276
- package/src/app/services/DJService.js +25 -26
- package/src/app/services/__tests__/DJService.test.jsx +21 -37
- package/src/mocks/mockNodes.jsx +7 -61
- package/src/styles/index.css +11 -113
- package/src/app/components/NodeMaterializationDelete.jsx +0 -80
- package/src/app/pages/NodePage/PartitionValueForm.jsx +0 -60
package/src/mocks/mockNodes.jsx
CHANGED
|
@@ -41,9 +41,7 @@ export const mocks = {
|
|
|
41
41
|
type: 'string',
|
|
42
42
|
attributes: [],
|
|
43
43
|
dimension: null,
|
|
44
|
-
partition:
|
|
45
|
-
type_: 'categorical',
|
|
46
|
-
},
|
|
44
|
+
partition: null,
|
|
47
45
|
},
|
|
48
46
|
],
|
|
49
47
|
updated_at: '2024-01-24T16:39:14.029366+00:00',
|
|
@@ -463,14 +461,12 @@ export const mocks = {
|
|
|
463
461
|
{
|
|
464
462
|
backfills: [
|
|
465
463
|
{
|
|
466
|
-
spec:
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
],
|
|
473
|
-
urls: ['a', 'b'],
|
|
464
|
+
spec: {
|
|
465
|
+
column_name: 'default_DOT_hard_hat_DOT_hire_date',
|
|
466
|
+
values: null,
|
|
467
|
+
range: ['20230101', '20230102'],
|
|
468
|
+
},
|
|
469
|
+
urls: [],
|
|
474
470
|
},
|
|
475
471
|
],
|
|
476
472
|
name: 'country_birth_date_contractor_id_379232101',
|
|
@@ -481,7 +477,6 @@ export const mocks = {
|
|
|
481
477
|
"SELECT default_DOT_hard_hats.address,\n\tdefault_DOT_hard_hats.birth_date,\n\tdefault_DOT_hard_hats.city,\n\tdefault_DOT_hard_hats.contractor_id,\n\tdefault_DOT_hard_hats.country,\n\tdefault_DOT_hard_hats.first_name,\n\tdefault_DOT_hard_hats.hard_hat_id,\n\tdefault_DOT_hard_hats.hire_date,\n\tdefault_DOT_hard_hats.last_name,\n\tdefault_DOT_hard_hats.manager,\n\tdefault_DOT_hard_hats.postal_code,\n\tdefault_DOT_hard_hats.state,\n\tdefault_DOT_hard_hats.title \n FROM roads.hard_hats AS default_DOT_hard_hats \n WHERE default_DOT_hard_hats.country IN ('DE', 'MY') AND default_DOT_hard_hats.contractor_id BETWEEN 1 AND 10\n\n",
|
|
482
478
|
upstream_tables: ['default.roads.hard_hats'],
|
|
483
479
|
},
|
|
484
|
-
strategy: 'incremental_time',
|
|
485
480
|
schedule: '0 * * * *',
|
|
486
481
|
job: 'SparkSqlMaterializationJob',
|
|
487
482
|
output_tables: ['common.a', 'common.b'],
|
|
@@ -1558,53 +1553,4 @@ export const mocks = {
|
|
|
1558
1553
|
tag_type: 'reports',
|
|
1559
1554
|
},
|
|
1560
1555
|
],
|
|
1561
|
-
materializationInfo: {
|
|
1562
|
-
job_types: [
|
|
1563
|
-
{
|
|
1564
|
-
name: 'spark_sql',
|
|
1565
|
-
label: 'Spark SQL',
|
|
1566
|
-
description: 'Spark SQL materialization job',
|
|
1567
|
-
allowed_node_types: ['transform', 'dimension', 'cube'],
|
|
1568
|
-
job_class: 'SparkSqlMaterializationJob',
|
|
1569
|
-
},
|
|
1570
|
-
{
|
|
1571
|
-
name: 'druid_measures_cube',
|
|
1572
|
-
label: 'Druid Measures Cube (Pre-Agg Cube)',
|
|
1573
|
-
description:
|
|
1574
|
-
"Used to materialize a cube's measures to Druid for low-latency access to a set of metrics and dimensions. While the logical cube definition is at the level of metrics and dimensions, this materialized Druid cube will contain measures and dimensions, with rollup configured on the measures where appropriate.",
|
|
1575
|
-
allowed_node_types: ['cube'],
|
|
1576
|
-
job_class: 'DruidMeasuresCubeMaterializationJob',
|
|
1577
|
-
},
|
|
1578
|
-
{
|
|
1579
|
-
name: 'druid_metrics_cube',
|
|
1580
|
-
label: 'Druid Metrics Cube (Post-Agg Cube)',
|
|
1581
|
-
description:
|
|
1582
|
-
"Used to materialize a cube of metrics and dimensions to Druid for low-latency access. The materialized cube is at the metric level, meaning that all metrics will be aggregated to the level of the cube's dimensions.",
|
|
1583
|
-
allowed_node_types: ['cube'],
|
|
1584
|
-
job_class: 'DruidMetricsCubeMaterializationJob',
|
|
1585
|
-
},
|
|
1586
|
-
],
|
|
1587
|
-
strategies: [
|
|
1588
|
-
{
|
|
1589
|
-
name: 'full',
|
|
1590
|
-
label: 'Full',
|
|
1591
|
-
},
|
|
1592
|
-
{
|
|
1593
|
-
name: 'snapshot',
|
|
1594
|
-
label: 'Snapshot',
|
|
1595
|
-
},
|
|
1596
|
-
{
|
|
1597
|
-
name: 'snapshot_partition',
|
|
1598
|
-
label: 'Snapshot Partition',
|
|
1599
|
-
},
|
|
1600
|
-
{
|
|
1601
|
-
name: 'incremental_time',
|
|
1602
|
-
label: 'Incremental Time',
|
|
1603
|
-
},
|
|
1604
|
-
{
|
|
1605
|
-
name: 'view',
|
|
1606
|
-
label: 'View',
|
|
1607
|
-
},
|
|
1608
|
-
],
|
|
1609
|
-
},
|
|
1610
1556
|
};
|
package/src/styles/index.css
CHANGED
|
@@ -593,12 +593,6 @@ tbody th {
|
|
|
593
593
|
color: #777777;
|
|
594
594
|
}
|
|
595
595
|
|
|
596
|
-
.strategy {
|
|
597
|
-
background-color: rgb(255, 239, 215) !important;
|
|
598
|
-
color: #6c3b21;
|
|
599
|
-
font-size: 1rem;
|
|
600
|
-
}
|
|
601
|
-
|
|
602
596
|
.status__valid {
|
|
603
597
|
color: #00b368;
|
|
604
598
|
}
|
|
@@ -1024,19 +1018,17 @@ pre {
|
|
|
1024
1018
|
}
|
|
1025
1019
|
|
|
1026
1020
|
.add_button {
|
|
1027
|
-
background-color: #
|
|
1028
|
-
color: #
|
|
1029
|
-
text-transform:
|
|
1021
|
+
background-color: #f0f8ff !important;
|
|
1022
|
+
color: #24518f;
|
|
1023
|
+
text-transform: uppercase;
|
|
1030
1024
|
vertical-align: middle;
|
|
1031
|
-
padding
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
padding-bottom: 0.5rem;
|
|
1035
|
-
margin-bottom: 0.5rem !important;
|
|
1036
|
-
font-size: 1rem;
|
|
1025
|
+
padding: 0.2rem 0.5rem 0.1rem 0.5rem;
|
|
1026
|
+
border: 1px solid #819bc0;
|
|
1027
|
+
font-size: 1.2rem;
|
|
1037
1028
|
border-radius: 0.5rem;
|
|
1038
1029
|
word-wrap: break-word;
|
|
1039
1030
|
white-space: break-spaces;
|
|
1031
|
+
margin-left: 1rem;
|
|
1040
1032
|
}
|
|
1041
1033
|
|
|
1042
1034
|
.edit_button {
|
|
@@ -1098,6 +1090,10 @@ pre {
|
|
|
1098
1090
|
transition: opacity 0.15s linear;
|
|
1099
1091
|
}
|
|
1100
1092
|
|
|
1093
|
+
.partitionLink:hover {
|
|
1094
|
+
text-decoration: none;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1101
1097
|
.dimensionsList {
|
|
1102
1098
|
padding: 12px;
|
|
1103
1099
|
opacity: 1;
|
|
@@ -1220,102 +1216,4 @@ pre {
|
|
|
1220
1216
|
background-color: #ffffff;
|
|
1221
1217
|
margin-bottom: 3px;
|
|
1222
1218
|
margin-left: -20px;
|
|
1223
|
-
}
|
|
1224
|
-
|
|
1225
|
-
.partitionLink {
|
|
1226
|
-
/*border: 1px solid #ccc4d5;*/
|
|
1227
|
-
padding: 12px;
|
|
1228
|
-
margin: 5px;
|
|
1229
|
-
border-radius: 0.375rem;
|
|
1230
|
-
background-color: #ccc4d525;
|
|
1231
|
-
}
|
|
1232
|
-
.partitionLink:hover {
|
|
1233
|
-
background-color: rgba(157, 147, 168, 0.15);
|
|
1234
|
-
}
|
|
1235
|
-
.partitionLink a:hover {
|
|
1236
|
-
text-decoration: none;
|
|
1237
|
-
}
|
|
1238
|
-
|
|
1239
|
-
.backfills {
|
|
1240
|
-
margin-left: -4rem;
|
|
1241
|
-
--spacing : 1.5rem;
|
|
1242
|
-
--radius : 10px;
|
|
1243
|
-
}
|
|
1244
|
-
|
|
1245
|
-
.backfills li{
|
|
1246
|
-
display : block;
|
|
1247
|
-
position : relative;
|
|
1248
|
-
padding-left : calc(2 * var(--spacing) - var(--radius) - 2px);
|
|
1249
|
-
}
|
|
1250
|
-
|
|
1251
|
-
.backfills ul{
|
|
1252
|
-
margin-left : calc(var(--radius) - var(--spacing));
|
|
1253
|
-
padding-left : 2rem;
|
|
1254
|
-
}
|
|
1255
|
-
|
|
1256
|
-
.backfills ul li{
|
|
1257
|
-
border-left : 2px solid #ddd;
|
|
1258
|
-
}
|
|
1259
|
-
|
|
1260
|
-
.backfills ul li:last-child{
|
|
1261
|
-
border-color : transparent;
|
|
1262
|
-
}
|
|
1263
|
-
|
|
1264
|
-
.backfills ul li::before{
|
|
1265
|
-
content : '';
|
|
1266
|
-
display : block;
|
|
1267
|
-
position : absolute;
|
|
1268
|
-
top : calc(var(--spacing) / -2);
|
|
1269
|
-
left : -2px;
|
|
1270
|
-
width : calc(var(--spacing) + 2px);
|
|
1271
|
-
height : calc(var(--spacing) + 1px);
|
|
1272
|
-
border : solid #ddd;
|
|
1273
|
-
border-width : 0 0 2px 2px;
|
|
1274
|
-
}
|
|
1275
|
-
|
|
1276
|
-
.backfills summary{
|
|
1277
|
-
display : block;
|
|
1278
|
-
cursor : pointer;
|
|
1279
|
-
margin-bottom: 10px;
|
|
1280
|
-
}
|
|
1281
|
-
|
|
1282
|
-
.backfills summary::marker,
|
|
1283
|
-
.backfills summary::-webkit-details-marker{
|
|
1284
|
-
display : none;
|
|
1285
|
-
}
|
|
1286
|
-
|
|
1287
|
-
.backfills summary:focus{
|
|
1288
|
-
outline : none;
|
|
1289
|
-
}
|
|
1290
|
-
|
|
1291
|
-
.backfills summary:focus-visible{
|
|
1292
|
-
outline : 1px dotted #000;
|
|
1293
|
-
}
|
|
1294
|
-
|
|
1295
|
-
.backfills summary::before{
|
|
1296
|
-
z-index : 1;
|
|
1297
|
-
/*background : #696 url('expand-collapse.svg') 0 0;*/
|
|
1298
|
-
}
|
|
1299
|
-
|
|
1300
|
-
.backfills details[open] > summary::before{
|
|
1301
|
-
background-position : calc(-2 * var(--radius)) 0;
|
|
1302
|
-
}
|
|
1303
|
-
|
|
1304
|
-
.backfills_header {
|
|
1305
|
-
font-size: 16px;
|
|
1306
|
-
margin-left: 18px;
|
|
1307
|
-
border-left: 2px solid #ddd;
|
|
1308
|
-
padding-left: 40px;
|
|
1309
|
-
margin-bottom: 10px;
|
|
1310
|
-
}
|
|
1311
|
-
|
|
1312
|
-
.tr {
|
|
1313
|
-
display: inline-flex;
|
|
1314
|
-
}
|
|
1315
|
-
.tr li {
|
|
1316
|
-
padding-right: 10px;
|
|
1317
|
-
}
|
|
1318
|
-
.td {
|
|
1319
|
-
display: table-cell;
|
|
1320
|
-
padding: 8px;
|
|
1321
1219
|
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import DJClientContext from '../providers/djclient';
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
import DeleteIcon from '../icons/DeleteIcon';
|
|
4
|
-
import { Form, Formik } from 'formik';
|
|
5
|
-
import { useContext } from 'react';
|
|
6
|
-
import { displayMessageAfterSubmit } from '../../utils/form';
|
|
7
|
-
|
|
8
|
-
export default function NodeMaterializationDelete({
|
|
9
|
-
nodeName,
|
|
10
|
-
materializationName,
|
|
11
|
-
}) {
|
|
12
|
-
const [deleteButton, setDeleteButton] = React.useState(<DeleteIcon />);
|
|
13
|
-
|
|
14
|
-
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
15
|
-
const deleteNode = async (values, { setStatus }) => {
|
|
16
|
-
if (
|
|
17
|
-
!window.confirm(
|
|
18
|
-
'Deleting materialization job ' +
|
|
19
|
-
values.materializationName +
|
|
20
|
-
'. Are you sure?',
|
|
21
|
-
)
|
|
22
|
-
) {
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
const { status, json } = await djClient.deleteMaterialization(
|
|
26
|
-
values.nodeName,
|
|
27
|
-
values.materializationName,
|
|
28
|
-
);
|
|
29
|
-
if (status === 200 || status === 201 || status === 204) {
|
|
30
|
-
window.location.reload();
|
|
31
|
-
setStatus({
|
|
32
|
-
success: (
|
|
33
|
-
<>
|
|
34
|
-
Successfully deleted materialization job:{' '}
|
|
35
|
-
{values.materializationName}
|
|
36
|
-
</>
|
|
37
|
-
),
|
|
38
|
-
});
|
|
39
|
-
setDeleteButton(''); // hide the Delete button
|
|
40
|
-
} else {
|
|
41
|
-
setStatus({
|
|
42
|
-
failure: `${json.message}`,
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const initialValues = {
|
|
48
|
-
nodeName: nodeName,
|
|
49
|
-
materializationName: materializationName,
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
return (
|
|
53
|
-
<div>
|
|
54
|
-
<Formik initialValues={initialValues} onSubmit={deleteNode}>
|
|
55
|
-
{function Render({ status, setFieldValue }) {
|
|
56
|
-
return (
|
|
57
|
-
<Form className="deleteNode">
|
|
58
|
-
{displayMessageAfterSubmit(status)}
|
|
59
|
-
{
|
|
60
|
-
<>
|
|
61
|
-
<button
|
|
62
|
-
type="submit"
|
|
63
|
-
style={{
|
|
64
|
-
marginLeft: 0,
|
|
65
|
-
all: 'unset',
|
|
66
|
-
color: '#005c72',
|
|
67
|
-
cursor: 'pointer',
|
|
68
|
-
}}
|
|
69
|
-
>
|
|
70
|
-
{deleteButton}
|
|
71
|
-
</button>
|
|
72
|
-
</>
|
|
73
|
-
}
|
|
74
|
-
</Form>
|
|
75
|
-
);
|
|
76
|
-
}}
|
|
77
|
-
</Formik>
|
|
78
|
-
</div>
|
|
79
|
-
);
|
|
80
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { Field } from 'formik';
|
|
3
|
-
|
|
4
|
-
export default function PartitionValueForm({ col, materialization }) {
|
|
5
|
-
if (col.partition.type_ === 'temporal') {
|
|
6
|
-
return (
|
|
7
|
-
<>
|
|
8
|
-
<div
|
|
9
|
-
className="partition__full"
|
|
10
|
-
key={col.name}
|
|
11
|
-
style={{ width: '50%' }}
|
|
12
|
-
>
|
|
13
|
-
<div className="partition__header">{col.display_name}</div>
|
|
14
|
-
<div className="partition__body">
|
|
15
|
-
<span style={{ padding: '0.5rem' }}>From</span>{' '}
|
|
16
|
-
<Field
|
|
17
|
-
type="text"
|
|
18
|
-
name={`partitionValues.['${col.name}'].from`}
|
|
19
|
-
id={`${col.name}.from`}
|
|
20
|
-
placeholder="20230101"
|
|
21
|
-
default="20230101"
|
|
22
|
-
style={{ width: '7rem', paddingRight: '1rem' }}
|
|
23
|
-
/>{' '}
|
|
24
|
-
<span style={{ padding: '0.5rem' }}>To</span>
|
|
25
|
-
<Field
|
|
26
|
-
type="text"
|
|
27
|
-
name={`partitionValues.['${col.name}'].to`}
|
|
28
|
-
id={`${col.name}.to`}
|
|
29
|
-
placeholder="20230102"
|
|
30
|
-
default="20230102"
|
|
31
|
-
style={{ width: '7rem' }}
|
|
32
|
-
/>
|
|
33
|
-
</div>
|
|
34
|
-
</div>
|
|
35
|
-
</>
|
|
36
|
-
);
|
|
37
|
-
} else {
|
|
38
|
-
return (
|
|
39
|
-
<>
|
|
40
|
-
<div
|
|
41
|
-
className="partition__full"
|
|
42
|
-
key={col.name}
|
|
43
|
-
style={{ width: '50%' }}
|
|
44
|
-
>
|
|
45
|
-
<div className="partition__header">{col.display_name}</div>
|
|
46
|
-
<div className="partition__body">
|
|
47
|
-
<Field
|
|
48
|
-
type="text"
|
|
49
|
-
name={`partitionValues.['${col.name}']`}
|
|
50
|
-
id={col.name}
|
|
51
|
-
placeholder=""
|
|
52
|
-
default=""
|
|
53
|
-
style={{ width: '7rem', paddingRight: '1rem' }}
|
|
54
|
-
/>
|
|
55
|
-
</div>
|
|
56
|
-
</div>
|
|
57
|
-
</>
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
}
|