datajunction-ui 0.0.1-a87.dev0 → 0.0.1-a88
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 +1 -1
- package/src/app/components/AddNodeDropdown.jsx +4 -1
- package/src/app/pages/AddEditNodePage/ColumnsSelect.jsx +5 -1
- package/src/app/pages/AddEditNodePage/FormikSelect.jsx +2 -0
- package/src/app/pages/AddEditNodePage/index.jsx +16 -9
- package/src/app/pages/NodePage/__tests__/__snapshots__/NodePage.test.jsx.snap +2 -1
- package/src/app/icons/WrenchIcon.jsx +0 -36
- package/src/app/pages/AddEditNodePage/ColumnMetadata.jsx +0 -61
- package/src/app/pages/AddEditNodePage/ColumnsMetadataInput.jsx +0 -72
- package/src/app/pages/NodePage/LinkComplexDimensionPopover.jsx +0 -141
package/package.json
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export default function AddNodeDropdown({ namespace }) {
|
|
2
2
|
return (
|
|
3
|
-
<span
|
|
3
|
+
<span
|
|
4
|
+
className="menu-link"
|
|
5
|
+
style={{ margin: '0.5em 0 0 1em', width: '130px' }}
|
|
6
|
+
>
|
|
4
7
|
<span className="menu-title">
|
|
5
8
|
<div className="dropdown">
|
|
6
9
|
<span className="add_node">+ Add Node</span>
|
|
@@ -12,6 +12,7 @@ export const ColumnsSelect = ({
|
|
|
12
12
|
label,
|
|
13
13
|
labelStyle = {},
|
|
14
14
|
isMulti = false,
|
|
15
|
+
isClearable = true,
|
|
15
16
|
}) => {
|
|
16
17
|
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
17
18
|
|
|
@@ -67,12 +68,15 @@ export const ColumnsSelect = ({
|
|
|
67
68
|
label: val,
|
|
68
69
|
};
|
|
69
70
|
})
|
|
70
|
-
:
|
|
71
|
+
: defaultValue
|
|
72
|
+
? { value: defaultValue, label: defaultValue }
|
|
73
|
+
: null
|
|
71
74
|
}
|
|
72
75
|
selectOptions={selectableOptions}
|
|
73
76
|
formikFieldName={fieldName}
|
|
74
77
|
onFocus={event => fetchColumns(event)}
|
|
75
78
|
isMulti={isMulti}
|
|
79
|
+
isClearable={isClearable}
|
|
76
80
|
/>
|
|
77
81
|
</span>
|
|
78
82
|
</div>
|
|
@@ -12,6 +12,7 @@ export const FormikSelect = ({
|
|
|
12
12
|
style,
|
|
13
13
|
className = 'SelectInput',
|
|
14
14
|
isMulti = false,
|
|
15
|
+
isClearable = false,
|
|
15
16
|
onFocus = event => {},
|
|
16
17
|
}) => {
|
|
17
18
|
// eslint-disable-next-line no-unused-vars
|
|
@@ -38,6 +39,7 @@ export const FormikSelect = ({
|
|
|
38
39
|
onChange={selected => setValue(getValue(selected))}
|
|
39
40
|
styles={style}
|
|
40
41
|
isMulti={isMulti}
|
|
42
|
+
isClearable={isClearable}
|
|
41
43
|
onFocus={event => onFocus(event)}
|
|
42
44
|
id={field.name}
|
|
43
45
|
/>
|
|
@@ -332,11 +332,11 @@ export function AddEditNodePage({ extensions = {} }) {
|
|
|
332
332
|
<Formik
|
|
333
333
|
initialValues={initialValues}
|
|
334
334
|
validate={validator}
|
|
335
|
-
onSubmit={(values, { setSubmitting, setStatus }) => {
|
|
335
|
+
onSubmit={async (values, { setSubmitting, setStatus }) => {
|
|
336
336
|
try {
|
|
337
|
-
|
|
338
|
-
handler(values, { setSubmitting, setStatus })
|
|
339
|
-
|
|
337
|
+
for (const handler of submitHandlers) {
|
|
338
|
+
await handler(values, { setSubmitting, setStatus });
|
|
339
|
+
}
|
|
340
340
|
} catch (error) {
|
|
341
341
|
console.error('Error in submission', error);
|
|
342
342
|
} finally {
|
|
@@ -438,11 +438,18 @@ export function AddEditNodePage({ extensions = {} }) {
|
|
|
438
438
|
<ExtensionComponent
|
|
439
439
|
node={node}
|
|
440
440
|
action={action}
|
|
441
|
-
registerSubmitHandler={
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
441
|
+
registerSubmitHandler={(
|
|
442
|
+
onSubmit,
|
|
443
|
+
{ prepend } = {},
|
|
444
|
+
) => {
|
|
445
|
+
if (!submitHandlers.includes(onSubmit)) {
|
|
446
|
+
if (prepend) {
|
|
447
|
+
submitHandlers.unshift(onSubmit);
|
|
448
|
+
} else {
|
|
449
|
+
submitHandlers.push(onSubmit);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}}
|
|
446
453
|
/>
|
|
447
454
|
</div>
|
|
448
455
|
),
|
|
@@ -70,6 +70,7 @@ exports[`<NodePage /> renders the NodeMaterialization tab with materializations
|
|
|
70
70
|
Strategy
|
|
71
71
|
</label>
|
|
72
72
|
<select
|
|
73
|
+
id="strategy"
|
|
73
74
|
name="strategy"
|
|
74
75
|
>
|
|
75
76
|
<option
|
|
@@ -105,7 +106,7 @@ exports[`<NodePage /> renders the NodeMaterialization tab with materializations
|
|
|
105
106
|
class="DescriptionInput"
|
|
106
107
|
>
|
|
107
108
|
<label
|
|
108
|
-
for="
|
|
109
|
+
for="lookback_window"
|
|
109
110
|
>
|
|
110
111
|
Lookback Window
|
|
111
112
|
</label>
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
const WrenchIcon = props => (
|
|
2
|
-
<svg
|
|
3
|
-
width="16"
|
|
4
|
-
height="17"
|
|
5
|
-
viewBox="0 0 16 17"
|
|
6
|
-
fill="none"
|
|
7
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
8
|
-
>
|
|
9
|
-
<g clip-path="url(#clip0_24_77)">
|
|
10
|
-
<rect
|
|
11
|
-
width="16"
|
|
12
|
-
height="16"
|
|
13
|
-
transform="translate(0 0.649803)"
|
|
14
|
-
fill="white"
|
|
15
|
-
/>
|
|
16
|
-
<path
|
|
17
|
-
fill-rule="evenodd"
|
|
18
|
-
clip-rule="evenodd"
|
|
19
|
-
d="M6.41665 5.44985C6.41665 2.8265 8.5433 0.699852 11.1667 0.699852C11.4613 0.699852 11.7504 0.726773 12.0313 0.778484C12.5762 0.878798 12.9364 1.28101 13.0406 1.74377C13.1406 2.18774 13.0066 2.67055 12.6619 3.01531L11.2273 4.44985L12.1667 5.38919L13.6012 3.95465C13.946 3.60989 14.4288 3.47589 14.8728 3.57591C15.3355 3.68017 15.7377 4.04033 15.838 4.58525C15.8898 4.86615 15.9167 5.15519 15.9167 5.44985C15.9167 8.0732 13.79 10.1999 11.1667 10.1999C10.658 10.1999 10.167 10.1196 9.70625 9.97091L3.50172 16.1754C2.94847 16.7287 2.05149 16.7287 1.49825 16.1754L0.441055 15.1183C-0.112189 14.565 -0.112186 13.668 0.441056 13.1148L6.64559 6.91025C6.49685 6.44951 6.41665 5.9585 6.41665 5.44985ZM11.1667 2.19985C9.37172 2.19985 7.91665 3.65492 7.91665 5.44985C7.91665 5.92812 8.01948 6.38034 8.20352 6.7873L8.41725 7.25991L8.05048 7.62667L1.56064 14.1165L2.49998 15.0559L8.98982 8.56601L9.35659 8.19925L9.8292 8.41298C10.2362 8.59702 10.6884 8.69985 11.1667 8.69985C12.9616 8.69985 14.4167 7.24477 14.4167 5.44985C14.4167 5.38796 14.415 5.32654 14.4116 5.26562L12.697 6.98018L12.1667 7.51051L11.6363 6.98018L9.63632 4.98018L9.10599 4.44985L9.63632 3.91952L11.3509 2.20496C11.29 2.20157 11.2286 2.19985 11.1667 2.19985Z"
|
|
20
|
-
fill="black"
|
|
21
|
-
fill-opacity="0.9"
|
|
22
|
-
/>
|
|
23
|
-
</g>
|
|
24
|
-
<defs>
|
|
25
|
-
<clipPath id="clip0_24_77">
|
|
26
|
-
<rect
|
|
27
|
-
width="16"
|
|
28
|
-
height="16"
|
|
29
|
-
fill="white"
|
|
30
|
-
transform="translate(0 0.649803)"
|
|
31
|
-
/>
|
|
32
|
-
</clipPath>
|
|
33
|
-
</defs>
|
|
34
|
-
</svg>
|
|
35
|
-
);
|
|
36
|
-
export default WrenchIcon;
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Component for arbitrary column metadata
|
|
3
|
-
*/
|
|
4
|
-
import { ErrorMessage, useFormikContext } from 'formik';
|
|
5
|
-
import { useContext, useMemo, useState } from 'react';
|
|
6
|
-
import DJClientContext from '../../providers/djclient';
|
|
7
|
-
import { FormikSelect } from './FormikSelect';
|
|
8
|
-
|
|
9
|
-
export const ColumnMetadata = ({ name, label, defaultValue }) => {
|
|
10
|
-
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
11
|
-
|
|
12
|
-
// Used to pull out current form values for node validation
|
|
13
|
-
const { values } = useFormikContext();
|
|
14
|
-
|
|
15
|
-
// The available columns, determined from validating the node query
|
|
16
|
-
const [availableColumns, setAvailableColumns] = useState([]);
|
|
17
|
-
const selectableOptions = useMemo(() => {
|
|
18
|
-
if (availableColumns && availableColumns.length > 0) {
|
|
19
|
-
return availableColumns;
|
|
20
|
-
}
|
|
21
|
-
}, [availableColumns]);
|
|
22
|
-
|
|
23
|
-
// When focus is on the input field, refresh the list of available columns for selection
|
|
24
|
-
const refreshColumns = event => {
|
|
25
|
-
async function fetchData() {
|
|
26
|
-
// eslint-disable-next-line no-unused-vars
|
|
27
|
-
const { status, json } = await djClient.validateNode(
|
|
28
|
-
values.type,
|
|
29
|
-
values.name,
|
|
30
|
-
values.display_name,
|
|
31
|
-
values.description,
|
|
32
|
-
values.query,
|
|
33
|
-
);
|
|
34
|
-
setAvailableColumns(
|
|
35
|
-
json.columns.map(col => {
|
|
36
|
-
return { value: col.name, label: col.name };
|
|
37
|
-
}),
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
fetchData();
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<div className="NodeCreationInput" style={{ width: '25%' }}>
|
|
45
|
-
<ErrorMessage name={name} component="span" />
|
|
46
|
-
<label htmlFor="react-select-3-input">{label}</label>
|
|
47
|
-
<span data-testid={`select-${name}`}>
|
|
48
|
-
<FormikSelect
|
|
49
|
-
className="SelectInput"
|
|
50
|
-
style={{ width: '100px' }}
|
|
51
|
-
defaultValue={defaultValue}
|
|
52
|
-
selectOptions={selectableOptions}
|
|
53
|
-
formikFieldName={name}
|
|
54
|
-
// placeholder={`Choose ${label}`}
|
|
55
|
-
onFocus={event => refreshColumns(event)}
|
|
56
|
-
isMulti={false}
|
|
57
|
-
/>
|
|
58
|
-
</span>
|
|
59
|
-
</div>
|
|
60
|
-
);
|
|
61
|
-
};
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Column metadata configuration component
|
|
3
|
-
*/
|
|
4
|
-
import { ErrorMessage, useFormikContext } from 'formik';
|
|
5
|
-
import { useContext, useMemo, useState, useEffect } from 'react';
|
|
6
|
-
import DJClientContext from '../../providers/djclient';
|
|
7
|
-
import { FormikSelect } from './FormikSelect';
|
|
8
|
-
import WrenchIcon from 'app/icons/WrenchIcon';
|
|
9
|
-
|
|
10
|
-
export const ColumnsMetadataInput = ({ columns }) => {
|
|
11
|
-
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
12
|
-
|
|
13
|
-
// Used to pull out current form values for node validation
|
|
14
|
-
const { values } = useFormikContext();
|
|
15
|
-
|
|
16
|
-
// The available columns, determined from validating the node query
|
|
17
|
-
const [availableColumns, setAvailableColumns] = useState([]);
|
|
18
|
-
const selectableOptions = useMemo(() => {
|
|
19
|
-
if (availableColumns && availableColumns.length > 0) {
|
|
20
|
-
return availableColumns;
|
|
21
|
-
}
|
|
22
|
-
}, [availableColumns]);
|
|
23
|
-
|
|
24
|
-
// When focus is on the primary key field, refresh the list of available
|
|
25
|
-
// primary key columns for selection
|
|
26
|
-
useEffect(() => {
|
|
27
|
-
const fetchData = async () => {
|
|
28
|
-
// eslint-disable-next-line no-unused-vars
|
|
29
|
-
const { status, json } = await djClient.validateNode(
|
|
30
|
-
values.type,
|
|
31
|
-
values.name,
|
|
32
|
-
values.display_name,
|
|
33
|
-
values.description,
|
|
34
|
-
values.query,
|
|
35
|
-
);
|
|
36
|
-
setAvailableColumns(
|
|
37
|
-
json.columns.map(col => {
|
|
38
|
-
return { value: col.name, label: col.name };
|
|
39
|
-
}),
|
|
40
|
-
);
|
|
41
|
-
};
|
|
42
|
-
fetchData().catch(console.error);
|
|
43
|
-
}, [djClient, name]);
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<div
|
|
47
|
-
className="ColumnsMetadataInput NodeCreationInput"
|
|
48
|
-
style={{ border: 'dashed 1px #ccc', padding: '20px' }}
|
|
49
|
-
>
|
|
50
|
-
<ErrorMessage name="mode" component="span" />
|
|
51
|
-
<label htmlFor="Mode">Columns Metadata</label>
|
|
52
|
-
<table>
|
|
53
|
-
<thead>
|
|
54
|
-
<tr>
|
|
55
|
-
<th>Column</th>
|
|
56
|
-
<th>Metadata</th>
|
|
57
|
-
</tr>
|
|
58
|
-
</thead>
|
|
59
|
-
<tbody>
|
|
60
|
-
{availableColumns.map(col => (
|
|
61
|
-
<tr key={col.value}>
|
|
62
|
-
<td>{col.value}</td>
|
|
63
|
-
<td>
|
|
64
|
-
<WrenchIcon />
|
|
65
|
-
</td>
|
|
66
|
-
</tr>
|
|
67
|
-
))}
|
|
68
|
-
</tbody>
|
|
69
|
-
</table>
|
|
70
|
-
</div>
|
|
71
|
-
);
|
|
72
|
-
};
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
import { useContext, useEffect, useRef, useState } from 'react';
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
import DJClientContext from '../../providers/djclient';
|
|
4
|
-
import { Field, Form, Formik } from 'formik';
|
|
5
|
-
import { FormikSelect } from '../AddEditNodePage/FormikSelect';
|
|
6
|
-
import EditIcon from '../../icons/EditIcon';
|
|
7
|
-
import { displayMessageAfterSubmit } from '../../../utils/form';
|
|
8
|
-
import LoadingIcon from '../../icons/LoadingIcon';
|
|
9
|
-
import { MetricQueryField } from '../AddEditNodePage/MetricQueryField';
|
|
10
|
-
|
|
11
|
-
export default function LinkComplexDimensionPopover({ link, onSubmit }) {
|
|
12
|
-
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
13
|
-
const [popoverAnchor, setPopoverAnchor] = useState(false);
|
|
14
|
-
const ref = useRef(null);
|
|
15
|
-
|
|
16
|
-
useEffect(() => {
|
|
17
|
-
const handleClickOutside = event => {
|
|
18
|
-
if (ref.current && !ref.current.contains(event.target)) {
|
|
19
|
-
setPopoverAnchor(false);
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
document.addEventListener('click', handleClickOutside, true);
|
|
23
|
-
return () => {
|
|
24
|
-
document.removeEventListener('click', handleClickOutside, true);
|
|
25
|
-
};
|
|
26
|
-
}, [setPopoverAnchor]);
|
|
27
|
-
|
|
28
|
-
const handleSubmit = async (
|
|
29
|
-
{ node, column, dimension },
|
|
30
|
-
{ setSubmitting, setStatus },
|
|
31
|
-
) => {
|
|
32
|
-
if (referencedDimensionNode && dimension === 'Remove') {
|
|
33
|
-
await unlinkDimension(
|
|
34
|
-
node,
|
|
35
|
-
column,
|
|
36
|
-
referencedDimensionNode,
|
|
37
|
-
setStatus,
|
|
38
|
-
).then(_ => setSubmitting(false));
|
|
39
|
-
} else {
|
|
40
|
-
await linkDimension(node, column, dimension, setStatus).then(_ =>
|
|
41
|
-
setSubmitting(false),
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
onSubmit();
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const linkDimension = async (node, column, dimension, setStatus) => {
|
|
48
|
-
const response = await djClient.linkDimension(node, column, dimension);
|
|
49
|
-
if (response.status === 200 || response.status === 201) {
|
|
50
|
-
setStatus({ success: 'Saved!' });
|
|
51
|
-
} else {
|
|
52
|
-
setStatus({
|
|
53
|
-
failure: `${response.json.message}`,
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const unlinkDimension = async (node, column, currentDimension, setStatus) => {
|
|
59
|
-
const response = await djClient.unlinkDimension(
|
|
60
|
-
node,
|
|
61
|
-
column,
|
|
62
|
-
currentDimension,
|
|
63
|
-
);
|
|
64
|
-
if (response.status === 200 || response.status === 201) {
|
|
65
|
-
setStatus({ success: 'Removed dimension link!' });
|
|
66
|
-
} else {
|
|
67
|
-
setStatus({
|
|
68
|
-
failure: `${response.json.message}`,
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
return (
|
|
74
|
-
<>
|
|
75
|
-
<button
|
|
76
|
-
className="edit_button"
|
|
77
|
-
aria-label="LinkDimension"
|
|
78
|
-
tabIndex="0"
|
|
79
|
-
onClick={() => {
|
|
80
|
-
setPopoverAnchor(!popoverAnchor);
|
|
81
|
-
}}
|
|
82
|
-
>
|
|
83
|
-
<EditIcon />
|
|
84
|
-
</button>
|
|
85
|
-
<div
|
|
86
|
-
className="popover"
|
|
87
|
-
role="dialog"
|
|
88
|
-
aria-label="client-code"
|
|
89
|
-
style={{ display: popoverAnchor === false ? 'none' : 'block' }}
|
|
90
|
-
ref={ref}
|
|
91
|
-
>
|
|
92
|
-
<Formik
|
|
93
|
-
initialValues={
|
|
94
|
-
{
|
|
95
|
-
// column: column.name,
|
|
96
|
-
// node: node.name,
|
|
97
|
-
// dimension: '',
|
|
98
|
-
// currentDimension: referencedDimensionNode,
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
onSubmit={handleSubmit}
|
|
102
|
-
>
|
|
103
|
-
{function Render({ isSubmitting, status, setFieldValue }) {
|
|
104
|
-
return (
|
|
105
|
-
<Form>
|
|
106
|
-
{displayMessageAfterSubmit(status)}
|
|
107
|
-
<span data-testid="link-dimension">
|
|
108
|
-
<label>Join Type</label>
|
|
109
|
-
<FormikSelect
|
|
110
|
-
selectOptions={[{ value: 'left', label: 'LEFT' }]}
|
|
111
|
-
formikFieldName="join_type"
|
|
112
|
-
placeholder="Select join type"
|
|
113
|
-
className="join_type"
|
|
114
|
-
defaultValue={link.join_type || ''}
|
|
115
|
-
isMulti={false}
|
|
116
|
-
/>
|
|
117
|
-
{console.log('link, ', link)}
|
|
118
|
-
|
|
119
|
-
<label>Join On</label>
|
|
120
|
-
<MetricQueryField
|
|
121
|
-
djClient={djClient}
|
|
122
|
-
value={link.join_sql ? link.join_sql : ''}
|
|
123
|
-
/>
|
|
124
|
-
</span>
|
|
125
|
-
<button
|
|
126
|
-
className="add_node"
|
|
127
|
-
type="submit"
|
|
128
|
-
aria-label="SaveComplexDimension"
|
|
129
|
-
aria-hidden="false"
|
|
130
|
-
disabled={isSubmitting}
|
|
131
|
-
>
|
|
132
|
-
{isSubmitting ? <LoadingIcon /> : 'Save'}
|
|
133
|
-
</button>
|
|
134
|
-
</Form>
|
|
135
|
-
);
|
|
136
|
-
}}
|
|
137
|
-
</Formik>
|
|
138
|
-
</div>
|
|
139
|
-
</>
|
|
140
|
-
);
|
|
141
|
-
}
|