diff --git a/apps/explorer/src/pages/trust-framework/audit-trail-result/AuditTrailContent.tsx b/apps/explorer/src/pages/trust-framework/audit-trail-result/AuditTrailContent.tsx index 740f417c7e..d5964d469b 100644 --- a/apps/explorer/src/pages/trust-framework/audit-trail-result/AuditTrailContent.tsx +++ b/apps/explorer/src/pages/trust-framework/audit-trail-result/AuditTrailContent.tsx @@ -21,6 +21,7 @@ import { TransactionsView } from '../common/TransactionsView'; import { AuditTrailSummaryView } from './views/AuditTrailSummaryView'; import { MetadataView } from './views/MetadataView'; import { LockLifecycleView } from './views/lock-lifecycle/LockLifecycleView'; +import { RolesView } from './views/roles/RolesView'; import { TagsView } from './views/TagsView'; import { RecordsView } from './views/RecordsView'; import { SideBySidePanels } from '~/components/ui/SideBySidePanels'; @@ -127,7 +128,7 @@ export function AuditTrailContent({ objectId }: AuditTrailContentProps) { Replace by RolesView

} + firstPanel={} secondPanel={} /> diff --git a/apps/explorer/src/pages/trust-framework/audit-trail-result/views/roles/RolesView.tsx b/apps/explorer/src/pages/trust-framework/audit-trail-result/views/roles/RolesView.tsx new file mode 100644 index 0000000000..1a0aef0eb6 --- /dev/null +++ b/apps/explorer/src/pages/trust-framework/audit-trail-result/views/roles/RolesView.tsx @@ -0,0 +1,93 @@ +// Copyright (c) 2026 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import { type ColumnDef } from '@tanstack/react-table'; +import { TableCard } from '../../../../../components/ui/TableCard'; +import { getPermissionName } from './helper'; +import { type RolePermissionsEntry, type RoleTags } from '@iota/audit-trail'; +import { + TableCellBase, + TableCellText, + Title, + Panel, + InfoBox, + InfoBoxType, + InfoBoxStyle, +} from '@iota/apps-ui-kit'; +import { Info } from '@iota/apps-ui-icons'; + +interface RolesCardProps { + roles: RolePermissionsEntry[]; +} + +export function RolesView({ roles }: RolesCardProps) { + return ( + +
+ + <div className="flex flex-col gap-sm"> + {roles.length === 0 ? ( + <InfoBox + title="No roles found" + supportingText="This audit trail has no roles configured." + type={InfoBoxType.Default} + style={InfoBoxStyle.Elevated} + icon={<Info />} + /> + ) : ( + <TableCard + data={roles} + columns={generateRolesColumns()} + defaultSorting={[{ id: 'role', desc: false }]} + /> + )} + </div> + </div> + </Panel> + ); +} + +export function generateRolesColumns(): ColumnDef<RolePermissionsEntry>[] { + return [ + { + header: 'Role Name', + accessorKey: 'name', + cell: ({ getValue }) => { + const role = getValue<string>(); + return ( + <TableCellBase> + <TableCellText>{role}</TableCellText> + </TableCellBase> + ); + }, + }, + { + header: 'Permissions', + accessorKey: 'permissions', + cell: ({ getValue }) => { + const permissions = getValue<number[]>() + .map((p: number) => getPermissionName(p)) + .join(', '); + return ( + <TableCellBase> + <TableCellText>{permissions}</TableCellText> + </TableCellBase> + ); + }, + }, + { + header: 'Tags', + accessorKey: 'roleTags', + cell: ({ getValue }) => { + const roleTags = getValue<RoleTags>(); + const tags = !roleTags ? 'N/A' : roleTags.tags.join(', '); + return ( + <TableCellBase> + <TableCellText>{tags}</TableCellText> + </TableCellBase> + ); + }, + }, + // Note: A column for Tags will be added here in a subsequent step. + ]; +} diff --git a/apps/explorer/src/pages/trust-framework/audit-trail-result/views/roles/helper.ts b/apps/explorer/src/pages/trust-framework/audit-trail-result/views/roles/helper.ts new file mode 100644 index 0000000000..48a7950bc1 --- /dev/null +++ b/apps/explorer/src/pages/trust-framework/audit-trail-result/views/roles/helper.ts @@ -0,0 +1,30 @@ +// Copyright (c) 2026 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import { Permission } from '@iota/audit-trail'; + +export const permissionMap = new Map<number, string>([ + [Permission.DeleteAuditTrail, 'DeleteAuditTrail'], + [Permission.DeleteAllRecords, 'DeleteAllRecords'], + [Permission.AddRecord, 'AddRecord'], + [Permission.DeleteRecord, 'DeleteRecord'], + [Permission.CorrectRecord, 'CorrectRecord'], + [Permission.UpdateLockingConfig, 'UpdateLockingConfig'], + [Permission.UpdateLockingConfigForDeleteRecord, 'UpdateLockingConfigForDeleteRecord'], + [Permission.UpdateLockingConfigForDeleteTrail, 'UpdateLockingConfigForDeleteTrail'], + [Permission.UpdateLockingConfigForWrite, 'UpdateLockingConfigForWrite'], + [Permission.AddRoles, 'AddRoles'], + [Permission.UpdateRoles, 'UpdateRoles'], + [Permission.DeleteRoles, 'DeleteRoles'], + [Permission.AddCapabilities, 'AddCapabilities'], + [Permission.RevokeCapabilities, 'RevokeCapabilities'], + [Permission.UpdateMetadata, 'UpdateMetadata'], + [Permission.DeleteMetadata, 'DeleteMetadata'], + [Permission.Migrate, 'Migrate'], + [Permission.AddRecordTags, 'AddRecordTags'], + [Permission.DeleteRecordTags, 'DeleteRecordTags'], +]); + +export function getPermissionName(code: number): string { + return permissionMap.get(code) ?? 'UnknownPermission'; +}