datajunction-ui 0.0.1-a46.dev1 → 0.0.1-a47

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.
@@ -41,7 +41,9 @@ export const mocks = {
41
41
  type: 'string',
42
42
  attributes: [],
43
43
  dimension: null,
44
- partition: null,
44
+ partition: {
45
+ type_: 'categorical',
46
+ },
45
47
  },
46
48
  ],
47
49
  updated_at: '2024-01-24T16:39:14.029366+00:00',
@@ -461,12 +463,14 @@ export const mocks = {
461
463
  {
462
464
  backfills: [
463
465
  {
464
- spec: {
465
- column_name: 'default_DOT_hard_hat_DOT_hire_date',
466
- values: null,
467
- range: ['20230101', '20230102'],
468
- },
469
- urls: [],
466
+ spec: [
467
+ {
468
+ column_name: 'default_DOT_hard_hat_DOT_hire_date',
469
+ values: null,
470
+ range: ['20230101', '20230102'],
471
+ },
472
+ ],
473
+ urls: ['a', 'b'],
470
474
  },
471
475
  ],
472
476
  name: 'country_birth_date_contractor_id_379232101',
@@ -477,6 +481,7 @@ export const mocks = {
477
481
  "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",
478
482
  upstream_tables: ['default.roads.hard_hats'],
479
483
  },
484
+ strategy: 'incremental_time',
480
485
  schedule: '0 * * * *',
481
486
  job: 'SparkSqlMaterializationJob',
482
487
  output_tables: ['common.a', 'common.b'],
@@ -1553,4 +1558,53 @@ export const mocks = {
1553
1558
  tag_type: 'reports',
1554
1559
  },
1555
1560
  ],
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
+ },
1556
1610
  };
@@ -593,6 +593,12 @@ 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
+
596
602
  .status__valid {
597
603
  color: #00b368;
598
604
  }
@@ -1018,17 +1024,19 @@ pre {
1018
1024
  }
1019
1025
 
1020
1026
  .add_button {
1021
- background-color: #f0f8ff !important;
1022
- color: #24518f;
1023
- text-transform: uppercase;
1027
+ background-color: #2f7986 !important;
1028
+ color: #fff;
1029
+ text-transform: none;
1024
1030
  vertical-align: middle;
1025
- padding: 0.2rem 0.5rem 0.1rem 0.5rem;
1026
- border: 1px solid #819bc0;
1027
- font-size: 1.2rem;
1031
+ padding-right: 1rem;
1032
+ padding-left: 1rem;
1033
+ padding-top: 0.5rem;
1034
+ padding-bottom: 0.5rem;
1035
+ margin-bottom: 0.5rem !important;
1036
+ font-size: 1rem;
1028
1037
  border-radius: 0.5rem;
1029
1038
  word-wrap: break-word;
1030
1039
  white-space: break-spaces;
1031
- margin-left: 1rem;
1032
1040
  }
1033
1041
 
1034
1042
  .edit_button {
@@ -1090,10 +1098,6 @@ pre {
1090
1098
  transition: opacity 0.15s linear;
1091
1099
  }
1092
1100
 
1093
- .partitionLink:hover {
1094
- text-decoration: none;
1095
- }
1096
-
1097
1101
  .dimensionsList {
1098
1102
  padding: 12px;
1099
1103
  opacity: 1;
@@ -1216,4 +1220,102 @@ pre {
1216
1220
  background-color: #ffffff;
1217
1221
  margin-bottom: 3px;
1218
1222
  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;
1219
1321
  }
@@ -0,0 +1,4 @@
1
+ table {
2
+ width: 100%;
3
+ height: min-content;
4
+ }
@@ -1,61 +0,0 @@
1
- import { ErrorMessage } from 'formik';
2
- import { FormikSelect } from '../../pages/AddEditNodePage/FormikSelect';
3
- import { Action } from './Action';
4
- import { useContext, useEffect, useState } from 'react';
5
- import DJClientContext from '../../providers/djclient';
6
-
7
- export default function NodeTagsInput({ action, node }) {
8
- const djClient = useContext(DJClientContext).DataJunctionAPI;
9
- const [tags, setTags] = useState([]);
10
-
11
- // Get list of tags
12
- useEffect(() => {
13
- const fetchData = async () => {
14
- const tags = await djClient.listTags();
15
- setTags(
16
- tags.map(tag => ({
17
- value: tag.name,
18
- label: tag.display_name,
19
- })),
20
- );
21
- };
22
- fetchData().catch(console.error);
23
- }, [djClient, djClient.listTags]);
24
-
25
- return (
26
- <div
27
- className="TagsInput"
28
- style={{ width: '25%', margin: '1rem 0 1rem 1.2rem' }}
29
- >
30
- <ErrorMessage name="tags" component="span" />
31
- <label htmlFor="react-select-3-input">Tags</label>
32
- <span data-testid="select-tags">
33
- {action === Action.Edit && node?.tags?.length >= 0 ? (
34
- <FormikSelect
35
- className=""
36
- isMulti={true}
37
- selectOptions={tags}
38
- formikFieldName="tags"
39
- placeholder="Choose Tags"
40
- defaultValue={node?.tags?.map(t => {
41
- return { value: t.name, label: t.display_name };
42
- })}
43
- />
44
- ) : (
45
- ''
46
- )}
47
- {action === Action.Add ? (
48
- <FormikSelect
49
- className=""
50
- isMulti={true}
51
- selectOptions={tags}
52
- formikFieldName="tags"
53
- placeholder="Choose Tags"
54
- />
55
- ) : (
56
- ''
57
- )}
58
- </span>
59
- </div>
60
- );
61
- }
@@ -1,62 +0,0 @@
1
- /**
2
- * Query tester component
3
- */
4
- import { ErrorMessage, useFormikContext } from 'formik';
5
- import React, { useContext, useEffect, useState } from 'react';
6
- import DJClientContext from '../../providers/djclient';
7
- import { FormikSelect } from './FormikSelect';
8
- import QueryBuilder from 'react-querybuilder';
9
-
10
- export const QueryTesterSection = ({}) => {
11
- const djClient = useContext(DJClientContext).DataJunctionAPI;
12
-
13
- const [fields, setFields] = useState([]);
14
- const [filters, setFilters] = useState({
15
- combinator: 'and',
16
- rules: [],
17
- });
18
-
19
- // Used to pull out current form values for node validation
20
- const { values } = useFormikContext();
21
-
22
- // Select options, i.e., the available dimensions
23
- const [selectOptions, setSelectOptions] = useState([]);
24
-
25
- useEffect(() => {
26
- const fetchData = async () => {
27
- if (values.query) {
28
- const data = await djClient.node(values.upstream_node);
29
- setSelectOptions(
30
- data.columns.map(col => {
31
- return {
32
- value: col.name,
33
- label: col.name,
34
- };
35
- }),
36
- );
37
- }
38
- };
39
- fetchData().catch(console.error);
40
- }, [djClient, values.upstream_node]);
41
-
42
- return (
43
- <>
44
- <h4>Test Query</h4>
45
- <label>Add Filters</label>
46
- <QueryBuilder
47
- fields={fields}
48
- query={filters}
49
- onQueryChange={q => setFilters(q)}
50
- />
51
- <span
52
- className="button-3 execute-button"
53
- // onClick={getData}
54
- role="button"
55
- aria-label="RunQuery"
56
- aria-hidden="false"
57
- >
58
- {'Run Query'}
59
- </span>
60
- </>
61
- );
62
- };
@@ -1,31 +0,0 @@
1
- import QueryBuilder from 'react-querybuilder';
2
- import { useState } from 'react';
3
-
4
- export function QueryRunner() {
5
- const [fields, setFields] = useState([]);
6
- const [filters, setFilters] = useState({
7
- combinator: 'and',
8
- rules: [],
9
- });
10
-
11
- return (
12
- <>
13
- <h4>Test Query</h4>
14
- <label>Add Filters</label>
15
- <QueryBuilder
16
- fields={fields}
17
- query={filters}
18
- onQueryChange={q => setFilters(q)}
19
- />
20
- <span
21
- className="button-3 execute-button"
22
- // onClick={getData}
23
- role="button"
24
- aria-label="RunQuery"
25
- aria-hidden="false"
26
- >
27
- {'Run Query'}
28
- </span>
29
- </>
30
- );
31
- }