diff --git a/jccm/src/Frontend/Components/Login.js b/jccm/src/Frontend/Components/Login.js index 5c97fb2..fbdf1ea 100644 --- a/jccm/src/Frontend/Components/Login.js +++ b/jccm/src/Frontend/Components/Login.js @@ -56,6 +56,7 @@ export const Login = ({ isOpen, onClose }) => { setIsUserLoggedIn, setCurrentActiveThemeName, getConsoleWindowWidth, + settings, } = useStore(); const { showMessageBar } = useMessageBar(); const [cloudList, setCloudList] = useState([]); @@ -95,6 +96,8 @@ export const Login = ({ isOpen, onClose }) => { const [isGoogleSSOLogin, setIsGoogleSSOLogin] = useState(false); + const ignoreCaseInName = settings?.ignoreCaseInName || false; + const togglePasswordVisibility = () => { setPasswordVisible(!passwordVisible); @@ -247,7 +250,7 @@ export const Login = ({ isOpen, onClose }) => { return { status: 'two_factor' }; } else { // console.log('Login successful!'); - // await eventBus.emit('cloud-inventory-refresh'); + // await eventBus.emit('cloud-inventory-refresh', {force: true, ignoreCaseInName}); return { status: 'success', @@ -294,9 +297,10 @@ export const Login = ({ isOpen, onClose }) => { Constants.getActiveThemeName(data?.user?.theme) ); - setTimeout(async () => { - await eventBus.emit('cloud-inventory-refresh'); - }, 1000); + await eventBus.emit('cloud-inventory-refresh', { + force: true, + ignoreCaseInName, + }); onClose(); } else if (response.status === 'two_factor') { diff --git a/jccm/src/Frontend/Layout/Contents.js b/jccm/src/Frontend/Layout/Contents.js deleted file mode 100644 index e69de29..0000000 diff --git a/jccm/src/Frontend/Layout/Devices.js b/jccm/src/Frontend/Layout/Devices.js index fa501f9..385f582 100644 --- a/jccm/src/Frontend/Layout/Devices.js +++ b/jccm/src/Frontend/Layout/Devices.js @@ -11,11 +11,9 @@ export const getDeviceFacts = async (device, upperSerialNumber=false, bastionHos } }; -export const adoptDevices = async (device, jsiTerm=false, deleteOutboundSSHTerm=false, bastionHost = {}) => { +export const adoptDevices = async (device, jsiTerm=false, deleteOutboundSSHTerm=false, bastionHost = {}, ignoreCaseInName = false) => { const { address, port, username, password, organization, site } = device; - const response = await electronAPI.saAdoptDevice({ address, port, username, password, organization, site, jsiTerm, deleteOutboundSSHTerm, bastionHost }); - - // console.log('>>>>adoptDevices -> response: ', response); + const response = await electronAPI.saAdoptDevice({ address, port, username, password, organization, site, jsiTerm, deleteOutboundSSHTerm, bastionHost, ignoreCaseInName }); if (response?.adopt) { return { status: true, result: response.reply }; @@ -26,8 +24,8 @@ export const adoptDevices = async (device, jsiTerm=false, deleteOutboundSSHTerm= }; export const releaseDevices = async (deviceInfo) => { - const { organization, serialNumber} = deviceInfo; - const response = await electronAPI.saReleaseDevice({ organization, serial: serialNumber }); + const { organization, serialNumber, ignoreCaseInName = false} = deviceInfo; + const response = await electronAPI.saReleaseDevice({ organization, serial: serialNumber, ignoreCaseInName }); if (response.release) { return { status: true, result: response.reply }; diff --git a/jccm/src/Frontend/Layout/GlobalSettings/GeneralCard.js b/jccm/src/Frontend/Layout/GlobalSettings/GeneralCard.js index 70145a2..1e4a40e 100644 --- a/jccm/src/Frontend/Layout/GlobalSettings/GeneralCard.js +++ b/jccm/src/Frontend/Layout/GlobalSettings/GeneralCard.js @@ -62,6 +62,15 @@ export const GeneralCard = () => { saveFunction(); }; + const saveIgnoreCase = (newIgnoreCase) => { + const saveFunction = async () => { + const newSettings = { ...settings, ignoreCase: newIgnoreCase }; + setSettings(newSettings); + exportSettings(newSettings); + }; + saveFunction(); + }; + const saveDeleteOutboundSSHTerm = (newDeleteOutboundSSHTerm) => { const saveFunction = async () => { const newSettings = { @@ -93,6 +102,12 @@ export const GeneralCard = () => { saveDeleteOutboundSSHTerm(checked); }; + const onChangeIgnoreCase = async (event) => { + const checked = event.currentTarget.checked; + saveIgnoreCase(checked); + }; + + return (
{ {settings.jsiTerm ? 'Enabled' : 'Disabled'}
+
+ Ignore case of org name and site name: +
+ +
+ {settings.ignoreCase ? 'Enabled' : 'Disabled'} +
+
{ return ( -
+
{ }; return ( -
+
{isOpen && ( <> {isSelected ? ( @@ -265,16 +293,28 @@ const AsideView = ({ path, device }) => { }; const convertToFlatTreeItems = (localInventory, deviceFacts) => { - if (!localInventory || !Array.isArray(localInventory) || localInventory.length === 0) return []; + if ( + !localInventory || + !Array.isArray(localInventory) || + localInventory.length === 0 + ) + return []; const flatTreeItems = []; const organizationMap = new Map(); // Add root node - flatTreeItems.push({ value: '/Inventory', content: 'Inventory Layout', icon: null, counter: 0, type: 'root' }); + flatTreeItems.push({ + value: '/Inventory', + content: 'Inventory Layout', + icon: null, + counter: 0, + type: 'root', + }); localInventory.forEach((item) => { - const { organization, site, address, port, username, password, _path } = item; + const { organization, site, address, port, username, password, _path } = + item; const facts = deviceFacts[_path] || {}; if (!organizationMap.has(organization)) { @@ -331,7 +371,12 @@ const convertToFlatTreeItems = (localInventory, deviceFacts) => { value: `/Inventory/${organization}`, content: organization, icon: ( - + ), // Placeholder for icon, replace with actual icon if needed counter: orgData.counter, type: 'org', @@ -344,7 +389,10 @@ const convertToFlatTreeItems = (localInventory, deviceFacts) => { content: site, icon: ( ), // Placeholder for icon, replace with actual icon if needed counter: siteData.counter, @@ -356,7 +404,10 @@ const convertToFlatTreeItems = (localInventory, deviceFacts) => { }); // Update root counter - flatTreeItems[0].counter = flatTreeItems.reduce((acc, item) => acc + (item.type === 'device' ? 1 : 0), 0); + flatTreeItems[0].counter = flatTreeItems.reduce( + (acc, item) => acc + (item.type === 'device' ? 1 : 0), + 0 + ); return flatTreeItems; }; @@ -365,8 +416,20 @@ const InventoryTreeMenuLocal = () => { const { showContextMenu } = useContextMenu(); const { notify } = useNotify(); const { isUserLoggedIn, orgs, settings } = useStore(); - const { tabs, addTab, setSelectedTabValue, adoptConfig, inventory, setInventory } = useStore(); - const { cloudInventory, setCloudInventory, setCloudInventoryFilterApplied, cloudDevices } = useStore(); + const { + tabs, + addTab, + setSelectedTabValue, + adoptConfig, + inventory, + setInventory, + } = useStore(); + const { + cloudInventory, + setCloudInventory, + setCloudInventoryFilterApplied, + cloudDevices, + } = useStore(); const { isChecking, setIsChecking, resetIsChecking } = useStore(); const { deviceFacts, setDeviceFacts, deleteDeviceFacts } = useStore(); @@ -378,6 +441,7 @@ const InventoryTreeMenuLocal = () => { return new Set(flatTreeItems.map((item) => item.value)); }); + const ignoreCaseInName = settings.ignoreCase || false; const deviceFactsRef = useRef(deviceFacts); useEffect(() => { @@ -407,7 +471,12 @@ const InventoryTreeMenuLocal = () => { typeof value !== 'object' || value === null ? (
{ > {key}: - + {String(value)}
@@ -428,10 +494,25 @@ const InventoryTreeMenuLocal = () => { ); }; + const findFact = (path) => { + // Find the fact based on the path, considering case sensitivity + const factKey = Object.keys(deviceFacts).find((key) => + ignoreCaseInName + ? key.toLowerCase() === path.toLowerCase() + : key === path + ); + + if (!factKey) return undefined; // Return an empty object if no match is found + const fact = deviceFacts[factKey]; + + return fact; + }; + const findCloudDevice = (path) => { - const fact = deviceFacts[path] || {}; + const fact = findFact(path); + if (!fact) return undefined; // Return an empty object if no match is found - if (fact.vc) { + if (fact?.vc) { for (const member of fact.vc) { const device = cloudDevices[member.serial]; if (device) return device; @@ -461,13 +542,31 @@ const InventoryTreeMenuLocal = () => { const deviceOrgName = device.orgName; const deviceSiteName = device.siteName; - setIsOrgMatch(cloudOrgName === deviceOrgName); - setIsSiteMatch(cloudSiteName === deviceSiteName); + // Check org and site name with case sensitivity based on ignoreCaseInName + if (ignoreCaseInName) { + setIsOrgMatch( + cloudOrgName?.toLowerCase() === + deviceOrgName?.toLowerCase() + ); + setIsSiteMatch( + cloudSiteName?.toLowerCase() === + deviceSiteName?.toLowerCase() + ); + } else { + setIsOrgMatch(cloudOrgName === deviceOrgName); + setIsSiteMatch(cloudSiteName === deviceSiteName); + } } setIsAdopted(adopted); }, [cloudDevices, device]); - const IconWithTooltip = ({ content, relationship, Icon, size, color }) => ( + const IconWithTooltip = ({ + content, + relationship, + Icon, + size, + color, + }) => ( { ); const orgMismatchContent = ( -
+
- The organization name ({device.orgName}) does not exist in your account: + The organization name ({device.orgName}) does not + exist in your account: - + {`"${device.orgName}" ≠ "${foundCloudDevice?.org_name}"`}
); const siteMismatchContent = ( -
+
- The site name ({device.siteName}) does not exist in your account: + The site name ({device.siteName}) does not exist in + your account: - + {`"${device.siteName}" ≠ "${foundCloudDevice?.site_name}"`}
@@ -607,22 +714,45 @@ const InventoryTreeMenuLocal = () => { const deviceFact = deviceFacts[path] || null; const vcMembers = deviceFact?.vc || []; - const deviceName = parseInt(device.port, 10) === 22 ? device.address : `${device.address}:${device.port}`; - const cloudDevice = cloudDevices[deviceFact?.systemInformation?.serialNumber]; + const deviceName = + parseInt(device.port, 10) === 22 + ? device.address + : `${device.address}:${device.port}`; + const cloudDevice = + cloudDevices[deviceFact?.systemInformation?.serialNumber]; let facts = []; if (deviceFact) { facts = [ - { key: 'Hardware Model', value: deviceFact.systemInformation?.hardwareModel }, + { + key: 'Hardware Model', + value: deviceFact.systemInformation?.hardwareModel, + }, { key: 'OS Name', value: deviceFact.systemInformation?.osName }, - { key: 'OS Version', value: deviceFact.systemInformation?.osVersion }, - { key: 'Serial Number', value: deviceFact.systemInformation?.serialNumber }, - { key: 'Host Name', value: deviceFact.systemInformation?.hostName }, + { + key: 'OS Version', + value: deviceFact.systemInformation?.osVersion, + }, + { + key: 'Serial Number', + value: deviceFact.systemInformation?.serialNumber, + }, + { + key: 'Host Name', + value: deviceFact.systemInformation?.hostName, + }, ]; } return ( -
+
{deviceFact && !isChecking?.status ? ( vcMembers.length > 0 ? (