optimize node top metric and change cluster config editing logic
This commit is contained in:
parent
740cda1ff7
commit
475dd606e8
|
@ -448,7 +448,7 @@ export default [
|
|||
hideInMenu: true,
|
||||
},
|
||||
{
|
||||
path: "/system/cluster/edit",
|
||||
path: "/system/cluster/:id/edit",
|
||||
name: "editCluster",
|
||||
component: "./System/Cluster/Form",
|
||||
hideInMenu: true,
|
||||
|
|
|
@ -16,6 +16,7 @@ class DropdownSelect extends React.Component {
|
|||
overlayVisible: false,
|
||||
data: (props.data || []).slice(0, props.size),
|
||||
dataSource: [...props.data],
|
||||
selectedIndex: -1,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -75,9 +76,38 @@ class DropdownSelect extends React.Component {
|
|||
hasMore: newData.length > this.props.size,
|
||||
});
|
||||
};
|
||||
selectOffset = (offset) => {
|
||||
let { selectedIndex, data } = this.state;
|
||||
const len = data.length;
|
||||
selectedIndex = (selectedIndex + offset + len) % len;
|
||||
this.setState({
|
||||
selectedIndex,
|
||||
});
|
||||
};
|
||||
|
||||
onKeyDown = (e) => {
|
||||
const { which } = e;
|
||||
switch (which) {
|
||||
case 38:
|
||||
this.selectOffset(-1);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
break;
|
||||
case 40:
|
||||
this.selectOffset(1);
|
||||
e.stopPropagation();
|
||||
break;
|
||||
case 13:
|
||||
const { data, selectedIndex } = this.state;
|
||||
if (selectedIndex > -1) {
|
||||
this.handleItemClick(data[selectedIndex]);
|
||||
this.setState({ overlayVisible: false });
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
let me = this;
|
||||
const { labelField, clusterStatus } = this.props;
|
||||
let value = this.props.value || this.state.value;
|
||||
let displayVaue = value[labelField];
|
||||
|
@ -86,6 +116,10 @@ class DropdownSelect extends React.Component {
|
|||
<div
|
||||
className={styles.infiniteContainer}
|
||||
style={{ height: this.props.height }}
|
||||
onMouseEnter={() => {
|
||||
this.searchInputRef.focus();
|
||||
}}
|
||||
onKeyDown={this.onKeyDown}
|
||||
>
|
||||
<div
|
||||
className={styles.filter}
|
||||
|
@ -97,6 +131,9 @@ class DropdownSelect extends React.Component {
|
|||
onChange={this.handleInputChange}
|
||||
placeholder="输入集群名称查找"
|
||||
value={this.state.displayValue || ""}
|
||||
ref={(ref) => {
|
||||
this.searchInputRef = ref;
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<InfiniteScroll
|
||||
|
@ -118,7 +155,7 @@ class DropdownSelect extends React.Component {
|
|||
匹配不到集群(匹配规则为前缀匹配)
|
||||
</div>
|
||||
)}
|
||||
{(this.state.data || []).map((item) => {
|
||||
{(this.state.data || []).map((item, idx) => {
|
||||
// return <div className={styles.item}>
|
||||
// <Button key={item[labelField]}
|
||||
// onClick={() => {
|
||||
|
@ -132,6 +169,7 @@ class DropdownSelect extends React.Component {
|
|||
key={item.id}
|
||||
isSelected={item.id === value.id}
|
||||
clusterItem={item}
|
||||
isSelected={this.state.selectedIndex == idx}
|
||||
clusterStatus={cstatus}
|
||||
onClick={() => {
|
||||
this.handleItemClick(item);
|
||||
|
|
|
@ -37,6 +37,7 @@ interface props {
|
|||
initialText: string;
|
||||
paneKey: string;
|
||||
height: number;
|
||||
isActive: boolean;
|
||||
}
|
||||
|
||||
const INITIAL_PANEL_WIDTH = 50;
|
||||
|
@ -47,6 +48,7 @@ const ConsoleWrapper = ({
|
|||
saveEditorContent,
|
||||
initialText,
|
||||
paneKey,
|
||||
isActive,
|
||||
height,
|
||||
}: props) => {
|
||||
const {
|
||||
|
@ -84,6 +86,7 @@ const ConsoleWrapper = ({
|
|||
saveEditorContent={saveEditorContent}
|
||||
initialText={initialText}
|
||||
paneKey={paneKey}
|
||||
isActive={isActive}
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
|
|
|
@ -71,6 +71,7 @@ interface ConsoleInputProps {
|
|||
initialText: string | undefined;
|
||||
saveEditorContent: (content: string) => void;
|
||||
paneKey: string;
|
||||
isActive: boolean;
|
||||
height?: string;
|
||||
}
|
||||
|
||||
|
@ -87,6 +88,7 @@ const ConsoleInputUI = ({
|
|||
saveEditorContent,
|
||||
paneKey,
|
||||
height = "100%",
|
||||
isActive,
|
||||
}: ConsoleInputProps) => {
|
||||
const editorRef = useRef<HTMLDivElement | null>(null);
|
||||
const editorActionsRef = useRef<HTMLDivElement | null>(null);
|
||||
|
@ -103,6 +105,11 @@ const ConsoleInputUI = ({
|
|||
const {
|
||||
services: { settings },
|
||||
} = useServicesContext();
|
||||
// if (isActive) {
|
||||
// if (aceEditorRef.current) {
|
||||
// aceEditorRef.current.focus();
|
||||
// }
|
||||
// }
|
||||
|
||||
useEffect(() => {
|
||||
const aceEditor = ace.edit(editorRef.current!);
|
||||
|
|
|
@ -90,7 +90,7 @@ export default {
|
|||
"form.button.pre": "上一步",
|
||||
"form.button.goback": "返回",
|
||||
"form.button.reset": "重置",
|
||||
"form.label.search-keyword": "观检测",
|
||||
"form.label.search-keyword": "关键词",
|
||||
|
||||
"component.globalHeader.search": "站内搜索",
|
||||
"component.globalHeader.search.example1": "搜索提示一",
|
||||
|
|
|
@ -246,6 +246,7 @@ export default {
|
|||
updateCluster(state, { payload }) {
|
||||
let idx = state.clusterList.findIndex((item) => item.id === payload.id);
|
||||
idx > -1 && (state.clusterList[idx].name = payload.name);
|
||||
state.clusterStatus[payload.id].config.monitored = payload.monitored;
|
||||
return state;
|
||||
},
|
||||
changeClusterById(state, { payload }) {
|
||||
|
|
|
@ -16,6 +16,7 @@ import {
|
|||
} from "antd";
|
||||
import moment from "moment";
|
||||
import router from "umi/router";
|
||||
import Link from "umi/link";
|
||||
|
||||
import "@elastic/charts/dist/theme_only_light.css";
|
||||
import {
|
||||
|
@ -38,6 +39,7 @@ import NodeMetric from "./components/node_metric";
|
|||
import IndexMetric from "./components/index_metric";
|
||||
import ClusterMetric from "./components/cluster_metric";
|
||||
import QueueMetric from "./components/queue_metric";
|
||||
// import StorageMetric from "./components/storage_metric";
|
||||
import { formatter, getFormatter, getNumFormatter } from "./format";
|
||||
|
||||
const { RangePicker } = DatePicker;
|
||||
|
@ -452,8 +454,10 @@ class ClusterMonitor extends PureComponent {
|
|||
});
|
||||
let clusterAvailable = true;
|
||||
const { clusterStatus: cstatus, selectedCluster } = this.props;
|
||||
let clusterMonitored = true;
|
||||
if (cstatus && selectedCluster && cstatus[selectedCluster.id]) {
|
||||
clusterAvailable = cstatus[selectedCluster.id].available;
|
||||
clusterMonitored = cstatus[selectedCluster.id].config.monitored;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -476,10 +480,26 @@ class ClusterMonitor extends PureComponent {
|
|||
Last data collection time: {clusterStats?.timestamp}
|
||||
</div>
|
||||
</div>
|
||||
) : !clusterMonitored ? (
|
||||
<div className={styles.mask}>
|
||||
<div>
|
||||
Cluster is not monitored.{" "}
|
||||
<Button type="primary">
|
||||
<Link to={`/system/cluster/${selectedCluster.id}/edit`}>
|
||||
Go to open
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
<div className={styles.time}>
|
||||
Last data collection time: {clusterStats?.timestamp}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
<Row
|
||||
gutter={[16, { xs: 8, sm: 16, md: 24, lg: 32 }]}
|
||||
className={!clusterAvailable ? styles.metricMask : ""}
|
||||
className={
|
||||
!clusterAvailable || !clusterMonitored ? styles.metricMask : ""
|
||||
}
|
||||
>
|
||||
<Col md={2} xs={4}>
|
||||
<Statistic
|
||||
|
@ -510,7 +530,11 @@ class ClusterMonitor extends PureComponent {
|
|||
</Col>
|
||||
<Col md={2} xs={4}>
|
||||
<Statistic
|
||||
valueStyle={vstyle}
|
||||
valueStyle={{
|
||||
...vstyle,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
}}
|
||||
title={formatMessage({
|
||||
id: "cluster.monitor.summary.health",
|
||||
})}
|
||||
|
@ -649,6 +673,18 @@ class ClusterMonitor extends PureComponent {
|
|||
handleTimeChange={this.handleTimeChange}
|
||||
/>
|
||||
</Tabs.TabPane>
|
||||
{/* <Tabs.TabPane
|
||||
key="storage"
|
||||
tab={formatMessage({
|
||||
id: "cluster.monitor.queue.storage",
|
||||
})}
|
||||
>
|
||||
<StorageMetric
|
||||
clusterID={this.props.selectedCluster.id}
|
||||
timezone={timezone}
|
||||
timeRange={this.state.timeRange}
|
||||
/>
|
||||
</Tabs.TabPane> */}
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -23,10 +23,10 @@ import MetricContainer from "./metric_container";
|
|||
import _ from "lodash";
|
||||
|
||||
const gorupOrder = [
|
||||
"storage",
|
||||
"document",
|
||||
"operations",
|
||||
"latency",
|
||||
"storage",
|
||||
"document",
|
||||
"memory",
|
||||
"cache",
|
||||
];
|
||||
|
|
|
@ -23,10 +23,10 @@ import MetricContainer from "./metric_container";
|
|||
import _ from "lodash";
|
||||
|
||||
const gorupOrder = [
|
||||
"system",
|
||||
"transport",
|
||||
"operations",
|
||||
"latency",
|
||||
"system",
|
||||
"transport",
|
||||
"storage",
|
||||
"document",
|
||||
"http",
|
||||
|
|
|
@ -23,8 +23,8 @@ import MetricContainer from "./metric_container";
|
|||
import _ from "lodash";
|
||||
|
||||
const gorupOrder = [
|
||||
"thread_pool_search",
|
||||
"thread_pool_write",
|
||||
"thread_pool_search",
|
||||
"thread_pool_index",
|
||||
"thread_pool_bulk",
|
||||
"thread_pool_get",
|
||||
|
|
|
@ -436,6 +436,7 @@ export const ConsoleUI = ({
|
|||
paneKey={pane.key}
|
||||
saveEditorContent={saveEditorContent}
|
||||
initialText={pane.content}
|
||||
isActive={pane.key == tabState.activeKey}
|
||||
/>
|
||||
{/* {pane.content} */}
|
||||
</TabPane>
|
||||
|
|
|
@ -25,23 +25,36 @@ import { formatMessage } from "umi/locale";
|
|||
class ClusterForm extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
let editValue = this.props.clusterConfig.editValue;
|
||||
let needAuth = false;
|
||||
if (
|
||||
editValue.basic_auth &&
|
||||
typeof editValue.basic_auth.username !== "undefined" &&
|
||||
editValue.basic_auth.username !== ""
|
||||
) {
|
||||
needAuth = true;
|
||||
}
|
||||
|
||||
this.state = {
|
||||
confirmDirty: false,
|
||||
needAuth: needAuth,
|
||||
isLoading: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
//console.log(this.props.clusterConfig.editMode)
|
||||
const { match, dispatch, clusterConfig } = this.props;
|
||||
dispatch({
|
||||
type: "clusterConfig/fetchCluster",
|
||||
payload: {
|
||||
id: match.params.id,
|
||||
},
|
||||
}).then((res) => {
|
||||
if (res && res.found) {
|
||||
let editValue = res._source;
|
||||
let needAuth = false;
|
||||
if (
|
||||
editValue.basic_auth &&
|
||||
typeof editValue.basic_auth.username !== "undefined"
|
||||
) {
|
||||
needAuth = true;
|
||||
}
|
||||
this.setState({
|
||||
needAuth: needAuth,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
compareToFirstPassword = (rule, value, callback) => {
|
||||
|
@ -62,7 +75,7 @@ class ClusterForm extends React.Component {
|
|||
};
|
||||
|
||||
handleSubmit = () => {
|
||||
const { form, dispatch, clusterConfig } = this.props;
|
||||
const { form, dispatch, clusterConfig, history } = this.props;
|
||||
form.validateFields((errors, values) => {
|
||||
if (errors) {
|
||||
return;
|
||||
|
@ -100,7 +113,8 @@ class ClusterForm extends React.Component {
|
|||
}).then(function(rel) {
|
||||
if (rel) {
|
||||
message.success("修改成功");
|
||||
router.push("/system/cluster");
|
||||
// router.push("/system/cluster");
|
||||
history.go(-1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -256,7 +270,7 @@ class ClusterForm extends React.Component {
|
|||
})}
|
||||
>
|
||||
<Switch
|
||||
defaultChecked={this.state.needAuth}
|
||||
checked={this.state.needAuth}
|
||||
onChange={this.handleAuthChange}
|
||||
checkedChildren={<Icon type="check" />}
|
||||
unCheckedChildren={<Icon type="close" />}
|
||||
|
|
|
@ -178,7 +178,7 @@ class Index extends React.Component {
|
|||
render: (text, record) => (
|
||||
<div>
|
||||
<Link
|
||||
to="/system/cluster/edit"
|
||||
to={`/system/cluster/${record.id}/edit`}
|
||||
onClick={() => {
|
||||
this.handleEditClick(record);
|
||||
}}
|
||||
|
|
|
@ -4,6 +4,7 @@ import {
|
|||
updateClusterConfig,
|
||||
deleteClusterConfig,
|
||||
tryConnect,
|
||||
getClusterConfig,
|
||||
} from "@/services/cluster";
|
||||
import { message } from "antd";
|
||||
import { formatESSearchResult } from "@/lib/elasticsearch/util";
|
||||
|
@ -36,6 +37,23 @@ export default {
|
|||
},
|
||||
});
|
||||
},
|
||||
*fetchCluster({ payload }, { call, put, select }) {
|
||||
let res = yield call(getClusterConfig, payload);
|
||||
if (res.error) {
|
||||
message.error(res.error);
|
||||
return false;
|
||||
}
|
||||
yield put({
|
||||
type: "saveData",
|
||||
payload: {
|
||||
editValue: {
|
||||
...res._source,
|
||||
id: res._id,
|
||||
},
|
||||
},
|
||||
});
|
||||
return res;
|
||||
},
|
||||
*addCluster({ payload }, { call, put, select }) {
|
||||
let res = yield call(createClusterConfig, payload);
|
||||
if (res.error) {
|
||||
|
@ -76,20 +94,22 @@ export default {
|
|||
return false;
|
||||
}
|
||||
let { data } = yield select((state) => state.clusterConfig);
|
||||
let idx = data.findIndex((item) => {
|
||||
return item.id === res._id;
|
||||
});
|
||||
if (data) {
|
||||
let idx = data.findIndex((item) => {
|
||||
return item.id === res._id;
|
||||
});
|
||||
data[idx] = {
|
||||
...data[idx],
|
||||
...res._source,
|
||||
};
|
||||
yield put({
|
||||
type: "saveData",
|
||||
payload: {
|
||||
data,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
data[idx] = {
|
||||
...data[idx],
|
||||
...res._source,
|
||||
};
|
||||
yield put({
|
||||
type: "saveData",
|
||||
payload: {
|
||||
data,
|
||||
},
|
||||
});
|
||||
//handle global cluster logic
|
||||
|
||||
yield put({
|
||||
|
@ -97,9 +117,9 @@ export default {
|
|||
payload: {
|
||||
id: res._id,
|
||||
name: res._source.name,
|
||||
monitored: res._source.monitored,
|
||||
},
|
||||
});
|
||||
|
||||
return res;
|
||||
},
|
||||
*deleteCluster({ payload }, { call, put, select }) {
|
||||
|
|
|
@ -72,3 +72,10 @@ export async function tryConnect(params) {
|
|||
body: params,
|
||||
});
|
||||
}
|
||||
|
||||
export async function getClusterConfig(params) {
|
||||
let url = `${ESPrefix}/${params.id}`;
|
||||
return request(url, {
|
||||
method: "GET",
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue