diff --git a/web/src/assets/cluster_bg.png b/web/src/assets/cluster_bg.png new file mode 100644 index 00000000..0aaa07e4 Binary files /dev/null and b/web/src/assets/cluster_bg.png differ diff --git a/web/src/components/kibana/console/components/Console.tsx b/web/src/components/kibana/console/components/Console.tsx index 6e405d67..8b64c8cd 100644 --- a/web/src/components/kibana/console/components/Console.tsx +++ b/web/src/components/kibana/console/components/Console.tsx @@ -43,7 +43,7 @@ const ConsoleWrapper = ({ { export const RequestStatusBar: FunctionComponent = ({ requestInProgress, requestResult, + selectedCluster, }) => { let content: React.ReactNode = null; + const clusterContent = ( + + {selectedCluster.endpoint} - {selectedCluster.version} + +); if (requestInProgress) { content = ( @@ -122,6 +128,7 @@ export const RequestStatusBar: FunctionComponent = ({ gutterSize="s" responsive={false} > + {clusterContent} {content} ); diff --git a/web/src/components/kibana/data/public/query/timefilter/timefilter.ts b/web/src/components/kibana/data/public/query/timefilter/timefilter.ts index 5eb1546f..e850c706 100644 --- a/web/src/components/kibana/data/public/query/timefilter/timefilter.ts +++ b/web/src/components/kibana/data/public/query/timefilter/timefilter.ts @@ -23,7 +23,9 @@ import moment from 'moment'; import { areRefreshIntervalsDifferent, areTimeRangesDifferent } from './lib/diff_time_picker_vals'; import { getForceNow } from './lib/get_force_now'; import { TimefilterConfig, InputTimeRange, TimeRangeBounds } from './types'; -import { calculateBounds, getTime, RefreshInterval, TimeRange } from '../../../common'; +import { getTime, RefreshInterval, TimeRange } from '../../../common'; +import { calculateBounds } from '../../../common/query/timefilter/get_time'; + import { TimeHistoryContract } from './time_history'; import { IndexPattern } from '../../index_patterns'; @@ -173,6 +175,9 @@ export class Timefilter { } public calculateBounds(timeRange: TimeRange): TimeRangeBounds { + if(typeof calculateBounds !== 'function'){ + console.log(typeof(calculateBounds), calculateBounds) + } return calculateBounds(timeRange, { forceNow: this.getForceNow() }); } diff --git a/web/src/models/global.js b/web/src/models/global.js index b7da15d8..3d827f08 100644 --- a/web/src/models/global.js +++ b/web/src/models/global.js @@ -53,6 +53,8 @@ export default { return { name: item.name, id: item.id, + endpoint: item.endpoint, + version: item.version, }; }) diff --git a/web/src/pages/DataManagement/context.js b/web/src/pages/DataManagement/context.js index d1999f45..fc34f797 100644 --- a/web/src/pages/DataManagement/context.js +++ b/web/src/pages/DataManagement/context.js @@ -164,7 +164,7 @@ const filterManager = new FilterManager(); const storage = new Storage(localStorage); const queryStringManager = new QueryStringManager(storage); const timefilterConfig = { - timeDefaults: { from: 'now-1y', to: 'now' }, + timeDefaults: { from: 'now-15m', to: 'now' }, refreshIntervalDefaults: { pause: true, value: 10000 }, }; const timeHistory = new TimeHistory(storage); diff --git a/web/src/pages/System/Cluster/Form.js b/web/src/pages/System/Cluster/Form.js index dff6afda..1d71310d 100644 --- a/web/src/pages/System/Cluster/Form.js +++ b/web/src/pages/System/Cluster/Form.js @@ -1,10 +1,11 @@ import React from 'react'; -import {Card, Form, Icon, Input, InputNumber, Button, Switch, message} from 'antd'; +import {Card, Form, Icon, Input, InputNumber, Button, Switch, message, Spin} from 'antd'; import router from 'umi/router'; import styles from './Form.less'; import {connect} from "dva"; import NewCluster from './Step'; +import PageHeaderWrapper from '@/components/PageHeaderWrapper'; @Form.create() @connect(({clusterConfig}) =>({ @@ -21,6 +22,7 @@ class ClusterForm extends React.Component{ this.state = { confirmDirty: false, needAuth: needAuth, + isLoading: false, } } componentDidMount() { @@ -61,6 +63,7 @@ class ClusterForm extends React.Component{ description: values.description, enabled: values.enabled, monitored: values.monitored, + version: values.version, schema: values.isTLS === true ? 'https': 'http', // order: values.order, } @@ -95,6 +98,40 @@ class ClusterForm extends React.Component{ }) } + tryConnect = async ()=>{ + const {dispatch, form} = this.props; + const values = await form.validateFields((errors, values) => { + if(errors){ + return false; + } + let newVals = { + name: values.name, + host: values.host, + basic_auth: { + username: values.username, + password: values.password, + }, + schema: values.isTLS === true ? 'https': 'http', + } + return values; + }); + if(!values){ + return + } + this.setState({isLoading: true}) + const res = await dispatch({ + type: 'clusterConfig/doTryConnect', + payload: values + }); + if(res){ + message.success('连接成功!') + form.setFieldsValue({ + version: res.version + }) + } + this.setState({isLoading: false}) + } + render() { const {getFieldDecorator} = this.props.form; const formItemLayout = { @@ -121,11 +158,13 @@ class ClusterForm extends React.Component{ }; const {editValue, editMode} = this.props.clusterConfig; return ( + { router.push('/system/cluster'); }}>返回]} > +
{getFieldDecorator('name', { @@ -154,6 +193,13 @@ class ClusterForm extends React.Component{ ], })()} + + {getFieldDecorator('version', { + initialValue: editValue.version, + rules: [ + ], + })()} + {getFieldDecorator('isTLS', { initialValue: editValue?.schema === "https", @@ -175,14 +221,14 @@ class ClusterForm extends React.Component{ {this.state.needAuth === true ? (
{getFieldDecorator('username', { - initialValue: editValue.basic_auth.username, + initialValue: editValue.basic_auth?.username, rules: [ ], })()} {getFieldDecorator('password', { - initialValue: editValue.basic_auth.password, + initialValue: editValue.basic_auth?.password, rules: [ ], })()} @@ -220,9 +266,14 @@ class ClusterForm extends React.Component{ + + + ) } } diff --git a/web/src/pages/System/Cluster/Index.js b/web/src/pages/System/Cluster/Index.js index 93dba2d3..24572475 100644 --- a/web/src/pages/System/Cluster/Index.js +++ b/web/src/pages/System/Cluster/Index.js @@ -2,10 +2,27 @@ import React from 'react'; import {Button, Card, Col, Divider, Form, Input, Row, Table, Switch, Icon, Popconfirm, message} from "antd"; import Link from "umi/link"; import {connect} from "dva"; +import {HealthStatusCircle} from './health_status'; +import PageHeaderWrapper from '@/components/PageHeaderWrapper'; +import styles from './step.less'; +import clusterBg from '@/assets/cluster_bg.png'; -const HealthStatusCircle = ({status})=>{ - return
-} +const content = ( +
+

+ 集群管理通过注册新集群,删除集群让您高效的管理多个 Elasticsearch 集群。 +

+
+); + +const extraContent = ( +
+ 集群管理 +
+); @Form.create() @connect(({clusterConfig}) =>({ @@ -18,10 +35,15 @@ class Index extends React.Component { key: 'name', },{ title: '健康状态', - dataIndex: 'status.health_status', + dataIndex: 'id', key: 'health_status', render: (val)=>{ - return + const {clusterStatus} = this.props.clusterConfig; + if(!clusterStatus || !clusterStatus[val]){ + return + } + const status = clusterStatus[val].health_status; + return } },{ title: '所属业务', @@ -54,10 +76,14 @@ class Index extends React.Component { // } },{ title: '节点数', - dataIndex: 'node_count', + dataIndex: 'id', key: 'mode_count', - render: ()=>{ - return 1; + render: (val)=>{ + const {clusterStatus} = this.props.clusterConfig; + if(!clusterStatus || !clusterStatus[val]){ + return + } + return clusterStatus[val].nodes_count; } },{ title: '集群地址', @@ -69,7 +95,7 @@ class Index extends React.Component { dataIndex: 'monitored', key: 'monitored', render: (val) => { - return val? '是': '否'; + return val? '启用': '关闭'; } }, // { @@ -114,15 +140,26 @@ class Index extends React.Component { }) } componentDidMount() { + this.fetchData({}) + this.fetchClusterStatus(); + } + componentWillUnmount(){ + if(this.fetchClusterStatusTimer){ + clearTimeout(this.fetchClusterStatusTimer); + } + } + fetchClusterStatus = async ()=>{ const {dispatch} = this.props; - dispatch({ + const res = await dispatch({ type: 'clusterConfig/fetchClusterStatus', - }).then(()=>{ - if(typeof this.props.clusterConfig.data === 'undefined') { - this.fetchData({}) - } - }) - + }); + if(this.fetchClusterStatusTimer){ + clearTimeout(this.fetchClusterStatusTimer); + } + if(!res){ + return + } + this.fetchClusterStatusTimer = setTimeout(this.fetchClusterStatus, 10000); } handleSearchClick = ()=>{ @@ -185,43 +222,45 @@ class Index extends React.Component { }; const {data} = this.props.clusterConfig; return ( - -
-
-
- - - - {getFieldDecorator('name')()} - - - -
- -
- -
-
+ + +
+
+
+ + + + {getFieldDecorator('name')()} + + + +
+ +
+ +
+
+
+
+ {/* } + unCheckedChildren={} + onChange={this.handleEnabledChange} + defaultChecked + />是否启用 */} + +
-
- } - unCheckedChildren={} - onChange={this.handleEnabledChange} - defaultChecked - />是否启用 - -
-
- - +
+ + ); } diff --git a/web/src/pages/System/Cluster/Step.js b/web/src/pages/System/Cluster/Step.js index fe9c73cb..5188dba9 100644 --- a/web/src/pages/System/Cluster/Step.js +++ b/web/src/pages/System/Cluster/Step.js @@ -4,20 +4,19 @@ import { useState, useRef } from 'react'; import {InitialStep, ExtraStep, ResultStep} from './steps'; import PageHeaderWrapper from '@/components/PageHeaderWrapper'; import styles from './step.less'; +import clusterBg from '@/assets/cluster_bg.png'; const { Step } = Steps; const steps = [ { - title: '初始化', + title: '连接', }, { - title: '信息确认', - content: 'Second-content', + title: '确认', }, { title: '完成', - content: 'Last-content', }, ]; @@ -152,7 +151,7 @@ const ClusterStep = ({

输入集群地址和身份验证信息分步创建集群。

- */} ); const extraContent = (
这是一个标题
); diff --git a/web/src/pages/System/Cluster/health_status.js b/web/src/pages/System/Cluster/health_status.js new file mode 100644 index 00000000..613c6234 --- /dev/null +++ b/web/src/pages/System/Cluster/health_status.js @@ -0,0 +1,3 @@ +export const HealthStatusCircle = ({status})=>{ + return
+} \ No newline at end of file diff --git a/web/src/pages/System/Cluster/models/cluster.js b/web/src/pages/System/Cluster/models/cluster.js index b9123f17..c2117e6d 100644 --- a/web/src/pages/System/Cluster/models/cluster.js +++ b/web/src/pages/System/Cluster/models/cluster.js @@ -21,7 +21,8 @@ export default { payload: { clusterStatus: res } - }) + }); + return res; }, *fetchClusterList({payload}, {call, put, select}){ let res = yield call(searchClusterConfig, payload); @@ -31,9 +32,9 @@ export default { } res = formatESSearchResult(res) const {clusterStatus} = yield select(state => state.clusterConfig); - for(let item of res.data){ - item.status= clusterStatus[item.id] - } + // for(let item of res.data){ + // item.status= clusterStatus[item.id] + // } yield put({ type: 'saveData', payload: res diff --git a/web/src/pages/System/Cluster/steps/extra_step.js b/web/src/pages/System/Cluster/steps/extra_step.js index d5a17ef3..5ed9f976 100644 --- a/web/src/pages/System/Cluster/steps/extra_step.js +++ b/web/src/pages/System/Cluster/steps/extra_step.js @@ -1,4 +1,5 @@ import {Form, Input, Switch, Icon, InputNumber, Divider, Descriptions} from 'antd'; +import {HealthStatusCircle} from '../health_status'; @Form.create() export class ExtraStep extends React.Component { @@ -19,19 +20,28 @@ export class ExtraStep extends React.Component { return ( <> + + {initialValue?.host} + + + {initialValue?.isTLS ? : null} + {initialValue?.version} - - - {initialValue?.status} - + + {initialValue?.username ? : null} + + + + + {initialValue?.number_of_nodes} {initialValue?.number_of_data_nodes} - + {initialValue?.active_shards}