Added subscription name to planner, visualize, and peering components

This commit is contained in:
Matthew Garrett 2023-02-23 23:37:34 -08:00
Родитель e673ec6ec9
Коммит a4fd136052
8 изменённых файлов: 216 добавлений и 142 удалений

Просмотреть файл

@ -299,6 +299,8 @@ async def subscription(
subscription_list = await get_subscriptions_sdk(creds)
await creds.close()
return subscription_list
@router.get(

Просмотреть файл

@ -16,6 +16,7 @@ import RestoreIcon from '@mui/icons-material/Restore';
import { cloneDeep, isEmpty } from "lodash";
import {
selectSubscriptions,
selectNetworks
} from "../ipam/ipamSlice";
@ -84,46 +85,6 @@ const opt = {
},
formatter: function (d) {
if(d.dataType === "edge") {
const source = d.data.source;
const target = d.data.target;
const lineColor = d.data.lineStyle.color;
const colorMap = {
'#00FF00': 'Connected',
'#FF0000': 'Disconnected'
};
const vNetPattern = "/Microsoft.Network/virtualNetworks/";
const vHubPattern = "/Microsoft.Network/virtualHubs/";
const resourceGroupPattern = "(?<=/resourceGroups/).+?(?=/)";
const subscriptionPattern = "(?<=/subscriptions/).+?(?=/)";
var sourceVnetName = '';
var targetVnetName = '';
if(source.includes(vNetPattern)) {
sourceVnetName = source.substr(source.indexOf(vNetPattern) + vNetPattern.length, source.length);
}
if(source.includes(vHubPattern)) {
sourceVnetName = source.substr(source.indexOf(vHubPattern) + vHubPattern.length, source.length);
}
if(target.includes(vNetPattern)) {
targetVnetName = target.substr(source.indexOf(vNetPattern) + vNetPattern.length, target.length);
}
if(target.includes(vHubPattern)) {
targetVnetName = target.substr(source.indexOf(vHubPattern) + vHubPattern.length, target.length);
}
const sourceResourceGroup = source.match(resourceGroupPattern)[0];
const targetResourceGroup = target.match(resourceGroupPattern)[0];
const sourceSubscription = source.match(subscriptionPattern)[0];
const targetSubscription = target.match(subscriptionPattern)[0];
const x = `
<style>
.wrapper {
@ -186,7 +147,7 @@ const opt = {
left: calc(50% - 6px);
border-width: 0px 12px 12px;
border-style: solid;
border-color: ${lineColor} transparent;
border-color: ${d.data.lineStyle.color} transparent;
}
.wrapper::after {
@ -208,15 +169,19 @@ const opt = {
</div>
<div class="data">
<span style="font-weight: bold">Network Name:&nbsp;</span>
${sourceVnetName}
${d.data.detail.sourceVnetName}
</div>
<div class="data">
<span style="font-weight: bold">Resource Group:&nbsp;</span>
${sourceResourceGroup}
${d.data.detail.sourceResourceGroup}
</div>
<div class="data">
<span style="font-weight: bold">Subscription:&nbsp;</span>
${sourceSubscription}
<span style="font-weight: bold">Subscription Name:&nbsp;</span>
${d.data.detail.sourceSubscriptionName}
</div>
<div class="data">
<span style="font-weight: bold">Subscription ID:&nbsp;</span>
${d.data.detail.sourceSubscriptionId}
</div>
</div>
<div class="center">
@ -228,22 +193,26 @@ const opt = {
</div>
<div class="data">
<span style="font-weight: bold">Network Name:&nbsp;</span>
${targetVnetName}
${d.data.detail.targetVnetName}
</div>
<div class="data">
<span style="font-weight: bold">Resource Group:&nbsp;</span>
${targetResourceGroup}
${d.data.detail.targetResourceGroup}
</div>
<div class="data">
<span style="font-weight: bold">Subscription:&nbsp;</span>
${targetSubscription}
<span style="font-weight: bold">Subscription Name:&nbsp;</span>
${d.data.detail.targetSubscriptionName}
</div>
<div class="data">
<span style="font-weight: bold">Subscription ID:&nbsp;</span>
${d.data.detail.targetSubscriptionId}
</div>
</div>
</div>
<div class="footer">
<div class="dot" style="background-color: ${lineColor}"></div>
<div class="dot" style="background-color: ${d.data.lineStyle.color}"></div>
<span style="font-weight: bold">
${colorMap[lineColor]}
${d.data.detail.state}
</span>
</div>
</div>
@ -251,30 +220,30 @@ const opt = {
return x;
} else {
const name = d.name;
const peers = d.value;
const color = d.color;
// const name = d.name;
// const peers = d.value;
// const color = d.color;
const display = d.data.category !== 'error' && 'none';
const vNetPattern = "/Microsoft.Network/virtualNetworks/";
const vHubPattern = "/Microsoft.Network/virtualHubs/";
// const vNetPattern = "/Microsoft.Network/virtualNetworks/";
// const vHubPattern = "/Microsoft.Network/virtualHubs/";
const resourceGroupPattern = "(?<=/resourceGroups/).+?(?=/)";
const subscriptionPattern = "(?<=/subscriptions/).+?(?=/)";
// const resourceGroupPattern = "(?<=/resourceGroups/).+?(?=/)";
// const subscriptionPattern = "(?<=/subscriptions/).+?(?=/)";
var vNetName = '';
// var vNetName = '';
if(name.includes(vNetPattern)) {
vNetName = name.substr(name.indexOf(vNetPattern) + vNetPattern.length, name.length);
}
// if(name.includes(vNetPattern)) {
// vNetName = name.substr(name.indexOf(vNetPattern) + vNetPattern.length, name.length);
// }
if(name.includes(vHubPattern)) {
vNetName = name.substr(name.indexOf(vHubPattern) + vHubPattern.length, name.length);
}
// if(name.includes(vHubPattern)) {
// vNetName = name.substr(name.indexOf(vHubPattern) + vHubPattern.length, name.length);
// }
const resourceGroup = name.match(resourceGroupPattern)[0];
const subscription = name.match(subscriptionPattern)[0];
// const resourceGroup = name.match(resourceGroupPattern)[0];
// const subscription = name.match(subscriptionPattern)[0];
const y = `
<style>
@ -323,7 +292,7 @@ const opt = {
left: calc(50% - 6px);
border-width: 0px 12px 12px;
border-style: solid;
border-color: ${color} transparent;
border-color: ${d.color} transparent;
}
.outer::after {
@ -345,20 +314,24 @@ const opt = {
</div>
<div class="data">
<span style="font-weight: bold">Network Name:&nbsp;</span>
${vNetName}
${d.data.detail.vNetName}
</div>
<div class="data">
<span style="font-weight: bold">Resource Group:&nbsp;</span>
${resourceGroup}
${d.data.detail.resourceGroup}
</div>
<div class="data">
<span style="font-weight: bold">Subscription:&nbsp;</span>
${subscription}
<span style="font-weight: bold">Subscription Name:&nbsp;</span>
${d.data.detail.subscriptionName}
</div>
<div class="data">
<span style="font-weight: bold">Subscription ID:&nbsp;</span>
${d.data.detail.subscriptionId}
</div>
<div class="footer">
<div class="dot" style="background-color: ${color}"></div>
<div class="dot" style="background-color: ${d.color}"></div>
<span style="font-weight: bold">Peerings:&nbsp;</span>
${peers}
${d.value}
<span style="margin-left: auto; color: crimson; font-weight: bold; display: ${display}">vNET Missing</span>
</div>
</div>
@ -373,7 +346,7 @@ const opt = {
series: []
};
function parseNets(data) {
function parseNets(data, subscriptions) {
const factor = 3;
const stateMap = {
@ -394,13 +367,38 @@ function parseNets(data) {
var visibleNets = [];
const nodes = data.map(vnet => {
const vNetPattern = "/Microsoft.Network/virtualNetworks/";
const vHubPattern = "/Microsoft.Network/virtualHubs/";
const resourceGroupPattern = "(?<=/resourceGroups/).+?(?=/)";
const subscriptionPattern = "(?<=/subscriptions/).+?(?=/)";
var vNetName = '';
if(vnet.id.includes(vNetPattern)) {
vNetName = vnet.id.substr(vnet.id.indexOf(vNetPattern) + vNetPattern.length, vnet.id.length);
}
if(vnet.id.includes(vHubPattern)) {
vNetName = vnet.id.substr(vnet.id.indexOf(vHubPattern) + vHubPattern.length, vnet.id.length);
}
const resourceGroup = vnet.id.match(resourceGroupPattern)[0];
const subscriptionId = vnet.id.match(subscriptionPattern)[0];
const subscriptionName = subscriptions.find(sub => sub.subscription_id === subscriptionId)?.name || 'Unknown';
visibleNets.push(vnet.id);
let node = {
name: vnet.id,
value: vnet.peerings.length, //vnet.id
detail: {
vNetName: vNetName,
resourceGroup: resourceGroup,
subscriptionId: subscriptionId,
subscriptionName: subscriptionName
},
symbolSize: (vnet.peerings.length * factor) + factor,
category: vnet.id,
label: {
@ -421,9 +419,36 @@ function parseNets(data) {
uniqueMissing.forEach((peer) => {
if(!visibleNets.includes(peer.remote_network)) {
const vNetPattern = "/Microsoft.Network/virtualNetworks/";
const vHubPattern = "/Microsoft.Network/virtualHubs/";
const resourceGroupPattern = "(?<=/resourceGroups/).+?(?=/)";
const subscriptionPattern = "(?<=/subscriptions/).+?(?=/)";
var vNetName = '';
if(peer.remote_network.includes(vNetPattern)) {
vNetName = peer.remote_network.substr(peer.remote_network.indexOf(vNetPattern) + vNetPattern.length, peer.remote_network.length);
}
if(peer.remote_network.includes(vHubPattern)) {
vNetName = peer.remote_network.substr(peer.remote_network.indexOf(vHubPattern) + vHubPattern.length, peer.remote_network.length);
}
const resourceGroup = peer.remote_network.match(resourceGroupPattern)[0];
const subscriptionId = peer.remote_network.match(subscriptionPattern)[0];
const subscriptionName = subscriptions.find(sub => sub.subscription_id === subscriptionId)?.name || 'Unknown';
let node = {
name: peer.remote_network,
value: 1,
detail: {
vNetName: vNetName,
resourceGroup: resourceGroup,
subscriptionId: subscriptionId,
subscriptionName: subscriptionName
},
symbol: 'image:///warning.png',
symbolSize: (1 * factor) + factor,
category: 'error',
@ -444,9 +469,54 @@ function parseNets(data) {
let peerArr = [];
item.peerings.forEach((peer) => {
const vNetPattern = "/Microsoft.Network/virtualNetworks/";
const vHubPattern = "/Microsoft.Network/virtualHubs/";
const resourceGroupPattern = "(?<=/resourceGroups/).+?(?=/)";
const subscriptionPattern = "(?<=/subscriptions/).+?(?=/)";
var sourceVnetName = '';
var targetVnetName = '';
if(item.id.includes(vNetPattern)) {
sourceVnetName = item.id.substr(item.id.indexOf(vNetPattern) + vNetPattern.length, item.id.length);
}
if(item.id.includes(vHubPattern)) {
sourceVnetName = item.id.substr(item.id.indexOf(vHubPattern) + vHubPattern.length, item.id.length);
}
if(peer.remote_network.includes(vNetPattern)) {
targetVnetName = peer.remote_network.substr(peer.remote_network.indexOf(vNetPattern) + vNetPattern.length, peer.remote_network.length);
}
if(peer.remote_network.includes(vHubPattern)) {
targetVnetName = peer.remote_network.substr(peer.remote_network.indexOf(vHubPattern) + vHubPattern.length, peer.remote_network.length);
}
const sourceResourceGroup = item.id.match(resourceGroupPattern)[0];
const targetResourceGroup = peer.remote_network.match(resourceGroupPattern)[0];
const sourceSubscriptionId = item.id.match(subscriptionPattern)[0];
const targetSubscriptionId = peer.remote_network.match(subscriptionPattern)[0];
const sourceSubscriptionName = subscriptions.find(sub => sub.subscription_id === sourceSubscriptionId)?.name || 'Unknown';
const targetSubscriptionName = subscriptions.find(sub => sub.subscription_id === targetSubscriptionId)?.name || 'Unknown';
const data = {
source: item.id,
target: peer.remote_network,
detail: {
sourceVnetName: sourceVnetName,
targetVnetName: targetVnetName,
sourceResourceGroup: sourceResourceGroup,
targetResourceGroup: targetResourceGroup,
sourceSubscriptionId: sourceSubscriptionId,
targetSubscriptionId: targetSubscriptionId,
sourceSubscriptionName: sourceSubscriptionName,
targetSubscriptionName: targetSubscriptionName,
state: peer.state
},
lineStyle: {
color: stateMap[peer.state].color,
type: stateMap[peer.state].lineStyle,
@ -674,6 +744,7 @@ const Peering = () => {
const searchRef = React.useRef(null);
const subscriptions = useSelector(selectSubscriptions);
const networks = useSelector(selectNetworks);
const theme = useTheme();
@ -688,14 +759,14 @@ const Peering = () => {
}, []);
React.useEffect(() => {
if(networks) {
let vnetOptions = parseNets(networks);
if(subscriptions && networks) {
let vnetOptions = parseNets(networks, subscriptions);
vnetOptions.darkMode = theme.palette.mode === "dark" ? true : false;
setOptions(vnetOptions);
}
}, [networks, theme]);
}, [subscriptions, networks, theme]);
function filterByVnet(options, target, previousTarget, currentMembers) {
const members = [];

Просмотреть файл

@ -19,6 +19,7 @@ import { cloneDeep, isEmpty } from "lodash";
import {
selectSpaces,
selectSubscriptions,
selectVNets,
selectVHubs,
selectEndpoints
@ -169,6 +170,10 @@ const opt = {
<span style="font-weight: bold">Resource Group:&nbsp;</span>
${d.value.resourceGroup}
</div>
<div class="data">
<span style="font-weight: bold">Subscription Name:&nbsp;</span>
${d.value.subscriptionName}
</div>
<div class="data">
<span style="font-weight: bold">Subscription ID:&nbsp;</span>
${d.value.subscriptionId}
@ -205,6 +210,10 @@ const opt = {
<span style="font-weight: bold">Resource Group:&nbsp;</span>
${d.value.resourceGroup}
</div>
<div class="data">
<span style="font-weight: bold">Subscription Name:&nbsp;</span>
${d.value.subscriptionName}
</div>
<div class="data">
<span style="font-weight: bold">Subscription ID:&nbsp;</span>
${d.value.subscriptionId}
@ -229,6 +238,10 @@ const opt = {
<span style="font-weight: bold">Resource Group:&nbsp;</span>
${d.value.resourceGroup}
</div>
<div class="data">
<span style="font-weight: bold">Subscription Name:&nbsp;</span>
${d.value.subscriptionName}
</div>
<div class="data">
<span style="font-weight: bold">Subscription ID:&nbsp;</span>
${d.value.subscriptionId}
@ -265,6 +278,10 @@ const opt = {
<span style="font-weight: bold">Resource Group:&nbsp;</span>
${d.value.resourceGroup}
</div>
<div class="data">
<span style="font-weight: bold">Subscription Name:&nbsp;</span>
${d.value.subscriptionName}
</div>
<div class="data">
<span style="font-weight: bold">Subscription ID:&nbsp;</span>
${d.value.subscriptionId}
@ -343,7 +360,7 @@ const opt = {
series: []
};
function parseTree(spaces, vnets, vhubs, endpoints) {
function parseTree(spaces, subscriptions, vnets, vhubs, endpoints) {
const series = spaces.map((space) => {
const data = {
name: space.name,
@ -368,6 +385,7 @@ function parseTree(spaces, vnets, vhubs, endpoints) {
parentVWan: target.vwan_name,
resourceGroup: target.resource_group,
subscriptionId: target.subscription_id,
subscriptionName: subscriptions.find((sub) => sub.subscription_id === target.subscription_id)?.name || 'Unknown',
tentantId: target.tenant_id,
prefix: target.prefixes.toString(),
size: target.size
@ -389,6 +407,7 @@ function parseTree(spaces, vnets, vhubs, endpoints) {
name: target.name,
resourceGroup: target.resource_group,
subscriptionId: target.subscription_id,
subscriptionName: subscriptions.find((sub) => sub.subscription_id === target.subscription_id)?.name || 'Unknown',
tentantId: target.tenant_id,
prefixes: target.prefixes,
size: target.size,
@ -404,6 +423,7 @@ function parseTree(spaces, vnets, vhubs, endpoints) {
name: subnet.name,
resourceGroup: target.resource_group,
subscriptionId: target.subscription_id,
subscriptionName: subscriptions.find((sub) => sub.subscription_id === target.subscription_id)?.name || 'Unknown',
tentantId: target.tenant_id,
prefix: subnet.prefix,
size: subnet.size,
@ -419,6 +439,7 @@ function parseTree(spaces, vnets, vhubs, endpoints) {
privateIp: endpoint.private_ip,
resourceGroup: endpoint.resource_group,
subscriptionId: endpoint.subscription_id,
subscriptionName: subscriptions.find((sub) => sub.subscription_id === target.subscription_id)?.name || 'Unknown',
tentantId: endpoint.tenant_id
}
};
@ -594,6 +615,7 @@ const Visualize = () => {
const searchRef = React.useRef(null);
const spaces = useSelector(selectSpaces);
const subscriptions = useSelector(selectSubscriptions);
const vnets = useSelector(selectVNets);
const vhubs = useSelector(selectVHubs);
const endpoints = useSelector(selectEndpoints);
@ -607,12 +629,12 @@ const Visualize = () => {
}, []);
React.useEffect(() => {
if(spaces && vnets && vhubs && endpoints) {
if(spaces && subscriptions && vnets && vhubs && endpoints) {
var newOptions = cloneDeep(opt);
delete newOptions.graphic;
newOptions.darkMode = theme.palette.mode === 'dark' ? true : false;
newOptions.series = parseTree(spaces, vnets, vhubs, endpoints);
newOptions.series = parseTree(spaces, subscriptions, vnets, vhubs, endpoints);
newOptions.legend.data = newOptions.series.map((option) => {
return {
name: option.name,
@ -627,7 +649,7 @@ const Visualize = () => {
})
);
}
}, [spaces, vnets, vhubs, endpoints, theme]);
}, [spaces, subscriptions, vnets, vhubs, endpoints, theme]);
function setDataFocus(target) {
if(eChartsRef && !isEmpty(options.series)) {

Просмотреть файл

@ -313,6 +313,7 @@ export default function EditReservations(props) {
showActiveRowIndicator={false}
enableColumnAutosize={false}
showColumnMenuGroupOptions={false}
showColumnMenuLockOptions={false}
columns={columns}
loading={loading}
loadingText={sending ? <Update>Updating</Update> : "Loading"}

Просмотреть файл

@ -60,7 +60,7 @@ const gridStyle = {
const columns = [
{ name: "name", header: "Name", defaultFlex: 1 },
{ name: "subscription_id", header: "Subscription", defaultFlex: 1 },
{ name: "subscription_id", header: "Subscription", defaultFlex: 1, defaultVisible: false },
{ name: "resource_group", header: "Resource Group", defaultFlex: 1 },
{ name: "prefixes", header: "Prefixes", defaultFlex: 0.75, render: ({value}) => value.join(", ") },
];
@ -76,6 +76,8 @@ export default function EditVnets(props) {
const [sending, setSending] = React.useState(false);
const [refreshing, setRefreshing] = React.useState(false);
const gridRef = React.createRef();
const dispatch = useDispatch();
const theme = useTheme();
@ -197,8 +199,8 @@ export default function EditVnets(props) {
}
return (
<div sx={{ height: "300px", width: "100%" }}>
<Dialog open={open} onClose={handleClose} maxWidth="md" fullWidth>
<div sx={{ height: "400px", width: "100%" }}>
<Dialog open={open} onClose={handleClose} maxWidth="lg" fullWidth>
<DialogTitle>
<Box sx={{ display: "flex", flexDirection: "row" }}>
<Box>
@ -223,7 +225,7 @@ export default function EditVnets(props) {
<Box
sx={{
pt: 4,
height: "300px",
height: "400px",
'& .ipam-block-vnet-stale': {
background: theme.palette.mode === 'dark' ? 'rgb(220, 20, 20) !important' : 'rgb(255, 230, 230) !important',
'.InovuaReactDataGrid__row-hover-target': {
@ -243,6 +245,7 @@ export default function EditVnets(props) {
}}
>
<ReactDataGrid
ref={gridRef}
theme={theme.palette.mode === 'dark' ? "default-dark" : "default-light"}
idProperty="id"
showCellBorders="horizontal"
@ -254,6 +257,10 @@ export default function EditVnets(props) {
showActiveRowIndicator={false}
enableColumnAutosize={false}
showColumnMenuGroupOptions={false}
showColumnMenuLockOptions={false}
columnContextMenuConstrainTo={gridRef.current?.getBoundingClientRect()}
// columnContextMenuPosition={"fixed"}
// updateMenuPositionOnColumnsChange={true}
columns={columns}
loading={sending || refreshing || refreshingState}
loadingText={sending ? <Update>Updating</Update> : "Loading"}

Просмотреть файл

@ -310,6 +310,7 @@ export function fetchNetworks(token) {
export function refreshAll(token) {
const stack = [
(async () => await fetchSpaces(token, true))(),
(async () => await fetchSubscriptions(token, true))(),
(async () => await fetchNetworks(token))(),
(async () => await fetchEndpoints(token))()
];

Просмотреть файл

@ -25,6 +25,7 @@ const initialState = {
isAdmin: false,
spaces: null,
blocks: null,
subscriptions: null,
vNets: null,
vHubs: null,
subnets: null,
@ -278,11 +279,17 @@ export const ipamSlice = createSlice({
});
return space.blocks;
}).flat();
}).flat();
if(action.payload[1].status === 'fulfilled') {
const vNetData = action.payload[1].value.filter((x) => x.id.toLowerCase().includes(vNetProvider.toLowerCase()));
const vHubData = action.payload[1].value.filter((x) => x.id.toLowerCase().includes(vHubProvider.toLowerCase()));
state.subscriptions = action.payload[1].value;
} else {
state.subscriptions = [];
}
if(action.payload[2].status === 'fulfilled') {
const vNetData = action.payload[2].value.filter((x) => x.id.toLowerCase().includes(vNetProvider.toLowerCase()));
const vHubData = action.payload[2].value.filter((x) => x.id.toLowerCase().includes(vHubProvider.toLowerCase()));
const vnets = vNetData.map((vnet) => {
vnet.available = (vnet.size - vnet.used);
@ -329,8 +336,8 @@ export const ipamSlice = createSlice({
state.vHubs = [];
}
if(action.payload[2].status === 'fulfilled') {
const endpoints = action.payload[2].value.map((endpoint) => {
if(action.payload[3].status === 'fulfilled') {
const endpoints = action.payload[3].value.map((endpoint) => {
endpoint.uniqueId = `${endpoint.id}@$${endpoint.private_ip}`
return endpoint;
@ -385,8 +392,19 @@ export const getRefreshing = (state) => state.ipam.refreshing;
export const getDarkMode = (state) => state.ipam.darkMode;
export const getMeLoaded = (state) => state.ipam.meLoaded;
// const subFixup = (data, state) => {
// data?.forEach((item) => {
// let target = state.subscriptions?.find((x) => x.subscription_id === item.subcription_id);
// item['subscription_name'] = target ? target.name : 'Unknown';
// });
// return data;
// };
export const selectSpaces = (state) => state.ipam.spaces;
export const selectBlocks = (state) => state.ipam.blocks;
export const selectSubscriptions = (state) => state.ipam.subscriptions;
export const selectVNets = (state) => state.ipam.vNets;
export const selectVHubs = (state) => state.ipam.vHubs;
export const selectSubnets = (state) => state.ipam.subnets;

Просмотреть файл

@ -2,11 +2,6 @@ import * as React from 'react';
import { useSelector } from 'react-redux';
import { ThemeProvider, createTheme, styled } from '@mui/material/styles';
import { useMsal } from "@azure/msal-react";
import { InteractionRequiredAuthError } from "@azure/msal-browser";
import { useSnackbar } from 'notistack';
import { find } from 'lodash';
import {
@ -33,15 +28,10 @@ import {
} from '@mui/icons-material';
import {
selectSubscriptions,
selectVNets
} from "../ipam/ipamSlice";
import {
fetchSubscriptions
} from "../ipam/ipamAPI";
import { apiRequest } from "../../msal/authConfig";
import { availableSubnets } from './utils/iputils';
const plannerTheme = (theme) => createTheme({
@ -115,12 +105,7 @@ const Separator = (props) => {
};
const Planner = () => {
const { instance, accounts } = useMsal();
const { enqueueSnackbar } = useSnackbar();
const [subscriptions, setSubscriptions] = React.useState(null);
const [newVNets, setNewVNets] = React.useState([]);
const [subnetData, setSubnetData] = React.useState(null);
const [vNetInput, setVNetInput] = React.useState('');
@ -137,43 +122,10 @@ const Planner = () => {
const [showAll, setShowAll] = React.useState(false);
const subsLoadingRef = React.useRef(false);
const subscriptions = useSelector(selectSubscriptions);
const vNets = useSelector(selectVNets);
const loading = !vNets || subsLoadingRef.current;
const refreshSubscriptions = React.useCallback(() => {
const request = {
scopes: apiRequest.scopes,
account: accounts[0],
};
(async () => {
try {
subsLoadingRef.current = true;
const response = await instance.acquireTokenSilent(request);
const data = await fetchSubscriptions(response.accessToken);
setSubscriptions(data);
} catch (e) {
if (e instanceof InteractionRequiredAuthError) {
instance.acquireTokenRedirect(request);
} else {
console.log("ERROR");
console.log("------------------");
console.log(e);
console.log("------------------");
enqueueSnackbar("Error fetching subnets", { variant: "error" });
}
} finally {
subsLoadingRef.current = false;
}
})();
}, [accounts, enqueueSnackbar, instance]);
React.useEffect(() => {
!subsLoadingRef.current && refreshSubscriptions();
}, [vNets, refreshSubscriptions]);
const loading = !vNets || !subscriptions;
React.useEffect(() => {
if (vNets && subscriptions) {