Skip to content

Commit 71cafe1

Browse files
authored
Merge pull request #66 from KelvinTegelaar/main
[pull] main from KelvinTegelaar:main
2 parents d33a328 + 16146ca commit 71cafe1

File tree

16 files changed

+193
-168
lines changed

16 files changed

+193
-168
lines changed

generate-placeholders.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ const pages = [
4343
{ title: "BPA Report Builder", path: "/tenant/tools/bpa-report-builder" },
4444
{ title: "Standards", path: "/tenant/standards" },
4545
{ title: "Edit Standards", path: "/tenant/standards/list-applied-standards" },
46-
{ title: "List Standards", path: "/tenant/standards/list-standards" },
46+
{ title: "List Standards", path: "/tenant/standards" },
4747
{ title: "Best Practice Analyser", path: "/tenant/standards/bpa-report" },
4848
{ title: "Domains Analyser", path: "/tenant/standards/domains-analyser" },
4949
{ title: "Conditional Access", path: "/tenant/administration" },

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cipp",
3-
"version": "8.8.1",
3+
"version": "8.8.2",
44
"author": "CIPP Contributors",
55
"homepage": "https://cipp.app/",
66
"bugs": {

public/version.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"version": "8.8.1"
2+
"version": "8.8.2"
33
}

src/components/CippComponents/CippBreadcrumbNav.jsx

Lines changed: 80 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ async function loadTabOptions() {
1616
"/email/administration/exchange-retention",
1717
"/cipp/custom-data",
1818
"/cipp/super-admin",
19-
"/tenant/standards/list-standards",
19+
"/tenant/standards",
2020
"/tenant/manage",
2121
"/tenant/administration/applications",
2222
"/tenant/administration/tenants",
@@ -499,6 +499,46 @@ export const CippBreadcrumbNav = () => {
499499
return result;
500500
};
501501

502+
// Check if a path is valid and return its title from navigation or tabs
503+
const getPathInfo = (path) => {
504+
if (!path) return { isValid: false, title: null };
505+
506+
const normalizedPath = path.replace(/\/$/, "");
507+
508+
// Helper function to recursively search menu items
509+
const findInMenu = (items) => {
510+
for (const item of items) {
511+
if (item.path) {
512+
const normalizedItemPath = item.path.replace(/\/$/, "");
513+
if (normalizedItemPath === normalizedPath) {
514+
return { isValid: true, title: item.title };
515+
}
516+
}
517+
if (item.items && item.items.length > 0) {
518+
const found = findInMenu(item.items);
519+
if (found.isValid) {
520+
return found;
521+
}
522+
}
523+
}
524+
return { isValid: false, title: null };
525+
};
526+
527+
// Check if path exists in navigation
528+
const menuResult = findInMenu(nativeMenuItems);
529+
if (menuResult.isValid) {
530+
return menuResult;
531+
}
532+
533+
// Check if path exists in tab options
534+
const matchingTab = tabOptions.find((tab) => tab.path.replace(/\/$/, "") === normalizedPath);
535+
if (matchingTab) {
536+
return { isValid: true, title: matchingTab.title };
537+
}
538+
539+
return { isValid: false, title: null };
540+
};
541+
502542
// Handle click for hierarchical breadcrumbs
503543
const handleHierarchicalClick = (path, query) => {
504544
if (path) {
@@ -580,6 +620,9 @@ export const CippBreadcrumbNav = () => {
580620
>
581621
{breadcrumbs.map((crumb, index) => {
582622
const isLast = index === breadcrumbs.length - 1;
623+
const pathInfo = getPathInfo(crumb.path);
624+
// Use title from nav/tabs if available, otherwise use the crumb's title
625+
const displayTitle = pathInfo.title || crumb.title;
583626

584627
// Items without paths (headers/groups) - show as text
585628
if (!crumb.path) {
@@ -590,31 +633,46 @@ export const CippBreadcrumbNav = () => {
590633
variant="subtitle2"
591634
sx={{ fontWeight: isLast ? 500 : 400 }}
592635
>
593-
{crumb.title}
636+
{displayTitle}
594637
</Typography>
595638
);
596639
}
597640

598-
// All items with paths are clickable, including the last one
599-
return (
600-
<Link
601-
key={index}
602-
component="button"
603-
variant="subtitle2"
604-
onClick={() => handleHierarchicalClick(crumb.path, crumb.query)}
605-
sx={{
606-
textDecoration: "none",
607-
color: isLast ? "text.primary" : "text.secondary",
608-
fontWeight: isLast ? 500 : 400,
609-
"&:hover": {
610-
textDecoration: "underline",
611-
color: "primary.main",
612-
},
613-
}}
614-
>
615-
{crumb.title}
616-
</Link>
617-
);
641+
// Items with valid paths are clickable
642+
// Items with invalid paths (fallback) are shown as plain text
643+
if (pathInfo.isValid) {
644+
return (
645+
<Link
646+
key={index}
647+
component="button"
648+
variant="subtitle2"
649+
onClick={() => handleHierarchicalClick(crumb.path, crumb.query)}
650+
sx={{
651+
textDecoration: "none",
652+
color: isLast ? "text.primary" : "text.secondary",
653+
fontWeight: isLast ? 500 : 400,
654+
"&:hover": {
655+
textDecoration: "underline",
656+
color: "primary.main",
657+
},
658+
}}
659+
>
660+
{displayTitle}
661+
</Link>
662+
);
663+
} else {
664+
// Invalid path - show as text only
665+
return (
666+
<Typography
667+
key={index}
668+
color={isLast ? "text.primary" : "text.secondary"}
669+
variant="subtitle2"
670+
sx={{ fontWeight: isLast ? 500 : 400 }}
671+
>
672+
{displayTitle}
673+
</Typography>
674+
);
675+
}
618676
})}
619677
</Breadcrumbs>
620678
</Box>

src/components/CippComponents/CippCADeployDrawer.jsx

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import CippJsonView from "../CippFormPages/CippJSONView";
99
import { CippApiResults } from "./CippApiResults";
1010
import { useSettings } from "../../hooks/use-settings";
1111
import { CippFormTenantSelector } from "./CippFormTenantSelector";
12+
import { CippFormCondition } from "./CippFormCondition";
1213

1314
export const CippCADeployDrawer = ({
1415
buttonText = "Deploy CA Policy",
@@ -24,6 +25,10 @@ export const CippCADeployDrawer = ({
2425
const CATemplates = ApiGetCall({ url: "/api/ListCATemplates", queryKey: "CATemplates" });
2526
const [JSONData, setJSONData] = useState();
2627
const watcher = useWatch({ control: formControl.control, name: "TemplateList" });
28+
const selectedReplaceMode = useWatch({
29+
control: formControl.control,
30+
name: "replacename",
31+
});
2732

2833
// Use external open state if provided, otherwise use internal state
2934
const drawerVisible = open !== null ? open : internalDrawerVisible;
@@ -199,13 +204,25 @@ export const CippCADeployDrawer = ({
199204
label="Disable Security Defaults if enabled when creating policy"
200205
formControl={formControl}
201206
/>
202-
203-
<CippFormComponent
204-
type="switch"
205-
name="CreateGroups"
206-
label="Create groups if they do not exist"
207+
<CippFormCondition
207208
formControl={formControl}
208-
/>
209+
field="replacename"
210+
compareType="is"
211+
compareValue="displayName"
212+
action="disable"
213+
>
214+
<CippFormComponent
215+
type="switch"
216+
name="CreateGroups"
217+
label="Create groups if they do not exist"
218+
formControl={formControl}
219+
helperText={
220+
selectedReplaceMode !== "displayName"
221+
? "Select 'Replace by display name' to create groups specified in the template."
222+
: "Enable this option to create groups that do not exist in the tenant."
223+
}
224+
/>
225+
</CippFormCondition>
209226
</Stack>
210227
</CippOffCanvas>
211228
</>

src/components/CippComponents/CippCentralSearch.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ async function loadTabOptions() {
4646
"/email/administration/exchange-retention",
4747
"/cipp/custom-data",
4848
"/cipp/super-admin",
49-
"/tenant/standards/list-standards",
49+
"/tenant/standards",
5050
"/tenant/manage",
5151
"/tenant/administration/applications",
5252
"/tenant/administration/tenants",

src/components/CippComponents/CippFormCondition.jsx

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const CippFormCondition = (props) => {
1818

1919
if (
2020
field === undefined ||
21-
compareValue === undefined ||
21+
(compareValue === undefined && compareType !== "hasValue") ||
2222
children === undefined ||
2323
formControl === undefined
2424
) {
@@ -148,10 +148,18 @@ export const CippFormCondition = (props) => {
148148
watcher.length >= compareValue
149149
);
150150
case "hasValue":
151-
return (
152-
(watcher !== undefined && watcher !== null && watcher !== "") ||
153-
(watcher?.value !== undefined && watcher?.value !== null && watcher?.value !== "")
154-
);
151+
// Check watchedValue (the extracted value based on propertyName)
152+
// For simple values (strings, numbers)
153+
if (watchedValue === undefined || watchedValue === null || watchedValue === "") {
154+
return false;
155+
}
156+
// If it's an array, check if it has elements
157+
if (Array.isArray(watchedValue)) {
158+
return watchedValue.length > 0;
159+
}
160+
console.log("watched value:", watchedValue);
161+
// For any other truthy value (objects, numbers, strings), consider it as having a value
162+
return true;
155163
case "labelEq":
156164
return Array.isArray(watcher) && watcher.some((item) => item?.label === compareValue);
157165
case "labelContains":

src/components/CippComponents/CippRestoreBackupDrawer.jsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { ApiPostCall } from "../../api/ApiCall";
1313
export const CippRestoreBackupDrawer = ({
1414
buttonText = "Restore Backup",
1515
backupName = null,
16+
backupData = null,
1617
requiredPermissions = [],
1718
PermissionButton = Button,
1819
...props
@@ -85,7 +86,12 @@ export const CippRestoreBackupDrawer = ({
8586
const values = formControl.getValues();
8687
const startDate = new Date();
8788
const unixTime = Math.floor(startDate.getTime() / 1000) - 45;
88-
const tenantFilterValue = tenantFilter;
89+
90+
// If in AllTenants context, use the tenant from the backup data
91+
let tenantFilterValue = tenantFilter;
92+
if (tenantFilter === "AllTenants" && backupData?.tenantSource) {
93+
tenantFilterValue = backupData.tenantSource;
94+
}
8995

9096
const shippedValues = {
9197
TenantFilter: tenantFilterValue,
@@ -202,7 +208,12 @@ export const CippRestoreBackupDrawer = ({
202208
queryKey: `BackupList-${tenantFilter}-autocomplete`,
203209
labelField: (option) => {
204210
const match = option.BackupName.match(/.*_(\d{4}-\d{2}-\d{2})-(\d{2})(\d{2})/);
205-
return match ? `${match[1]} @ ${match[2]}:${match[3]}` : option.BackupName;
211+
const dateTime = match
212+
? `${match[1]} @ ${match[2]}:${match[3]}`
213+
: option.BackupName;
214+
const tenantDisplay =
215+
tenantFilter === "AllTenants" ? ` (${option.TenantFilter})` : "";
216+
return `${dateTime}${tenantDisplay}`;
206217
},
207218
valueField: "BackupName",
208219
data: {

src/components/CippStandards/CippStandardsSideBar.jsx

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -144,34 +144,12 @@ const CippStandardsSideBar = ({
144144
}
145145

146146
// Filter out current template if editing
147-
console.log("Duplicate detection debug:", {
148-
edit,
149-
currentGUID: watchForm.GUID,
150-
allTemplates: driftValidationApi.data?.map((t) => ({
151-
GUID: t.GUID,
152-
standardId: t.standardId,
153-
standardName: t.standardName,
154-
})),
155-
});
156-
157147
const existingTemplates = driftValidationApi.data.filter((template) => {
158148
const shouldInclude =
159149
edit && watchForm.GUID ? template.standardId !== watchForm.GUID : true;
160-
console.log(
161-
`Template ${template.standardId} (${template.standardName}): shouldInclude=${shouldInclude}, currentGUID=${watchForm.GUID}`
162-
);
163150
return shouldInclude;
164151
});
165152

166-
console.log(
167-
"Filtered templates:",
168-
existingTemplates?.map((t) => ({
169-
GUID: t.GUID,
170-
standardId: t.standardId,
171-
standardName: t.standardName,
172-
}))
173-
);
174-
175153
// Get tenant groups data
176154
const groups = tenantGroupsApi.data?.Results || [];
177155

@@ -198,45 +176,27 @@ const CippStandardsSideBar = ({
198176
});
199177

200178
// Check for conflicts with unique templates
201-
console.log("Checking conflicts with unique templates:", uniqueTemplates);
202-
console.log("Selected tenant list:", selectedTenantList);
203-
204179
for (const templateId in uniqueTemplates) {
205180
const template = uniqueTemplates[templateId];
206181
const templateTenants = template.tenants;
207182

208-
console.log(
209-
`Checking template ${templateId} (${template.standardName}) with tenants:`,
210-
templateTenants
211-
);
212-
213183
const hasConflict = selectedTenantList.some((selectedTenant) => {
214184
// Check if any template tenant matches the selected tenant
215185
const conflict = templateTenants.some((templateTenant) => {
216186
if (selectedTenant === "AllTenants" || templateTenant === "AllTenants") {
217-
console.log(
218-
`Conflict found: ${selectedTenant} vs ${templateTenant} (AllTenants match)`
219-
);
220187
return true;
221188
}
222189
const match = selectedTenant === templateTenant;
223-
if (match) {
224-
console.log(`Conflict found: ${selectedTenant} vs ${templateTenant} (exact match)`);
225-
}
226190
return match;
227191
});
228192
return conflict;
229193
});
230194

231-
console.log(`Template ${templateId} has conflict: ${hasConflict}`);
232-
233195
if (hasConflict) {
234196
conflicts.push(template.standardName || "Unknown Template");
235197
}
236198
}
237199

238-
console.log("Final conflicts:", conflicts);
239-
240200
if (conflicts.length > 0) {
241201
setDriftError(
242202
`This template has tenants that are assigned to another Drift Template. You can only assign one Drift Template to each tenant. Please check the ${conflicts.join(

src/data/standards.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5056,10 +5056,7 @@
50565056
"queryKey": "ListIntuneTemplates-tag-autcomplete",
50575057
"url": "/api/ListIntuneTemplates?mode=Tag",
50585058
"labelField": "label",
5059-
"valueField": "value",
5060-
"addedField": {
5061-
"templates": "templates"
5062-
}
5059+
"valueField": "value"
50635060
}
50645061
},
50655062
{

0 commit comments

Comments
 (0)