diff --git a/package.json b/package.json index cae512d4c086..879b3c54028c 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ }, "license": "AGPL-3.0", "engines": { - "node": "^20.18.3" + "node": "^22.13.0" }, "repository": { "type": "git", @@ -71,6 +71,7 @@ "nprogress": "0.2.0", "numeral": "2.0.6", "prop-types": "15.8.1", + "punycode": "^2.3.1", "react": "19.0.0", "react-apexcharts": "1.7.0", "react-beautiful-dnd": "13.1.1", diff --git a/public/version.json b/public/version.json index aaa3822d959a..e13bd0cafa30 100644 --- a/public/version.json +++ b/public/version.json @@ -1,3 +1,3 @@ { - "version": "7.4.1" + "version": "7.4.2" } diff --git a/src/components/CippCards/CippDomainCards.jsx b/src/components/CippCards/CippDomainCards.jsx index 286e7cc35808..03fd08306afc 100644 --- a/src/components/CippCards/CippDomainCards.jsx +++ b/src/components/CippCards/CippDomainCards.jsx @@ -28,6 +28,7 @@ import { CippCodeBlock } from "/src/components/CippComponents/CippCodeBlock"; import { CippOffCanvas } from "../CippComponents/CippOffCanvas"; import { CippPropertyListCard } from "./CippPropertyListCard"; import { getCippFormatting } from "../../utils/get-cipp-formatting"; +import punycode from "punycode"; const ResultList = ({ passes = [], warns = [], fails = [] }) => ( @@ -395,7 +396,8 @@ export const CippDomainCards = ({ domain: propDomain = "", fullwidth = false }) }, [propDomain, setValue]); const onSubmit = (values) => { - setDomain(values.domain); + const punycodedDomain = punycode.toASCII(values.domain); + setDomain(punycodedDomain); setSelector(values.dkimSelector); setSpfRecord(values.spfRecord); setSubdomains(values.subdomains); diff --git a/src/components/CippComponents/CippApiDialog.jsx b/src/components/CippComponents/CippApiDialog.jsx index 28bfd7901a03..865e28e38d6c 100644 --- a/src/components/CippComponents/CippApiDialog.jsx +++ b/src/components/CippComponents/CippApiDialog.jsx @@ -282,38 +282,36 @@ export const CippApiDialog = (props) => { .reduce((acc, key) => (acc && acc[key] !== undefined ? acc[key] : undefined), obj); }; - // Handling external link navigation - useEffect(() => { - if (api.link && createDialog.open) { - const linkWithRowData = api.link.replace(/\[([^\]]+)\]/g, (_, key) => { - return getNestedValue(row, key) || `[${key}]`; - }); + const [linkClicked, setLinkClicked] = useState(false); - if (!linkWithRowData.startsWith("/")) { - window.open(linkWithRowData, api.target || "_blank"); - createDialog.handleClose(); - } - } - }, [api.link, createDialog.open]); + useEffect(() => { + if (api.link && !linkClicked && row && Object.keys(row).length > 0) { + const timeoutId = setTimeout(() => { + const linkWithRowData = api.link.replace(/\[([^\]]+)\]/g, (_, key) => { + return getNestedValue(row, key) || `[${key}]`; + }); - // Handling internal link navigation - if (api.link && createDialog.open) { - const linkWithRowData = api.link.replace(/\[([^\]]+)\]/g, (_, key) => { - return getNestedValue(row, key) || `[${key}]`; - }); + if (linkWithRowData.startsWith("/")) { + // Internal link navigation + setLinkClicked(true); + router.push(linkWithRowData, undefined, { shallow: true }); + } else { + // External link navigation + setLinkClicked(true); + window.open(linkWithRowData, api.target || "_blank"); + } + }, 0); // Delay execution to the next event loop cycle - if (linkWithRowData.startsWith("/")) { - router.push(linkWithRowData, undefined, { shallow: true }); - createDialog.handleClose(); + return () => clearTimeout(timeoutId); } - } + }, [api.link, linkClicked, row, router]); useEffect(() => { - if (api.noConfirm) { + if (api.noConfirm && !api.link) { formHook.handleSubmit(onSubmit)(); // Submits the form on mount createDialog.handleClose(); // Closes the dialog after submitting } - }, [api.noConfirm]); // Run effect only when api.noConfirm changes + }, [api.noConfirm, api.link]); // Run effect when noConfirm or link changes const handleClose = () => { createDialog.handleClose(); @@ -336,44 +334,52 @@ export const CippApiDialog = (props) => { } return ( - -
- {title} - - {confirmText} - - - - {fields && - fields.map((fieldProps, index) => { - if (fieldProps?.api?.processFieldData) { - fieldProps.api.data = processActionData(fieldProps.api.data, row); - } - return ( - - - - ); - })} - - - - - - - - - -
-
+ <> + {!api?.link && ( + +
+ {title} + + {confirmText} + + + + {fields && + fields.map((fieldProps, index) => { + if (fieldProps?.api?.processFieldData) { + fieldProps.api.data = processActionData(fieldProps.api.data, row); + } + return ( + + + + ); + })} + + + + + + + + + +
+
+ )} + ); }; diff --git a/src/components/CippComponents/CippApiResults.jsx b/src/components/CippComponents/CippApiResults.jsx index 4d0180f485df..b7bcc0a675be 100644 --- a/src/components/CippComponents/CippApiResults.jsx +++ b/src/components/CippComponents/CippApiResults.jsx @@ -38,7 +38,7 @@ const extractAllResults = (data) => { if (item && typeof item === "object") { const text = item.resultText || ""; - const copyField = item.copyField || text; + const copyField = item.copyField || ""; const severity = typeof item.state === "string" ? item.state : getSeverity(item) ? "error" : "success"; @@ -47,6 +47,7 @@ const extractAllResults = (data) => { text, copyField, severity, + ...item, }; } } @@ -172,6 +173,7 @@ export const CippApiResults = (props) => { copyField: res.copyField, severity: res.severity, visible: true, + ...res, })) ); } else { diff --git a/src/components/CippComponents/CippCustomVariables.jsx b/src/components/CippComponents/CippCustomVariables.jsx index b7395e1aaece..18319a4064e1 100644 --- a/src/components/CippComponents/CippCustomVariables.jsx +++ b/src/components/CippComponents/CippCustomVariables.jsx @@ -92,8 +92,8 @@ const CippCustomVariables = ({ id }) => { {id === "AllTenants" - ? "Global variables are key-value pairs that can be used to store additional information for All Tenants. These are applied to templates in standards using the format %VariableName%. If a tenant has a custom variable with the same name, the tenant's variable will take precedence." - : "Custom variables are key-value pairs that can be used to store additional information about a tenant. These are applied to templates in standards using the format %VariableName%."} + ? "Global variables are key-value pairs that can be used to store additional information for All Tenants. These are applied to templates in standards using the format %variablename%. If a tenant has a custom variable with the same name, the tenant's variable will take precedence." + : "Custom variables are key-value pairs that can be used to store additional information about a tenant. These are applied to templates in standards using the format %variablename%."} { const { @@ -79,9 +80,11 @@ export const CippDataTable = (props) => { useEffect(() => { if (Array.isArray(data) && !api?.url) { - setUsedData(data); + if (!isEqual(data, usedData)) { + setUsedData(data); + } } - }, [data, api?.url]); + }, [data, api?.url, usedData]); useEffect(() => { if (getRequestData.isSuccess && !getRequestData.isFetching) { @@ -127,7 +130,13 @@ export const CippDataTable = (props) => { queryKey, ]); useEffect(() => { - if (!Array.isArray(usedData) || usedData.length === 0 || typeof usedData[0] !== "object") { + if ( + !Array.isArray(usedData) || + usedData.length === 0 || + typeof usedData[0] !== "object" || + usedData === null || + usedData === undefined + ) { return; } const apiColumns = utilColumnsFromAPI(usedData); @@ -156,7 +165,7 @@ export const CippDataTable = (props) => { } setUsedColumns(finalColumns); setColumnVisibility(newVisibility); - }, [columns.length, usedData.length, queryKey]); + }, [columns.length, usedData, queryKey]); const createDialog = useDialog(); @@ -195,7 +204,7 @@ export const CippDataTable = (props) => { }, }), columns: memoizedColumns, - data: memoizedData, + data: memoizedData ?? [], state: { columnVisibility, sorting, @@ -294,8 +303,8 @@ export const CippDataTable = (props) => { data={data} columnVisibility={columnVisibility} getRequestData={getRequestData} - usedColumns={usedColumns} - usedData={usedData} + usedColumns={memoizedColumns} + usedData={memoizedData ?? []} title={title} actions={actions} exportEnabled={exportEnabled} diff --git a/src/data/M365Licenses.json b/src/data/M365Licenses.json index c306c614f4a5..aa7ef62fb439 100644 --- a/src/data/M365Licenses.json +++ b/src/data/M365Licenses.json @@ -27471,6 +27471,310 @@ "Service_Plan_Id": "89f1c4c8-0878-40f7-804d-869c9128ab5d", "Service_Plans_Included_Friendly_Names": "Power Platform Connectors in Microsoft 365 Copilot" }, + { + "Product_Display_Name": "Microsoft 365 Copilot for Sales", + "String_Id": "Microsoft_Copilot_for_Sales", + "GUID": "15f2e9fc-b782-4f73-bf51-81d8b7fff6f4", + "Service_Plan_Name": "COPILOT_STUDIO_IN_COPILOT_FOR_M365", + "Service_Plan_Id": "fe6c28b3-d468-44ea-bbd0-a10a5167435c", + "Service_Plans_Included_Friendly_Names": "Copilot Studio in Copilot for M365" + }, + { + "Product_Display_Name": "Microsoft 365 Copilot for Sales", + "String_Id": "Microsoft_Copilot_for_Sales", + "GUID": "15f2e9fc-b782-4f73-bf51-81d8b7fff6f4", + "Service_Plan_Name": "GRAPH_CONNECTORS_COPILOT", + "Service_Plan_Id": "82d30987-df9b-4486-b146-198b21d164c7", + "Service_Plans_Included_Friendly_Names": "Graph Connectors in Microsoft 365 Copilot" + }, + { + "Product_Display_Name": "Microsoft 365 Copilot for Sales", + "String_Id": "Microsoft_Copilot_for_Sales", + "GUID": "15f2e9fc-b782-4f73-bf51-81d8b7fff6f4", + "Service_Plan_Name": "M365_COPILOT_INTELLIGENT_SEARCH", + "Service_Plan_Id": "931e4a88-a67f-48b5-814f-16a5f1e6028d", + "Service_Plans_Included_Friendly_Names": "Intelligent Search" + }, + { + "Product_Display_Name": "Microsoft 365 Copilot for Sales", + "String_Id": "Microsoft_Copilot_for_Sales", + "GUID": "15f2e9fc-b782-4f73-bf51-81d8b7fff6f4", + "Service_Plan_Name": "M365_COPILOT_SHAREPOINT", + "Service_Plan_Id": "0aedf20c-091d-420b-aadf-30c042609612", + "Service_Plans_Included_Friendly_Names": "Microsoft 365 Copilot for SharePoint" + }, + { + "Product_Display_Name": "Microsoft 365 Copilot for Sales", + "String_Id": "Microsoft_Copilot_for_Sales", + "GUID": "15f2e9fc-b782-4f73-bf51-81d8b7fff6f4", + "Service_Plan_Name": "M365_COPILOT_TEAMS", + "Service_Plan_Id": "b95945de-b3bd-46db-8437-f2beb6ea2347", + "Service_Plans_Included_Friendly_Names": "Microsoft 365 Copilot in Microsoft Teams" + }, + { + "Product_Display_Name": "Microsoft 365 Copilot for Sales", + "String_Id": "Microsoft_Copilot_for_Sales", + "GUID": "15f2e9fc-b782-4f73-bf51-81d8b7fff6f4", + "Service_Plan_Name": "M365_COPILOT_APPS", + "Service_Plan_Id": "a62f8878-de10-42f3-b68f-6149a25ceb97", + "Service_Plans_Included_Friendly_Names": "Microsoft 365 Copilot in Productivity Apps" + }, + { + "Product_Display_Name": "Microsoft 365 Copilot for Sales", + "String_Id": "Microsoft_Copilot_for_Sales", + "GUID": "15f2e9fc-b782-4f73-bf51-81d8b7fff6f4", + "Service_Plan_Name": "Microsoft_Copilot_for_Sales", + "Service_Plan_Id": "a2194428-ead1-4fc1-bb81-ab8675125f42", + "Service_Plans_Included_Friendly_Names": "Microsoft Copilot for Sales" + }, + { + "Product_Display_Name": "Microsoft 365 Copilot for Sales", + "String_Id": "Microsoft_Copilot_for_Sales", + "GUID": "15f2e9fc-b782-4f73-bf51-81d8b7fff6f4", + "Service_Plan_Name": "Microsoft_Copilot_for_Sales_PowerAutomate", + "Service_Plan_Id": "0c1c2af2-6c51-43c7-9c55-fa487ac147ff", + "Service_Plans_Included_Friendly_Names": "Microsoft Copilot for Sales with Power Automate" + }, + { + "Product_Display_Name": "Microsoft 365 Copilot for Sales", + "String_Id": "Microsoft_Copilot_for_Sales", + "GUID": "15f2e9fc-b782-4f73-bf51-81d8b7fff6f4", + "Service_Plan_Name": "M365_COPILOT_BUSINESS_CHAT", + "Service_Plan_Id": "3f30311c-6b1e-48a4-ab79-725b469da960", + "Service_Plans_Included_Friendly_Names": "Microsoft Copilot with Graph-grounded chat" + }, + { + "Product_Display_Name": "Microsoft 365 Copilot for Sales", + "String_Id": "Microsoft_Copilot_for_Sales", + "GUID": "15f2e9fc-b782-4f73-bf51-81d8b7fff6f4", + "Service_Plan_Name": "WORKPLACE_ANALYTICS_INSIGHTS_USER", + "Service_Plan_Id": "b622badb-1b45-48d5-920f-4b27a2c0996c", + "Service_Plans_Included_Friendly_Names": "Microsoft Viva Insights" + }, + { + "Product_Display_Name": "Microsoft 365 Copilot for Sales", + "String_Id": "Microsoft_Copilot_for_Sales", + "GUID": "15f2e9fc-b782-4f73-bf51-81d8b7fff6f4", + "Service_Plan_Name": "WORKPLACE_ANALYTICS_INSIGHTS_BACKEND", + "Service_Plan_Id": "ff7b261f-d98b-415b-827c-42a3fdf015af", + "Service_Plans_Included_Friendly_Names": "Microsoft Viva Insights Backend" + }, + { + "Product_Display_Name": "Microsoft 365 Copilot for Sales", + "String_Id": "Microsoft_Copilot_for_Sales", + "GUID": "15f2e9fc-b782-4f73-bf51-81d8b7fff6f4", + "Service_Plan_Name": "M365_COPILOT_CONNECTORS", + "Service_Plan_Id": "89f1c4c8-0878-40f7-804d-869c9128ab5d", + "Service_Plans_Included_Friendly_Names": "Power Platform Connectors in Microsoft 365 Copilot" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio", + "String_Id": "Power_Virtual_Agents", + "GUID": "75564b9c-51e8-431c-b8fe-d472d5a545c8", + "Service_Plan_Name": "CDS_VIRTUAL_AGENT_BASE_MESSAGES", + "Service_Plan_Id": "5dd1819f-0de7-487f-985b-c450a4c9cc1d", + "Service_Plans_Included_Friendly_Names": "Dataverse for Microsoft Copilot Studio" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio", + "String_Id": "Power_Virtual_Agents", + "GUID": "75564b9c-51e8-431c-b8fe-d472d5a545c8", + "Service_Plan_Name": "VIRTUAL_AGENT_BASE_MESSAGES", + "Service_Plan_Id": "7b0640f1-63cc-4f83-b8c6-0a4d78b8b988", + "Service_Plans_Included_Friendly_Names": "Microsoft Copilot Studio – Messages" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio", + "String_Id": "Power_Virtual_Agents", + "GUID": "75564b9c-51e8-431c-b8fe-d472d5a545c8", + "Service_Plan_Name": "FLOW_VIRTUAL_AGENT_BASE_MESSAGES", + "Service_Plan_Id": "4b9ec373-ed29-4192-8a47-c9ab9048b079", + "Service_Plans_Included_Friendly_Names": "Power Automate for Microsoft Copilot Studio" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio for GCC", + "String_Id": "Power_Virtual_Agents_for_GCC_GCC", + "GUID": "d7974fa0-ddd7-4899-9589-1ea04273aa26", + "Service_Plan_Name": "CDS_VIRTUAL_AGENT_BASE_MESSAGES", + "Service_Plan_Id": "5dd1819f-0de7-487f-985b-c450a4c9cc1d", + "Service_Plans_Included_Friendly_Names": "Dataverse for Microsoft Copilot Studio" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio for GCC", + "String_Id": "Power_Virtual_Agents_for_GCC_GCC", + "GUID": "d7974fa0-ddd7-4899-9589-1ea04273aa26", + "Service_Plan_Name": "VIRTUAL_AGENT_BASE_MESSAGES", + "Service_Plan_Id": "7b0640f1-63cc-4f83-b8c6-0a4d78b8b988", + "Service_Plans_Included_Friendly_Names": "Microsoft Copilot Studio – Messages" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio for GCC", + "String_Id": "Power_Virtual_Agents_for_GCC_GCC", + "GUID": "d7974fa0-ddd7-4899-9589-1ea04273aa26", + "Service_Plan_Name": "FLOW_VIRTUAL_AGENT_BASE_MESSAGES", + "Service_Plan_Id": "4b9ec373-ed29-4192-8a47-c9ab9048b079", + "Service_Plans_Included_Friendly_Names": "Power Automate for Microsoft Copilot Studio" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio_USGOV_GCCHIGH", + "String_Id": "Power_Virtual_Agents_USGOV_GCCHIGH", + "GUID": "84ed7c30-3738-43a0-aa03-cf6c577d8dbb", + "Service_Plan_Name": "CDS_VIRTUAL_AGENT_BASE_MESSAGES", + "Service_Plan_Id": "5dd1819f-0de7-487f-985b-c450a4c9cc1d", + "Service_Plans_Included_Friendly_Names": "CDS_VIRTUAL_AGENT_BASE_MESSAGES" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio_USGOV_GCCHIGH", + "String_Id": "Power_Virtual_Agents_USGOV_GCCHIGH", + "GUID": "84ed7c30-3738-43a0-aa03-cf6c577d8dbb", + "Service_Plan_Name": "VIRTUAL_AGENT_BASE_MESSAGES", + "Service_Plan_Id": "7b0640f1-63cc-4f83-b8c6-0a4d78b8b988", + "Service_Plans_Included_Friendly_Names": "VIRTUAL_AGENT_BASE_MESSAGES" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio_USGOV_GCCHIGH", + "String_Id": "Power_Virtual_Agents_USGOV_GCCHIGH", + "GUID": "84ed7c30-3738-43a0-aa03-cf6c577d8dbb", + "Service_Plan_Name": "FLOW_VIRTUAL_AGENT_BASE_MESSAGES", + "Service_Plan_Id": "4b9ec373-ed29-4192-8a47-c9ab9048b079", + "Service_Plans_Included_Friendly_Names": "FLOW_VIRTUAL_AGENT_BASE_MESSAGES" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio User License", + "String_Id": "VIRTUAL_AGENT_USL", + "GUID": "4b74a65c-8b4a-4fc8-9f6b-5177ed11ddfa", + "Service_Plan_Name": "CDS_VIRTUAL_AGENT_USL", + "Service_Plan_Id": "cb867b3c-7f38-4d0d-99ce-e29cd69812c8", + "Service_Plans_Included_Friendly_Names": "Common Data Service" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio User License", + "String_Id": "VIRTUAL_AGENT_USL", + "GUID": "4b74a65c-8b4a-4fc8-9f6b-5177ed11ddfa", + "Service_Plan_Name": "FLOW_VIRTUAL_AGENT_USL", + "Service_Plan_Id": "82f141c9-2e87-4f43-8cb2-12d2701dc6b3", + "Service_Plans_Included_Friendly_Names": "Power Automate for Virtual Agent" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio User License", + "String_Id": "VIRTUAL_AGENT_USL", + "GUID": "4b74a65c-8b4a-4fc8-9f6b-5177ed11ddfa", + "Service_Plan_Name": "VIRTUAL_AGENT_USL", + "Service_Plan_Id": "1263586c-59a4-4ad0-85e1-d50bc7149501", + "Service_Plans_Included_Friendly_Names": "Virtual Agent" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio User License for GCC", + "String_Id": "VIRTUAL_AGENT_USL_GCC", + "GUID": "f1de227b-f1bd-4959-bd80-b80547095e6d", + "Service_Plan_Name": "CDS_Virtual_Agent_Usl_Gov", + "Service_Plan_Id": "bcc0702e-ba97-48d9-ae04-fa8689c53bba", + "Service_Plans_Included_Friendly_Names": "Dataverse for Virtual Agent USL for GCC" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio User License for GCC", + "String_Id": "VIRTUAL_AGENT_USL_GCC", + "GUID": "f1de227b-f1bd-4959-bd80-b80547095e6d", + "Service_Plan_Name": "Virtual_Agent_Usl_Gov", + "Service_Plan_Id": "00b6f978-853b-4041-9de0-a233d18669aa", + "Service_Plans_Included_Friendly_Names": "Virtual Agent for GCC" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio User License for GCC", + "String_Id": "VIRTUAL_AGENT_USL_GCC", + "GUID": "f1de227b-f1bd-4959-bd80-b80547095e6d", + "Service_Plan_Name": "CDS_Virtual_Agent_Usl_GCC", + "Service_Plan_Id": "95df1203-fee7-4726-b7e1-8037a8e899eb", + "Service_Plans_Included_Friendly_Names": "Dataverse for Virtual Agent USL for GCC" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio User License for GCC", + "String_Id": "VIRTUAL_AGENT_USL_GCC", + "GUID": "f1de227b-f1bd-4959-bd80-b80547095e6d", + "Service_Plan_Name": "Flow_Virtual_Agent_Usl_Gov", + "Service_Plan_Id": "0b939472-1861-45f1-ab6d-208f359c05cd", + "Service_Plans_Included_Friendly_Names": "Flow for Virtual Agent for GCC" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio User License for GCC", + "String_Id": "VIRTUAL_AGENT_USL_GCC", + "GUID": "f1de227b-f1bd-4959-bd80-b80547095e6d", + "Service_Plan_Name": "FLOW_Virtual_Agent_Base_Gov", + "Service_Plan_Id": "f9f6db16-ace6-4838-b11c-892ee75e810a", + "Service_Plans_Included_Friendly_Names": "Power Automate for Virtual Agent for GCC" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio User License for GCC", + "String_Id": "VIRTUAL_AGENT_USL_GCC", + "GUID": "f1de227b-f1bd-4959-bd80-b80547095e6d", + "Service_Plan_Name": "Power_Virtual_Agent_Usl_GCC", + "Service_Plan_Id": "0bdd5466-65c3-470a-9fa6-f679b48286b0", + "Service_Plans_Included_Friendly_Names": "Power Virtual Agent USL for GCC" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio User License for GCC High_USGOV_GCCHIGH", + "String_Id": "VIRTUAL_AGENT_USL_AR_USGOV_GCCHIGH", + "GUID": "470845c0-6884-47e1-89d0-9d6244a77b44", + "Service_Plan_Name": "Virtual_Agent_Usl_Gov_High", + "Service_Plan_Id": "7ffee552-ebe8-4725-8678-5c1775c05847", + "Service_Plans_Included_Friendly_Names": "Virtual Agent for GCC High" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio User License for GCC High_USGOV_GCCHIGH", + "String_Id": "VIRTUAL_AGENT_USL_AR_USGOV_GCCHIGH", + "GUID": "470845c0-6884-47e1-89d0-9d6244a77b44", + "Service_Plan_Name": "CDS_VIRTUAL_AGENT_USL", + "Service_Plan_Id": "cb867b3c-7f38-4d0d-99ce-e29cd69812c8", + "Service_Plans_Included_Friendly_Names": "Common Data Service" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio User License for GCC High_USGOV_GCCHIGH", + "String_Id": "VIRTUAL_AGENT_USL_AR_USGOV_GCCHIGH", + "GUID": "470845c0-6884-47e1-89d0-9d6244a77b44", + "Service_Plan_Name": "FLOW_Virtual_Agent_Base_Gov_High", + "Service_Plan_Id": "225e52e5-7bbf-4793-8fb1-4307a7a1ae8e", + "Service_Plans_Included_Friendly_Names": "Flow for Virtual Agent for GCC High" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio User License for GCC High_USGOV_GCCHIGH", + "String_Id": "VIRTUAL_AGENT_USL_AR_USGOV_GCCHIGH", + "GUID": "470845c0-6884-47e1-89d0-9d6244a77b44", + "Service_Plan_Name": "Flow_Virtual_Agent_Usl_Gov_High", + "Service_Plan_Id": "aaae1744-dc7a-4811-9dd0-2bf926ff9d80", + "Service_Plans_Included_Friendly_Names": "Flow for Virtual Agent for GCC High" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio User License for GCC High_USGOV_GCCHIGH", + "String_Id": "VIRTUAL_AGENT_USL_AR_USGOV_GCCHIGH", + "GUID": "470845c0-6884-47e1-89d0-9d6244a77b44", + "Service_Plan_Name": "Power_Virtual_Agent_Usl_GCC_High", + "Service_Plan_Id": "3fbe8cdf-c735-44bf-bbfa-646724af4bb4", + "Service_Plans_Included_Friendly_Names": "Power Virtual Agent USL for GCC High" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio Viral Trial", + "String_Id": "CCIBOTS_PRIVPREV_VIRAL", + "GUID": "606b54a9-78d8-4298-ad8b-df6ef4481c80", + "Service_Plan_Name": "DYN365_CDS_CCI_BOTS", + "Service_Plan_Id": "cf7034ed-348f-42eb-8bbd-dddeea43ee81", + "Service_Plans_Included_Friendly_Names": "DYN365_CDS_CCI_BOTS" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio Viral Trial", + "String_Id": "CCIBOTS_PRIVPREV_VIRAL", + "GUID": "606b54a9-78d8-4298-ad8b-df6ef4481c80", + "Service_Plan_Name": "CCIBOTS_PRIVPREV_VIRAL", + "Service_Plan_Id": "ce312d15-8fdf-44c0-9974-a25a177125ee", + "Service_Plans_Included_Friendly_Names": "CCIBOTS_PRIVPREV_VIRAL" + }, + { + "Product_Display_Name": "Microsoft Copilot Studio Viral Trial", + "String_Id": "CCIBOTS_PRIVPREV_VIRAL", + "GUID": "606b54a9-78d8-4298-ad8b-df6ef4481c80", + "Service_Plan_Name": "FLOW_CCI_BOTS", + "Service_Plan_Id": "5d798708-6473-48ad-9776-3acc301c40af", + "Service_Plans_Included_Friendly_Names": "FLOW_CCI_BOTS" + }, { "Product_Display_Name": "Microsoft Cloud App Security", "String_Id": "ADALLOM_STANDALONE", diff --git a/src/data/standards.json b/src/data/standards.json index 952616f3853a..71d668bf8bca 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -1155,6 +1155,7 @@ "type": "autoComplete", "multiple": true, "creatable": true, + "required": false, "label": "Enter allowed senders(domain.com, *.domain.com or test@domain.com)", "name": "standards.SpoofWarn.AllowListAdd" } diff --git a/src/pages/identity/administration/groups/index.js b/src/pages/identity/administration/groups/index.js index 0df2e951e942..ce0fd6b290f8 100644 --- a/src/pages/identity/administration/groups/index.js +++ b/src/pages/identity/administration/groups/index.js @@ -3,7 +3,15 @@ import { CippTablePage } from "/src/components/CippComponents/CippTablePage.jsx" import { Layout as DashboardLayout } from "/src/layouts/index.js"; import Link from "next/link"; import { TrashIcon } from "@heroicons/react/24/outline"; -import { Visibility, VisibilityOff, GroupAdd, Edit, LockOpen, Lock } from "@mui/icons-material"; +import { + Visibility, + VisibilityOff, + GroupAdd, + Edit, + LockOpen, + Lock, + GroupSharp, +} from "@mui/icons-material"; const Page = () => { const pageTitle = "Groups"; @@ -72,6 +80,22 @@ const Page = () => { "Are you sure you want to allow messages from people inside and outside the organisation? Remember this will not work if the group is AD Synched.", multiPost: false, }, + { + label: "Create template based on group", + type: "POST", + url: "/api/AddGroupTemplate", + icon: , + data: { + Displayname: "displayname", + Description: "description", + GroupType: "calculatedGroupType", + MembershipRules: "membershipRule", + allowExternal: "allowExternal", + username: "mailNickname", + }, + confirmText: "Are you sure you want to create a template based on this group?", + multiPost: false, + }, { label: "Delete Group", type: "POST", diff --git a/src/pages/tenant/standards/compare/index.js b/src/pages/tenant/standards/compare/index.js index 51aa7d630902..7b96932616fe 100644 --- a/src/pages/tenant/standards/compare/index.js +++ b/src/pages/tenant/standards/compare/index.js @@ -2,7 +2,6 @@ import { useState, useEffect } from "react"; import { Button, Card, - CardContent, Stack, Typography, Box, @@ -12,22 +11,24 @@ import { Alert, IconButton, Tooltip, + ButtonGroup, + TextField, + InputAdornment, } from "@mui/material"; import { Layout as DashboardLayout } from "/src/layouts/index.js"; import { - PlayArrow, CheckCircle, Cancel, Info, - Public, Microsoft, - Description, Sync, + FilterAlt, + Close, + Search, + FactCheck, } from "@mui/icons-material"; import { ArrowLeftIcon } from "@mui/x-date-pickers"; -import CippFormComponent from "/src/components/CippComponents/CippFormComponent"; import standards from "/src/data/standards.json"; -import { CippApiResults } from "../../../../components/CippComponents/CippApiResults"; import { CippApiDialog } from "../../../../components/CippComponents/CippApiDialog"; import { SvgIcon } from "@mui/material"; import { useForm } from "react-hook-form"; @@ -52,6 +53,8 @@ const Page = () => { }, }); const runReportDialog = useDialog(); + const [filter, setFilter] = useState("all"); + const [searchQuery, setSearchQuery] = useState(""); const templateDetails = ApiGetCall({ url: `/api/listStandardTemplates`, @@ -238,6 +241,27 @@ const Page = () => { ]); const comparisonModeOptions = [{ label: "Compare Tenant to Standard", value: "standard" }]; + const filteredData = comparisonData?.filter((standard) => { + const matchesFilter = + filter === "all" || + (filter === "compliant" && standard.complianceStatus === "Compliant") || + (filter === "nonCompliant" && standard.complianceStatus === "Non-Compliant"); + + const matchesSearch = + !searchQuery || + standard.standardName.toLowerCase().includes(searchQuery.toLowerCase()) || + standard.standardDescription.toLowerCase().includes(searchQuery.toLowerCase()); + + return matchesFilter && matchesSearch; + }); + + const allCount = comparisonData?.length || 0; + const compliantCount = + comparisonData?.filter((standard) => standard.complianceStatus === "Compliant").length || 0; + const nonCompliantCount = + comparisonData?.filter((standard) => standard.complianceStatus === "Non-Compliant").length || 0; + const compliancePercentage = allCount > 0 ? Math.round((compliantCount / allCount) * 100) : 0; + return ( @@ -271,17 +295,37 @@ const Page = () => { {comparisonApi.data?.find((comparison) => comparison.RowKey === currentTenant) && ( - - - - - Updated on{" "} - {new Date( + + + + } + label={`${compliancePercentage}% Compliant`} + variant="outlined" + size="small" + color={ + compliancePercentage === 100 + ? "success" + : compliancePercentage >= 50 + ? "warning" + : "error" + } + sx={{ ml: 2 }} + /> + + + + } + size="small" + label={`Updated on ${new Date( comparisonApi.data.find( (comparison) => comparison.RowKey === currentTenant ).LastRefresh - ).toLocaleString()} - + ).toLocaleString()}`} + /> )} @@ -320,7 +364,7 @@ const Page = () => { alignItems="center" sx={{ mb: 2, px: 1 }} > - + @@ -328,7 +372,7 @@ const Page = () => { - + { alignItems="center" sx={{ p: 3 }} > - + @@ -353,7 +401,7 @@ const Page = () => { - + { )} + + + + setSearchQuery(e.target.value)} + slotProps={{ + input: { + startAdornment: ( + + + + ), + endAdornment: searchQuery && ( + + + setSearchQuery("")} + aria-label="Clear search" + > + + + + + ), + }, + }} + /> + + + + + + + + {comparisonApi.isError && ( @@ -432,11 +549,21 @@ const Page = () => { )} - {comparisonData && - comparisonData.length > 0 && - comparisonData.map((standard, index) => ( + {filteredData && filteredData.length === 0 && ( + + + No standards match the selected filter criteria or search query. + + + Try selecting a different filter or modifying the search query. + + + )} + {filteredData && + filteredData.length > 0 && + filteredData.map((standard, index) => ( - + { {standard?.standardName} - + + +
@@ -570,7 +699,7 @@ const Page = () => { - + { {currentTenant} - + + +