diff --git a/web/src/components/Overview/Header/index.tsx b/web/src/components/Overview/Header/index.tsx index dcdbed22..97ed32b1 100644 --- a/web/src/components/Overview/Header/index.tsx +++ b/web/src/components/Overview/Header/index.tsx @@ -1,7 +1,7 @@ import { HealthStatusCircle } from "@/components/infini/health_status_circle"; import request from "@/utils/request"; import { AutoComplete, Input, Select, Button, Radio, Icon } from "antd"; -import { Fragment, useState } from "react"; +import { Fragment, useEffect, useMemo, useRef, useState } from "react"; import Filters from "./Filters"; import styles from "./index.scss"; import CardViewSvg from "@/components/Icons/CardView"; @@ -53,8 +53,10 @@ export default (props: IProps) => { showStatus = false, showTags = false, getOptionMeta, + getSearch }, getExtra, + defaultSearchValue, } = props; const [searchValue, setSearchValue] = useState(""); @@ -63,10 +65,18 @@ export default (props: IProps) => { const [searchOpen, setSearchOpen] = useState(false); + const firstInitRef = useRef(true) + + useEffect(() => { + if (defaultSearchValue) { + setSearchValue(defaultSearchValue) + } + }, [defaultSearchValue]) + function renderOption(item) { - const { title, desc, right, tags, status } = getOptionMeta(item); + const { title, desc, right, tags, status, text } = getOptionMeta(item); return ( - +
@@ -132,6 +142,14 @@ export default (props: IProps) => { const activeColor = "#1890ff"; + const autoCompleteProps = useMemo(() => { + if (defaultSearchValue && firstInitRef.current) { + firstInitRef.current = false + return { value: defaultSearchValue } + } + return {} + }, [defaultSearchValue, searchValue]) + return ( <>
@@ -180,12 +198,24 @@ export default (props: IProps) => { onSearchChange(option.props.text)} + onSelect={(value, option) => { + if (getSearch) { + const search = getSearch(option.props.item) + if (search) { + setSearchValue(search.keyword) + onSearchChange(search.keyword) + if (search.filter) { + onFacetChange(search.filter) + } + } + } + }} onSearch={handleSearch} optionLabelProp="text" getPopupContainer={(trigger) => trigger.parentElement} open={searchOpen} onDropdownVisibleChange={setSearchOpen} + {...autoCompleteProps} > { throw new Error(); } } - const [queryParams, dispatch] = useReducer(reducer, initialQueryParams); + const [queryParams, dispatch] = useReducer(reducer, { + from: param?.from || initialQueryParams.from, + size: param?.size || initialQueryParams.size , + keyword: param?.keyword || initialQueryParams.keyword + }); const { run, loading, value } = useFetch( searchAction, @@ -166,10 +170,10 @@ export default forwardRef((props: IProps, ref: any) => { }, filter: param?.filters || {}, sort: param?.sort || [], - search_field: searchField, + search_field: searchField || searchAutoCompleteConfig?.defaultSearchField, }, }, - [queryParams, param?.filters, param?.sort] + [queryParams, param?.filters, param?.sort, aggsParams, searchHighlightFields, searchField, searchAutoCompleteConfig?.defaultSearchField] ); const result = (value as any)?.hits || {}; @@ -220,7 +224,7 @@ export default forwardRef((props: IProps, ref: any) => { return; } - fetchListInfo(); + // fetchListInfo(); }, [value]); useEffect(() => { @@ -248,7 +252,10 @@ export default forwardRef((props: IProps, ref: any) => { setSearchField(value); setParam({ ...param, search_field: value }); }} - onSearchChange={(value) => dispatch({ type: "search", value })} + defaultSearchValue={queryParams?.keyword} + onSearchChange={(value) => { + dispatch({ type: "search", value }) + }} onFacetChange={onFacetChange} dispalyType={dispalyTypeObj[currentTab]} onDisplayTypeChange={onDisplayTypeChange} @@ -278,6 +285,7 @@ export default forwardRef((props: IProps, ref: any) => { return ( { drawRef.current?.open(); }} onChangeFacet={onFacetChange} + infoAction={infoAction} + parentLoading={loading} /> ); }} diff --git a/web/src/pages/Platform/Overview/Cluster/Card/index.js b/web/src/pages/Platform/Overview/Cluster/Card/index.js index 273f1edb..3e1aef8e 100644 --- a/web/src/pages/Platform/Overview/Cluster/Card/index.js +++ b/web/src/pages/Platform/Overview/Cluster/Card/index.js @@ -1,5 +1,5 @@ import React, { useState, useEffect } from "react"; -import { Icon, Tooltip } from "antd"; +import { Icon, Spin, Tooltip } from "antd"; import TinyArea from "@/components/infini/TinyArea"; import { Pie } from "@/components/Charts"; import { formatter } from "@/utils/format"; @@ -10,12 +10,39 @@ import "./index.scss"; import { Providers, ProviderIcon } from "@/lib/providers"; import { formatMessage } from "umi/locale"; import { SearchEngineIcon } from "@/lib/search_engines"; +import request from "@/utils/request"; export default (props) => { + const { infoAction, id, parentLoading } = props; const clusterID = props.data?._id; const metadata = props.data._source || {}; - const summary = props.info.summary || {}; - const metrics = props.info.metrics || {}; + + const [info, setInfo] = useState({}); + const [loading, setLoading] = useState(false) + + const fetchListInfo = async (id) => { + if (!id) return + setLoading(true) + const res = await request(infoAction, { + method: "POST", + body: [id], + ignoreTimeout: true + }, false, false); + if (res) { + setInfo(res[id] || {}); + } + setLoading(false) + }; + + useEffect(() => { + if (!parentLoading) { + fetchListInfo(id) + } + }, [id, parentLoading]) + + const summary = info?.summary || {}; + const metrics = info?.metrics || {}; + const fs_total_in_bytes = summary?.fs?.total_in_bytes || 0; const fs_available_in_bytes = summary?.fs?.available_in_bytes || 0; const fs_used_in_bytes = fs_total_in_bytes - fs_available_in_bytes; @@ -84,7 +111,9 @@ export default (props) => { const healthStatus = metadata.labels?.health_status; return ( -
+ + +
props.onSelect()} @@ -243,5 +272,6 @@ export default (props) => {
+ ); }; diff --git a/web/src/pages/Platform/Overview/Cluster/index.tsx b/web/src/pages/Platform/Overview/Cluster/index.tsx index 3f377573..5a9341dd 100644 --- a/web/src/pages/Platform/Overview/Cluster/index.tsx +++ b/web/src/pages/Platform/Overview/Cluster/index.tsx @@ -41,15 +41,20 @@ export default () => { searchAutoCompleteConfig={{ showStatus: true, showTags: true, + defaultSearchField: 'name', + getSearch: (item) => ({ + keyword: item?._source?.name, + }), getOptionMeta: (item) => ({ title: item.highlight?.name || item._source?.name, desc: item.highlight?.version || item._source?.version, right: item.highlight?.host || item._source?.host, tags: item._source?.tags, status: item._source.labels?.health_status, + text: item?._source?.name }), }} - infoAction={`${ESPrefix}/cluster/info`} + infoAction={`${ESPrefix}/cluster/info?timeout=120s`} facetLabels={facetLabels} aggsParams={aggsParams} sideSorterOptions={sideSorterOptions} diff --git a/web/src/pages/Platform/Overview/Indices/Card/index.js b/web/src/pages/Platform/Overview/Indices/Card/index.js index 79da6a5a..e4d6af55 100644 --- a/web/src/pages/Platform/Overview/Indices/Card/index.js +++ b/web/src/pages/Platform/Overview/Indices/Card/index.js @@ -1,5 +1,5 @@ import React, { useState, useEffect } from "react"; -import { Icon, Tooltip } from "antd"; +import { Icon, Spin, Tooltip } from "antd"; import TinyArea from "@/components/infini/TinyArea"; import { Pie } from "@/components/Charts"; import { formatter } from "@/utils/format"; @@ -9,11 +9,11 @@ import moment from "moment"; import { formatUtcTimeToLocal } from "@/utils/utils"; import { FieldFilterFacet } from "@/components/Overview/List/FieldFilterFacet"; import "./index.scss"; +import request from "@/utils/request"; export default (props) => { + const { infoAction, id, parentLoading } = props; const metadata = props.data._source?.metadata || {}; - const summary = props.info?.summary || {}; - const metrics = props.info?.metrics || {}; const timestamp = props.data._source?.timestamp ? formatUtcTimeToLocal(props.data._source?.timestamp) : "N/A"; @@ -27,6 +27,32 @@ export default (props) => { return items; }; + const [info, setInfo] = useState({}); + const [loading, setLoading] = useState(false) + + const fetchListInfo = async (id) => { + if (!id) return + setLoading(true) + const res = await request(infoAction, { + method: "POST", + body: [id], + ignoreTimeout: true + }, false, false); + if (res) { + setInfo(res[id] || {}); + } + setLoading(false) + }; + + useEffect(() => { + if (!parentLoading) { + fetchListInfo(id) + } + }, [id, parentLoading]) + + const summary = info?.summary || {}; + const metrics = info?.metrics || {}; + let metricsSearch = metrics?.search || {}; let metricsSearchData = metricsSearch?.data || defaultEmptyMetricsData(); let searchLineMaxValue = metricsSearchData?.[0]?.[1] || 0; @@ -81,6 +107,7 @@ export default (props) => { const unassignedShards = (numReplicas+1)*numShards-summary?.shards - summary?.replicas || 0 return ( +
{
+ ); }; diff --git a/web/src/pages/Platform/Overview/Indices/index.tsx b/web/src/pages/Platform/Overview/Indices/index.tsx index 28c68902..30b3364b 100644 --- a/web/src/pages/Platform/Overview/Indices/index.tsx +++ b/web/src/pages/Platform/Overview/Indices/index.tsx @@ -6,13 +6,13 @@ import Table from "./Table"; import Overview from "@/components/Overview"; const facetLabels = { - "metadata.index_name": "index", + "metadata.cluster_name": "cluster", "metadata.labels.health_status": "health", "metadata.labels.state": "state", }; const aggsParams = [ - { field: "metadata.index_name", params: { size: 500 } }, + { field: "metadata.cluster_name", params: { size: 150 } }, { field: "metadata.labels.state", params: { size: 100 } }, { field: "metadata.labels.health_status", params: { size: 150 } }, ]; @@ -39,6 +39,11 @@ export default () => { ]} searchAutoCompleteConfig={{ showStatus: true, + defaultSearchField: 'metadata.index_name', + getSearch: (item) => ({ + keyword: item?._source?.metadata?.index_name, + filter: { value: [item?._source?.metadata?.cluster_name], field: 'metadata.cluster_name' } + }), getOptionMeta: (item) => ({ title: item?.highlight?.index_name || item?._source?.metadata?.index_name, @@ -46,9 +51,10 @@ export default () => { item?.highlight?.cluster_name || item?._source?.metadata?.cluster_name, status: item?._source?.metadata?.labels?.health_status, + text: item?._source?.metadata?.index_name }), }} - infoAction={`${ESPrefix}/index/info`} + infoAction={`${ESPrefix}/index/info?timeout=120s`} facetLabels={facetLabels} aggsParams={aggsParams} sideSorterOptions={sideSorterOptions} diff --git a/web/src/pages/Platform/Overview/Node/Card/index.js b/web/src/pages/Platform/Overview/Node/Card/index.js index 395900a9..ce4fb77a 100644 --- a/web/src/pages/Platform/Overview/Node/Card/index.js +++ b/web/src/pages/Platform/Overview/Node/Card/index.js @@ -1,5 +1,5 @@ import React, { useState, useEffect } from "react"; -import { Icon, Tooltip } from "antd"; +import { Icon, Spin, Tooltip } from "antd"; import TinyArea from "@/components/infini/TinyArea"; import { Pie } from "@/components/Charts"; import { formatter } from "@/utils/format"; @@ -8,11 +8,36 @@ import { HealthStatusView } from "@/components/infini/health_status_view"; import { formatUtcTimeToLocal } from "@/utils/utils"; import { FieldFilterFacet } from "@/components/Overview/List/FieldFilterFacet"; import "./index.scss"; +import request from "@/utils/request"; export default (props) => { + const { infoAction, id, parentLoading } = props; const metadata = props.data._source?.metadata || {}; - const summary = props.info?.summary || {}; - const metrics = props.info?.metrics || {}; + const [info, setInfo] = useState({}); + const [loading, setLoading] = useState(false) + + const fetchListInfo = async (id) => { + if (!id) return + setLoading(true) + const res = await request(infoAction, { + method: "POST", + body: [id], + ignoreTimeout: true + }, false, false); + if (res) { + setInfo(res[id] || {}); + } + setLoading(false) + }; + + useEffect(() => { + if (!parentLoading) { + fetchListInfo(id) + } + }, [id, parentLoading]) + + const summary = info?.summary || {}; + const metrics = info?.metrics || {}; const fs_total_in_bytes = summary?.fs?.total?.total_in_bytes || 0; const fs_available_in_bytes = summary?.fs?.total?.available_in_bytes || 0; const fs_used_in_bytes = fs_total_in_bytes - fs_available_in_bytes; @@ -81,6 +106,8 @@ export default (props) => { const healthStatus = metadata?.labels?.status; return ( + +
{
+ ); }; diff --git a/web/src/pages/Platform/Overview/Node/index.tsx b/web/src/pages/Platform/Overview/Node/index.tsx index bc5f0f7b..e3060961 100644 --- a/web/src/pages/Platform/Overview/Node/index.tsx +++ b/web/src/pages/Platform/Overview/Node/index.tsx @@ -48,6 +48,11 @@ export default () => { "metadata.cluster_name", ]} searchAutoCompleteConfig={{ + defaultSearchField: 'metadata.node_name', + getSearch: (item) => ({ + keyword: item?._source?.metadata?.node_name, + filter: { value: [item?._source?.metadata?.cluster_name], field: 'metadata.cluster_name' } + }), getOptionMeta: (item) => ({ title: item?.highlight?.node_name || item?._source?.metadata?.node_name, @@ -55,9 +60,10 @@ export default () => { item?.highlight?.cluster_name || item?._source?.metadata?.cluster_name, right: item?.highlight?.host || item?._source?.metadata?.host, + text: item?._source?.metadata?.node_name }), }} - infoAction={`${ESPrefix}/node/info`} + infoAction={`${ESPrefix}/node/info?timeout=120s`} facetLabels={facetLabels} selectFilterLabels={selectFilterLabels} aggsParams={aggsParams}