diff --git a/src/components/CippComponents/CippApiResults.jsx b/src/components/CippComponents/CippApiResults.jsx
index 21af58b8cc39..0c5807c379ed 100644
--- a/src/components/CippComponents/CippApiResults.jsx
+++ b/src/components/CippComponents/CippApiResults.jsx
@@ -10,7 +10,7 @@ const extractAllResults = (data) => {
const getSeverity = (text) => {
if (typeof text !== "string") return "success";
- return /error|failed|exception|not found/i.test(text) ? "error" : "success";
+ return /error|failed|exception|not found|invalid_grant/i.test(text) ? "error" : "success";
};
const processResultItem = (item) => {
diff --git a/src/components/CippComponents/CippFormComponent.jsx b/src/components/CippComponents/CippFormComponent.jsx
index 28abfd910586..d44f547f94d7 100644
--- a/src/components/CippComponents/CippFormComponent.jsx
+++ b/src/components/CippComponents/CippFormComponent.jsx
@@ -24,12 +24,17 @@ import {
} from "mui-tiptap";
import StarterKit from "@tiptap/starter-kit";
import { CippDataTable } from "../CippTable/CippDataTable";
+import React from "react";
// Helper function to convert bracket notation to dot notation
const convertBracketsToDots = (name) => {
return name.replace(/\[(\d+)\]/g, ".$1"); // Replace [0] with .0
};
+const MemoizedCippAutoComplete = React.memo((props) => {
+ return ;
+});
+
export const CippFormComponent = (props) => {
const {
validators,
@@ -233,19 +238,17 @@ export const CippFormComponent = (props) => {
name={convertedName}
control={formControl.control}
rules={validators}
- render={({ field }) =>
- React.memo(
- field.onChange(value.value)}
- />
- )
- }
+ render={({ field }) => (
+ field.onChange(value.value)}
+ />
+ )}
/>
@@ -263,7 +266,7 @@ export const CippFormComponent = (props) => {
control={formControl.control}
rules={validators}
render={({ field }) => (
- {
},
{
label: "Clear Immutable ID",
- type: "GET",
+ type: "POST",
icon: ,
url: "/api/ExecClrImmId",
data: {
diff --git a/src/components/CippWizard/CippWizardCSVImport.jsx b/src/components/CippWizard/CippWizardCSVImport.jsx
index 6f665df4523b..141672f68874 100644
--- a/src/components/CippWizard/CippWizardCSVImport.jsx
+++ b/src/components/CippWizard/CippWizardCSVImport.jsx
@@ -32,6 +32,11 @@ export const CippWizardCSVImport = (props) => {
const [newTableData, setTableData] = useState([]);
const [open, setOpen] = useState(false);
+ // Register form field with validation
+ formControl.register(name, {
+ validate: (value) => Array.isArray(value) && value.length > 0,
+ });
+
const handleRemoveItem = (row) => {
if (row === undefined) return false;
const index = tableData?.findIndex((item) => item === row);
@@ -49,7 +54,9 @@ export const CippWizardCSVImport = (props) => {
};
useEffect(() => {
- formControl.setValue(name, newTableData);
+ formControl.setValue(name, newTableData, {
+ shouldValidate: true,
+ });
}, [newTableData]);
const actions = [
diff --git a/src/components/CippWizard/CippWizardOffboarding.jsx b/src/components/CippWizard/CippWizardOffboarding.jsx
index d61e9365c1e5..6c79070dcd81 100644
--- a/src/components/CippWizard/CippWizardOffboarding.jsx
+++ b/src/components/CippWizard/CippWizardOffboarding.jsx
@@ -97,6 +97,12 @@ export const CippWizardOffboarding = (props) => {
type="switch"
formControl={formControl}
/>
+
{
url: "/.auth/me",
queryKey: "authmecipp",
});
+ const [hideSidebar, setHideSidebar] = useState(false);
useEffect(() => {
if (currentRole.isSuccess && !currentRole.isFetching) {
const userRoles = currentRole.data?.clientPrincipal?.userRoles;
if (!userRoles) {
+ setMenuItems([]);
+ setHideSidebar(true);
return;
}
const filterItemsByRole = (items) => {
@@ -200,15 +203,19 @@ export const Layout = (props) => {
return (
<>
-
- {mdDown && (
-
+ {hideSidebar === false && (
+ <>
+
+ {mdDown && (
+
+ )}
+ {!mdDown && }
+ >
)}
- {!mdDown && }
diff --git a/src/pages/email/resources/management/list-rooms/edit.jsx b/src/pages/email/resources/management/list-rooms/edit.jsx
new file mode 100644
index 000000000000..91e9ecd66b11
--- /dev/null
+++ b/src/pages/email/resources/management/list-rooms/edit.jsx
@@ -0,0 +1,311 @@
+import React, { useEffect } from "react";
+import { Grid, Divider, Typography } from "@mui/material";
+import { useForm } from "react-hook-form";
+import { Layout as DashboardLayout } from "/src/layouts/index.js";
+import CippFormPage from "/src/components/CippFormPages/CippFormPage";
+import CippFormComponent from "/src/components/CippComponents/CippFormComponent";
+import { useSettings } from "/src/hooks/use-settings";
+import { useRouter } from "next/router";
+import { ApiGetCall } from "/src/api/ApiCall";
+import countryList from "/src/data/countryList.json";
+
+const EditRoomMailbox = () => {
+ const router = useRouter();
+ const { roomId } = router.query;
+ const tenantDomain = useSettings().currentTenant;
+ const formControl = useForm({
+ mode: "onChange",
+ });
+
+ const roomInfo = ApiGetCall({
+ url: `/api/ListRooms?roomId=${roomId}&tenantFilter=${tenantDomain}`,
+ queryKey: `Room-${roomId}`,
+ waiting: false,
+ });
+
+ useEffect(() => {
+ if (roomInfo.isSuccess && roomInfo.data?.[0]) {
+ const room = roomInfo.data[0];
+ formControl.reset({
+ // Core Properties
+ displayName: room.displayName,
+ hiddenFromAddressListsEnabled: room.hiddenFromAddressListsEnabled,
+
+ // Room Booking Settings
+ capacity: room.capacity,
+
+ // Location Information
+ building: room.building,
+ floor: room.floor,
+ floorLabel: room.floorLabel,
+ street: room.street,
+ city: room.city,
+ state: room.state,
+ postalCode: room.postalCode,
+ countryOrRegion: room.countryOrRegion
+ ? countryList.find((c) => c.Name === room.countryOrRegion)?.Code || ""
+ : "",
+
+ // Room Equipment
+ audioDeviceName: room.audioDeviceName,
+ videoDeviceName: room.videoDeviceName,
+ displayDeviceName: room.displayDeviceName,
+
+ // Room Features
+ isWheelChairAccessible: room.isWheelChairAccessible,
+ phone: room.phone,
+ tags: room.tags?.map(tag => ({ label: tag, value: tag })) || [],
+ });
+ }
+ }, [roomInfo.isSuccess, roomInfo.data]);
+
+ useEffect(() => {
+ if (roomId) {
+ roomInfo.refetch();
+ }
+ }, [router.query, roomId, tenantDomain]);
+
+ return (
+ ({
+ tenantID: tenantDomain,
+ roomId: roomId,
+ displayName: values.displayName?.trim(),
+ hiddenFromAddressListsEnabled: values.hiddenFromAddressListsEnabled,
+
+ // Room Booking Settings
+ capacity: values.capacity,
+
+ // Location Information
+ building: values.building?.trim(),
+ floor: values.floor,
+ floorLabel: values.floorLabel?.trim(),
+ street: values.street?.trim(),
+ city: values.city?.trim(),
+ state: values.state?.trim(),
+ postalCode: values.postalCode?.trim(),
+ countryOrRegion: values.countryOrRegion?.value || values.countryOrRegion,
+
+ // Room Equipment
+ audioDeviceName: values.audioDeviceName?.trim(),
+ videoDeviceName: values.videoDeviceName?.trim(),
+ displayDeviceName: values.displayDeviceName?.trim(),
+
+ // Room Features
+ isWheelChairAccessible: values.isWheelChairAccessible,
+ phone: values.phone?.trim(),
+ tags: values.tags?.map(tag => tag.value),
+ })}
+ >
+
+ {/* Core & Booking Settings */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Location Information */}
+
+ Location Information
+
+
+ {/* Building and Floor Info */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Address Fields */}
+
+
+
+
+
+ {/* City and Postal Code */}
+
+
+
+
+
+
+
+
+ {/* State and Country */}
+
+
+
+
+
+ ({
+ label: Name,
+ value: Code,
+ }))}
+ formControl={formControl}
+ />
+
+
+
+
+
+
+ {/* Room Equipment */}
+
+ Room Equipment
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Room Features */}
+
+ Room Features
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+EditRoomMailbox.getLayout = (page) => {page};
+
+export default EditRoomMailbox;
\ No newline at end of file
diff --git a/src/pages/email/resources/management/list-rooms/index.js b/src/pages/email/resources/management/list-rooms/index.js
index a3fe7dab1547..9fc307d60e63 100644
--- a/src/pages/email/resources/management/list-rooms/index.js
+++ b/src/pages/email/resources/management/list-rooms/index.js
@@ -2,16 +2,68 @@ import { Layout as DashboardLayout } from "/src/layouts/index.js";
import { CippTablePage } from "/src/components/CippComponents/CippTablePage.jsx";
import { Button } from "@mui/material";
import Link from "next/link";
-import { AddHomeWork } from "@mui/icons-material";
+import { AddHomeWork, Edit, Block, LockOpen } from "@mui/icons-material";
+import { TrashIcon } from "@heroicons/react/24/outline";
const Page = () => {
const pageTitle = "Rooms";
+ const actions = [
+ {
+ label: "Edit Room",
+ link: `/email/resources/management/list-rooms/edit?roomId=[id]`,
+ icon: ,
+ color: "info",
+ condition: (row) => !row.isDirSynced,
+ },
+ {
+ label: "Block Sign In",
+ type: "GET",
+ icon: ,
+ url: "/api/ExecDisableUser",
+ data: { ID: "id" },
+ confirmText: "Are you sure you want to block the sign-in for this room mailbox?",
+ multiPost: false,
+ condition: (row) => !row.accountDisabled && !row.isDirSynced,
+ },
+ {
+ label: "Unblock Sign In",
+ type: "GET",
+ icon: ,
+ url: "/api/ExecDisableUser",
+ data: { ID: "id", Enable: true },
+ confirmText: "Are you sure you want to unblock sign-in for this room mailbox?",
+ multiPost: false,
+ condition: (row) => row.accountDisabled && !row.isDirSynced,
+ },
+ {
+ label: "Delete Room",
+ type: "GET",
+ icon: ,
+ url: "/api/RemoveMailbox",
+ data: { ID: "mail" },
+ confirmText: "Are you sure you want to delete this room mailbox?",
+ multiPost: false,
+ condition: (row) => !row.isDirSynced,
+ },
+ ];
+
return (
{
title={pageTitle}
apiUrl={apiUrl}
actions={actions}
+ apiDataKey="ListRoomListsResults"
offCanvas={offCanvas}
simpleColumns={simpleColumns}
/>
diff --git a/src/pages/tools/community-repos/index.js b/src/pages/tools/community-repos/index.js
index 8fe3c2b65da1..f862ba2aa028 100644
--- a/src/pages/tools/community-repos/index.js
+++ b/src/pages/tools/community-repos/index.js
@@ -18,6 +18,7 @@ import {
Typography,
Alert,
Link,
+ Chip,
} from "@mui/material";
import { TrashIcon } from "@heroicons/react/24/outline";
import { ApiPostCall } from "/src/api/ApiCall";
@@ -37,6 +38,7 @@ const Page = () => {
const [results, setResults] = useState([]);
const [repo, setRepo] = useState("");
const [user, setUser] = useState("");
+ const [org, setOrg] = useState("");
const actions = [
{
@@ -51,6 +53,7 @@ const Page = () => {
data: { Action: "Delete", Id: "Id" },
confirmText: "Are you sure you want to delete this repo?",
icon: ,
+ multiPost: false,
queryKey: "CommunityRepos",
},
];
@@ -80,8 +83,9 @@ const Page = () => {
url: "/api/ExecGitHubAction",
data: {
Search: {
- Repository: repo ? [repo] : [],
- User: user ? [user] : [],
+ Repository: repo ? repo : "",
+ User: user ? user : "",
+ Org: org ? org : "",
SearchTerm: searchTerms,
Type: "repositories",
},
@@ -143,6 +147,7 @@ const Page = () => {
onChange={(e) => searchForm.setValue("searchType", e.target.value)}
>
} label="User" />
+ } label="Org" />
} label="Repository" />
@@ -182,6 +187,28 @@ const Page = () => {
label="Search Terms"
/>
+
+ setOrg(e.target.value)}
+ />
+
+
@@ -217,8 +244,32 @@ const Page = () => {
-
- {r.full_name}
+
+
+
+ {r.full_name}
+
+
+
{r.html_url}
diff --git a/src/pages/tools/templatelib/index.jsx b/src/pages/tools/templatelib/index.jsx
index e654b87f1a8e..fbe16255ecc8 100644
--- a/src/pages/tools/templatelib/index.jsx
+++ b/src/pages/tools/templatelib/index.jsx
@@ -76,7 +76,11 @@ const TemplateLibrary = () => {
>
-
+
@@ -89,18 +93,14 @@ const TemplateLibrary = () => {
`${option.Name} (${option.URL})`,
+ }}
formControl={formControl}
multiple={false}
/>
diff --git a/src/pages/unauthenticated.js b/src/pages/unauthenticated.js
index ce64a19fa462..6c06e2ca3a80 100644
--- a/src/pages/unauthenticated.js
+++ b/src/pages/unauthenticated.js
@@ -3,6 +3,7 @@ import Head from "next/head";
import { CippImageCard } from "../components/CippCards/CippImageCard";
import { Layout as DashboardLayout } from "../layouts/index.js";
import { ApiGetCall } from "../api/ApiCall";
+import { useState, useEffect } from "react";
const Page = () => {
const orgData = ApiGetCall({
@@ -10,9 +11,16 @@ const Page = () => {
queryKey: "me",
});
const blockedRoles = ["anonymous", "authenticated"];
- const userRoles = orgData.data?.clientPrincipal?.userRoles.filter(
- (role) => !blockedRoles.includes(role)
- );
+ const [userRoles, setUserRoles] = useState([]);
+
+ useEffect(() => {
+ if (orgData.isSuccess) {
+ const roles = orgData.data?.clientPrincipal?.userRoles.filter(
+ (role) => !blockedRoles.includes(role)
+ );
+ setUserRoles(roles ?? []);
+ }
+ }, [orgData, blockedRoles]);
return (
<>
@@ -36,14 +44,16 @@ const Page = () => {
sx={{ height: "100%" }} // Ensure the container takes full height
>
- 0 ? "Return" : "Login"}
- link={userRoles.length > 0 ? "/" : "/.auth/login/aad"}
- />
+ {orgData.isSuccess && Array.isArray(userRoles) && (
+ 0 ? "Return" : "Login"}
+ link={userRoles.length > 0 ? "/" : "/.auth/login/aad"}
+ />
+ )}
diff --git a/src/utils/get-cipp-formatting.js b/src/utils/get-cipp-formatting.js
index 2feaacacf94d..b6b7fa399571 100644
--- a/src/utils/get-cipp-formatting.js
+++ b/src/utils/get-cipp-formatting.js
@@ -429,6 +429,25 @@ export const getCippFormatting = (data, cellName, type, canReceive) => {
);
}
+ if (cellName === "Visibility") {
+ const gitHubVisibility = ["public", "private", "internal"];
+ if (gitHubVisibility.includes(data)) {
+ return isText ? (
+ data
+ ) : (
+
+ );
+ }
+ }
+
if (cellName === "AutoMapUrl") {
return isText ? data : ;
}