Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 85 additions & 17 deletions src/components/CippComponents/CippBreadcrumbNav.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,27 @@ export const CippBreadcrumbNav = () => {
const titleCheckCountRef = useRef(0);
const titleCheckIntervalRef = useRef(null);

// Helper function to filter out unnecessary query parameters
const getCleanQueryParams = (query) => {
const cleaned = { ...query };
// Remove tenantFilter if it's "AllTenants" or not explicitly needed
if (cleaned.tenantFilter === "AllTenants" || cleaned.tenantFilter === undefined) {
delete cleaned.tenantFilter;
}
return cleaned;
};

// Helper function to clean page titles
const cleanPageTitle = (title) => {
if (!title) return title;
// Remove AllTenants and any surrounding separators
return title
.replace(/\s*-\s*AllTenants\s*/, "")
.replace(/AllTenants\s*-\s*/, "")
.replace(/AllTenants/, "")
.trim();
};

// Load tab options on mount
useEffect(() => {
loadTabOptions().then(setTabOptions);
Expand Down Expand Up @@ -109,6 +130,9 @@ export const CippBreadcrumbNav = () => {
pageTitle = parts.slice(0, -1).join(" - ").trim();
}

// Clean AllTenants from title
pageTitle = cleanPageTitle(pageTitle);

// Skip if title is empty, generic, or error page
if (
!pageTitle ||
Expand Down Expand Up @@ -155,7 +179,10 @@ export const CippBreadcrumbNav = () => {
if (samePath && !sameTitle) {
// Same URL but title changed - update the entry
const updated = [...prevHistory];
updated[prevHistory.length - 1] = currentPage;
updated[prevHistory.length - 1] = {
...currentPage,
query: getCleanQueryParams(currentPage.query),
};
if (titleCheckIntervalRef.current) {
clearInterval(titleCheckIntervalRef.current);
titleCheckIntervalRef.current = null;
Expand All @@ -173,7 +200,11 @@ export const CippBreadcrumbNav = () => {

// URL not in history (except possibly as last entry which we handled) - add as new entry
if (existingIndex === -1) {
const newHistory = [...prevHistory, currentPage];
const cleanedCurrentPage = {
...currentPage,
query: getCleanQueryParams(currentPage.query),
};
const newHistory = [...prevHistory, cleanedCurrentPage];

// Keep only the last MAX_HISTORY_STORAGE pages
const trimmedHistory =
Expand All @@ -192,7 +223,10 @@ export const CippBreadcrumbNav = () => {
titleCheckIntervalRef.current = null;
}
const updated = prevHistory.slice(0, existingIndex + 1);
updated[existingIndex] = currentPage;
updated[existingIndex] = {
...currentPage,
query: getCleanQueryParams(currentPage.query),
};
return updated;
});
};
Expand All @@ -211,9 +245,10 @@ export const CippBreadcrumbNav = () => {
const handleBreadcrumbClick = (index) => {
const page = history[index];
if (page) {
const cleanedQuery = getCleanQueryParams(page.query);
router.push({
pathname: page.path,
query: page.query,
query: cleanedQuery,
});
}
};
Expand Down Expand Up @@ -247,15 +282,18 @@ export const CippBreadcrumbNav = () => {
return;
}

const pageTitle = document.title.replace(" - CIPP", "").trim();
let pageTitle = document.title.replace(" - CIPP", "").trim();
const parts = pageTitle.split(" - ");
const cleanTitle =
parts.length > 1 && parts[parts.length - 1].includes(".")
? parts.slice(0, -1).join(" - ").trim()
: pageTitle;

if (cleanTitle && cleanTitle !== "CIPP" && !cleanTitle.toLowerCase().includes("loading")) {
setCurrentPageTitle(cleanTitle);
// Clean AllTenants from title
const finalTitle = cleanPageTitle(cleanTitle);

if (finalTitle && finalTitle !== "CIPP" && !finalTitle.toLowerCase().includes("loading")) {
setCurrentPageTitle(finalTitle);
// Stop checking once we have a valid title
if (hierarchicalTitleCheckRef.current) {
clearInterval(hierarchicalTitleCheckRef.current);
Expand Down Expand Up @@ -316,11 +354,11 @@ export const CippBreadcrumbNav = () => {

// Check if this item matches the current path
if (item.path && pathsMatch(item.path, currentPath)) {
// If this is the current page, include current query params
// If this is the current page, include current query params (cleaned)
if (item.path === currentPath) {
const lastItem = currentBreadcrumb[currentBreadcrumb.length - 1];
if (lastItem) {
lastItem.query = { ...router.query };
lastItem.query = getCleanQueryParams(router.query);
}
}
return currentBreadcrumb;
Expand All @@ -339,6 +377,32 @@ export const CippBreadcrumbNav = () => {

let result = findPathInMenu(nativeMenuItems);

// If we found a menu item, check if the current path matches any tab
// If so, tabOptions wins and we use its label
if (result.length > 0 && tabOptions.length > 0) {
const normalizedCurrentPath = currentPath.replace(/\/$/, "");

// Check if current path matches any tab (exact match)
const matchingTab = tabOptions.find((tab) => {
const normalizedTabPath = tab.path.replace(/\/$/, "");
return normalizedTabPath === normalizedCurrentPath;
});

if (matchingTab) {
// Tab matches the current path - use tab's label instead of config's
result = result.map((item, idx) => {
if (idx === result.length - 1) {
return {
...item,
title: matchingTab.title,
type: "tab",
};
}
return item;
});
}
}

// If not found in main menu, check if it's a tab page
if (result.length === 0 && tabOptions.length > 0) {
const normalizedCurrentPath = currentPath.replace(/\/$/, "");
Expand Down Expand Up @@ -395,12 +459,12 @@ export const CippBreadcrumbNav = () => {
if (basePagePath.length > 0) {
result = basePagePath;

// Add the tab as the final breadcrumb with current query params
// Add the tab as the final breadcrumb with current query params (cleaned)
result.push({
title: matchingTab.title,
path: matchingTab.path,
type: "tab",
query: { ...router.query }, // Include current query params for tab page
query: getCleanQueryParams(router.query), // Include current query params for tab page
});
}
}
Expand All @@ -411,7 +475,10 @@ export const CippBreadcrumbNav = () => {
const lastItem = result[result.length - 1];
if (lastItem.path && lastItem.path !== currentPath && currentPath.startsWith(lastItem.path)) {
// Use the tracked page title if available, otherwise fall back to document.title
const tabTitle = currentPageTitle || document.title.replace(" - CIPP", "").trim();
let tabTitle = currentPageTitle || document.title.replace(" - CIPP", "").trim();

// Clean AllTenants from title
tabTitle = cleanPageTitle(tabTitle);

// Add tab as an additional breadcrumb item
if (
Expand All @@ -423,7 +490,7 @@ export const CippBreadcrumbNav = () => {
title: tabTitle,
path: currentPath,
type: "tab",
query: { ...router.query }, // Include current query params
query: getCleanQueryParams(router.query), // Include current query params (cleaned)
});
}
}
Expand All @@ -435,10 +502,11 @@ export const CippBreadcrumbNav = () => {
// Handle click for hierarchical breadcrumbs
const handleHierarchicalClick = (path, query) => {
if (path) {
if (query && Object.keys(query).length > 0) {
const cleanedQuery = getCleanQueryParams(query);
if (cleanedQuery && Object.keys(cleanedQuery).length > 0) {
router.push({
pathname: path,
query: query,
query: cleanedQuery,
});
} else {
router.push(path);
Expand Down Expand Up @@ -478,7 +546,7 @@ export const CippBreadcrumbNav = () => {
title,
path,
type: "fallback",
query: index === pathSegments.length - 1 ? { ...router.query } : {},
query: index === pathSegments.length - 1 ? getCleanQueryParams(router.query) : {},
};
});

Expand All @@ -488,7 +556,7 @@ export const CippBreadcrumbNav = () => {
currentPageTitle !== "CIPP" &&
!currentPageTitle.toLowerCase().includes("loading")
) {
breadcrumbs[breadcrumbs.length - 1].title = currentPageTitle;
breadcrumbs[breadcrumbs.length - 1].title = cleanPageTitle(currentPageTitle);
}
}
}
Expand Down
61 changes: 30 additions & 31 deletions src/components/CippComponents/CippTenantSelector.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ export const CippTenantSelector = (props) => {
// Cancel all in-flight queries before changing tenant
queryClient.cancelQueries();

// Update router and settings
// Update router only - let the URL watcher handle settings
query.tenantFilter = currentTenant.value;
router.replace(
{
Expand All @@ -194,53 +194,52 @@ export const CippTenantSelector = (props) => {
undefined,
{ shallow: true }
);

settings.handleUpdate({
currentTenant: currentTenant.value,
});
}
//if we have a tenantfilter, we add the tenantfilter to the title of the tab/page so its "Tenant - original title".
}
}, [currentTenant?.value]);

// This effect handles when the URL parameter changes externally
// This effect handles when the URL parameter changes (from deep link or user selection)
// This is the single source of truth for tenant changes
useEffect(() => {
if (!router.isReady || !tenantList.isSuccess || !settings.isInitialized) return;
if (!router.isReady || !tenantList.isSuccess) return;

// Get the current tenant from URL or settings
const urlTenant = router.query.tenantFilter || settings.currentTenant;
const urlTenant = router.query.tenantFilter;

// Only update if there's a URL tenant and it's different from our current state
if (urlTenant && (!currentTenant || urlTenant !== currentTenant.value)) {
// Only process if we have a URL tenant
if (urlTenant) {
// Find the tenant in our list
const matchingTenant = tenantList.data.find(
({ defaultDomainName }) => defaultDomainName === urlTenant
);

if (matchingTenant) {
setSelectedTenant({
value: urlTenant,
label: `${matchingTenant.displayName} (${urlTenant})`,
addedFields: {
defaultDomainName: matchingTenant.defaultDomainName,
displayName: matchingTenant.displayName,
customerId: matchingTenant.customerId,
initialDomainName: matchingTenant.initialDomainName,
},
});
// Update local state if different
if (!currentTenant || urlTenant !== currentTenant.value) {
setSelectedTenant({
value: urlTenant,
label: `${matchingTenant.displayName} (${urlTenant})`,
addedFields: {
defaultDomainName: matchingTenant.defaultDomainName,
displayName: matchingTenant.displayName,
customerId: matchingTenant.customerId,
initialDomainName: matchingTenant.initialDomainName,
},
});
}

// Update settings if different (null filter in settings-context prevents saving null)
if (settings.currentTenant !== urlTenant) {
settings.handleUpdate({
currentTenant: urlTenant,
});
}
}
}
}, [
router.isReady,
router.query.tenantFilter,
tenantList.isSuccess,
settings.currentTenant,
settings.isInitialized,
]);
}, [router.isReady, router.query.tenantFilter, tenantList.isSuccess]);

// This effect ensures the tenant filter parameter is included in the URL when missing
useEffect(() => {
if (!router.isReady || !settings.isInitialized || !settings.currentTenant) return;
if (!router.isReady || !settings.currentTenant) return;

// If the tenant parameter is missing from the URL but we have it in settings
if (!router.query.tenantFilter && settings.currentTenant) {
Expand All @@ -254,7 +253,7 @@ export const CippTenantSelector = (props) => {
{ shallow: true }
);
}
}, [router.isReady, router.query, settings.currentTenant, settings.isInitialized]);
}, [router.isReady, router.query.tenantFilter, settings.currentTenant]);

useEffect(() => {
if (tenant && currentTenant?.value && currentTenant?.value !== "AllTenants") {
Expand Down
2 changes: 1 addition & 1 deletion src/components/CippStandards/CippStandardsSideBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ const CippStandardsSideBar = ({
title="Add Standard"
api={{
confirmText: isDriftMode
? "This template will automatically every hour to detect drift. Are you sure you want to apply this Drift Template?"
? "This template will automatically every 12 hours to detect drift. Are you sure you want to apply this Drift Template?"
: watchForm.runManually
? "Are you sure you want to apply this standard? This template has been set to never run on a schedule. After saving the template you will have to run it manually."
: "Are you sure you want to apply this standard? This will apply the template and run every 3 hours.",
Expand Down
2 changes: 1 addition & 1 deletion src/layouts/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ export const nativeMenuItems = [
items: [
{
title: "Standards Management",
path: "/tenant/standards/list-standards",
path: "/tenant/standards/alignment",
permissions: ["Tenant.Standards.*"],
},
{
Expand Down
10 changes: 2 additions & 8 deletions src/pages/endpoint/MEM/devices/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,7 @@ const Page = () => {
GUID: "id",
Action: "resetPasscode",
},
condition: (row) =>
row.operatingSystem === "iOS" ||
row.operatingSystem === "macOS" ||
row.operatingSystem === "Android",
condition: (row) => row.operatingSystem === "Android",
confirmText:
"Are you sure you want to reset the passcode for [deviceName]? A new passcode will be generated and displayed.",
},
Expand All @@ -194,10 +191,7 @@ const Page = () => {
GUID: "id",
Action: "removeDevicePasscode",
},
condition: (row) =>
row.operatingSystem === "iOS" ||
row.operatingSystem === "macOS" ||
row.operatingSystem === "Android",
condition: (row) => row.operatingSystem === "iOS",
confirmText:
"Are you sure you want to remove the passcode from [deviceName]? This will remove the device passcode requirement.",
},
Expand Down
2 changes: 1 addition & 1 deletion src/pages/tenant/administration/tenants/groups/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ const Page = () => {
dynamicRules: formattedDynamicRules,
});
}
}, [groupDetails.isSuccess, groupDetails.data]);
}, [groupDetails.isSuccess, groupDetails.data, id]);

const customDataFormatter = (values) => {
const formattedData = {
Expand Down
6 changes: 4 additions & 2 deletions src/pages/tenant/manage/driftManagementActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,13 @@ export const createDriftManagementActions = ({
// Use Next.js router for internal navigation
import("next/router")
.then(({ default: router }) => {
router.push(`/tenant/standards/template?id=${templateId}&type=${templateType}`);
router.push(
`/tenant/standards/templates/template?id=${templateId}&type=${templateType}`
);
})
.catch(() => {
// Fallback to window.location if router is not available
window.location.href = `/tenant/standards/template?id=${templateId}&type=${templateType}`;
window.location.href = `/tenant/standards/templates/template?id=${templateId}&type=${templateType}`;
});
},
});
Expand Down
Loading