Skip to content
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
1 change: 1 addition & 0 deletions hugegraph-dist/release-docs/LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ See licenses/ for text of these licenses.
hugegraph-hubble/ui/favicon.ico
(Apache License, Version 2.0) * kotlin-stdlib (org.jetbrains.kotlin:kotlin-stdlib:1.6.20 - https://github.com/JetBrains/kotlin)
(Apache License, Version 2.0) * kotlin-stdlib-common (org.jetbrains.kotlin:kotlin-stdlib-common:1.5.31 - https://github.com/JetBrains/kotlin)
(Apache License, Version 2.0) * kotlin-stdlib-common (org.jetbrains.kotlin:kotlin-stdlib-common:1.6.20 - https://github.com/JetBrains/kotlin)
(Apache License, Version 2.0) * kotlin-stdlib-jdk7 (org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.71 - https://github.com/JetBrains/kotlin)
(Apache License, Version 2.0) * kotlin-stdlib-jdk7 (org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.10 - https://github.com/JetBrains/kotlin)
(Apache License, Version 2.0) * kotlin-stdlib-jdk8 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.71 - https://github.com/JetBrains/kotlin)
Expand Down
1 change: 1 addition & 0 deletions hugegraph-dist/scripts/dependency/known-dependencies.txt
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ kerby-xdr-1.0.1.jar
kerby-xdr-2.0.0.jar
kotlin-stdlib-1.6.20.jar
kotlin-stdlib-common-1.5.31.jar
kotlin-stdlib-common-1.6.20.jar
Comment thread
imbajin marked this conversation as resolved.
kotlin-stdlib-jdk7-1.2.71.jar
kotlin-stdlib-jdk7-1.6.10.jar
kotlin-stdlib-jdk8-1.2.71.jar
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import {Input} from 'antd';
import {useTranslation} from 'react-i18next';

import {isValidFavoriteName} from '../../utils/rules';

const FavoriteNameInput = props => {
const {t} = useTranslation();
const {value, ...inputProps} = props;
const invalid = value && !isValidFavoriteName(value);

return (
<>
<Input
{...inputProps}
value={value}
showCount
maxLength={48}
status={invalid ? 'error' : undefined}
/>
{invalid && (
<div role='alert' style={{color: '#ff4d4f', fontSize: '12px'}}>
{t('common.validation.favorite_name_rule')}
</div>
)}
</>
);
};

export default FavoriteNameInput;
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import {fireEvent, render, screen} from '@testing-library/react';
import {useCallback, useState} from 'react';

import FavoriteNameInput from './index';

jest.mock('react-i18next', () => ({
initReactI18next: {type: '3rdParty', init: jest.fn()},
useTranslation: () => ({t: key => key}),
}));

test('explains invalid favorite names and clears the error for valid names', () => {
const FavoriteNameEditor = () => {
const [name, setName] = useState('');
const onChange = useCallback(e => setName(e.target.value), []);
return <FavoriteNameInput value={name} onChange={onChange} />;
};
render(<FavoriteNameEditor />);

const input = screen.getByRole('textbox');
fireEvent.change(input, {target: {value: 'query-name'}});
expect(screen.getByRole('alert')).toHaveTextContent(
'common.validation.favorite_name_rule'
);

fireEvent.change(input, {target: {value: 'query_name'}});
expect(screen.queryByRole('alert')).not.toBeInTheDocument();
});
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"normal_name_rule": "Use Chinese characters, letters, numbers, or underscores only, up to 20 characters",
"jdbc_rule": "Enter a valid JDBC URL, for example: jdbc:mysql://127.0.0.1:3306/db_name",
"account_name_rule": "Account name must be within 16 characters and cannot start or end with an underscore",
"favorite_name_rule": "Use Chinese characters, letters, numbers, or underscores only, up to 48 characters",
"invalid_data_format": "Invalid data format"
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"normal_name_rule": "只能包含中文、字母、数字、_, 不能超过20个字符",
"jdbc_rule": "请输入正确的jdbc url, 例如:jdbc:mysql://127.0.0.1:3306/db_name",
"account_name_rule": "账号名不超过16个字符,且不能以下划线开始和结尾",
"favorite_name_rule": "只能包含中文、字母、数字、_, 不能超过48个字符",
"invalid_data_format": "非法的数据格式"
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@

import React, {useState, useCallback} from 'react';
import {useTranslation} from 'react-i18next';
import {Button, Table, Space, Tag, Input, Popconfirm} from 'antd';
import {Button, Table, Space, Tag, Popconfirm} from 'antd';
import ExecutionContent from '../../../../components/ExecutionContent';
import FavoriteNameInput from '../../../../components/FavoriteNameInput';
import {isValidFavoriteName} from '../../../../utils/rules';
import c from './index.module.scss';

const EXECUTE_TYPE_KEY = {
Expand Down Expand Up @@ -67,17 +69,14 @@ const ExecuteLog = props => {
} = props;

const [favoriteName, setFavoriteName] = useState();
const [disabledFavorite, setDisabledFavorite] = useState(true);

const onFavoraiteName = useCallback(
e => {
setFavoriteName(e.target.value);
e.target.value ? setDisabledFavorite(false) : setDisabledFavorite(true);
}, []);

const onFavoriteCard = useCallback(() => {
setFavoriteName('');
setDisabledFavorite(true);
}, []);

const updateAddCollection = useCallback(
Expand All @@ -97,11 +96,9 @@ const ExecuteLog = props => {
<div style={{marginBottom: '16px'}}>
{t('analysis.logs.favorite_statement')}
</div>
<Input
<FavoriteNameInput
style={{marginBottom: '18px'}}
placeholder={t('analysis.logs.favorite_name_placeholder')}
showCount
maxLength={48}
value={favoriteName}
onChange={onFavoraiteName}
/>
Expand Down Expand Up @@ -169,7 +166,7 @@ const ExecuteLog = props => {
placement="left"
title={favoriteContent(rowData)}
onConfirm={createValueHandler(onAddFavorite, rowData.content)}
okButtonProps={{disabled: disabledFavorite}}
okButtonProps={{disabled: !isValidFavoriteName(favoriteName)}}
okText={t('analysis.logs.action.favorite')}
cancelText={t('common.action.cancel')}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import {useTranslation} from 'react-i18next';
import Highlighter from 'react-highlight-words';
import {Button, Table, Input, Popconfirm, Modal} from 'antd';
import ExecutionContent from '../../../../components/ExecutionContent';
import FavoriteNameInput from '../../../../components/FavoriteNameInput';
import {isValidFavoriteName} from '../../../../utils/rules';
import c from './index.module.scss';

const createValueHandler = (handler, value) => () => handler(value);
Expand All @@ -48,7 +50,6 @@ const Favorite = props => {
const [favoriteName, setFavoriteName] = useState();
const [searchCache, setSearchCache] = useState('');
const [search, setSearch] = useState('');
const [isDisabledName, setDisabledName] = useState(false);

const changeCollection = useCallback(
rowData => {
Expand All @@ -72,7 +73,6 @@ const Favorite = props => {
const onChangeFavoraiteName = useCallback(
e => {
setFavoriteName(e.target.value);
e.target.value ? setDisabledName(false) : setDisabledName(true);
}, []);

const onConfirm = id => {
Expand All @@ -90,11 +90,9 @@ const Favorite = props => {
<div style={{marginBottom: '16px'}}>
{t('analysis.logs.edit_name')}
</div>
<Input
<FavoriteNameInput
style={{marginBottom: '18px'}}
placeholder={t('analysis.logs.favorite_name_placeholder')}
showCount
maxLength={48}
value={favoriteName}
onChange={onChangeFavoraiteName}
/>
Expand Down Expand Up @@ -159,7 +157,7 @@ const Favorite = props => {
title={editFavoriteForm}
onConfirm={createValueHandler(onSaveEditFavorite, rowData)}
okText={t('analysis.logs.action.save')}
okButtonProps={{disabled: isDisabledName}}
okButtonProps={{disabled: !isValidFavoriteName(favoriteName)}}
cancelText={t('common.action.cancel')}
>
<Button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@

import {useState, useCallback} from 'react';
import {useTranslation} from 'react-i18next';
import {Button, Table, Space, Tag, Input, Popconfirm} from 'antd';
import {Button, Table, Space, Tag, Popconfirm} from 'antd';
import ExecutionContent from '../../../../components/ExecutionContent';
import FavoriteNameInput from '../../../../components/FavoriteNameInput';
import {isValidFavoriteName} from '../../../../utils/rules';
import c from './index.module.scss';

const EXECUTE_TYPE_KEY = {
Expand Down Expand Up @@ -116,7 +118,6 @@ const ExecuteLog = props => {
} = props;

const [favoriteName, setFavoriteName] = useState();
const [disabledFavorite, setDisabledFavorite] = useState(true);

const loadStatements = useCallback(
(text, rowData, index) => {
Expand All @@ -130,15 +131,13 @@ const ExecuteLog = props => {
const onFavoraiteName = useCallback(
e => {
setFavoriteName(e.target.value);
e.target.value ? setDisabledFavorite(false) : setDisabledFavorite(true);
},
[]
);

const onFavoriteCard = useCallback(
() => {
setFavoriteName('');
setDisabledFavorite(true);
},
[]
);
Expand All @@ -163,11 +162,9 @@ const ExecuteLog = props => {
<div style={{marginBottom: '16px'}}>
{t('analysis.logs.favorite_statement')}
</div>
<Input
<FavoriteNameInput
style={{marginBottom: '18px'}}
placeholder={t('analysis.logs.favorite_name_placeholder')}
showCount
maxLength={48}
value={favoriteName}
onChange={onFavoraiteName}
/>
Expand Down Expand Up @@ -254,7 +251,7 @@ const ExecuteLog = props => {
onAddFavorite={onAddFavorite}
onFavoriteCard={onFavoriteCard}
loadStatements={loadStatements}
disabledFavorite={disabledFavorite}
disabledFavorite={!isValidFavoriteName(favoriteName)}
t={t}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import React, {useState, useCallback} from 'react';
import {useTranslation} from 'react-i18next';
import {Button, Table, Input, Popconfirm, Modal} from 'antd';
import ExecutionContent from '../../../../components/ExecutionContent';
import FavoriteNameInput from '../../../../components/FavoriteNameInput';
import {isValidFavoriteName} from '../../../../utils/rules';
import Highlighter from 'react-highlight-words';
import c from './index.module.scss';

Expand Down Expand Up @@ -98,7 +100,6 @@ const Favorite = props => {
const [favoriteName, setFavoriteName] = useState();
const [searchCache, setSearchCache] = useState('');
const [search, setSearch] = useState('');
const [isDisabledName, setDisabledName] = useState(false);

const loadStatements = useCallback(
(content, index) => {
Expand Down Expand Up @@ -135,7 +136,6 @@ const Favorite = props => {
const onChangeFavoraiteName = useCallback(
e => {
setFavoriteName(e.target.value);
e.target.value ? setDisabledName(false) : setDisabledName(true);
},
[]
);
Expand All @@ -155,11 +155,9 @@ const Favorite = props => {
<div style={{marginBottom: '16px'}}>
{t('analysis.logs.edit_name')}
</div>
<Input
<FavoriteNameInput
style={{marginBottom: '18px'}}
placeholder={t('analysis.logs.favorite_name_placeholder')}
showCount
maxLength={48}
value={favoriteName}
onChange={onChangeFavoraiteName}
/>
Expand Down Expand Up @@ -225,7 +223,7 @@ const Favorite = props => {
onEditFavorite={onEditFavorite}
onConfirm={onConfirm}
editFavoriteForm={editFavoriteForm}
isDisabledName={isDisabledName}
isDisabledName={!isValidFavoriteName(favoriteName)}
t={t}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@

import React, {useCallback, useState, useContext} from 'react';
import {useTranslation} from 'react-i18next';
import {Button, Tooltip, Dropdown, Input, Popover, message, Space} from 'antd';
import {Button, Tooltip, Dropdown, Popover, message, Space} from 'antd';
import {UpOutlined, DownOutlined, QuestionCircleOutlined} from '@ant-design/icons';
import {GREMLIN_EXECUTES_MODE} from '../../../../utils/constants';
import GraphAnalysisContext from '../../../Context';
import classnames from 'classnames';
import {isValidFavoriteName} from '../../../../utils/rules';
import FavoriteNameInput from '../../../../components/FavoriteNameInput';
import c from './index.module.scss';
import * as api from '../../../../api/index';
import KeyboardAction from '../../../../components/KeyboardAction';
Expand Down Expand Up @@ -139,17 +141,15 @@ const ContentCommon = props => {
e => {
const favoriteName = e.target.value;
setFavoriteName(favoriteName);
favoriteName ? setDisabledFavorite(false) : setDisabledFavorite(true);
setDisabledFavorite(!isValidFavoriteName(favoriteName));
Comment thread
imbajin marked this conversation as resolved.
},
[]
);

const favoriteContent = (
<>
<Input
<FavoriteNameInput
placeholder={t('analysis.query.favorite_name_placeholder')}
showCount
maxLength={48}
value={favoriteName}
onChange={onChangeFavoraiteName}
/>
Expand Down
Loading
Loading