Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: init schema & space create page #115

Merged
merged 2 commits into from
Feb 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
});
Comment on lines +68 to +70
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const list = [...keyWords, ...operators, ...ban].filter(item => item.startsWith(str));


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());
}
};
Comment on lines +112 to +116
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's more elegant to use optional chaining instead of a && a.b && a.b()

blur = instance => 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