Skip to content

Commit

Permalink
feat: init task log
Browse files Browse the repository at this point in the history
feat: add log read

mod: change key

mod: code review

mod: add template import

mod: code review
  • Loading branch information
hetao92 committed Mar 15, 2022
1 parent c52a497 commit 57f7832
Show file tree
Hide file tree
Showing 20 changed files with 530 additions and 60 deletions.
1 change: 1 addition & 0 deletions app/app.less
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
border: none;
white-space: nowrap;
color: @darkBlue;

&.ant-radio-button-wrapper-checked {
color: #fff;
}
Expand Down
15 changes: 11 additions & 4 deletions app/config/locale/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,10 @@
"createTask": "New Import",
"uploadTemp": "Import Template",
"downloadConfig": "Download Config",
"downloadLog": "Download Log",
"viewLogs": "View Logs",
"details": "Details",
"lines": "Lines",
"task": "import task",
"taskList": "Task List",
"taskName": "Task Name",
"vertices": "Map Vertices",
Expand Down Expand Up @@ -332,10 +333,16 @@
"importCompleted": "Import completed",
"importStopped": "Import stopped",
"importFailed": "Failed",
"notImported": "{total} lines not imported",
"readFailed": "{total} lines read failed",
"notImported": "{total} not imported",
"readFailed": "{total} read failed",
"selectFile": "Select bind source file",
"addTag": "Add Tag"
"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"
},
"schema": {
"spaceList": "Graph Space List",
Expand Down
15 changes: 11 additions & 4 deletions app/config/locale/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,10 @@
"createTask": "创建导入任务",
"uploadTemp": "导入模板",
"downloadConfig": "下载配置文件",
"downloadLog": "下载日志",
"viewLogs": "查看日志",
"details": "详情",
"lines": "",
"task": "导入任务",
"taskList": "任务列表",
"taskName": "任务名称",
"vertices": "关联点",
Expand Down Expand Up @@ -328,10 +329,16 @@
"importCompleted": "导入完成",
"importStopped": "导入中止",
"importFailed": "导入失败",
"notImported": "{total}行未导入",
"readFailed": "{total}行读取失败",
"notImported": "{total}未导入",
"readFailed": "{total}读取失败",
"selectFile": "选择绑定文件",
"addTag": "添加 Tag"
"addTag": "添加 Tag",
"config": "任务配置",
"parseFailed": "文件解析失败",
"uploadTemplate": "点击或拖动yaml配置文件到该区域上传",
"uploadTemplateTip": "模板中所有文件路径请仅保留文件名(保留文件扩展名),比如 logPath: config.csv",
"fileUploadRequired": "上传配置前请确保所有 csv 数据文件已上传",
"reUpload": "重新上传"
},
"schema": {
"spaceList": "图空间列表",
Expand Down
14 changes: 14 additions & 0 deletions app/config/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const importData = post('/api-nebula/task/import');
const handleImportAction = post('/api-nebula/task/import/action');

const getLog = get('/api/import/log');
const getErrLog = get('/api/import/err_log');
const finishImport = post('/api/import/finish');

const getImportWokingDir = get('/api/import/working_dir');
Expand All @@ -31,6 +32,15 @@ const uploadFiles = (params?, config?) =>
'Content-Type': 'multipart/form-data',
},
});


const getTaskLogs = (params?, config?) => {
const { id, ...others } = params;
return get(`/api/import/task_log_paths/${id}`)(others, config);
};

const getTaskConfigUrl = (id: number) => `/api-nebula/task/import/config/${id}`;
const getTaskLogUrl = (path: string) => `/api-nebula/task/import/log?pathName=${encodeURI(path)}`;
export default {
execNGQL,
batchExecNGQL,
Expand All @@ -40,10 +50,14 @@ export default {
finishImport,
handleImportAction,
getLog,
getErrLog,
getImportWokingDir,
getUploadDir,
getTaskDir,
deteleFile,
getFiles,
uploadFiles,
getTaskConfigUrl,
getTaskLogs,
getTaskLogUrl
};
9 changes: 6 additions & 3 deletions app/interfaces/import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ export enum ITaskStatus {
}

export interface ITaskStats {
totalLine: number;
totalCount: number;
totalBatches: number;
totalBytes: number;
totalImportedBytes: number;
totalLatency: number;
totalReqTime: number;
numFailed: number;
numReadFailed: number;
}
Expand All @@ -23,7 +26,7 @@ export interface ITaskItem {
user: string;
taskStatus: ITaskStatus;
taskMessage: string;
statsQuery: ITaskStats;
stats: ITaskStats;
}

export interface IVerticesConfig {
Expand Down
2 changes: 0 additions & 2 deletions app/pages/Console/OutputBox/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,7 @@ const OutputBox = (props: IProps) => {
const link = document.createElement('a');
link.href = url;
link.download = `result.csv`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};

const handleExplore = () => {
Expand Down
2 changes: 1 addition & 1 deletion app/pages/Console/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Button, Select, Tooltip, message } from 'antd';
import React, { useEffect, useRef, useState } from 'react';
import intl from 'react-intl-universal';
import { observer } from 'mobx-react-lite';
import { trackPageView, trackEvent } from '@app/utils/stat';
import { trackEvent, trackPageView } from '@app/utils/stat';
import { useStore } from '@app/stores';
import Instruction from '@app/components/Instruction';
import Icon from '@app/components/Icon';
Expand Down
4 changes: 2 additions & 2 deletions app/pages/Import/TaskCreate/SchemaConfig/TagConfig/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ interface IProps {
const VerticesConfig = (props: IProps) => {
const { tag, tagIndex, configIndex, file } = props;
const { dataImport, schema } = useStore();
const { asyncUpdateTagConfig, updateTagPropMapping } = dataImport;
const { updateTagConfig, updateTagPropMapping } = dataImport;
const { tags } = schema;

const handleTagChange = (configIndex: number, tagIndex: number, value: string) => {
asyncUpdateTagConfig({ configIndex, tagIndex, tag: value });
updateTagConfig({ configIndex, tagIndex, tag: value });
};

const handlePropChange = (index, field, value) => {
Expand Down
4 changes: 2 additions & 2 deletions app/pages/Import/TaskCreate/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const formItemLayout = {
};
const TaskCreate = () => {
const { dataImport, schema, global } = useStore();
const { taskDir, asyncGetTaskDir, basicConfig, verticesConfig, edgesConfig, updateBasicConfig, importTask } = dataImport;
const { taskDir, getTaskDir, basicConfig, verticesConfig, edgesConfig, updateBasicConfig, importTask } = dataImport;
const { spaces, spaceVidType, getSpaces, updateSpaceInfo, currentSpace } = schema;
const { host, username } = global;
const { batchSize } = basicConfig;
Expand Down Expand Up @@ -125,7 +125,7 @@ const TaskCreate = () => {
};

useEffect(() => {
asyncGetTaskDir();
getTaskDir();
getSpaces();
if(currentSpace) {
updateSpaceInfo(currentSpace);
Expand Down
62 changes: 62 additions & 0 deletions app/pages/Import/TaskList/TaskItem/LogModal/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
@import '~@app/common.less';
.log-modal {
height: 100vh;
.ant-modal {
height: 80%;
.ant-modal-content {
height: 100%;
}
}
.import-modal-title {
display: flex;
align-items: center;
}
.ant-modal-header {
border-bottom: none;
padding-right: 80px;
padding-top: 15px;
.ant-modal-title {
display: flex;
align-items: center;
justify-content: space-between;
}
.ant-modal-close {
top: 5px;
}
}
.ant-modal-body {
display: flex;
height: 91%;
}
.log-container {
width: 100%;
height: 100%;
overflow: auto;
padding: 10px 20px 120px;
font-size: 18px;
text-align: left;
background: #333;
color: #fff;
word-break: break-all;
}
}
.log-tab {
max-height: 65vh;
.ant-tabs-nav {
width: 200px;
.ant-tabs-tab {
background-color: @lightGray;
color: @darkBlue;
}
.ant-tabs-tab-active {
background-color: #0091FF;
color: #fff;
.ant-tabs-tab-btn {
color: #fff;
}
}
}
.ant-tabs-content-holder > .ant-tabs-content {
display: none
}
}
131 changes: 131 additions & 0 deletions app/pages/Import/TaskList/TaskItem/LogModal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { Button, Modal, Tabs } from 'antd';
import _ from 'lodash';
import React, { useEffect, useRef, useState } from 'react';
import intl from 'react-intl-universal';
import Icon from '@app/components/Icon';
import './index.less';
import { useStore } from '@app/stores';
import { ITaskStatus } from '@app/interfaces/import';

const { TabPane } = Tabs;

interface ILogDimension {
space: string;
id: number;
status: ITaskStatus;
}

interface ILog {
name: string;
path: string;
}
interface IProps {
logDimension: ILogDimension;
visible: boolean;
onCancel: () => void;
}
const LogModal = (props: IProps) => {
const { visible, onCancel, logDimension: { space, id, status } } = props;
const { dataImport: { getLogs, downloadTaskLog, getImportLogDetail, getErrLogDetail } } = useStore();
const logRef = useRef<HTMLDivElement>(null);
const timer = useRef<any>(null);
const offset = useRef(0);
const _status = useRef(status);
const [logs, setLogs] = useState<ILog[]>([]);
const [currentLog, setCurrentLog] = useState<ILog | null>(null);
const handleTabChange = (key: string) => {
setCurrentLog(logs.filter(item => item.name === key)[0]);
};

const getAllLogs = async() => {
const { code, data } = await getLogs(id);
if(code === 0) {
setLogs(data);
setCurrentLog(data[0]);
}
};

const handleLogDownload = () => {
if(currentLog) {
downloadTaskLog(currentLog.path);
}
};

const readLog = async() => {
const getLogDetail = currentLog!.name === 'import.log' ? getImportLogDetail : getErrLogDetail;
const res = await getLogDetail({
offset: offset.current,
taskId: id,
path: currentLog!.path
});
handleLogData(res);
};

const handleLogData = (res) => {
const { data } = res;
if(!logRef.current) {
timer.current = setTimeout(readLog, 2000);
return;
}
if (data) {
logRef.current.innerHTML += data.join('<br/>') + '<br/>';
logRef.current.scrollTop = logRef.current.scrollHeight;
offset.current += data.length;
timer.current = setTimeout(readLog, 2000);
} else if (_status.current === ITaskStatus.StatusProcessing) {
timer.current = setTimeout(readLog, 2000);
} else {
offset.current = 0;
}
};

useEffect(() => {
getAllLogs();
return () => {
clearTimeout(timer.current);
};
}, []);

useEffect(() => {
_status.current = status;
}, [status]);
useEffect(() => {
clearTimeout(timer.current);
if(logRef.current) {
logRef.current.innerHTML = '';
}
offset.current = 0;
if(currentLog) {
readLog();
}
}, [currentLog]);
return (
<Modal
title={<>
<div className="import-modal-title">
<span>{`${space} ${intl.get('import.task')} - ${intl.get('common.log')}`}</span>
{status === ITaskStatus.StatusProcessing && <Button type="text" loading={true} />}
</div>
<Button className="studio-add-btn primary-btn" onClick={handleLogDownload}>
<Icon type="icon-studio-btn-download" />
{intl.get('import.downloadLog')}
</Button>
</>}
width="80%"
visible={visible}
onCancel={onCancel}
wrapClassName="log-modal"
destroyOnClose={true}
footer={false}
>
<Tabs className="log-tab" tabBarGutter={0} tabPosition="left" onChange={handleTabChange}>
{logs.map(log => (
<TabPane tab={`${log.name}`} key={log.name} />
))}
</Tabs>
<div className="log-container" ref={logRef}/>
</Modal>
);
};

export default LogModal;
3 changes: 3 additions & 0 deletions app/pages/Import/TaskList/TaskItem/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
& > span {
margin-right: 6px
}
.red {
color: @red
}
}
.err-info {
color: @red
Expand Down
Loading

0 comments on commit 57f7832

Please sign in to comment.