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:
parent
16110912c3
commit
4d52f2882a
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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 />
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -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 />
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -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 />
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue