Skip to content

Commit

Permalink
feat: init schema & space create page (vesoft-inc#115)
Browse files Browse the repository at this point in the history
  • Loading branch information
hetao92 committed Mar 31, 2022
1 parent 2c1637b commit 506a91b
Show file tree
Hide file tree
Showing 33 changed files with 849 additions and 109 deletions.
15 changes: 8 additions & 7 deletions app-v2/common.less
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
@grayDark: #36383D;
@dark: rgba(0,0,0,.9);
@disableGray: rgba(255, 255, 255, 0.3);
@promptGray: #8C8C8C;
@blue: #0091ff;
@errorRed: #E02020;
@disableBlue: #375d7a;
@gray: #D5DDEB;
@lightGray: #F8F8F8;
@containerWidth: 1180px;

@font-face {
font-family: 'Roboto-Black';
Expand All @@ -30,3 +26,8 @@
font-family: 'Roboto-Regular';
src: url(~@appv2/static/fonts/Roboto-Regular.ttf);
}

.center-layout {
width: @containerWidth;
margin: 0 auto;
}
3 changes: 2 additions & 1 deletion app-v2/components/Breadcrumb/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
font-size: 18px;
align-items: center;
display: flex;
padding-left: 40px;
padding-left: 0;
padding-right: 0;
.arrow-icon {
width: 23px;
height: 23px;
Expand Down
22 changes: 15 additions & 7 deletions app-v2/components/Breadcrumb/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PageHeader } from 'antd';
import { Breadcrumb, PageHeader } from 'antd';
import React from 'react';
import { Link } from 'react-router-dom';

Expand All @@ -9,7 +9,7 @@ interface IProps {
path: string;
breadcrumbName: string;
}[];
ExtraNode?: JSX.Element;
extraNode?: JSX.Element;
}

const itemRender = (route, _params, routes, _paths) => {
Expand All @@ -31,16 +31,24 @@ const itemRender = (route, _params, routes, _paths) => {
);
};

const Breadcrumb: React.FC<IProps> = (props: IProps) => {
const { routes, ExtraNode } = props;
const NebulaBreadcrumb: React.FC<IProps> = (props: IProps) => {
const { routes, extraNode } = props;
return (
<PageHeader
title={null}
className="nebula-breadcrumb"
breadcrumb={{ routes, itemRender }}
extra={ExtraNode}
breadcrumbRender={() => {
return <>
<Breadcrumb
className="center-layout"
routes={routes}
itemRender={itemRender}
/>
{extraNode}
</>;
}}
/>
);
};

export default Breadcrumb;
export default NebulaBreadcrumb;
9 changes: 9 additions & 0 deletions app-v2/components/CodeMirror/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.CodeMirror-wrap pre.CodeMirror-line,
.CodeMirror-wrap pre.CodeMirror-line-like {
word-break: break-all !important;
}

.CodeMirror {
resize: vertical;
overflow: auto !important;
}
195 changes: 195 additions & 0 deletions app-v2/components/CodeMirror/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
import CodeMirror from 'codemirror';
import 'codemirror/addon/comment/comment';
import 'codemirror/addon/display/autorefresh';
import 'codemirror/addon/edit/matchbrackets';
import 'codemirror/addon/hint/show-hint';
import 'codemirror/addon/hint/show-hint.css';
import 'codemirror/keymap/sublime';
import 'codemirror/lib/codemirror.css';
import 'codemirror/mode/meta';
import 'codemirror/theme/monokai.css';
import React from 'react';

import { ban, keyWords, maxLineNum, operators } from '@appv2/config/nebulaQL';

import './index.less';

interface IProps {
options?: object;
value: string;
ref?: any;
width?: string;
height?: string;
onShiftEnter?: () => void;
onChange?: (value: string) => void;
onBlur?: (value: string) => void;
onChangeLine?: () => void;
}

export default class ReactCodeMirror extends React.PureComponent<IProps, any> {
codemirror;
editor;
textarea;
constructor(props) {
super(props);
}
public componentDidMount() {
CodeMirror.defineMode('nebula', () => {
return {
token: stream => {
if (stream.eatSpace()) {
return null;
}
stream.eatWhile(/[\$:\w\u4e00-\u9fa5]/);
const cur = stream.current();
if (keyWords.some(item => item === cur)) {
return 'keyword';
} else if (operators.some(item => item === cur)) {
return 'def';
} else if (ban.some(item => item === cur)) {
return 'error';
}
stream.next();
},
};
});

CodeMirror.registerHelper('hint', 'nebula', cm => {
const cur = cm.getCursor();
const token = cm.getTokenAt(cur);
const str = token.string;
const start = token.start;
const end = cur.ch;

if (str === '') {
return;
}

const list = [...keyWords, ...operators, ...ban].filter(item => {
return item.indexOf(str) === 0;
});

if (list.length) {
return {
list,
from: CodeMirror.Pos(cur.line, start),
to: CodeMirror.Pos(cur.line, end),
};
}
});
this.renderCodeMirror();
}
renderCodeMirror() {
// parameters of the combined
const options = {
tabSize: 2,
fontSize: '14px',
autoCloseBrackets: true,
matchBrackets: true,
showCursorWhenSelecting: true,
lineWrapping: true,
// show number of rows
lineNumbers: true,
fullScreen: true,
mode: 'nebula',
...this.props.options,
};
this.editor = CodeMirror.fromTextArea(this.textarea, options);
// Getting CodeMirror is used to get some of these constants
this.codemirror = CodeMirror;
// event
this.editor.on('change', this.codemirrorValueChange);
this.editor.on('keydown', this.keydown);
this.editor.on('blur', this.blur);
const { value, width, height } = this.props;
this.editor.setValue(value || '');
if (width || height) {
// set size
this.editor.setSize(width, height);
}
}

blur = instance => {
if (this.props.onBlur) {
this.props.onBlur(instance.doc.getValue());
}
};

keydown = (_, change) => {
if (change.shiftKey === true && change.keyCode === 13) {
if (this.props.onShiftEnter) {
this.props.onShiftEnter();
}
change.preventDefault();
}
};

codemirrorValueChange = (doc, change) => {
if (change.origin !== 'setValue') {
if (this.props.onChange) {
this.props.onChange(doc.getValue());
}
}
if (change.origin === '+input') {
CodeMirror.commands.autocomplete(this.editor, null, {
completeSingle: false,
});
}
if (
this.props.onChangeLine &&
(change.origin === '+delete' || change.origin === '+input')
) {
this.props.onChangeLine();
}
};

async UNSAFE_componentWillReceiveProps(nextProps) {
const { options, value } = nextProps;
await this.setOptions(options);
if (value !== this.editor.getValue()) {
this.editor.setValue(value || '');
let line;
if (this.editor.lineCount() > maxLineNum) {
line = maxLineNum;
} else if (this.editor.lineCount() < 5) {
line = 5;
} else {
line = this.editor.lineCount();
}
this.editor.setSize(undefined, line * 24 + 10 + 'px');
}
}

async setOptions(options) {
if (typeof options === 'object') {
const mode = CodeMirror.findModeByName(options.mode);
if (mode && mode.mode) {
await import(`codemirror/mode/${mode.mode}/${mode.mode}.js`);
}
if (mode) {
options.mode = mode.mime;
}
Object.keys(options).forEach(name => {
if (options[name] && JSON.stringify(options[name])) {
this.editor.setOption(name, options[name]);
}
});
}
}

componentWillUnmount() {
if (this.editor) {
this.editor.toTextArea();
}
}

render() {
return (
<textarea
ref={instance => {
this.textarea = instance;
}}
/>
);
}
}
16 changes: 16 additions & 0 deletions app-v2/components/GQLCodeMirror/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
@import '~@appv2/common.less';
.export-gql {
text-align: left;
margin-top: 24px;
background: #FFFFFF;
border: 1px solid @gray;
.ant-collapse-item {
border-bottom: none;
}
box-sizing: border-box;
border-radius: 3px;
}

.export-gql .ant-collapse-content-box div {
cursor: not-allowed;
}
29 changes: 29 additions & 0 deletions app-v2/components/GQLCodeMirror/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Collapse } from 'antd';
import React from 'react';
import intl from 'react-intl-universal';

import CodeMirror from '@appv2/components/CodeMirror';

import './index.less';
const Panel = Collapse.Panel;
interface IOptions {
[propName: string]: any;
}
const GQLCodeMirror = (props: { currentGQL: string; option?: IOptions }) => {
const options = {
keyMap: 'sublime',
fullScreen: true,
mode: 'nebula',
readOnly: true,
...props.option,
};
return (
<Collapse className="export-gql">
<Panel header={intl.get('common.exportNGQL')} key="ngql">
<CodeMirror value={props.currentGQL} options={options} height="80px" />
</Panel>
</Collapse>
);
};

export default GQLCodeMirror;
19 changes: 18 additions & 1 deletion app-v2/config/locale/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"name": "Name",
"operation": "Operations",
"delete": "Delete",
"optionalParameters": "Optional Parameters",
"optional": "Optional",
"exportNGQL": "View nGQL",
"field": "Field",
"relatedProperties": "Related Properties",
Expand Down Expand Up @@ -368,5 +368,22 @@
"mannualHref": "https://docs.nebula-graph.io/3.0.0/nebula-studio/about-studio/st-ug-what-is-graph-studio/",
"versionLogHref": "https://docs.nebula-graph.io/3.0.0/nebula-studio/about-studio/st-ug-release-note/",
"forumLink": "https://discuss.nebula-graph.io/"
},
"_schema": {
"spaceList": "Graph Space List",
"createSpace": "Create Space",
"No": "No",
"spaceName": "Name",
"partitionNumber": "Partition Number",
"replicaFactor": "Replica Factor",
"charset": "Charset",
"collate": "Collate",
"vidType": "Vid Type",
"atomicEdge": "Atomic Edge",
"group": "Group",
"comment": "Comment",
"operations": "Operations",
"useSpaceErrTip": "Space not found. Trying to use a newly created graph space may fail because the creation is implemented asynchronously. To make sure the follow-up operations work as expected, Wait for two heartbeat cycles, i.e., 20 seconds.",
"spaceNameEnter": "Please enter the space name"
}
}
19 changes: 18 additions & 1 deletion app-v2/config/locale/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"name": "名称",
"operation": "操作",
"delete": "删除",
"optionalParameters": "可选参数",
"optional": "可选",
"exportNGQL": "对应的nGQL语句",
"field": "字段",
"relatedProperties": "相关属性",
Expand Down Expand Up @@ -364,5 +364,22 @@
"mannualHref": "https://docs.nebula-graph.com.cn/3.0.0/nebula-studio/about-studio/st-ug-what-is-graph-studio/",
"versionLogHref": "https://docs.nebula-graph.com.cn/3.0.0/nebula-studio/about-studio/st-ug-release-note/",
"forumLink": "https://discuss.nebula-graph.com.cn/"
},
"_schema": {
"spaceList": "图空间列表",
"createSpace": "创建图空间",
"No": "序号",
"spaceName": "名称",
"partitionNumber": "Partition Number",
"replicaFactor": "Replica Factor",
"charset": "Charset",
"collate": "Collate",
"vidType": "Vid Type",
"atomicEdge": "Atomic Edge",
"group": "Group",
"comment": "Comment",
"operations": "操作",
"useSpaceErrTip": "图空间未找到。立刻尝试使用刚创建的图空间可能会失败,因为创建是异步实现的。为确保数据同步,后续操作能顺利进行,请等待 2 个心跳周期(20 秒)。",
"spaceNameEnter": "请输入图空间名称"
}
}
Loading

0 comments on commit 506a91b

Please sign in to comment.