datajunction-ui 0.0.1-a46.dev1 → 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/package.json +1 -1
- package/src/app/pages/CubeBuilderPage/index.jsx +19 -4
- package/src/app/pages/NamespacePage/index.jsx +1 -0
- package/src/styles/node-list.css +4 -0
- package/src/app/components/forms/NodeTagsInput.jsx +0 -61
- package/src/app/pages/AddEditNodePage/QueryTesterSection.jsx +0 -62
- package/src/app/pages/NodePage/PartitionValueForm.jsx +0 -63
- package/src/app/pages/QueryRunner.jsx +0 -31
package/package.json
CHANGED
|
@@ -9,9 +9,9 @@ import { displayMessageAfterSubmit } from '../../../utils/form';
|
|
|
9
9
|
import { useParams } from 'react-router-dom';
|
|
10
10
|
import { Action } from '../../components/forms/Action';
|
|
11
11
|
import NodeNameField from '../../components/forms/NodeNameField';
|
|
12
|
-
import NodeTagsInput from '../../components/forms/NodeTagsInput';
|
|
13
12
|
import { MetricsSelect } from './MetricsSelect';
|
|
14
13
|
import { DimensionsSelect } from './DimensionsSelect';
|
|
14
|
+
import { TagsField } from '../AddEditNodePage/TagsField';
|
|
15
15
|
|
|
16
16
|
export function CubeBuilderPage() {
|
|
17
17
|
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
@@ -29,6 +29,7 @@ export function CubeBuilderPage() {
|
|
|
29
29
|
metrics: [],
|
|
30
30
|
dimensions: [],
|
|
31
31
|
filters: [],
|
|
32
|
+
tags: [],
|
|
32
33
|
};
|
|
33
34
|
|
|
34
35
|
const handleSubmit = (values, { setSubmitting, setStatus }) => {
|
|
@@ -105,10 +106,23 @@ export function CubeBuilderPage() {
|
|
|
105
106
|
}
|
|
106
107
|
};
|
|
107
108
|
|
|
108
|
-
const updateFieldsWithNodeData = (data, setFieldValue) => {
|
|
109
|
+
const updateFieldsWithNodeData = (data, setFieldValue, setSelectTags) => {
|
|
109
110
|
setFieldValue('display_name', data.display_name || '', false);
|
|
110
111
|
setFieldValue('description', data.description || '', false);
|
|
111
112
|
setFieldValue('mode', data.mode || 'draft', false);
|
|
113
|
+
setFieldValue(
|
|
114
|
+
'tags',
|
|
115
|
+
data.tags.map(tag => tag.name),
|
|
116
|
+
);
|
|
117
|
+
// For react-select fields, we have to explicitly set the entire
|
|
118
|
+
// field rather than just the values
|
|
119
|
+
setSelectTags(
|
|
120
|
+
<TagsField
|
|
121
|
+
defaultValue={data.tags.map(t => {
|
|
122
|
+
return { value: t.name, label: t.display_name };
|
|
123
|
+
})}
|
|
124
|
+
/>,
|
|
125
|
+
);
|
|
112
126
|
};
|
|
113
127
|
|
|
114
128
|
const staticFieldsInEdit = () => (
|
|
@@ -144,14 +158,15 @@ export function CubeBuilderPage() {
|
|
|
144
158
|
>
|
|
145
159
|
{function Render({ isSubmitting, status, setFieldValue, props }) {
|
|
146
160
|
const [node, setNode] = useState([]);
|
|
161
|
+
const [selectTags, setSelectTags] = useState(null);
|
|
147
162
|
|
|
148
163
|
// Get cube
|
|
149
164
|
useEffect(() => {
|
|
150
165
|
const fetchData = async () => {
|
|
151
166
|
if (name) {
|
|
152
167
|
const cube = await djClient.cube(name);
|
|
153
|
-
updateFieldsWithNodeData(cube, setFieldValue);
|
|
154
168
|
setNode(cube);
|
|
169
|
+
updateFieldsWithNodeData(cube, setFieldValue, setSelectTags);
|
|
155
170
|
}
|
|
156
171
|
};
|
|
157
172
|
fetchData().catch(console.error);
|
|
@@ -227,7 +242,7 @@ export function CubeBuilderPage() {
|
|
|
227
242
|
<option value="published">Published</option>
|
|
228
243
|
</Field>
|
|
229
244
|
</div>
|
|
230
|
-
|
|
245
|
+
{action === Action.Edit ? selectTags : <TagsField />}
|
|
231
246
|
<button
|
|
232
247
|
type="submit"
|
|
233
248
|
disabled={isSubmitting}
|
|
@@ -6,6 +6,7 @@ import DJClientContext from '../../providers/djclient';
|
|
|
6
6
|
import Explorer from '../NamespacePage/Explorer';
|
|
7
7
|
import NodeListActions from '../../components/NodeListActions';
|
|
8
8
|
import AddNamespacePopover from './AddNamespacePopover';
|
|
9
|
+
import 'styles/node-list.css';
|
|
9
10
|
|
|
10
11
|
export function NamespacePage() {
|
|
11
12
|
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
@@ -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,63 +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 { displayMessageAfterSubmit } from '../../../utils/form';
|
|
6
|
-
|
|
7
|
-
export default function PartitionValueForm({ col, materialization }) {
|
|
8
|
-
if (col.partition.type_ === 'temporal') {
|
|
9
|
-
return (
|
|
10
|
-
<>
|
|
11
|
-
<div
|
|
12
|
-
className="partition__full"
|
|
13
|
-
key={col.name}
|
|
14
|
-
style={{ width: '50%' }}
|
|
15
|
-
>
|
|
16
|
-
<div className="partition__header">{col.display_name}</div>
|
|
17
|
-
<div className="partition__body">
|
|
18
|
-
<span style={{ padding: '0.5rem' }}>From</span>{' '}
|
|
19
|
-
<Field
|
|
20
|
-
type="text"
|
|
21
|
-
name={`partitionValues.['${col.name}'].from`}
|
|
22
|
-
id={`${col.name}.from`}
|
|
23
|
-
placeholder="20230101"
|
|
24
|
-
default="20230101"
|
|
25
|
-
style={{ width: '7rem', paddingRight: '1rem' }}
|
|
26
|
-
/>{' '}
|
|
27
|
-
<span style={{ padding: '0.5rem' }}>To</span>
|
|
28
|
-
<Field
|
|
29
|
-
type="text"
|
|
30
|
-
name={`partitionValues.['${col.name}'].to`}
|
|
31
|
-
id={`${col.name}.to`}
|
|
32
|
-
placeholder="20230102"
|
|
33
|
-
default="20230102"
|
|
34
|
-
style={{ width: '7rem' }}
|
|
35
|
-
/>
|
|
36
|
-
</div>
|
|
37
|
-
</div>
|
|
38
|
-
</>
|
|
39
|
-
);
|
|
40
|
-
} else {
|
|
41
|
-
return (
|
|
42
|
-
<>
|
|
43
|
-
<div
|
|
44
|
-
className="partition__full"
|
|
45
|
-
key={col.name}
|
|
46
|
-
style={{ width: '50%' }}
|
|
47
|
-
>
|
|
48
|
-
<div className="partition__header">{col.display_name}</div>
|
|
49
|
-
<div className="partition__body">
|
|
50
|
-
<Field
|
|
51
|
-
type="text"
|
|
52
|
-
name={`partitionValues.['${col.name}']`}
|
|
53
|
-
id={col.name}
|
|
54
|
-
placeholder=""
|
|
55
|
-
default=""
|
|
56
|
-
style={{ width: '7rem', paddingRight: '1rem' }}
|
|
57
|
-
/>
|
|
58
|
-
</div>
|
|
59
|
-
</div>
|
|
60
|
-
</>
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
@@ -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
|
-
}
|