Add a refresh button to the table views (#287)

Co-authored-by: braginini <bangvalo@gmail.com>
This commit is contained in:
Sarooj bukhari
2023-10-15 22:04:05 +05:00
committed by GitHub
parent 2d55d0736f
commit ddd812e9a0
8 changed files with 406 additions and 50 deletions

View File

@@ -21,6 +21,7 @@ import {
Tooltip,
Typography,
} from "antd";
import { ReloadOutlined } from "@ant-design/icons";
import { Container } from "../components/Container";
import { useDispatch, useSelector } from "react-redux";
import { storeFilterState, getFilterState } from "../utils/filterState";
@@ -72,7 +73,7 @@ export const AccessControl = () => {
const { onChangePageSize, pageSizeOptions, pageSize } = usePageSizeHelpers();
const { getTokenSilently } = useGetTokenSilently();
const dispatch = useDispatch();
const policies = useSelector((state: RootState) => state.policy.data);
const failed = useSelector((state: RootState) => state.policy.failed);
const loading = useSelector((state: RootState) => state.policy.loading);
@@ -84,6 +85,7 @@ export const AccessControl = () => {
);
const [showTutorial, setShowTutorial] = useState(true);
const [isRefreshButtonDisabled, setIsRefreshButtonDisabled] = useState(false);
const [textToSearch, setTextToSearch] = useState("");
const [optionAllEnable, setOptionAllEnable] = useState("all");
const [currentPage, setCurrentPage] = useState(1);
@@ -184,6 +186,26 @@ export const AccessControl = () => {
);
}, []);
const fetchData = async () => {
setIsRefreshButtonDisabled(true);
dispatch(
policyActions.getPolicies.request({
getAccessTokenSilently: getTokenSilently,
payload: null,
})
);
dispatch(
groupActions.getGroups.request({
getAccessTokenSilently: getTokenSilently,
payload: null,
})
);
await new Promise((resolve) => setTimeout(resolve, 5000)).then(() =>
setIsRefreshButtonDisabled(false)
);
};
useEffect(() => {
if (failed) {
setShowTutorial(false);
@@ -298,7 +320,11 @@ export const AccessControl = () => {
setPolicyToAction(record as PolicyDataTable);
confirm({
icon: <ExclamationCircleOutlined />,
title: <span data-testid="confirm-delete-modal-title" className="font-500">Delete rule {record.name}</span>,
title: (
<span data-testid="confirm-delete-modal-title" className="font-500">
Delete rule {record.name}
</span>
),
width: 500,
content: (
<Space direction="vertical" size="small">
@@ -420,7 +446,6 @@ export const AccessControl = () => {
);
};
const toggleModalGroups = (
title: string,
groups: Group[] | string[] | null,
@@ -643,6 +668,7 @@ export const AccessControl = () => {
disabled={showTutorial}
/>
<Select
style={{ marginRight: "10px" }}
value={pageSize.toString()}
options={pageSizeOptions}
onChange={(value) => {
@@ -652,6 +678,22 @@ export const AccessControl = () => {
disabled={showTutorial}
/>
</Space>
<Tooltip
title={
isRefreshButtonDisabled
? "You can refresh it again in 5 seconds"
: "Refresh"
}
>
<Button
onClick={fetchData}
disabled={isRefreshButtonDisabled}
style={{ marginLeft: "5px", color: "#1890ff" }}
>
<ReloadOutlined />
</Button>
</Tooltip>
</Col>
{!showTutorial && (
<Col

View File

@@ -14,6 +14,7 @@ import {
Space,
Table,
Typography,
Tooltip,
} from "antd";
import { Event } from "../store/event/types";
import { filter } from "lodash";
@@ -23,7 +24,7 @@ import { useOidcUser } from "@axa-fr/react-oidc";
import { capitalize, formatDateTime } from "../utils/common";
import { User } from "../store/user/types";
import { usePageSizeHelpers } from "../utils/pageSize";
import { QuestionCircleFilled } from "@ant-design/icons";
import { ReloadOutlined } from "@ant-design/icons";
import { storeFilterState, getFilterState } from "../utils/filterState";
const { Title, Paragraph, Text } = Typography;
@@ -44,6 +45,7 @@ export const Activity = () => {
const setupKeys = useSelector((state: RootState) => state.setupKey.data);
const [textToSearch, setTextToSearch] = useState("");
const [isRefreshButtonDisabled, setIsRefreshButtonDisabled] = useState(false);
const [dataTable, setDataTable] = useState([] as EventDataTable[]);
const transformDataTable = (d: Event[]): EventDataTable[] => {
@@ -58,6 +60,21 @@ export const Activity = () => {
})
);
}, []);
const fetchData = async() => {
setIsRefreshButtonDisabled(true);
dispatch(
eventActions.getEvents.request({
getAccessTokenSilently: getTokenSilently,
payload: null,
})
);
await new Promise((resolve) => setTimeout(resolve, 5000)).then(() =>
setIsRefreshButtonDisabled(false)
);
};
// useEffect(() => {
// setDataTable(transformDataTable(events));
// }, [events]);
@@ -427,6 +444,7 @@ export const Activity = () => {
<Col xs={24} sm={24} md={11} lg={11} xl={11} xxl={11} span={11}>
<Space size="middle">
<Select
style={{ marginRight: "10px" }}
value={pageSize.toString()}
options={pageSizeOptions}
onChange={(value) => {
@@ -435,6 +453,22 @@ export const Activity = () => {
className="select-rows-per-page-en"
/>
</Space>
<Tooltip
title={
isRefreshButtonDisabled
? "You can refresh it again in 5 seconds"
: "Refresh"
}
>
<Button
onClick={fetchData}
disabled={isRefreshButtonDisabled}
style={{ marginLeft: "5px", color: "#1890ff" }}
>
<ReloadOutlined />
</Button>
</Tooltip>
</Col>
</Row>
{failed && (

View File

@@ -2,7 +2,6 @@ import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { RootState } from "typesafe-actions";
import { actions as nsGroupActions } from "../store/nameservers";
import { Container } from "../components/Container";
import {
Alert,
Button,
@@ -21,8 +20,10 @@ import {
Table,
Tag,
Typography,
Tooltip,
} from "antd";
import { filter } from "lodash";
import { ReloadOutlined } from "@ant-design/icons";
import tableSpin from "../components/Spin";
import { storeFilterState, getFilterState } from "../utils/filterState";
import { useGetTokenSilently } from "../utils/token";
@@ -77,6 +78,7 @@ export const Nameservers = () => {
);
const [textToSearch, setTextToSearch] = useState("");
const [isRefreshButtonDisabled, setIsRefreshButtonDisabled] = useState(false);
const [optionAllEnable, setOptionAllEnable] = useState("all");
const [dataTable, setDataTable] = useState([] as NameserverGroupDataTable[]);
const [showTutorial, setShowTutorial] = useState(false);
@@ -192,6 +194,26 @@ export const Nameservers = () => {
);
}, []);
const fetchData = async () => {
setIsRefreshButtonDisabled(true);
dispatch(
nsGroupActions.getNameServerGroups.request({
getAccessTokenSilently: getTokenSilently,
payload: null,
})
);
dispatch(
groupActions.getGroups.request({
getAccessTokenSilently: getTokenSilently,
payload: null,
})
);
await new Promise((resolve) => setTimeout(resolve, 5000)).then(() =>
setIsRefreshButtonDisabled(false)
);
};
const onChangeAllEnabled = ({ target: { value } }: RadioChangeEvent) => {
setOptionAllEnable(value);
storeFilterState("nameServerFilter", "quickFilter", value);
@@ -554,6 +576,22 @@ export const Nameservers = () => {
className="select-rows-per-page-en"
disabled={showTutorial}
/>
<Tooltip
title={
isRefreshButtonDisabled
? "You can refresh it again in 5 seconds"
: "Refresh"
}
>
<Button
onClick={fetchData}
disabled={isRefreshButtonDisabled}
style={{ color: "#1890ff" }}
>
<ReloadOutlined />
</Button>
</Tooltip>
</Space>
</Col>
<Col xs={24} sm={24} md={5} lg={5} xl={5} xxl={5} span={5}>

View File

@@ -94,6 +94,7 @@ export const Peers = () => {
const [groupPopupVisible, setGroupPopupVisible] = useState("");
const [showTutorial, setShowTutorial] = useState(false);
const [hadFirstRun, setHadFirstRun] = useState(true);
const [isRefreshButtonDisabled, setIsRefreshButtonDisabled] = useState(false);
const [confirmModal, confirmModalContextHolder] = Modal.useModal();
const optionsOnOff = [
@@ -182,6 +183,33 @@ export const Peers = () => {
);
};
const fetchData = async () => {
setIsRefreshButtonDisabled(true);
dispatch(
userActions.getUsers.request({
getAccessTokenSilently: getTokenSilently,
payload: null,
})
);
dispatch(
peerActions.getPeers.request({
getAccessTokenSilently: getTokenSilently,
payload: null,
})
);
dispatch(
groupActions.getGroups.request({
getAccessTokenSilently: getTokenSilently,
payload: null,
})
);
await new Promise((resolve) => setTimeout(resolve, 5000)).then(() =>
setIsRefreshButtonDisabled(false)
);
};
useEffect(() => {
getLocalItem<boolean>(StorageKey.hadFirstRun).then((f) =>
setHadFirstRun(f === null ? false : f)
@@ -694,7 +722,7 @@ export const Peers = () => {
{isAdmin && (
<Select
mode="tags"
style={{ marginRight: "15px" }}
style={{ marginRight: "10px" }}
placeholder="Filter by groups"
tagRender={blueTagRender}
// dropdownRender={dropDownRender}
@@ -715,10 +743,17 @@ export const Peers = () => {
</Select>
)}
<Tooltip title="Refersh">
<Tooltip
title={
isRefreshButtonDisabled
? "You can refresh it again in 5 seconds"
: "Refresh"
}
>
<Button
onClick={refresh}
style={{color: "#1890ff" }}
onClick={fetchData}
disabled={isRefreshButtonDisabled}
style={{ marginLeft: "5px", color: "#1890ff" }}
>
<ReloadOutlined />
</Button>

View File

@@ -41,7 +41,7 @@ import { usePageSizeHelpers } from "../utils/pageSize";
import AddServiceUserPopup from "../components/popups/AddServiceUserPopup";
import InviteUserPopup from "../components/popups/InviteUserPopup";
import { Peer, PeerDataTable } from "../store/peer/types";
import { ExclamationCircleOutlined, MinusOutlined } from "@ant-design/icons";
import { ExclamationCircleOutlined, ReloadOutlined } from "@ant-design/icons";
import { actions as peerActions } from "../store/peer";
import { useOidcUser } from "@axa-fr/react-oidc";
import { storeFilterState, getFilterState } from "../utils/filterState";
@@ -79,6 +79,7 @@ export const RegularUsers = () => {
null as UserDataTable | null
);
const [textToSearch, setTextToSearch] = useState("");
const [isRefreshButtonDisabled, setIsRefreshButtonDisabled] = useState(false);
const [dataTable, setDataTable] = useState([] as UserDataTable[]);
const [confirmModal, confirmModalContextHolder] = Modal.useModal();
@@ -166,6 +167,31 @@ export const RegularUsers = () => {
);
}, [savedUser]);
const fetchData = async () => {
setIsRefreshButtonDisabled(true);
dispatch(
userActions.getUsers.request({
getAccessTokenSilently: getTokenSilently,
payload: null,
})
);
dispatch(
userActions.getRegularUsers.request({
getAccessTokenSilently: getTokenSilently,
payload: null,
})
);
dispatch(
groupActions.getGroups.request({
getAccessTokenSilently: getTokenSilently,
payload: null,
})
);
await new Promise((resolve) => setTimeout(resolve, 5000)).then(() =>
setIsRefreshButtonDisabled(false)
);
};
useEffect(() => {
if (!loading && groups.length && users) {
const searchText = getFilterState("userFilter", "search");
@@ -396,7 +422,7 @@ export const RegularUsers = () => {
icon: <ExclamationCircleOutlined />,
title: (
<span className="font-500">
Are you sure you want to block {user.name? user.name : user.id}?
Are you sure you want to block {user.name ? user.name : user.id}?
</span>
),
width: 600,
@@ -450,12 +476,18 @@ export const RegularUsers = () => {
const handleDeleteUser = (user: UserDataTable) => {
confirmModal.confirm({
icon: <ExclamationCircleOutlined />,
title: <span className="font-500">Are you sure you want to delete {user.name? user.name : user.id}?</span>,
title: (
<span className="font-500">
Are you sure you want to delete {user.name ? user.name : user.id}?
</span>
),
width: 500,
content: (
<Space direction="vertical" size="small">
<Paragraph>
Deleting this user will remove their devices and remove dashboard access.</Paragraph>
Deleting this user will remove their devices and remove dashboard
access.
</Paragraph>
</Space>
),
onOk() {
@@ -510,6 +542,7 @@ export const RegularUsers = () => {
<Col xs={24} sm={24} md={11} lg={11} xl={11} xxl={11} span={11}>
<Space size="middle">
<Select
style={{ marginRight: "10px" }}
value={pageSize.toString()}
options={pageSizeOptions}
onChange={(value) => {
@@ -518,6 +551,21 @@ export const RegularUsers = () => {
className="select-rows-per-page-en"
/>
</Space>
<Tooltip
title={
isRefreshButtonDisabled
? "You can refresh it again in 5 seconds"
: "Refresh"
}
>
<Button
onClick={fetchData}
disabled={isRefreshButtonDisabled}
style={{ marginLeft: "5px", color: "#1890ff" }}
>
<ReloadOutlined />
</Button>
</Tooltip>
</Col>
<Col xs={24} sm={24} md={5} lg={5} xl={5} xxl={5} span={5}>
{(isNetBirdHosted() || isLocalDev()) && (
@@ -583,47 +631,87 @@ export const RegularUsers = () => {
if ((record as User).is_current) {
return (
<>
<div>
{btn}
<Tag color="blue">me</Tag>
</div>
{(isNetBirdHosted() || isLocalDev()) && ((record as User).last_login && <Text type={"secondary"} style={{paddingLeft: "15px"}}>Last login: {String(timeAgo((record as User).last_login))}</Text>)}
</>
<>
<div>
{btn}
<Tag color="blue">me</Tag>
</div>
{(isNetBirdHosted() || isLocalDev()) &&
(record as User).last_login && (
<Text
type={"secondary"}
style={{ paddingLeft: "15px" }}
>
Last login:{" "}
{String(timeAgo((record as User).last_login))}
</Text>
)}
</>
);
}
if ((record as User).status === "invited") {
return (
<>
<div>
{btn}
<Tag color="gold">invited</Tag>
</div>
{(isNetBirdHosted() || isLocalDev()) && ((record as User).last_login && <Text type={"secondary"} style={{paddingLeft: "15px", paddingTop: "0px"}}>Last login: {String(timeAgo((record as User).last_login))}</Text>)}
</>
<>
<div>
{btn}
<Tag color="gold">invited</Tag>
</div>
{(isNetBirdHosted() || isLocalDev()) &&
(record as User).last_login && (
<Text
type={"secondary"}
style={{
paddingLeft: "15px",
paddingTop: "0px",
}}
>
Last login:{" "}
{String(timeAgo((record as User).last_login))}
</Text>
)}
</>
);
}
if ((record as User).status === "blocked") {
return (
<>
<div>
{btn}
<Tag color="red">blocked</Tag>
</div>
{(isNetBirdHosted() || isLocalDev()) && ((record as User).last_login && <Text type={"secondary"} style={{paddingLeft: "15px"}}>Last login: {String(timeAgo((record as User).last_login))}</Text>)}
</>
<>
<div>
{btn}
<Tag color="red">blocked</Tag>
</div>
{(isNetBirdHosted() || isLocalDev()) &&
(record as User).last_login && (
<Text
type={"secondary"}
style={{ paddingLeft: "15px" }}
>
Last login:{" "}
{String(timeAgo((record as User).last_login))}
</Text>
)}
</>
);
}
return (
<>
<div>
{btn}
</div>
{(isNetBirdHosted() || isLocalDev()) && ((record as User).last_login && <Text type={"secondary"} style={{paddingLeft: "15px", paddingTop: "0px"}}>Last login: {String(timeAgo((record as User).last_login))}</Text>)}
</>
<>
<div>{btn}</div>
{(isNetBirdHosted() || isLocalDev()) &&
(record as User).last_login && (
<Text
type={"secondary"}
style={{
paddingLeft: "15px",
paddingTop: "0px",
}}
>
Last login:{" "}
{String(timeAgo((record as User).last_login))}
</Text>
)}
</>
);
}}
/>

View File

@@ -34,6 +34,7 @@ import {
EllipsisOutlined,
ExclamationCircleOutlined,
ExclamationCircleFilled,
ReloadOutlined,
} from "@ant-design/icons";
import { storeFilterState, getFilterState } from "../utils/filterState";
import RouteAddNew from "../components/RouteAddNew";
@@ -89,6 +90,7 @@ export const Routes = () => {
(state: RootState) => state.route.setupEditRouteVisible
);
const [showTutorial, setShowTutorial] = useState(true);
const [isRefreshButtonDisabled, setIsRefreshButtonDisabled] = useState(false);
const [textToSearch, setTextToSearch] = useState("");
const [optionAllEnable, setOptionAllEnable] = useState("enabled");
const [dataTable, setDataTable] = useState([] as RouteDataTable[]);
@@ -184,8 +186,29 @@ export const Routes = () => {
payload: null,
})
);
}, []);
const fetchData = async() => {
setIsRefreshButtonDisabled(true);
dispatch(
peerActions.getPeers.request({
getAccessTokenSilently: getTokenSilently,
payload: null,
})
);
dispatch(
groupActions.getGroups.request({
getAccessTokenSilently: getTokenSilently,
payload: null,
})
);
await new Promise((resolve) => setTimeout(resolve, 5000)).then(() =>
setIsRefreshButtonDisabled(false)
);
};
const filterGroupedDataTable = (
routes: GroupedDataTable[],
searchText: string
@@ -861,6 +884,7 @@ export const Routes = () => {
>
<Space size="middle">
<Radio.Group
style={{ marginRight: "10px" }}
options={optionsAllEnabled}
onChange={onChangeAllEnabled}
value={optionAllEnable}
@@ -869,6 +893,21 @@ export const Routes = () => {
disabled={showTutorial}
/>
</Space>
<Tooltip
title={
isRefreshButtonDisabled
? "You can refresh it again in 5 seconds"
: "Refresh"
}
>
<Button
onClick={fetchData}
disabled={isRefreshButtonDisabled}
style={{ marginLeft: "5px", color: "#1890ff" }}
>
<ReloadOutlined />
</Button>
</Tooltip>
</Col>
{!showTutorial && (
<Col

View File

@@ -17,11 +17,13 @@ import {
Table,
Tag,
Typography,
Tooltip,
} from "antd";
import { User } from "../store/user/types";
import { filter } from "lodash";
import tableSpin from "../components/Spin";
import { useGetTokenSilently } from "../utils/token";
import { ReloadOutlined } from "@ant-design/icons";
import { actions as groupActions } from "../store/group";
import { capitalize, isLocalDev, isNetBirdHosted } from "../utils/common";
import { usePageSizeHelpers } from "../utils/pageSize";
@@ -53,6 +55,7 @@ export const ServiceUsers = () => {
);
const savedUser = useSelector((state: RootState) => state.user.savedUser);
const deletedUser = useSelector((state: RootState) => state.user.deletedUser);
const [isRefreshButtonDisabled, setIsRefreshButtonDisabled] = useState(false);
const [showTutorial, setShowTutorial] = useState(false);
const [confirmModal, confirmModalContextHolder] = Modal.useModal();
@@ -78,18 +81,42 @@ export const ServiceUsers = () => {
);
}, [savedUser, deletedUser]);
const fetchData = async () => {
setIsRefreshButtonDisabled(true);
dispatch(
userActions.getUsers.request({
getAccessTokenSilently: getTokenSilently,
payload: null,
})
);
dispatch(
userActions.getServiceUsers.request({
getAccessTokenSilently: getTokenSilently,
payload: null,
})
);
dispatch(
groupActions.getGroups.request({
getAccessTokenSilently: getTokenSilently,
payload: null,
})
);
await new Promise((resolve) => setTimeout(resolve, 5000)).then(() =>
setIsRefreshButtonDisabled(false)
);
};
// useEffect(() => {
// setDataTable(transformDataTable(users));
// }, [users, groups]);
useEffect(() => {
if (users.length > 0) {
setShowTutorial(false);
} else {
setShowTutorial(true);
}
// setDataTable(transformDataTable(filterDataTable()));
}, [users]);
useEffect(() => {
if (users.length > 0) {
setShowTutorial(false);
} else {
setShowTutorial(true);
}
// setDataTable(transformDataTable(filterDataTable()));
}, [users]);
useEffect(() => {
if (!loading && groups.length) {
@@ -227,8 +254,6 @@ export const ServiceUsers = () => {
});
};
return (
<>
{!user && (
@@ -289,6 +314,7 @@ export const ServiceUsers = () => {
>
<Space size="middle">
<Select
style={{ marginRight: "10px" }}
value={pageSize.toString()}
options={pageSizeOptions}
onChange={(value) => {
@@ -298,6 +324,21 @@ export const ServiceUsers = () => {
disabled={showTutorial}
/>
</Space>
<Tooltip
title={
isRefreshButtonDisabled
? "You can refresh it again in 5 seconds"
: "Refresh"
}
>
<Button
onClick={fetchData}
disabled={isRefreshButtonDisabled}
style={{ marginLeft: "5px", color: "#1890ff" }}
>
<ReloadOutlined />
</Button>
</Tooltip>
</Col>
{!showTutorial && (
<Col xs={24} sm={24} md={5} lg={5} xl={5} xxl={5} span={5}>

View File

@@ -3,6 +3,7 @@ import { useDispatch, useSelector } from "react-redux";
import { RootState } from "typesafe-actions";
import { actions as setupKeyActions } from "../store/setup-key";
import { Container } from "../components/Container";
import { ReloadOutlined } from "@ant-design/icons";
import {
Alert,
Button,
@@ -51,6 +52,7 @@ export const SetupKeys = () => {
const { getTokenSilently } = useGetTokenSilently();
const dispatch = useDispatch();
const [showGroupModal, setShowGroupModal] = useState(false);
const [isRefreshButtonDisabled, setIsRefreshButtonDisabled] = useState(false);
const setupKeys = useSelector((state: RootState) => state.setupKey.data);
const failed = useSelector((state: RootState) => state.setupKey.failed);
@@ -109,6 +111,26 @@ export const SetupKeys = () => {
);
}, []);
const fetchData = async () => {
setIsRefreshButtonDisabled(true);
dispatch(
setupKeyActions.getSetupKeys.request({
getAccessTokenSilently: getTokenSilently,
payload: null,
})
);
dispatch(
groupActions.getGroups.request({
getAccessTokenSilently: getTokenSilently,
payload: null,
})
);
await new Promise((resolve) => setTimeout(resolve, 5000)).then(() =>
setIsRefreshButtonDisabled(false)
);
};
useEffect(() => {
setDataTable(transformDataTable(filterDataTable("")));
}, [textToSearch, optionValidAll]);
@@ -475,6 +497,7 @@ export const SetupKeys = () => {
disabled={!dataTable?.length}
/>
<Select
style={{ marginRight: "10px" }}
disabled={!dataTable?.length}
value={pageSize.toString()}
options={pageSizeOptions}
@@ -484,6 +507,22 @@ export const SetupKeys = () => {
className="select-rows-per-page-en"
/>
</Space>
<Tooltip
title={
isRefreshButtonDisabled
? "You can refresh it again in 5 seconds"
: "Refresh"
}
>
<Button
onClick={fetchData}
disabled={isRefreshButtonDisabled}
style={{ marginLeft: "5px", color: "#1890ff" }}
>
<ReloadOutlined />
</Button>
</Tooltip>
</Col>
{dataTable.length ? (
<Col xs={24} sm={24} md={5} lg={5} xl={5} xxl={5} span={5}>