diff --git a/AdminDashboard/src/App.tsx b/AdminDashboard/src/App.tsx
index ec56a4b201c..47ed64da79c 100644
--- a/AdminDashboard/src/App.tsx
+++ b/AdminDashboard/src/App.tsx
@@ -23,6 +23,10 @@ import {
useNavigate,
useParams,
} from "react-router-dom";
+import UserView from "./Pages/Users/View/Index";
+import UserDelete from "./Pages/Users/View/Delete";
+import ProjectView from "./Pages/Projects/View/Index";
+import ProjectDelete from "./Pages/Projects/View/Delete";
const App: () => JSX.Element = () => {
Navigation.setNavigateHook(useNavigate());
@@ -61,6 +65,26 @@ const App: () => JSX.Element = () => {
element={}
/>
+ }
+ />
+
+ }
+ />
+
+ }
+ />
+
+ }
+ />
+
}
diff --git a/AdminDashboard/src/Pages/Projects/Index.tsx b/AdminDashboard/src/Pages/Projects/Index.tsx
index 72fb60ed78e..3f624600384 100644
--- a/AdminDashboard/src/Pages/Projects/Index.tsx
+++ b/AdminDashboard/src/Pages/Projects/Index.tsx
@@ -187,7 +187,7 @@ const Projects: FunctionComponent = (): ReactElement => {
isEditable={false}
isCreateable={true}
name="Projects"
- isViewable={false}
+ isViewable={true}
cardProps={{
title: "Projects",
description: "Here is a list of proejcts in OneUptime.",
diff --git a/AdminDashboard/src/Pages/Projects/View/Delete.tsx b/AdminDashboard/src/Pages/Projects/View/Delete.tsx
new file mode 100644
index 00000000000..90a116e9e2c
--- /dev/null
+++ b/AdminDashboard/src/Pages/Projects/View/Delete.tsx
@@ -0,0 +1,52 @@
+import PageMap from "../../../Utils/PageMap";
+import RouteMap, { RouteUtil } from "../../../Utils/RouteMap";
+import Route from "Common/Types/API/Route";
+import ObjectID from "Common/Types/ObjectID";
+import ModelDelete from "CommonUI/src/Components/ModelDelete/ModelDelete";
+import Navigation from "CommonUI/src/Utils/Navigation";
+import React, { FunctionComponent, ReactElement } from "react";
+import SideMenuComponent from "./SideMenu";
+import Project from "Model/Models/Project";
+import ModelPage from "CommonUI/src/Components/Page/ModelPage";
+
+const DeletePage: FunctionComponent = (): ReactElement => {
+ const modelId: ObjectID = Navigation.getLastParamAsObjectID(1);
+
+ return (
+
+ modelId={modelId}
+ modelNameField="name"
+ modelType={Project}
+ title={"Project"}
+ breadcrumbLinks={[
+ {
+ title: "Admin Dashboard",
+ to: RouteUtil.populateRouteParams(RouteMap[PageMap.HOME] as Route),
+ },
+ {
+ title: "Projects",
+ to: RouteUtil.populateRouteParams(
+ RouteMap[PageMap.PROJECTS] as Route,
+ ),
+ },
+ {
+ title: "Project",
+ to: RouteUtil.populateRouteParams(
+ RouteMap[PageMap.PROJECT_VIEW] as Route,
+ ),
+ },
+ ]}
+ sideMenu={}
+ >
+ {
+ Navigation.navigate(RouteMap[PageMap.PROJECTS] as Route);
+ }}
+ />
+
+ );
+};
+
+export default DeletePage;
diff --git a/AdminDashboard/src/Pages/Projects/View/Index.tsx b/AdminDashboard/src/Pages/Projects/View/Index.tsx
new file mode 100644
index 00000000000..665c7ddabe7
--- /dev/null
+++ b/AdminDashboard/src/Pages/Projects/View/Index.tsx
@@ -0,0 +1,90 @@
+import ObjectID from "Common/Types/ObjectID";
+import PageMap from "../../../Utils/PageMap";
+import RouteMap, { RouteUtil } from "../../../Utils/RouteMap";
+import Route from "Common/Types/API/Route";
+import Navigation from "CommonUI/src/Utils/Navigation";
+import Project from "Model/Models/Project";
+import React, { FunctionComponent, ReactElement } from "react";
+import CardModelDetail from "CommonUI/src/Components/ModelDetail/CardModelDetail";
+import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
+import FieldType from "CommonUI/src/Components/Types/FieldType";
+import ModelPage from "CommonUI/src/Components/Page/ModelPage";
+import SideMenuComponent from "./SideMenu";
+
+const Projects: FunctionComponent = (): ReactElement => {
+ const modelId: ObjectID = Navigation.getLastParamAsObjectID();
+
+ return (
+ }
+ >
+
+
+ name="Project"
+ cardProps={{
+ title: "Project",
+ description: "Project details",
+ }}
+ isEditable={true}
+ editButtonText="Edit Project"
+ formFields={[
+ {
+ field: {
+ name: true,
+ },
+ title: "Name",
+ fieldType: FormFieldSchemaType.Text,
+ required: true,
+ },
+ ]}
+ modelDetailProps={{
+ modelType: Project,
+ id: "model-detail-user",
+ fields: [
+ {
+ field: {
+ _id: true,
+ },
+ title: "Project ID",
+ fieldType: FieldType.Text,
+ placeholder: "-",
+ },
+ {
+ field: {
+ name: true,
+ },
+ title: "Name",
+ fieldType: FieldType.Text,
+ },
+ ],
+ modelId: modelId,
+ }}
+ />
+
+
+ );
+};
+
+export default Projects;
diff --git a/AdminDashboard/src/Pages/Projects/View/Layout.tsx b/AdminDashboard/src/Pages/Projects/View/Layout.tsx
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/AdminDashboard/src/Pages/Projects/View/SideMenu.tsx b/AdminDashboard/src/Pages/Projects/View/SideMenu.tsx
new file mode 100644
index 00000000000..a40bb37ece1
--- /dev/null
+++ b/AdminDashboard/src/Pages/Projects/View/SideMenu.tsx
@@ -0,0 +1,53 @@
+import PageMap from "../../../Utils/PageMap";
+import RouteMap, { RouteUtil } from "../../../Utils/RouteMap";
+import Route from "Common/Types/API/Route";
+import IconProp from "Common/Types/Icon/IconProp";
+import ObjectID from "Common/Types/ObjectID";
+import SideMenu from "CommonUI/src/Components/SideMenu/SideMenu";
+import SideMenuItem from "CommonUI/src/Components/SideMenu/SideMenuItem";
+import SideMenuSection from "CommonUI/src/Components/SideMenu/SideMenuSection";
+import React, { FunctionComponent, ReactElement } from "react";
+
+export interface SideMenuProps {
+ modelId: ObjectID;
+}
+
+const SideMenuComponent: FunctionComponent = (
+ props: SideMenuProps,
+): ReactElement => {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default SideMenuComponent;
diff --git a/AdminDashboard/src/Pages/Users/Index.tsx b/AdminDashboard/src/Pages/Users/Index.tsx
index f71d7f03316..f6b8f670835 100644
--- a/AdminDashboard/src/Pages/Users/Index.tsx
+++ b/AdminDashboard/src/Pages/Users/Index.tsx
@@ -1,31 +1,15 @@
import PageMap from "../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../Utils/RouteMap";
import Route from "Common/Types/API/Route";
-import { ErrorFunction } from "Common/Types/FunctionTypes";
-import { ButtonStyleType } from "CommonUI/src/Components/Button/Button";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
-import ConfirmModal from "CommonUI/src/Components/Modal/ConfirmModal";
import ModelTable from "CommonUI/src/Components/ModelTable/ModelTable";
import Page from "CommonUI/src/Components/Page/Page";
import FieldType from "CommonUI/src/Components/Types/FieldType";
-import API from "CommonUI/src/Utils/API/API";
-import ModelAPI from "CommonUI/src/Utils/ModelAPI/ModelAPI";
import Navigation from "CommonUI/src/Utils/Navigation";
import User from "Model/Models/User";
-import React, { FunctionComponent, ReactElement, useState } from "react";
+import React, { FunctionComponent, ReactElement } from "react";
const Users: FunctionComponent = (): ReactElement => {
- const [showConfirmVerifyEmailModal, setShowConfirmVerifyEmailModal] =
- useState(false);
- const [selectedUser, setSelectedUser] = useState(null);
- const [error, setError] = useState(null);
-
- const [isConfimModalLoading, setIsConfirmModalLoading] =
- useState(false);
-
- const [refreshItemsTrigger, setRefreshItemsTrigger] =
- useState(false);
-
return (
{
isDeleteable={false}
isEditable={false}
showViewIdButton={true}
- refreshToggle={refreshItemsTrigger}
isCreateable={true}
name="Users"
- isViewable={false}
+ isViewable={true}
cardProps={{
title: "Users",
description: "Here is a list of users in OneUptime.",
}}
- actionButtons={[
- {
- title: "Verify Email",
- buttonStyleType: ButtonStyleType.NORMAL,
- isVisible: (item: User) => {
- return !item.isEmailVerified;
- },
- onClick: async (
- item: User,
- onCompleteAction: VoidFunction,
- onError: ErrorFunction,
- ) => {
- try {
- setSelectedUser(item);
- setShowConfirmVerifyEmailModal(true);
-
- onCompleteAction();
- } catch (err) {
- onCompleteAction();
- onError(err as Error);
- }
- },
- },
- ]}
noItemsMessage={"No users found."}
formFields={[
{
@@ -164,53 +123,6 @@ const Users: FunctionComponent = (): ReactElement => {
},
]}
/>
-
- {error ? (
- {
- setError(null);
- }}
- submitButtonType={ButtonStyleType.NORMAL}
- />
- ) : (
- <>>
- )}
-
- {showConfirmVerifyEmailModal && selectedUser ? (
- {
- setShowConfirmVerifyEmailModal(false);
- setSelectedUser(null);
- }}
- onSubmit={async () => {
- try {
- setIsConfirmModalLoading(true);
- await ModelAPI.updateById({
- modelType: User,
- id: selectedUser.id!,
- data: {
- isEmailVerified: true,
- },
- });
- } catch (err) {
- setError(API.getFriendlyMessage(err as Error));
- }
-
- setRefreshItemsTrigger(!refreshItemsTrigger);
- setIsConfirmModalLoading(false);
- setShowConfirmVerifyEmailModal(false);
- }}
- />
- ) : (
- <>>
- )}
);
};
diff --git a/AdminDashboard/src/Pages/Users/View/Delete.tsx b/AdminDashboard/src/Pages/Users/View/Delete.tsx
new file mode 100644
index 00000000000..3996a6562f6
--- /dev/null
+++ b/AdminDashboard/src/Pages/Users/View/Delete.tsx
@@ -0,0 +1,50 @@
+import PageMap from "../../../Utils/PageMap";
+import RouteMap, { RouteUtil } from "../../../Utils/RouteMap";
+import Route from "Common/Types/API/Route";
+import ObjectID from "Common/Types/ObjectID";
+import ModelDelete from "CommonUI/src/Components/ModelDelete/ModelDelete";
+import Navigation from "CommonUI/src/Utils/Navigation";
+import React, { FunctionComponent, ReactElement } from "react";
+import SideMenuComponent from "./SideMenu";
+import User from "Model/Models/User";
+import ModelPage from "CommonUI/src/Components/Page/ModelPage";
+
+const DeletePage: FunctionComponent = (): ReactElement => {
+ const modelId: ObjectID = Navigation.getLastParamAsObjectID(1);
+
+ return (
+ }
+ >
+ {
+ Navigation.navigate(RouteMap[PageMap.USERS] as Route);
+ }}
+ />
+
+ );
+};
+
+export default DeletePage;
diff --git a/AdminDashboard/src/Pages/Users/View/Index.tsx b/AdminDashboard/src/Pages/Users/View/Index.tsx
new file mode 100644
index 00000000000..d1b900589be
--- /dev/null
+++ b/AdminDashboard/src/Pages/Users/View/Index.tsx
@@ -0,0 +1,136 @@
+import ObjectID from "Common/Types/ObjectID";
+import PageMap from "../../../Utils/PageMap";
+import RouteMap, { RouteUtil } from "../../../Utils/RouteMap";
+import Route from "Common/Types/API/Route";
+import Navigation from "CommonUI/src/Utils/Navigation";
+import User from "Model/Models/User";
+import React, { FunctionComponent, ReactElement } from "react";
+import CardModelDetail from "CommonUI/src/Components/ModelDetail/CardModelDetail";
+import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
+import FieldType from "CommonUI/src/Components/Types/FieldType";
+import ModelPage from "CommonUI/src/Components/Page/ModelPage";
+import SideMenuComponent from "./SideMenu";
+
+const Users: FunctionComponent = (): ReactElement => {
+ const modelId: ObjectID = Navigation.getLastParamAsObjectID();
+
+ return (
+ }
+ >
+
+
+ name="User"
+ cardProps={{
+ title: "User",
+ description: "User details",
+ }}
+ isEditable={true}
+ editButtonText="Edit User"
+ formFields={[
+ {
+ field: {
+ name: true,
+ },
+ title: "Name",
+ fieldType: FormFieldSchemaType.Text,
+ required: true,
+ },
+ {
+ field: {
+ email: true,
+ },
+ title: "Email",
+ fieldType: FormFieldSchemaType.Email,
+ required: true,
+ },
+ {
+ field: {
+ isEmailVerified: true,
+ },
+ title: "Email Verified",
+ fieldType: FormFieldSchemaType.Toggle,
+ required: false,
+ },
+ {
+ field: {
+ enableTwoFactorAuth: true,
+ },
+ title: "Two Factor Auth Enabled",
+ fieldType: FormFieldSchemaType.Toggle,
+ required: false,
+ },
+ ]}
+ modelDetailProps={{
+ modelType: User,
+ id: "model-detail-user",
+ fields: [
+ {
+ field: {
+ _id: true,
+ },
+ title: "User ID",
+ fieldType: FieldType.Text,
+ placeholder: "-",
+ },
+ {
+ field: {
+ name: true,
+ },
+ title: "Name",
+ fieldType: FieldType.Text,
+ },
+ {
+ field: {
+ email: true,
+ },
+ title: "Email",
+ fieldType: FieldType.Email,
+ placeholder: "-",
+ },
+ {
+ field: {
+ isEmailVerified: true,
+ },
+ title: "Email Verified",
+ fieldType: FieldType.Boolean,
+ placeholder: "No",
+ },
+ {
+ field: {
+ enableTwoFactorAuth: true,
+ },
+ title: "Two Factor Auth Enabled",
+ fieldType: FieldType.Boolean,
+ placeholder: "No",
+ },
+ ],
+ modelId: modelId,
+ }}
+ />
+
+
+ );
+};
+
+export default Users;
diff --git a/AdminDashboard/src/Pages/Users/View/SideMenu.tsx b/AdminDashboard/src/Pages/Users/View/SideMenu.tsx
new file mode 100644
index 00000000000..cb16a22bfda
--- /dev/null
+++ b/AdminDashboard/src/Pages/Users/View/SideMenu.tsx
@@ -0,0 +1,53 @@
+import PageMap from "../../../Utils/PageMap";
+import RouteMap, { RouteUtil } from "../../../Utils/RouteMap";
+import Route from "Common/Types/API/Route";
+import IconProp from "Common/Types/Icon/IconProp";
+import ObjectID from "Common/Types/ObjectID";
+import SideMenu from "CommonUI/src/Components/SideMenu/SideMenu";
+import SideMenuItem from "CommonUI/src/Components/SideMenu/SideMenuItem";
+import SideMenuSection from "CommonUI/src/Components/SideMenu/SideMenuSection";
+import React, { FunctionComponent, ReactElement } from "react";
+
+export interface SideMenuProps {
+ modelId: ObjectID;
+}
+
+const SideMenuComponent: FunctionComponent = (
+ props: SideMenuProps,
+): ReactElement => {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default SideMenuComponent;
diff --git a/AdminDashboard/src/Utils/PageMap.ts b/AdminDashboard/src/Utils/PageMap.ts
index cc7e7dfa175..7bd76d9fc68 100644
--- a/AdminDashboard/src/Utils/PageMap.ts
+++ b/AdminDashboard/src/Utils/PageMap.ts
@@ -3,8 +3,14 @@ enum PageMap {
HOME = "HOME",
LOGOUT = "LOGOUT",
SETTINGS = "SETTINGS",
+
USERS = "USERS",
+ USER_VIEW = "USER_VIEW",
+ USER_DELETE = "USER_DELETE",
+
PROJECTS = "PROJECTS",
+ PROJECT_VIEW = "PROJECT_VIEW",
+ PROJECT_DELETE = "PROJECT_DELETE",
SETTINGS_HOST = "SETTINGS_HOST",
SETTINGS_SMTP = "SETTINGS_SMTP",
diff --git a/AdminDashboard/src/Utils/RouteMap.ts b/AdminDashboard/src/Utils/RouteMap.ts
index dd8978321ae..ae6bf8979a5 100644
--- a/AdminDashboard/src/Utils/RouteMap.ts
+++ b/AdminDashboard/src/Utils/RouteMap.ts
@@ -9,8 +9,19 @@ const RouteMap: Dictionary = {
[PageMap.HOME]: new Route(`/admin`),
[PageMap.LOGOUT]: new Route(`/admin/logout`),
[PageMap.SETTINGS]: new Route(`/admin/settings/host`),
+
[PageMap.PROJECTS]: new Route(`/admin/projects`),
+ [PageMap.PROJECT_VIEW]: new Route(`/admin/projects/${RouteParams.ModelID}`),
+ [PageMap.PROJECT_DELETE]: new Route(
+ `/admin/projects/${RouteParams.ModelID}/delete`,
+ ),
+
[PageMap.USERS]: new Route(`/admin/users`),
+ [PageMap.USER_VIEW]: new Route(`/admin/users/${RouteParams.ModelID}`),
+ [PageMap.USER_DELETE]: new Route(
+ `/admin/users/${RouteParams.ModelID}/delete`,
+ ),
+
[PageMap.SETTINGS_HOST]: new Route(`/admin/settings/host`),
[PageMap.SETTINGS_SMTP]: new Route(`/admin/settings/smtp`),
[PageMap.SETTINGS_CALL_AND_SMS]: new Route(`/admin/settings/call-and-sms`),