datajunction-ui 0.0.107 → 0.0.109

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.107",
3
+ "version": "0.0.109",
4
4
  "description": "DataJunction UI",
5
5
  "module": "src/index.tsx",
6
6
  "repository": {
@@ -8,7 +8,7 @@ const Explorer = ({
8
8
  item = [],
9
9
  current,
10
10
  isTopLevel = false,
11
- namespaceSources = {},
11
+ gitRoots = new Set(),
12
12
  }) => {
13
13
  const djClient = useContext(DJClientContext).DataJunctionAPI;
14
14
  const [items, setItems] = useState([]);
@@ -139,50 +139,41 @@ const Explorer = ({
139
139
  >
140
140
  {items.namespace}
141
141
  </a>
142
- {/* Deployment source badge */}
143
- {namespaceSources[items.path] &&
144
- namespaceSources[items.path].total_deployments > 0 &&
145
- namespaceSources[items.path].primary_source?.type === 'git' && (
146
- <span
147
- title={`Git: ${
148
- namespaceSources[items.path].primary_source.repository ||
149
- 'unknown'
150
- }${
151
- namespaceSources[items.path].primary_source.branch
152
- ? ` (${namespaceSources[items.path].primary_source.branch})`
153
- : ''
154
- }`}
155
- style={{
156
- marginLeft: '6px',
157
- fontSize: '9px',
158
- padding: '1px 4px',
159
- borderRadius: '3px',
160
- backgroundColor: '#d4edda',
161
- color: '#155724',
162
- display: 'inline-flex',
163
- alignItems: 'center',
164
- gap: '2px',
165
- }}
142
+ {/* Git root badge */}
143
+ {gitRoots.has(items.path) && (
144
+ <span
145
+ title="Git-backed namespace"
146
+ style={{
147
+ marginLeft: '6px',
148
+ fontSize: '9px',
149
+ padding: '1px 4px',
150
+ borderRadius: '3px',
151
+ backgroundColor: '#d4edda',
152
+ color: '#155724',
153
+ display: 'inline-flex',
154
+ alignItems: 'center',
155
+ gap: '2px',
156
+ }}
157
+ >
158
+ <svg
159
+ xmlns="http://www.w3.org/2000/svg"
160
+ width="10"
161
+ height="10"
162
+ viewBox="0 0 24 24"
163
+ fill="none"
164
+ stroke="currentColor"
165
+ strokeWidth="2"
166
+ strokeLinecap="round"
167
+ strokeLinejoin="round"
166
168
  >
167
- <svg
168
- xmlns="http://www.w3.org/2000/svg"
169
- width="10"
170
- height="10"
171
- viewBox="0 0 24 24"
172
- fill="none"
173
- stroke="currentColor"
174
- strokeWidth="2"
175
- strokeLinecap="round"
176
- strokeLinejoin="round"
177
- >
178
- <line x1="6" y1="3" x2="6" y2="15"></line>
179
- <circle cx="18" cy="6" r="3"></circle>
180
- <circle cx="6" cy="18" r="3"></circle>
181
- <path d="M18 9a9 9 0 0 1-9 9"></path>
182
- </svg>
183
- Git
184
- </span>
185
- )}
169
+ <line x1="6" y1="3" x2="6" y2="15"></line>
170
+ <circle cx="18" cy="6" r="3"></circle>
171
+ <circle cx="6" cy="18" r="3"></circle>
172
+ <path d="M18 9a9 9 0 0 1-9 9"></path>
173
+ </svg>
174
+ Git
175
+ </span>
176
+ )}
186
177
  <button
187
178
  className="namespace-add-button"
188
179
  onClick={e => {
@@ -289,7 +280,7 @@ const Explorer = ({
289
280
  item={item}
290
281
  current={highlight}
291
282
  isTopLevel={false}
292
- namespaceSources={namespaceSources}
283
+ gitRoots={gitRoots}
293
284
  />
294
285
  </div>
295
286
  </div>
@@ -8,6 +8,7 @@ import userEvent from '@testing-library/user-event';
8
8
 
9
9
  const mockDjClient = {
10
10
  namespaces: jest.fn(),
11
+ listNamespacesWithGit: jest.fn(),
11
12
  namespace: jest.fn(),
12
13
  listNodesForLanding: jest.fn(),
13
14
  addNamespace: jest.fn(),
@@ -81,40 +82,18 @@ describe('NamespacePage', () => {
81
82
  mockDjClient.getNamespaceBranches.mockResolvedValue([]);
82
83
  mockDjClient.listDeployments.mockResolvedValue([]);
83
84
  mockDjClient.getPullRequest.mockResolvedValue(null);
84
- mockDjClient.namespaces.mockResolvedValue([
85
- {
86
- namespace: 'common.one',
87
- num_nodes: 3,
88
- },
89
- {
90
- namespace: 'common.one.a',
91
- num_nodes: 6,
92
- },
93
- {
94
- namespace: 'common.one.b',
95
- num_nodes: 17,
96
- },
97
- {
98
- namespace: 'common.one.c',
99
- num_nodes: 64,
100
- },
101
- {
102
- namespace: 'default',
103
- num_nodes: 41,
104
- },
105
- {
106
- namespace: 'default.fruits',
107
- num_nodes: 1,
108
- },
109
- {
110
- namespace: 'default.fruits.citrus.lemons',
111
- num_nodes: 1,
112
- },
113
- {
114
- namespace: 'default.vegetables',
115
- num_nodes: 2,
116
- },
117
- ]);
85
+ const mockNamespaces = [
86
+ { namespace: 'common.one', numNodes: 3, git: null },
87
+ { namespace: 'common.one.a', numNodes: 6, git: null },
88
+ { namespace: 'common.one.b', numNodes: 17, git: null },
89
+ { namespace: 'common.one.c', numNodes: 64, git: null },
90
+ { namespace: 'default', numNodes: 41, git: null },
91
+ { namespace: 'default.fruits', numNodes: 1, git: null },
92
+ { namespace: 'default.fruits.citrus.lemons', numNodes: 1, git: null },
93
+ { namespace: 'default.vegetables', numNodes: 2, git: null },
94
+ ];
95
+ mockDjClient.namespaces.mockResolvedValue(mockNamespaces);
96
+ mockDjClient.listNamespacesWithGit.mockResolvedValue(mockNamespaces);
118
97
  mockDjClient.namespace.mockResolvedValue([
119
98
  {
120
99
  name: 'testNode',
@@ -376,7 +376,7 @@ export function NamespacePage() {
376
376
  const [retrieved, setRetrieved] = useState(false);
377
377
 
378
378
  const [namespaceHierarchy, setNamespaceHierarchy] = useState([]);
379
- const [namespaceSources, setNamespaceSources] = useState({});
379
+ const [gitRoots, setGitRoots] = useState(new Set());
380
380
  // Use undefined to indicate "not yet loaded", null means "loaded but no config"
381
381
  const [gitConfig, setGitConfig] = useState(undefined);
382
382
 
@@ -506,23 +506,19 @@ export function NamespacePage() {
506
506
 
507
507
  useEffect(() => {
508
508
  const fetchData = async () => {
509
- const namespaces = await djClient.namespaces();
509
+ const namespaces = await djClient.listNamespacesWithGit();
510
510
  const hierarchy = createNamespaceHierarchy(namespaces);
511
511
  setNamespaceHierarchy(hierarchy);
512
512
 
513
- // Fetch sources for all namespaces in bulk
514
- const allNamespaceNames = namespaces.map(ns => ns.namespace);
515
- if (allNamespaceNames.length > 0) {
516
- const sourcesResponse = await djClient.namespaceSourcesBulk(
517
- allNamespaceNames,
518
- );
519
- if (sourcesResponse && sourcesResponse.sources) {
520
- setNamespaceSources(sourcesResponse.sources);
521
- }
522
- }
513
+ const roots = new Set(
514
+ namespaces
515
+ .filter(ns => ns.git?.__typename === 'GitRootConfig')
516
+ .map(ns => ns.namespace),
517
+ );
518
+ setGitRoots(roots);
523
519
  };
524
520
  fetchData().catch(console.error);
525
- }, [djClient, djClient.namespaces]);
521
+ }, [djClient]);
526
522
 
527
523
  useEffect(() => {
528
524
  const fetchData = async () => {
@@ -1133,7 +1129,7 @@ export function NamespacePage() {
1133
1129
  defaultExpand={true}
1134
1130
  isTopLevel={true}
1135
1131
  key={child.namespace}
1136
- namespaceSources={namespaceSources}
1132
+ gitRoots={gitRoots}
1137
1133
  />
1138
1134
  ))
1139
1135
  : null}
@@ -1123,6 +1123,44 @@ export const DataJunctionAPI = {
1123
1123
  ).json();
1124
1124
  },
1125
1125
 
1126
+ listNamespacesWithGit: async function () {
1127
+ const query = `
1128
+ query ListNamespaces {
1129
+ listNamespaces {
1130
+ namespace
1131
+ numNodes
1132
+ git {
1133
+ __typename
1134
+ ... on GitRootConfig {
1135
+ repo
1136
+ path
1137
+ defaultBranch
1138
+ }
1139
+ ... on GitBranchConfig {
1140
+ branch
1141
+ gitOnly
1142
+ parentNamespace
1143
+ root {
1144
+ repo
1145
+ path
1146
+ defaultBranch
1147
+ }
1148
+ }
1149
+ }
1150
+ }
1151
+ }
1152
+ `;
1153
+ const result = await (
1154
+ await fetch(DJ_GQL, {
1155
+ method: 'POST',
1156
+ headers: { 'Content-Type': 'application/json' },
1157
+ credentials: 'include',
1158
+ body: JSON.stringify({ query }),
1159
+ })
1160
+ ).json();
1161
+ return result?.data?.listNamespaces || [];
1162
+ },
1163
+
1126
1164
  namespaceSources: async function (namespace) {
1127
1165
  return await (
1128
1166
  await fetch(`${DJ_URL}/namespaces/${namespace}/sources`, {