From 94dfeb921711f8ae446fd0dcda0b69fdf31b273a Mon Sep 17 00:00:00 2001 From: liugq Date: Fri, 26 Nov 2021 16:23:45 +0800 Subject: [PATCH] cluster and command pagination and new metrics --- api/init.go | 20 +- console.yml | 8 +- .../kibana/console/components/Console.tsx | 248 +++++++----- .../console/components/ConsoleInput.tsx | 6 +- .../use_send_current_request_to_es/index.ts | 70 ++-- .../kibana/console/modules/es/index.ts | 54 +-- web/src/locales/en-US.js | 6 +- web/src/locales/en-US/cluster.js | 8 + web/src/locales/zh-CN.js | 9 +- web/src/locales/zh-CN/cluster.js | 11 + web/src/pages/Cluster/Metrics.js | 3 +- .../pages/Cluster/components/node_metric.jsx | 1 + web/src/pages/DevTool/Console.tsx | 13 +- web/src/pages/System/Cluster/Form.js | 367 ++++++++++-------- web/src/pages/System/Cluster/Index.js | 25 +- .../pages/System/Cluster/models/cluster.js | 7 +- web/src/pages/System/Command/Index.js | 24 +- .../pages/System/Command/models/command.js | 10 +- 18 files changed, 544 insertions(+), 346 deletions(-) diff --git a/api/init.go b/api/init.go index b13468ae..2011793a 100644 --- a/api/init.go +++ b/api/init.go @@ -1,9 +1,7 @@ package api import ( - log "github.com/cihub/seelog" "infini.sh/framework/core/api" - "infini.sh/framework/core/task" "infini.sh/search-center/api/index_management" "infini.sh/search-center/config" "infini.sh/search-center/service/alerting" @@ -79,14 +77,14 @@ func Init(cfg *config.AppConfig) { api.HandleAPIMethod(api.POST, "/elasticsearch/:id/alerting/_monitors/:monitorID/_acknowledge/alerts", alerting.AcknowledgeAlerts) - task.RegisterScheduleTask(task.ScheduleTask{ - Description: "sync reindex task result", - Task: func() { - err := index_management.SyncRebuildResult(cfg.Elasticsearch) - if err != nil { - log.Error(err) - } - }, - }) + //task.RegisterScheduleTask(task.ScheduleTask{ + // Description: "sync reindex task result", + // Task: func() { + // err := index_management.SyncRebuildResult(cfg.Elasticsearch) + // if err != nil { + // log.Error(err) + // } + // }, + //}) } diff --git a/console.yml b/console.yml index d60512d8..a3b0c62d 100644 --- a/console.yml +++ b/console.yml @@ -3,10 +3,14 @@ elasticsearch: - name: default enabled: true monitored: false - endpoint: http://192.168.3.188:9299 +# endpoint: https://k8es.client.bindiego.com +# basic_auth: +# username: infini +# password: BTxSrT5m33rfpF4 + endpoint: http://localhost:9200 basic_auth: username: elastic - password: ZBdkVQUUdF1Sir4X4BGB + password: infinilabs #前端 UI HTTP 配置 web: diff --git a/web/src/components/kibana/console/components/Console.tsx b/web/src/components/kibana/console/components/Console.tsx index b7853c03..26501c1c 100644 --- a/web/src/components/kibana/console/components/Console.tsx +++ b/web/src/components/kibana/console/components/Console.tsx @@ -1,32 +1,46 @@ // @ts-ignore -import React, { useRef, useMemo,useEffect, useLayoutEffect, useState } from 'react'; -import ConsoleInput from './ConsoleInput'; -import ConsoleOutput from './ConsoleOutput'; -import { Panel } from './Panel'; -import PanelsContainer from './PanelContainer'; -import { PanelContextProvider } from '../contexts/panel_context'; -import { PanelRegistry } from '../contexts/panel_context/registry'; -import './Console.scss'; -import { RequestContextProvider, useRequestReadContext } from '../contexts/request_context'; -import {EditorContextProvider} from '../contexts/editor_context/editor_context'; -import { ServicesContextProvider } from '../contexts/services_context'; -import { createHistory, History, createStorage, createSettings } from '../services'; -import { create } from '../storage/local_storage_object_client'; -import { EuiFlexGroup, EuiFlexItem,EuiCodeBlock } from '@elastic/eui'; -import {RequestStatusBar} from './request_status_bar'; -import useEventListener from '@/lib/hooks/use_event_listener'; -import {Tabs} from 'antd'; +import React, { + useRef, + useMemo, + useEffect, + useLayoutEffect, + useState, +} from "react"; +import ConsoleInput from "./ConsoleInput"; +import ConsoleOutput from "./ConsoleOutput"; +import { Panel } from "./Panel"; +import PanelsContainer from "./PanelContainer"; +import { PanelContextProvider } from "../contexts/panel_context"; +import { PanelRegistry } from "../contexts/panel_context/registry"; +import "./Console.scss"; +import { + RequestContextProvider, + useRequestReadContext, +} from "../contexts/request_context"; +import { EditorContextProvider } from "../contexts/editor_context/editor_context"; +import { ServicesContextProvider } from "../contexts/services_context"; +import { + createHistory, + History, + createStorage, + createSettings, +} from "../services"; +import { create } from "../storage/local_storage_object_client"; +import { EuiFlexGroup, EuiFlexItem, EuiCodeBlock } from "@elastic/eui"; +import { RequestStatusBar } from "./request_status_bar"; +import useEventListener from "@/lib/hooks/use_event_listener"; +import { Tabs } from "antd"; interface props { selectedCluster: any; - saveEditorContent: (content: string)=>void; + saveEditorContent: (content: string) => void; initialText: string; paneKey: string; height: number; } const INITIAL_PANEL_WIDTH = 50; -const PANEL_MIN_WIDTH = '300px'; +const PANEL_MIN_WIDTH = "300px"; const ConsoleWrapper = ({ selectedCluster, @@ -34,7 +48,7 @@ const ConsoleWrapper = ({ initialText, paneKey, height, -}:props) => { +}: props) => { const { requestInFlight: requestInProgress, lastResult: { data: requestData, error: requestError }, @@ -42,7 +56,7 @@ const ConsoleWrapper = ({ const lastDatum = requestData?.[requestData.length - 1] ?? requestError; - const calcHeight = height > 0 ? (height)+'px' : '100%'; + const calcHeight = height > 0 ? height + "px" : "100%"; // const leftBarRef = useRef(null) // const rightBarRef = useRef(null) // const [widths, setWidths] = useState(['calc(50% - 7px)', 'calc(50% - 7px)']) @@ -51,14 +65,39 @@ const ConsoleWrapper = ({ // setWidths([lp+'%', rp+'%']); // } - return ( -
-
- - - -
- +
+ + + +
+ -
-
- - - -
- -
- -
- - - - - {lastDatum?.request.header} - - - - - {lastDatum?.response.header} - - - - -
-
- +
+
+ + + +
+ +
+
+ + + + + {lastDatum?.request.header} + + + + + {lastDatum?.response.header} + + + + +
+
+ -
-
-
-
- {/*
+ timeElapsedMs: lastDatum.response.timeMs, + requestHeader: lastDatum.request.header, + responseHeader: lastDatum.response.header, + } + : undefined + } + /> +
+ + +
+ {/*
*/} -
+
); }; -const Console = (params:props) => { - +const Console = (params: props) => { const registryRef = useRef(new PanelRegistry()); // const [consoleInputKey] = useMemo(()=>{ // return [selectedCluster.id + '-console-input']; // },[selectedCluster]) - const {storage, history, objectStorageClient, settings} = useMemo(()=>{ + const { storage, history, objectStorageClient, settings } = useMemo(() => { const storage = createStorage({ engine: window.localStorage, - prefix: 'sense:', + prefix: "sense:", }); const history: History = createHistory({ storage }); const objectStorageClient = create(storage); - const settings = createSettings({storage}); - return {storage, history, objectStorageClient, settings}; - }, []) - return ( - - - + const settings = createSettings({ storage }); + return { storage, history, objectStorageClient, settings }; + }, []); + return ( + + + + - + - ); - -} + ); +}; export default Console; - diff --git a/web/src/components/kibana/console/components/ConsoleInput.tsx b/web/src/components/kibana/console/components/ConsoleInput.tsx index 0a472edb..c30398cd 100644 --- a/web/src/components/kibana/console/components/ConsoleInput.tsx +++ b/web/src/components/kibana/console/components/ConsoleInput.tsx @@ -166,8 +166,10 @@ const ConsoleInputUI = ({ }; }, []); useEffect(() => { - retrieveAutoCompleteInfo(settings, settings.getAutocomplete(), clusterID); - aceEditorRef.current && (aceEditorRef.current["clusterID"] = clusterID); + if (clusterID) { + retrieveAutoCompleteInfo(settings, settings.getAutocomplete(), clusterID); + aceEditorRef.current && (aceEditorRef.current["clusterID"] = clusterID); + } }, [clusterID]); const handleSaveAsCommonCommand = async () => { diff --git a/web/src/components/kibana/console/hooks/use_send_current_request_to_es/index.ts b/web/src/components/kibana/console/hooks/use_send_current_request_to_es/index.ts index f1687e42..d44f53ca 100644 --- a/web/src/components/kibana/console/hooks/use_send_current_request_to_es/index.ts +++ b/web/src/components/kibana/console/hooks/use_send_current_request_to_es/index.ts @@ -30,58 +30,64 @@ * GitHub history for details. */ -import { useCallback } from 'react'; -import { sendRequestToES } from './send_request_to_es'; -import { instance as registry } from '../../contexts/editor_context/editor_registry'; -import { useRequestActionContext } from '../../contexts/request_context'; -import { useServicesContext } from '../../contexts/services_context'; -import {getCommand} from '../../modules/mappings/mappings'; -import {useEditorReadContext} from '../../contexts/editor_context'; +import { useCallback } from "react"; +import { sendRequestToES } from "./send_request_to_es"; +import { instance as registry } from "../../contexts/editor_context/editor_registry"; +import { useRequestActionContext } from "../../contexts/request_context"; +import { useServicesContext } from "../../contexts/services_context"; +import { getCommand } from "../../modules/mappings/mappings"; +import { useEditorReadContext } from "../../contexts/editor_context"; -function buildRawCommonCommandRequest(cmd:any){ - const {requests} = cmd._source; - const strReqs = requests.map((req: any)=>{ - const {method, path, body} = req; +function buildRawCommonCommandRequest(cmd: any) { + const { requests } = cmd._source; + const strReqs = requests.map((req: any) => { + const { method, path, body } = req; return `${method} ${path}\n${body}`; - }) - return strReqs.join('\n'); + }); + return strReqs.join("\n"); } export const useSendCurrentRequestToES = () => { const dispatch = useRequestActionContext(); - const { services: { history }, clusterID } = useServicesContext(); - const {sensorEditor:editor} = useEditorReadContext(); + const { + services: { history }, + clusterID, + } = useServicesContext(); + const { sensorEditor: editor } = useEditorReadContext(); return useCallback(async () => { try { // const editor = registry.getInputEditor(); - if(!editor) return + if (!editor) return; const requests = await editor.getRequestsInRange(); if (!requests.length) { - console.log('No request selected. Select a request by placing the cursor inside it.'); + console.log( + "No request selected. Select a request by placing the cursor inside it." + ); return; } - const {url, method, data} = requests[0]; - if(method === 'LOAD'){ - const rawUrl = data[0]? data[0].slice(4).trim(): url; + const { url, method, data } = requests[0]; + if (method === "LOAD") { + const rawUrl = data[0] ? data[0].slice(4).trim() : url; const cmd = getCommand(rawUrl); - // const curPostion = editor.currentReqRange //(editor.getCoreEditor().getCurrentPosition()); - const lineNumber = editor.getCoreEditor().getCurrentPosition().lineNumber; - let crange = await editor.getRequestRange(lineNumber) - const rawRequest = buildRawCommonCommandRequest(cmd) + // const curPostion = editor.currentReqRange //(editor.getCoreEditor().getCurrentPosition()); + const lineNumber = editor.getCoreEditor().getCurrentPosition() + .lineNumber; + let crange = await editor.getRequestRange(lineNumber); + const rawRequest = buildRawCommonCommandRequest(cmd); await editor.getCoreEditor().replaceRange(crange as any, rawRequest); // await editor.autoIndent(); // editor.getCoreEditor().getContainer().focus(); // crange = await editor.getRequestRange(lineNumber) - + // editor.getCoreEditor().moveCursorToPosition({ // ...crange?.end as any, // // column: editor.getCoreEditor().getLineValue(lineNumber).length + 1, // }); - + return; } - dispatch({ type: 'sendRequest', payload: undefined }); + dispatch({ type: "sendRequest", payload: undefined }); // @ts-ignore const results = await sendRequestToES({ requests, clusterID }); @@ -104,20 +110,20 @@ export const useSendCurrentRequestToES = () => { // } // dispatch({ - type: 'requestSuccess', + type: "requestSuccess", payload: { data: results, }, }); } catch (e) { - if (e?.response) { + if (e) { dispatch({ - type: 'requestFail', - payload: e, + type: "requestSuccess", + payload: { data: [e] }, }); } else { dispatch({ - type: 'requestFail', + type: "requestFail", payload: undefined, }); } diff --git a/web/src/components/kibana/console/modules/es/index.ts b/web/src/components/kibana/console/modules/es/index.ts index 90c4c02d..f5fd9a9c 100644 --- a/web/src/components/kibana/console/modules/es/index.ts +++ b/web/src/components/kibana/console/modules/es/index.ts @@ -31,10 +31,10 @@ */ // @ts-ignore -import $ from 'jquery'; +import $ from "jquery"; // @ts-ignore -import { stringify } from 'query-string'; -import {pathPrefix, ESPrefix} from '@/services/common'; +import { stringify } from "query-string"; +import { pathPrefix, ESPrefix } from "@/services/common"; interface SendOptions { asSystemRequest?: boolean; @@ -48,14 +48,14 @@ export function getVersion() { } export function getContentType(body: unknown) { - if (!body) return 'text/plain'; - return 'application/json'; + if (!body) return "text/plain"; + return "application/json"; } -export function extractClusterIDFromURL(){ +export function extractClusterIDFromURL() { const matchs = location.hash.match(/\/elasticsearch\/(\w+)\/?/); - if(!matchs){ - return '' + if (!matchs) { + return ""; } return matchs[1]; } @@ -84,16 +84,20 @@ export function send( data, contentType: getContentType(data), cache: false, - crossDomain: true, - type: 'POST', - dataType: 'json', // disable automatic guessing + // crossDomain: true, + type: "POST", + dataType: "json", // disable automatic guessing }; $.ajax(options).then( (responseData: any, textStatus: string, jqXHR: unknown) => { wrappedDfd.resolveWith({}, [responseData, textStatus, jqXHR]); }, - ((jqXHR: { status: number; responseText: string }, textStatus: string, errorThrown: Error) => { + (( + jqXHR: { status: number; responseText: string }, + textStatus: string, + errorThrown: Error + ) => { if (jqXHR.status === 0) { jqXHR.responseText = "\n\nFailed to connect to Console's backend.\nPlease check the server is up and running"; @@ -106,26 +110,26 @@ export function send( export function queryCommonCommands(title?: string) { let url = `${pathPrefix}/elasticsearch/command`; - if(title){ - url +=`?title=${title}` + if (title) { + url += `?title=${title}`; } return fetch(url, { - method: 'GET', - }) + method: "GET", + }); } export function constructESUrl(baseUri: string, path: string) { - baseUri = baseUri.replace(/\/+$/, ''); - path = path.replace(/^\/+/, ''); - return baseUri + '/' + path; + baseUri = baseUri.replace(/\/+$/, ""); + path = path.replace(/^\/+/, ""); + return baseUri + "/" + path; } export function saveCommonCommand(params: any) { return fetch(`${pathPrefix}/elasticsearch/command`, { - method: 'POST', + method: "POST", body: JSON.stringify(params), - headers:{ - 'content-type': 'application/json' - } - }) -} \ No newline at end of file + headers: { + "content-type": "application/json", + }, + }); +} diff --git a/web/src/locales/en-US.js b/web/src/locales/en-US.js index 3a13cdcb..36ea53c4 100644 --- a/web/src/locales/en-US.js +++ b/web/src/locales/en-US.js @@ -207,8 +207,12 @@ export default { "Storage Usage", "dashboard.charts.title.cluster_storage.axis.available_storage": "Storage Available", - "dashboard.charts.title.cluster_documents.axis.documents": "Documents Count", + "dashboard.charts.title.cluster_documents.axis.count": "Documents Count", + "dashboard.charts.title.cluster_documents.axis.deleted": "Docmuents Deleted", + "dashboard.charts.title.cluster_indices.axis.count": "Indices Count", "dashboard.charts.title.cluster_documents.axis.counts": "Shards Count", + "dashboard.charts.title.node_count.axis.count": "Nodes Count", + "dashboard.charts.title.cluster_health.axis.percent": "Health Percent", "app.login.message-invalid-credentials": "Invalid username or password(admin/888888)", diff --git a/web/src/locales/en-US/cluster.js b/web/src/locales/en-US/cluster.js index 41c2d089..44e5014e 100644 --- a/web/src/locales/en-US/cluster.js +++ b/web/src/locales/en-US/cluster.js @@ -76,6 +76,13 @@ export default { "cluster.metrics.node.axis.docs_count.title": "Document Count", "cluster.metrics.node.axis.index_storage.title": "Indices Storage", "cluster.metrics.node.axis.jvm_heap_used_percent.title": "JVM Heap Usage", + "cluster.metrics.node.axis.os_cpu.title": "OS CPU Percent", + "cluster.metrics.node.axis.os_used_mem.title": "OS Mem Usage", + "cluster.metrics.node.axis.indexing_pressure_memory.title": + "Indexing Pressure", + "cluster.metrics.node.axis.jvm_used_heap.title": "JVM Used Heap", + "cluster.metrics.node.axis.jvm_young_gc_rate.title": "Young GC Rate", + "cluster.metrics.node.axis.jvm_young_gc_latency.title": "Young GC Latency", "cluster.metrics.index.axis.index_storage.title": "Index Storage", "cluster.metrics.index.axis.doc_count.title": "Document count", @@ -105,4 +112,5 @@ export default { "cluster.metrics.group.http": "Http Traffic", "cluster.metrics.group.memory": "Memory", "cluster.metrics.group.cache": "Cache", + "cluster.metrics.group.JVM": "JVM", }; diff --git a/web/src/locales/zh-CN.js b/web/src/locales/zh-CN.js index 52eff973..27dee964 100644 --- a/web/src/locales/zh-CN.js +++ b/web/src/locales/zh-CN.js @@ -6,7 +6,8 @@ export default { "navBar.lang": "语言", "layout.user.appname": "极限数据管理后台", - "layout.user.appslogon": "极限科技的数据管理平台是东半球最好用的实时数据管理平台", + "layout.user.appslogon": + "极限科技的数据管理平台是东半球最好用的实时数据管理平台", "app.setting.appname": "极限数据中心", "layout.user.link.help": "帮助", @@ -209,8 +210,12 @@ export default { "dashboard.charts.title.cluster_storage.axis.indices_storage": "索引存储", "dashboard.charts.title.cluster_storage.axis.available_storage": "剩余存储", + "dashboard.charts.title.node_count.axis.count": "节点数", + "dashboard.charts.title.cluster_health.axis.percent": "健康状态百分比", - "dashboard.charts.title.cluster_documents.axis.documents": "文档总数", + "dashboard.charts.title.cluster_documents.axis.count": "文档总数", + "dashboard.charts.title.cluster_documents.axis.deleted": "文档删除数", + "dashboard.charts.title.cluster_indices.axis.count": "索引总数", "dashboard.charts.title.cluster_documents.axis.counts": "分片总数", "app.login.message-invalid-credentials": "账户或密码错误(admin/888888)", diff --git a/web/src/locales/zh-CN/cluster.js b/web/src/locales/zh-CN/cluster.js index 599632ab..5771ecaa 100644 --- a/web/src/locales/zh-CN/cluster.js +++ b/web/src/locales/zh-CN/cluster.js @@ -77,6 +77,16 @@ export default { "cluster.metrics.node.axis.docs_count.title": "Document Count", "cluster.metrics.node.axis.index_storage.title": "Indices Storage", "cluster.metrics.node.axis.jvm_heap_used_percent.title": "JVM Heap Usage", + "cluster.metrics.node.axis.os_cpu.title": "OS CPU Percent", + "cluster.metrics.node.axis.os_used_mem.title": "OS Mem Usage", + "cluster.metrics.node.axis.indexing_pressure_memory.title": + "Indexing Pressure", + "cluster.metrics.node.axis.jvm_used_heap.title": "JVM Used Heap", + "cluster.metrics.node.axis.jvm_young_gc_rate.title": "Young GC Rate", + "cluster.metrics.node.axis.jvm_young_gc_latency.title": "Young GC Latency", + "cluster.metrics.node.axis.jvm_mem_young_used.title": "Pools Young Used", + "cluster.metrics.node.axis.jvm_mem_young_peak_used.title": + "Pools Young Peak Used", "cluster.metrics.index.axis.index_storage.title": "Index Storage", "cluster.metrics.index.axis.doc_count.title": "Document count", @@ -106,4 +116,5 @@ export default { "cluster.metrics.group.http": "Http Traffic", "cluster.metrics.group.memory": "Memory", "cluster.metrics.group.cache": "Cache", + "cluster.metrics.group.JVM": "JVM", }; diff --git a/web/src/pages/Cluster/Metrics.js b/web/src/pages/Cluster/Metrics.js index 4c7d507f..d46193ec 100644 --- a/web/src/pages/Cluster/Metrics.js +++ b/web/src/pages/Cluster/Metrics.js @@ -453,7 +453,7 @@ class ClusterMonitor extends PureComponent { }); let clusterAvailable = true; const { clusterStatus: cstatus, selectedCluster } = this.props; - if (cstatus && selectedCluster) { + if (cstatus && selectedCluster && cstatus[selectedCluster.id]) { clusterAvailable = cstatus[selectedCluster.id].available; } @@ -674,6 +674,7 @@ class ClusterMonitor extends PureComponent { id={item.metric.label} groupId={item.metric.group} timeZone={timezone} + color={item.color} xScaleType={ScaleType.Time} yScaleType={ScaleType.Linear} xAccessor={0} diff --git a/web/src/pages/Cluster/components/node_metric.jsx b/web/src/pages/Cluster/components/node_metric.jsx index 2b34caac..395fe4ab 100644 --- a/web/src/pages/Cluster/components/node_metric.jsx +++ b/web/src/pages/Cluster/components/node_metric.jsx @@ -28,6 +28,7 @@ const gorupOrder = [ "latency", "storage", "http", + "JVM", "memory", "cache", ]; diff --git a/web/src/pages/DevTool/Console.tsx b/web/src/pages/DevTool/Console.tsx index f92c7b52..a770e6c7 100644 --- a/web/src/pages/DevTool/Console.tsx +++ b/web/src/pages/DevTool/Console.tsx @@ -10,6 +10,7 @@ import { useEffect, useMemo, useRef, + useLayoutEffect, } from "react"; import { useLocalStorage } from "@/lib/hooks/storage"; import { setClusterID } from "../../components/kibana/console/modules/mappings/mappings"; @@ -116,6 +117,9 @@ const consoleTabReducer = (state: any, action: any) => { ...state, order: action.payload.order, }; + break; + case "init": + newState = action.payload; default: } // setLocalState(newState); @@ -199,11 +203,16 @@ export const ConsoleUI = ({ }); if (panes.length == 0) { - removeLocalState(); + //reset tabState + dispatch({ + type: "init", + payload: initialDefaultState(), + }); + //removeLocalState(); return; } setLocalState(tabState); - }, [tabState, clusterMap]); + }, [tabState, clusterMap, dispatch]); const saveEditorContent = useCallback( (content) => { diff --git a/web/src/pages/System/Cluster/Form.js b/web/src/pages/System/Cluster/Form.js index 1d71310d..9722bbbd 100644 --- a/web/src/pages/System/Cluster/Form.js +++ b/web/src/pages/System/Cluster/Form.js @@ -1,29 +1,43 @@ -import React from 'react'; -import {Card, Form, Icon, Input, InputNumber, Button, Switch, message, Spin} from 'antd'; -import router from 'umi/router'; +import React from "react"; +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'; +import styles from "./Form.less"; +import { connect } from "dva"; +import NewCluster from "./Step"; +import PageHeaderWrapper from "@/components/PageHeaderWrapper"; @Form.create() -@connect(({clusterConfig}) =>({ - clusterConfig +@connect(({ clusterConfig }) => ({ + clusterConfig, })) -class ClusterForm extends React.Component{ +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 !== ''){ + 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) @@ -31,8 +45,8 @@ class ClusterForm extends React.Component{ compareToFirstPassword = (rule, value, callback) => { const { form } = this.props; - if (value && value !== form.getFieldValue('password')) { - callback('Two passwords that you enter is inconsistent!'); + if (value && value !== form.getFieldValue("password")) { + callback("Two passwords that you enter is inconsistent!"); } else { callback(); } @@ -41,16 +55,16 @@ class ClusterForm extends React.Component{ validateToNextPassword = (rule, value, callback) => { const { form } = this.props; if (value && this.state.confirmDirty) { - form.validateFields(['confirm'], { force: true }); + form.validateFields(["confirm"], { force: true }); } callback(); }; - handleSubmit = () =>{ - const {form, dispatch, clusterConfig} = this.props; + handleSubmit = () => { + const { form, dispatch, clusterConfig } = this.props; form.validateFields((errors, values) => { - if(errors){ - return + if (errors) { + return; } //console.log(values); let newVals = { @@ -64,76 +78,78 @@ class ClusterForm extends React.Component{ enabled: values.enabled, monitored: values.monitored, version: values.version, - schema: values.isTLS === true ? 'https': 'http', + schema: values.isTLS === true ? "https" : "http", // order: values.order, - } - if(clusterConfig.editMode === 'NEW') { + }; + if (clusterConfig.editMode === "NEW") { dispatch({ - type: 'clusterConfig/addCluster', + type: "clusterConfig/addCluster", payload: newVals, - }).then(function (rel){ - if(rel){ - message.success("添加成功") - router.push('/system/cluster'); + }).then(function(rel) { + if (rel) { + message.success("添加成功"); + router.push("/system/cluster"); } }); - }else{ + } else { newVals.id = clusterConfig.editValue.id; dispatch({ - type: 'clusterConfig/updateCluster', + type: "clusterConfig/updateCluster", payload: newVals, - }).then(function (rel){ - if(rel){ - message.success("修改成功") - router.push('/system/cluster'); + }).then(function(rel) { + if (rel) { + message.success("修改成功"); + router.push("/system/cluster"); } }); } - }) - } + }); + }; handleAuthChange = (val) => { this.setState({ needAuth: val, - }) - } + }); + }; - tryConnect = async ()=>{ - const {dispatch, form} = this.props; - const values = await form.validateFields((errors, values) => { - if(errors){ + 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 + + if (!values) { + return; } - this.setState({isLoading: true}) + let newVals = { + name: values.name, + host: values.host, + basic_auth: { + username: values.username, + password: values.password, + }, + schema: values.isTLS === true ? "https" : "http", + }; + this.setState({ isLoading: true }); const res = await dispatch({ - type: 'clusterConfig/doTryConnect', - payload: values + type: "clusterConfig/doTryConnect", + payload: newVals, }); - if(res){ - message.success('连接成功!') + if (res) { + message.success("连接成功!"); form.setFieldsValue({ - version: res.version - }) + version: res.version, + }); } - this.setState({isLoading: false}) - } + this.setState({ isLoading: false }); + }; render() { - const {getFieldDecorator} = this.props.form; + const { getFieldDecorator } = this.props.form; const formItemLayout = { labelCol: { xs: { span: 24 }, @@ -156,95 +172,105 @@ class ClusterForm extends React.Component{ }, }, }; - const {editValue, editMode} = this.props.clusterConfig; + const { editValue, editMode } = this.props.clusterConfig; return ( - - { - router.push('/system/cluster'); - }}>返回]} - > - -
- - {getFieldDecorator('name', { - initialValue: editValue.name, - rules: [ - { - required: true, - message: 'Please input cluster name!', - }, - ], - })()} - - - {getFieldDecorator('host', { - initialValue: editValue.host, - rules: [ - { - type: 'string', - pattern: /^[\w\.]+\:\d+$/, //(https?:\/\/)? - message: '请输入域名或 IP 地址和端口号', - }, - { - required: true, - message: '请输入域名或 IP 地址和端口号!', - }, - ], - })()} - - - {getFieldDecorator('version', { - initialValue: editValue.version, - rules: [ - ], - })()} - - - {getFieldDecorator('isTLS', { - initialValue: editValue?.schema === "https", - })( - } - unCheckedChildren={} - />)} - - - } - unCheckedChildren={} - /> - - {this.state.needAuth === true ? (
- - {getFieldDecorator('username', { - initialValue: editValue.basic_auth?.username, - rules: [ - ], - })()} - - - {getFieldDecorator('password', { - initialValue: editValue.basic_auth?.password, - rules: [ - ], - })()} - -
):''} - {/* + + { + router.push("/system/cluster"); + }} + > + 返回 + , + ]} + > + + + + {getFieldDecorator("name", { + initialValue: editValue.name, + rules: [ + { + required: true, + message: "Please input cluster name!", + }, + ], + })()} + + + {getFieldDecorator("host", { + initialValue: editValue.host, + rules: [ + { + type: "string", + pattern: /^[\w\.]+\:\d+$/, //(https?:\/\/)? + message: "请输入域名或 IP 地址和端口号", + }, + { + required: true, + message: "请输入域名或 IP 地址和端口号!", + }, + ], + })()} + + + {getFieldDecorator("version", { + initialValue: editValue.version, + rules: [], + })()} + + + {getFieldDecorator("isTLS", { + initialValue: editValue?.schema === "https", + })( + } + unCheckedChildren={} + /> + )} + + + } + unCheckedChildren={} + /> + + {this.state.needAuth === true ? ( +
+ + {getFieldDecorator("username", { + initialValue: editValue.basic_auth?.username, + rules: [], + })()} + + + {getFieldDecorator("password", { + initialValue: editValue.basic_auth?.password, + rules: [], + })()} + +
+ ) : ( + "" + )} + {/* {getFieldDecorator('order', { initialValue: editValue.order || 0, })()} */} - - {getFieldDecorator('description', { - initialValue: editValue.description, - })()} - - {/* + + {getFieldDecorator("description", { + initialValue: editValue.description, + })()} + + {/* {getFieldDecorator('enabled', { valuePropName: 'checked', initialValue: typeof editValue.enabled === 'undefined' ? true: editValue.enabled, @@ -253,29 +279,34 @@ class ClusterForm extends React.Component{ unCheckedChildren={} />)} */} - - {getFieldDecorator('monitored', { - valuePropName: 'checked', - initialValue: typeof editValue.monitored === 'undefined' ? true: editValue.monitored, - })(} - unCheckedChildren={} - />)} - - - - - - -
-
+ + {getFieldDecorator("monitored", { + valuePropName: "checked", + initialValue: + typeof editValue.monitored === "undefined" + ? true + : editValue.monitored, + })( + } + unCheckedChildren={} + /> + )} + + + + + + +
+
- ) + ); } } -export default ClusterForm; +export default ClusterForm; diff --git a/web/src/pages/System/Cluster/Index.js b/web/src/pages/System/Cluster/Index.js index 792e9761..d283371f 100644 --- a/web/src/pages/System/Cluster/Index.js +++ b/web/src/pages/System/Cluster/Index.js @@ -214,13 +214,17 @@ class Index extends React.Component { }); }; componentDidMount() { - this.fetchData({}); + const { pageSize } = this.props.clusterConfig; + this.fetchData({ + size: pageSize, + }); } handleSearchClick = () => { const { form } = this.props; this.fetchData({ name: form.getFieldValue("name"), + current: 1, }); }; @@ -268,6 +272,17 @@ class Index extends React.Component { }); }; + handleTableChange = (pagination, filters, sorter, extra) => { + const { form } = this.props; + const { pageSize, current } = pagination; + this.fetchData({ + from: (current - 1) * pageSize, + size: pageSize, + name: form.getFieldValue("name"), + current, + }); + }; + render() { const { getFieldDecorator } = this.props.form; const formItemLayout = { @@ -275,7 +290,7 @@ class Index extends React.Component { wrapperCol: { span: 14 }, style: { marginBottom: 0 }, }; - const { data } = this.props.clusterConfig; + const { total, data, pageSize, current } = this.props.clusterConfig; return ( diff --git a/web/src/pages/System/Cluster/models/cluster.js b/web/src/pages/System/Cluster/models/cluster.js index e08af381..3fcaf0da 100644 --- a/web/src/pages/System/Cluster/models/cluster.js +++ b/web/src/pages/System/Cluster/models/cluster.js @@ -13,6 +13,8 @@ export default { state: { editMode: "", editValue: {}, + pageSize: 20, + current: 1, }, effects: { *fetchClusterList({ payload }, { call, put, select }) { @@ -28,7 +30,10 @@ export default { // } yield put({ type: "saveData", - payload: res, + payload: { + ...res, + current: payload.current, + }, }); }, *addCluster({ payload }, { call, put, select }) { diff --git a/web/src/pages/System/Command/Index.js b/web/src/pages/System/Command/Index.js index 76875201..588bb8f0 100644 --- a/web/src/pages/System/Command/Index.js +++ b/web/src/pages/System/Command/Index.js @@ -113,7 +113,9 @@ class Index extends PureComponent { ]; componentDidMount() { - this.fetchData(); + this.fetchData({ + current: 1, + }); } fetchData = (params = {}) => { @@ -159,6 +161,7 @@ class Index extends PureComponent { keyword: fieldsValue.keyword, from: 0, size: 10, + current: 1, }); this.setState({ searchKey: fieldsValue.keyword, @@ -231,9 +234,19 @@ class Index extends PureComponent { }, }); }; + handleTableChange = (pagination, filters, sorter, extra) => { + const { form } = this.props; + const { pageSize, current } = pagination; + this.fetchData({ + from: (current - 1) * pageSize, + size: pageSize, + keyword: form.getFieldValue("keyword"), + current, + }); + }; render() { - const { data, total } = this.props.command; + const { data, total, pageSize, current } = this.props.command; const { modalVisible, updateModalVisible, @@ -301,7 +314,12 @@ class Index extends PureComponent { bordered dataSource={data} rowKey="id" - pagination={{ pageSize: 10 }} + pagination={{ + pageSize: pageSize, + current: current, + total: total?.value || total, + }} + onChange={this.handleTableChange} columns={this.columns} /> diff --git a/web/src/pages/System/Command/models/command.js b/web/src/pages/System/Command/models/command.js index 594a3222..c287f29a 100644 --- a/web/src/pages/System/Command/models/command.js +++ b/web/src/pages/System/Command/models/command.js @@ -4,7 +4,10 @@ import { formatESSearchResult } from "@/lib/elasticsearch/util"; export default { namespace: "command", - state: {}, + state: { + pageSize: 20, + current: 1, + }, effects: { *fetchCommandList({ payload }, { call, put, select }) { let res = yield call(searchCommand, payload); @@ -15,7 +18,10 @@ export default { res = formatESSearchResult(res); yield put({ type: "saveData", - payload: res, + payload: { + ...res, + current: payload.current, + }, }); },