Skip to content

Commit

Permalink
spotless (#2185)
Browse files Browse the repository at this point in the history
  • Loading branch information
zackyoungh authored Aug 9, 2023
1 parent 74d746f commit b4e1ac1
Show file tree
Hide file tree
Showing 15 changed files with 389 additions and 112 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.dinky.data.result.SqlExplainResult;
import org.dinky.explainer.lineage.LineageResult;
import org.dinky.job.JobResult;
import org.dinky.metadata.result.JdbcSelectResult;
import org.dinky.service.StudioService;

import java.util.List;
Expand Down Expand Up @@ -127,6 +128,11 @@ public Result<IResult> executeDDL(@RequestBody StudioDDLDTO studioDDLDTO) {
public Result<SelectResult> getJobData(@RequestParam String jobId) {
return Result.succeed(studioService.getJobData(jobId));
}
/** 根据jobId获取数据 */
@GetMapping("/getCommonSqlData")
public Result<JdbcSelectResult> getJobData(@RequestParam Integer taskId) {
return Result.succeed(studioService.getCommonSqlData(taskId));
}

/** 获取单任务实例的血缘分析 */
@PostMapping("/getLineage")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.dinky.data.result.SqlExplainResult;
import org.dinky.explainer.lineage.LineageResult;
import org.dinky.job.JobResult;
import org.dinky.metadata.result.JdbcSelectResult;

import java.util.List;

Expand All @@ -57,6 +58,8 @@ public interface StudioService {

ObjectNode getJobPlan(StudioExecuteDTO studioExecuteDTO);

JdbcSelectResult getCommonSqlData(Integer taskId);

SelectResult getJobData(String jobId);

LineageResult getLineage(StudioCADTO studioCADTO);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -82,6 +83,8 @@
import com.fasterxml.jackson.databind.node.ObjectNode;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.cache.Cache;
import cn.hutool.cache.impl.TimedCache;
import lombok.RequiredArgsConstructor;

/** StudioServiceImpl */
Expand All @@ -90,6 +93,9 @@
public class StudioServiceImpl implements StudioService {

private static final Logger logger = LoggerFactory.getLogger(StudioServiceImpl.class);
/** Common sql query result cache */
private static final Cache<Integer, JdbcSelectResult> COMMON_SQL_SEARCH_CACHE =
new TimedCache<>(TimeUnit.MINUTES.toMillis(10));

private final ClusterInstanceService clusterInstanceService;
private final ClusterConfigurationService clusterConfigurationService;
Expand Down Expand Up @@ -165,11 +171,15 @@ private void buildSession(JobConfig config) {
@Override
public JobResult executeSql(StudioExecuteDTO studioExecuteDTO) {
if (Dialect.notFlinkSql(studioExecuteDTO.getDialect())) {
return executeCommonSql(
SqlDTO.build(
studioExecuteDTO.getStatement(),
studioExecuteDTO.getDatabaseId(),
studioExecuteDTO.getMaxRowNum()));
JobResult jobResult =
executeCommonSql(
SqlDTO.build(
studioExecuteDTO.getStatement(),
studioExecuteDTO.getDatabaseId(),
studioExecuteDTO.getMaxRowNum()));
COMMON_SQL_SEARCH_CACHE.put(
studioExecuteDTO.getTaskId(), (JdbcSelectResult) jobResult.getResult());
return jobResult;
} else {
return executeFlinkSql(studioExecuteDTO);
}
Expand Down Expand Up @@ -344,6 +354,11 @@ public ObjectNode getJobPlan(StudioExecuteDTO studioExecuteDTO) {
}
}

@Override
public JdbcSelectResult getCommonSqlData(Integer taskId) {
return COMMON_SQL_SEARCH_CACHE.get(taskId);
}

@Override
public SelectResult getJobData(String jobId) {
return JobManager.getJobData(jobId);
Expand Down
2 changes: 2 additions & 0 deletions dinky-web/src/locales/en-US/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,8 @@ export default {
'pages.datastudio.footer.lineSeparator': "Line Separator: ",
'pages.datastudio.footer.codeEncoding': "File Encoding: ",
'pages.datastudio.footer.codePosition': "Ln {Ln}:Col {Col} ",
'pages.datastudio.label.result.query.latest.data': 'Get the latest data',



'datastudio.middle.qg': 'Quick Guide',
Expand Down
3 changes: 3 additions & 0 deletions dinky-web/src/locales/zh-CN/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1021,6 +1021,9 @@ export default {
'pages.datastudio.footer.codeEncoding': "文件编码:",
'pages.datastudio.footer.codePosition': "行{Ln}:列{Col} ",

'pages.datastudio.label.result.query.latest.data': '获取最新数据',


'datastudio.middle.qg': '快捷引导',
'datastudio.middle.qg.clusterInstance': '注册 Session 集群',
'datastudio.middle.qg.clusterConfiguration': '注册集群配置',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { ColumnType } from "antd/es/table";
import {DataIndex} from "rc-table/es/interface";
import {Input} from "antd";

206 changes: 206 additions & 0 deletions dinky-web/src/pages/DataStudio/BottomContainer/Result/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
import {connect} from "umi";
import {isSql} from "@/pages/DataStudio/HeaderContainer/service";
import {Button, Empty, Input, InputRef, Space, Table, Tag} from "antd";
import {FireOutlined, SearchOutlined} from "@ant-design/icons";
import {l} from "@/utils/intl";
import {getCurrentData, getCurrentTab, mapDispatchToProps} from "@/pages/DataStudio/function";
import {DataStudioParams, StateType, TabsPageType} from "@/pages/DataStudio/model";
import {useEffect, useRef, useState} from "react";
import {handleGetOption} from "@/services/BusinessCrud";
import {API_CONSTANTS} from "@/services/constants";
import {postAll} from "@/services/api";
import {ColumnsType, ColumnType} from "antd/es/table";
import {DataIndex} from "rc-table/es/interface";
import {FilterConfirmProps} from "antd/es/table/interface";
import {Highlight} from "@ant-design/pro-layout/es/components/Help/Search";
import {transformTableDataToCsv} from "@/utils/function";

type Data = {
[c: string]: any,
columns?: string[],
rowData?: object[]
}
const Result = (props: any) => {

const {saveTabs, tabs: {panes, activeKey}} = props;
const [data, setData] = useState<Data>({})
const [loading, setLoading] = useState<boolean>(true)
const currentTabs = getCurrentTab(panes, activeKey);
const current = getCurrentData(panes, activeKey);

const [searchText, setSearchText] = useState('');
const [searchedColumn, setSearchedColumn] = useState('');
const searchInput = useRef<InputRef>(null);
const handleReset = (clearFilters: () => void) => {
clearFilters();
setSearchText('');
};
const handleSearch = (
selectedKeys: string[],
confirm: (param?: FilterConfirmProps) => void,
dataIndex: DataIndex,
) => {
confirm();
setSearchText(selectedKeys[0]);
setSearchedColumn(dataIndex.toString());
};
const getColumnSearchProps = (dataIndex: string): ColumnType<Data> => ({
filterDropdown: ({setSelectedKeys, selectedKeys, confirm, clearFilters}) => (
<div style={{padding: 8}} onKeyDown={(e) => e.stopPropagation()}>
<Input
ref={searchInput}
placeholder={`Search ${dataIndex}`}
value={selectedKeys[0]}
onChange={(e) => setSelectedKeys(e.target.value ? [e.target.value] : [])}
onPressEnter={() => handleSearch(selectedKeys as string[], confirm, dataIndex)}
style={{marginBottom: 8, display: 'block'}}
/>
<Space>
<Button
type="primary"
onClick={() => handleSearch(selectedKeys as string[], confirm, dataIndex)}
icon={<SearchOutlined/>}
size="small"
style={{width: 90}}
>
{l("button.search")}
</Button>
<Button
onClick={() => clearFilters && handleReset(clearFilters)}
size="small"
style={{width: 90}}
>
{l("button.reset")}
</Button>
</Space>
</div>
),
filterIcon: (filtered: boolean) => (
<SearchOutlined style={{color: filtered ? '#1677ff' : undefined}}/>
),
onFilter: (value, record) =>
record[dataIndex]
.toString()
.toLowerCase()
.includes((value as string).toLowerCase()),
onFilterDropdownOpenChange: (visible) => {
if (visible) {
setTimeout(() => searchInput.current?.select(), 100);
}
},
render: (text) =>
searchedColumn === dataIndex ? (
<Highlight label={text ? text.toString() : ''} words={[searchText]}/>
) : (
text
),
});


const loadData = async (isRefresh?: boolean) => {
if (!currentTabs) {
return
}
if (currentTabs.type !== TabsPageType.project) {
return
}
if ((currentTabs?.params as DataStudioParams).resultData && !isRefresh) {
setData((currentTabs?.params as DataStudioParams).resultData)
} else {
if (isSql(current.dialect)) {
// common sql
const res = await handleGetOption("api/studio/getCommonSqlData", "Get Data", {taskId: (currentTabs?.params as DataStudioParams).taskId});
if (res.datas) {
(currentTabs?.params as DataStudioParams).resultData = res.datas
saveTabs({...props.tabs})
setData(res.datas)
}
} else {
// flink sql
if (current.jobInstanceId) {
const res = await postAll(API_CONSTANTS.GET_JOB_BY_ID, {id: current.jobInstanceId});
const jobData = res.datas;
if ("unknown" !== jobData.status.toLowerCase()) {
const jid = jobData.jid;
const tableData = await handleGetOption("api/studio/getJobData", "Get Data", {jobId: jid});
const datas = tableData.datas;
datas.jid = jid;
if (datas.success) {
(currentTabs?.params as DataStudioParams).resultData = datas
saveTabs({...props.tabs})
}
}
}
}
}
setLoading(false)
}
useEffect(() => {
setData({})
loadData()
}, [currentTabs])


const getColumns = (columns: string[]) => {
return columns?.map((item) => {
return {
title: item, dataIndex: item,
sorter: (a, b) => a[item] - b[item],
...getColumnSearchProps(item),
};
}) as ColumnsType<any>;
};

const showDetail = async () => {
setLoading(true)
await loadData(true);
setLoading(false)

};

const renderFlinkSQLContent = () => {
return (<>
{current.jobInstanceId ? (<>
<Space>
<Button loading={loading} type="primary" onClick={showDetail} icon={<SearchOutlined/>}>
{l('pages.datastudio.label.result.query.latest.data')}
</Button>
<Tag color="blue" key={data.jid}>
<FireOutlined/> {data.jid}
</Tag>
</Space>
</>) : undefined}
</>)
}
const renderDownloadButton = () => {
if (current && data.columns) {
const _utf = "\uFEFF";
const csvDataBlob = new Blob([_utf + transformTableDataToCsv(data.columns!, data.rowData!)], {
type: "text/csv",
});
const url = URL.createObjectURL(csvDataBlob);
return <Button type="link" href={url}>Export Csv</Button>
}
return undefined
}


return (
<div style={{width: '100%'}}>
<div style={{direction: "rtl"}}>
{renderDownloadButton()}
{current ? (isSql(current.dialect) ? <></> : renderFlinkSQLContent()) : undefined}
</div>
{data.columns ?
<Table columns={getColumns(data.columns)} dataSource={data.rowData!.map((item: any, index: number) => {
return {...item, key: index}
})} loading={loading}/>
: (<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>)
}
</div>
);
};

export default connect(({Studio}: { Studio: StateType }) => ({
tabs: Studio.tabs,
}), mapDispatchToProps)(Result);
Loading

0 comments on commit b4e1ac1

Please sign in to comment.