parent
5846e92924
commit
3c0f3a7001
web/src/app
@ -52,7 +52,7 @@ function LeaveAComment() {
|
||||
)
|
||||
}
|
||||
|
||||
export default function Comments(stats: CommentersProps) {
|
||||
export function Comments(stats: CommentersProps) {
|
||||
return (<>
|
||||
<section className="comments">
|
||||
{stats.comments_data.comments.length===0
|
||||
@ -66,5 +66,6 @@ export default function Comments(stats: CommentersProps) {
|
||||
}
|
||||
|
||||
export {
|
||||
type CreatorAndReviewStatus
|
||||
type CreatorAndReviewStatus,
|
||||
type Comment,
|
||||
}
|
||||
|
@ -5,7 +5,8 @@ import type { CreatorAndReviewStatus } from "./_comments";
|
||||
import { MapImage } from "./_mapImage";
|
||||
import { useParams } from "next/navigation";
|
||||
import ReviewButtons from "./_reviewButtons";
|
||||
import Comments from "./_comments";
|
||||
import { Comments, Comment } from "./_comments";
|
||||
import { AuditEvent, decodeAuditEvent } from "@/app/ts/AuditEvent";
|
||||
import Webpage from "@/app/_components/webpage";
|
||||
import Link from "next/link";
|
||||
import { useState, useEffect } from "react";
|
||||
@ -62,19 +63,35 @@ function TitleAndComments(stats: CreatorAndReviewStatus) {
|
||||
}
|
||||
|
||||
export default function MapfixInfoPage() {
|
||||
const dynamicId = useParams<{mapfixId: string}>()
|
||||
const { mapfixId } = useParams < { mapfixId: string } >()
|
||||
|
||||
const [mapfix, setMapfix] = useState<MapfixInfo | null>(null)
|
||||
const [auditEvents, setAuditEvents] = useState<AuditEvent[]>([])
|
||||
|
||||
useEffect(() => { // needs to be client sided since server doesn't have a session, nextjs got mad at me for exporting an async function: (https://nextjs.org/docs/messages/no-async-client-component)
|
||||
async function getMapfix() {
|
||||
const res = await fetch(`/api/mapfixes/${dynamicId.mapfixId}`)
|
||||
const res = await fetch(`/api/mapfixes/${mapfixId}`)
|
||||
if (res.ok) {
|
||||
setMapfix(await res.json())
|
||||
}
|
||||
}
|
||||
getMapfix()
|
||||
}, [dynamicId.mapfixId])
|
||||
async function getAuditEvents() {
|
||||
const res = await fetch(`/api/mapfixes/${mapfixId}/audit-events?Page=1&Limit=100`)
|
||||
if (res.ok) {
|
||||
setAuditEvents(await res.json())
|
||||
}
|
||||
}
|
||||
getMapfix()
|
||||
getAuditEvents()
|
||||
}, [mapfixId])
|
||||
|
||||
const comments:Comment[] = auditEvents.map((auditEvent) => {
|
||||
return {
|
||||
date: auditEvent.created_at,
|
||||
name: auditEvent.user.toString(),
|
||||
comment: decodeAuditEvent(auditEvent).event_data.toString(),
|
||||
}
|
||||
})
|
||||
|
||||
if (!mapfix) {
|
||||
return <Webpage>
|
||||
@ -85,7 +102,7 @@ export default function MapfixInfoPage() {
|
||||
<Webpage>
|
||||
<main className="map-page-main">
|
||||
<section className="review-section">
|
||||
<RatingArea mapfixId={dynamicId.mapfixId} mapfixStatus={mapfix.StatusID} mapfixSubmitter={mapfix.Submitter} mapfixAssetId={mapfix.AssetID} mapfixTargetAssetId={mapfix.TargetAssetID} />
|
||||
<RatingArea mapfixId={mapfixId} mapfixStatus={mapfix.StatusID} mapfixSubmitter={mapfix.Submitter} mapfixAssetId={mapfix.AssetID} mapfixTargetAssetId={mapfix.TargetAssetID} />
|
||||
<TitleAndComments
|
||||
name={mapfix.DisplayName}
|
||||
creator={mapfix.Creator}
|
||||
@ -94,7 +111,7 @@ export default function MapfixInfoPage() {
|
||||
submitter={mapfix.Submitter}
|
||||
target_asset_id={mapfix.TargetAssetID}
|
||||
description={mapfix.Description}
|
||||
comments={[]}
|
||||
comments={comments}
|
||||
/>
|
||||
</section>
|
||||
</main>
|
||||
|
101
web/src/app/ts/AuditEvent.ts
Normal file
101
web/src/app/ts/AuditEvent.ts
Normal file
@ -0,0 +1,101 @@
|
||||
// Shared audit event types
|
||||
export enum AuditEventType {
|
||||
Action = 0,
|
||||
Comment = 1,
|
||||
ChangeModel = 2,
|
||||
ChangeValidatedModel = 3,
|
||||
ChangeDisplayName = 4,
|
||||
ChangeCreator = 5,
|
||||
Error = 6,
|
||||
}
|
||||
|
||||
// Discriminated union types for each event
|
||||
export type AuditEventData =
|
||||
| { event_type: AuditEventType.Action; event_data: AuditEventDataAction }
|
||||
| { event_type: AuditEventType.Comment; event_data: AuditEventDataComment }
|
||||
| { event_type: AuditEventType.ChangeModel; event_data: AuditEventDataChangeModel }
|
||||
| { event_type: AuditEventType.ChangeValidatedModel; event_data: AuditEventDataChangeValidatedModel; }
|
||||
| { event_type: AuditEventType.ChangeDisplayName; event_data: AuditEventDataChangeName; }
|
||||
| { event_type: AuditEventType.ChangeCreator; event_data: AuditEventDataChangeName; }
|
||||
| { event_type: AuditEventType.Error; event_data: AuditEventDataError };
|
||||
|
||||
// Concrete data interfaces
|
||||
export interface AuditEventDataAction {
|
||||
target_status: number;
|
||||
}
|
||||
|
||||
export interface AuditEventDataComment {
|
||||
comment: string;
|
||||
}
|
||||
|
||||
export interface AuditEventDataChangeModel {
|
||||
old_model_id: number;
|
||||
old_model_version: number;
|
||||
new_model_id: number;
|
||||
new_model_version: number;
|
||||
}
|
||||
|
||||
export interface AuditEventDataChangeValidatedModel {
|
||||
validated_model_id: number;
|
||||
validated_model_version: number;
|
||||
}
|
||||
|
||||
export interface AuditEventDataChangeName {
|
||||
old_name: string;
|
||||
new_name: string;
|
||||
}
|
||||
|
||||
export interface AuditEventDataError {
|
||||
error: string;
|
||||
}
|
||||
|
||||
// Full audit event type (mirroring the Go struct)
|
||||
export interface AuditEvent {
|
||||
id: number;
|
||||
created_at: string; // ISO string, can convert to Date if needed
|
||||
user: number;
|
||||
resource_type: string; // Assuming this is a string enum or similar
|
||||
resource_id: number;
|
||||
event_type: AuditEventType;
|
||||
event_data: unknown; // You'll decode this into a specific AuditEventData based on `event_type`
|
||||
}
|
||||
|
||||
// Optional: decode function to parse event_data into strongly-typed structure
|
||||
export function decodeAuditEvent(event: AuditEvent): AuditEventData {
|
||||
switch (event.event_type) {
|
||||
case AuditEventType.Action:
|
||||
return {
|
||||
event_type: event.event_type,
|
||||
event_data: event.event_data as AuditEventDataAction,
|
||||
};
|
||||
case AuditEventType.Comment:
|
||||
return {
|
||||
event_type: event.event_type,
|
||||
event_data: event.event_data as AuditEventDataComment,
|
||||
};
|
||||
case AuditEventType.ChangeModel:
|
||||
return {
|
||||
event_type: event.event_type,
|
||||
event_data: event.event_data as AuditEventDataChangeModel,
|
||||
};
|
||||
case AuditEventType.ChangeValidatedModel:
|
||||
return {
|
||||
event_type: event.event_type,
|
||||
event_data:
|
||||
event.event_data as AuditEventDataChangeValidatedModel,
|
||||
};
|
||||
case AuditEventType.ChangeDisplayName:
|
||||
case AuditEventType.ChangeCreator:
|
||||
return {
|
||||
event_type: event.event_type,
|
||||
event_data: event.event_data as AuditEventDataChangeName,
|
||||
};
|
||||
case AuditEventType.Error:
|
||||
return {
|
||||
event_type: event.event_type,
|
||||
event_data: event.event_data as AuditEventDataError,
|
||||
};
|
||||
default:
|
||||
throw new Error(`Unknown event_type: ${event.event_type}`);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user