Skip to content

Commit

Permalink
Added a setting to override outbound SSH config and fixed device coun…
Browse files Browse the repository at this point in the history
…t issue.
  • Loading branch information
simonrho committed Aug 5, 2024
1 parent 197e0c9 commit 59a54e1
Show file tree
Hide file tree
Showing 10 changed files with 377 additions and 80 deletions.
2 changes: 1 addition & 1 deletion jccm/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "jccm",
"productName": "Juniper Cloud Connection Manager",
"version": "1.1.0",
"version": "1.1.1",
"description": "Juniper Cloud Connection Manager",
"main": ".webpack/main",
"scripts": {
Expand Down
22 changes: 20 additions & 2 deletions jccm/src/Frontend/Common/StateStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ const useStore = create((set, get) => ({
const orgs = {};
user?.privileges.forEach((item) => {
if (item.scope === 'org') {
const orgId = item.org_id
const orgId = item.org_id;
const orgName = item.name;
orgs[orgId] = orgName;
orgs[orgId] = orgName;
}
});
return { user, orgs };
Expand Down Expand Up @@ -332,6 +332,24 @@ const useStore = create((set, get) => ({
};
}),

cleanUpDeviceFacts: async () => {
const state = get();
const inventoryPaths = new Set(state.inventory.map((item) => item._path));
const cleanedDeviceFacts = Object.fromEntries(
Object.entries(state.deviceFacts).filter(([key]) => inventoryPaths.has(key))
);

console.log('inventoryPaths', inventoryPaths);
console.log('state.deviceFacts', state.deviceFacts);
console.log('cleanedDeviceFacts', cleanedDeviceFacts);

await electronAPI.saSaveDeviceFacts({ facts: cleanedDeviceFacts });

set(() => ({
deviceFacts: cleanedDeviceFacts,
}));
},

deleteDeviceFacts: (path) =>
set((state) => {
const { [path]: _, ...rest } = state.deviceFacts;
Expand Down
2 changes: 1 addition & 1 deletion jccm/src/Frontend/Layout/ChangeIcon.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const CircleIcon = ({ Icon, color = tokens.colorPaletteGreenBorder2, size
width: `calc(${size} + 2px)`,
height: `calc(${size} + 2px)`,
borderRadius: '50%',
border: `2px solid ${color}`,
border: `0.5px solid ${color}`,
}}
>
<Icon style={{ fontSize: size, color: color }} />
Expand Down
8 changes: 4 additions & 4 deletions jccm/src/Frontend/Layout/Devices.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const { electronAPI } = window;

export const adoptDevices = async (device, jsiTerm=false) => {
export const adoptDevices = async (device, jsiTerm=false, deleteOutboundSSHTerm=false) => {
const { address, port, username, password, organization, site } = device;
const response = await electronAPI.saAdoptDevice({ address, port, username, password, organization, site, jsiTerm });
const response = await electronAPI.saAdoptDevice({ address, port, username, password, organization, site, jsiTerm, deleteOutboundSSHTerm });

if (response.adopt) {
return { status: true, result: response.result };
Expand All @@ -12,8 +12,8 @@ export const adoptDevices = async (device, jsiTerm=false) => {
}
};

export const releaseDevices = async (device, serialNumber) => {
const { organization } = device;
export const releaseDevices = async (deviceInfo) => {
const { organization, serialNumber} = deviceInfo;
const response = await electronAPI.saReleaseDevice({ organization, serial: serialNumber });

if (response.release) {
Expand Down
49 changes: 47 additions & 2 deletions jccm/src/Frontend/Layout/Footer.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect } from 'react';
import React, { useEffect, useState } from 'react';

import { Label, Button, tokens } from '@fluentui/react-components';
import { HexagonThreeRegular, HexagonThreeFilled, bundleIcon } from '@fluentui/react-icons';
Expand All @@ -7,12 +7,49 @@ import useStore from '../Common/StateStore';
import { BastionHostButton } from './BastionHostButton';

export default () => {
const { inventory, deviceFacts, cloudDevices } = useStore();
const { isUserLoggedIn, inventory, deviceFacts, cloudDevices, cloudInventory } = useStore();
const [countOfOrgOrSiteUnmatched, setCountOfOrgOrSiteUnmatched] = useState(0);

const countOfDeviceFacts = Object.keys(deviceFacts).length;
const countOfAdoptedDevices = Object.values(deviceFacts).filter(
(facts) => cloudDevices[facts?.serialNumber]
).length;

const doesSiteNameExist = (orgName, siteName) => {
const org = cloudInventory.find((item) => item.name === orgName);

// If the organization is not found, return false
if (!org) {
return false;
}

// Check if the site name exists within the organization's sites array
const siteExists = org.sites.some((site) => site.name === siteName);

return siteExists;
};

const countNonMatchingInventoryItems = () => {
let nonMatchingCount = 0;
inventory.forEach((item) => {
const existence = doesSiteNameExist(item.organization, item.site);
if (!existence) {
nonMatchingCount++;
}
});

return nonMatchingCount;
}

useEffect(() => {
const timer = setTimeout(() => {
const count = countNonMatchingInventoryItems();
setCountOfOrgOrSiteUnmatched(count);
}, 3000); // 3 seconds delay

return () => clearTimeout(timer); // Cleanup timer on component unmount
}, [inventory, cloudDevices]);

return (
<div
style={{
Expand Down Expand Up @@ -44,6 +81,14 @@ export default () => {
>
Adopted Devices: {countOfAdoptedDevices}
</Label>
{isUserLoggedIn && countOfOrgOrSiteUnmatched > 0 && (
<Label
size='small'
style={{ color: tokens.colorNeutralForeground4 }}
>
Devices with unmatched organization or site: {countOfOrgOrSiteUnmatched}
</Label>
)}
</div>
</div>
);
Expand Down
62 changes: 58 additions & 4 deletions jccm/src/Frontend/Layout/GlobalSettings/GeneralCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
export const GeneralCard = () => {
const { settings, setSettings, importSettings, exportSettings } = useStore();
const [jsiTerm, setJsiTerm] = useState(false);
const [deleteOutboundSSHTerm, setDeleteOutboundSSHTerm] = useState(false);

const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
Expand All @@ -49,7 +50,10 @@ export const GeneralCard = () => {
const fetchData = async () => {
importSettings();
await delay(300);

console.log('importing settings', settings);
setJsiTerm(settings?.jsiTerm ? true : false);
setDeleteOutboundSSHTerm(settings?.deleteOutboundSSHTerm ? true : false);
};
fetchData();
}, []);
Expand All @@ -63,15 +67,38 @@ export const GeneralCard = () => {
saveFunction();
};

const handleActive = async (event) => {
const saveDeleteOutboundSSHTerm = (newDeleteOutboundSSHTerm) => {
const saveFunction = async () => {
const newSettings = { ...settings, deleteOutboundSSHTerm: newDeleteOutboundSSHTerm };
setSettings(newSettings);
exportSettings(newSettings);
};
saveFunction();
};

const onChangeJsiTerm = async (event) => {
const checked = event.currentTarget.checked;
setJsiTerm(checked);

saveJsiTerm(checked);
};

const onChangeDeleteOutboundSSHTerm = async (event) => {
const checked = event.currentTarget.checked;
setDeleteOutboundSSHTerm(checked);
saveDeleteOutboundSSHTerm(checked);
};

return (
<div>
<div
style={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'center',
width: '100%',
marginLeft: '10px',
}}
>
<div
style={{
display: 'flex',
Expand All @@ -92,11 +119,38 @@ export const GeneralCard = () => {
>
<Switch
checked={jsiTerm}
onChange={handleActive}
onChange={onChangeJsiTerm}
/>
</div>
<Text>{jsiTerm ? 'Enabled' : 'Disabled'}</Text>
</div>

<div
style={{
display: 'flex',
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center',
gap: '0px',
width: '100%',
marginLeft: '10px',
}}
>
<Text>Override outbound SSH config during adoption:</Text>

<div
style={{
transform: 'scale(0.6)',
transformOrigin: 'right',
}}
>
<Switch
checked={deleteOutboundSSHTerm}
onChange={onChangeDeleteOutboundSSHTerm}
/>
</div>
<Text>{deleteOutboundSSHTerm ? 'Enabled' : 'Disabled'}</Text>
</div>
</div>
);
};
4 changes: 3 additions & 1 deletion jccm/src/Frontend/Layout/InventoryLocalEditForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const { electronAPI } = window;
import * as Constants from '../Common/CommonVariables';
import useStore from '../Common/StateStore';
import { useNotify } from '../Common/NotificationContext';
import eventBus from '../Common/eventBus';

const Dismiss = bundleIcon(DismissFilled, DismissRegular);
const AddCircle = bundleIcon(AddCircleFilled, AddCircleRegular);
Expand Down Expand Up @@ -186,7 +187,8 @@ const InventoryLocalEditForm = ({ isOpen, onClose, title, importedInventory }) =
const onSave = async () => {
setInventory(rowData);
await electronAPI.saSetLocalInventory({ inventory: rowData });
setTimeout(() => {
setTimeout(async () => {
await eventBus.emit('device-facts-cleanup', { notification: false });
onClose();
}, 300);
};
Expand Down
Loading

0 comments on commit 59a54e1

Please sign in to comment.