@teambit/graph 1.0.316 → 1.0.318
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/artifacts/__bit_junit.xml +1 -1
- package/artifacts/preview/teambit_component_graph-preview.js +1 -1
- package/artifacts/schema.json +281 -172
- package/dist/graph.graphql.js +3 -2
- package/dist/graph.graphql.js.map +1 -1
- package/dist/{preview-1719372071684.js → preview-1719544843434.js} +2 -2
- package/dist/ui/component-node/component-node.js +6 -7
- package/dist/ui/component-node/component-node.js.map +1 -1
- package/dist/ui/dependencies-compare/compare-node-model.d.ts +1 -1
- package/dist/ui/dependencies-compare/compare-node-model.js.map +1 -1
- package/dist/ui/dependencies-compare/dependency-compare-node.js +7 -4
- package/dist/ui/dependencies-compare/dependency-compare-node.js.map +1 -1
- package/dist/ui/dependencies-compare/diff-graph.js +4 -4
- package/dist/ui/dependencies-compare/diff-graph.js.map +1 -1
- package/dist/ui/dependencies-graph/calc-elements.js +2 -2
- package/dist/ui/dependencies-graph/calc-elements.js.map +1 -1
- package/dist/ui/dependencies-graph/dependencies-graph.d.ts +3 -2
- package/dist/ui/dependencies-graph/dependencies-graph.js +30 -12
- package/dist/ui/dependencies-graph/dependencies-graph.js.map +1 -1
- package/dist/ui/graph-page/graph-filters.d.ts +1 -0
- package/dist/ui/graph-page/graph-filters.js.map +1 -1
- package/dist/ui/graph-page/graph-page.js +18 -19
- package/dist/ui/graph-page/graph-page.js.map +1 -1
- package/dist/ui/graph-page/graph-page.module.scss +3 -1
- package/dist/ui/graph.section.js +3 -3
- package/dist/ui/graph.section.js.map +1 -1
- package/dist/ui/query/get-graph.query.d.ts +2 -1
- package/dist/ui/query/get-graph.query.js +15 -3
- package/dist/ui/query/get-graph.query.js.map +1 -1
- package/dist/ui/query/node-model.d.ts +3 -2
- package/dist/ui/query/node-model.js +3 -1
- package/dist/ui/query/node-model.js.map +1 -1
- package/dist/ui/query/use-graph-query.d.ts +2 -1
- package/dist/ui/query/use-graph-query.js +43 -14
- package/dist/ui/query/use-graph-query.js.map +1 -1
- package/dist/ui/query/use-graph.d.ts +2 -0
- package/package.json +13 -15
- package/ui/component-node/component-node.tsx +6 -5
- package/ui/dependencies-compare/compare-node-model.ts +1 -1
- package/ui/dependencies-compare/dependency-compare-node.tsx +4 -4
- package/ui/dependencies-compare/diff-graph.ts +5 -4
- package/ui/dependencies-graph/calc-elements.tsx +2 -2
- package/ui/dependencies-graph/dependencies-graph.tsx +29 -10
- package/ui/graph-page/graph-filters.tsx +1 -0
- package/ui/graph-page/graph-page.module.scss +3 -1
- package/ui/graph-page/graph-page.tsx +17 -15
- package/ui/graph.section.tsx +3 -3
- package/ui/query/get-graph.query.ts +15 -5
- package/ui/query/node-model.ts +5 -3
- package/ui/query/use-graph-query.ts +53 -11
@@ -1,4 +1,4 @@
|
|
1
|
-
import React, { useCallback,
|
1
|
+
import React, { useCallback, useMemo, useRef, useEffect } from 'react';
|
2
2
|
import classnames from 'classnames';
|
3
3
|
import ReactFlow, {
|
4
4
|
Background,
|
@@ -11,6 +11,7 @@ import ReactFlow, {
|
|
11
11
|
Position,
|
12
12
|
ReactFlowProps,
|
13
13
|
ReactFlowProvider,
|
14
|
+
useNodesState,
|
14
15
|
} from 'reactflow';
|
15
16
|
import { ComponentID } from '@teambit/component';
|
16
17
|
import { ComponentWidgetSlot } from '../../graph.ui.runtime';
|
@@ -36,9 +37,10 @@ function ComponentNodeContainer(props: NodeProps) {
|
|
36
37
|
|
37
38
|
export type DependenciesGraphProps = {
|
38
39
|
rootNode: ComponentID;
|
39
|
-
graph
|
40
|
+
graph?: GraphModel<NodeModel, EdgeModel>;
|
40
41
|
componentWidgets: ComponentWidgetSlot;
|
41
42
|
onLoad?: (instance: ReactFlowInstance) => void;
|
43
|
+
loadingGraphMetadata?: boolean;
|
42
44
|
} & Omit<ReactFlowProps, 'elements'>;
|
43
45
|
|
44
46
|
export function DependenciesGraph({
|
@@ -48,17 +50,24 @@ export function DependenciesGraph({
|
|
48
50
|
className,
|
49
51
|
onLoad,
|
50
52
|
children,
|
53
|
+
loadingGraphMetadata,
|
51
54
|
...rest
|
52
55
|
}: DependenciesGraphProps) {
|
53
56
|
const nodeTypes: NodeTypes = React.useMemo(() => ({ ComponentNode: ComponentNodeContainer }), []);
|
54
57
|
const graphRef = useRef<ReactFlowInstance>();
|
55
58
|
const elements = calcElements(graph, { rootNode });
|
59
|
+
const [nodes, setNodes] = useNodesState(elements.nodes);
|
56
60
|
|
57
|
-
|
61
|
+
useEffect(() => {
|
62
|
+
setNodes(elements.nodes);
|
63
|
+
}, [elements.nodes]);
|
64
|
+
|
65
|
+
const context = useMemo(() => ({ componentWidgets, loadingGraphMetadata }), [componentWidgets, loadingGraphMetadata]);
|
58
66
|
|
59
67
|
const handleLoad = useCallback(
|
60
68
|
(instance: ReactFlowInstance) => {
|
61
|
-
|
69
|
+
graphRef.current = instance;
|
70
|
+
if ((elements?.nodes.length ?? 0) <= 3) {
|
62
71
|
instance.fitView({
|
63
72
|
padding: 2,
|
64
73
|
maxZoom: 1,
|
@@ -78,13 +87,18 @@ export function DependenciesGraph({
|
|
78
87
|
|
79
88
|
useEffect(() => {
|
80
89
|
setTimeout(() => {
|
81
|
-
if (
|
90
|
+
if (!elements?.nodes.length) return;
|
91
|
+
if ((elements?.nodes?.length ?? 0) <= 3) {
|
82
92
|
return graphRef.current?.fitView({
|
83
93
|
padding: 2,
|
94
|
+
maxZoom: 1,
|
84
95
|
});
|
85
|
-
|
86
|
-
|
87
|
-
|
96
|
+
}
|
97
|
+
return graphRef.current?.fitView({
|
98
|
+
maxZoom: 1,
|
99
|
+
});
|
100
|
+
}, 100);
|
101
|
+
}, [elements?.nodes.length]);
|
88
102
|
|
89
103
|
return (
|
90
104
|
<ComponentGraphContext.Provider value={context}>
|
@@ -101,10 +115,15 @@ export function DependenciesGraph({
|
|
101
115
|
minZoom={0}
|
102
116
|
{...rest}
|
103
117
|
className={classnames(styles.graph, className)}
|
104
|
-
|
105
|
-
|
118
|
+
nodes={nodes}
|
119
|
+
edges={elements.edges}
|
106
120
|
nodeTypes={nodeTypes}
|
107
121
|
onInit={handleLoad}
|
122
|
+
fitView={true}
|
123
|
+
fitViewOptions={{
|
124
|
+
padding: (elements?.nodes.length ?? 0) <= 3 ? 2 : undefined,
|
125
|
+
maxZoom: 1,
|
126
|
+
}}
|
108
127
|
proOptions={{
|
109
128
|
hideAttribution: true,
|
110
129
|
}}
|
@@ -1,10 +1,9 @@
|
|
1
1
|
import React, { useContext, useState } from 'react';
|
2
|
-
|
3
|
-
import { H2 } from '@teambit/documenter.ui.heading';
|
4
2
|
import { NotFoundPage } from '@teambit/design.ui.pages.not-found';
|
5
3
|
import { ServerErrorPage } from '@teambit/design.ui.pages.server-error';
|
6
4
|
import { ComponentContext } from '@teambit/component';
|
7
|
-
import {
|
5
|
+
import { skeleton } from '@teambit/design.skeletons.base-skeleton';
|
6
|
+
import classNames from 'classnames';
|
8
7
|
|
9
8
|
import { useGraphQuery } from '../query';
|
10
9
|
import { DependenciesGraph } from '../dependencies-graph';
|
@@ -23,31 +22,34 @@ export function GraphPage({ componentWidgets }: GraphPageProps) {
|
|
23
22
|
const component = useContext(ComponentContext);
|
24
23
|
|
25
24
|
const [filter, setFilter] = useState<GraphFilter>('runtimeOnly');
|
25
|
+
|
26
26
|
const onCheckFilter = (isFiltered: boolean) => {
|
27
27
|
setFilter(isFiltered ? 'runtimeOnly' : undefined);
|
28
28
|
};
|
29
29
|
|
30
|
-
const { graph, error, loading } = useGraphQuery([component.id.toString()], filter);
|
31
|
-
if (error) return error.code === 404 ? <NotFoundPage /> : <ServerErrorPage />;
|
32
|
-
if (!graph) return <FullLoader />;
|
30
|
+
const { graph, error, graphLoading, loading } = useGraphQuery([component.id.toString()], filter);
|
33
31
|
|
34
32
|
const isFiltered = filter === 'runtimeOnly';
|
35
33
|
|
34
|
+
if (error) return error.code === 404 ? <NotFoundPage /> : <ServerErrorPage />;
|
35
|
+
|
36
36
|
return (
|
37
|
-
<div className={styles.page}>
|
38
|
-
<H2 size="xs">Component Dependencies</H2>
|
37
|
+
<div className={classNames(styles.page)}>
|
39
38
|
<DependenciesGraph
|
40
39
|
componentWidgets={componentWidgets}
|
41
40
|
graph={graph}
|
42
41
|
rootNode={component.id}
|
43
|
-
className={styles.graph}
|
42
|
+
className={classNames(styles.graph, !graph && skeleton)}
|
43
|
+
loadingGraphMetadata={graphLoading}
|
44
44
|
>
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
45
|
+
{graph && (
|
46
|
+
<GraphFilters
|
47
|
+
className={classNames(styles.filters)}
|
48
|
+
disable={loading}
|
49
|
+
isFiltered={isFiltered}
|
50
|
+
onChangeFilter={onCheckFilter}
|
51
|
+
/>
|
52
|
+
)}
|
51
53
|
</DependenciesGraph>
|
52
54
|
</div>
|
53
55
|
);
|
package/ui/graph.section.tsx
CHANGED
@@ -8,12 +8,12 @@ export class GraphSection implements Section {
|
|
8
8
|
constructor(private componentWidgetSlot: ComponentWidgetSlot) {}
|
9
9
|
|
10
10
|
route = {
|
11
|
-
path: '~
|
11
|
+
path: '~graph',
|
12
12
|
element: <GraphPage componentWidgets={this.componentWidgetSlot} />,
|
13
13
|
};
|
14
14
|
navigationLink = {
|
15
|
-
href: '~
|
16
|
-
children: '
|
15
|
+
href: '~graph',
|
16
|
+
children: 'Graph',
|
17
17
|
};
|
18
18
|
order = 40;
|
19
19
|
}
|
@@ -1,7 +1,20 @@
|
|
1
1
|
import { gql } from '@apollo/client';
|
2
2
|
import { EdgeType } from '../../edge-type';
|
3
3
|
|
4
|
-
|
4
|
+
export const GET_GRAPH_IDS = gql`
|
5
|
+
query graph($ids: [String], $filter: String) {
|
6
|
+
graph(ids: $ids, filter: $filter) {
|
7
|
+
nodes {
|
8
|
+
id
|
9
|
+
}
|
10
|
+
edges {
|
11
|
+
sourceId
|
12
|
+
targetId
|
13
|
+
dependencyLifecycleType
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
17
|
+
`;
|
5
18
|
|
6
19
|
export const GET_GRAPH = gql`
|
7
20
|
query graph($ids: [String], $filter: String) {
|
@@ -46,19 +59,16 @@ export type RawGraph = {
|
|
46
59
|
|
47
60
|
export type RawNode = {
|
48
61
|
id: string;
|
49
|
-
component
|
62
|
+
component?: {
|
50
63
|
id: {
|
51
64
|
name: string;
|
52
65
|
scope: string;
|
53
66
|
version: string;
|
54
67
|
};
|
55
|
-
|
56
68
|
displayName: string;
|
57
|
-
|
58
69
|
deprecation: {
|
59
70
|
isDeprecate: boolean;
|
60
71
|
};
|
61
|
-
|
62
72
|
env: {
|
63
73
|
id: string;
|
64
74
|
icon: string;
|
package/ui/query/node-model.ts
CHANGED
@@ -1,16 +1,18 @@
|
|
1
|
-
import { ComponentModel } from '@teambit/component';
|
1
|
+
import { ComponentID, ComponentModel } from '@teambit/component';
|
2
2
|
import { RawNode } from './get-graph.query';
|
3
3
|
|
4
4
|
export class NodeModel {
|
5
5
|
id: string;
|
6
|
-
component
|
6
|
+
component?: ComponentModel;
|
7
|
+
componentId: ComponentID;
|
7
8
|
|
8
9
|
static from(rawNode: RawNode) {
|
9
10
|
const node = new NodeModel();
|
10
11
|
node.id = rawNode.id;
|
11
12
|
// @TODO - component model should not expect all fields to have values
|
12
13
|
// @ts-ignore
|
13
|
-
node.component = ComponentModel.from(rawNode.component);
|
14
|
+
node.component = rawNode.component ? ComponentModel.from(rawNode.component) : undefined;
|
15
|
+
node.componentId = node.component ? node.component.id : ComponentID.fromString(rawNode.id);
|
14
16
|
return node;
|
15
17
|
}
|
16
18
|
}
|
@@ -1,7 +1,7 @@
|
|
1
|
-
import { useMemo } from 'react';
|
2
|
-
import {
|
1
|
+
import { useMemo, useEffect, useState } from 'react';
|
2
|
+
import { useQuery, useLazyQuery } from '@apollo/client';
|
3
3
|
import { GraphQlError } from '@teambit/graphql';
|
4
|
-
import { GET_GRAPH, RawGraphQuery } from './get-graph.query';
|
4
|
+
import { GET_GRAPH, RawGraphQuery, GET_GRAPH_IDS } from './get-graph.query';
|
5
5
|
import { GraphModel } from './graph-model';
|
6
6
|
|
7
7
|
type QueryVariables = {
|
@@ -9,22 +9,64 @@ type QueryVariables = {
|
|
9
9
|
filter?: string;
|
10
10
|
};
|
11
11
|
|
12
|
-
/** provides dependencies graph data from graphQL */
|
13
12
|
export function useGraphQuery(componentId?: string[], filter?: string) {
|
14
|
-
|
13
|
+
// Eagerly fetch GET_GRAPH_IDS
|
14
|
+
const {
|
15
|
+
data: idsData,
|
16
|
+
error: idsError,
|
17
|
+
loading: idsLoading,
|
18
|
+
} = useQuery<RawGraphQuery, QueryVariables>(GET_GRAPH_IDS, {
|
15
19
|
variables: { ids: componentId, filter },
|
16
|
-
skip: !componentId,
|
20
|
+
skip: !componentId || !filter,
|
17
21
|
});
|
18
22
|
|
19
|
-
|
20
|
-
const
|
21
|
-
|
23
|
+
// Lazily fetch GET_GRAPH
|
24
|
+
const [getGraph, { data: graphData, error: graphError, loading: graphLoading }] = useLazyQuery<
|
25
|
+
RawGraphQuery,
|
26
|
+
QueryVariables
|
27
|
+
>(GET_GRAPH);
|
28
|
+
|
29
|
+
const [fetchError, setFetchError] = useState<GraphQlError | undefined>(undefined);
|
30
|
+
|
31
|
+
const [shouldRefetchGraph, setShouldRefetchGraph] = useState(false);
|
32
|
+
|
33
|
+
useEffect(() => {
|
34
|
+
if (idsData?.graph.nodes.length || !filter) {
|
35
|
+
setShouldRefetchGraph(true);
|
36
|
+
}
|
37
|
+
}, [idsData?.graph.nodes.length, filter]);
|
38
|
+
|
39
|
+
useEffect(() => {
|
40
|
+
if (shouldRefetchGraph) {
|
41
|
+
setShouldRefetchGraph(false);
|
42
|
+
void getGraph({ variables: { ids: componentId, filter } }).catch((error) => {
|
43
|
+
setFetchError(new GraphQlError(500, error.message));
|
44
|
+
});
|
45
|
+
}
|
46
|
+
}, [componentId, filter, getGraph, shouldRefetchGraph]);
|
47
|
+
|
48
|
+
const rawGraph = idsLoading
|
49
|
+
? undefined
|
50
|
+
: (idsData?.graph &&
|
51
|
+
graphData?.graph &&
|
52
|
+
idsData?.graph.nodes.length === graphData?.graph.nodes.length &&
|
53
|
+
graphData?.graph) ||
|
54
|
+
idsData?.graph ||
|
55
|
+
graphData?.graph;
|
56
|
+
|
57
|
+
const clientError = !rawGraph && !idsLoading && !graphLoading ? new GraphQlError(404) : undefined;
|
58
|
+
const serverError =
|
59
|
+
graphError?.message || idsError?.message
|
60
|
+
? new GraphQlError(500, graphError?.message || idsError?.message)
|
61
|
+
: fetchError;
|
22
62
|
|
23
63
|
return useMemo(() => {
|
24
64
|
return {
|
25
65
|
graph: rawGraph ? GraphModel.from(rawGraph) : undefined,
|
26
66
|
error: serverError || clientError,
|
27
|
-
loading,
|
67
|
+
loading: idsLoading || graphLoading,
|
68
|
+
idsLoading,
|
69
|
+
graphLoading,
|
28
70
|
};
|
29
|
-
}, [rawGraph,
|
71
|
+
}, [rawGraph, serverError, clientError, idsLoading, graphLoading]);
|
30
72
|
}
|