fixed high level changes
This commit is contained in:
parent
09bb58e50e
commit
9311f41f56
@ -19,54 +19,60 @@ import { useSelectedProject } from "../../slices/apiDataManager";
|
||||
import Loader from "../common/Loader";
|
||||
|
||||
|
||||
const InfraPlanning = () =>
|
||||
{
|
||||
const {profile: LoggedUser, refetch : fetchData} = useProfile()
|
||||
const dispatch = useDispatch()
|
||||
// const selectedProject = useSelector((store)=>store.localVariables.projectId)
|
||||
|
||||
|
||||
const InfraPlanning = () => {
|
||||
const { profile: LoggedUser, refetch: fetchData } = useProfile();
|
||||
const dispatch = useDispatch();
|
||||
const selectedProject = useSelectedProject();
|
||||
const {projectInfra, isLoading, error} = useProjectInfra( selectedProject )
|
||||
|
||||
const { projectInfra, isLoading, isError, error, isFetched } = useProjectInfra(selectedProject);
|
||||
|
||||
|
||||
const ManageInfra = useHasUserPermission( MANAGE_PROJECT_INFRA )
|
||||
const ApprovedTaskRights = useHasUserPermission(APPROVE_TASK)
|
||||
const ReportTaskRights = useHasUserPermission(ASSIGN_REPORT_TASK)
|
||||
const reloadedData = useSelector( ( store ) => store.localVariables.reload )
|
||||
const canManageInfra = useHasUserPermission(MANAGE_PROJECT_INFRA);
|
||||
const canApproveTask = useHasUserPermission(APPROVE_TASK);
|
||||
const canReportTask = useHasUserPermission(ASSIGN_REPORT_TASK);
|
||||
|
||||
|
||||
// useEffect( () =>
|
||||
// {
|
||||
// if (reloadedData)
|
||||
// {
|
||||
// refetch()
|
||||
// dispatch( refreshData( false ) )
|
||||
// }
|
||||
const reloadedData = useSelector((store) => store.localVariables.reload);
|
||||
|
||||
// },[reloadedData])
|
||||
const hasAccess = canManageInfra || canApproveTask || canReportTask;
|
||||
|
||||
if (isError) {
|
||||
return <div>{error?.response?.data?.message || error?.message}</div>;
|
||||
}
|
||||
|
||||
if (!hasAccess && !isLoading) {
|
||||
return (
|
||||
<div className="text-center">
|
||||
<i className="fa-solid fa-triangle-exclamation fs-5"></i>
|
||||
<p>Access Denied: You don't have permission to perform this action.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
return <Loader />;
|
||||
}
|
||||
|
||||
if (isFetched && (!projectInfra || projectInfra.length === 0)) {
|
||||
return (
|
||||
<div className="card text-center">
|
||||
<p className="my-3">No Result Found</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="col-md-12 col-lg-12 col-xl-12 order-0 mb-4">
|
||||
<div className="card">
|
||||
<div className="card-body" style={{ padding: "0.5rem" }}>
|
||||
{(ApprovedTaskRights || ReportTaskRights) ? (
|
||||
<div className="align-items-center">
|
||||
<div className="row ">
|
||||
{isLoading && (<Loader/> )}
|
||||
{( !isLoading && projectInfra?.length === 0 ) && ( <p>No Result Found</p> )}
|
||||
{(!isLoading && projectInfra?.length > 0) && (<InfraTable buildings={projectInfra} projectId={selectedProject}/>)}
|
||||
<div className="card">
|
||||
<div className="card-body" style={{ padding: "0.5rem" }}>
|
||||
<div className="row">
|
||||
<InfraTable buildings={projectInfra} projectId={selectedProject} />
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-center">
|
||||
<i className="fa-solid fa-triangle-exclamation fs-5"></i>
|
||||
<p>Access Denied: You don't have permission to perform this action. !</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default InfraPlanning;
|
||||
|
||||
|
@ -1,16 +1,26 @@
|
||||
|
||||
import { useSelectedProject } from "../slices/apiDataManager";
|
||||
import { useAllProjectLevelPermissions, useProfile } from "./useProfile";
|
||||
|
||||
export const useHasUserPermission = (permission) => {
|
||||
const selectedProject = useSelectedProject();
|
||||
const { profile } = useProfile();
|
||||
const { data: projectPermissions = [], isLoading, isError } = useAllProjectLevelPermissions(selectedProject);
|
||||
const {
|
||||
data: projectPermissions = [],
|
||||
isLoading,
|
||||
isError,
|
||||
} = useAllProjectLevelPermissions(selectedProject);
|
||||
|
||||
if (isLoading || !permission) return false;
|
||||
|
||||
const globalPerms = profile?.featurePermissions ?? [];
|
||||
const projectPerms = projectPermissions ?? [];
|
||||
|
||||
return globalPerms.includes(permission) || projectPerms.includes(permission);
|
||||
if (selectedProject) {
|
||||
if (projectPerms.length === 0) {
|
||||
return projectPerms.includes(permission);
|
||||
} else {
|
||||
return projectPerms.includes(permission);
|
||||
}
|
||||
} else {
|
||||
return globalPerms.includes(permission);
|
||||
}
|
||||
};
|
||||
|
26
src/hooks/useProjectAccess.js
Normal file
26
src/hooks/useProjectAccess.js
Normal file
@ -0,0 +1,26 @@
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useEffect } from "react";
|
||||
import { useHasUserPermission } from "./useHasUserPermission";
|
||||
import { useAllProjectLevelPermissions } from "./useProfile";
|
||||
import { VIEW_PROJECTS } from "../utils/constants";
|
||||
import showToast from "../services/toastService";
|
||||
|
||||
export const useProjectAccess = (projectId) => {
|
||||
const { data: projectPermissions, isLoading, isFetched } =
|
||||
useAllProjectLevelPermissions(projectId);
|
||||
|
||||
const canView = useHasUserPermission(VIEW_PROJECTS);
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
if (projectId && isFetched && !isLoading && !canView) {
|
||||
showToast("You don't have permission to view project details", "warning");
|
||||
navigate("/projects");
|
||||
}
|
||||
}, [projectId, isFetched, isLoading, canView, navigate]);
|
||||
|
||||
return {
|
||||
canView,
|
||||
loading: isLoading || !isFetched,
|
||||
};
|
||||
};
|
@ -177,6 +177,7 @@ export const useProjectInfra = (projectId) => {
|
||||
data: projectInfra,
|
||||
isLoading,
|
||||
error,
|
||||
isFetched
|
||||
} = useQuery({
|
||||
queryKey: ["ProjectInfra", projectId],
|
||||
queryFn: async () => {
|
||||
@ -190,7 +191,7 @@ export const useProjectInfra = (projectId) => {
|
||||
},
|
||||
});
|
||||
|
||||
return { projectInfra, isLoading, error };
|
||||
return { projectInfra, isLoading, error, isFetched };
|
||||
};
|
||||
|
||||
export const useProjectTasks = (workAreaId, IsExpandedArea = false) => {
|
||||
|
@ -21,6 +21,7 @@ import ContactProfile from "../../components/Directory/ContactProfile";
|
||||
import GlobalModel from "../../components/common/GlobalModel";
|
||||
import { exportToCSV } from "../../utils/exportUtils";
|
||||
import ConfirmModal from "../../components/common/ConfirmModal";
|
||||
import { useSelectedProject } from "../../slices/apiDataManager";
|
||||
|
||||
const NotesPage = lazy(() => import("./NotesPage"));
|
||||
const ContactsPage = lazy(() => import("./ContactsPage"));
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { useSelector, useDispatch } from "react-redux"; // Import useSelector
|
||||
import React, { useState, useEffect, useCallback } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import ProjectOverview from "../../components/Project/ProjectOverview";
|
||||
import AboutProject from "../../components/Project/AboutProject";
|
||||
@ -9,63 +10,43 @@ import ProjectInfra from "../../components/Project/ProjectInfra";
|
||||
import Loader from "../../components/common/Loader";
|
||||
import WorkPlan from "../../components/Project/WorkPlan";
|
||||
import Breadcrumb from "../../components/common/Breadcrumb";
|
||||
import {
|
||||
cacheData,
|
||||
clearCacheKey,
|
||||
getCachedData,
|
||||
useSelectedProject,
|
||||
} from "../../slices/apiDataManager";
|
||||
import "./ProjectDetails.css";
|
||||
import { useProjectDetails } from "../../hooks/useProjects";
|
||||
import { useSelectedProject } from "../../slices/apiDataManager";
|
||||
import { useProjectDetails, useProjectName } from "../../hooks/useProjects";
|
||||
import { ComingSoonPage } from "../Misc/ComingSoonPage";
|
||||
import eventBus from "../../services/eventBus";
|
||||
import ProjectProgressChart from "../../components/Dashboard/ProjectProgressChart";
|
||||
import { useProjectName } from "../../hooks/useProjects";
|
||||
import AttendanceOverview from "../../components/Dashboard/AttendanceChart";
|
||||
import { setProjectId } from "../../slices/localVariablesSlice";
|
||||
import ProjectDocument from "../../components/Project/ProjectDocuments";
|
||||
import ProjectDocuments from "../../components/Project/ProjectDocuments";
|
||||
import ProjectSetting from "../../components/Project/ProjectSetting";
|
||||
import DirectoryPage from "../Directory/DirectoryPage";
|
||||
import { useHasAnyPermission } from "../../hooks/useExpense";
|
||||
import { VIEW_PROJECTS } from "../../utils/constants";
|
||||
import { useNavigate, useRoutes } from "react-router-dom";
|
||||
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
||||
import { useProjectAccess } from "../../hooks/useProjectAccess"; // ✅ new
|
||||
|
||||
import "./ProjectDetails.css";
|
||||
|
||||
const ProjectDetails = () => {
|
||||
const projectId = useSelectedProject();
|
||||
const CanViewProject = useHasUserPermission(VIEW_PROJECTS);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { projectNames, fetchData } = useProjectName();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const { projectNames } = useProjectName();
|
||||
const { projects_Details, loading: projectLoading, refetch } =
|
||||
useProjectDetails(projectId);
|
||||
|
||||
const { canView, loading: permsLoading } = useProjectAccess(projectId);
|
||||
|
||||
useEffect(() => {
|
||||
if (!CanViewProject) {
|
||||
navigate("/dashboard");
|
||||
if (!projectId && projectNames.length > 0) {
|
||||
dispatch(setProjectId(projectNames[0].id));
|
||||
}
|
||||
if (projectId == null) {
|
||||
dispatch(setProjectId(projectNames[0]?.id));
|
||||
}
|
||||
}, [projectNames]);
|
||||
}, [projectId, projectNames, dispatch]);
|
||||
|
||||
const {
|
||||
projects_Details,
|
||||
loading: projectLoading,
|
||||
error: projectError,
|
||||
refetch,
|
||||
} = useProjectDetails(projectId);
|
||||
|
||||
const [activePill, setActivePill] = useState(() => {
|
||||
return localStorage.getItem("lastActiveProjectTab") || "profile";
|
||||
});
|
||||
const [activePill, setActivePill] = useState(
|
||||
localStorage.getItem("lastActiveProjectTab") || "profile"
|
||||
);
|
||||
|
||||
const handler = useCallback(
|
||||
(msg) => {
|
||||
if (
|
||||
msg.keyword === "Update_Project" &&
|
||||
projects_Details?.id === msg.response.id
|
||||
) {
|
||||
if (msg.keyword === "Update_Project" && projects_Details?.id === msg.response.id) {
|
||||
refetch();
|
||||
}
|
||||
},
|
||||
@ -79,69 +60,42 @@ const ProjectDetails = () => {
|
||||
|
||||
const handlePillClick = (pillKey) => {
|
||||
setActivePill(pillKey);
|
||||
localStorage.setItem("lastActiveProjectTab", pillKey);
|
||||
localStorage.setItem("lastActiveProjectTab", pillKey);
|
||||
};
|
||||
|
||||
const renderContent = () => {
|
||||
if (projectLoading || !projects_Details) return <Loader />;
|
||||
if (projectLoading || permsLoading || !projects_Details) {
|
||||
return <Loader />;
|
||||
}
|
||||
|
||||
const renderContent = () => {
|
||||
switch (activePill) {
|
||||
case "profile":
|
||||
return (
|
||||
<>
|
||||
<div className="row">
|
||||
<div className="col-lg-4 col-md-5 mt-2">
|
||||
<AboutProject></AboutProject>
|
||||
<ProjectOverview project={projectId} />
|
||||
</div>
|
||||
<div className="col-lg-8 col-md-7 mt-5">
|
||||
<ProjectProgressChart
|
||||
ShowAllProject="false"
|
||||
DefaultRange="1M"
|
||||
/>
|
||||
<div className="mt-5">
|
||||
{" "}
|
||||
<AttendanceOverview />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
case "teams":
|
||||
return (
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<Teams />
|
||||
<div className="col-lg-4 col-md-5 mt-2">
|
||||
<AboutProject />
|
||||
<ProjectOverview project={projectId} />
|
||||
</div>
|
||||
<div className="col-lg-8 col-md-7 mt-5">
|
||||
<ProjectProgressChart ShowAllProject="false" DefaultRange="1M" />
|
||||
<div className="mt-5">
|
||||
<AttendanceOverview />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
case "teams":
|
||||
return <Teams />;
|
||||
case "infra":
|
||||
return <ProjectInfra data={projects_Details} onDataChange={refetch} />;
|
||||
|
||||
case "workplan":
|
||||
return <WorkPlan data={projects_Details} onDataChange={refetch} />;
|
||||
|
||||
case "directory":
|
||||
return (
|
||||
<div className="row mt-2">
|
||||
<DirectoryPage IsPage={false} projectId={projects_Details.id} />
|
||||
</div>
|
||||
);
|
||||
return <DirectoryPage IsPage={false} projectId={projects_Details.id} />;
|
||||
case "documents":
|
||||
return (
|
||||
<div className="row">
|
||||
<ProjectDocuments />
|
||||
</div>
|
||||
);
|
||||
return <ProjectDocuments />;
|
||||
case "setting":
|
||||
return (
|
||||
<div className="row">
|
||||
<ProjectSetting />
|
||||
</div>
|
||||
);
|
||||
|
||||
return <ProjectSetting />;
|
||||
default:
|
||||
return <ComingSoonPage />;
|
||||
}
|
||||
@ -156,7 +110,6 @@ const ProjectDetails = () => {
|
||||
{ label: projects_Details?.name || "Project", link: null },
|
||||
]}
|
||||
/>
|
||||
|
||||
<div className="row">
|
||||
<ProjectNav onPillClick={handlePillClick} activePill={activePill} />
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user