datajunction-ui 0.0.30 → 0.0.34
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/TODO.md +265 -0
- package/package.json +1 -1
- package/src/app/components/ListGroupItem.jsx +2 -2
- package/src/app/components/NamespaceHeader.jsx +423 -65
- package/src/app/components/QueryInfo.jsx +2 -1
- package/src/app/components/__tests__/NamespaceHeader.test.jsx +14 -9
- package/src/app/components/__tests__/__snapshots__/ListGroupItem.test.tsx.snap +2 -2
- package/src/app/components/__tests__/__snapshots__/NamespaceHeader.test.jsx.snap +139 -34
- package/src/app/components/djgraph/__tests__/Collapse.test.jsx +6 -3
- package/src/app/pages/AddEditNodePage/index.jsx +1 -1
- package/src/app/pages/AddEditTagPage/index.jsx +1 -1
- package/src/app/pages/CubeBuilderPage/__tests__/index.test.jsx +55 -21
- package/src/app/pages/NamespacePage/index.jsx +44 -511
- package/src/app/pages/NodePage/NodeInfoTab.jsx +17 -6
- package/src/app/pages/NodePage/NodeMaterializationTab.jsx +5 -0
- package/src/app/pages/NodePage/NodePreAggregationsTab.jsx +656 -0
- package/src/app/pages/NodePage/NodeValidateTab.jsx +4 -2
- package/src/app/pages/NodePage/__tests__/NodePage.test.jsx +58 -45
- package/src/app/pages/NodePage/__tests__/NodePreAggregationsTab.test.jsx +654 -0
- package/src/app/pages/NodePage/index.jsx +9 -1
- package/src/app/pages/NotificationsPage/__tests__/index.test.jsx +19 -4
- package/src/app/pages/SQLBuilderPage/__tests__/index.test.jsx +47 -9
- package/src/app/pages/SQLBuilderPage/index.jsx +2 -2
- package/src/app/services/DJService.js +26 -0
- package/src/styles/preaggregations.css +547 -0
package/TODO.md
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# UI Test Improvements TODO
|
|
2
|
+
|
|
3
|
+
## Phase 1: Fix Test Warnings (Completed)
|
|
4
|
+
|
|
5
|
+
### 1.1 Fix `act()` Warnings ✅
|
|
6
|
+
|
|
7
|
+
- [x] Wrap async state updates in `waitFor()` properly
|
|
8
|
+
- [x] Add proper cleanup/waiting in tests for components with async effects
|
|
9
|
+
- [x] Fixed: SQLBuilderPage, NotificationsPage, CubeBuilderPage tests
|
|
10
|
+
- [ ] Remaining: Some AddEditNodePage/AddEditTagPage warnings (minor, from Formik internals)
|
|
11
|
+
|
|
12
|
+
### 1.2 Fix Key Prop Warnings ✅
|
|
13
|
+
|
|
14
|
+
- [x] Fix `key={rowValue}` in SQLBuilderPage (line 185) - use index-based key
|
|
15
|
+
- [x] Fix `key={rowValue}` in NodeValidateTab (line 346) - use index-based key
|
|
16
|
+
- [x] Fix missing key in QueryInfo.jsx error mapping (line 125)
|
|
17
|
+
- [x] Fix incorrect mock data in Collapse.test.jsx causing undefined keys
|
|
18
|
+
- [x] Fix missing key in NodeInfoTab.jsx: nodeTags, primary_key, required_dimensions, owners
|
|
19
|
+
|
|
20
|
+
### 1.3 Fix DOM/React Warnings ✅
|
|
21
|
+
|
|
22
|
+
- [x] Fix `value` prop on `textarea` should not be null - changed `custom_metadata: null` to `''` in AddEditNodePage
|
|
23
|
+
- [x] Fix invalid DOM property `class` -> `className` in AddEditTagPage
|
|
24
|
+
- [x] Fix nested elements: changed `<div>` to `<span>` in NodeInfoTab nodeTags
|
|
25
|
+
- [x] Fix nested `<p>` tags: changed outer `<p>` to `<div>` in ListGroupItem (Markdown can render `<p>`)
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Phase 2: GraphQL Type Safety (In Progress)
|
|
30
|
+
|
|
31
|
+
### Goal
|
|
32
|
+
|
|
33
|
+
Migrate all REST GET endpoints to GraphQL for:
|
|
34
|
+
|
|
35
|
+
- Field selection (fetch only what's needed)
|
|
36
|
+
- Type safety via GraphQL codegen
|
|
37
|
+
- Single source of truth for read operations
|
|
38
|
+
|
|
39
|
+
Keep REST for mutations (POST/PATCH/DELETE) since they're already implemented and mutations are simpler.
|
|
40
|
+
|
|
41
|
+
### Completed ✅
|
|
42
|
+
|
|
43
|
+
#### 2.1 Type Generation Setup
|
|
44
|
+
|
|
45
|
+
- [x] Added `@graphql-codegen/cli`, `@graphql-codegen/typescript`, `@graphql-codegen/typescript-operations`
|
|
46
|
+
- [x] Added `openapi-typescript` for REST type generation
|
|
47
|
+
- [x] Created `codegen.yml` pointing to static `schema.graphql` (no live server needed)
|
|
48
|
+
- [x] Added scripts: `yarn codegen`, `yarn codegen:graphql`, `yarn codegen:openapi`, `yarn codegen:check`
|
|
49
|
+
- [x] Generated types:
|
|
50
|
+
- `src/types/graphql.ts` (GraphQL types + query operation types)
|
|
51
|
+
- `src/types/openapi.ts` (REST endpoint types)
|
|
52
|
+
- [x] Server Makefile updated with `make generate-schemas` and `make check-schemas`
|
|
53
|
+
|
|
54
|
+
#### 2.2 GraphQL Query Files
|
|
55
|
+
|
|
56
|
+
- [x] Created `src/graphql/queries/` directory with 10 `.graphql` files:
|
|
57
|
+
- `listNodesForLanding.graphql`
|
|
58
|
+
- `listCubesForPreset.graphql`
|
|
59
|
+
- `cubeForPlanner.graphql`
|
|
60
|
+
- `getNodeForEditing.graphql`
|
|
61
|
+
- `getNodesByNames.graphql`
|
|
62
|
+
- `getMetric.graphql`
|
|
63
|
+
- `getCubeForEditing.graphql`
|
|
64
|
+
- `upstreamNodes.graphql`
|
|
65
|
+
- `downstreamNodes.graphql`
|
|
66
|
+
- `getNodeColumnsWithPartitions.graphql`
|
|
67
|
+
|
|
68
|
+
#### 2.3 Typed GraphQL Service
|
|
69
|
+
|
|
70
|
+
- [x] Created `src/app/services/DJGraphQLService.ts` - fully typed GraphQL service
|
|
71
|
+
- [x] All 10 existing GraphQL methods are now typed
|
|
72
|
+
- [x] DJService.js GraphQL methods now delegate to DJGraphQLService.ts
|
|
73
|
+
- [x] Components continue to use djClient context pattern (no changes needed)
|
|
74
|
+
|
|
75
|
+
### Usage
|
|
76
|
+
|
|
77
|
+
Components continue to use the existing djClient pattern - no changes needed:
|
|
78
|
+
|
|
79
|
+
```jsx
|
|
80
|
+
// Existing pattern (still works, now backed by typed service)
|
|
81
|
+
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
82
|
+
const node = await djClient.getNodeForEditing('my.node');
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
For direct typed access (optional):
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { DJGraphQLService } from '../services/DJGraphQLService';
|
|
89
|
+
import type { GetNodeForEditingQuery } from '../../types/graphql';
|
|
90
|
+
|
|
91
|
+
const node = await DJGraphQLService.getNodeForEditing('my.node');
|
|
92
|
+
// node.name, node.type, node.current.displayName are all typed
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Development Workflow
|
|
96
|
+
|
|
97
|
+
**Schema files (committed to repo):**
|
|
98
|
+
| File | Source |
|
|
99
|
+
|------|--------|
|
|
100
|
+
| `openapi.json` (monorepo root) | Server OpenAPI spec |
|
|
101
|
+
| `datajunction-server/.../schema.graphql` | Server GraphQL schema |
|
|
102
|
+
| `datajunction-ui/src/types/graphql.ts` | Generated GraphQL types |
|
|
103
|
+
| `datajunction-ui/src/types/openapi.ts` | Generated REST types |
|
|
104
|
+
|
|
105
|
+
**When you change the server API:**
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
cd datajunction-server
|
|
109
|
+
make generate-schemas # Regenerates openapi.json + schema.graphql
|
|
110
|
+
git add ../openapi.json datajunction_server/api/graphql/schema.graphql
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**When you change UI GraphQL queries or pull server changes:**
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
cd datajunction-ui
|
|
117
|
+
yarn codegen # Regenerates graphql.ts + openapi.ts
|
|
118
|
+
git add src/types/
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**CI validation:**
|
|
122
|
+
|
|
123
|
+
- Server: `make check` includes `make check-schemas` → fails if schemas are stale
|
|
124
|
+
- UI: `yarn codegen:check` → fails if generated types are stale
|
|
125
|
+
|
|
126
|
+
### Current State
|
|
127
|
+
|
|
128
|
+
**Typed GraphQL methods (in DJGraphQLService.ts):**
|
|
129
|
+
| Method | Purpose |
|
|
130
|
+
|--------|---------|
|
|
131
|
+
| `listNodesForLanding` | Paginated node listing |
|
|
132
|
+
| `listCubesForPreset` | Cube dropdown |
|
|
133
|
+
| `cubeForPlanner` | Query planner page |
|
|
134
|
+
| `getNodeForEditing` | Edit node form |
|
|
135
|
+
| `getNodesByNames` | Batch node fetch |
|
|
136
|
+
| `getMetric` | Metric details |
|
|
137
|
+
| `getCubeForEditing` | Edit cube form |
|
|
138
|
+
| `upstreamNodes` | Upstream nodes |
|
|
139
|
+
| `downstreamNodes` | Downstream nodes |
|
|
140
|
+
| `getNodeColumnsWithPartitions` | Column partitions |
|
|
141
|
+
|
|
142
|
+
### REST GET Endpoints to Migrate (~45 methods)
|
|
143
|
+
|
|
144
|
+
#### High Priority (core functionality, frequently used)
|
|
145
|
+
|
|
146
|
+
- [ ] `node` - GET /nodes/{name}/ → Full node details page
|
|
147
|
+
- [ ] `nodes` - GET /nodes/?prefix= → Node listings
|
|
148
|
+
- [ ] `nodesWithType` - GET /nodes/?node_type= → Filtered node lists
|
|
149
|
+
- [ ] `metric` - GET /metrics/{name}/ → Metric details (REST version)
|
|
150
|
+
- [ ] `metrics` - GET /metrics/ → All metrics list
|
|
151
|
+
- [ ] `cube` - GET /cubes/{name}/ → Full cube details
|
|
152
|
+
- [ ] `commonDimensions` - GET /metrics/common/dimensions/ → Dimension lookups
|
|
153
|
+
- [ ] `upstreams` - GET /nodes/{name}/upstream/ → (has GQL version, deprecate REST)
|
|
154
|
+
- [ ] `downstreams` - GET /nodes/{name}/downstream/ → (has GQL version, deprecate REST)
|
|
155
|
+
- [ ] `history` - GET /history?node= → Activity history
|
|
156
|
+
- [ ] `revisions` - GET /nodes/{name}/revisions/ → Node revision history
|
|
157
|
+
|
|
158
|
+
#### Medium Priority (namespace/catalog/tags)
|
|
159
|
+
|
|
160
|
+
- [ ] `namespaces` - GET /namespaces/ → Namespace list
|
|
161
|
+
- [ ] `namespace` - GET /namespaces/{nmspce} → Namespace details
|
|
162
|
+
- [ ] `namespaceSources` - GET /namespaces/{namespace}/sources
|
|
163
|
+
- [ ] `catalogs` - GET /catalogs → Catalog list
|
|
164
|
+
- [ ] `engines` - GET /engines → Engine list
|
|
165
|
+
- [ ] `dimensions` - GET /dimensions → All dimensions
|
|
166
|
+
- [ ] `nodeDimensions` - GET /nodes/{nodeName}/dimensions
|
|
167
|
+
- [ ] `nodesWithDimension` - GET /dimensions/{name}/nodes/
|
|
168
|
+
- [ ] `attributes` - GET /attributes
|
|
169
|
+
- [ ] `listTags` - GET /tags → Tag list
|
|
170
|
+
- [ ] `getTag` - GET /tags/{tagName} → Tag details
|
|
171
|
+
- [ ] `listNodesForTag` - GET /tags/{tagName}/nodes
|
|
172
|
+
- [ ] `users` - GET /users?with_activity=true
|
|
173
|
+
|
|
174
|
+
#### Medium Priority (materializations)
|
|
175
|
+
|
|
176
|
+
- [ ] `materializations` - GET /nodes/{node}/materializations
|
|
177
|
+
- [ ] `availabilityStates` - GET /nodes/{node}/availability/
|
|
178
|
+
- [ ] `materializationInfo` - GET /materialization/info
|
|
179
|
+
- [ ] `listPreaggs` - GET /preaggs/
|
|
180
|
+
- [ ] `getPreagg` - GET /preaggs/{preaggId}
|
|
181
|
+
- [ ] `getCubeDetails` - GET /cubes/{cubeName}
|
|
182
|
+
|
|
183
|
+
#### Lower Priority (SQL/data - may need special handling)
|
|
184
|
+
|
|
185
|
+
- [ ] `sql` - GET /sql/{metric_name}?... → Generated SQL
|
|
186
|
+
- [ ] `sqls` - GET /sql/?metrics=&dimensions= → Multi-metric SQL
|
|
187
|
+
- [ ] `measuresV3` - GET /sql/measures/v3/ → V3 measures SQL
|
|
188
|
+
- [ ] `metricsV3` - GET /sql/metrics/v3/ → V3 metrics SQL
|
|
189
|
+
- [ ] `data` - GET /data/?metrics=&dimensions= → Query execution
|
|
190
|
+
- [ ] `nodeData` - GET /data/{nodeName}? → Node data query
|
|
191
|
+
- [ ] `compiledSql` - GET /sql/{node}/ → Compiled SQL
|
|
192
|
+
|
|
193
|
+
#### Lower Priority (system metrics/admin)
|
|
194
|
+
|
|
195
|
+
- [ ] `querySystemMetric` - GET /system/data/{metric} → Dashboard analytics
|
|
196
|
+
- [ ] `system.node_counts_by_*` - System metrics
|
|
197
|
+
- [ ] `system.dimensions` - GET /system/dimensions
|
|
198
|
+
- [ ] `nodeDetails` - GET /nodes/details/
|
|
199
|
+
- [ ] `node_dag` - GET /nodes/{name}/dag/
|
|
200
|
+
- [ ] `node_lineage` - GET /nodes/{name}/lineage/
|
|
201
|
+
- [ ] `listDeployments` - GET /deployments
|
|
202
|
+
- [ ] `listMetricMetadata` - GET /metrics/metadata
|
|
203
|
+
|
|
204
|
+
#### Lower Priority (notifications/export)
|
|
205
|
+
|
|
206
|
+
- [ ] `getNotificationPreferences` - GET /notifications/
|
|
207
|
+
- [ ] `getSubscribedHistory` - GET /history/?only_subscribed=true
|
|
208
|
+
- [ ] `listServiceAccounts` - GET /service-accounts
|
|
209
|
+
- [ ] `clientCode` - GET /datajunction-clients/python/new_node/{name}
|
|
210
|
+
- [ ] `notebookExportCube` - GET /datajunction-clients/python/notebook/?cube=
|
|
211
|
+
- [ ] `notebookExportNamespace` - GET /datajunction-clients/python/notebook/?namespace=
|
|
212
|
+
|
|
213
|
+
#### Keep as REST (streaming - EventSource)
|
|
214
|
+
|
|
215
|
+
- `stream` - EventSource /stream/... (GraphQL subscriptions are different tech)
|
|
216
|
+
- `streamNodeData` - EventSource /stream/{nodeName}...
|
|
217
|
+
|
|
218
|
+
### Implementation Tasks
|
|
219
|
+
|
|
220
|
+
1. **Server-side: Extend GraphQL schema**
|
|
221
|
+
|
|
222
|
+
- [ ] Ensure all required fields are available in GraphQL schema
|
|
223
|
+
- [ ] Add any missing queries to the GraphQL API
|
|
224
|
+
- [ ] Verify introspection is enabled for codegen
|
|
225
|
+
|
|
226
|
+
2. **UI-side: Set up GraphQL codegen**
|
|
227
|
+
|
|
228
|
+
- [ ] Add `@graphql-codegen/cli` and `@graphql-codegen/typescript` as dev dependencies
|
|
229
|
+
- [ ] Create `codegen.yml` configuration
|
|
230
|
+
- [ ] Add npm script: `yarn generate-types`
|
|
231
|
+
- [ ] Generate types to `src/types/graphql.ts`
|
|
232
|
+
|
|
233
|
+
3. **UI-side: Migrate DJService methods**
|
|
234
|
+
|
|
235
|
+
- [ ] Start with high-priority methods
|
|
236
|
+
- [ ] Create GraphQL queries in `src/graphql/queries/`
|
|
237
|
+
- [ ] Update DJService.js methods to use GraphQL
|
|
238
|
+
- [ ] Remove deprecated REST calls
|
|
239
|
+
|
|
240
|
+
4. **Type the mutation payloads**
|
|
241
|
+
- [ ] Keep OpenAPI types for REST mutations
|
|
242
|
+
- [ ] Add `openapi-typescript` for mutation request/response types
|
|
243
|
+
- [ ] Generate to `src/types/api-mutations.ts`
|
|
244
|
+
|
|
245
|
+
### Benefits
|
|
246
|
+
|
|
247
|
+
- **Field selection**: UI fetches only needed data
|
|
248
|
+
- **Type safety**: Compile-time errors when code doesn't match schema
|
|
249
|
+
- **Single type source for reads**: GraphQL schema is authoritative
|
|
250
|
+
- **Performance**: Already proven with `cubeForPlanner`, `listNodesForLanding`
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Phase 3: Integration Tests (Long-term)
|
|
255
|
+
|
|
256
|
+
### Goal
|
|
257
|
+
|
|
258
|
+
Add integration test suite that runs against a real DJ server to catch real integration issues.
|
|
259
|
+
|
|
260
|
+
### Tasks
|
|
261
|
+
|
|
262
|
+
- [ ] Add Docker Compose setup for test DJ server
|
|
263
|
+
- [ ] Create separate test suite for integration tests
|
|
264
|
+
- [ ] Add CI workflow to run integration tests
|
|
265
|
+
- [ ] Consider using Playwright or Cypress for E2E tests
|
package/package.json
CHANGED
|
@@ -9,14 +9,14 @@ export default class ListGroupItem extends Component {
|
|
|
9
9
|
<div className="d-flex gap-2 w-100 justify-content-between py-3">
|
|
10
10
|
<div>
|
|
11
11
|
<h6 className="mb-0 w-100">{label}</h6>
|
|
12
|
-
<
|
|
12
|
+
<div
|
|
13
13
|
className="mb-0 opacity-75"
|
|
14
14
|
role="dialog"
|
|
15
15
|
aria-hidden="false"
|
|
16
16
|
aria-label={label}
|
|
17
17
|
>
|
|
18
18
|
<Markdown>{value}</Markdown>
|
|
19
|
-
</
|
|
19
|
+
</div>
|
|
20
20
|
</div>
|
|
21
21
|
</div>
|
|
22
22
|
</div>
|