AuditLogDetail kısmı çalışmıyordu düzeltildi.

This commit is contained in:
Sedat Öztürk 2026-05-25 21:30:08 +03:00
parent 0f5d44ceb0
commit d50c62cd1c
6 changed files with 142 additions and 66 deletions

View file

@ -5,11 +5,11 @@ namespace Sozsoft.Platform.AuditLogs;
public class AuditLogActionDto : EntityDto<Guid>
{
public virtual Guid AuditLogId { get; protected set; }
public virtual string ServiceName { get; protected set; }
public virtual string MethodName { get; protected set; }
public virtual string Parameters { get; protected set; }
public virtual DateTime ExecutionTime { get; protected set; }
public virtual int ExecutionDuration { get; protected set; }
public virtual Guid AuditLogId { get; set; }
public virtual string ServiceName { get; set; }
public virtual string MethodName { get; set; }
public virtual string Parameters { get; set; }
public virtual DateTime ExecutionTime { get; set; }
public virtual int ExecutionDuration { get; set; }
}

View file

@ -13,24 +13,24 @@ public class AuditLogDto : EntityDto<Guid>
}
public string ApplicationName { get; set; }
public Guid? UserId { get; protected set; }
public string UserName { get; protected set; }
public Guid? TenantId { get; protected set; }
public string TenantName { get; protected set; }
public DateTime ExecutionTime { get; protected set; }
public int ExecutionDuration { get; protected set; }
public string ClientIpAddress { get; protected set; }
public string ClientName { get; protected set; }
public Guid? UserId { get; set; }
public string UserName { get; set; }
public Guid? TenantId { get; set; }
public string TenantName { get; set; }
public DateTime ExecutionTime { get; set; }
public int ExecutionDuration { get; set; }
public string ClientIpAddress { get; set; }
public string ClientName { get; set; }
public string ClientId { get; set; }
public string CorrelationId { get; set; }
public string BrowserInfo { get; protected set; }
public string HttpMethod { get; protected set; }
public string Url { get; protected set; }
public string Exceptions { get; protected set; }
public string Comments { get; protected set; }
public string BrowserInfo { get; set; }
public string HttpMethod { get; set; }
public string Url { get; set; }
public string Exceptions { get; set; }
public string Comments { get; set; }
public int? HttpStatusCode { get; set; }
public ICollection<EntityChangeDto> EntityChanges { get; protected set; }
public ICollection<AuditLogActionDto> Actions { get; protected set; }
public ICollection<EntityChangeDto> EntityChanges { get; set; }
public ICollection<AuditLogActionDto> Actions { get; set; }
public int? EntityChangeCount { get; set; }

View file

@ -12,12 +12,12 @@ public class EntityChangeDto : EntityDto<Guid>
PropertyChanges = new List<EntityPropertyChangeDto>();
}
public virtual Guid AuditLogId { get; protected set; }
public virtual DateTime ChangeTime { get; protected set; }
public virtual EntityChangeType ChangeType { get; protected set; }
public virtual Guid? EntityTenantId { get; protected set; }
public virtual string EntityId { get; protected set; }
public virtual string EntityTypeFullName { get; protected set; }
public virtual ICollection<EntityPropertyChangeDto> PropertyChanges { get; protected set; }
public virtual Guid AuditLogId { get; set; }
public virtual DateTime ChangeTime { get; set; }
public virtual EntityChangeType ChangeType { get; set; }
public virtual Guid? EntityTenantId { get; set; }
public virtual string EntityId { get; set; }
public virtual string EntityTypeFullName { get; set; }
public virtual ICollection<EntityPropertyChangeDto> PropertyChanges { get; set; }
}

View file

@ -5,10 +5,10 @@ namespace Sozsoft.Platform.AuditLogs;
public class EntityPropertyChangeDto : EntityDto<Guid>
{
public virtual Guid EntityChangeId { get; protected set; }
public virtual string NewValue { get; protected set; }
public virtual string OriginalValue { get; protected set; }
public virtual string PropertyName { get; protected set; }
public virtual string PropertyTypeFullName { get; protected set; }
public virtual Guid EntityChangeId { get; set; }
public virtual string NewValue { get; set; }
public virtual string OriginalValue { get; set; }
public virtual string PropertyName { get; set; }
public virtual string PropertyTypeFullName { get; set; }
}

View file

@ -1,4 +1,6 @@
export interface AuditLogActionDto {
id: string
auditLogId: string
serviceName: string
methodName: string
executionTime: string // Date string
@ -7,6 +9,8 @@ export interface AuditLogActionDto {
}
export interface EntityPropertyChangeDto {
id: string
entityChangeId: string
propertyName: string
propertyTypeFullName: string
originalValue: string | null
@ -14,8 +18,11 @@ export interface EntityPropertyChangeDto {
}
export interface EntityChangeDto {
id: string
auditLogId: string
changeTime: string // Date string
changeType: number
entityTenantId?: string
entityId: string
entityTypeFullName: string
propertyChanges: EntityPropertyChangeDto[]

View file

@ -69,10 +69,40 @@ function AuditLogs({
}
const formatDuration = (ms: number) => {
if (ms === undefined || ms === null) return 'Unknown'
if (ms < 1000) return `${ms}ms`
return `${(ms / 1000).toFixed(2)}s`
}
const formatDateTime = (value?: string) => {
if (!value) return 'Unknown'
const date = new Date(value)
if (Number.isNaN(date.getTime()) || date.getFullYear() <= 1) return 'Unknown'
return date.toLocaleString('tr-TR', {
day: '2-digit',
month: '2-digit',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
})
}
const formatValue = (value?: string | number | null) => {
if (value === undefined || value === null || value === '') return 'Unknown'
return value
}
const formatJson = (value: string) => {
try {
return JSON.stringify(JSON.parse(value), null, 2)
} catch {
return value
}
}
const InfoRow = ({ icon: Icon, label, value, valueClassName = '' }: any) => (
<div className="flex items-start gap-3 py-2 border-b border-gray-100 last:border-0">
<Icon className="w-5 h-5 text-gray-400 mt-0.5 flex-shrink-0" />
@ -86,7 +116,7 @@ function AuditLogs({
return (
<Dialog width="90%" isOpen={open} onClose={onDialogClose} onRequestClose={onDialogClose}>
{/* Header */}
<div className="flex items-center justify-between mb-6 pb-4 border-b border-gray-200 dark:border-gray-700">
<div className="flex items-center justify-between mb-2 pb-2 border-b border-gray-200 dark:border-gray-700">
<div>
<h4 className="text-xl font-bold text-gray-800 dark:text-gray-100">Audit Log Details</h4>
{selectedLog?.id && <p className="text-sm text-gray-500 dark:text-gray-400 mt-1">ID: {selectedLog.id}</p>}
@ -113,7 +143,7 @@ function AuditLogs({
</div>
) : (
<Tabs defaultValue="log" variant="pill">
<TabList className="mb-6 bg-gray-50 dark:bg-gray-800 p-1 rounded-lg">
<TabList className="mb-2 bg-gray-50 dark:bg-gray-800 p-1 rounded-lg">
<TabNav value="log">
<FaRegFileAlt className="w-4 h-4 mr-2" />
<span className="text-gray-700 dark:text-gray-200">Overview</span>
@ -145,7 +175,7 @@ function AuditLogs({
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{/* Request Information */}
<AdaptableCard className="shadow-sm dark:bg-gray-900 dark:border-gray-700">
<h6 className="font-semibold text-gray-700 dark:text-gray-200 mb-4 flex items-center gap-2">
<h6 className="font-semibold text-gray-700 dark:text-gray-200 mb-2 flex items-center gap-2">
<FaGlobe className="w-5 h-5 text-blue-500 dark:text-blue-400" />
Request Information
</h6>
@ -153,20 +183,13 @@ function AuditLogs({
<InfoRow
icon={FaUser}
label="User"
value={selectedLog.userName || 'Anonymous'}
value={selectedLog.userName || selectedLog.userId || 'Anonymous'}
valueClassName="font-medium text-gray-800 dark:text-gray-100"
/>
<InfoRow
icon={FaRegClock}
label="Execution Time"
value={new Date(selectedLog.executionTime).toLocaleString('tr-TR', {
day: '2-digit',
month: '2-digit',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
})}
value={formatDateTime(selectedLog.executionTime)}
/>
<InfoRow
icon={FaRegClock}
@ -181,14 +204,33 @@ function AuditLogs({
<InfoRow
icon={FaGlobe}
label="Client IP"
value={selectedLog.clientIpAddress || 'Unknown'}
value={formatValue(selectedLog.clientIpAddress)}
/>
<InfoRow
icon={FaRegFileAlt}
label="Client Name"
value={formatValue(selectedLog.clientName)}
/>
<InfoRow
icon={FaRegFileAlt}
label="Client ID"
value={formatValue(selectedLog.clientId)}
/>
<InfoRow
icon={FaUser}
label="Tenant"
value={
selectedLog.tenantName ||
selectedLog.tenantId ||
'Host'
}
/>
</div>
</AdaptableCard>
{/* HTTP Details */}
<AdaptableCard className="shadow-sm dark:bg-gray-900 dark:border-gray-700">
<h6 className="font-semibold text-gray-700 dark:text-gray-200 mb-4 flex items-center gap-2">
<h6 className="font-semibold text-gray-700 dark:text-gray-200 mb-2 flex items-center gap-2">
<FaCode className="w-5 h-5 text-green-500 dark:text-green-400" />
HTTP Details
</h6>
@ -197,20 +239,24 @@ function AuditLogs({
icon={FaCode}
label="Method"
value={
<Badge
className={
selectedLog.httpMethod === 'POST'
? 'bg-blue-500'
: selectedLog.httpMethod === 'GET'
? 'bg-green-500'
: selectedLog.httpMethod === 'PUT'
? 'bg-yellow-500'
: selectedLog.httpMethod === 'DELETE'
? 'bg-red-500'
: 'bg-gray-500'
}
content={selectedLog.httpMethod}
></Badge>
selectedLog.httpMethod ? (
<Badge
className={
selectedLog.httpMethod === 'POST'
? 'bg-blue-500'
: selectedLog.httpMethod === 'GET'
? 'bg-green-500'
: selectedLog.httpMethod === 'PUT'
? 'bg-yellow-500'
: selectedLog.httpMethod === 'DELETE'
? 'bg-red-500'
: 'bg-gray-500'
}
content={selectedLog.httpMethod}
></Badge>
) : (
'Unknown'
)
}
/>
<InfoRow
@ -221,7 +267,7 @@ function AuditLogs({
<InfoRow
icon={FaGlobe}
label="URL"
value={selectedLog.url}
value={formatValue(selectedLog.url)}
valueClassName="text-blue-600 dark:text-blue-400 font-mono text-xs"
/>
<InfoRow
@ -233,6 +279,12 @@ function AuditLogs({
</span>
}
/>
<InfoRow
icon={FaRegFileAlt}
label="Correlation ID"
value={formatValue(selectedLog.correlationId)}
valueClassName="font-mono text-xs"
/>
</div>
</AdaptableCard>
@ -291,13 +343,25 @@ function AuditLogs({
<div>
<p className="text-xs text-gray-500 dark:text-gray-400 mb-1">Service Name</p>
<p className="text-sm font-mono text-gray-700 dark:text-gray-200 break-all">
{action.serviceName}
{formatValue(action.serviceName)}
</p>
</div>
<div>
<p className="text-xs text-gray-500 dark:text-gray-400 mb-1">Method Name</p>
<p className="text-sm font-mono text-gray-700 dark:text-gray-200 break-all">
{formatValue(action.methodName)}
</p>
</div>
<div>
<p className="text-xs text-gray-500 dark:text-gray-400 mb-1">Execution Time</p>
<p className="text-sm text-gray-700 dark:text-gray-200">
{new Date(action.executionTime).toLocaleString('tr-TR')}
{formatDateTime(action.executionTime)}
</p>
</div>
<div>
<p className="text-xs text-gray-500 dark:text-gray-400 mb-1">Action ID</p>
<p className="text-sm font-mono text-gray-700 dark:text-gray-200 break-all">
{formatValue(action.id)}
</p>
</div>
</div>
@ -306,7 +370,7 @@ function AuditLogs({
<div>
<p className="text-xs text-gray-500 dark:text-gray-400 mb-2">Parameters</p>
<pre className="bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 p-3 rounded-lg text-xs overflow-x-auto text-gray-700 dark:text-gray-200">
{JSON.stringify(JSON.parse(action.parameters), null, 2)}
{formatJson(action.parameters)}
</pre>
</div>
)}
@ -338,12 +402,17 @@ function AuditLogs({
{change.entityTypeFullName}
</h6>
<p className="text-xs text-gray-500 dark:text-gray-400">ID: {change.entityId}</p>
{change.entityTenantId && (
<p className="text-xs text-gray-500 dark:text-gray-400">
Tenant ID: {change.entityTenantId}
</p>
)}
</div>
</div>
<div className="flex items-center gap-2">
{getChangeTypeBadge(change.changeType)}
<span className="text-xs text-gray-500 dark:text-gray-400">
{new Date(change.changeTime).toLocaleTimeString('tr-TR')}
{formatDateTime(change.changeTime)}
</span>
</div>
</div>