Skip to content
Permalink
Browse files
Support data-import task manager (#239)
* [hubble-fe] Add keyboard shortcut in queries

* [hubble-fe] Adjust style lints temporarily

* [hubble-fe] Upgrade component lib and other dependencies

* [hubble-fe] Abstract react-popper-tooltip configs and replace them to where there are standing

* [hubble-fe] Fix RadioGroup primary button style issue after component lib upgrades

* [hubble-fe] Fix <Switch />, <Select /> issues after component lib upgrades

* [hubble-fe] modify text in vertex/edge map

* [hubble-fe] Add v1.3.1 support

* [hubble-fe] Bumped version v1.3.0 -> v1.3.1
  • Loading branch information
OshotOkill committed Jul 29, 2020
1 parent ca9f697 commit 14b62a25454b4a016d6b4d7a22b426967d514953
Showing 78 changed files with 7,487 additions and 5,632 deletions.
@@ -1,5 +1,9 @@
{
"extends": "stylelint-config-standard",
"rules": {
"no-descending-specificity": null,
"no-duplicate-selectors": null
},
"ignoreFiles": [
"**/*.ts",
"**/*.tsx",
@@ -1,3 +1,16 @@
## 1.3.1 (2020-07-28)

1.3.1 added support for data import from users by uploading their .csv files and setting data mappings.

Users can create jobs and manage load tasks with each. Details of Jobs that failed or succeed can be checked out.

#### :rocket: New Feature

- data-import support
- Job manager can handle different jobs, which could contain multiple load tasks

<br />

## 1.2.1 (2020-02-27)

1.2.1 added graph-mode view for metadata management. It supports all functions that list-mode has with better visual effect.
@@ -1,3 +1,14 @@
## 1.3.1 (2020-07-28)

1.3.1 添加了数据导入支持,用户可通过上传 .csv 文件来导入相应的数据并设置数据映射

用户可创建任务并管理相应的导入任务,成功或失败的任务可查看详情

#### :rocket: 特性

- 数据导入支持
- 任务管理可处理多个任务,每个任务可包含多个导入任务

## 1.2.1 (2020-02-27)

1.2.1 在元数据管理模块添加图模式,包含列表模式的大部分功能,且有着更好的视觉效果
@@ -1,31 +1,32 @@
{
"name": "hubble",
"version": "1.3.0",
"version": "1.3.1",
"author": "wangzixi",
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/hugegraph/hugegraph-hubble"
},
"dependencies": {
"@baidu/one-ui": "3.0.14-beta-45",
"@baidu/one-ui": "3.1.1-beta-18",
"@types/classnames": "^2.2.10",
"@types/codemirror": "^0.0.95",
"@types/codemirror": "^0.0.96",
"@types/d3": "^5.7.2",
"@types/file-saver": "^2.0.1",
"@types/jest": "24.0.15",
"@types/lodash-es": "^4.17.3",
"@types/node": "14.0.10",
"@types/react": "16.9.35",
"@types/node": "14.0.14",
"@types/react": "16.9.41",
"@types/react-dom": "16.9.8",
"@types/react-highlight-words": "^0.16.1",
"@types/validator": "^13.0.0",
"@types/validator": "^13.1.0",
"axios": "^0.19.0",
"classnames": "^2.2.6",
"codemirror": "^5.54.0",
"codemirror": "^5.55.0",
"file-saver": "^2.0.2",
"i18next": "^19.4.5",
"less": "^3.11.2",
"framer-motion": "^1.11.1",
"i18next": "^19.5.3",
"less": "^3.11.3",
"lodash-es": "^4.17.15",
"mobx": "^5.13.0",
"mobx-react": "^6.2.2",
@@ -35,12 +36,12 @@
"react-dnd-html5-backend": "^11.1.3",
"react-dom": "^16.13.1",
"react-highlight-words": "^0.16.0",
"react-i18next": "^11.5.0",
"react-i18next": "^11.7.0",
"react-json-view": "^1.19.1",
"react-popper-tooltip": "^2.11.1",
"react-scripts": "3.4.1",
"typescript": "^3.9.5",
"validator": "^13.0.0",
"typescript": "^3.9.6",
"validator": "^13.1.1",
"vis-network": "7.3.5",
"wouter": "^2.1.1"
},
@@ -65,7 +66,7 @@
"customize-cra": "^0.9.1",
"less-loader": "^5.0.0",
"react-app-rewired": "^2.1.6",
"stylelint": "^13.5.0",
"stylelint": "^13.6.1",
"stylelint-config-standard": "^20.0.0"
},
"keywords": [
@@ -1,15 +1,20 @@
import React, { useContext, useEffect } from 'react';
import { Route, useRoute } from 'wouter';
import { observer } from 'mobx-react';
import React from 'react';
import { Route } from 'wouter';

import { AppBar } from './common';
import {
GraphManagement,
DataAnalyze,
MetadataConfigs,
ImportTasks
ImportTasks,
ImportManager,
JobDetails
} from './graph-management';
import {
TaskErrorLogs,
JobErrorLogs
} from './graph-management/data-import/import-tasks/error-logs';
import GraphManagementSidebar from './graph-management/GraphManagementSidebar';
import { DataImportRootStoreContext } from '../stores';

const App: React.FC = () => {
return (
@@ -18,7 +23,11 @@ const App: React.FC = () => {
<GraphManagementSidebar />
<Route
path="/graph-management/:id/data-import/import-tasks/:taskId/error-log"
component={ErrorLogs}
component={TaskErrorLogs}
/>
<Route
path="/graph-management/:id/data-import/import-manager/:jobId/error-log"
component={JobErrorLogs}
/>
<Route
path="/graph-management/:id/data-analyze"
@@ -29,48 +38,21 @@ const App: React.FC = () => {
component={MetadataConfigs}
/>
<Route
path="/graph-management/:id/data-import/import-tasks"
path="/graph-management/:id/data-import/:jobId/import-tasks"
component={ImportTasks}
/>
<Route
path="/graph-management/:id/data-import/import-manager/:jobId/details"
component={JobDetails}
/>
<Route
path="/graph-management/:id/data-import/import-manager"
component={ImportManager}
/>
<Route path="/graph-management" component={GraphManagement} />
<Route path="/" component={GraphManagement} />
</div>
);
};

const ErrorLogs: React.FC = observer(() => {
const dataImportRootStore = useContext(DataImportRootStoreContext);
const { serverDataImportStore } = dataImportRootStore;
const [, params] = useRoute(
'/graph-management/:id/data-import/import-tasks/:taskId/error-log'
);

useEffect(() => {
serverDataImportStore.checkErrorLogs(
Number(params!.taskId),
Number(params!.id)
);
}, [params!.id, params!.taskId]);

return (
<section
style={{
width: '80vw',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
marginBottom: 16,
position: 'relative',
top: 76,
left: '10vw',
lineHeight: 2,
whiteSpace: 'pre',
fontSize: 14
}}
>
<div>{serverDataImportStore.errorLogs}</div>
</section>
);
});

export default App;
@@ -0,0 +1,28 @@
.table-data-loading {
&-wrapper {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}

&-bg {
width: 144px;
height: 144px;
position: relative;
margin-bottom: 10px;
}

&-back {
position: absolute;
left: 22px;
top: 20px;
}

&-front {
position: absolute;
left: 57.1px;
top: 52.1px;
animation: loading-rotate 2s linear infinite;
}
}
@@ -0,0 +1,41 @@
import React from 'react';
import { observer } from 'mobx-react';
import { useTranslation } from 'react-i18next';

import LoadingBackIcon from '../../assets/imgs/ic_loading_back.svg';
import LoadingFrontIcon from '../../assets/imgs/ic_loading_front.svg';

import './LoadingDataView.less';

export interface LoadingDataViewProps {
isLoading: boolean;
emptyView?: React.ReactElement;
}

const LoadingDataView: React.FC<LoadingDataViewProps> = observer(
({ isLoading, emptyView }) => {
const { t } = useTranslation();

return isLoading ? (
<div className="table-data-loading-wrapper">
<div className="table-data-loading-bg">
<img
className="table-data-loading-back"
src={LoadingBackIcon}
alt="load background"
/>
<img
className="table-data-loading-front"
src={LoadingFrontIcon}
alt="load spinner"
/>
</div>
<span>{t('common.loading-data')}...</span>
</div>
) : emptyView ? (
emptyView
) : null;
}
);

export default LoadingDataView;
@@ -0,0 +1,81 @@
import React from 'react';
import { observer } from 'mobx-react';
import TooltipTrigger, { Trigger } from 'react-popper-tooltip';
import 'react-popper-tooltip/dist/styles.css';

import type { Placement, Modifiers } from 'popper.js';

export interface TooltipProps {
placement: Placement;
tooltipShown?: boolean;
trigger?: Trigger;
modifiers?: Modifiers;
tooltipWrapper: React.ReactNode;
tooltipWrapperProps?: any;
tooltipArrowClassName?: string;
childrenWrapperElement?: 'div' | 'span' | 'img';
childrenProps?: any;
children?: React.ReactNode;
}

const Tooltip: React.FC<TooltipProps> = observer(
({
placement,
tooltipShown,
trigger = 'click',
modifiers,
children,
tooltipWrapper,
tooltipWrapperProps,
tooltipArrowClassName,
childrenWrapperElement = 'span',
childrenProps
}) => (
<TooltipTrigger
trigger={trigger}
placement={placement}
tooltipShown={tooltipShown}
modifiers={modifiers}
tooltip={({
arrowRef,
tooltipRef,
getArrowProps,
getTooltipProps,
placement
}) => (
<div
{...getTooltipProps({
ref: tooltipRef,
...tooltipWrapperProps
})}
>
<div
{...getArrowProps({
ref: arrowRef,
className: 'tooltip-arrow ' + (tooltipArrowClassName || ''),
'data-placement': placement
})}
/>
{tooltipWrapper}
</div>
)}
>
{({ getTriggerProps, triggerRef }) => {
const Tag = childrenWrapperElement;

return (
<Tag
{...getTriggerProps({
ref: triggerRef,
...childrenProps
})}
>
{children}
</Tag>
);
}}
</TooltipTrigger>
)
);

export default Tooltip;
@@ -1,3 +1,5 @@
import AppBar from './AppBar';
import Tooltip from './Tooltip';
import LoadingDataView from './LoadingDataView';

export { AppBar };
export { AppBar, Tooltip, LoadingDataView };

0 comments on commit 14b62a2

Please sign in to comment.