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`),