This commit is contained in:
Flatlogic Bot 2026-05-11 12:57:58 +00:00
parent 97439eda85
commit b073dd491e
38 changed files with 540 additions and 659 deletions

View File

@ -43,7 +43,7 @@ export const loadColumns = async (
{
field: 'name',
headerName: 'ToolName',
headerName: 'Tool Name',
flex: 1,
minWidth: 120,
filterable: false,
@ -58,7 +58,7 @@ export const loadColumns = async (
{
field: 'tool_type',
headerName: 'ToolType',
headerName: 'Tool Type',
flex: 1,
minWidth: 120,
filterable: false,
@ -95,7 +95,7 @@ export const loadColumns = async (
{
field: 'deployment_model',
headerName: 'DeploymentModel',
headerName: 'Deployment Model',
flex: 1,
minWidth: 120,
filterable: false,
@ -110,7 +110,7 @@ export const loadColumns = async (
{
field: 'approval_status',
headerName: 'ApprovalStatus',
headerName: 'Approval Status',
flex: 1,
minWidth: 120,
filterable: false,
@ -125,7 +125,7 @@ export const loadColumns = async (
{
field: 'supports_sso',
headerName: 'SupportsSSO',
headerName: 'Supports SSO',
flex: 1,
minWidth: 120,
filterable: false,
@ -141,7 +141,7 @@ export const loadColumns = async (
{
field: 'supports_audit_logs',
headerName: 'SupportsAuditLogs',
headerName: 'Supports Audit Logs',
flex: 1,
minWidth: 120,
filterable: false,
@ -157,7 +157,7 @@ export const loadColumns = async (
{
field: 'soc2_status',
headerName: 'SOC2Status',
headerName: 'SOC2 Status',
flex: 1,
minWidth: 120,
filterable: false,
@ -172,7 +172,7 @@ export const loadColumns = async (
{
field: 'data_retention_policy',
headerName: 'DataRetentionPolicy',
headerName: 'Data Retention Policy',
flex: 1,
minWidth: 120,
filterable: false,
@ -187,7 +187,7 @@ export const loadColumns = async (
{
field: 'training_on_client_data_policy',
headerName: 'TrainingOnClientDataPolicy',
headerName: 'Training On Client Data Policy',
flex: 1,
minWidth: 120,
filterable: false,
@ -202,7 +202,7 @@ export const loadColumns = async (
{
field: 'data_residency',
headerName: 'DataResidency',
headerName: 'Data Residency',
flex: 1,
minWidth: 120,
filterable: false,
@ -217,7 +217,7 @@ export const loadColumns = async (
{
field: 'deletion_policy',
headerName: 'DeletionPolicy',
headerName: 'Deletion Policy',
flex: 1,
minWidth: 120,
filterable: false,
@ -232,7 +232,7 @@ export const loadColumns = async (
{
field: 'security_posture_summary',
headerName: 'SecurityPostureSummary',
headerName: 'Security Posture Summary',
flex: 1,
minWidth: 120,
filterable: false,
@ -247,7 +247,7 @@ export const loadColumns = async (
{
field: 'security_documents',
headerName: 'SecurityDocuments',
headerName: 'Security Documents',
flex: 1,
minWidth: 120,
filterable: false,
@ -273,7 +273,7 @@ export const loadColumns = async (
{
field: 'monthly_cost',
headerName: 'MonthlyCost',
headerName: 'Monthly Cost',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -43,7 +43,7 @@ export const loadColumns = async (
{
field: 'use_case',
headerName: 'AIUseCase',
headerName: 'AI Use Case',
flex: 1,
minWidth: 120,
filterable: false,
@ -65,7 +65,7 @@ export const loadColumns = async (
{
field: 'step_type',
headerName: 'StepType',
headerName: 'Step Type',
flex: 1,
minWidth: 120,
filterable: false,
@ -80,7 +80,7 @@ export const loadColumns = async (
{
field: 'assigned_reviewer',
headerName: 'AssignedReviewer',
headerName: 'Assigned Reviewer',
flex: 1,
minWidth: 120,
filterable: false,
@ -132,7 +132,7 @@ export const loadColumns = async (
{
field: 'assigned_at',
headerName: 'AssignedAt',
headerName: 'Assigned At',
flex: 1,
minWidth: 120,
filterable: false,
@ -150,7 +150,7 @@ export const loadColumns = async (
{
field: 'decided_at',
headerName: 'DecidedAt',
headerName: 'Decided At',
flex: 1,
minWidth: 120,
filterable: false,
@ -168,7 +168,7 @@ export const loadColumns = async (
{
field: 'step_order',
headerName: 'StepOrder',
headerName: 'Step Order',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -43,7 +43,7 @@ export const loadColumns = async (
{
field: 'label',
headerName: 'ClassificationLabel',
headerName: 'Classification Label',
flex: 1,
minWidth: 120,
filterable: false,
@ -58,7 +58,7 @@ export const loadColumns = async (
{
field: 'level',
headerName: 'SensitivityLevel',
headerName: 'Sensitivity Level',
flex: 1,
minWidth: 120,
filterable: false,
@ -88,7 +88,7 @@ export const loadColumns = async (
{
field: 'risk_notes',
headerName: 'RiskNotes',
headerName: 'Risk Notes',
flex: 1,
minWidth: 120,
filterable: false,
@ -103,7 +103,7 @@ export const loadColumns = async (
{
field: 'required_human_review_level',
headerName: 'RequiredHumanReviewLevel',
headerName: 'Required Human Review Level',
flex: 1,
minWidth: 120,
filterable: false,
@ -118,7 +118,7 @@ export const loadColumns = async (
{
field: 'requires_client_notice',
headerName: 'RequiresClientNotice',
headerName: 'Requires Client Notice',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -43,7 +43,7 @@ export const loadColumns = async (
{
field: 'name',
headerName: 'ChecklistName',
headerName: 'Checklist Name',
flex: 1,
minWidth: 120,
filterable: false,
@ -88,7 +88,7 @@ export const loadColumns = async (
{
field: 'practice_group',
headerName: 'PracticeGroupScope',
headerName: 'Practice Group Scope',
flex: 1,
minWidth: 120,
filterable: false,
@ -110,7 +110,7 @@ export const loadColumns = async (
{
field: 'data_classification',
headerName: 'DataClassificationScope',
headerName: 'Data Classification Scope',
flex: 1,
minWidth: 120,
filterable: false,
@ -132,7 +132,7 @@ export const loadColumns = async (
{
field: 'required_reviewer_role',
headerName: 'RequiredReviewerRole',
headerName: 'Required Reviewer Role',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -43,7 +43,7 @@ export const loadColumns = async (
{
field: 'name',
headerName: 'IntegrationName',
headerName: 'Integration Name',
flex: 1,
minWidth: 120,
filterable: false,
@ -104,7 +104,7 @@ export const loadColumns = async (
{
field: 'configuration_notes',
headerName: 'ConfigurationNotes',
headerName: 'Configuration Notes',
flex: 1,
minWidth: 120,
filterable: false,
@ -119,7 +119,7 @@ export const loadColumns = async (
{
field: 'configuration_files',
headerName: 'ConfigurationFiles',
headerName: 'Configuration Files',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -1,135 +1,3 @@
import React from 'react';
import ImageField from '../ImageField';
import ListActionsPopover from '../ListActionsPopover';
import { useAppSelector } from '../../stores/hooks';
import dataFormatter from '../../helpers/dataFormatter';
import { Pagination } from '../Pagination';
import {saveFile} from "../../helpers/fileSaver";
import LoadingSpinner from "../LoadingSpinner";
import Link from 'next/link';
import ListMatter_types from './ListMatter_types';
import {hasPermission} from "../../helpers/userPermissions";
type Props = {
matter_types: any[];
loading: boolean;
onDelete: (id: string) => void;
currentPage: number;
numPages: number;
onPageChange: (page: number) => void;
};
const CardMatter_types = ({
matter_types,
loading,
onDelete,
currentPage,
numPages,
onPageChange,
}: Props) => {
const asideScrollbarsStyle = useAppSelector(
(state) => state.style.asideScrollbarsStyle,
);
const bgColor = useAppSelector((state) => state.style.cardsColor);
const darkMode = useAppSelector((state) => state.style.darkMode);
const corners = useAppSelector((state) => state.style.corners);
const focusRing = useAppSelector((state) => state.style.focusRingColor);
const currentUser = useAppSelector((state) => state.auth.currentUser);
const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_MATTER_TYPES')
return (
<div className={'p-4'}>
{loading && <LoadingSpinner />}
<ul
role='list'
className='grid grid-cols-1 gap-x-6 gap-y-8 lg:grid-cols-3 2xl:grid-cols-4 xl:gap-x-8'
>
{!loading && matter_types.map((item, index) => (
<li
key={item.id}
className={`overflow-hidden ${corners !== 'rounded-full'? corners : 'rounded-3xl'} border ${focusRing} border-gray-200 dark:border-dark-700 ${
darkMode ? 'aside-scrollbars-[slate]' : asideScrollbarsStyle
}`}
>
<div className={`flex items-center ${bgColor} p-6 gap-x-4 border-b border-gray-900/5 bg-gray-50 dark:bg-dark-800 relative`}>
<Link href={`/matter_types/matter_types-view/?id=${item.id}`} className='text-lg font-bold leading-6 line-clamp-1'>
{item.name}
</Link>
<div className='ml-auto '>
<ListActionsPopover
onDelete={onDelete}
itemId={item.id}
pathEdit={`/matter_types/matter_types-edit/?id=${item.id}`}
pathView={`/matter_types/matter_types-view/?id=${item.id}`}
hasUpdatePermission={hasUpdatePermission}
/>
</div>
</div>
<dl className='divide-y divide-stone-300 dark:divide-dark-700 px-6 py-4 text-sm leading-6 h-64 overflow-y-auto'>
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>MatterType</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.name }
</div>
</dd>
</div>
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>Description</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.description }
</div>
</dd>
</div>
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>Active</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ dataFormatter.booleanFormatter(item.is_active) }
</div>
</dd>
</div>
</dl>
</li>
))}
{!loading && matter_types.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p>
</div>
)}
</ul>
<div className={'flex items-center justify-center my-6'}>
<Pagination
currentPage={currentPage}
numPages={numPages}
setCurrentPage={onPageChange}
/>
</div>
</div>
);
};
export default CardMatter_types;
export default ListMatter_types;

View File

@ -1,16 +1,10 @@
import React from 'react';
import CardBox from '../CardBox';
import ImageField from '../ImageField';
import dataFormatter from '../../helpers/dataFormatter';
import {saveFile} from "../../helpers/fileSaver";
import ListActionsPopover from "../ListActionsPopover";
import {useAppSelector} from "../../stores/hooks";
import {Pagination} from "../Pagination";
import LoadingSpinner from "../LoadingSpinner";
import Link from 'next/link';
import {hasPermission} from "../../helpers/userPermissions";
import ListActionsPopover from "../ListActionsPopover";
import { useAppSelector } from "../../stores/hooks";
import { Pagination } from "../Pagination";
import LoadingSpinner from "../LoadingSpinner";
import { hasPermission } from "../../helpers/userPermissions";
type Props = {
matter_types: any[];
@ -21,84 +15,111 @@ type Props = {
onPageChange: (page: number) => void;
};
const ListMatter_types = ({ matter_types, loading, onDelete, currentPage, numPages, onPageChange }: Props) => {
const currentUser = useAppSelector((state) => state.auth.currentUser);
const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_MATTER_TYPES')
const corners = useAppSelector((state) => state.style.corners);
const bgColor = useAppSelector((state) => state.style.cardsColor);
const getInitials = (name?: string) => {
if (!name) {
return 'MT';
}
return name
.split(' ')
.map((part) => part[0])
.join('')
.slice(0, 2)
.toUpperCase();
};
const ListMatter_types = ({ matter_types, loading, onDelete, currentPage, numPages, onPageChange }: Props) => {
const currentUser = useAppSelector((state) => state.auth.currentUser);
const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_MATTER_TYPES');
return (
<>
<div className='relative overflow-x-auto p-4 space-y-4'>
{loading && <LoadingSpinner />}
<div className='grid grid-cols-[repeat(auto-fit,minmax(340px,1fr))] gap-4 p-4'>
{loading && (
<div className='col-span-full rounded-xl border border-[#DDD5C7] bg-white p-10'>
<LoadingSpinner />
</div>
)}
{!loading && matter_types.map((item) => (
<div key={item.id}>
<CardBox hasTable isList className={'rounded shadow-none'}>
<div className={`flex rounded dark:bg-dark-900 border border-stone-300 items-center overflow-hidden`}>
<Link
href={`/matter_types/matter_types-view/?id=${item.id}`}
className={
'flex-1 px-4 py-6 h-24 flex divide-x-2 divide-stone-300 items-center overflow-hidden`}> dark:divide-dark-700 overflow-x-auto'
}
>
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>MatterType</p>
<p className={'line-clamp-2'}>{ item.name }</p>
<div
key={item.id}
className='min-w-0 overflow-hidden rounded-xl border border-[#DDD5C7] bg-white shadow-sm shadow-[#83755E]/10 transition hover:border-[#D8B75E]/70 hover:shadow-md'
>
<div className='flex items-start justify-between gap-4 border-b border-[#E5E0D6] bg-[#FBF8F1] p-5'>
<div className='flex min-w-0 gap-4'>
<div className='flex h-12 w-12 shrink-0 items-center justify-center rounded-lg bg-[#0E1A2B] text-sm font-semibold text-[#D8B75E]'>
{getInitials(item.name)}
</div>
<div className='min-w-0'>
<p className='text-xs font-semibold uppercase tracking-[0.14em] text-[#8B7A61]'>
Matter type
</p>
<Link
href={`/matter_types/matter_types-view/?id=${item.id}`}
className='mt-2 block text-lg font-semibold leading-6 text-[#0E1A2B] hover:text-[#7A5B13]'
>
{item.name || 'Unnamed matter type'}
</Link>
</div>
</div>
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>Description</p>
<p className={'line-clamp-2'}>{ item.description }</p>
</div>
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>Active</p>
<p className={'line-clamp-2'}>{ dataFormatter.booleanFormatter(item.is_active) }</p>
</div>
</Link>
<ListActionsPopover
onDelete={onDelete}
itemId={item.id}
pathEdit={`/matter_types/matter_types-edit/?id=${item.id}`}
pathView={`/matter_types/matter_types-view/?id=${item.id}`}
hasUpdatePermission={hasUpdatePermission}
onDelete={onDelete}
itemId={item.id}
pathEdit={`/matter_types/matter_types-edit/?id=${item.id}`}
pathView={`/matter_types/matter_types-view/?id=${item.id}`}
hasUpdatePermission={hasUpdatePermission}
/>
</div>
</CardBox>
</div>
<div className='space-y-4 p-5'>
<div className='flex flex-wrap gap-2'>
<span
className={
item.is_active
? 'rounded-full border border-emerald-200 bg-emerald-50 px-3 py-1 text-xs font-semibold text-emerald-700'
: 'rounded-full border border-slate-200 bg-slate-50 px-3 py-1 text-xs font-semibold text-slate-600'
}
>
{item.is_active ? 'Active' : 'Inactive'}
</span>
<span className='rounded-full border border-[#D8D0C2] bg-[#F6F3EC] px-3 py-1 text-xs font-semibold text-[#7A5B13]'>
Intake context
</span>
</div>
<p className='min-h-[72px] text-sm leading-6 text-[#5B6472]'>
{item.description || 'No matter-type description yet.'}
</p>
<div className='rounded-lg border border-[#E5E0D6] bg-[#FBF8F1] p-4'>
<p className='text-xs font-semibold uppercase tracking-[0.14em] text-[#8B7A61]'>
Governance use
</p>
<p className='mt-2 text-sm leading-6 text-[#0E1A2B]'>
Helps classify AI use cases by legal matter context before risk review and approval.
</p>
</div>
</div>
</div>
))}
{!loading && matter_types.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p>
</div>
<div className='col-span-full flex h-40 items-center justify-center rounded-xl border border-dashed border-[#D8D0C2] bg-white'>
<p className='text-sm text-[#5B6472]'>No matter types to display</p>
</div>
)}
</div>
<div className={'flex items-center justify-center my-6'}>
<div className='my-6 flex items-center justify-center'>
<Pagination
currentPage={currentPage}
numPages={numPages}
setCurrentPage={onPageChange}
currentPage={currentPage}
numPages={numPages}
setCurrentPage={onPageChange}
/>
</div>
</>
)
};
export default ListMatter_types
export default ListMatter_types

View File

@ -44,9 +44,6 @@ const TableSampleMatter_types = ({ filterItems, setFilterItems, filters, showGri
const { matter_types, loading, count, notify: matter_typesNotify, refetch } = useAppSelector((state) => state.matter_types)
const { currentUser } = useAppSelector((state) => state.auth);
const focusRing = useAppSelector((state) => state.style.focusRingColor);
const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
const corners = useAppSelector((state) => state.style.corners);
const numPages = Math.floor(count / perPage) === 0 ? 1 : Math.ceil(count / perPage);
for (let i = 0; i < numPages; i++) {
pagesList.push(i);
@ -204,9 +201,7 @@ const TableSampleMatter_types = ({ filterItems, setFilterItems, filters, showGri
};
const controlClasses =
'w-full py-2 px-2 my-2 rounded dark:placeholder-gray-400 ' +
` ${bgColor} ${focusRing} ${corners} ` +
'dark:bg-slate-800 border';
'w-full my-1.5 rounded-lg border border-[#D8D0C2] bg-white px-3 py-2 text-sm text-[#0E1A2B] shadow-sm outline-none placeholder:text-[#9A8F7F] focus:border-[#D8B75E] focus:ring-2 focus:ring-[#D8B75E]/25 dark:border-dark-700 dark:bg-slate-800 dark:placeholder-gray-400';
const dataGrid = (
@ -264,7 +259,7 @@ const TableSampleMatter_types = ({ filterItems, setFilterItems, filters, showGri
return (
<>
{filterItems && Array.isArray( filterItems ) && filterItems.length ?
<CardBox>
<CardBox className='mb-6 border border-[#DDD5C7] bg-[#FBF8F1] shadow-sm'>
<Formik
initialValues={{
checkboxes: ['lorem'],
@ -275,11 +270,18 @@ const TableSampleMatter_types = ({ filterItems, setFilterItems, filters, showGri
>
<Form>
<>
<div className='mb-4 flex flex-wrap items-center justify-between gap-3'>
<div>
<p className='text-xs font-semibold uppercase tracking-[0.14em] text-[#7A5B13]'>Active filters</p>
<p className='mt-1 text-sm text-[#5B6472]'>Narrow matter types by name or description.</p>
</div>
<span className='rounded-full border border-[#D8B75E] bg-[#FFF8DF] px-3 py-1 text-xs font-semibold text-[#7A5B13]'>Matter scope</span>
</div>
{filterItems && filterItems.map((filterItem) => {
return (
<div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div>
<div key={filterItem.id} className="grid gap-3 rounded-lg border border-[#E5E0D6] bg-white p-4 shadow-sm md:grid-cols-[minmax(180px,0.9fr)_minmax(240px,1.4fr)_auto] md:items-end">
<div className="flex flex-col w-full">
<div className="text-xs font-semibold uppercase tracking-[0.12em] text-[#7A5B13]">Filter</div>
<Field
className={controlClasses}
name='selectedField'
@ -301,8 +303,8 @@ const TableSampleMatter_types = ({ filterItems, setFilterItems, filters, showGri
{filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField
)?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold">
<div className="flex flex-col w-full">
<div className="text-xs font-semibold uppercase tracking-[0.12em] text-[#7A5B13]">
Value
</div>
<Field
@ -326,9 +328,9 @@ const TableSampleMatter_types = ({ filterItems, setFilterItems, filters, showGri
) : filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField
)?.number ? (
<div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div>
<div className="grid w-full gap-3 sm:grid-cols-2">
<div className="flex flex-col w-full">
<div className="text-xs font-semibold uppercase tracking-[0.12em] text-[#7A5B13]">From</div>
<Field
className={controlClasses}
name='filterValueFrom'
@ -339,7 +341,7 @@ const TableSampleMatter_types = ({ filterItems, setFilterItems, filters, showGri
/>
</div>
<div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div>
<div className="text-xs font-semibold uppercase tracking-[0.12em] text-[#7A5B13]">To</div>
<Field
className={controlClasses}
name='filterValueTo'
@ -355,9 +357,9 @@ const TableSampleMatter_types = ({ filterItems, setFilterItems, filters, showGri
filter.title ===
filterItem?.fields?.selectedField
)?.date ? (
<div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'>
<div className='grid w-full gap-3 sm:grid-cols-2'>
<div className='flex flex-col w-full'>
<div className='text-xs font-semibold uppercase tracking-[0.12em] text-[#7A5B13]'>
From
</div>
<Field
@ -371,7 +373,7 @@ const TableSampleMatter_types = ({ filterItems, setFilterItems, filters, showGri
/>
</div>
<div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div>
<div className='text-xs font-semibold uppercase tracking-[0.12em] text-[#7A5B13]'>To</div>
<Field
className={controlClasses}
name='filterValueTo'
@ -384,8 +386,8 @@ const TableSampleMatter_types = ({ filterItems, setFilterItems, filters, showGri
</div>
</div>
) : (
<div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div>
<div className="flex flex-col w-full">
<div className="text-xs font-semibold uppercase tracking-[0.12em] text-[#7A5B13]">Contains</div>
<Field
className={controlClasses}
name='filterValue'
@ -397,7 +399,7 @@ const TableSampleMatter_types = ({ filterItems, setFilterItems, filters, showGri
</div>
)}
<div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div>
<div className="text-xs font-semibold uppercase tracking-[0.12em] text-[#7A5B13]">Action</div>
<BaseButton
className="my-2"
type='reset'
@ -411,17 +413,17 @@ const TableSampleMatter_types = ({ filterItems, setFilterItems, filters, showGri
</div>
)
})}
<div className="flex">
<div className="flex flex-wrap gap-2">
<BaseButton
className="my-2 mr-3"
color="success"
color="info"
label='Apply'
onClick={handleSubmit}
/>
<BaseButton
className="my-2"
color='info'
label='Cancel'
color='whiteDark'
label='Reset'
onClick={handleReset}
/>
</div>

View File

@ -43,7 +43,7 @@ export const loadColumns = async (
{
field: 'name',
headerName: 'MatterType',
headerName: 'Matter type',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -43,7 +43,7 @@ export const loadColumns = async (
{
field: 'title',
headerName: 'PolicyTitle',
headerName: 'Policy Title',
flex: 1,
minWidth: 120,
filterable: false,
@ -58,7 +58,7 @@ export const loadColumns = async (
{
field: 'policy_type',
headerName: 'PolicyType',
headerName: 'Policy Type',
flex: 1,
minWidth: 120,
filterable: false,
@ -88,7 +88,7 @@ export const loadColumns = async (
{
field: 'practice_group',
headerName: 'PracticeGroupScope',
headerName: 'Practice Group Scope',
flex: 1,
minWidth: 120,
filterable: false,
@ -110,7 +110,7 @@ export const loadColumns = async (
{
field: 'data_classification',
headerName: 'DataClassificationScope',
headerName: 'Data Classification Scope',
flex: 1,
minWidth: 120,
filterable: false,
@ -162,7 +162,7 @@ export const loadColumns = async (
{
field: 'effective_from',
headerName: 'EffectiveFrom',
headerName: 'Effective From',
flex: 1,
minWidth: 120,
filterable: false,
@ -180,7 +180,7 @@ export const loadColumns = async (
{
field: 'effective_to',
headerName: 'EffectiveTo',
headerName: 'Effective To',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -43,7 +43,7 @@ export const loadColumns = async (
{
field: 'name',
headerName: 'PracticeGroupName',
headerName: 'Practice Group Name',
flex: 1,
minWidth: 120,
filterable: false,
@ -73,7 +73,7 @@ export const loadColumns = async (
{
field: 'lead_user',
headerName: 'PracticeGroupLead',
headerName: 'Practice Group Lead',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -43,7 +43,7 @@ export const loadColumns = async (
{
field: 'workflow_run',
headerName: 'WorkflowRun',
headerName: 'Workflow Run',
flex: 1,
minWidth: 120,
filterable: false,
@ -87,7 +87,7 @@ export const loadColumns = async (
{
field: 'raised_by',
headerName: 'RaisedBy',
headerName: 'Raised By',
flex: 1,
minWidth: 120,
filterable: false,
@ -109,7 +109,7 @@ export const loadColumns = async (
{
field: 'exception_type',
headerName: 'ExceptionType',
headerName: 'Exception Type',
flex: 1,
minWidth: 120,
filterable: false,
@ -139,7 +139,7 @@ export const loadColumns = async (
{
field: 'resolution_status',
headerName: 'ResolutionStatus',
headerName: 'Resolution Status',
flex: 1,
minWidth: 120,
filterable: false,
@ -154,7 +154,7 @@ export const loadColumns = async (
{
field: 'raised_at',
headerName: 'RaisedAt',
headerName: 'Raised At',
flex: 1,
minWidth: 120,
filterable: false,
@ -172,7 +172,7 @@ export const loadColumns = async (
{
field: 'resolved_at',
headerName: 'ResolvedAt',
headerName: 'Resolved At',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -1,123 +1,3 @@
import React from 'react';
import ImageField from '../ImageField';
import ListActionsPopover from '../ListActionsPopover';
import { useAppSelector } from '../../stores/hooks';
import dataFormatter from '../../helpers/dataFormatter';
import { Pagination } from '../Pagination';
import {saveFile} from "../../helpers/fileSaver";
import LoadingSpinner from "../LoadingSpinner";
import Link from 'next/link';
import ListRoles_catalog from './ListRoles_catalog';
import {hasPermission} from "../../helpers/userPermissions";
type Props = {
roles_catalog: any[];
loading: boolean;
onDelete: (id: string) => void;
currentPage: number;
numPages: number;
onPageChange: (page: number) => void;
};
const CardRoles_catalog = ({
roles_catalog,
loading,
onDelete,
currentPage,
numPages,
onPageChange,
}: Props) => {
const asideScrollbarsStyle = useAppSelector(
(state) => state.style.asideScrollbarsStyle,
);
const bgColor = useAppSelector((state) => state.style.cardsColor);
const darkMode = useAppSelector((state) => state.style.darkMode);
const corners = useAppSelector((state) => state.style.corners);
const focusRing = useAppSelector((state) => state.style.focusRingColor);
const currentUser = useAppSelector((state) => state.auth.currentUser);
const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_ROLES_CATALOG')
return (
<div className={'p-4'}>
{loading && <LoadingSpinner />}
<ul
role='list'
className='grid grid-cols-1 gap-x-6 gap-y-8 lg:grid-cols-3 2xl:grid-cols-4 xl:gap-x-8'
>
{!loading && roles_catalog.map((item, index) => (
<li
key={item.id}
className={`overflow-hidden ${corners !== 'rounded-full'? corners : 'rounded-3xl'} border ${focusRing} border-gray-200 dark:border-dark-700 ${
darkMode ? 'aside-scrollbars-[slate]' : asideScrollbarsStyle
}`}
>
<div className={`flex items-center ${bgColor} p-6 gap-x-4 border-b border-gray-900/5 bg-gray-50 dark:bg-dark-800 relative`}>
<Link href={`/roles_catalog/roles_catalog-view/?id=${item.id}`} className='text-lg font-bold leading-6 line-clamp-1'>
{item.name}
</Link>
<div className='ml-auto '>
<ListActionsPopover
onDelete={onDelete}
itemId={item.id}
pathEdit={`/roles_catalog/roles_catalog-edit/?id=${item.id}`}
pathView={`/roles_catalog/roles_catalog-view/?id=${item.id}`}
hasUpdatePermission={hasUpdatePermission}
/>
</div>
</div>
<dl className='divide-y divide-stone-300 dark:divide-dark-700 px-6 py-4 text-sm leading-6 h-64 overflow-y-auto'>
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>RoleName</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.name }
</div>
</dd>
</div>
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>Description</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.description }
</div>
</dd>
</div>
</dl>
</li>
))}
{!loading && roles_catalog.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p>
</div>
)}
</ul>
<div className={'flex items-center justify-center my-6'}>
<Pagination
currentPage={currentPage}
numPages={numPages}
setCurrentPage={onPageChange}
/>
</div>
</div>
);
};
export default CardRoles_catalog;
export default ListRoles_catalog;

View File

@ -1,16 +1,10 @@
import React from 'react';
import CardBox from '../CardBox';
import ImageField from '../ImageField';
import dataFormatter from '../../helpers/dataFormatter';
import {saveFile} from "../../helpers/fileSaver";
import ListActionsPopover from "../ListActionsPopover";
import {useAppSelector} from "../../stores/hooks";
import {Pagination} from "../Pagination";
import LoadingSpinner from "../LoadingSpinner";
import Link from 'next/link';
import {hasPermission} from "../../helpers/userPermissions";
import ListActionsPopover from "../ListActionsPopover";
import { useAppSelector } from "../../stores/hooks";
import { Pagination } from "../Pagination";
import LoadingSpinner from "../LoadingSpinner";
import { hasPermission } from "../../helpers/userPermissions";
type Props = {
roles_catalog: any[];
@ -21,76 +15,105 @@ type Props = {
onPageChange: (page: number) => void;
};
const ListRoles_catalog = ({ roles_catalog, loading, onDelete, currentPage, numPages, onPageChange }: Props) => {
const currentUser = useAppSelector((state) => state.auth.currentUser);
const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_ROLES_CATALOG')
const corners = useAppSelector((state) => state.style.corners);
const bgColor = useAppSelector((state) => state.style.cardsColor);
const getInitials = (name?: string) => {
if (!name) {
return 'RC';
}
return name
.split(' ')
.map((part) => part[0])
.join('')
.slice(0, 2)
.toUpperCase();
};
const ListRoles_catalog = ({ roles_catalog, loading, onDelete, currentPage, numPages, onPageChange }: Props) => {
const currentUser = useAppSelector((state) => state.auth.currentUser);
const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_ROLES_CATALOG');
return (
<>
<div className='relative overflow-x-auto p-4 space-y-4'>
{loading && <LoadingSpinner />}
<div className='grid grid-cols-[repeat(auto-fit,minmax(340px,1fr))] gap-4 p-4'>
{loading && (
<div className='col-span-full rounded-xl border border-[#DDD5C7] bg-white p-10'>
<LoadingSpinner />
</div>
)}
{!loading && roles_catalog.map((item) => (
<div key={item.id}>
<CardBox hasTable isList className={'rounded shadow-none'}>
<div className={`flex rounded dark:bg-dark-900 border border-stone-300 items-center overflow-hidden`}>
<Link
href={`/roles_catalog/roles_catalog-view/?id=${item.id}`}
className={
'flex-1 px-4 py-6 h-24 flex divide-x-2 divide-stone-300 items-center overflow-hidden`}> dark:divide-dark-700 overflow-x-auto'
}
>
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>RoleName</p>
<p className={'line-clamp-2'}>{ item.name }</p>
<div
key={item.id}
className='min-w-0 overflow-hidden rounded-xl border border-[#DDD5C7] bg-white shadow-sm shadow-[#83755E]/10 transition hover:border-[#D8B75E]/70 hover:shadow-md'
>
<div className='flex items-start justify-between gap-4 border-b border-[#E5E0D6] bg-[#FBF8F1] p-5'>
<div className='flex min-w-0 gap-4'>
<div className='flex h-12 w-12 shrink-0 items-center justify-center rounded-lg bg-[#0E1A2B] text-sm font-semibold text-[#D8B75E]'>
{getInitials(item.name)}
</div>
<div className='min-w-0'>
<p className='text-xs font-semibold uppercase tracking-[0.14em] text-[#8B7A61]'>
Governance role
</p>
<Link
href={`/roles_catalog/roles_catalog-view/?id=${item.id}`}
className='mt-2 block text-lg font-semibold leading-6 text-[#0E1A2B] hover:text-[#7A5B13]'
>
{item.name || 'Unnamed role'}
</Link>
</div>
</div>
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>Description</p>
<p className={'line-clamp-2'}>{ item.description }</p>
</div>
</Link>
<ListActionsPopover
onDelete={onDelete}
itemId={item.id}
pathEdit={`/roles_catalog/roles_catalog-edit/?id=${item.id}`}
pathView={`/roles_catalog/roles_catalog-view/?id=${item.id}`}
hasUpdatePermission={hasUpdatePermission}
onDelete={onDelete}
itemId={item.id}
pathEdit={`/roles_catalog/roles_catalog-edit/?id=${item.id}`}
pathView={`/roles_catalog/roles_catalog-view/?id=${item.id}`}
hasUpdatePermission={hasUpdatePermission}
/>
</div>
</CardBox>
</div>
<div className='space-y-4 p-5'>
<div className='flex flex-wrap gap-2'>
<span className='rounded-full border border-[#D8B75E] bg-[#FFF8DF] px-3 py-1 text-xs font-semibold text-[#7A5B13]'>
Role catalog
</span>
<span className='rounded-full border border-[#D8D0C2] bg-[#F6F3EC] px-3 py-1 text-xs font-semibold text-[#7A5B13]'>
Approval ownership
</span>
</div>
<p className='min-h-[72px] text-sm leading-6 text-[#5B6472]'>
{item.description || 'No role description yet.'}
</p>
<div className='rounded-lg border border-[#E5E0D6] bg-[#FBF8F1] p-4'>
<p className='text-xs font-semibold uppercase tracking-[0.14em] text-[#8B7A61]'>
Governance use
</p>
<p className='mt-2 text-sm leading-6 text-[#0E1A2B]'>
Defines who can own, approve, review, or monitor AI governance workflows.
</p>
</div>
</div>
</div>
))}
{!loading && roles_catalog.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p>
</div>
<div className='col-span-full flex h-40 items-center justify-center rounded-xl border border-dashed border-[#D8D0C2] bg-white'>
<p className='text-sm text-[#5B6472]'>No roles to display</p>
</div>
)}
</div>
<div className={'flex items-center justify-center my-6'}>
<div className='my-6 flex items-center justify-center'>
<Pagination
currentPage={currentPage}
numPages={numPages}
setCurrentPage={onPageChange}
currentPage={currentPage}
numPages={numPages}
setCurrentPage={onPageChange}
/>
</div>
</>
)
};
export default ListRoles_catalog
export default ListRoles_catalog

View File

@ -44,9 +44,6 @@ const TableSampleRoles_catalog = ({ filterItems, setFilterItems, filters, showGr
const { roles_catalog, loading, count, notify: roles_catalogNotify, refetch } = useAppSelector((state) => state.roles_catalog)
const { currentUser } = useAppSelector((state) => state.auth);
const focusRing = useAppSelector((state) => state.style.focusRingColor);
const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
const corners = useAppSelector((state) => state.style.corners);
const numPages = Math.floor(count / perPage) === 0 ? 1 : Math.ceil(count / perPage);
for (let i = 0; i < numPages; i++) {
pagesList.push(i);
@ -204,9 +201,7 @@ const TableSampleRoles_catalog = ({ filterItems, setFilterItems, filters, showGr
};
const controlClasses =
'w-full py-2 px-2 my-2 rounded dark:placeholder-gray-400 ' +
` ${bgColor} ${focusRing} ${corners} ` +
'dark:bg-slate-800 border';
'w-full my-1.5 rounded-lg border border-[#D8D0C2] bg-white px-3 py-2 text-sm text-[#0E1A2B] shadow-sm outline-none placeholder:text-[#9A8F7F] focus:border-[#D8B75E] focus:ring-2 focus:ring-[#D8B75E]/25 dark:border-dark-700 dark:bg-slate-800 dark:placeholder-gray-400';
const dataGrid = (
@ -264,7 +259,7 @@ const TableSampleRoles_catalog = ({ filterItems, setFilterItems, filters, showGr
return (
<>
{filterItems && Array.isArray( filterItems ) && filterItems.length ?
<CardBox>
<CardBox className='mb-6 border border-[#DDD5C7] bg-[#FBF8F1] shadow-sm'>
<Formik
initialValues={{
checkboxes: ['lorem'],
@ -275,11 +270,18 @@ const TableSampleRoles_catalog = ({ filterItems, setFilterItems, filters, showGr
>
<Form>
<>
<div className='mb-4 flex flex-wrap items-center justify-between gap-3'>
<div>
<p className='text-xs font-semibold uppercase tracking-[0.14em] text-[#7A5B13]'>Active filters</p>
<p className='mt-1 text-sm text-[#5B6472]'>Narrow the role catalog by owner role or description.</p>
</div>
<span className='rounded-full border border-[#D8B75E] bg-[#FFF8DF] px-3 py-1 text-xs font-semibold text-[#7A5B13]'>Role scope</span>
</div>
{filterItems && filterItems.map((filterItem) => {
return (
<div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div>
<div key={filterItem.id} className="grid gap-3 rounded-lg border border-[#E5E0D6] bg-white p-4 shadow-sm md:grid-cols-[minmax(180px,0.9fr)_minmax(240px,1.4fr)_auto] md:items-end">
<div className="flex flex-col w-full">
<div className="text-xs font-semibold uppercase tracking-[0.12em] text-[#7A5B13]">Filter</div>
<Field
className={controlClasses}
name='selectedField'
@ -301,8 +303,8 @@ const TableSampleRoles_catalog = ({ filterItems, setFilterItems, filters, showGr
{filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField
)?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold">
<div className="flex flex-col w-full">
<div className="text-xs font-semibold uppercase tracking-[0.12em] text-[#7A5B13]">
Value
</div>
<Field
@ -326,9 +328,9 @@ const TableSampleRoles_catalog = ({ filterItems, setFilterItems, filters, showGr
) : filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField
)?.number ? (
<div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div>
<div className="grid w-full gap-3 sm:grid-cols-2">
<div className="flex flex-col w-full">
<div className="text-xs font-semibold uppercase tracking-[0.12em] text-[#7A5B13]">From</div>
<Field
className={controlClasses}
name='filterValueFrom'
@ -339,7 +341,7 @@ const TableSampleRoles_catalog = ({ filterItems, setFilterItems, filters, showGr
/>
</div>
<div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div>
<div className="text-xs font-semibold uppercase tracking-[0.12em] text-[#7A5B13]">To</div>
<Field
className={controlClasses}
name='filterValueTo'
@ -351,13 +353,13 @@ const TableSampleRoles_catalog = ({ filterItems, setFilterItems, filters, showGr
</div>
</div>
) : filters.find(
(filter) =>
filter.title ===
filterItem?.fields?.selectedField
(filter) =>
filter.title ===
filterItem?.fields?.selectedField
)?.date ? (
<div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'>
<div className='grid w-full gap-3 sm:grid-cols-2'>
<div className='flex flex-col w-full'>
<div className='text-xs font-semibold uppercase tracking-[0.12em] text-[#7A5B13]'>
From
</div>
<Field
@ -371,7 +373,7 @@ const TableSampleRoles_catalog = ({ filterItems, setFilterItems, filters, showGr
/>
</div>
<div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div>
<div className='text-xs font-semibold uppercase tracking-[0.12em] text-[#7A5B13]'>To</div>
<Field
className={controlClasses}
name='filterValueTo'
@ -384,8 +386,8 @@ const TableSampleRoles_catalog = ({ filterItems, setFilterItems, filters, showGr
</div>
</div>
) : (
<div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div>
<div className="flex flex-col w-full">
<div className="text-xs font-semibold uppercase tracking-[0.12em] text-[#7A5B13]">Contains</div>
<Field
className={controlClasses}
name='filterValue'
@ -397,7 +399,7 @@ const TableSampleRoles_catalog = ({ filterItems, setFilterItems, filters, showGr
</div>
)}
<div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div>
<div className="text-xs font-semibold uppercase tracking-[0.12em] text-[#7A5B13]">Action</div>
<BaseButton
className="my-2"
type='reset'
@ -411,17 +413,17 @@ const TableSampleRoles_catalog = ({ filterItems, setFilterItems, filters, showGr
</div>
)
})}
<div className="flex">
<div className="flex flex-wrap gap-2">
<BaseButton
className="my-2 mr-3"
color="success"
color="info"
label='Apply'
onClick={handleSubmit}
/>
<BaseButton
className="my-2"
color='info'
label='Cancel'
color='whiteDark'
label='Reset'
onClick={handleReset}
/>
</div>

View File

@ -43,7 +43,7 @@ export const loadColumns = async (
{
field: 'name',
headerName: 'RoleName',
headerName: 'Role name',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -65,7 +65,7 @@ export const loadColumns = async (
{
field: 'tool',
headerName: 'AITool',
headerName: 'AI Tool',
flex: 1,
minWidth: 120,
filterable: false,
@ -87,7 +87,7 @@ export const loadColumns = async (
{
field: 'entitlement_status',
headerName: 'EntitlementStatus',
headerName: 'Entitlement Status',
flex: 1,
minWidth: 120,
filterable: false,
@ -102,7 +102,7 @@ export const loadColumns = async (
{
field: 'effective_from',
headerName: 'EffectiveFrom',
headerName: 'Effective From',
flex: 1,
minWidth: 120,
filterable: false,
@ -120,7 +120,7 @@ export const loadColumns = async (
{
field: 'effective_to',
headerName: 'EffectiveTo',
headerName: 'Effective To',
flex: 1,
minWidth: 120,
filterable: false,
@ -138,7 +138,7 @@ export const loadColumns = async (
{
field: 'restriction_reason',
headerName: 'RestrictionReason',
headerName: 'Restriction Reason',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -43,7 +43,7 @@ export const loadColumns = async (
{
field: 'name',
headerName: 'CourseName',
headerName: 'Course Name',
flex: 1,
minWidth: 120,
filterable: false,
@ -73,7 +73,7 @@ export const loadColumns = async (
{
field: 'delivery_type',
headerName: 'DeliveryType',
headerName: 'Delivery Type',
flex: 1,
minWidth: 120,
filterable: false,
@ -103,7 +103,7 @@ export const loadColumns = async (
{
field: 'duration_minutes',
headerName: 'DurationMinutes',
headerName: 'Duration Minutes',
flex: 1,
minWidth: 120,
filterable: false,
@ -119,7 +119,7 @@ export const loadColumns = async (
{
field: 'validity_days',
headerName: 'ValidityDays',
headerName: 'Validity Days',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -87,7 +87,7 @@ export const loadColumns = async (
{
field: 'completion_status',
headerName: 'CompletionStatus',
headerName: 'Completion Status',
flex: 1,
minWidth: 120,
filterable: false,
@ -102,7 +102,7 @@ export const loadColumns = async (
{
field: 'completed_at',
headerName: 'CompletedAt',
headerName: 'Completed At',
flex: 1,
minWidth: 120,
filterable: false,
@ -120,7 +120,7 @@ export const loadColumns = async (
{
field: 'expires_at',
headerName: 'ExpiresAt',
headerName: 'Expires At',
flex: 1,
minWidth: 120,
filterable: false,
@ -138,7 +138,7 @@ export const loadColumns = async (
{
field: 'evidence_note',
headerName: 'EvidenceNote',
headerName: 'Evidence Note',
flex: 1,
minWidth: 120,
filterable: false,
@ -153,7 +153,7 @@ export const loadColumns = async (
{
field: 'certificate_files',
headerName: 'CertificateFiles',
headerName: 'Certificate Files',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -65,7 +65,7 @@ export const loadColumns = async (
{
field: 'tool',
headerName: 'AITool',
headerName: 'AI Tool',
flex: 1,
minWidth: 120,
filterable: false,
@ -87,7 +87,7 @@ export const loadColumns = async (
{
field: 'assessment_status',
headerName: 'AssessmentStatus',
headerName: 'Assessment Status',
flex: 1,
minWidth: 120,
filterable: false,
@ -102,7 +102,7 @@ export const loadColumns = async (
{
field: 'confidentiality_score',
headerName: 'ConfidentialityScore',
headerName: 'Confidentiality Score',
flex: 1,
minWidth: 120,
filterable: false,
@ -118,7 +118,7 @@ export const loadColumns = async (
{
field: 'security_score',
headerName: 'SecurityScore',
headerName: 'Security Score',
flex: 1,
minWidth: 120,
filterable: false,
@ -134,7 +134,7 @@ export const loadColumns = async (
{
field: 'integration_readiness_score',
headerName: 'IntegrationReadinessScore',
headerName: 'Integration Readiness Score',
flex: 1,
minWidth: 120,
filterable: false,
@ -150,7 +150,7 @@ export const loadColumns = async (
{
field: 'legal_specific_risk_score',
headerName: 'LegalSpecificRiskScore',
headerName: 'Legal Specific Risk Score',
flex: 1,
minWidth: 120,
filterable: false,
@ -166,7 +166,7 @@ export const loadColumns = async (
{
field: 'pricing_score',
headerName: 'PricingScore',
headerName: 'Pricing Score',
flex: 1,
minWidth: 120,
filterable: false,
@ -182,7 +182,7 @@ export const loadColumns = async (
{
field: 'support_score',
headerName: 'SupportScore',
headerName: 'Support Score',
flex: 1,
minWidth: 120,
filterable: false,
@ -198,7 +198,7 @@ export const loadColumns = async (
{
field: 'compliance_score',
headerName: 'ComplianceScore',
headerName: 'Compliance Score',
flex: 1,
minWidth: 120,
filterable: false,
@ -214,7 +214,7 @@ export const loadColumns = async (
{
field: 'overall_score',
headerName: 'OverallScore',
headerName: 'Overall Score',
flex: 1,
minWidth: 120,
filterable: false,
@ -260,7 +260,7 @@ export const loadColumns = async (
{
field: 'evidence_files',
headerName: 'EvidenceFiles',
headerName: 'Evidence Files',
flex: 1,
minWidth: 120,
filterable: false,
@ -286,7 +286,7 @@ export const loadColumns = async (
{
field: 'owner',
headerName: 'AssessmentOwner',
headerName: 'Assessment Owner',
flex: 1,
minWidth: 120,
filterable: false,
@ -308,7 +308,7 @@ export const loadColumns = async (
{
field: 'started_at',
headerName: 'StartedAt',
headerName: 'Started At',
flex: 1,
minWidth: 120,
filterable: false,
@ -326,7 +326,7 @@ export const loadColumns = async (
{
field: 'completed_at',
headerName: 'CompletedAt',
headerName: 'Completed At',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -43,7 +43,7 @@ export const loadColumns = async (
{
field: 'name',
headerName: 'VendorName',
headerName: 'Vendor Name',
flex: 1,
minWidth: 120,
filterable: false,
@ -73,7 +73,7 @@ export const loadColumns = async (
{
field: 'vendor_status',
headerName: 'VendorStatus',
headerName: 'Vendor Status',
flex: 1,
minWidth: 120,
filterable: false,
@ -88,7 +88,7 @@ export const loadColumns = async (
{
field: 'primary_contact_name',
headerName: 'PrimaryContactName',
headerName: 'Primary Contact Name',
flex: 1,
minWidth: 120,
filterable: false,
@ -103,7 +103,7 @@ export const loadColumns = async (
{
field: 'primary_contact_email',
headerName: 'PrimaryContactEmail',
headerName: 'Primary Contact Email',
flex: 1,
minWidth: 120,
filterable: false,
@ -118,7 +118,7 @@ export const loadColumns = async (
{
field: 'contract_documents',
headerName: 'ContractDocuments',
headerName: 'Contract Documents',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -43,7 +43,7 @@ export const loadColumns = async (
{
field: 'use_case',
headerName: 'AIUseCase',
headerName: 'AI Use Case',
flex: 1,
minWidth: 120,
filterable: false,
@ -109,7 +109,7 @@ export const loadColumns = async (
{
field: 'practice_group',
headerName: 'PracticeGroup',
headerName: 'Practice Group',
flex: 1,
minWidth: 120,
filterable: false,
@ -131,7 +131,7 @@ export const loadColumns = async (
{
field: 'matter_type',
headerName: 'MatterType',
headerName: 'Matter Type',
flex: 1,
minWidth: 120,
filterable: false,
@ -153,7 +153,7 @@ export const loadColumns = async (
{
field: 'review_status',
headerName: 'ReviewStatus',
headerName: 'Review Status',
flex: 1,
minWidth: 120,
filterable: false,
@ -168,7 +168,7 @@ export const loadColumns = async (
{
field: 'output_disposition',
headerName: 'OutputDisposition',
headerName: 'Output Disposition',
flex: 1,
minWidth: 120,
filterable: false,
@ -183,7 +183,7 @@ export const loadColumns = async (
{
field: 'issues_found',
headerName: 'IssuesFound',
headerName: 'Issues Found',
flex: 1,
minWidth: 120,
filterable: false,
@ -198,7 +198,7 @@ export const loadColumns = async (
{
field: 'actual_hours_saved',
headerName: 'ActualHoursSaved',
headerName: 'Actual Hours Saved',
flex: 1,
minWidth: 120,
filterable: false,
@ -214,7 +214,7 @@ export const loadColumns = async (
{
field: 'run_cost',
headerName: 'RunCost',
headerName: 'Run Cost',
flex: 1,
minWidth: 120,
filterable: false,
@ -230,7 +230,7 @@ export const loadColumns = async (
{
field: 'ran_at',
headerName: 'RanAt',
headerName: 'Ran At',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -70,13 +70,13 @@
@apply text-sm font-normal text-pavitra-900 dark:text-white;
}
.datagrid--table, .MuiDataGrid-root {
@apply rounded border-none !important;
.datagrid--table {
@apply rounded-xl border-none !important;
}
.datagrid--header {
@apply uppercase !important;
letter-spacing: 0.07em !important;
text-transform: uppercase !important;
}
.datagrid--header,
@ -95,7 +95,31 @@
}
.datagrid--row {
@apply even:bg-gray-100 dark:even:bg-[#1B1D22] dark:odd:bg-dark-900 !important;
@apply even:bg-[#F7F5EF] odd:bg-white dark:even:bg-[#1B1D22] dark:odd:bg-dark-900 !important;
}
.datagrid--table .MuiDataGrid-cell,
.datagrid--table .MuiDataGrid-columnHeader {
min-width: 0;
}
.datagrid--table .MuiDataGrid-cellContent,
.datagrid--table .MuiDataGrid-columnHeaderTitle {
word-break: normal !important;
}
.datagrid--table .MuiDataGrid-cellContent {
overflow-wrap: normal;
white-space: nowrap !important;
}
.datagrid--table .MuiDataGrid-columnHeaderTitle {
overflow-wrap: normal;
white-space: normal !important;
}
.datagrid--table .MuiDataGrid-cellContent {
color: #374151;
}
@ -111,7 +135,7 @@
@apply dark:bg-dark-700;
}
.MuiButton-colorInherit {
.datagrid--table .MuiButton-colorInherit {
@apply text-blue-600 dark:text-dark-700 !important;
}
}

View File

@ -134,7 +134,7 @@ const AiUseCasesNew = () => {
</div>
</CardBox>
<CardBox className='border border-[#D6E0F5] bg-[#0F172A] text-white'>
<CardBox className='border-0 !bg-[#0F172A] !text-white'>
<div className='space-y-5'>
<div>
<p className='text-sm font-semibold uppercase tracking-[0.18em] text-slate-300'>What happens next</p>

View File

@ -275,7 +275,7 @@ const GovernanceWorkbench = () => {
</NotificationBar>
)}
<CardBox className='mb-6 overflow-hidden border-0 bg-[#0F172A] text-white'>
<CardBox className='mb-6 overflow-hidden border-0 !bg-[#0F172A] !text-white'>
<div className='grid gap-8 xl:grid-cols-[minmax(0,1.45fr)_minmax(320px,0.8fr)]'>
<div className='space-y-6 p-2'>
<div className='inline-flex items-center rounded-full border border-white/15 bg-white/5 px-3 py-1 text-xs font-semibold uppercase tracking-[0.18em] text-slate-200'>

View File

@ -178,11 +178,11 @@ const EditMatter_types = () => {
<FormField
label="MatterType"
label="Matter type"
>
<Field
name="name"
placeholder="MatterType"
placeholder="e.g. Litigation, contracts, employment"
/>
</FormField>

View File

@ -158,10 +158,10 @@ const EditMatter_typesPage = () => {
return (
<>
<Head>
<title>{getPageTitle('Edit matter_types')}</title>
<title>{getPageTitle('Edit matter type')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit matter_types'} main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit matter type'} main>
{''}
</SectionTitleLineWithButton>
<CardBox>
@ -175,11 +175,11 @@ const EditMatter_typesPage = () => {
<FormField
label="MatterType"
label="Matter type"
>
<Field
name="name"
placeholder="MatterType"
placeholder="e.g. Litigation, contracts, employment"
/>
</FormField>

View File

@ -6,11 +6,11 @@ import CardBox from '../../components/CardBox'
import LayoutAuthenticated from '../../layouts/Authenticated'
import SectionMain from '../../components/SectionMain'
import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
import LegalOpsPageIntro from '../../components/LegalOpsPageIntro'
import { getPageTitle } from '../../config'
import TableMatter_types from '../../components/Matter_types/TableMatter_types'
import BaseButton from '../../components/BaseButton'
import axios from "axios";
import Link from "next/link";
import {useAppDispatch, useAppSelector} from "../../stores/hooks";
import CardBoxModal from "../../components/CardBoxModal";
import DragDropFilePicker from "../../components/DragDropFilePicker";
@ -34,7 +34,7 @@ const Matter_typesTablesPage = () => {
const dispatch = useAppDispatch();
const [filters] = useState([{label: 'MatterType', title: 'name'},{label: 'Description', title: 'description'},
const [filters] = useState([{label: 'Matter type', title: 'name'},{label: 'Description', title: 'description'},
@ -86,27 +86,33 @@ const Matter_typesTablesPage = () => {
return (
<>
<Head>
<title>{getPageTitle('Matter_types')}</title>
<title>{getPageTitle('Matter types')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Matter_types" main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Matter types" main>
{''}
</SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/matter_types/matter_types-new'} color='info' label='New Item'/>}
<LegalOpsPageIntro
eyebrow='Matter context'
title='Classify legal AI requests by matter type before risk review'
description='Maintain the matter taxonomy used during AI use-case intake, data sensitivity classification, reviewer routing, and policy coverage.'
metrics={[
{ label: 'Classification', value: 'Matter type', helper: 'Every AI request can carry legal context from intake.' },
{ label: 'Risk lens', value: 'Context-aware', helper: 'Different matters can imply different privilege and confidentiality concerns.' },
{ label: 'Routing', value: 'Review support', helper: 'Matter type helps send requests to the right practice owners.' },
]}
>
{hasCreatePermission && <BaseButton href={'/matter_types/matter_types-new'} color='info' label='New matter type'/>}
<BaseButton
className={'mr-3'}
color='info'
label='Filter'
label='Add filter'
onClick={addFilter}
/>
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getMatter_typesCSV} />
<BaseButton color='whiteDark' label='Export CSV' onClick={getMatter_typesCSV} />
{hasCreatePermission && (
<BaseButton
color='info'
color='whiteDark'
label='Upload CSV'
onClick={() => setIsModalActive(true)}
/>
@ -116,11 +122,9 @@ const Matter_typesTablesPage = () => {
<div id='delete-rows-button'></div>
</div>
<div className='md:inline-flex items-center ms-auto'>
<Link href={'/matter_types/matter_types-table'}>Switch to Table</Link>
</div>
<BaseButton href={'/matter_types/matter_types-table'} color='whiteDark' label='Table view'/>
</CardBox>
</LegalOpsPageIntro>
<CardBox className="mb-6" hasTable>
<TableMatter_types

View File

@ -94,10 +94,10 @@ const Matter_typesNew = () => {
return (
<>
<Head>
<title>{getPageTitle('New Item')}</title>
<title>{getPageTitle('New matter type')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="New Item" main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="New matter type" main>
{''}
</SectionTitleLineWithButton>
<CardBox>
@ -114,11 +114,11 @@ const Matter_typesNew = () => {
<FormField
label="MatterType"
label="Matter type"
>
<Field
name="name"
placeholder="MatterType"
placeholder="e.g. Litigation, contracts, employment"
/>
</FormField>

View File

@ -6,11 +6,11 @@ import CardBox from '../../components/CardBox'
import LayoutAuthenticated from '../../layouts/Authenticated'
import SectionMain from '../../components/SectionMain'
import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
import LegalOpsPageIntro from '../../components/LegalOpsPageIntro'
import { getPageTitle } from '../../config'
import TableMatter_types from '../../components/Matter_types/TableMatter_types'
import BaseButton from '../../components/BaseButton'
import axios from "axios";
import Link from "next/link";
import {useAppDispatch, useAppSelector} from "../../stores/hooks";
import CardBoxModal from "../../components/CardBoxModal";
import DragDropFilePicker from "../../components/DragDropFilePicker";
@ -34,7 +34,7 @@ const Matter_typesTablesPage = () => {
const dispatch = useAppDispatch();
const [filters] = useState([{label: 'MatterType', title: 'name'},{label: 'Description', title: 'description'},
const [filters] = useState([{label: 'Matter type', title: 'name'},{label: 'Description', title: 'description'},
@ -86,27 +86,33 @@ const Matter_typesTablesPage = () => {
return (
<>
<Head>
<title>{getPageTitle('Matter_types')}</title>
<title>{getPageTitle('Matter types table')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Matter_types" main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Matter types table" main>
{''}
</SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/matter_types/matter_types-new'} color='info' label='New Item'/>}
<LegalOpsPageIntro
eyebrow='Matter context'
title='Matter types as an editable governance table'
description='Use table view to scan and edit the matter taxonomy used for AI request classification and review routing.'
metrics={[
{ label: 'View mode', value: 'Table', helper: 'Best for quick taxonomy cleanup and bulk review.' },
{ label: 'Classification', value: 'Matter type', helper: 'Matter context gives AI workflows legal specificity.' },
{ label: 'Routing', value: 'Review support', helper: 'Matter type can inform practice-owner review paths.' },
]}
>
{hasCreatePermission && <BaseButton href={'/matter_types/matter_types-new'} color='info' label='New matter type'/>}
<BaseButton
className={'mr-3'}
color='info'
label='Filter'
label='Add filter'
onClick={addFilter}
/>
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getMatter_typesCSV} />
<BaseButton color='whiteDark' label='Export CSV' onClick={getMatter_typesCSV} />
{hasCreatePermission && (
<BaseButton
color='info'
color='whiteDark'
label='Upload CSV'
onClick={() => setIsModalActive(true)}
/>
@ -114,13 +120,9 @@ const Matter_typesTablesPage = () => {
<div className='md:inline-flex items-center ms-auto'>
<div id='delete-rows-button'></div>
<Link href={'/matter_types/matter_types-list'}>
Back to <span className='capitalize'>list</span>
</Link>
</div>
</CardBox>
<BaseButton href={'/matter_types/matter_types-list'} color='whiteDark' label='Card view'/>
</LegalOpsPageIntro>
<CardBox className="mb-6" hasTable>
<TableMatter_types
filterItems={filterItems}

View File

@ -29,11 +29,6 @@ const Matter_typesView = () => {
const { id } = router.query;
function removeLastCharacter(str) {
console.log(str,`str`)
return str.slice(0, -1);
}
useEffect(() => {
dispatch(fetch({ id }));
}, [dispatch, id]);
@ -42,10 +37,10 @@ const Matter_typesView = () => {
return (
<>
<Head>
<title>{getPageTitle('View matter_types')}</title>
<title>{getPageTitle('Matter type details')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View matter_types')} main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Matter type details" main>
<BaseButton
color='info'
label='Edit'
@ -57,7 +52,7 @@ const Matter_typesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>MatterType</p>
<p className={'block font-bold mb-2'}>Matter type</p>
<p>{matter_types?.name}</p>
</div>
@ -163,7 +158,7 @@ const Matter_typesView = () => {
<>
<p className={'block font-bold mb-2'}>Ai_use_cases MatterType</p>
<p className={'block font-bold mb-2'}>AI use cases</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
@ -310,7 +305,7 @@ const Matter_typesView = () => {
<>
<p className={'block font-bold mb-2'}>Workflow_runs MatterType</p>
<p className={'block font-bold mb-2'}>Workflow runs</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
@ -456,4 +451,4 @@ Matter_typesView.getLayout = function getLayout(page: ReactElement) {
)
}
export default Matter_typesView;
export default Matter_typesView;

View File

@ -133,10 +133,10 @@ const EditRoles_catalog = () => {
return (
<>
<Head>
<title>{getPageTitle('Edit roles_catalog')}</title>
<title>{getPageTitle('Edit governance role')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit roles_catalog'} main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit governance role'} main>
{''}
</SectionTitleLineWithButton>
<CardBox>
@ -150,11 +150,11 @@ const EditRoles_catalog = () => {
<FormField
label="RoleName"
label="Role name"
>
<Field
name="name"
placeholder="RoleName"
placeholder="e.g. AI review owner, IT security approver"
/>
</FormField>

View File

@ -130,10 +130,10 @@ const EditRoles_catalogPage = () => {
return (
<>
<Head>
<title>{getPageTitle('Edit roles_catalog')}</title>
<title>{getPageTitle('Edit governance role')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit roles_catalog'} main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit governance role'} main>
{''}
</SectionTitleLineWithButton>
<CardBox>
@ -147,11 +147,11 @@ const EditRoles_catalogPage = () => {
<FormField
label="RoleName"
label="Role name"
>
<Field
name="name"
placeholder="RoleName"
placeholder="e.g. AI review owner, IT security approver"
/>
</FormField>

View File

@ -6,11 +6,11 @@ import CardBox from '../../components/CardBox'
import LayoutAuthenticated from '../../layouts/Authenticated'
import SectionMain from '../../components/SectionMain'
import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
import LegalOpsPageIntro from '../../components/LegalOpsPageIntro'
import { getPageTitle } from '../../config'
import TableRoles_catalog from '../../components/Roles_catalog/TableRoles_catalog'
import BaseButton from '../../components/BaseButton'
import axios from "axios";
import Link from "next/link";
import {useAppDispatch, useAppSelector} from "../../stores/hooks";
import CardBoxModal from "../../components/CardBoxModal";
import DragDropFilePicker from "../../components/DragDropFilePicker";
@ -34,7 +34,7 @@ const Roles_catalogTablesPage = () => {
const dispatch = useAppDispatch();
const [filters] = useState([{label: 'RoleName', title: 'name'},{label: 'Description', title: 'description'},
const [filters] = useState([{label: 'Role name', title: 'name'},{label: 'Description', title: 'description'},
@ -86,27 +86,35 @@ const Roles_catalogTablesPage = () => {
return (
<>
<Head>
<title>{getPageTitle('Roles_catalog')}</title>
<title>{getPageTitle('Roles catalog')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Roles_catalog" main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Roles catalog" main>
{''}
</SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
<LegalOpsPageIntro
eyebrow='Governance ownership'
title='Define accountable roles for AI approvals and oversight'
description='Maintain the role catalog that describes who can approve use cases, review AI outputs, own vendors, and monitor compliance workflows.'
metrics={[
{ label: 'Ownership', value: 'Named role', helper: 'Clear roles keep AI approvals and escalations accountable.' },
{ label: 'Workflow fit', value: 'Approval paths', helper: 'Requests can be routed through the right legal, IT, risk, or business owners.' },
{ label: 'Audit posture', value: 'Defensible record', helper: 'Role definitions make governance decisions easier to explain.' },
]}
>
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/roles_catalog/roles_catalog-new'} color='info' label='New Item'/>}
{hasCreatePermission && <BaseButton href={'/roles_catalog/roles_catalog-new'} color='info' label='New role'/>}
<BaseButton
className={'mr-3'}
color='info'
label='Filter'
label='Add filter'
onClick={addFilter}
/>
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getRoles_catalogCSV} />
<BaseButton color='whiteDark' label='Export CSV' onClick={getRoles_catalogCSV} />
{hasCreatePermission && (
<BaseButton
color='info'
color='whiteDark'
label='Upload CSV'
onClick={() => setIsModalActive(true)}
/>
@ -116,11 +124,9 @@ const Roles_catalogTablesPage = () => {
<div id='delete-rows-button'></div>
</div>
<div className='md:inline-flex items-center ms-auto'>
<Link href={'/roles_catalog/roles_catalog-table'}>Switch to Table</Link>
</div>
<BaseButton href={'/roles_catalog/roles_catalog-table'} color='whiteDark' label='Table view'/>
</CardBox>
</LegalOpsPageIntro>
<CardBox className="mb-6" hasTable>
<TableRoles_catalog

View File

@ -78,10 +78,10 @@ const Roles_catalogNew = () => {
return (
<>
<Head>
<title>{getPageTitle('New Item')}</title>
<title>{getPageTitle('New governance role')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="New Item" main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="New governance role" main>
{''}
</SectionTitleLineWithButton>
<CardBox>
@ -98,11 +98,11 @@ const Roles_catalogNew = () => {
<FormField
label="RoleName"
label="Role name"
>
<Field
name="name"
placeholder="RoleName"
placeholder="e.g. AI review owner, IT security approver"
/>
</FormField>

View File

@ -6,11 +6,11 @@ import CardBox from '../../components/CardBox'
import LayoutAuthenticated from '../../layouts/Authenticated'
import SectionMain from '../../components/SectionMain'
import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
import LegalOpsPageIntro from '../../components/LegalOpsPageIntro'
import { getPageTitle } from '../../config'
import TableRoles_catalog from '../../components/Roles_catalog/TableRoles_catalog'
import BaseButton from '../../components/BaseButton'
import axios from "axios";
import Link from "next/link";
import {useAppDispatch, useAppSelector} from "../../stores/hooks";
import CardBoxModal from "../../components/CardBoxModal";
import DragDropFilePicker from "../../components/DragDropFilePicker";
@ -34,7 +34,7 @@ const Roles_catalogTablesPage = () => {
const dispatch = useAppDispatch();
const [filters] = useState([{label: 'RoleName', title: 'name'},{label: 'Description', title: 'description'},
const [filters] = useState([{label: 'Role name', title: 'name'},{label: 'Description', title: 'description'},
@ -86,27 +86,35 @@ const Roles_catalogTablesPage = () => {
return (
<>
<Head>
<title>{getPageTitle('Roles_catalog')}</title>
<title>{getPageTitle('Roles catalog table')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Roles_catalog" main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Roles catalog table" main>
{''}
</SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
<LegalOpsPageIntro
eyebrow='Governance ownership'
title='Roles catalog as an editable governance table'
description='Use table view to scan and update the role definitions that support AI approval routing, review ownership, and compliance accountability.'
metrics={[
{ label: 'View mode', value: 'Table', helper: 'Best for quick role cleanup and CSV-quality review.' },
{ label: 'Ownership', value: 'Role name', helper: 'Role names give workflow approvals a clear accountable owner.' },
{ label: 'Audit posture', value: 'Documented', helper: 'Descriptions explain why each role exists in governance workflows.' },
]}
>
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/roles_catalog/roles_catalog-new'} color='info' label='New Item'/>}
{hasCreatePermission && <BaseButton href={'/roles_catalog/roles_catalog-new'} color='info' label='New role'/>}
<BaseButton
className={'mr-3'}
color='info'
label='Filter'
label='Add filter'
onClick={addFilter}
/>
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getRoles_catalogCSV} />
<BaseButton color='whiteDark' label='Export CSV' onClick={getRoles_catalogCSV} />
{hasCreatePermission && (
<BaseButton
color='info'
color='whiteDark'
label='Upload CSV'
onClick={() => setIsModalActive(true)}
/>
@ -114,13 +122,9 @@ const Roles_catalogTablesPage = () => {
<div className='md:inline-flex items-center ms-auto'>
<div id='delete-rows-button'></div>
<Link href={'/roles_catalog/roles_catalog-list'}>
Back to <span className='capitalize'>list</span>
</Link>
</div>
</CardBox>
<BaseButton href={'/roles_catalog/roles_catalog-list'} color='whiteDark' label='Card view'/>
</LegalOpsPageIntro>
<CardBox className="mb-6" hasTable>
<TableRoles_catalog
filterItems={filterItems}

View File

@ -29,11 +29,6 @@ const Roles_catalogView = () => {
const { id } = router.query;
function removeLastCharacter(str) {
console.log(str,`str`)
return str.slice(0, -1);
}
useEffect(() => {
dispatch(fetch({ id }));
}, [dispatch, id]);
@ -42,10 +37,10 @@ const Roles_catalogView = () => {
return (
<>
<Head>
<title>{getPageTitle('View roles_catalog')}</title>
<title>{getPageTitle('Governance role details')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View roles_catalog')} main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Governance role details" main>
<BaseButton
color='info'
label='Edit'
@ -57,7 +52,7 @@ const Roles_catalogView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>RoleName</p>
<p className={'block font-bold mb-2'}>Role name</p>
<p>{roles_catalog?.name}</p>
</div>
@ -90,7 +85,7 @@ const Roles_catalogView = () => {
<FormField label='Multi Text' hasTextareaHeight>
<FormField label='Description' hasTextareaHeight>
<textarea className={'w-full'} disabled value={roles_catalog?.description} />
</FormField>
@ -132,7 +127,7 @@ const Roles_catalogView = () => {
<>
<p className={'block font-bold mb-2'}>Human_review_checklists RequiredReviewerRole</p>
<p className={'block font-bold mb-2'}>Human review checklists</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
@ -291,4 +286,4 @@ Roles_catalogView.getLayout = function getLayout(page: ReactElement) {
)
}
export default Roles_catalogView;
export default Roles_catalogView;

View File

@ -56,31 +56,68 @@ export const white: StyleObject = {
export const dataGridStyles = {
'& .MuiDataGrid-cell': {
paddingX: 3,
alignItems: 'center',
borderColor: '#E5E0D6',
color: '#374151',
display: 'flex',
fontSize: '0.9rem',
lineHeight: 1.25,
padding: '8px 18px',
whiteSpace: 'nowrap',
},
'& .MuiDataGrid-columnHeader': {
paddingX: 3,
minHeight: '58px !important',
padding: '10px 18px',
color: '#0E1A2B',
fontWeight: 700,
},
'& .MuiDataGrid-columnHeaderCheckbox': {
paddingX: 0,
paddingX: 1.5,
},
'& .MuiDataGrid-columnHeaders': {
paddingY: 4,
minHeight: '58px !important',
maxHeight: 'unset !important',
borderStartStartRadius: 7,
borderStartEndRadius: 7,
backgroundColor: '#FBF8F1',
borderColor: '#DDD5C7',
},
'& .MuiDataGrid-columnHeaderTitle': {
color: '#0E1A2B',
fontSize: '0.72rem',
fontWeight: 800,
letterSpacing: '0.07em',
lineHeight: 1.15,
overflow: 'visible',
textOverflow: 'clip',
textTransform: 'uppercase',
whiteSpace: 'normal',
wordBreak: 'normal',
},
'& .MuiDataGrid-columnHeaderTitleContainer': {
overflow: 'visible',
whiteSpace: 'normal',
},
'& .MuiDataGrid-columnHeaderTitleContainerContent': {
minWidth: 0,
overflow: 'visible',
},
'& .MuiDataGrid-cellContent': {
display: 'block',
lineHeight: 1.25,
maxWidth: '100%',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
wordBreak: 'normal',
},
'& .MuiDataGrid-footerContainer': {
paddingY: 0.5,
borderEndStartRadius: 7,
borderEndEndRadius: 7,
borderColor: '#DDD5C7',
backgroundColor: '#FBF8F1',
minHeight: '60px',
},
'& .MuiDataGrid-root': {
border: '1px solid #DDD5C7',
@ -88,9 +125,27 @@ export const dataGridStyles = {
overflow: 'hidden',
backgroundColor: '#FFFFFF',
},
'& .MuiDataGrid-row': {
borderColor: '#E5E0D6',
},
'& .MuiDataGrid-row.Mui-selected': {
backgroundColor: '#FFF3C9',
},
'& .MuiDataGrid-row.Mui-selected:hover': {
backgroundColor: '#FFEDB1',
},
'& .MuiDataGrid-row:hover': {
backgroundColor: '#FFF8E8',
},
'& .MuiDataGrid-iconButtonContainer .MuiIconButton-root': {
color: '#7A5B13',
},
'& .MuiCheckbox-root': {
color: '#8B7A61',
},
'& .MuiCheckbox-root.Mui-checked': {
color: '#7A5B13',
},
};
export const basic: StyleObject = {