datajunction-ui 0.0.1-a81 → 0.0.1-a83

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "datajunction-ui",
3
- "version": "0.0.1a81",
3
+ "version": "0.0.1a83",
4
4
  "description": "DataJunction Metrics Platform UI",
5
5
  "module": "src/index.tsx",
6
6
  "repository": {
@@ -166,9 +166,9 @@
166
166
  "coverageThreshold": {
167
167
  "global": {
168
168
  "statements": 87,
169
- "branches": 74,
169
+ "branches": 70,
170
170
  "lines": 80,
171
- "functions": 85
171
+ "functions": 83
172
172
  }
173
173
  },
174
174
  "moduleNameMapper": {
@@ -1,5 +1,5 @@
1
1
  import { Component } from 'react';
2
- import Markdown from 'react-markdown'
2
+ import Markdown from 'react-markdown';
3
3
 
4
4
  export default class ListGroupItem extends Component {
5
5
  render() {
@@ -37,7 +37,7 @@ export const DimensionsSelect = ({ cube }) => {
37
37
  value: cubeDim.node_name + '.' + cubeDim.name,
38
38
  label:
39
39
  labelize(cubeDim.name) +
40
- (cubeDim.is_primary_key ? ' (PK)' : ''),
40
+ (cubeDim.properties?.includes('primary_key') ? ' (PK)' : ''),
41
41
  };
42
42
  });
43
43
  setDefaultDimensions(cubeDimensions);
@@ -118,7 +118,7 @@ export const DimensionsSelect = ({ cube }) => {
118
118
  value: dim.name,
119
119
  label:
120
120
  labelize(dim.name.split('.').slice(-1)[0]) +
121
- (dim.is_primary_key ? ' (PK)' : ''),
121
+ (dim.properties?.includes('primary_key') ? ' (PK)' : ''),
122
122
  };
123
123
  });
124
124
  //
@@ -106,7 +106,7 @@ const mockCommonDimensions = [
106
106
  type: 'timestamp',
107
107
  node_name: 'default.date_dim',
108
108
  node_display_name: 'Date',
109
- is_primary_key: false,
109
+ properties: [],
110
110
  path: [
111
111
  'default.repair_order_details.repair_order_id',
112
112
  'default.repair_order.hard_hat_id',
@@ -118,7 +118,7 @@ const mockCommonDimensions = [
118
118
  type: 'timestamp',
119
119
  node_name: 'default.date_dim',
120
120
  node_display_name: 'Date',
121
- is_primary_key: true,
121
+ properties: [],
122
122
  path: [
123
123
  'default.repair_order_details.repair_order_id',
124
124
  'default.repair_order.hard_hat_id',
@@ -130,7 +130,7 @@ const mockCommonDimensions = [
130
130
  type: 'int',
131
131
  node_name: 'default.date_dim',
132
132
  node_display_name: 'Date',
133
- is_primary_key: false,
133
+ properties: [],
134
134
  path: [
135
135
  'default.repair_order_details.repair_order_id',
136
136
  'default.repair_order.hard_hat_id',
@@ -142,7 +142,7 @@ const mockCommonDimensions = [
142
142
  type: 'int',
143
143
  node_name: 'default.date_dim',
144
144
  node_display_name: 'Date',
145
- is_primary_key: false,
145
+ properties: [],
146
146
  path: [
147
147
  'default.repair_order_details.repair_order_id',
148
148
  'default.repair_order.hard_hat_id',
@@ -154,7 +154,7 @@ const mockCommonDimensions = [
154
154
  type: 'int',
155
155
  node_name: 'default.date_dim',
156
156
  node_display_name: 'Date',
157
- is_primary_key: false,
157
+ properties: [],
158
158
  path: [
159
159
  'default.repair_order_details.repair_order_id',
160
160
  'default.repair_order.hard_hat_id',
@@ -166,7 +166,7 @@ const mockCommonDimensions = [
166
166
  type: 'int',
167
167
  node_name: 'default.date_dim',
168
168
  node_display_name: 'Date',
169
- is_primary_key: false,
169
+ properties: [],
170
170
  path: [
171
171
  'default.repair_order_details.repair_order_id',
172
172
  'default.repair_order.hard_hat_id',
@@ -178,7 +178,7 @@ const mockCommonDimensions = [
178
178
  type: 'int',
179
179
  node_name: 'default.date_dim',
180
180
  node_display_name: 'Date',
181
- is_primary_key: false,
181
+ properties: [],
182
182
  path: [
183
183
  'default.repair_order_details.repair_order_id',
184
184
  'default.repair_order.hard_hat_id',
@@ -190,7 +190,7 @@ const mockCommonDimensions = [
190
190
  type: 'int',
191
191
  node_name: 'default.date_dim',
192
192
  node_display_name: 'Date',
193
- is_primary_key: false,
193
+ properties: [],
194
194
  path: [
195
195
  'default.repair_order_details.repair_order_id',
196
196
  'default.repair_order.hard_hat_id',
@@ -133,7 +133,6 @@ export function NamespacePage() {
133
133
  useEffect(() => {
134
134
  const fetchData = async () => {
135
135
  setRetrieved(false);
136
- console.log('cursor', before, filters.edited_by);
137
136
  const nodes = await djClient.listNodesForLanding(
138
137
  namespace,
139
138
  filters.node_type ? [filters.node_type.toUpperCase()] : [],
@@ -143,7 +142,6 @@ export function NamespacePage() {
143
142
  after,
144
143
  50,
145
144
  );
146
- console.log('nodes', nodes);
147
145
 
148
146
  setState({
149
147
  namespace: namespace,
@@ -158,10 +156,6 @@ export function NamespacePage() {
158
156
  setNextCursor(
159
157
  nodes.data ? nodes.data.findNodesPaginated.pageInfo.endCursor : '',
160
158
  );
161
- console.log(
162
- 'setting hasPrevPage, ',
163
- nodes.data.findNodesPaginated.pageInfo.hasPrevPage,
164
- );
165
159
  setHasPrevPage(
166
160
  nodes.data
167
161
  ? nodes.data.findNodesPaginated.pageInfo.hasPrevPage
@@ -98,7 +98,7 @@ export function NodeDimensionsList({ rawDimensions }) {
98
98
  value: dim.name,
99
99
  label:
100
100
  labelize(dim.name.split('.').slice(-1)[0]) +
101
- (dim.is_primary_key ? ' (PK)' : ''),
101
+ (dim.properties.includes('primary_key') ? ' (PK)' : ''),
102
102
  };
103
103
  });
104
104
  return (
@@ -57,7 +57,10 @@ export default function NodeHistory({ node, djClient }) {
57
57
  </div>
58
58
  );
59
59
  }
60
- if (['create', 'update', 'delete'].includes(event.activity_type) && event.entity_type === 'link') {
60
+ if (
61
+ ['create', 'update', 'delete'].includes(event.activity_type) &&
62
+ event.entity_type === 'link'
63
+ ) {
61
64
  return (
62
65
  <div className="history-left">
63
66
  <b style={{ textTransform: 'capitalize' }}>{event.activity_type}</b>{' '}
@@ -180,8 +183,9 @@ export default function NodeHistory({ node, djClient }) {
180
183
  if (event.activity_type === 'create' && event.entity_type === 'backfill') {
181
184
  return (
182
185
  <div className="history-left">
183
- <b>Backfill</b> created for materialization {event.details.materialization}{' '}
184
- for partition {event.details.partition[0].column_name} from{' '}
186
+ <b>Backfill</b> created for materialization{' '}
187
+ {event.details.materialization} for partition{' '}
188
+ {event.details.partition[0].column_name} from{' '}
185
189
  {event.details.partition[0].range[0]} to{' '}
186
190
  {event.details.partition[0].range[1]}
187
191
  </div>
@@ -7,9 +7,6 @@ import ListGroupItem from '../../components/ListGroupItem';
7
7
  import ToggleSwitch from '../../components/ToggleSwitch';
8
8
  import DJClientContext from '../../providers/djclient';
9
9
  import { labelize } from '../../../utils/form';
10
- import { AlertMessage } from '../AddEditNodePage/AlertMessage';
11
- import AlertIcon from '../../icons/AlertIcon';
12
- import InvalidIcon from '../../icons/InvalidIcon';
13
10
 
14
11
  SyntaxHighlighter.registerLanguage('sql', sql);
15
12
  foundation.hljs['padding'] = '2rem';
@@ -71,24 +68,30 @@ export default function NodeInfoTab({ node }) {
71
68
  ) : (
72
69
  ''
73
70
  );
74
- const metricQueryDiv = (
75
- <div className="list-group-item d-flex">
76
- <div className="gap-2 w-100 justify-content-between py-3">
77
- <div style={{ marginBottom: '30px' }}>
78
- <h6 className="mb-0 w-100">Upstream Node</h6>
79
- <p>
80
- <a href={`/nodes/${node?.upstream_node}`}>{node?.upstream_node}</a>
81
- </p>
82
- </div>
83
- <div>
84
- <h6 className="mb-0 w-100">Aggregate Expression</h6>
85
- <SyntaxHighlighter language="sql" style={foundation}>
86
- {node?.expression}
87
- </SyntaxHighlighter>
71
+
72
+ const metricQueryDiv =
73
+ node.type === 'metric' ? (
74
+ <div className="list-group-item d-flex">
75
+ <div className="gap-2 w-100 justify-content-between py-3">
76
+ <div style={{ marginBottom: '30px' }}>
77
+ <h6 className="mb-0 w-100">Upstream Node</h6>
78
+ <p>
79
+ <a href={`/nodes/${node?.upstream_node}`}>
80
+ {node?.upstream_node}
81
+ </a>
82
+ </p>
83
+ </div>
84
+ <div>
85
+ <h6 className="mb-0 w-100">Aggregate Expression</h6>
86
+ <SyntaxHighlighter language="sql" style={foundation}>
87
+ {node?.expression}
88
+ </SyntaxHighlighter>
89
+ </div>
88
90
  </div>
89
91
  </div>
90
- </div>
91
- );
92
+ ) : (
93
+ ''
94
+ );
92
95
  const queryDiv = node?.query ? (
93
96
  <div className="list-group-item d-flex">
94
97
  <div className="d-flex gap-2 w-100 justify-content-between py-3">
@@ -158,7 +161,7 @@ export default function NodeInfoTab({ node }) {
158
161
  aria-label="MetricDirection"
159
162
  >
160
163
  {node?.metric_metadata?.direction
161
- ? labelize(node?.metric_metadata?.direction)
164
+ ? labelize(node?.metric_metadata?.direction?.toLowerCase())
162
165
  : 'None'}
163
166
  </p>
164
167
  </div>
@@ -170,8 +173,8 @@ export default function NodeInfoTab({ node }) {
170
173
  aria-hidden="false"
171
174
  aria-label="MetricUnit"
172
175
  >
173
- {node?.metric_metadata?.unit
174
- ? labelize(node?.metric_metadata?.unit?.label)
176
+ {node?.metric_metadata?.unit?.name
177
+ ? labelize(node?.metric_metadata?.unit?.name?.toLowerCase())
175
178
  : 'None'}
176
179
  </p>
177
180
  </div>
@@ -73,7 +73,7 @@ export default function NodeValidateTab({ node, djClient }) {
73
73
  const dimensionsList = dimensions.flatMap(grouping => {
74
74
  const dimensionsInGroup = grouping[1];
75
75
  return dimensionsInGroup
76
- .filter(dim => dim.is_primary_key === true)
76
+ .filter(dim => dim.properties.includes('primary_key') === true)
77
77
  .map(dim => {
78
78
  return {
79
79
  value: dim.name,
@@ -167,7 +167,7 @@ export default function NodeValidateTab({ node, djClient }) {
167
167
  const filters = dimensions.map(grouping => {
168
168
  const dimensionsInGroup = grouping[1];
169
169
  const dimensionGroupOptions = dimensionsInGroup
170
- .filter(dim => dim.is_primary_key === true)
170
+ .filter(dim => dim.properties.includes('primary_key') === true)
171
171
  .map(dim => {
172
172
  return {
173
173
  value: dim.name,
@@ -183,7 +183,14 @@ export default function RevisionDiff() {
183
183
  </SyntaxHighlighter>
184
184
  </>
185
185
  ) : field === 'columns' ? (
186
- <div>{prevRevision[0][field].map(col => <>{col.name}<br /></>)}</div>
186
+ <div>
187
+ {prevRevision[0][field].map(col => (
188
+ <>
189
+ {col.name}
190
+ <br />
191
+ </>
192
+ ))}
193
+ </div>
187
194
  ) : (
188
195
  prevRevision[0][field].toString()
189
196
  )
@@ -95,7 +95,7 @@ describe('<NodeDependenciesTab />', () => {
95
95
 
96
96
  const mockDimensions = [
97
97
  {
98
- is_primary_key: false,
98
+ properties: [],
99
99
  name: 'default.dispatcher.company_name',
100
100
  node_display_name: 'Default: Dispatcher',
101
101
  node_name: 'default.dispatcher',
@@ -103,7 +103,7 @@ describe('<NodeDependenciesTab />', () => {
103
103
  type: 'string',
104
104
  },
105
105
  {
106
- is_primary_key: true,
106
+ properties: ['primary_key'],
107
107
  name: 'default.dispatcher.dispatcher_id',
108
108
  node_display_name: 'Default: Dispatcher',
109
109
  node_name: 'default.dispatcher',
@@ -111,7 +111,7 @@ describe('<NodeDependenciesTab />', () => {
111
111
  type: 'int',
112
112
  },
113
113
  {
114
- is_primary_key: false,
114
+ properties: [],
115
115
  name: 'default.hard_hat.city',
116
116
  node_display_name: 'Default: Hard Hat',
117
117
  node_name: 'default.hard_hat',
@@ -119,7 +119,7 @@ describe('<NodeDependenciesTab />', () => {
119
119
  type: 'string',
120
120
  },
121
121
  {
122
- is_primary_key: true,
122
+ properties: ['primary_key'],
123
123
  name: 'default.hard_hat.hard_hat_id',
124
124
  node_display_name: 'Default: Hard Hat',
125
125
  node_name: 'default.hard_hat',
@@ -34,7 +34,8 @@ describe('<NodeColumnLineage />', () => {
34
34
 
35
35
  it('renders and calls node_lineage with the correct node name', async () => {
36
36
  const djClient = mockDJClient();
37
- djClient.DataJunctionAPI.metric = name => defaultProps.djNode;
37
+ djClient.DataJunctionAPI.node = name => mocks.mockMetricNode;
38
+ djClient.DataJunctionAPI.getMetric = name => mocks.mockMetricNodeJson;
38
39
  const { container } = render(
39
40
  <DJClientContext.Provider value={djClient}>
40
41
  <NodeColumnLineage {...defaultProps} />
@@ -43,7 +44,7 @@ describe('<NodeColumnLineage />', () => {
43
44
 
44
45
  await waitFor(() => {
45
46
  expect(djClient.DataJunctionAPI.node_lineage).toHaveBeenCalledWith(
46
- defaultProps.djNode.name,
47
+ mocks.mockMetricNode.name,
47
48
  );
48
49
 
49
50
  // The origin node should be displayed
@@ -23,6 +23,7 @@ describe('<NodePage />', () => {
23
23
  DataJunctionAPI: {
24
24
  node: jest.fn(),
25
25
  metric: jest.fn(),
26
+ getMetric: jest.fn(),
26
27
  revalidate: jest.fn().mockReturnValue({ status: 'valid' }),
27
28
  node_dag: jest.fn().mockReturnValue(mocks.mockNodeDAG),
28
29
  clientCode: jest.fn().mockReturnValue('dj_client = DJClient()'),
@@ -279,7 +280,9 @@ describe('<NodePage />', () => {
279
280
  it('renders the NodeInfo tab correctly for a metric node', async () => {
280
281
  const djClient = mockDJClient();
281
282
  djClient.DataJunctionAPI.node.mockReturnValue(mocks.mockMetricNode);
282
- djClient.DataJunctionAPI.metric.mockReturnValue(mocks.mockMetricNode);
283
+ djClient.DataJunctionAPI.getMetric.mockReturnValue(
284
+ mocks.mockMetricNodeJson,
285
+ );
283
286
  const element = (
284
287
  <DJClientContext.Provider value={djClient}>
285
288
  <NodePage {...defaultProps} />
@@ -399,7 +402,9 @@ describe('<NodePage />', () => {
399
402
  it('renders the NodeColumns tab correctly', async () => {
400
403
  const djClient = mockDJClient();
401
404
  djClient.DataJunctionAPI.node.mockReturnValue(mocks.mockMetricNode);
402
- djClient.DataJunctionAPI.metric.mockReturnValue(mocks.mockMetricNode);
405
+ djClient.DataJunctionAPI.getMetric.mockReturnValue(
406
+ mocks.mockMetricNodeJson,
407
+ );
403
408
  djClient.DataJunctionAPI.columns.mockReturnValue(mocks.metricNodeColumns);
404
409
  djClient.DataJunctionAPI.attributes.mockReturnValue(mocks.attributes);
405
410
  djClient.DataJunctionAPI.dimensions.mockReturnValue(mocks.dimensions);
@@ -476,7 +481,9 @@ describe('<NodePage />', () => {
476
481
  it('renders the NodeHistory tab correctly', async () => {
477
482
  const djClient = mockDJClient();
478
483
  djClient.DataJunctionAPI.node.mockReturnValue(mocks.mockMetricNode);
479
- djClient.DataJunctionAPI.metric.mockReturnValue(mocks.mockMetricNode);
484
+ djClient.DataJunctionAPI.getMetric.mockReturnValue(
485
+ mocks.mockMetricNodeJson,
486
+ );
480
487
  djClient.DataJunctionAPI.columns.mockReturnValue(mocks.metricNodeColumns);
481
488
  djClient.DataJunctionAPI.history.mockReturnValue(mocks.metricNodeHistory);
482
489
  djClient.DataJunctionAPI.revisions.mockReturnValue(
@@ -576,7 +583,9 @@ describe('<NodePage />', () => {
576
583
  it('renders an empty NodeMaterialization tab correctly', async () => {
577
584
  const djClient = mockDJClient();
578
585
  djClient.DataJunctionAPI.node.mockReturnValue(mocks.mockMetricNode);
579
- djClient.DataJunctionAPI.metric.mockReturnValue(mocks.mockMetricNode);
586
+ djClient.DataJunctionAPI.getMetric.mockReturnValue(
587
+ mocks.mockMetricNodeJson,
588
+ );
580
589
  djClient.DataJunctionAPI.columns.mockReturnValue(mocks.metricNodeColumns);
581
590
  djClient.DataJunctionAPI.materializations.mockReturnValue([]);
582
591
 
@@ -609,7 +618,9 @@ describe('<NodePage />', () => {
609
618
  it('renders the NodeMaterialization tab with materializations correctly', async () => {
610
619
  const djClient = mockDJClient();
611
620
  djClient.DataJunctionAPI.node.mockReturnValue(mocks.mockTransformNode);
612
- // djClient.DataJunctionAPI.metric.mockReturnValue(mocks.mockMetricNode);
621
+ djClient.DataJunctionAPI.getMetric.mockReturnValue(
622
+ mocks.mockMetricNodeJson,
623
+ );
613
624
  djClient.DataJunctionAPI.columns.mockReturnValue(mocks.metricNodeColumns);
614
625
  djClient.DataJunctionAPI.materializations.mockReturnValue(
615
626
  mocks.nodeMaterializations,
@@ -659,10 +670,10 @@ describe('<NodePage />', () => {
659
670
  const djClient = mockDJClient();
660
671
  window.scrollTo = jest.fn();
661
672
  djClient.DataJunctionAPI.node.mockReturnValue(mocks.mockMetricNode);
662
- djClient.DataJunctionAPI.nodeDimensions.mockReturnValue(
663
- mocks.mockMetricNodeJson.dimensions,
673
+ djClient.DataJunctionAPI.nodeDimensions.mockReturnValue([]);
674
+ djClient.DataJunctionAPI.getMetric.mockReturnValue(
675
+ mocks.mockMetricNodeJson,
664
676
  );
665
- djClient.DataJunctionAPI.metric.mockReturnValue(mocks.mockMetricNode);
666
677
  djClient.DataJunctionAPI.columns.mockReturnValue(mocks.metricNodeColumns);
667
678
  djClient.DataJunctionAPI.sql.mockReturnValue({
668
679
  sql: 'SELECT * FROM testNode',
@@ -765,7 +776,9 @@ describe('<NodePage />', () => {
765
776
  it('renders a NodeColumnLineage tab correctly', async () => {
766
777
  const djClient = mockDJClient();
767
778
  djClient.DataJunctionAPI.node.mockReturnValue(mocks.mockMetricNode);
768
- djClient.DataJunctionAPI.metric.mockReturnValue(mocks.mockMetricNodeJson);
779
+ djClient.DataJunctionAPI.getMetric.mockReturnValue(
780
+ mocks.mockMetricNodeJson,
781
+ );
769
782
  djClient.DataJunctionAPI.columns.mockReturnValue(mocks.metricNodeColumns);
770
783
  djClient.DataJunctionAPI.node_lineage.mockReturnValue(
771
784
  mocks.mockNodeLineage,
@@ -796,7 +809,9 @@ describe('<NodePage />', () => {
796
809
  it('renders a NodeGraph tab correctly', async () => {
797
810
  const djClient = mockDJClient();
798
811
  djClient.DataJunctionAPI.node.mockReturnValue(mocks.mockMetricNode);
799
- djClient.DataJunctionAPI.metric.mockReturnValue(mocks.mockMetricNodeJson);
812
+ djClient.DataJunctionAPI.getMetric.mockReturnValue(
813
+ mocks.mockMetricNodeJson,
814
+ );
800
815
  djClient.DataJunctionAPI.columns.mockReturnValue(mocks.metricNodeColumns);
801
816
 
802
817
  const element = (
@@ -53,13 +53,13 @@ export function NodePage() {
53
53
  const data = await djClient.node(name);
54
54
  data.createNodeClientCode = await djClient.clientCode(name);
55
55
  if (data.type === 'metric') {
56
- const metric = await djClient.metric(name);
57
- data.dimensions = metric.dimensions;
58
- data.metric_metadata = metric.metric_metadata;
59
- data.required_dimensions = metric.required_dimensions;
60
- data.upstream_node = metric.upstream_node;
61
- data.expression = metric.expression;
62
- data.incompatible_druid_functions = metric.incompatible_druid_functions;
56
+ const metric = await djClient.getMetric(name);
57
+ data.metric_metadata = metric.current.metricMetadata;
58
+ data.required_dimensions = metric.current.requiredDimensions;
59
+ data.upstream_node = metric.current.parents[0].name;
60
+ data.expression = metric.current.metricMetadata.expression;
61
+ data.incompatible_druid_functions =
62
+ metric.current.metricMetadata.incompatibleDruidFunctions;
63
63
  }
64
64
  if (data.type === 'cube') {
65
65
  const cube = await djClient.cube(name);
@@ -128,6 +128,45 @@ export const DataJunctionAPI = {
128
128
  return data;
129
129
  },
130
130
 
131
+ getMetric: async function (name) {
132
+ const query = `
133
+ query GetMetric($name: String!) {
134
+ findNodes (names: [$name]) {
135
+ name
136
+ current {
137
+ parents { name }
138
+ metricMetadata {
139
+ direction
140
+ unit { name }
141
+ expression
142
+ incompatibleDruidFunctions
143
+ }
144
+ requiredDimensions {
145
+ name
146
+ }
147
+ }
148
+ }
149
+ }
150
+ `;
151
+
152
+ const results = await (
153
+ await fetch(DJ_GQL, {
154
+ method: 'POST',
155
+ headers: {
156
+ 'Content-Type': 'application/json',
157
+ },
158
+ credentials: 'include',
159
+ body: JSON.stringify({
160
+ query,
161
+ variables: {
162
+ name: name,
163
+ },
164
+ }),
165
+ })
166
+ ).json();
167
+ return results.data.findNodes[0];
168
+ },
169
+
131
170
  nodes: async function (prefix) {
132
171
  const queryParams = prefix ? `?prefix=${prefix}` : '';
133
172
  return await (
@@ -1096,4 +1096,45 @@ describe('DataJunctionAPI', () => {
1096
1096
  }),
1097
1097
  );
1098
1098
  });
1099
+
1100
+ it('calls getMetric correctly', async () => {
1101
+ fetch.mockResponseOnce(
1102
+ JSON.stringify({
1103
+ data: { findNodes: [{ name: 'default.num_repair_orders' }] },
1104
+ }),
1105
+ );
1106
+ await DataJunctionAPI.getMetric('default.num_repair_orders');
1107
+ expect(fetch).toHaveBeenCalledWith(
1108
+ `${DJ_URL}/graphql`,
1109
+ expect.objectContaining({
1110
+ method: 'POST',
1111
+ credentials: 'include',
1112
+ headers: {
1113
+ 'Content-Type': 'application/json',
1114
+ },
1115
+ }),
1116
+ );
1117
+ });
1118
+
1119
+ it('calls notebookExportCube correctly', async () => {
1120
+ fetch.mockResponseOnce(JSON.stringify({}));
1121
+ await DataJunctionAPI.notebookExportCube('default.repairs_cube');
1122
+ expect(fetch).toHaveBeenCalledWith(
1123
+ `${DJ_URL}/datajunction-clients/python/notebook/?cube=default.repairs_cube`,
1124
+ {
1125
+ credentials: 'include',
1126
+ },
1127
+ );
1128
+ });
1129
+
1130
+ it('calls notebookExportNamespace correctly', async () => {
1131
+ fetch.mockResponseOnce(JSON.stringify({}));
1132
+ await DataJunctionAPI.notebookExportNamespace('default');
1133
+ expect(fetch).toHaveBeenCalledWith(
1134
+ `${DJ_URL}/datajunction-clients/python/notebook/?namespace=default`,
1135
+ {
1136
+ credentials: 'include',
1137
+ },
1138
+ );
1139
+ });
1099
1140
  });
@@ -422,11 +422,13 @@ export const mocks = {
422
422
  post: { status: 'invalid' },
423
423
  details: {
424
424
  materialization: 'druid_metrics_cube__incremental_time__xyz',
425
- partition: [{
426
- column_name: 'xyz.abc',
427
- values: null,
428
- range: ['20240201', '20240301'],
429
- }],
425
+ partition: [
426
+ {
427
+ column_name: 'xyz.abc',
428
+ values: null,
429
+ range: ['20240201', '20240301'],
430
+ },
431
+ ],
430
432
  },
431
433
  created_at: '2023-08-21T16:48:56.950482+00:00',
432
434
  },
@@ -915,297 +917,20 @@ export const mocks = {
915
917
  },
916
918
  ],
917
919
  mockMetricNodeJson: {
918
- namespace: 'default',
919
- node_revision_id: 24,
920
- node_id: 24,
921
- type: 'metric',
922
- name: 'default.avg_repair_price',
923
- display_name: 'Default: Avg Repair Price',
924
- version: 'v1.0',
925
- status: 'valid',
926
- mode: 'published',
927
- catalog: {
928
- id: 1,
929
- uuid: '0fc18295-e1a2-4c3c-b72a-894725c12488',
930
- created_at: '2023-08-21T16:48:51.146121+00:00',
931
- updated_at: '2023-08-21T16:48:51.146122+00:00',
932
- extra_params: {},
933
- name: 'warehouse',
934
- },
935
- schema_: null,
936
- table: null,
937
- description: 'Average repair price',
938
- query:
939
- 'SELECT avg(price) default_DOT_avg_repair_price \n FROM default.repair_order_details\n\n',
940
- availability: null,
941
- columns: [
942
- {
943
- name: 'default_DOT_avg_repair_price',
944
- type: 'double',
945
- display_name: 'Default DOT avg repair price',
946
- attributes: [],
947
- dimension: null,
948
- },
949
- ],
950
- updated_at: '2023-08-21T16:48:56.932231+00:00',
951
- materializations: [],
952
- parents: [
953
- {
954
- name: 'default.repair_order_details',
955
- },
956
- ],
957
- created_at: '2023-08-21T16:48:56.932162+00:00',
958
- tags: [],
959
- primary_key: [],
960
- createNodeClientCode:
961
- 'dj = DJBuilder(DJ_URL)\n\navg_repair_price = dj.create_metric(\n description="Average repair price",\n display_name="Default: Avg Repair Price",\n name="default.avg_repair_price",\n primary_key=[],\n query="""SELECT avg(price) default_DOT_avg_repair_price \n FROM default.repair_order_details\n\n"""\n)',
962
- dimensions: [
963
- {
964
- name: 'default.date_dim.dateint',
965
- node_name: 'default.date_dim',
966
- node_display_name: 'Date Dim',
967
- is_primary_key: true,
968
- type: 'timestamp',
969
- path: [
970
- 'default.repair_order_details.repair_order_id',
971
- 'default.repair_order.hard_hat_id',
972
- 'default.hard_hat.birth_date',
973
- ],
974
- },
975
- {
976
- name: 'default.date_dim.dateint',
977
- node_name: 'default.date_dim',
978
- node_display_name: 'Date Dim',
979
- is_primary_key: true,
980
- type: 'timestamp',
981
- path: [
982
- 'default.repair_order_details.repair_order_id',
983
- 'default.repair_order.hard_hat_id',
984
- 'default.hard_hat.hire_date',
985
- ],
986
- },
987
- {
988
- name: 'default.date_dim.day',
989
- node_name: 'default.date_dim',
990
- node_display_name: 'Date Dim',
991
- is_primary_key: false,
992
- type: 'int',
993
- path: [
994
- 'default.repair_order_details.repair_order_id',
995
- 'default.repair_order.hard_hat_id',
996
- 'default.hard_hat.birth_date',
997
- ],
998
- },
999
- {
1000
- name: 'default.date_dim.day',
1001
- node_name: 'default.date_dim',
1002
- node_display_name: 'Date Dim',
1003
- is_primary_key: false,
1004
- type: 'int',
1005
- path: [
1006
- 'default.repair_order_details.repair_order_id',
1007
- 'default.repair_order.hard_hat_id',
1008
- 'default.hard_hat.hire_date',
1009
- ],
1010
- },
1011
- {
1012
- name: 'default.date_dim.month',
1013
- node_name: 'default.date_dim',
1014
- node_display_name: 'Date Dim',
1015
- is_primary_key: false,
1016
- type: 'int',
1017
- path: [
1018
- 'default.repair_order_details.repair_order_id',
1019
- 'default.repair_order.hard_hat_id',
1020
- 'default.hard_hat.birth_date',
1021
- ],
1022
- },
1023
- {
1024
- name: 'default.date_dim.month',
1025
- node_name: 'default.date_dim',
1026
- node_display_name: 'Date Dim',
1027
- is_primary_key: false,
1028
- type: 'int',
1029
- path: [
1030
- 'default.repair_order_details.repair_order_id',
1031
- 'default.repair_order.hard_hat_id',
1032
- 'default.hard_hat.hire_date',
1033
- ],
1034
- },
1035
- {
1036
- name: 'default.date_dim.year',
1037
- node_name: 'default.date_dim',
1038
- node_display_name: 'Date Dim',
1039
- is_primary_key: false,
1040
- type: 'int',
1041
- path: [
1042
- 'default.repair_order_details.repair_order_id',
1043
- 'default.repair_order.hard_hat_id',
1044
- 'default.hard_hat.birth_date',
1045
- ],
1046
- },
1047
- {
1048
- name: 'default.date_dim.year',
1049
- node_name: 'default.date_dim',
1050
- node_display_name: 'Date Dim',
1051
- is_primary_key: false,
1052
- type: 'int',
1053
- path: [
1054
- 'default.repair_order_details.repair_order_id',
1055
- 'default.repair_order.hard_hat_id',
1056
- 'default.hard_hat.hire_date',
1057
- ],
1058
- },
1059
- {
1060
- name: 'default.hard_hat.address',
1061
- node_name: 'default.hard_hat',
1062
- node_display_name: 'Hard hat',
1063
- is_primary_key: false,
1064
- type: 'string',
1065
- path: [
1066
- 'default.repair_order_details.repair_order_id',
1067
- 'default.repair_order.hard_hat_id',
1068
- ],
1069
- },
1070
- {
1071
- name: 'default.hard_hat.birth_date',
1072
- node_name: 'default.hard_hat',
1073
- node_display_name: 'Hard hat',
1074
- is_primary_key: false,
1075
- type: 'date',
1076
- path: [
1077
- 'default.repair_order_details.repair_order_id',
1078
- 'default.repair_order.hard_hat_id',
1079
- ],
1080
- },
1081
- {
1082
- name: 'default.hard_hat.city',
1083
- node_name: 'default.hard_hat',
1084
- node_display_name: 'Hard hat',
1085
- is_primary_key: false,
1086
- type: 'string',
1087
- path: [
1088
- 'default.repair_order_details.repair_order_id',
1089
- 'default.repair_order.hard_hat_id',
1090
- ],
1091
- },
1092
- {
1093
- name: 'default.hard_hat.contractor_id',
1094
- node_name: 'default.hard_hat',
1095
- node_display_name: 'Hard hat',
1096
- is_primary_key: false,
1097
- type: 'int',
1098
- path: [
1099
- 'default.repair_order_details.repair_order_id',
1100
- 'default.repair_order.hard_hat_id',
1101
- ],
1102
- },
1103
- {
1104
- name: 'default.hard_hat.country',
1105
- node_name: 'default.hard_hat',
1106
- node_display_name: 'Hard hat',
1107
- is_primary_key: false,
1108
- type: 'string',
1109
- path: [
1110
- 'default.repair_order_details.repair_order_id',
1111
- 'default.repair_order.hard_hat_id',
1112
- ],
1113
- },
1114
- {
1115
- name: 'default.hard_hat.first_name',
1116
- node_name: 'default.hard_hat',
1117
- node_display_name: 'Hard hat',
1118
- is_primary_key: false,
1119
- type: 'string',
1120
- path: [
1121
- 'default.repair_order_details.repair_order_id',
1122
- 'default.repair_order.hard_hat_id',
1123
- ],
1124
- },
1125
- {
1126
- name: 'default.hard_hat.hard_hat_id',
1127
- node_name: 'default.hard_hat',
1128
- node_display_name: 'Hard hat',
1129
- is_primary_key: true,
1130
- type: 'int',
1131
- path: [
1132
- 'default.repair_order_details.repair_order_id',
1133
- 'default.repair_order.hard_hat_id',
1134
- ],
1135
- },
1136
- {
1137
- name: 'default.hard_hat.hire_date',
1138
- node_name: 'default.hard_hat',
1139
- node_display_name: 'Hard hat',
1140
- is_primary_key: false,
1141
- type: 'date',
1142
- path: [
1143
- 'default.repair_order_details.repair_order_id',
1144
- 'default.repair_order.hard_hat_id',
1145
- ],
1146
- },
1147
- {
1148
- name: 'default.hard_hat.last_name',
1149
- node_name: 'default.hard_hat',
1150
- node_display_name: 'Hard hat',
1151
- is_primary_key: false,
1152
- type: 'string',
1153
- path: [
1154
- 'default.repair_order_details.repair_order_id',
1155
- 'default.repair_order.hard_hat_id',
1156
- ],
1157
- },
1158
- {
1159
- name: 'default.hard_hat.manager',
1160
- node_name: 'default.hard_hat',
1161
- node_display_name: 'Hard hat',
1162
- is_primary_key: false,
1163
- type: 'int',
1164
- path: [
1165
- 'default.repair_order_details.repair_order_id',
1166
- 'default.repair_order.hard_hat_id',
1167
- ],
1168
- },
1169
- {
1170
- name: 'default.hard_hat.postal_code',
1171
- node_name: 'default.hard_hat',
1172
- node_display_name: 'Hard hat',
1173
- is_primary_key: false,
1174
- type: 'string',
1175
- path: [
1176
- 'default.repair_order_details.repair_order_id',
1177
- 'default.repair_order.hard_hat_id',
1178
- ],
1179
- },
1180
- {
1181
- name: 'default.hard_hat.state',
1182
- node_name: 'default.hard_hat',
1183
- node_display_name: 'Hard hat',
1184
- is_primary_key: false,
1185
- type: 'string',
1186
- path: [
1187
- 'default.repair_order_details.repair_order_id',
1188
- 'default.repair_order.hard_hat_id',
1189
- ],
1190
- },
1191
- {
1192
- name: 'default.hard_hat.title',
1193
- node_name: 'default.hard_hat',
1194
- node_display_name: 'Hard hat',
1195
- is_primary_key: false,
1196
- type: 'string',
1197
- path: [
1198
- 'default.repair_order_details.repair_order_id',
1199
- 'default.repair_order.hard_hat_id',
1200
- ],
1201
- },
1202
- ],
1203
- metric_metadata: {
1204
- unit: {
1205
- name: 'unitless',
1206
- label: 'Unitless',
920
+ name: 'default.num_repair_orders',
921
+ current: {
922
+ parents: [
923
+ {
924
+ name: 'default.repair_orders',
925
+ },
926
+ ],
927
+ metricMetadata: {
928
+ direction: null,
929
+ unit: null,
930
+ expression: 'count(repair_order_id)',
931
+ incompatibleDruidFunctions: [],
1207
932
  },
1208
- direction: 'neutral',
933
+ requiredDimensions: [],
1209
934
  },
1210
935
  },
1211
936
  mockNodeDAG: [