added document permissions

This commit is contained in:
pramod mahajan 2025-09-03 11:52:49 +05:30
parent fd14328562
commit e2de5eba40
5 changed files with 81 additions and 42 deletions

View File

@ -1,7 +1,7 @@
import React, { createContext, useContext, useEffect, useState } from "react"; import React, { createContext, useContext, useEffect, useState } from "react";
import GlobalModel from "../common/GlobalModel"; import GlobalModel from "../common/GlobalModel";
import NewDocument from "./ManageDocument"; import NewDocument from "./ManageDocument";
import { DOCUMENTS_ENTITIES } from "../../utils/constants"; import { DOCUMENTS_ENTITIES, UPLOAD_DOCUMENT } from "../../utils/constants";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import DocumentsList from "./DocumentsList"; import DocumentsList from "./DocumentsList";
import DocumentFilterPanel from "./DocumentFilterPanel"; import DocumentFilterPanel from "./DocumentFilterPanel";
@ -15,6 +15,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
import ManageDocument from "./ManageDocument"; import ManageDocument from "./ManageDocument";
import ViewDocument from "./ViewDocument"; import ViewDocument from "./ViewDocument";
import DocumentViewerModal from "./DocumentViewerModal"; import DocumentViewerModal from "./DocumentViewerModal";
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
// Context // Context
export const DocumentContext = createContext(); export const DocumentContext = createContext();
@ -63,6 +64,8 @@ const Documents = ({ Document_Entity, Entity }) => {
isOpen: false, isOpen: false,
}); });
const canUploadDocument = useHasUserPermission(UPLOAD_DOCUMENT)
const { setOffcanvasContent, setShowTrigger } = useFab(); const { setOffcanvasContent, setShowTrigger } = useFab();
const methods = useForm({ const methods = useForm({
@ -154,7 +157,7 @@ const Documents = ({ Document_Entity, Entity }) => {
</span> </span>
</label> </label>
<button {canUploadDocument && (<button
type="button" type="button"
title="Add New Document" title="Add New Document"
className="p-1 bg-primary rounded-circle cursor-pointer" className="p-1 bg-primary rounded-circle cursor-pointer"
@ -166,7 +169,7 @@ const Documents = ({ Document_Entity, Entity }) => {
} }
> >
<i className="bx bx-plus fs-4 text-white"></i> <i className="bx bx-plus fs-4 text-white"></i>
</button> </button>)}
</div> </div>
</div> </div>
<DocumentsList <DocumentsList

View File

@ -3,7 +3,11 @@ import {
useActiveInActiveDocument, useActiveInActiveDocument,
useDocumentListByEntityId, useDocumentListByEntityId,
} from "../../hooks/useDocument"; } from "../../hooks/useDocument";
import { ITEMS_PER_PAGE } from "../../utils/constants"; import {
DELETE_DOCUMENT,
ITEMS_PER_PAGE,
MODIFY_DOCUMENT,
} from "../../utils/constants";
import Avatar from "../common/Avatar"; import Avatar from "../common/Avatar";
import { formatUTCToLocalTime } from "../../utils/dateUtils"; import { formatUTCToLocalTime } from "../../utils/dateUtils";
import { useDebounce } from "../../utils/appUtils"; import { useDebounce } from "../../utils/appUtils";
@ -12,6 +16,7 @@ import { getDocuementsStatus, useDocumentContext } from "./Documents";
import Pagination from "../common/Pagination"; import Pagination from "../common/Pagination";
import ConfirmModal from "../common/ConfirmModal"; import ConfirmModal from "../common/ConfirmModal";
import { isPending } from "@reduxjs/toolkit"; import { isPending } from "@reduxjs/toolkit";
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
const DocumentsList = ({ const DocumentsList = ({
Document_Entity, Document_Entity,
@ -27,7 +32,8 @@ const DocumentsList = ({
const [restoringIds, setRestoringIds] = useState([]); const [restoringIds, setRestoringIds] = useState([]);
const debouncedSearch = useDebounce(searchText, 500); const debouncedSearch = useDebounce(searchText, 500);
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
const canDeleteDocument = useHasUserPermission(DELETE_DOCUMENT);
const canModifyDocument = useHasUserPermission(MODIFY_DOCUMENT);
const { data, isError, isLoading, error, refetch, isFetching } = const { data, isError, isLoading, error, refetch, isFetching } =
useDocumentListByEntityId( useDocumentListByEntityId(
Document_Entity, Document_Entity,
@ -206,20 +212,24 @@ const DocumentsList = ({
} }
></i> ></i>
<i {canModifyDocument && (
className="bx bx-edit text-secondary cursor-pointer" <i
onClick={() => className="bx bx-edit text-secondary cursor-pointer"
setManageDoc({ document: doc.id, isOpen: true }) onClick={() =>
} setManageDoc({ document: doc.id, isOpen: true })
></i> }
></i>
)}
<i {canDeleteDocument && (
className="bx bx-trash text-danger cursor-pointer" <i
onClick={() => { className="bx bx-trash text-danger cursor-pointer"
setIsDeleteModalOpen(true); onClick={() => {
setDeletingId(doc.id); setIsDeleteModalOpen(true);
}} setDeletingId(doc.id);
></i> }}
></i>
)}
</div> </div>
) : isRestoring ? ( ) : isRestoring ? (
<div <div

View File

@ -7,14 +7,21 @@ import {
import { getDocuementsStatus, useDocumentContext } from "./Documents"; import { getDocuementsStatus, useDocumentContext } from "./Documents";
import { formatUTCToLocalTime } from "../../utils/dateUtils"; import { formatUTCToLocalTime } from "../../utils/dateUtils";
import Avatar from "../common/Avatar"; import Avatar from "../common/Avatar";
import { ITEMS_PER_PAGE } from "../../utils/constants"; import {
DOWNLOAD_DOCUMENT,
ITEMS_PER_PAGE,
VERIFY_DOCUMENT,
} from "../../utils/constants";
import Pagination from "../common/Pagination"; import Pagination from "../common/Pagination";
import VersionListSkeleton from "./VersionListSkeleton"; import VersionListSkeleton from "./VersionListSkeleton";
import DocumentDetailsSkeleton from "./DocumentDetailsSkeleton "; import DocumentDetailsSkeleton from "./DocumentDetailsSkeleton ";
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
const ViewDocument = () => { const ViewDocument = () => {
const { viewDoc, setViewDoc, setOpenDocument } = useDocumentContext(); const { viewDoc, setViewDoc, setOpenDocument } = useDocumentContext();
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
const canVerifyDocument = useHasUserPermission(VERIFY_DOCUMENT);
const canDownloadDocument = useHasUserPermission(DOWNLOAD_DOCUMENT);
const { data, isLoading, isError, error } = useDocumentDetails( const { data, isLoading, isError, error } = useDocumentDetails(
viewDoc?.document viewDoc?.document
); );
@ -40,10 +47,13 @@ const ViewDocument = () => {
}; };
if (isLoading) return <DocumentDetailsSkeleton />; if (isLoading) return <DocumentDetailsSkeleton />;
if (isError) return <div> if (isError)
<p>{error?.response?.data?.message || error?.message}</p> return (
<p className="danger-text">{error?.response?.status}</p> <div>
</div>; <p>{error?.response?.data?.message || error?.message}</p>
<p className="danger-text">{error?.response?.status}</p>
</div>
);
return ( return (
<div className="p-1"> <div className="p-1">
<p className="fw-bold fs-6">Document Details</p> <p className="fw-bold fs-6">Document Details</p>
@ -178,7 +188,10 @@ const ViewDocument = () => {
{!versionLoding && ( {!versionLoding && (
<div className="list-group mx-0"> <div className="list-group mx-0">
{versionList?.data.map((document) => ( {versionList?.data.map((document) => (
<a className="list-group-item list-group-item-action py-1 border border-bottom border-top-0 border-start-0 border-end-0" key={document.id}> <a
className="list-group-item list-group-item-action py-1 border border-bottom border-top-0 border-start-0 border-end-0"
key={document.id}
>
<div className="d-flex w-100 justify-content-between m-0"> <div className="d-flex w-100 justify-content-between m-0">
<p className="m-0"> <p className="m-0">
{document.name}{" "} {document.name}{" "}
@ -208,6 +221,7 @@ const ViewDocument = () => {
</div> </div>
<div className="d-flex text-primary align-items-center gap-2 "> <div className="d-flex text-primary align-items-center gap-2 ">
{document.isVerified == null && {document.isVerified == null &&
canVerifyDocument &&
(isPending ? ( (isPending ? (
<div <div
class="spinner-border spinner-border-sm text-primary" class="spinner-border spinner-border-sm text-primary"
@ -223,22 +237,17 @@ const ViewDocument = () => {
verify verify
</span> </span>
))} ))}
<span {canDownloadDocument && (
className="cursor-pointer text-decoration-underline" <span
onClick={() => setOpenDocument(true)} className="cursor-pointer text-decoration-underline"
> onClick={() => setOpenDocument(true)}
<small>view</small>{" "} >
<i className="bx bx-sm bx-link-external"></i> <small>view</small>{" "}
</span> <i className="bx bx-sm bx-link-external"></i>
</span>
)}
</div> </div>
</div> </div>
{/* <div className="d-flex gap-2">
{document?.updatedAt && (
<span className="small text-secondary">
Updated At : {formatUTCToLocalTime(document.updatedAt)}
</span>
)}
</div> */}
</a> </a>
))} ))}
</div> </div>

View File

@ -1,11 +1,18 @@
import React from "react"; import React from "react";
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
import { VIEW_DOCUMENT } from "../../utils/constants";
const EmployeeNav = ({ onPillClick, activePill }) => { const EmployeeNav = ({ onPillClick, activePill }) => {
const tabs = [ const canViewDocuments = useHasUserPermission(VIEW_DOCUMENT)
const tabs = [
{ key: "profile", icon: "bx bx-user", label: "Profile" }, { key: "profile", icon: "bx bx-user", label: "Profile" },
{ key: "attendance", icon: "bx bx-group", label: "Attendances" }, { key: "attendance", icon: "bx bx-group", label: "Attendances" },
{ key: "documents", icon: "bx bx-user", label: "Documents" }, canViewDocuments && {
key: "documents",
icon: "bx bx-file",
label: "Documents",
},
{ key: "activities", icon: "bx bx-grid-alt", label: "Activities" }, { key: "activities", icon: "bx bx-grid-alt", label: "Activities" },
]; ].filter(Boolean);
return ( return (
<div className="col-md-12"> <div className="col-md-12">

View File

@ -39,12 +39,14 @@ export const VIEW_TASK = "9fcc5f87-25e3-4846-90ac-67a71ab92e3c"
export const ASSIGN_REPORT_TASK = "6a32379b-8b3f-49a6-8c48-4b7ac1b55dc2" export const ASSIGN_REPORT_TASK = "6a32379b-8b3f-49a6-8c48-4b7ac1b55dc2"
// ------------------------Directory-------------------------------------
export const DIRECTORY_ADMIN = "4286a13b-bb40-4879-8c6d-18e9e393beda" export const DIRECTORY_ADMIN = "4286a13b-bb40-4879-8c6d-18e9e393beda"
export const DIRECTORY_MANAGER = "62668630-13ce-4f52-a0f0-db38af2230c5" export const DIRECTORY_MANAGER = "62668630-13ce-4f52-a0f0-db38af2230c5"
export const DIRECTORY_USER = "0f919170-92d4-4337-abd3-49b66fc871bb" export const DIRECTORY_USER = "0f919170-92d4-4337-abd3-49b66fc871bb"
// -----------------------Expense----------------------------------------
export const VIEW_SELF_EXPENSE = "385be49f-8fde-440e-bdbc-3dffeb8dd116" export const VIEW_SELF_EXPENSE = "385be49f-8fde-440e-bdbc-3dffeb8dd116"
export const VIEW_ALL_EXPNESE = "01e06444-9ca7-4df4-b900-8c3fa051b92f"; export const VIEW_ALL_EXPNESE = "01e06444-9ca7-4df4-b900-8c3fa051b92f";
@ -55,7 +57,6 @@ export const REVIEW_EXPENSE = "1f4bda08-1873-449a-bb66-3e8222bd871b";
export const APPROVE_EXPENSE = "eaafdd76-8aac-45f9-a530-315589c6deca"; export const APPROVE_EXPENSE = "eaafdd76-8aac-45f9-a530-315589c6deca";
export const PROCESS_EXPENSE = "ea5a1529-4ee8-4828-80ea-0e23c9d4dd11" export const PROCESS_EXPENSE = "ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"
export const EXPENSE_MANAGE = "ea5a1529-4ee8-4828-80ea-0e23c9d4dd11" export const EXPENSE_MANAGE = "ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"
@ -64,10 +65,19 @@ export const EXPENSE_REJECTEDBY = ["d1ee5eec-24b6-4364-8673-a8f859c60729","965ed
export const EXPENSE_DRAFT = "297e0d8f-f668-41b5-bfea-e03b354251c8" export const EXPENSE_DRAFT = "297e0d8f-f668-41b5-bfea-e03b354251c8"
// ----------------------------Tenant-------------------------
export const SUPPER_TENANT = "d032cb1a-3f30-462c-bef0-7ace73a71c0b" export const SUPPER_TENANT = "d032cb1a-3f30-462c-bef0-7ace73a71c0b"
export const MANAGE_TENANTS = "00e20637-ce8d-4417-bec4-9b31b5e65092" export const MANAGE_TENANTS = "00e20637-ce8d-4417-bec4-9b31b5e65092"
export const VIEW_TENANTS = "647145c6-2108-4c98-aab4-178602236e55" export const VIEW_TENANTS = "647145c6-2108-4c98-aab4-178602236e55"
export const ActiveTenant = "297e0d8f-f668-41b5-bfea-e03b354251c8" export const ActiveTenant = "297e0d8f-f668-41b5-bfea-e03b354251c8"
// ---------------------Documents---------------------------------
export const VIEW_DOCUMENT = "71189504-f1c8-4ca5-8db6-810497be2854";
export const UPLOAD_DOCUMENT = "3f6d1f67-6fa5-4b7c-b17b-018d4fe4aab8";
export const MODIFY_DOCUMENT = "c423fd81-6273-4b9d-bb5e-76a0fb343833";
export const DELETE_DOCUMENT = "40863a13-5a66-469d-9b48-135bc5dbf486";
export const DOWNLOAD_DOCUMENT = "404373d0-860f-490e-a575-1c086ffbce1d";
export const VERIFY_DOCUMENT = "13a1f30f-38d1-41bf-8e7a-b75189aab8e0";
// -------------------Application Role------------------------------ // -------------------Application Role------------------------------
// 1 - Expense Manage // 1 - Expense Manage