Commit 5c6f8d22 authored by wenmo's avatar wenmo

BI

parent 9f3e81e2
...@@ -67,6 +67,9 @@ Dinky(原 Dlink): ...@@ -67,6 +67,9 @@ Dinky(原 Dlink):
| | | 新增 自动注册 Yarn 创建的集群 | 0.4.0 | | | | 新增 自动注册 Yarn 创建的集群 | 0.4.0 |
| | SQL | 新增 外部数据源的 SQL 校验 | 0.5.0 | | | SQL | 新增 外部数据源的 SQL 校验 | 0.5.0 |
| | | 新增 外部数据源的 SQL 执行与预览 | 0.5.0 | | | | 新增 外部数据源的 SQL 执行与预览 | 0.5.0 |
| | BI | 新增 折线图的渲染 | 0.5.0 |
| | | 新增 条形图图的渲染 | 0.5.0 |
| | | 新增 饼图的渲染 | 0.5.0 |
| | 元数据 | 新增 查询外部数据源的元数据信息 | 0.4.0 | | | 元数据 | 新增 查询外部数据源的元数据信息 | 0.4.0 |
| | 归档 | 新增 执行与提交历史 | 0.4.0 | | | 归档 | 新增 执行与提交历史 | 0.4.0 |
| 运维中心 | 暂无 | 暂无 | 0.4.0 | | 运维中心 | 暂无 | 暂无 | 0.4.0 |
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
<dependency> <dependency>
<groupId>mysql</groupId> <groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId> <artifactId>mysql-connector-java</artifactId>
<!-- <scope>test</scope>--> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>
@import '~antd/es/style/themes/default.less';
.form_setting{
padding-left: 10px;
}
.form_item{
margin-bottom: 5px;
}
import {Button, Tag, Row, Col, Form, Select, Empty, Switch} from "antd";
import {StateType} from "@/pages/FlinkSqlStudio/model";
import {connect} from "umi";
import styles from "./index.less";
import {FireOutlined, SearchOutlined, RedoOutlined, InfoCircleOutlined} from '@ant-design/icons';
import {useEffect, useState} from "react";
import React from "react";
const {Option} = Select;
export type BarChartConfig = {
isGroup: boolean,
isStack: boolean,
isPercent: boolean,
xField: string,
yField: string,
seriesField?: string,
label?: { },
};
export type BarChartProps = {
onChange: (values: Partial<BarChartConfig>) => void;
data: [];
column: [];
};
const BarChartSetting: React.FC<BarChartProps> = (props) => {
const {current,column,onChange: handleChange,dispatch} = props;
const [form] = Form.useForm();
useEffect(() => {
form.setFieldsValue(current.console.chart);
}, [current.console.chart]);
const onValuesChange = (change: any, all: any) => {
let config: BarChartConfig = {
isGroup: all.isGroup,
isStack: all.isStack,
isPercent: all.isPercent,
xField: all.xField?all.xField:column[0],
yField: all.yField?all.yField:column.length>1?column[1]:column[0],
label: {
position: 'middle',
content: (item) => {
return item[all.xField];
},
style: {
fill: '#fff',
},
},
};
if(all.seriesField){
config.seriesField = all.seriesField;
}
handleChange(config);
};
const getColumnOptions = () => {
const itemList = [];
for (const item of column) {
itemList.push(<Option key={item} value={item} label={item}>
{item}
</Option>)
}
return itemList;
};
return (
<>
<Form
form={form}
className={styles.form_setting}
onValuesChange={onValuesChange}
>
<Row>
<Col span={12}>
<Form.Item
label="x 轴" className={styles.form_item} name="xField"
>
{column&&column.length > 0 ? (
<Select allowClear showSearch
defaultValue={column[0]} value={column[0]}>
{getColumnOptions()}
</Select>):(<Select allowClear showSearch>
{column&&getColumnOptions()}
</Select>)}
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="y 轴" className={styles.form_item} name="yField"
>
{column&&column.length > 1 ? (
<Select allowClear showSearch
defaultValue={column[1]} value={column[1]}>
{getColumnOptions()}
</Select>):(<Select allowClear showSearch>
{column&&getColumnOptions()}
</Select>)}
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="分组字段" className={styles.form_item} name="seriesField"
>
{column&&column.length > 0 ? (
<Select allowClear showSearch>
{getColumnOptions()}
</Select>):(<Select allowClear showSearch>
{column&&getColumnOptions()}
</Select>)}
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="分组" className={styles.form_item} name="isGroup" valuePropName="checked"
>
<Switch checkedChildren="启用" unCheckedChildren="禁用"
/>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="堆叠" className={styles.form_item} name="isStack" valuePropName="checked"
>
<Switch checkedChildren="启用" unCheckedChildren="禁用"
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="百分比" className={styles.form_item} name="isPercent" valuePropName="checked"
>
<Switch checkedChildren="启用" unCheckedChildren="禁用"
/>
</Form.Item>
</Col>
</Row>
</Form>
</>
);
};
export default connect(({ Studio }: { Studio: StateType }) => ({
current: Studio.current,
result: Studio.result,
}))(BarChartSetting);
import {Button, Tag,Row, Col,Form,Select, Empty} from "antd"; import {Button, Tag, Row, Col, Form, Select, Empty, Switch} from "antd";
import {StateType} from "@/pages/FlinkSqlStudio/model"; import {StateType} from "@/pages/FlinkSqlStudio/model";
import {connect} from "umi"; import {connect} from "umi";
import styles from "./index.less"; import styles from "./index.less";
import {FireOutlined, SearchOutlined,RedoOutlined} from '@ant-design/icons'; import {FireOutlined, SearchOutlined, RedoOutlined, InfoCircleOutlined} from '@ant-design/icons';
import {useState} from "react"; import {useEffect, useState} from "react";
import React from "react"; import React from "react";
const {Option} = Select; const {Option} = Select;
export type LineChartConfig = { export type LineChartConfig = {
padding: string,
xField: string, xField: string,
yField: string, yField: string,
seriesField?: string, seriesField?: string,
stepType?: string,
xAxis?: { xAxis?: {
type?: string, type?: string,
}, },
slider?: {},
}; };
export type LineChartProps = { export type LineChartProps = {
...@@ -25,10 +28,33 @@ export type LineChartProps = { ...@@ -25,10 +28,33 @@ export type LineChartProps = {
const LineChartSetting: React.FC<LineChartProps> = (props) => { const LineChartSetting: React.FC<LineChartProps> = (props) => {
const {data,column,onChange: handleChange,dispatch} = props; const {current,column,onChange: handleChange,dispatch} = props;
const [form] = Form.useForm();
useEffect(() => {
form.setFieldsValue(current.console.chart);
}, [current.console.chart]);
const onValuesChange = (change: any, all: any) => { const onValuesChange = (change: any, all: any) => {
handleChange(all); let config: LineChartConfig = {
padding: 'auto',
xField: all.xField?all.xField:column[0],
yField: all.yField?all.yField:column.length>1?column[1]:column[0],
};
if(all.seriesField){
config.seriesField = all.seriesField;
}
if(all.openStepType){
config.stepType = 'hv';
}
if(all.openSlider){
config.slider = {
start: 0,
end: 0.5,
};
}
handleChange(config);
}; };
const getColumnOptions = () => { const getColumnOptions = () => {
...@@ -44,6 +70,7 @@ const LineChartSetting: React.FC<LineChartProps> = (props) => { ...@@ -44,6 +70,7 @@ const LineChartSetting: React.FC<LineChartProps> = (props) => {
return ( return (
<> <>
<Form <Form
form={form}
className={styles.form_setting} className={styles.form_setting}
onValuesChange={onValuesChange} onValuesChange={onValuesChange}
> >
...@@ -53,9 +80,10 @@ const LineChartSetting: React.FC<LineChartProps> = (props) => { ...@@ -53,9 +80,10 @@ const LineChartSetting: React.FC<LineChartProps> = (props) => {
label="x 轴" className={styles.form_item} name="xField" label="x 轴" className={styles.form_item} name="xField"
> >
{column&&column.length > 0 ? ( {column&&column.length > 0 ? (
<Select defaultValue={column[0]} value={column[0]}> <Select allowClear showSearch
defaultValue={column[0]} value={column[0]}>
{getColumnOptions()} {getColumnOptions()}
</Select>):(<Select > </Select>):(<Select allowClear showSearch>
{column&&getColumnOptions()} {column&&getColumnOptions()}
</Select>)} </Select>)}
</Form.Item> </Form.Item>
...@@ -64,10 +92,11 @@ const LineChartSetting: React.FC<LineChartProps> = (props) => { ...@@ -64,10 +92,11 @@ const LineChartSetting: React.FC<LineChartProps> = (props) => {
<Form.Item <Form.Item
label="y 轴" className={styles.form_item} name="yField" label="y 轴" className={styles.form_item} name="yField"
> >
{column&&column.length > 0 ? ( {column&&column.length > 1 ? (
<Select defaultValue={column[0]} value={column[0]}> <Select allowClear showSearch
defaultValue={column[1]} value={column[1]}>
{getColumnOptions()} {getColumnOptions()}
</Select>):(<Select > </Select>):(<Select allowClear showSearch>
{column&&getColumnOptions()} {column&&getColumnOptions()}
</Select>)} </Select>)}
</Form.Item> </Form.Item>
...@@ -79,13 +108,31 @@ const LineChartSetting: React.FC<LineChartProps> = (props) => { ...@@ -79,13 +108,31 @@ const LineChartSetting: React.FC<LineChartProps> = (props) => {
label="分组字段" className={styles.form_item} name="seriesField" label="分组字段" className={styles.form_item} name="seriesField"
> >
{column&&column.length > 0 ? ( {column&&column.length > 0 ? (
<Select defaultValue={column[0]} value={column[0]}> <Select allowClear showSearch>
{getColumnOptions()} {getColumnOptions()}
</Select>):(<Select > </Select>):(<Select allowClear showSearch>
{column&&getColumnOptions()} {column&&getColumnOptions()}
</Select>)} </Select>)}
</Form.Item> </Form.Item>
</Col> </Col>
<Col span={12}>
<Form.Item
label="缩略轴" className={styles.form_item} name="openSlider" valuePropName="checked"
>
<Switch checkedChildren="启用" unCheckedChildren="禁用"
/>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="阶梯线" className={styles.form_item} name="openStepType" valuePropName="checked"
>
<Switch checkedChildren="启用" unCheckedChildren="禁用"
/>
</Form.Item>
</Col>
</Row> </Row>
</Form> </Form>
</> </>
......
@import '~antd/es/style/themes/default.less';
.form_setting{
padding-left: 10px;
}
.form_item{
margin-bottom: 5px;
}
import {Button, Tag, Row, Col, Form, Select, Empty, Switch} from "antd";
import {StateType} from "@/pages/FlinkSqlStudio/model";
import {connect} from "umi";
import styles from "./index.less";
import {FireOutlined, SearchOutlined, RedoOutlined, InfoCircleOutlined} from '@ant-design/icons';
import {useEffect, useState} from "react";
import React from "react";
const {Option} = Select;
export type PieChartConfig = {
angleField: string,
colorField: string,
label: {},
interactions: [],
};
export type PieChartProps = {
onChange: (values: Partial<PieChartConfig>) => void;
data: [];
column: [];
};
const PieChartSetting: React.FC<PieChartProps> = (props) => {
const {current,column,onChange: handleChange,dispatch} = props;
const [form] = Form.useForm();
useEffect(() => {
form.setFieldsValue(current.console.chart);
}, [current.console.chart]);
const onValuesChange = (change: any, all: any) => {
let config: PieChartConfig = {
angleField: all.angleField?all.angleField:column[0],
colorField: all.colorField?all.colorField:column.length>1?column[1]:column[0],
label: {
type: 'inner',
offset: '-30%',
content: ({ percent }) => `${(percent * 100).toFixed(0)}%`,
style: {
fontSize: 14,
textAlign: 'center',
},
},
interactions: [
{
type: 'element-active',
},
],
};
handleChange(config);
};
const getColumnOptions = () => {
const itemList = [];
for (const item of column) {
itemList.push(<Option key={item} value={item} label={item}>
{item}
</Option>)
}
return itemList;
};
return (
<>
<Form
form={form}
className={styles.form_setting}
onValuesChange={onValuesChange}
>
<Row>
<Col span={12}>
<Form.Item
label="弧轴" className={styles.form_item} name="angleField"
>
{column&&column.length > 0 ? (
<Select allowClear showSearch
defaultValue={column[0]} value={column[0]}>
{getColumnOptions()}
</Select>):(<Select allowClear showSearch>
{column&&getColumnOptions()}
</Select>)}
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="颜色" className={styles.form_item} name="colorField"
>
{column&&column.length > 1 ? (
<Select allowClear showSearch
defaultValue={column[1]} value={column[1]}>
{getColumnOptions()}
</Select>):(<Select allowClear showSearch>
{column&&getColumnOptions()}
</Select>)}
</Form.Item>
</Col>
</Row>
</Form>
</>
);
};
export default connect(({ Studio }: { Studio: StateType }) => ({
current: Studio.current,
result: Studio.result,
}))(PieChartSetting);
...@@ -2,40 +2,32 @@ import {Button, Tag,Row, Col,Form,Select, Empty} from "antd"; ...@@ -2,40 +2,32 @@ import {Button, Tag,Row, Col,Form,Select, Empty} from "antd";
import {StateType} from "@/pages/FlinkSqlStudio/model"; import {StateType} from "@/pages/FlinkSqlStudio/model";
import {connect} from "umi"; import {connect} from "umi";
import styles from "./index.less"; import styles from "./index.less";
import {FireOutlined, SearchOutlined,RedoOutlined} from '@ant-design/icons'; import {RedoOutlined} from '@ant-design/icons';
import {CHART, isSql} from "@/components/Studio/conf"; import {CHART, isSql} from "@/components/Studio/conf";
import { Line } from '@ant-design/plots'; import { Line,Bar,Pie } from '@ant-design/plots';
import {useEffect, useState} from "react"; import React, {useEffect, useState} from "react";
import LineChartSetting from "./LineChartSetting"; import LineChartSetting from "./LineChartSetting";
import BarChartSetting from "./BarChartSetting";
import PieChartSetting from "./PieChartSetting";
import {showJobData} from "@/components/Studio/StudioEvent/DQL"; import {showJobData} from "@/components/Studio/StudioEvent/DQL";
import {Dispatch} from "@@/plugin-dva/connect";
const {Option} = Select; const {Option} = Select;
const Chart = (props:any) => { const Chart = (props:any) => {
const {current,result,dispatch} = props; const {current,result,height,dispatch} = props;
const [config, setConfig] = useState({}); const [config, setConfig] = useState({});
const [data, setData] = useState([]);
const [column, setColumn] = useState([]);
const [type, setType] = useState<string>(CHART.LINE); const [type, setType] = useState<string>(CHART.LINE);
const [form] = Form.useForm();
useEffect(() => { useEffect(() => {
toBuild(); form.setFieldsValue(current.console.chart);
}, [result,current.console.result]); }, [current.console.chart]);
const toBuild = () => {
if(isSql(current.task.dialect)){
setData(current.console.result.result.rowData);
setColumn(current.console.result.result.columns);
}else{
setData(result.rowData);
setColumn(result.columns);
}
};
const toRebuild = () => { const toRebuild = () => {
if(!isSql(current.task.diagnosticCodesToIgnore)){ if(!isSql(current.task.dialect)){
showJobData(current.console.result.jobId,dispatch); showJobData(current.console.result.jobId,dispatch);
} }
}; };
...@@ -43,29 +35,55 @@ const Chart = (props:any) => { ...@@ -43,29 +35,55 @@ const Chart = (props:any) => {
const onValuesChange = (change: any, all: any) => { const onValuesChange = (change: any, all: any) => {
if(change.type){ if(change.type){
setType(change.type); setType(change.type);
props.saveChart({type:change.type});
} }
}; };
const renderChartSetting = () => { const renderChartSetting = () => {
if(!current.console.chart||!current.console.result.result){
return undefined;
}
switch (type){ switch (type){
case CHART.LINE: case CHART.LINE:
return <LineChartSetting data={data} column={column} onChange={(value) => { return <LineChartSetting column={current.console.result.result.columns} onChange={(value) => {
setConfig(value); setConfig(value);
props.saveChart({...value,type: current.console.chart.type});
}} />;
case CHART.BAR:
return <BarChartSetting column={current.console.result.result.columns} onChange={(value) => {
setConfig(value);
props.saveChart({...value,type: current.console.chart.type});
}} />;
case CHART.PIE:
return <PieChartSetting column={current.console.result.result.columns} onChange={(value) => {
setConfig(value);
props.saveChart({...value,type: current.console.chart.type});
}} />; }} />;
default: default:
return <LineChartSetting />; return <LineChartSetting column={current.console.result.result.columns} onChange={(value) => {
setConfig(value);
props.saveChart({...value,type: current.console.chart.type});
}} />
} }
}; };
const renderChartContent = () => { const renderChartContent = () => {
if(column.length==0){ if(!current.console.result.result||!current.console.result.result.columns){
return <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />; return <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />;
} }
switch (type){ switch (current.console.chart.type){
case CHART.LINE: case CHART.LINE:
return <Line data={data} {...config} />; return <Line data={current.console.result.result.rowData} {...config} />;
case CHART.BAR:
return <Bar data={current.console.result.result.rowData} {...config} />;
case CHART.PIE:
if(config.angleField){
return <Pie data={current.console.result.result.rowData} {...config} />;
} else {
return <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />;
}
default: default:
return <Line data={data} {...config} />; return <Line data={current.console.result.result.rowData} {...config} />;
} }
}; };
...@@ -77,6 +95,7 @@ const Chart = (props:any) => { ...@@ -77,6 +95,7 @@ const Chart = (props:any) => {
</Col> </Col>
<Col span={8}> <Col span={8}>
<Form <Form
form={form}
className={styles.form_setting} className={styles.form_setting}
onValuesChange={onValuesChange} onValuesChange={onValuesChange}
> >
...@@ -86,15 +105,17 @@ const Chart = (props:any) => { ...@@ -86,15 +105,17 @@ const Chart = (props:any) => {
label="图形类型" className={styles.form_item} name="type" label="图形类型" className={styles.form_item} name="type"
> >
<Select defaultValue={CHART.LINE} value={CHART.LINE}> <Select defaultValue={CHART.LINE} value={CHART.LINE}>
<Option value={CHART.LINE}>折线图</Option> <Option value={CHART.LINE}>{CHART.LINE}</Option>
<Option value={CHART.BAR}>{CHART.BAR}</Option>
<Option value={CHART.PIE}>{CHART.PIE}</Option>
</Select> </Select>
</Form.Item> </Form.Item>
</Col> </Col>
<Col span={12}> { !isSql(current.task.dialect) ? <Col span={12}>
<Button type="primary" onClick={toRebuild} icon={<RedoOutlined />}> <Button type="primary" onClick={toRebuild} icon={<RedoOutlined />}>
重新渲染 刷新数据
</Button> </Button>
</Col> </Col>:undefined}
</Row> </Row>
</Form> </Form>
{renderChartSetting()} {renderChartSetting()}
...@@ -104,7 +125,14 @@ const Chart = (props:any) => { ...@@ -104,7 +125,14 @@ const Chart = (props:any) => {
); );
}; };
const mapDispatchToProps = (dispatch: Dispatch)=>({
saveChart:(chart: any)=>dispatch({
type: "Studio/saveChart",
payload: chart,
}),
})
export default connect(({ Studio }: { Studio: StateType }) => ({ export default connect(({ Studio }: { Studio: StateType }) => ({
current: Studio.current, current: Studio.current,
result: Studio.result, result: Studio.result,
}))(Chart); }),mapDispatchToProps)(Chart);
...@@ -12,6 +12,7 @@ import { ...@@ -12,6 +12,7 @@ import {
import styles from "./index.less"; import styles from "./index.less";
import {showJobData} from "@/components/Studio/StudioEvent/DQL"; import {showJobData} from "@/components/Studio/StudioEvent/DQL";
import StudioPreview from "../StudioPreview"; import StudioPreview from "../StudioPreview";
import {getJobData} from "@/pages/FlinkSqlStudio/service";
const { Title, Paragraph, Text, Link } = Typography; const { Title, Paragraph, Text, Link } = Typography;
...@@ -61,14 +62,19 @@ const StudioHistory = (props: any) => { ...@@ -61,14 +62,19 @@ const StudioHistory = (props: any) => {
const [row, setRow] = useState<HistoryItem>(); const [row, setRow] = useState<HistoryItem>();
const [config,setConfig] = useState<HistoryConfig>(); const [config,setConfig] = useState<HistoryConfig>();
const [type,setType] = useState<number>(); const [type,setType] = useState<number>();
const [result,setResult] = useState<{}>();
const showDetail=(row:HistoryItem,type:number)=>{ const showDetail=(row:HistoryItem,type:number)=>{
setRow(row); setRow(row);
setModalVisit(true); setModalVisit(true);
setType(type); setType(type);
setConfig(JSON.parse(row.config)); setConfig(JSON.parse(row.config));
if(type==3){ if(type===3){
showJobData(row.jobId,dispatch) // showJobData(row.jobId,dispatch)
const res = getJobData(row.jobId);
res.then((resd)=>{
setResult(resd.datas);
});
} }
}; };
...@@ -341,7 +347,7 @@ const StudioHistory = (props: any) => { ...@@ -341,7 +347,7 @@ const StudioHistory = (props: any) => {
</Tag> </Tag>
</ProDescriptions.Item> </ProDescriptions.Item>
<ProDescriptions.Item span={2} > <ProDescriptions.Item span={2} >
<StudioPreview style={{width: '100%'}}/> <StudioPreview result={result} style={{width: '100%'}}/>
</ProDescriptions.Item> </ProDescriptions.Item>
</ProDescriptions> </ProDescriptions>
)} )}
......
...@@ -34,5 +34,5 @@ const StudioPreview = (props:any) => { ...@@ -34,5 +34,5 @@ const StudioPreview = (props:any) => {
export default connect(({ Studio }: { Studio: StateType }) => ({ export default connect(({ Studio }: { Studio: StateType }) => ({
current: Studio.current, current: Studio.current,
result: Studio.result, // result: Studio.result,
}))(StudioPreview); }))(StudioPreview);
...@@ -32,8 +32,8 @@ const StudioTable = (props:any) => { ...@@ -32,8 +32,8 @@ const StudioTable = (props:any) => {
{current.console.result.jobId && (<Tag color="blue" key={current.console.result.jobId}> {current.console.result.jobId && (<Tag color="blue" key={current.console.result.jobId}>
<FireOutlined /> {current.console.result.jobId} <FireOutlined /> {current.console.result.jobId}
</Tag>)} </Tag>)}
{result.columns? {current.console.result.result&&current.console.result.result.columns?
<DTable dataSource={result.rowData} columns={getColumns(result.columns)}/> <DTable dataSource={current.console.result.result.rowData} columns={getColumns(current.console.result.result.columns)}/>
:(<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />) :(<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />)
} }
</>) </>)
......
...@@ -55,13 +55,13 @@ const StudioConsole = (props: any) => { ...@@ -55,13 +55,13 @@ const StudioConsole = (props: any) => {
tab={ tab={
<span> <span>
<BarChartOutlined /> <BarChartOutlined />
统计 BI
</span> </span>
} }
key="StudioChart" key="StudioChart"
> >
<Scrollbars style={{height: consoleHeight}}> <Scrollbars style={{height: consoleHeight}}>
<Chart/> <Chart height={consoleHeight} />
</Scrollbars> </Scrollbars>
</TabPane> </TabPane>
<TabPane <TabPane
......
import {getJobData} from "@/pages/FlinkSqlStudio/service"; import {getJobData} from "@/pages/FlinkSqlStudio/service";
export function showJobData(jobId:string,dispatch:any) { export function showJobData(jobId:string,dispatch:any) {
if(!jobId){
return;
}
const res = getJobData(jobId); const res = getJobData(jobId);
res.then((result)=>{ res.then((result)=>{
dispatch&&dispatch({ dispatch&&dispatch({
......
...@@ -161,7 +161,8 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -161,7 +161,8 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
...result.datas, ...result.datas,
}, },
console:{ console:{
result:[], result: {},
chart: {},
}, },
monaco: React.createRef(), monaco: React.createRef(),
}; };
......
...@@ -21,7 +21,9 @@ export const DIALECT = { ...@@ -21,7 +21,9 @@ export const DIALECT = {
}; };
export const CHART = { export const CHART = {
LINE:'Line', LINE:'折线图',
BAR:'条形图',
PIE:'饼图',
}; };
export const isSql = (dialect: string)=>{ export const isSql = (dialect: string)=>{
......
...@@ -96,6 +96,7 @@ export type TaskType = { ...@@ -96,6 +96,7 @@ export type TaskType = {
export type ConsoleType = { export type ConsoleType = {
result: {}; result: {};
chart: {};
} }
export type TabsItemType = { export type TabsItemType = {
...@@ -185,6 +186,7 @@ export type ModelType = { ...@@ -185,6 +186,7 @@ export type ModelType = {
saveClusterConfiguration: Reducer<StateType>; saveClusterConfiguration: Reducer<StateType>;
saveDataBase: Reducer<StateType>; saveDataBase: Reducer<StateType>;
saveEnv: Reducer<StateType>; saveEnv: Reducer<StateType>;
saveChart: Reducer<StateType>;
}; };
}; };
...@@ -239,6 +241,7 @@ const Model: ModelType = { ...@@ -239,6 +241,7 @@ const Model: ModelType = {
}, },
console: { console: {
result: {}, result: {},
chart: {},
}, },
monaco: {}, monaco: {},
sqlMetaData: undefined, sqlMetaData: undefined,
...@@ -285,6 +288,7 @@ const Model: ModelType = { ...@@ -285,6 +288,7 @@ const Model: ModelType = {
}, },
console: { console: {
result: {}, result: {},
chart: {},
}, },
monaco: {}, monaco: {},
sqlMetaData: undefined, sqlMetaData: undefined,
...@@ -510,11 +514,25 @@ const Model: ModelType = { ...@@ -510,11 +514,25 @@ const Model: ModelType = {
}; };
}, },
saveResult(state, {payload}) { saveResult(state, {payload}) {
// return {
// ...state,
// result: {
// ...payload
// },
// };
let newTabs = state?.tabs;
let newCurrent = state?.current;
for (let i = 0; i < newTabs.panes.length; i++) {
if (newTabs.panes[i].key === newTabs.activeKey) {
newTabs.panes[i].console.result.result = payload;
newCurrent = newTabs.panes[i];
break;
}
}
return { return {
...state, ...state,
result: { current: newCurrent,
...payload tabs: newTabs,
},
}; };
}, },
saveCluster(state, {payload}) { saveCluster(state, {payload}) {
...@@ -542,6 +560,21 @@ const Model: ModelType = { ...@@ -542,6 +560,21 @@ const Model: ModelType = {
...state, ...state,
env: payload, env: payload,
}; };
},saveChart(state, {payload}) {
let newTabs = state?.tabs;
let newCurrent = state?.current;
for (let i = 0; i < newTabs.panes.length; i++) {
if (newTabs.panes[i].key === newTabs.activeKey) {
newTabs.panes[i].console.chart = payload;
newCurrent = newTabs.panes[i];
break;
}
}
return {
...state,
current: newCurrent,
tabs: newTabs,
};
}, },
}, },
}; };
......
...@@ -554,7 +554,7 @@ export default (): React.ReactNode => { ...@@ -554,7 +554,7 @@ export default (): React.ReactNode => {
<Link>新增 编辑器选项卡右键关闭其他和关闭所有</Link> <Link>新增 编辑器选项卡右键关闭其他和关闭所有</Link>
</li> </li>
<li> <li>
<Link>新增 统计选项卡的图标支持</Link> <Link>新增 BI选项卡的折线图、条形图、饼图</Link>
</li> </li>
</ul> </ul>
</Paragraph> </Paragraph>
......
...@@ -105,6 +105,9 @@ Dinky 通过已注册的集群配置来获取对应的 YarnClient 实例。对 ...@@ -105,6 +105,9 @@ Dinky 通过已注册的集群配置来获取对应的 YarnClient 实例。对
| | | 新增 自动注册 Yarn 创建的集群 | 0.4.0 | | | | 新增 自动注册 Yarn 创建的集群 | 0.4.0 |
| | SQL | 新增 外部数据源的 SQL 校验 | 0.5.0 | | | SQL | 新增 外部数据源的 SQL 校验 | 0.5.0 |
| | | 新增 外部数据源的 SQL 执行与预览 | 0.5.0 | | | | 新增 外部数据源的 SQL 执行与预览 | 0.5.0 |
| | BI | 新增 折线图的渲染 | 0.5.0 |
| | | 新增 条形图图的渲染 | 0.5.0 |
| | | 新增 饼图的渲染 | 0.5.0 |
| | 元数据 | 新增 查询外部数据源的元数据信息 | 0.4.0 | | | 元数据 | 新增 查询外部数据源的元数据信息 | 0.4.0 |
| | 归档 | 新增 执行与提交历史 | 0.4.0 | | | 归档 | 新增 执行与提交历史 | 0.4.0 |
| 运维中心 | 暂无 | 暂无 | 0.4.0 | | 运维中心 | 暂无 | 暂无 | 0.4.0 |
......
...@@ -105,6 +105,9 @@ Dinky 通过已注册的集群配置来获取对应的 YarnClient 实例。对 ...@@ -105,6 +105,9 @@ Dinky 通过已注册的集群配置来获取对应的 YarnClient 实例。对
| | | 新增 自动注册 Yarn 创建的集群 | 0.4.0 | | | | 新增 自动注册 Yarn 创建的集群 | 0.4.0 |
| | SQL | 新增 外部数据源的 SQL 校验 | 0.5.0 | | | SQL | 新增 外部数据源的 SQL 校验 | 0.5.0 |
| | | 新增 外部数据源的 SQL 执行与预览 | 0.5.0 | | | | 新增 外部数据源的 SQL 执行与预览 | 0.5.0 |
| | BI | 新增 折线图的渲染 | 0.5.0 |
| | | 新增 条形图图的渲染 | 0.5.0 |
| | | 新增 饼图的渲染 | 0.5.0 |
| | 元数据 | 新增 查询外部数据源的元数据信息 | 0.4.0 | | | 元数据 | 新增 查询外部数据源的元数据信息 | 0.4.0 |
| | 归档 | 新增 执行与提交历史 | 0.4.0 | | | 归档 | 新增 执行与提交历史 | 0.4.0 |
| 运维中心 | 暂无 | 暂无 | 0.4.0 | | 运维中心 | 暂无 | 暂无 | 0.4.0 |
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment