Skip to content

Commit

Permalink
feat: add export to png & fix bugs
Browse files Browse the repository at this point in the history
fix: fix version

fix: code review

mod: add template file
  • Loading branch information
hetao92 committed Mar 23, 2022
1 parent c8665bc commit a8eff23
Show file tree
Hide file tree
Showing 30 changed files with 531 additions and 279 deletions.
23 changes: 15 additions & 8 deletions app/config/locale/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
"confirm": "Confirm",
"import": "Import",
"ask": "Are you sure to proceed?",
"output": "Export CSV File",
"openInExplore": "Open In Explorer",
"schema": "Schema",
"create": "Create",
Expand Down Expand Up @@ -77,14 +76,15 @@
"username": "Username",
"password": "Password",
"success": "succeed",
"clear": "Clear Connection",
"clear": "Log out",
"title": "Connect to Nebula Graph"
},
"formRules": {
"hostRequired": "Host Required",
"usernameRequired": "Username Required",
"passwordRequired": "Password Required",
"positiveIntegerRequired": "Please enter a non-negative integer",
"nameValidate": "The name must start with a letter, and it only supports English letters, numbers and underscores",
"nameRequired": "Please enter the name",
"numberRequired": "Please enter a positive integer",
"replicaLimit": "Replica factor must not exceed the number of your current online machines({number})",
Expand Down Expand Up @@ -154,10 +154,15 @@
"addTag": "Add Tag",
"config": "Task Config",
"parseFailed": "File parsing failed",
"uploadTemplate": "Click or drag the yaml configuration file to this area to upload",
"uploadTemplateTip": "Please keep only the file name (retain the file extension) for all file paths in the template, such as logPath: config.csv",
"fileUploadRequired": "Make sure all csv data files are uploaded before uploading the configuration",
"reUpload": "Re-upload"
"uploadTemplate": "Drag & drop the YAML configuration file to this area",
"uploadBoxTip": "The YAML configuration file is used to describe information about the files to be imported, the Nebula Graph server, and more. ",
"fileUploadRequired": "1. Please make sure all CSV data files are uploaded before import the YAML file. If not, please go to ",
"fileUploadRequired2": " first.",
"exampleDownload": "2. An example for the configuration file: ",
"uploadTemplateTip": "3. 3. Configure the Yaml file: please keep only the file name (retain the file extension) for all file paths (path, failDataPath, logPath) in the template, e.g. logPath: config.csv",
"reUpload": "Re-upload",
"fileNotExist": "{name} file does not exist!",
"importYaml": "Import the YAML file"
},
"schema": {
"spaceList": "Graph Space List",
Expand Down Expand Up @@ -215,11 +220,13 @@
"deleteSpace": "Delete Graph Space",
"cloneSpace": "Clone Graph Space",
"length": "Length",
"selectVidTypeTip": "Please select the type"
"selectVidTypeTip": "Please select the type",
"csvDownload": "Export CSV File",
"pngDownload": "Export PNG File"
},
"menu": {
"use": "Use Manual",
"release": "New Version",
"release": "Release Note",
"forum": "Help Forum",
"nGql": "nGQL"
},
Expand Down
23 changes: 15 additions & 8 deletions app/config/locale/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
"confirm": "确认",
"import": "导入",
"ask": "确定进行当前操作?",
"output":"导出CSV文件",
"openInExplore": "导入图探索",
"schema": "Schema",
"create": "创建",
Expand Down Expand Up @@ -77,14 +76,15 @@
"username": "用户名",
"password": "密码",
"success": "配置成功",
"clear": "清除连接",
"clear": "登出",
"title": "配置数据库"
},
"formRules": {
"hostRequired": "请填写数据库服务器的IP地址",
"usernameRequired": "请填写用户名",
"passwordRequired": "请填写密码",
"positiveIntegerRequired": "请输入一个非负整数",
"nameValidate": "命名必须以字母开头,且只支持输入英文字母、数字以及下划线_",
"nameRequired": "请输入名称",
"numberRequired": "请输入正整数",
"replicaLimit": "副本数量不得超过你当前 online 机器数量({number})",
Expand Down Expand Up @@ -154,10 +154,15 @@
"addTag": "添加 Tag",
"config": "任务配置",
"parseFailed": "文件解析失败",
"uploadTemplate": "点击或拖动yaml配置文件到该区域上传",
"uploadTemplateTip": "模板中所有文件路径请仅保留文件名(保留文件扩展名),比如 logPath: config.csv",
"fileUploadRequired": "上传配置前请确保所有 csv 数据文件已上传",
"reUpload": "重新上传"
"uploadTemplate": "将 YAML 配置文件拖放到该区域",
"uploadBoxTip": "The YAML configuration file is used to describe information about the files to be imported, the Nebula Graph server, and more. ",
"fileUploadRequired": "1. 请确保在导入 YAML 文件之前上传所有 CSV 数据文件。 如果没有,请先前往",
"fileUploadRequired2": "数据文件",
"exampleDownload": "2. 配置文件示例:",
"uploadTemplateTip": "3.配置Yaml文件:模板中所有文件路径(path、failDataPath、logPath)请只保留文件名(保留文件扩展名),例如: 日志路径:config.csv",
"reUpload": "重新上传",
"fileNotExist": "文件 {name} 不存在",
"importYaml": "导入 YAML 文件"
},
"schema": {
"spaceList": "图空间列表",
Expand Down Expand Up @@ -215,11 +220,13 @@
"deleteSpace": "删除图空间",
"cloneSpace": "克隆图空间",
"length": "长度",
"selectVidTypeTip": "选择 Vid 类型"
"selectVidTypeTip": "选择 Vid 类型",
"csvDownload": "导出 CSV",
"pngDownload": " 导出 PNG"
},
"menu": {
"use": "使用手册",
"release": "新发布",
"release": "更新日志",
"forum": "求助论坛",
"nGql": "nGQL"
},
Expand Down
30 changes: 23 additions & 7 deletions app/config/rules.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { POSITIVE_INTEGER_REGEX } from '@app/utils/constant';
import { NAME_REGEX, POSITIVE_INTEGER_REGEX } from '@app/utils/constant';
import intl from 'react-intl-universal';

export const hostRulesFn = () => [
Expand All @@ -22,12 +22,28 @@ export const passwordRulesFn = () => [
},
];

export const nameRulesFn = () => [
{
required: true,
message: intl.get('formRules.nameRequired'),
},
];
export const nameRulesFn = () => {
const version = sessionStorage.getItem('nebulaVersion');
if(version?.startsWith('v2')) {
return [
{
required: true,
message: intl.get('formRules.nameRequired'),
},
{
pattern: NAME_REGEX,
message: intl.get('formRules.nameValidate'),
},
];
} else {
return [
{
required: true,
message: intl.get('formRules.nameRequired'),
},
];
}
};

export const numberRulesFn = () => [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@import '~@app/common.less';

.display-panel {
.output-display-panel {
position: absolute;
top: 0;
right: 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const DisplayPanel = (props: IProps) => {
const [visible, setVisible] = useState(false);
const { data, spaceVidType } = props;
return (
<div className="display-panel">
<div className="output-display-panel">
<div className="btn-toggle-panel" onClick={() => setVisible(!visible)}>
<Icon type="icon-studio-btn-back" />
</div>
Expand Down
5 changes: 4 additions & 1 deletion app/pages/Console/OutputBox/ForceGraph/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import React, { useEffect, useRef, useState } from 'react';
import { parseSubGraph } from '@app/utils/parseData';
import { v4 as uuidv4 } from 'uuid';
import { useStore } from '@app/stores';
import { GraphStore } from '@app/stores/graph';
import { initTooltip } from './Tootip';
import DisplayPanel from './DisplayPanel';
import OperationPanel from './OperationPanel';
Expand All @@ -14,12 +15,13 @@ import './index.less';
interface IProps {
data: any;
spaceVidType: string;
onGraphInit: (graph: GraphStore) => void;
}
const ForceGraphBox = (props: IProps) => {
const [uuid ] = useState(uuidv4());
const { graphInstances: { graphs, initGraph, clearGraph } } = useStore();
const grapfDomRef = useRef<any>();
const { data, spaceVidType } = props;
const { data, spaceVidType, onGraphInit } = props;
const [loading, setLoading] = useState(false);
const init = async () => {
const { vertexes, edges } = parseSubGraph(data, spaceVidType);
Expand All @@ -29,6 +31,7 @@ const ForceGraphBox = (props: IProps) => {
id: uuid,
data: { vertexes, edges }
});
onGraphInit(graphs[uuid]);
initTooltip({ container: grapfDomRef.current, id: uuid });
initBrushSelect({ container: grapfDomRef.current, id: uuid });
setLoading(false);
Expand Down
23 changes: 23 additions & 0 deletions app/pages/Console/OutputBox/index.less
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@import '~@app/common.less';
.output-box {
overflow: hidden;
max-height: 850px;
background: #fff;
position: relative;
display: flex;
Expand Down Expand Up @@ -49,6 +50,9 @@
span.btn-yellow svg{
fill: #F2C94C;
}
.btn-export {
cursor: pointer;
}
}
}

Expand Down Expand Up @@ -126,3 +130,22 @@
letter-spacing: 1.48px;
}
}

.export-popover {
.ant-popover-inner-content {
padding: 0;
border-radius: 3px;
}
.download-item {
padding: 10px 20px;
display: flex;
align-items: center;
justify-content: center;
color: black;
font-weight: 400;
font-size: 12px;
&[disabled] {
color: rgba(0, 0, 0, 0.25);
}
}
}
55 changes: 46 additions & 9 deletions app/pages/Console/OutputBox/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Button, Table, Tabs, Tooltip } from 'antd';
import { Button, Table, Tabs, Tooltip, Popover } from 'antd';
import { BigNumber } from 'bignumber.js';
import React, { useCallback, useEffect, useState } from 'react';
import intl from 'react-intl-universal';
Expand All @@ -9,6 +9,7 @@ import { v4 as uuidv4 } from 'uuid';
import Icon from '@app/components/Icon';
import { parseSubGraph } from '@app/utils/parseData';
import classNames from 'classnames';
import { GraphStore } from '@app/stores/graph';
import Graphviz from './Graphviz';
import ForceGraph from './ForceGraph';

Expand Down Expand Up @@ -38,6 +39,8 @@ const OutputBox = (props: IProps) => {
const [dataSource, setDataSource] = useState<any>([]);
const [isFavorited, setIsFavorited] = useState(false);
const [showGraph, setShowGraph] = useState(false);
const [graph, setGraph] = useState<GraphStore | null>(null);
const [tab, setTab] = useState('');
const initData = () => {
let _columns = [] as any;
let _dataSource = [] as any;
Expand Down Expand Up @@ -110,6 +113,7 @@ const OutputBox = (props: IProps) => {
}, []);

const handleTabChange = useCallback(key => {
setTab(key);
trackEvent('console', `change_tab_${key}`);
}, []);

Expand Down Expand Up @@ -145,7 +149,7 @@ const OutputBox = (props: IProps) => {
});
};

const downloadData = () => {
const downloadCsv = () => {
if (!data) {
return ;
}
Expand Down Expand Up @@ -178,6 +182,31 @@ const OutputBox = (props: IProps) => {
link.click();
};

const downloadPng = () => {
if(graph) {
let canvas = graph.twoGraph.canvas;
const shadowCanvas = document.createElement('canvas');
shadowCanvas.width = canvas.width;
shadowCanvas.height = canvas.height;
const ctx = shadowCanvas.getContext('2d');
ctx.fillStyle = '#F3F6F9';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(canvas, 0, 0);
canvas = shadowCanvas;
setTimeout(() => {
canvas.toBlob(blob => {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = canvas.toDataURL('image/png');
a.download = 'Image.png';
a.click();
window.URL.revokeObjectURL(url);
});
}, 0);
}
trackEvent('console', 'export_graph_png');
};

const handleExplore = () => {
if (
data.tables.filter(
Expand Down Expand Up @@ -220,12 +249,20 @@ const OutputBox = (props: IProps) => {
onClick={removeFavorite}
/>
</Tooltip>}
<Tooltip title={intl.get('common.output')} placement="top">
<Icon
type="icon-studio-btn-output"
onClick={downloadData}
/>
</Tooltip>
<Popover
overlayClassName="export-popover"
placement="bottom"
content={<>
<Button type="link" className="download-item" onClick={downloadCsv}>
{intl.get('schema.csvDownload')}
</Button>
<Button disabled={!graph || tab !== 'graph'} type="link" className="download-item" onClick={downloadPng}>
{intl.get('schema.pngDownload')}
</Button>
</>}
>
<Icon className="btn-export" type="icon-studio-btn-output" />
</Popover>
{visible ? <Icon
type="icon-studio-btn-up"
onClick={() => setVisible(false)}
Expand Down Expand Up @@ -293,7 +330,7 @@ const OutputBox = (props: IProps) => {
}
key="graph"
>
<ForceGraph data={dataSource} spaceVidType={spaceVidType} />
<ForceGraph data={dataSource} spaceVidType={spaceVidType} onGraphInit={setGraph} />
</Tabs.TabPane>
)}
{code !== 0 && (
Expand Down
1 change: 1 addition & 0 deletions app/pages/Console/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
border: 1px solid @gray;
border-top: none;
cursor: pointer;
opacity: 0.7;
svg {
fill: @darkBlue;
}
Expand Down
4 changes: 2 additions & 2 deletions app/pages/Console/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const Console = (props: IProps) => {
const { onExplorer } = props;
const { spaces, getSpaces, switchSpace, currentSpace } = schema;
const { runGQL, currentGQL, results, runGQLLoading, getParams, update, paramsMap } = console;
const { username, host } = global;
const { username, host, nebulaVersion } = global;
const [isUpDown, setUpDown] = useState(false);
const [modalVisible, setModalVisible] = useState(false);
const [modalData, setModalData] = useState<any>(null);
Expand Down Expand Up @@ -154,7 +154,7 @@ const Console = (props: IProps) => {
</div>
</div>
<div className="code-input">
<CypherParameterBox onSelect={addParam} data={paramsMap} />
{nebulaVersion?.startsWith('v3') && <CypherParameterBox onSelect={addParam} data={paramsMap} />}
<CodeMirror
value={currentGQL}
onBlur={value => update({ currentGQL: value })}
Expand Down
2 changes: 1 addition & 1 deletion app/pages/Doc/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const MODULES = [
icon: 'icon-studio-nav-import',
title: 'import.importData',
tip: 'doc.importIntro',
link: '/import'
link: '/import/files'
},
{
icon: 'icon-studio-nav-console',
Expand Down
Loading

0 comments on commit a8eff23

Please sign in to comment.