}
>
{saveTemplate.isPending
- ? "Saving..."
+ ? 'Saving...'
: saveTemplate.isSuccess
- ? editGUID ? "Saved" : "Save Another"
- : `${editGUID ? "Update" : "Save"} Template (${getTotalApps()} app${getTotalApps() !== 1 ? "s" : ""})`}
+ ? editGUID
+ ? 'Saved'
+ : 'Save Another'
+ : `${editGUID ? 'Update' : 'Save'} Template (${getTotalApps()} app${getTotalApps() !== 1 ? 's' : ''})`}
-
-
-
-
-
-
-
-
+ {canViewGdapChecks && (
+ <>
+
+
+
+
+
+
+
+
+ >
+ )}
);
diff --git a/src/pages/tenant/gdap-management/offboarding.js b/src/pages/tenant/gdap-management/offboarding.js
index d9486f775c25..aa6cddc87d0d 100644
--- a/src/pages/tenant/gdap-management/offboarding.js
+++ b/src/pages/tenant/gdap-management/offboarding.js
@@ -22,60 +22,46 @@ const Page = () => {
return vendor.vendorTenantId;
})
.join(",");
- const vendorGraphFilter = `appOwnerOrganizationId in (${vendorFilter})`;
const tenantId = useWatch({
control: formControl.control,
name: "tenantFilter",
});
const gdapRelationships = ApiGetCall({
- url: "/api/ListGraphRequest",
- data: {
- Endpoint: "tenantRelationships/delegatedAdminRelationships",
- tenantFilter: "",
- $top: 300,
- },
+ url: "/api/ListGDAPRelationships",
queryKey: "ListGDAPRelationship",
});
const cspContracts = ApiGetCall({
- url: "/api/ListGraphRequest",
- data: {
- Endpoint: "contracts",
- tenantFilter: "",
- $top: 300,
- },
+ url: "/api/ListGDAPContracts",
queryKey: "ListContracts",
});
const mspApps = ApiGetCall({
- url: "/api/ListGraphRequest",
+ url: "/api/ListGDAPServicePrincipals",
data: {
- Endpoint: "servicePrincipals",
- TenantFilter: tenantId?.value,
- $filter: `appOwnerOrganizationId eq %partnertenantid%`,
- $select: "id,displayName,appId,appOwnerOrganizationId",
- $count: true,
+ tenantFilter: tenantId?.value,
+ ownerType: "partner",
},
queryKey: "ListMSPApps-" + tenantId?.value,
+ waiting: Boolean(tenantId?.value),
});
const vendorApps = ApiGetCallWithPagination({
- url: "/api/ListGraphRequest",
+ url: "/api/ListGDAPServicePrincipals",
data: {
- Endpoint: "servicePrincipals",
- TenantFilter: tenantId?.value,
- $filter: vendorGraphFilter,
- $select: "id,displayName,appId,appOwnerOrganizationId",
- $count: true,
+ tenantFilter: tenantId?.value,
+ ownerType: "vendor",
+ vendorTenantIds: vendorFilter,
},
queryKey: "ListVendorApps-" + tenantId?.value,
+ waiting: Boolean(tenantId?.value),
});
return (
<>
{
label="Select Tenant to Offboard"
type="autoComplete"
api={{
- url: "/api/ExecExcludeTenant",
- data: {
- ListAll: true,
- },
- queryKey: "ListAllTenants",
+ url: "/api/ListOffboardTenants",
+ queryKey: "ListOffboardTenants",
labelField: (tenant) => {
return `${tenant.displayName} (${tenant.defaultDomainName})`;
},
@@ -205,13 +188,11 @@ const Page = () => {
label="Vendor Applications to Remove"
type="autoComplete"
api={{
- url: "/api/ListGraphRequest",
+ url: "/api/ListGDAPServicePrincipals",
data: {
- Endpoint: "servicePrincipals",
- TenantFilter: tenantId.value,
- $filter: vendorGraphFilter,
- $select: "id,displayName,appId,appOwnerOrganizationId",
- $count: true,
+ tenantFilter: tenantId.value,
+ ownerType: "vendor",
+ vendorTenantIds: vendorFilter,
},
dataKey: "Results",
queryKey: "ListVendorApps-" + tenantId.value,
diff --git a/src/pages/tenant/gdap-management/onboarding/start.js b/src/pages/tenant/gdap-management/onboarding/start.js
index c2908d22a467..c5cf9cf5da3a 100644
--- a/src/pages/tenant/gdap-management/onboarding/start.js
+++ b/src/pages/tenant/gdap-management/onboarding/start.js
@@ -49,11 +49,7 @@ const Page = () => {
});
const relationshipList = ApiGetCall({
- url: "/api/ListGraphRequest",
- data: {
- TenantFilter: "",
- Endpoint: "tenantRelationships/delegatedAdminRelationships",
- },
+ url: "/api/ListGDAPRelationships",
queryKey: "GDAPRelationshipOnboarding",
});
const onboardingList = ApiGetCallWithPagination({
@@ -317,10 +313,7 @@ const Page = () => {
label="Select GDAP Relationship"
type="autoComplete"
api={{
- url: "/api/ListGraphRequest",
- data: {
- Endpoint: "tenantRelationships/delegatedAdminRelationships",
- },
+ url: "/api/ListGDAPRelationships",
excludeTenantFilter: true,
queryKey: "GDAPRelationships",
dataKey: "Results",
diff --git a/src/pages/tenant/gdap-management/relationships/index.js b/src/pages/tenant/gdap-management/relationships/index.js
index 8c3c3da01bc0..f3a3e4f441a7 100644
--- a/src/pages/tenant/gdap-management/relationships/index.js
+++ b/src/pages/tenant/gdap-management/relationships/index.js
@@ -4,8 +4,6 @@ import tabOptions from "../tabOptions";
import CippTablePage from "../../../../components/CippComponents/CippTablePage";
import CippGdapActions from "../../../../components/CippComponents/CippGdapActions";
-const pageTitle = "GDAP Relationships";
-
const actions = CippGdapActions();
const simpleColumns = [
@@ -47,20 +45,12 @@ const offCanvas = {
extendedInfoFields: simpleColumns,
};
-const apiUrl = "/api/ListGraphRequest";
-const apiData = {
- Endpoint: "tenantRelationships/delegatedAdminRelationships",
- tenantFilter: "",
- $top: 300,
-};
-
const Page = () => {
return (
{
const [relationshipData, setRelationshipData] = useState({});
const relationshipRequest = ApiGetCall({
- url: `/api/ListGraphRequest?Endpoint=tenantRelationships/delegatedAdminRelationships/${id}`,
+ url: `/api/ListGDAPRelationships?id=${id}`,
queryKey: `ListRelationships-${id}`,
});
diff --git a/src/pages/tenant/gdap-management/relationships/relationship/mappings.js b/src/pages/tenant/gdap-management/relationships/relationship/mappings.js
index 3ec708b70c66..b9669e3f725f 100644
--- a/src/pages/tenant/gdap-management/relationships/relationship/mappings.js
+++ b/src/pages/tenant/gdap-management/relationships/relationship/mappings.js
@@ -12,7 +12,7 @@ const Page = () => {
const { id } = router.query;
const relationshipRequest = ApiGetCall({
- url: `/api/ListGraphRequest?Endpoint=tenantRelationships/delegatedAdminRelationships/${id}`,
+ url: `/api/ListGDAPRelationships?id=${id}`,
queryKey: `ListRelationships-${id}`,
});
diff --git a/src/pages/tenant/manage/applied-standards.js b/src/pages/tenant/manage/applied-standards.js
index 221f7ca2e335..58cc78f19c88 100644
--- a/src/pages/tenant/manage/applied-standards.js
+++ b/src/pages/tenant/manage/applied-standards.js
@@ -121,6 +121,17 @@ const Page = () => {
enabled: !!templateId, // Only run the query if templateId is available
})
+ // Fetch drift deviation data for drift templates
+ const isDriftTemplate = selectedTemplate?.type === 'drift'
+ const driftApi = ApiGetCall({
+ url: '/api/listTenantDrift',
+ data: {
+ tenantFilter: currentTenant,
+ },
+ queryKey: `TenantDrift-applied-${currentTenant}`,
+ enabled: isDriftTemplate && !!currentTenant,
+ })
+
useEffect(() => {
if (templateId && templateDetails.isSuccess && templateDetails.data) {
const selectedTemplate = templateDetails.data.find((template) => template.GUID === templateId)
@@ -1165,6 +1176,50 @@ const Page = () => {
})
}
+ // For drift templates, cross-reference with drift deviation data
+ if (isDriftTemplate && driftApi.isSuccess && driftApi.data) {
+ const tenantDriftItems = Array.isArray(driftApi.data)
+ ? driftApi.data.filter((item) => item.tenantFilter === currentTenant)
+ : []
+
+ // Build a lookup of standardName -> deviation status
+ const deviationLookup = {}
+ tenantDriftItems.forEach((item) => {
+ if (item.acceptedDeviations) {
+ item.acceptedDeviations.forEach((dev) => {
+ if (dev?.standardName) {
+ deviationLookup[dev.standardName] = 'Accepted'
+ deviationLookup[`standards.${dev.standardName}`] = 'Accepted'
+ }
+ })
+ }
+ if (item.customerSpecificDeviations) {
+ item.customerSpecificDeviations.forEach((dev) => {
+ if (dev?.standardName) {
+ deviationLookup[dev.standardName] = 'CustomerSpecific'
+ deviationLookup[`standards.${dev.standardName}`] = 'CustomerSpecific'
+ }
+ })
+ }
+ })
+
+ // Update compliance status for accepted deviations
+ allStandards.forEach((standard) => {
+ if (standard.complianceStatus === 'Non-Compliant') {
+ const devStatus =
+ deviationLookup[standard.standardId] ||
+ deviationLookup[standard.standardId?.replace(/^standards\./, '')]
+ if (devStatus === 'Accepted') {
+ standard.complianceStatus = 'Accepted Deviation'
+ standard.deviationStatus = 'Accepted'
+ } else if (devStatus === 'CustomerSpecific') {
+ standard.complianceStatus = 'Customer Specific'
+ standard.deviationStatus = 'CustomerSpecific'
+ }
+ }
+ })
+ }
+
setComparisonData(allStandards)
} else {
setComparisonData([])
@@ -1179,6 +1234,10 @@ const Page = () => {
comparisonApi.isSuccess,
comparisonApi.data,
comparisonApi.isError,
+ isDriftTemplate,
+ driftApi.isSuccess,
+ driftApi.data,
+ currentTenant,
])
const comparisonModeOptions = [{ label: 'Compare Tenant to Standard', value: 'standard' }]
@@ -1233,6 +1292,9 @@ const Page = () => {
(filter === 'compliant' && standard.complianceStatus === 'Compliant') ||
(filter === 'nonCompliant' && standard.complianceStatus === 'Non-Compliant') ||
(filter === 'overridden' && standard.complianceStatus === 'Overridden') ||
+ (filter === 'acceptedDeviation' &&
+ (standard.complianceStatus === 'Accepted Deviation' ||
+ standard.complianceStatus === 'Customer Specific')) ||
(filter === 'nonCompliantWithLicense' &&
standard.complianceStatus === 'Non-Compliant' &&
!hasLicenseMissing) ||
@@ -1262,6 +1324,12 @@ const Page = () => {
comparisonData?.filter((standard) => standard.complianceStatus === 'Compliant').length || 0
const nonCompliantCount =
comparisonData?.filter((standard) => standard.complianceStatus === 'Non-Compliant').length || 0
+ const acceptedDeviationCount =
+ comparisonData?.filter(
+ (standard) =>
+ standard.complianceStatus === 'Accepted Deviation' ||
+ standard.complianceStatus === 'Customer Specific'
+ ).length || 0
const reportingDisabledCount =
comparisonData?.filter((standard) => standard.complianceStatus === 'Reporting Disabled')
.length || 0
@@ -1297,7 +1365,9 @@ const Page = () => {
const compliancePercentage =
allCount > 0
? Math.round(
- (compliantCount / (allCount - reportingDisabledCount - overriddenCount || 1)) * 100
+ ((compliantCount + acceptedDeviationCount) /
+ (allCount - reportingDisabledCount - overriddenCount || 1)) *
+ 100
)
: 0
@@ -1371,7 +1441,7 @@ const Page = () => {
backUrl="/tenant/standards"
actions={actions}
actionsData={{}}
- isFetching={comparisonApi.isFetching || templateDetails.isFetching}
+ isFetching={comparisonApi.isFetching || templateDetails.isFetching || driftApi.isFetching}
>
@@ -1606,6 +1676,17 @@ const Page = () => {
combinedScore >= 80 ? 'success' : combinedScore >= 60 ? 'warning' : 'error'
}
/>
+
+ {isDriftTemplate ? : }
+
+ }
+ label={isDriftTemplate ? 'Drift Standard' : 'Classic Standard'}
+ size="small"
+ color={isDriftTemplate ? 'info' : 'default'}
+ variant="outlined"
+ />
)}
))}
+ {alignedItemsWithActions.map((item) => (
+
+ ))}
+
{/* Hidden ExecutiveReportButton that gets triggered programmatically */}
{
- return ;
+ const currentTenant = useSettings().currentTenant;
+ const syncDialog = useDialog();
+ const [syncQueueId, setSyncQueueId] = useState(null);
+
+ const isAllTenants = currentTenant === "AllTenants";
+ const [useReportDB, setUseReportDB] = useState(true);
+
+ useEffect(() => {
+ setUseReportDB(true);
+ }, [currentTenant]);
+
+ const simpleColumns = isAllTenants
+ ? ["Tenant", "Name", "ApplicationID", "ObjectID", "Scope", "StartTime", "CacheTimestamp"]
+ : ["Name", "ApplicationID", "ObjectID", "Scope", "StartTime", "CacheTimestamp"];
+
+ return (
+ <>
+
+ {useReportDB && (
+ <>
+
+
+
+
+ }
+ size="xs"
+ onClick={syncDialog.handleOpen}
+ disabled={isAllTenants}
+ >
+ Sync
+
+ >
+ )}
+
+
+ : }
+ label={useReportDB ? "Cached" : "Live"}
+ color="primary"
+ size="small"
+ onClick={isAllTenants ? undefined : () => setUseReportDB((prev) => !prev)}
+ clickable={!isAllTenants}
+ disabled={isAllTenants}
+ variant="outlined"
+ />
+
+
+
+ }
+ />
+ {
+ if (response?.Metadata?.QueueId) {
+ setSyncQueueId(response.Metadata.QueueId);
+ }
+ },
+ }}
+ />
+ >
+ );
};
-Page.getLayout = (page) => {page};
+Page.getLayout = (page) => {page};
export default Page;
diff --git a/src/pages/tenant/reports/graph-office-reports/index.js b/src/pages/tenant/reports/graph-office-reports/index.js
index b97505d12ed4..39bb153c06b6 100644
--- a/src/pages/tenant/reports/graph-office-reports/index.js
+++ b/src/pages/tenant/reports/graph-office-reports/index.js
@@ -64,7 +64,7 @@ const Page = () => {
waiting: !!currentTenant,
})
- const reportOptions = (reportListApi.data ?? []).map((r) => ({
+ const reportOptions = (Array.isArray(reportListApi.data) ? reportListApi.data : []).map((r) => ({
label: prettifyReportName(r.name),
value: r.name,
type: r.type ?? null,
@@ -156,7 +156,7 @@ const Page = () => {
) : (
{
const pageTitle = 'Standard & Drift Alignment'
+ const [granular, setGranular] = useState(false)
- const filterList = [
+ const summaryFilterList = [
{
filterName: 'Drift Templates',
value: [{ id: 'standardType', value: 'drift' }],
@@ -21,7 +25,35 @@ const Page = () => {
},
]
- const actions = [
+ const granularFilterList = [
+ {
+ filterName: 'Non-Compliant',
+ value: [{ id: 'complianceStatus', value: 'Non-Compliant' }],
+ type: 'column',
+ },
+ {
+ filterName: 'Compliant',
+ value: [{ id: 'complianceStatus', value: 'Compliant' }],
+ type: 'column',
+ },
+ {
+ filterName: 'Accepted Deviation',
+ value: [{ id: 'complianceStatus', value: 'Accepted Deviation' }],
+ type: 'column',
+ },
+ {
+ filterName: 'Customer Specific',
+ value: [{ id: 'complianceStatus', value: 'Customer Specific' }],
+ type: 'column',
+ },
+ {
+ filterName: 'License Missing',
+ value: [{ id: 'complianceStatus', value: 'License Missing' }],
+ type: 'column',
+ },
+ ]
+
+ const summaryActions = [
{
label: 'View Tenant Report',
link: '/tenant/manage/applied-standards/?tenantFilter=[tenantFilter]&templateId=[standardId]',
@@ -29,6 +61,13 @@ const Page = () => {
color: 'info',
target: '_self',
},
+ {
+ label: 'Edit Template',
+ link: '/tenant/standards/templates/template?id=[standardId]&type=[standardType]',
+ icon: ,
+ color: 'success',
+ target: '_self',
+ },
{
label: 'Manage Drift',
link: '/tenant/manage/drift?templateId=[standardId]&tenantFilter=[tenantFilter]',
@@ -53,22 +92,401 @@ const Page = () => {
},
]
+ const granularActions = [
+ {
+ label: 'View Tenant Report',
+ link: '/tenant/manage/applied-standards/?tenantFilter=[tenantFilter]&templateId=[templateId]',
+ icon: ,
+ color: 'info',
+ target: '_self',
+ },
+ {
+ label: 'Edit Template',
+ link: '/tenant/standards/templates/template?id=[templateId]&type=[templateType]',
+ icon: ,
+ color: 'success',
+ target: '_self',
+ },
+ {
+ label: 'Manage Drift',
+ link: '/tenant/manage/drift?templateId=[templateId]&tenantFilter=[tenantFilter]',
+ icon: ,
+ color: 'info',
+ target: '_self',
+ condition: (row) => row.templateType === 'drift',
+ },
+ ]
+
+ const parseValue = (value) => {
+ if (value === null || value === undefined || value === '') return null
+ if (typeof value === 'string') {
+ try {
+ return JSON.parse(value)
+ } catch {
+ return value
+ }
+ }
+ return value
+ }
+
+ const normalizeObj = (val) => {
+ if (Array.isArray(val)) return val.map(normalizeObj)
+ if (val !== null && typeof val === 'object') {
+ return Object.fromEntries(
+ Object.keys(val)
+ .sort()
+ .map((k) => [k, normalizeObj(val[k])])
+ )
+ }
+ return val
+ }
+
+ const compareValues = (expected, current) => {
+ if (!expected || !current) return null
+ try {
+ const expectedObj = normalizeObj(
+ typeof expected === 'object' ? expected : JSON.parse(expected)
+ )
+ const currentObj = normalizeObj(typeof current === 'object' ? current : JSON.parse(current))
+ if (JSON.stringify(expectedObj) === JSON.stringify(currentObj)) return null
+ const differences = {}
+ const allKeys = new Set([...Object.keys(expectedObj), ...Object.keys(currentObj)])
+ allKeys.forEach((key) => {
+ const e = normalizeObj(expectedObj[key])
+ const c = normalizeObj(currentObj[key])
+ if (JSON.stringify(e) !== JSON.stringify(c)) {
+ differences[key] = { expected: expectedObj[key], current: currentObj[key] }
+ }
+ })
+ return Object.keys(differences).length > 0 ? differences : null
+ } catch {
+ return null
+ }
+ }
+
+ const granularOffCanvas = {
+ size: 'md',
+ title: 'Standard Details',
+ contentPadding: 0,
+ children: (row) => {
+ const expectedParsed = parseValue(row.expectedValue)
+ const currentParsed = parseValue(row.currentValue)
+ const diffs = compareValues(expectedParsed, currentParsed)
+ const baseName = row.standardId?.split('.').slice(0, -1).join('.')
+ const prettyName =
+ standardsData.find((s) => s.name === row.standardId)?.label ??
+ standardsData.find((s) => s.name === baseName)?.label ??
+ row.standardName
+
+ const complianceColors = {
+ compliant: 'success',
+ 'non-compliant': 'error',
+ 'accepted deviation': 'info',
+ 'customer specific': 'info',
+ 'license missing': 'warning',
+ 'reporting disabled': 'default',
+ }
+ const statusColor =
+ complianceColors[String(row.complianceStatus ?? '').toLowerCase()] ?? 'default'
+
+ const properties = [
+ { label: 'Standard', value: prettyName },
+ { label: 'Status', value: row.complianceStatus, color: statusColor },
+ { label: 'Template', value: row.templateName },
+ {
+ label: 'Type',
+ value: row.standardType === 'drift' ? 'Drift Standard' : 'Classic Standard',
+ },
+ {
+ label: 'Last Applied',
+ value: row.latestDataCollection
+ ? new Date(row.latestDataCollection).toLocaleString()
+ : 'N/A',
+ },
+ ]
+
+ return (
+
+ {/* Property list */}
+ }
+ sx={{ borderBottom: '1px solid', borderColor: 'divider' }}
+ >
+ {properties.map(({ label, value, color }) => (
+
+
+ {label}
+
+ {color ? (
+
+ ) : (
+
+ {value ?? 'N/A'}
+
+ )}
+
+ ))}
+
+
+ {/* Diff / value content */}
+ {(expectedParsed || currentParsed) && (
+
+ {diffs ? (
+ <>
+
+ Property Differences
+
+ {Object.entries(diffs).map(([key, { expected, current }]) => (
+
+
+ {key}
+
+
+
+
+ Expected
+
+
+
+ {JSON.stringify(expected, null, 2)}
+
+
+
+
+
+ Current
+
+
+
+ {JSON.stringify(current, null, 2)}
+
+
+
+
+
+ ))}
+ >
+ ) : (
+ <>
+ {expectedParsed !== null && (
+
+
+ Expected
+
+
+
+ {typeof expectedParsed === 'object'
+ ? JSON.stringify(expectedParsed, null, 2)
+ : String(expectedParsed)}
+
+
+
+ )}
+ {currentParsed !== null && (
+
+
+ Current
+
+
+
+ {typeof currentParsed === 'object'
+ ? JSON.stringify(currentParsed, null, 2)
+ : String(currentParsed)}
+
+
+
+ )}
+ >
+ )}
+
+ )}
+
+ )
+ },
+ }
+
+ const modeToggle = (
+
+
+
+ ) : (
+
+ )
+ }
+ label={granular ? 'Per Standard' : 'Summary'}
+ onClick={() => setGranular((v) => !v)}
+ color="primary"
+ variant="filled"
+ size="small"
+ clickable
+ />
+
+
+ )
+
return (
)
}
diff --git a/src/pages/tenant/tools/graph-explorer/index.js b/src/pages/tenant/tools/graph-explorer/index.js
index 2cbbd17a3ba1..bf4fde876376 100644
--- a/src/pages/tenant/tools/graph-explorer/index.js
+++ b/src/pages/tenant/tools/graph-explorer/index.js
@@ -18,9 +18,9 @@ const Page = () => {
const apiData = ApiGetCallWithPagination({
url: apiFilter.endpoint ? "/api/ListGraphRequest" : "/api/ListEmptyResults",
- data: apiFilter,
+ data: { tenantFilter, ...apiFilter },
queryKey: queryKey,
- waiting: !!apiFilter.endpoint,
+ waiting: !!apiFilter.endpoint && viewMode === "json",
});
const jsonData = apiData?.data?.pages?.[0]?.Results || apiData?.data || {};
diff --git a/src/pages/tools/community-repos/index.js b/src/pages/tools/community-repos/index.js
index 4213f74127d9..8b09c824d1e1 100644
--- a/src/pages/tools/community-repos/index.js
+++ b/src/pages/tools/community-repos/index.js
@@ -82,6 +82,7 @@ const Page = () => {
icon: ,
multiPost: false,
queryKey: "CommunityRepos",
+ condition: (row) => row.BuiltIn !== true,
},
{
label: "Set Upload Branch",
diff --git a/src/pages/tools/custom-tests/add.jsx b/src/pages/tools/custom-tests/add.jsx
index fb4387bbbdb8..6951fe57c507 100644
--- a/src/pages/tools/custom-tests/add.jsx
+++ b/src/pages/tools/custom-tests/add.jsx
@@ -406,7 +406,7 @@ All UPNs: {{join(Result[*].UserPrincipalName, ", ")}}`,
placeholder: `# Example: Find disabled users with licenses
param($TenantFilter, $DaysThreshold = 30)
-$users = New-CIPPDbRequest -TenantFilter $TenantFilter -Type 'Users'
+$users = Get-CIPPTestData -TenantFilter $TenantFilter -Type 'Users'
$results = $users | Where-Object {
$_.assignedLicenses.Count -gt 0 -and
$_.accountEnabled -eq $false
@@ -655,7 +655,7 @@ return $results`,
Data Access
- Read-only via New-CIPPDbRequest and Get-CIPPDbItem{' '}
+ Read-only via Get-CIPPTestData and Get-CIPPDbItem{' '}
with a -Type parameter.
{
- // Portal columns render as a small icon — header width is enough.
+// header is the translated column title text.
+export const getCippColumnSize = (accessorKey, header) => {
+ // Portal columns render as a small icon — size based on title length
+ // plus room for sort icon, column actions, and resize handle.
if (accessorKey && accessorKey.startsWith('portal_')) {
- return { size: 'header', minSize: 'header' }
+ const titleLen = header ? header.length : 6
+ const px = Math.round(titleLen * 8 + 85)
+ return { size: px, minSize: px }
}
// Progress bar / percentage columns need room for the bar component.
diff --git a/src/utils/get-cipp-error.js b/src/utils/get-cipp-error.js
index 4b38df2af676..105ced73caf2 100644
--- a/src/utils/get-cipp-error.js
+++ b/src/utils/get-cipp-error.js
@@ -16,7 +16,7 @@ export const getCippError = (data) => {
if (data.response?.data?.Results) {
return data.response.data.Results;
}
-
+
if (data.response?.data) {
return data.response.data;
}
diff --git a/src/utils/get-cipp-formatting.js b/src/utils/get-cipp-formatting.js
index 93f364ca77b2..b900905202ca 100644
--- a/src/utils/get-cipp-formatting.js
+++ b/src/utils/get-cipp-formatting.js
@@ -33,6 +33,7 @@ import DOMPurify from 'dompurify'
import { getSignInErrorCodeTranslation } from './get-cipp-signin-errorcode-translation'
import { CollapsibleChipList } from '../components/CippComponents/CollapsibleChipList'
import countryList from '../data/countryList.json'
+import standardsData from '../data/standards.json'
// Helper function to convert country codes to country names
const getCountryNameFromCode = (countryCode) => {
@@ -436,6 +437,29 @@ export const getCippFormatting = (data, cellName, type, canReceive, flatten = tr
))
}
}
+ if (cellName === 'complianceStatus') {
+ if (isText) return data
+ const complianceColors = {
+ compliant: 'success',
+ 'non-compliant': 'error',
+ 'license missing': 'warning',
+ 'reporting disabled': 'default',
+ }
+ const color = complianceColors[String(data).toLowerCase()] ?? 'default'
+ return
+ }
+
+ if (cellName === 'standardName') {
+ // Already resolved for templates; do a standards.json lookup for classic standards
+ if (!data?.startsWith('standards.')) return isText ? data : {data}
+ const baseName = data.split('.').slice(0, -1).join('.')
+ const label =
+ standardsData.find((s) => s.name === data)?.label ??
+ standardsData.find((s) => s.name === baseName)?.label ??
+ data
+ return label
+ }
+
if (cellName === 'standardType') {
return isText ? (
data
diff --git a/src/utils/get-cipp-license-translation.js b/src/utils/get-cipp-license-translation.js
index 0397585d927a..321379fc6785 100644
--- a/src/utils/get-cipp-license-translation.js
+++ b/src/utils/get-cipp-license-translation.js
@@ -3,9 +3,18 @@ import M365LicensesAdditional from "../data/M365Licenses-additional.json";
import { getCachedLicense } from "./cipp-license-cache";
import licenseBackfillManager from "./cipp-license-backfill-manager";
+// Create a Map for O(1) lookups of GUID to Product_Display_Name
+const licenseByGuid = new Map();
+[...M365LicensesDefault, ...M365LicensesAdditional].forEach((entry) => {
+ if (entry.GUID) {
+ const key = entry.GUID.toLowerCase();
+ if (!licenseByGuid.has(key)) {
+ licenseByGuid.set(key, entry.Product_Display_Name);
+ }
+ }
+});
+
export const getCippLicenseTranslation = (licenseArray) => {
- //combine M365LicensesDefault and M365LicensesAdditional to one array
- const M365Licenses = [...M365LicensesDefault, ...M365LicensesAdditional];
let licenses = [];
let missingSkuIds = [];
@@ -24,17 +33,16 @@ export const getCippLicenseTranslation = (licenseArray) => {
licenseArray?.forEach((licenseAssignment) => {
let found = false;
- // First, check static JSON files
- for (let x = 0; x < M365Licenses.length; x++) {
- if (licenseAssignment.skuId === M365Licenses[x].GUID) {
- licenses.push(
- M365Licenses[x].Product_Display_Name
- ? M365Licenses[x].Product_Display_Name
- : licenseAssignment.skuPartNumber,
- );
- found = true;
- break;
- }
+ // First, check static JSON map (O(1) lookup)
+ const skuLower = licenseAssignment.skuId?.toLowerCase();
+ const displayName = skuLower ? licenseByGuid.get(skuLower) : undefined;
+ if (displayName) {
+ licenses.push(displayName);
+ found = true;
+ } else if (skuLower && licenseByGuid.has(skuLower)) {
+ // Entry exists but Product_Display_Name is falsy — fall back to skuPartNumber
+ licenses.push(licenseAssignment.skuPartNumber || licenseAssignment.skuId);
+ found = true;
}
// Second, check dynamic cache
diff --git a/src/utils/get-cipp-validator.js b/src/utils/get-cipp-validator.js
index e1db092ae1ad..f5541e0dc25c 100644
--- a/src/utils/get-cipp-validator.js
+++ b/src/utils/get-cipp-validator.js
@@ -41,7 +41,7 @@ export const getCippValidator = (value, type) => {
case "wildcardDomain":
return /^(\*\.)?([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.\*)?$/.test(value) || /^(\*)?[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\*)?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$/.test(value) || "This is not a valid domain pattern";
case "wildcardUrl":
- return /^(https?:\/\/)?(\*\.)?([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.\*)?([\/\?\*][a-zA-Z0-9\-\.\~\*\/\?=&%]*)?$/.test(value) || "This is not a valid URL pattern";
+ return /^(https?:\/\/)?(\*\.)?([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)*[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.\*)?([\/\?\*][a-zA-Z0-9\-\.\~\*\/\?=&%]*)?$/.test(value) || "This is not a valid URL pattern";
case "senderEntry":
return (
/^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]$/.test(value) ||
diff --git a/yarn.lock b/yarn.lock
index 052eb57111f7..717cf1e70089 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1368,17 +1368,17 @@
dependencies:
"@monaco-editor/loader" "^1.5.0"
-"@mui/core-downloads-tracker@^7.3.7":
- version "7.3.9"
- resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-7.3.9.tgz#d944e385f8f7f5e680e5ba479b39ff8602bd4939"
- integrity sha512-MOkOCTfbMJwLshlBCKJ59V2F/uaLYfmKnN76kksj6jlGUVdI25A9Hzs08m+zjBRdLv+sK7Rqdsefe8X7h/6PCw==
+"@mui/core-downloads-tracker@^7.3.10":
+ version "7.3.10"
+ resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-7.3.10.tgz#f6af0bbfa825f11849f5f190d984d6f8d5c0d961"
+ integrity sha512-vrOpWRmPJSuwLo23J62wggEm/jvGdzqctej+UOCtgDUz6nZJQuj3ByPccVyaa7eQmwAzUwKN56FQPMKkqbj1GA==
-"@mui/icons-material@7.3.7":
- version "7.3.7"
- resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-7.3.7.tgz#01a6019c552e27c7f8a3451bcb47171ede8b34ac"
- integrity sha512-3Q+ulAqG+A1+R4ebgoIs7AccaJhIGy+Xi/9OnvX376jQ6wcy+rz4geDGrxQxCGzdjOQr4Z3NgyFSZCz4T999lA==
+"@mui/icons-material@7.3.10":
+ version "7.3.10"
+ resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-7.3.10.tgz#f0d232ebe007b3a125a52c5c9e1bece43a83b57c"
+ integrity sha512-Au0ma4NSKGKNiimukj8UT/W1x2Qx6Qwn2RvFGykiSqVLYBNlIOPbjnIMvrwLGLu89EEpTVdu/ys/OduZR+tWqw==
dependencies:
- "@babel/runtime" "^7.28.4"
+ "@babel/runtime" "^7.28.6"
"@mui/lab@7.0.0-beta.17":
version "7.0.0-beta.17"
@@ -1392,16 +1392,16 @@
clsx "^2.1.1"
prop-types "^15.8.1"
-"@mui/material@7.3.7":
- version "7.3.7"
- resolved "https://registry.yarnpkg.com/@mui/material/-/material-7.3.7.tgz#50fc9b9f8645a4d26a48d7c5f7fa0c9876a8c679"
- integrity sha512-6bdIxqzeOtBAj2wAsfhWCYyMKPLkRO9u/2o5yexcL0C3APqyy91iGSWgT3H7hg+zR2XgE61+WAu12wXPON8b6A==
+"@mui/material@7.3.10":
+ version "7.3.10"
+ resolved "https://registry.yarnpkg.com/@mui/material/-/material-7.3.10.tgz#1c954b0e7aba220703afe07594388a69383c7363"
+ integrity sha512-cHvGOk2ZEfbQt3LnGe0ZKd/ETs9gsUpkW66DCO+GSjMZhpdKU4XsuIr7zJ/B/2XaN8ihxuzHfYAR4zPtCN4RYg==
dependencies:
- "@babel/runtime" "^7.28.4"
- "@mui/core-downloads-tracker" "^7.3.7"
- "@mui/system" "^7.3.7"
- "@mui/types" "^7.4.10"
- "@mui/utils" "^7.3.7"
+ "@babel/runtime" "^7.28.6"
+ "@mui/core-downloads-tracker" "^7.3.10"
+ "@mui/system" "^7.3.10"
+ "@mui/types" "^7.4.12"
+ "@mui/utils" "^7.3.10"
"@popperjs/core" "^2.11.8"
"@types/react-transition-group" "^4.4.12"
clsx "^2.1.1"
@@ -1410,7 +1410,16 @@
react-is "^19.2.3"
react-transition-group "^4.4.5"
-"@mui/private-theming@^7.3.2", "@mui/private-theming@^7.3.9":
+"@mui/private-theming@^7.3.10":
+ version "7.3.10"
+ resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-7.3.10.tgz#2e500959f39c7b305a30ff3f947f47dea9e8eac1"
+ integrity sha512-j3EZN+zOctxUISvJSmsEPo5o2F8zse4l5vRkBY+ps6UtnL6J7o14kUaI4w7gwo73id9e3cDNMVQK/9BVaMHVBw==
+ dependencies:
+ "@babel/runtime" "^7.28.6"
+ "@mui/utils" "^7.3.10"
+ prop-types "^15.8.1"
+
+"@mui/private-theming@^7.3.9":
version "7.3.9"
resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-7.3.9.tgz#c785dc429b7ed62cf3952140be703cbe95704a13"
integrity sha512-ErIyRQvsiQEq7Yvcvfw9UDHngaqjMy9P3JDPnRAaKG5qhpl2C4tX/W1S4zJvpu+feihmZJStjIyvnv6KDbIrlw==
@@ -1419,7 +1428,19 @@
"@mui/utils" "^7.3.9"
prop-types "^15.8.1"
-"@mui/styled-engine@^7.3.2", "@mui/styled-engine@^7.3.9":
+"@mui/styled-engine@^7.3.10":
+ version "7.3.10"
+ resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-7.3.10.tgz#53e98c1fdeda972b5932c76f6a2a29faf33f0d11"
+ integrity sha512-WxE9SiF8xskAQqGjsp0poXCkCqsoXFEsSr0HBXfApmGHR+DBnXRp+z46Vsltg4gpPM4Z96DeAQRpeAOnhNg7Ng==
+ dependencies:
+ "@babel/runtime" "^7.28.6"
+ "@emotion/cache" "^11.14.0"
+ "@emotion/serialize" "^1.3.3"
+ "@emotion/sheet" "^1.4.0"
+ csstype "^3.2.3"
+ prop-types "^15.8.1"
+
+"@mui/styled-engine@^7.3.9":
version "7.3.9"
resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-7.3.9.tgz#e425ca7b5cb559bde01b8fa4a7a842e9b5916f53"
integrity sha512-JqujWt5bX4okjUPGpVof/7pvgClqh7HvIbsIBIOOlCh2u3wG/Bwp4+E1bc1dXSwkrkp9WUAoNdI5HEC+5HKvMw==
@@ -1431,21 +1452,21 @@
csstype "^3.2.3"
prop-types "^15.8.1"
-"@mui/system@7.3.2":
- version "7.3.2"
- resolved "https://registry.yarnpkg.com/@mui/system/-/system-7.3.2.tgz#e838097fc6cb0a2e4c1822478950db89affb116a"
- integrity sha512-9d8JEvZW+H6cVkaZ+FK56R53vkJe3HsTpcjMUtH8v1xK6Y1TjzHdZ7Jck02mGXJsE6MQGWVs3ogRHTQmS9Q/rA==
+"@mui/system@7.3.10", "@mui/system@^7.3.10":
+ version "7.3.10"
+ resolved "https://registry.yarnpkg.com/@mui/system/-/system-7.3.10.tgz#b8e668537605413be168a865d4e980c7d6747320"
+ integrity sha512-/sfPpdpJaQn7BSF+avjIdHSYmxHp0UOBYNxSG9QGKfMOD6sLANCpRPCnanq1Pe0lFf0NHkO2iUk0TNzdWC1USQ==
dependencies:
- "@babel/runtime" "^7.28.3"
- "@mui/private-theming" "^7.3.2"
- "@mui/styled-engine" "^7.3.2"
- "@mui/types" "^7.4.6"
- "@mui/utils" "^7.3.2"
+ "@babel/runtime" "^7.28.6"
+ "@mui/private-theming" "^7.3.10"
+ "@mui/styled-engine" "^7.3.10"
+ "@mui/types" "^7.4.12"
+ "@mui/utils" "^7.3.10"
clsx "^2.1.1"
- csstype "^3.1.3"
+ csstype "^3.2.3"
prop-types "^15.8.1"
-"@mui/system@^7.3.2", "@mui/system@^7.3.7":
+"@mui/system@^7.3.2":
version "7.3.9"
resolved "https://registry.yarnpkg.com/@mui/system/-/system-7.3.9.tgz#d8181dd9ad8c5e9afdf50eb7009062c506976ab1"
integrity sha512-aL1q9am8XpRrSabv9qWf5RHhJICJql34wnrc1nz0MuOglPRYF/liN+c8VqZdTvUn9qg+ZjRVbKf4sJVFfIDtmg==
@@ -1459,14 +1480,45 @@
csstype "^3.2.3"
prop-types "^15.8.1"
-"@mui/types@^7.4.10", "@mui/types@^7.4.12", "@mui/types@^7.4.6":
+"@mui/types@^7.4.12", "@mui/types@^7.4.6":
version "7.4.12"
resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.4.12.tgz#e4eba37a7506419ea5c5e0604322ba82b271bf46"
integrity sha512-iKNAF2u9PzSIj40CjvKJWxFXJo122jXVdrmdh0hMYd+FR+NuJMkr/L88XwWLCRiJ5P1j+uyac25+Kp6YC4hu6w==
dependencies:
"@babel/runtime" "^7.28.6"
-"@mui/utils@^7.3.2", "@mui/utils@^7.3.5", "@mui/utils@^7.3.7", "@mui/utils@^7.3.9":
+"@mui/types@^9.0.0":
+ version "9.0.0"
+ resolved "https://registry.yarnpkg.com/@mui/types/-/types-9.0.0.tgz#92d8c64e72cb863ee59108cb20cc476d648a3ab9"
+ integrity sha512-i1cuFCAWN44b3AJWO7mh7tuh1sqbQSeVr/94oG0TX5uXivac8XalgE4/6fQZcmGZigzbQ35IXxj/4jLpRIBYZg==
+ dependencies:
+ "@babel/runtime" "^7.29.2"
+
+"@mui/utils@9.0.0":
+ version "9.0.0"
+ resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-9.0.0.tgz#25b563ccbf537feba5f89c37a00cb8e6eea45ad0"
+ integrity sha512-bQcqyg/gjULUqTuyUjSAFr6LQGLvtkNtDbJerAtoUn9kGZ0hg5QJiN1PLHMLbeFpe3te1831uq7GFl2ITokGdg==
+ dependencies:
+ "@babel/runtime" "^7.29.2"
+ "@mui/types" "^9.0.0"
+ "@types/prop-types" "^15.7.15"
+ clsx "^2.1.1"
+ prop-types "^15.8.1"
+ react-is "^19.2.4"
+
+"@mui/utils@^7.3.10":
+ version "7.3.10"
+ resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-7.3.10.tgz#b74050131ca9022c0815d16f54f1a6d757ab343d"
+ integrity sha512-7y2eIfy0h7JPz+Yy4pS+wgV68d46PuuxDqKBN4Q8VlPQSsCAGwroMCV6xWyc7g9dvEp8ZNFsknc59GHWO+r6Ow==
+ dependencies:
+ "@babel/runtime" "^7.28.6"
+ "@mui/types" "^7.4.12"
+ "@types/prop-types" "^15.7.15"
+ clsx "^2.1.1"
+ prop-types "^15.8.1"
+ react-is "^19.2.3"
+
+"@mui/utils@^7.3.2", "@mui/utils@^7.3.9":
version "7.3.9"
resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-7.3.9.tgz#8af5093fc93c2e582fa3d047f561c7b690509bc2"
integrity sha512-U6SdZaGbfb65fqTsH3V5oJdFj9uYwyLE2WVuNvmbggTSDBb8QHrFsqY8BN3taK9t3yJ8/BPHD/kNvLNyjwM7Yw==
@@ -1478,26 +1530,26 @@
prop-types "^15.8.1"
react-is "^19.2.3"
-"@mui/x-date-pickers@^8.27.2":
- version "8.27.2"
- resolved "https://registry.yarnpkg.com/@mui/x-date-pickers/-/x-date-pickers-8.27.2.tgz#5ada1fb3adffff3e0fd0fee7702fba7f770dca68"
- integrity sha512-06LFkHFRXJ2O9DMXtWAA3kY0jpbL7XH8iqa8L5cBlN+8bRx/UVLKlZYlhGv06C88jF9kuZWY1bUgrv/EoY/2Ww==
+"@mui/x-date-pickers@^9.0.2":
+ version "9.0.2"
+ resolved "https://registry.yarnpkg.com/@mui/x-date-pickers/-/x-date-pickers-9.0.2.tgz#ac601e4655ce3017185d652f9f91a2914bb6e63a"
+ integrity sha512-rnyc2wFPnprTS5i8Lq9aX2Rlx+ZRvNZERTd7sPMErf/8HnMCYzxwErITbd+TuImlvo2vaLF1gNynqT8AJMusYw==
dependencies:
- "@babel/runtime" "^7.28.4"
- "@mui/utils" "^7.3.5"
- "@mui/x-internals" "8.26.0"
+ "@babel/runtime" "^7.28.6"
+ "@mui/utils" "9.0.0"
+ "@mui/x-internals" "^9.0.0"
"@types/react-transition-group" "^4.4.12"
clsx "^2.1.1"
prop-types "^15.8.1"
react-transition-group "^4.4.5"
-"@mui/x-internals@8.26.0":
- version "8.26.0"
- resolved "https://registry.yarnpkg.com/@mui/x-internals/-/x-internals-8.26.0.tgz#49caacac954c29a1b10425c67418310ceb9c8cfa"
- integrity sha512-B9OZau5IQUvIxwpJZhoFJKqRpmWf5r0yMmSXjQuqb5WuqM755EuzWJOenY48denGoENzMLT8hQpA0hRTeU2IPA==
+"@mui/x-internals@^9.0.0":
+ version "9.0.0"
+ resolved "https://registry.yarnpkg.com/@mui/x-internals/-/x-internals-9.0.0.tgz#8851a058e09b719690b4f398319805239e923855"
+ integrity sha512-E/4rdg69JjhyybpPGypCjAKSKLLnSdCFM+O6P/nkUg47+qt3uftxQEhjQO53rcn6ahHl6du/uNZ9BLgeY6kYxQ==
dependencies:
- "@babel/runtime" "^7.28.4"
- "@mui/utils" "^7.3.5"
+ "@babel/runtime" "^7.28.6"
+ "@mui/utils" "9.0.0"
reselect "^5.1.1"
use-sync-external-store "^1.6.0"
@@ -2147,10 +2199,10 @@
resolved "https://registry.yarnpkg.com/@tiptap/extension-bold/-/extension-bold-3.20.5.tgz#b40e8e43db3123c5dee9864931f7f9ad1b1e07dc"
integrity sha512-hraiiWkF58n8Jy0Wl3OGwjCTrGWwZZxez/IlexrzKQ/nMFdjDpensZucWwu59zhAM9fqZwGSLDtCFuak03WKnA==
-"@tiptap/extension-bubble-menu@^3.20.4":
- version "3.20.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-3.20.4.tgz#e7e3c033a74d5dc67b1dac84346ee12e07d81b86"
- integrity sha512-EXywPlI8wjPcAb8ozymgVhjtMjFrnhtoyNTy8ZcObdpUi5CdO9j892Y7aPbKe5hLhlDpvJk7rMfir4FFKEmfng==
+"@tiptap/extension-bubble-menu@^3.20.5":
+ version "3.22.3"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-3.22.3.tgz#f94a3ac119b8576d040dc458d44b4200ad03e27b"
+ integrity sha512-Y6zQjh0ypDg32HWgICEvmPSKjGLr39k3aDxxt/H0uQEZSfw4smT0hxUyyyjVjx68C6t6MTnwdfz0hPI5lL68vQ==
dependencies:
"@floating-ui/dom" "^1.0.0"
@@ -2179,10 +2231,10 @@
resolved "https://registry.yarnpkg.com/@tiptap/extension-dropcursor/-/extension-dropcursor-3.20.5.tgz#ea810297825b009c357559e66f5fd76e91e8c940"
integrity sha512-/lDG9OjvAv0ynmgFH17mt/GUeGT5bqu0iPW8JMgaRqlKawk+uUIv5SF5WkXS4SwxXih+hXdPEQD3PWZnxlQxAQ==
-"@tiptap/extension-floating-menu@^3.20.4":
- version "3.20.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-3.20.4.tgz#5b082cf500330f0a66f91a49c3a1a232038662a7"
- integrity sha512-AaPTFhoO8DBIElJyd/RTVJjkctvJuL+GHURX0npbtTxXq5HXbebVwf2ARNR7jMd/GThsmBaNJiGxZg4A2oeDqQ==
+"@tiptap/extension-floating-menu@^3.20.5":
+ version "3.22.3"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-3.22.3.tgz#c9a911b7784cb45d6f8e7260d77bf2015066e5a4"
+ integrity sha512-0f8b4KZ3XKai8GXWseIYJGdOfQr3evtFbBo3U08zy2aYzMMXWG0zEF7qe5/oiYp2aZ95edjjITnEceviTsZkIg==
"@tiptap/extension-gapcursor@^3.20.5":
version "3.20.5"
@@ -2295,17 +2347,17 @@
prosemirror-transform "^1.10.2"
prosemirror-view "^1.38.1"
-"@tiptap/react@^3.4.1":
- version "3.20.4"
- resolved "https://registry.yarnpkg.com/@tiptap/react/-/react-3.20.4.tgz#b313ff5051e30de4476138e47802a67bfda8ca2e"
- integrity sha512-1B8iWsHWwb5TeyVaUs8BRPzwWo4PsLQcl03urHaz0zTJ8DauopqvxzV3+lem1OkzRHn7wnrapDvwmIGoROCaQw==
+"@tiptap/react@^3.20.5":
+ version "3.20.5"
+ resolved "https://registry.yarnpkg.com/@tiptap/react/-/react-3.20.5.tgz#6b2bd999470d9037fd9741ba598c9b3dc12f7759"
+ integrity sha512-in37o1Eo7JCflcHyK/SDfgkJBgX0LRN3LMk+NdLPTerRnC0zhGLQlpfBL4591TLTOUQde7QIrLv98smYO2mj+w==
dependencies:
"@types/use-sync-external-store" "^0.0.6"
fast-equals "^5.3.3"
use-sync-external-store "^1.4.0"
optionalDependencies:
- "@tiptap/extension-bubble-menu" "^3.20.4"
- "@tiptap/extension-floating-menu" "^3.20.4"
+ "@tiptap/extension-bubble-menu" "^3.20.5"
+ "@tiptap/extension-floating-menu" "^3.20.5"
"@tiptap/starter-kit@^3.20.5":
version "3.20.5"
@@ -3041,10 +3093,10 @@ axe-core@^4.10.0:
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.11.1.tgz#052ff9b2cbf543f5595028b583e4763b40c78ea7"
integrity sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A==
-axios@1.14.0:
- version "1.14.0"
- resolved "https://registry.yarnpkg.com/axios/-/axios-1.14.0.tgz#7c29f4cf2ea91ef05018d5aa5399bf23ed3120eb"
- integrity sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ==
+axios@1.15.0:
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-1.15.0.tgz#0fcee91ef03d386514474904b27863b2c683bf4f"
+ integrity sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==
dependencies:
follow-redirects "^1.15.11"
form-data "^4.0.5"
@@ -7010,6 +7062,11 @@ react-is@^19.2.3:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-19.2.4.tgz#a080758243c572ccd4a63386537654298c99d135"
integrity sha512-W+EWGn2v0ApPKgKKCy/7s7WHXkboGcsrXE+2joLyVxkbyVQfO3MUEaUQDHoSmb8TFFrSKYa9mw64WZHNHSDzYA==
+react-is@^19.2.4:
+ version "19.2.5"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-19.2.5.tgz#7e7b54143e9313fed787b23fd4295d5a23872ad9"
+ integrity sha512-Dn0t8IQhCmeIT3wu+Apm1/YVsJXsGWi6k4sPdnBIdqMVtHtv0IGi6dcpNpNkNac0zB2uUAqNX3MHzN8c+z2rwQ==
+
react-leaflet-markercluster@^5.0.0-rc.0:
version "5.0.0-rc.0"
resolved "https://registry.yarnpkg.com/react-leaflet-markercluster/-/react-leaflet-markercluster-5.0.0-rc.0.tgz#42b1b9786de565fe69ec95abc6ff3232713f5300"
@@ -7130,10 +7187,10 @@ react-virtualized-auto-sizer@^1.0.26:
resolved "https://registry.yarnpkg.com/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.26.tgz#e9470ef6a778dc4f1d5fd76305fa2d8b610c357a"
integrity sha512-CblNyiNVw2o+hsa5/49NH2ogGxZ+t+3aweRvNSq7TVjDIlwk7ir4lencEg5HxHeSzwNarSkNkiu0qJSOXtxm5A==
-react-virtuoso@^4.18.3:
- version "4.18.3"
- resolved "https://registry.yarnpkg.com/react-virtuoso/-/react-virtuoso-4.18.3.tgz#12e69600c258bc6e6bd31c2516942ef08700deac"
- integrity sha512-fLz/peHAx4Eu0DLHurFEEI7Y6n5CqEoxBh04rgJM9yMuOJah2a9zWg/MUOmZLcp7zuWYorXq5+5bf3IRgkNvWg==
+react-virtuoso@^4.18.5:
+ version "4.18.5"
+ resolved "https://registry.yarnpkg.com/react-virtuoso/-/react-virtuoso-4.18.5.tgz#450108e585c7a1124b995c7ea3cf367ed4857631"
+ integrity sha512-QDyNjyNEuurZG67SOmzYyxEkQYSyGmAMixOI6M15L/Q4CF39EgG+88y6DgZRo0q7rmy0HPx3Fj90I8/tPdnRCQ==
react-window@^2.2.7:
version "2.2.7"