Skip to content

Commit 59e893e

Browse files
authored
Merge pull request #627 from GraphScope/chore-1204
2 parents da9cb29 + 0f9525e commit 59e893e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1632
-641
lines changed

packages/studio-explore/src/app.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ import {
3333
CurvatureLinks,
3434
DagreMode,
3535
Placeholder,
36+
LayoutSwitch,
37+
ZoomStatus,
38+
registerIcons,
3639
} from '@graphscope/studio-graph';
3740

3841
import { ToogleLeftButton, ToogleRightButton } from './components/ToggleButton';
@@ -45,7 +48,8 @@ interface ExploreProps {
4548
id?: string;
4649
services?: any;
4750
}
48-
51+
/** register graph icons */
52+
registerIcons();
4953
const Explore: React.FunctionComponent<ExploreProps> = props => {
5054
const { id } = props;
5155
const [services, setServices] = useState(props.services || getDefaultServices());
@@ -130,6 +134,8 @@ const Explore: React.FunctionComponent<ExploreProps> = props => {
130134
<Next />
131135
<PropertiesPanel />
132136

137+
<ZoomStatus />
138+
133139
<ContextMenu>
134140
<NeighborQuery />
135141
<CommonNeighbor onQuery={onQuery} />
@@ -156,6 +162,7 @@ const Explore: React.FunctionComponent<ExploreProps> = props => {
156162
<FixedMode />
157163
<CurvatureLinks />
158164
<DagreMode />
165+
<LayoutSwitch />
159166
<Divider style={{ margin: '0px' }} />
160167
<SwitchEngine />
161168
<RunCluster />

packages/studio-explore/src/components/Searchbar/index.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { useContext } from '@graphscope/studio-graph';
88
import CascaderSearch from './CascaderSearch';
99
import cssStyle from './css';
1010
import { getIconByType } from './utils';
11+
1112
const { debounce } = Utils;
1213
interface ISearchbarProps {}
1314

@@ -111,6 +112,10 @@ const Searchbar: React.FunctionComponent<ISearchbarProps> = props => {
111112
draft.data.nodes = Utils.uniqueElementsBy([...draft.data.nodes, node], (a, b) => {
112113
return a.id === b.id;
113114
});
115+
if (node) {
116+
//@ts-ignore
117+
draft.focusNodes = [node.id];
118+
}
114119
});
115120
};
116121

@@ -145,6 +150,7 @@ const Searchbar: React.FunctionComponent<ISearchbarProps> = props => {
145150
draft.source = data;
146151
draft.data = data;
147152
draft.isLoading = false;
153+
draft.focusNodes = data.nodes.map(item => item.id);
148154
});
149155
};
150156
const prefix = (
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import React, { useEffect, useState } from 'react';
2+
import Chart from '../../ChartView/index';
3+
import { useContext, IQueryStatement } from '@graphscope/studio-graph';
4+
import { Flex, Card } from 'antd';
5+
interface ILabelsProps {}
6+
7+
const Labels: React.FunctionComponent<ILabelsProps> = props => {
8+
const { store } = useContext();
9+
const { schema, getService } = store;
10+
const [state, setState] = useState({
11+
nodes: [],
12+
});
13+
const query = async () => {
14+
const { nodes } = schema;
15+
if (nodes.length === 0) {
16+
return;
17+
}
18+
const allFetch = nodes.map(item => {
19+
const { label } = item;
20+
const script = `MATCH (n:${label}) RETURN count(n) as ${label}`;
21+
return getService<IQueryStatement>('queryStatement')(script);
22+
});
23+
Promise.all(allFetch).then(res => {
24+
console.log(res);
25+
const data = res.map(item => {
26+
const { table } = item;
27+
const [name, value] = Object.entries(table[0])[0];
28+
return {
29+
name,
30+
value,
31+
};
32+
});
33+
//@ts-ignore
34+
setState(preState => {
35+
return {
36+
...preState,
37+
nodes: data,
38+
};
39+
});
40+
});
41+
};
42+
useEffect(() => {
43+
query();
44+
}, [schema]);
45+
console.log(state.nodes);
46+
47+
return (
48+
<Flex gap={12} style={{ width: '300px' }}>
49+
<Chart data={state.nodes} type="pie" xField="name" yField="value" style={{ height: 120, padding: 10 }} />
50+
</Flex>
51+
);
52+
};
53+
54+
export default Labels;

packages/studio-explore/src/components/Statistics/TotalCounts/index.tsx

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as React from 'react';
22
import { Flex, Typography, Statistic, Divider, Tooltip, Space, Button } from 'antd';
3-
import { useContext } from '@graphscope/studio-graph';
4-
3+
import { useContext, type IQueryStatement } from '@graphscope/studio-graph';
4+
import { PlayCircleOutlined } from '@ant-design/icons';
55
interface IUploadProps {
66
children?: React.ReactNode;
77
}
@@ -13,7 +13,7 @@ export interface IQueryStatistics {
1313
}>;
1414
}
1515
const TotalCounts: React.FunctionComponent<IUploadProps> = props => {
16-
const { store } = useContext();
16+
const { store, updateStore } = useContext();
1717
const { getService } = store;
1818
const { nodes, edges } = store.data;
1919
const [data, setData] = React.useState({
@@ -34,15 +34,52 @@ const TotalCounts: React.FunctionComponent<IUploadProps> = props => {
3434
initQuery();
3535
}, []);
3636

37+
const queryNodes = async () => {
38+
updateStore(draft => {
39+
draft.isLoading = true;
40+
});
41+
const res = await getService<IQueryStatement>('queryStatement')(` Match (n) return n`);
42+
updateStore(draft => {
43+
draft.data = res;
44+
draft.isLoading = false;
45+
});
46+
};
47+
const queryEdges = async () => {
48+
updateStore(draft => {
49+
draft.isLoading = true;
50+
});
51+
const res = await getService<IQueryStatement>('queryStatement')(`match (a)-[e]->(b) return a,b,e`);
52+
updateStore(draft => {
53+
draft.data = res;
54+
draft.isLoading = false;
55+
});
56+
};
57+
3758
const { total_vertex_count, total_edge_count } = data;
3859
return (
3960
<Flex vertical gap={12}>
4061
<Typography.Title level={5} style={{ margin: '0px' }}>
4162
Graph Statistics
4263
</Typography.Title>
4364
<Flex align="center" justify="start" gap={64}>
44-
<Statistic title="Vertex Count" value={`${nodes.length} / ${total_vertex_count}`} />
45-
<Statistic title="Edge Count" value={`${edges.length} / ${total_edge_count}`} />
65+
<Statistic
66+
title="Total Vertices"
67+
value={total_vertex_count}
68+
suffix={
69+
<Tooltip title="Query all vertices">
70+
<Button type="text" onClick={queryNodes} icon={<PlayCircleOutlined />}></Button>
71+
</Tooltip>
72+
}
73+
/>
74+
<Statistic
75+
title="Total Edges"
76+
value={`${total_edge_count}`}
77+
suffix={
78+
<Tooltip title="Query all edges">
79+
<Button type="text" onClick={queryEdges} icon={<PlayCircleOutlined />}></Button>
80+
</Tooltip>
81+
}
82+
/>
4683
</Flex>
4784
</Flex>
4885
);

packages/studio-explore/src/components/Statistics/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as React from 'react';
22
import { Flex, Divider } from 'antd';
33
import Properties from './Properties';
44
import TotalCounts from './TotalCounts';
5-
5+
// import Labels from './Lables';
66
interface IUploadProps {
77
children?: React.ReactNode;
88
}
1.43 MB
Loading
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
---
2+
order: 5
3+
title: 布局相关
4+
---
5+
6+
`@graphscope/studio-graph`的设计中,布局数据是由 `store.layout` 驱动的
7+
8+
| key | desc | default |
9+
| ------- | -------------- | ------- |
10+
| type | 布局类型 | force |
11+
| options | 布局的具体参数 | {} |
12+
13+
## 01. 力导布局 `force`
14+
15+
```jsx
16+
import React, { useEffect } from 'react';
17+
import { Canvas, GraphProvider, Prepare, useContext } from '@graphscope/studio-graph';
18+
import { schema } from './const';
19+
const CustomGraphFetch = () => {
20+
const { store, updateStore } = useContext();
21+
useEffect(() => {
22+
fetch('https://assets.antv.antgroup.com/g6/radial.json')
23+
.then(res => res.json())
24+
.then(res => {
25+
return {
26+
nodes: res.nodes.map(item => {
27+
return {
28+
id: item.id,
29+
properties: item,
30+
};
31+
}),
32+
edges: res.edges.map((item, index) => {
33+
return {
34+
id: String(index),
35+
source: item.source,
36+
target: item.target,
37+
properties: {},
38+
};
39+
}),
40+
};
41+
})
42+
.then(data => {
43+
updateStore(draft => {
44+
draft.data = data;
45+
draft.schema = schema;
46+
draft.source = data;
47+
//默认的layout就是这个,所以可以不用设置
48+
draft.layout = {
49+
type: 'force',
50+
options: {},
51+
};
52+
});
53+
});
54+
}, []);
55+
return null;
56+
};
57+
export default () => {
58+
return (
59+
<div style={{ height: '300px' }}>
60+
<GraphProvider id={String(Math.random())}>
61+
<CustomGraphFetch />
62+
<Canvas />
63+
</GraphProvider>
64+
</div>
65+
);
66+
};
67+
```
68+
69+
## 02. 层次布局 `dagre`
70+
71+
```jsx
72+
import React, { useEffect } from 'react';
73+
import { Canvas, GraphProvider, Prepare, useContext } from '@graphscope/studio-graph';
74+
import { data, schema } from './const';
75+
const CustomGraphFetch = () => {
76+
const { store, updateStore } = useContext();
77+
useEffect(() => {
78+
fetch('https://assets.antv.antgroup.com/g6/radial.json')
79+
.then(res => res.json())
80+
.then(res => {
81+
return {
82+
nodes: res.nodes.map(item => {
83+
return {
84+
id: item.id,
85+
properties: item,
86+
};
87+
}),
88+
edges: res.edges.map((item, index) => {
89+
return {
90+
id: String(index),
91+
source: item.source,
92+
target: item.target,
93+
properties: {},
94+
};
95+
}),
96+
};
97+
})
98+
.then(data => {
99+
updateStore(draft => {
100+
draft.data = data;
101+
draft.schema = schema;
102+
draft.source = data;
103+
//默认的layout就是这个,所以可以不用设置
104+
draft.layout = {
105+
type: 'dagre',
106+
options: {},
107+
};
108+
});
109+
});
110+
}, []);
111+
return null;
112+
};
113+
export default () => {
114+
return (
115+
<div style={{ height: '400px' }}>
116+
<GraphProvider id={String(Math.random())}>
117+
<CustomGraphFetch />
118+
<Canvas />
119+
</GraphProvider>
120+
</div>
121+
);
122+
};
123+
```
124+
125+
## 03. 预设布局 `preset`
126+
127+
```jsx
128+
import React, { useEffect } from 'react';
129+
import { Canvas, GraphProvider, Prepare, useContext, Loading } from '@graphscope/studio-graph';
130+
import { schema } from './const';
131+
const CustomGraphFetch = () => {
132+
const { store, updateStore } = useContext();
133+
useEffect(() => {
134+
(async () => {
135+
updateStore(draft => {
136+
draft.isLoading = true;
137+
});
138+
const { nodes, edges } = await fetch('https://assets.antv.antgroup.com/g6/20000.json').then(res => res.json());
139+
const data = {
140+
nodes: nodes.map(item => ({ id: item.id, properties: item.data })),
141+
edges: edges.map((item, index) => ({
142+
id: `${item.source}-${item.target}-${index}`,
143+
source: item.source,
144+
target: item.target,
145+
properties: item.data,
146+
})),
147+
};
148+
updateStore(draft => {
149+
draft.data = data;
150+
draft.isLoading = false;
151+
draft.layout = {
152+
type: 'preset',
153+
options: {},
154+
};
155+
});
156+
})();
157+
}, []);
158+
return null;
159+
};
160+
export default () => {
161+
return (
162+
<div style={{ height: '600px' }}>
163+
<GraphProvider id={String(Math.random())}>
164+
<CustomGraphFetch />
165+
<Canvas />
166+
<Loading />
167+
</GraphProvider>
168+
</div>
169+
);
170+
};
171+
```
172+
173+
## 04. Combo布局 `force-combo`

packages/studio-graph/docs/online.zh-CN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
order: 3
2+
order: 5
33
title: 综合应用
44
---
55

packages/studio-graph/docs/performance-1.zh-CN.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
group:
3+
order: 5
34
title: 性能测试
45
order: 3
56
title: Sigmajs-Dataset-G(2085,5409)

0 commit comments

Comments
 (0)