chore: add loading to each row in overview table (#51)

* chore: add loading to each row in overview table

* chore: update release notes

---------

Co-authored-by: yaojiping <yaojiping@infini.ltd>
This commit is contained in:
yaojp123 2024-12-20 15:52:26 +08:00 committed by GitHub
parent 16110912c3
commit 4d52f2882a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 140 additions and 96 deletions

View File

@ -12,11 +12,14 @@ Information about release notes of INFINI Console is provided here.
### Breaking changes ### Breaking changes
### Features ### Features
- add allocation to activities if is cluster health change and changed to red.
### Bug fix ### Bug fix
- fix: query thread pool metrics when cluster uuid is empty - fix: query thread pool metrics when cluster uuid is empty
### Improvements ### Improvements
- Optimize UI of agent list when its columns are overflow.
- add loading to each row in overview table.
## 1.27.0 (2024-12-09) ## 1.27.0 (2024-12-09)

View File

@ -1,5 +1,5 @@
import React, { useState, useEffect, useMemo } from "react"; import React, { useState, useEffect, useMemo } from "react";
import { Table, Tooltip, Progress } from "antd"; import { Table, Tooltip, Progress, Spin } from "antd";
import { formatter } from "@/utils/format"; import { formatter } from "@/utils/format";
import { formatMessage } from "umi/locale"; import { formatMessage } from "umi/locale";
import { SearchEngineIcon } from "@/lib/search_engines"; import { SearchEngineIcon } from "@/lib/search_engines";
@ -18,36 +18,39 @@ export default (props) => {
dataIndex: "name", dataIndex: "name",
render: (text, record) => { render: (text, record) => {
return ( return (
<Tooltip <>
placement="topLeft" <Tooltip
title={ placement="topLeft"
<span> title={
Host: {record.metadata?.host} <span>
<br /> Host: {record.metadata?.host}
Provider:{" "} <br />
{formatMessage({ Provider:{" "}
id: `cluster.providers.${record.metadata?.location {formatMessage({
?.provider ?? Providers.OnPremises}`, id: `cluster.providers.${record.metadata?.location
})} ?.provider ?? Providers.OnPremises}`,
<br /> })}
Region: {record.metadata?.location?.region ?? ""} <br />
<br /> Region: {record.metadata?.location?.region ?? ""}
Version: {record.metadata?.version ?? ""} <br />
<br /> Version: {record.metadata?.version ?? ""}
Tags:{" "} <br />
{record.metadata?.tags ? record.metadata.tags.toString() : ""} Tags:{" "}
</span> {record.metadata?.tags ? record.metadata.tags.toString() : ""}
} </span>
> }
<div style={{ display: "flex", alignContent: "center", gap: 5 }}> >
<SearchEngineIcon <div style={{ display: "flex", alignContent: "center", gap: 5 }}>
distribution={record.metadata?.distribution} <SearchEngineIcon
width="20px" distribution={record.metadata?.distribution}
height="20px" width="20px"
/> height="20px"
<span>{record.metadata?.name}</span> />
</div> <span>{record.metadata?.name}</span>
</Tooltip> </div>
</Tooltip>
<Spin />
</>
); );
}, },
}, },

View File

@ -1,5 +1,5 @@
import React, { useState, useEffect, useMemo } from "react"; import React, { useState, useEffect, useMemo } from "react";
import { Tooltip, Progress, Icon } from "antd"; import { Tooltip, Progress, Icon, Spin } from "antd";
import { formatter } from "@/utils/format"; import { formatter } from "@/utils/format";
import { formatUtcTimeToLocal } from "@/utils/utils"; import { formatUtcTimeToLocal } from "@/utils/utils";
import { formatMessage } from "umi/locale"; import { formatMessage } from "umi/locale";
@ -18,25 +18,28 @@ export default (props) => {
dataIndex: "name", dataIndex: "name",
render: (text, record) => { render: (text, record) => {
return ( return (
<Tooltip <>
placement="topLeft" <Tooltip
title={ placement="topLeft"
<span> title={
Cluster: {record.metadata?.cluster_name} <span>
<br /> Cluster: {record.metadata?.cluster_name}
Aliases: {record.metadata?.aliases?.join(",")} <br />
<br /> Aliases: {record.metadata?.aliases?.join(",")}
Timestamp: {record.timestamp} <br />
</span> Timestamp: {record.timestamp}
} </span>
> }
<div style={{ display: "flex", alignContent: "center", gap: 5 }}> >
<span> <div style={{ display: "flex", alignContent: "center", gap: 5 }}>
<Icon type="table" /> <span>
</span> <Icon type="table" />
<span>{record.metadata?.index_name}</span> </span>
</div> <span>{record.metadata?.index_name}</span>
</Tooltip> </div>
</Tooltip>
<Spin />
</>
); );
}, },
}, },

View File

@ -1,5 +1,5 @@
import React, { useState, useEffect, useMemo } from "react"; import React, { useState, useEffect, useMemo } from "react";
import { Tooltip, Progress, Icon } from "antd"; import { Tooltip, Progress, Icon, Spin } from "antd";
import { formatter } from "@/utils/format"; import { formatter } from "@/utils/format";
import { HealthStatusView } from "@/components/infini/health_status_view"; import { HealthStatusView } from "@/components/infini/health_status_view";
import { StatusBlockGroup } from "@/components/infini/status_block"; import { StatusBlockGroup } from "@/components/infini/status_block";
@ -15,35 +15,38 @@ export default (props) => {
dataIndex: "name", dataIndex: "name",
render: (text, record) => { render: (text, record) => {
return ( return (
<Tooltip <>
placement="topLeft" <Tooltip
title={ placement="topLeft"
<span> title={
Transport Address:{" "} <span>
{record.metadata?.labels?.transport_address} Transport Address:{" "}
<br /> {record.metadata?.labels?.transport_address}
Cluster: {record.metadata?.cluster_name ?? ""} <br />
<br /> Cluster: {record.metadata?.cluster_name ?? ""}
Version: {record.metadata?.labels?.version ?? ""} <br />
<br /> Version: {record.metadata?.labels?.version ?? ""}
Roles:{" "} <br />
{record.metadata?.labels?.roles Roles:{" "}
? record.metadata?.labels?.roles?.toString() {record.metadata?.labels?.roles
: ""} ? record.metadata?.labels?.roles?.toString()
</span> : ""}
} </span>
> }
<div style={{ display: "flex", alignContent: "center", gap: 5 }}> >
<span> <div style={{ display: "flex", alignContent: "center", gap: 5 }}>
{record.summary?.is_master_node ? ( <span>
<Icon type="star" theme="filled" /> {record.summary?.is_master_node ? (
) : ( <Icon type="star" theme="filled" />
<Icon type="database" /> ) : (
)} <Icon type="database" />
</span> )}
<span>{record.metadata?.node_name}</span> </span>
</div> <span>{record.metadata?.node_name}</span>
</Tooltip> </div>
</Tooltip>
<Spin />
</>
); );
}, },
}, },

View File

@ -27,24 +27,31 @@ export default (props) => {
} = props; } = props;
const [infos, setInfos] = useState({}); const [infos, setInfos] = useState({});
const [loadings, setLoadings] = useState({});
const fetchListInfo = async (data) => { const fetchListInfo = async (data) => {
const res = await Promise.all(data?.map((item) => request(infoAction, { data?.forEach((item) => {
method: "POST", setLoadings((loadings) => ({
body: [item.id], ...loadings,
}, false, false))); [item.id]: true
if (res) { }))
let newInfos = {} request(infoAction, {
res.forEach((item) => { method: "POST",
if (item && !item.error) { body: [item.id],
newInfos = { }, false, false).then((res) => {
...newInfos, if (res && !res.error) {
...item setInfos((infos) => ({
} ...infos,
...res
}));
} }
}).finally(() => {
setLoadings((loadings) => ({
...loadings,
[item.id]: false
}))
}) })
setInfos(newInfos); })
}
}; };
useEffect(() => { useEffect(() => {
@ -84,7 +91,7 @@ export default (props) => {
}, },
}; };
}} }}
rowClassName={() => styles.rowPointer} rowClassName={(record) => `${styles.rowPointer} ${loadings[record.id] && !parentLoading ? styles.loading : ''}`}
/> />
</div> </div>
); );

View File

@ -1,3 +1,28 @@
.rowPointer { .rowPointer {
cursor: pointer; cursor: pointer;
:global {
.ant-spin-spinning {
display: none;
}
}
}
.loading {
position: relative;
cursor: default;
pointer-events: none;
opacity: 0.5;
:global {
.ant-spin-spinning {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
z-index: 1;
}
}
} }