Implemented rbac
This commit is contained in:
@@ -39,6 +39,7 @@ import { HelpTooltip } from '../components/ui/HelpTooltip';
|
||||
import { ExportButton } from '../components/ui/ExportButton';
|
||||
import { ExportColumn } from '../utils/exportUtils';
|
||||
import { useTableSort, SortableTh } from '../utils/tableSort';
|
||||
import { useRbac } from '../auth/rbac';
|
||||
import { ApprovalStatusBadge, PriorityBadge } from '../components/ui/StatusBadge';
|
||||
import { Issue, ChangeRequest, ApprovalStatus, ActivityStatus, Priority } from '../types';
|
||||
import {
|
||||
@@ -109,6 +110,7 @@ type ResolveChangeFormValues = z.infer<typeof resolveChangeSchema>;
|
||||
export const ChangeManagementPage: React.FC = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { success, error: toastError } = useToast();
|
||||
const { canAdd, canApprove, canExport } = useRbac();
|
||||
|
||||
const [selectedProjectId, setSelectedProjectId] = useState<string>('all');
|
||||
const [activeTab, setActiveTab] = useState<'issues' | 'changes'>('issues');
|
||||
@@ -722,23 +724,26 @@ export const ChangeManagementPage: React.FC = () => {
|
||||
</button>
|
||||
|
||||
<ExportButton
|
||||
claim="change_management"
|
||||
data={sortedIssues}
|
||||
columns={issueExportCols}
|
||||
filename={`project_issues_${new Date().toISOString().split('T')[0]}`}
|
||||
title="Project Issues Register"
|
||||
/>
|
||||
|
||||
<button
|
||||
onClick={() => {
|
||||
setEditingIssue(null);
|
||||
issueForm.reset({ title: '', description: '', priority: Priority.Medium, assignedTo: '' });
|
||||
setIsIssueModalOpen(true);
|
||||
}}
|
||||
className="flex items-center gap-1.5 px-3.5 py-1.5 rounded-xl text-xs font-semibold bg-gradient-to-r from-amber-600 to-orange-600 text-white hover:from-amber-500 hover:to-orange-500 shadow-md shadow-amber-600/25 transition cursor-pointer"
|
||||
>
|
||||
<Plus className="w-3.5 h-3.5" />
|
||||
<span>Log Issue</span>
|
||||
</button>
|
||||
{canAdd('change_management') && (
|
||||
<button
|
||||
onClick={() => {
|
||||
setEditingIssue(null);
|
||||
issueForm.reset({ title: '', description: '', priority: Priority.Medium, assignedTo: '' });
|
||||
setIsIssueModalOpen(true);
|
||||
}}
|
||||
className="flex items-center gap-1.5 px-3.5 py-1.5 rounded-xl text-xs font-semibold bg-gradient-to-r from-amber-600 to-orange-600 text-white hover:from-amber-500 hover:to-orange-500 shadow-md shadow-amber-600/25 transition cursor-pointer"
|
||||
>
|
||||
<Plus className="w-3.5 h-3.5" />
|
||||
<span>Log Issue</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -920,28 +925,31 @@ export const ChangeManagementPage: React.FC = () => {
|
||||
</button>
|
||||
|
||||
<ExportButton
|
||||
claim="change_management"
|
||||
data={sortedChanges}
|
||||
columns={changeExportCols}
|
||||
filename={`change_requests_${new Date().toISOString().split('T')[0]}`}
|
||||
title="Change Requests Register"
|
||||
/>
|
||||
|
||||
<button
|
||||
onClick={() => {
|
||||
setEditingChange(null);
|
||||
changeForm.reset({
|
||||
title: '',
|
||||
justification: '',
|
||||
revisedBudget: 0,
|
||||
revisionDate: new Date().toISOString().split('T')[0],
|
||||
});
|
||||
setIsChangeModalOpen(true);
|
||||
}}
|
||||
className="flex items-center gap-1.5 px-3.5 py-1.5 rounded-xl text-xs font-semibold bg-slate-800 text-white hover:bg-slate-700 border border-slate-700 shadow-md transition cursor-pointer"
|
||||
>
|
||||
<GitPullRequest className="w-3.5 h-3.5 text-blue-400" />
|
||||
<span>Request Change</span>
|
||||
</button>
|
||||
{canAdd('change_management') && (
|
||||
<button
|
||||
onClick={() => {
|
||||
setEditingChange(null);
|
||||
changeForm.reset({
|
||||
title: '',
|
||||
justification: '',
|
||||
revisedBudget: 0,
|
||||
revisionDate: new Date().toISOString().split('T')[0],
|
||||
});
|
||||
setIsChangeModalOpen(true);
|
||||
}}
|
||||
className="flex items-center gap-1.5 px-3.5 py-1.5 rounded-xl text-xs font-semibold bg-slate-800 text-white hover:bg-slate-700 border border-slate-700 shadow-md transition cursor-pointer"
|
||||
>
|
||||
<GitPullRequest className="w-3.5 h-3.5 text-blue-400" />
|
||||
<span>Request Change</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1014,18 +1022,22 @@ export const ChangeManagementPage: React.FC = () => {
|
||||
</span>
|
||||
) : (
|
||||
<>
|
||||
<button
|
||||
onClick={() => openResolveChange(cr, ApprovalStatus.Approved)}
|
||||
className="px-2.5 py-1 text-xs font-semibold text-emerald-300 bg-emerald-950/50 hover:bg-emerald-900/60 border border-emerald-700/50 rounded-lg transition cursor-pointer flex items-center gap-1"
|
||||
>
|
||||
<Check className="w-3 h-3" /> Approve
|
||||
</button>
|
||||
<button
|
||||
onClick={() => openResolveChange(cr, ApprovalStatus.Rejected)}
|
||||
className="px-2.5 py-1 text-xs font-semibold text-rose-300 bg-rose-950/50 hover:bg-rose-900/60 border border-rose-700/50 rounded-lg transition cursor-pointer flex items-center gap-1"
|
||||
>
|
||||
<XCircle className="w-3 h-3" /> Reject
|
||||
</button>
|
||||
{canApprove('change_management') && (
|
||||
<button
|
||||
onClick={() => openResolveChange(cr, ApprovalStatus.Approved)}
|
||||
className="px-2.5 py-1 text-xs font-semibold text-emerald-300 bg-emerald-950/50 hover:bg-emerald-900/60 border border-emerald-700/50 rounded-lg transition cursor-pointer flex items-center gap-1"
|
||||
>
|
||||
<Check className="w-3 h-3" /> Approve
|
||||
</button>
|
||||
)}
|
||||
{canAdd('change_management') && (
|
||||
<button
|
||||
onClick={() => openResolveChange(cr, ApprovalStatus.Rejected)}
|
||||
className="px-2.5 py-1 text-xs font-semibold text-rose-300 bg-rose-950/50 hover:bg-rose-900/60 border border-rose-700/50 rounded-lg transition cursor-pointer flex items-center gap-1"
|
||||
>
|
||||
<XCircle className="w-3 h-3" /> Reject
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
@@ -1510,7 +1522,9 @@ export const ChangeManagementPage: React.FC = () => {
|
||||
>
|
||||
<option value={ApprovalStatus.Pending}>Pending Review</option>
|
||||
<option value={ApprovalStatus.Review}>Under Active Review</option>
|
||||
<option value={ApprovalStatus.Approved}>Approved & Enacted</option>
|
||||
<option value={ApprovalStatus.Approved} disabled={!canApprove('change_management')}>
|
||||
Approved & Enacted {!canApprove('change_management') ? '(Requires Update Permission)' : ''}
|
||||
</option>
|
||||
<option value={ApprovalStatus.Rejected}>Rejected</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user