remove activity timeline from detail view; double-refetch RV after submit

This commit is contained in:
Bhanu Prakash Sai Potteri 2026-06-02 20:08:58 +05:30
parent 1ec2b02192
commit 7ad50785cc

View File

@ -1,13 +1,13 @@
import { useEffect, useState, useCallback } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { Loader2, CheckCircle2, XCircle, PauseCircle, MessageSquare, Clock } from "lucide-react";
import { Loader2, CheckCircle2, XCircle, PauseCircle, MessageSquare } from "lucide-react";
import DynamicHeader from "./DynamicHeader";
import DashboardStats from "./DashboardStats";
import ScreenRenderer from "./ScreenRenderer";
import { TableSkeleton } from "./Skeleton";
import DetailViewPanel from "./DetailViewPanel";
import FormModal from "./FormModal";
import { getHeaderConfig, getScreen, getAuditLog, getInstance, type LayoutElement, type NavItem, type AuditEntry } from "../api/viewService";
import { getHeaderConfig, getScreen, getInstance, type LayoutElement, type NavItem } from "../api/viewService";
import { WORKFLOW_ID, ACTIVITY_IDS, STATE_IDS, SCREEN_UUIDS, RDBMS_RV_SCREEN_UUID, RDBMS_DV_SCREEN_UUID } from "../config";
import RecordViewTable from "./RecordViewTable";
@ -64,7 +64,6 @@ export default function AppShell() {
const [refreshKey, setRefreshKey] = useState(0);
const [formModal, setFormModal] = useState<{ activityId: string; instanceId: string; title: string } | null>(null);
const [instanceState, setInstanceState] = useState<string | null>(null);
const [audit, setAudit] = useState<AuditEntry[]>([]);
const [sidebarOpen, setSidebarOpen] = useState(true);
const [navItems, setNavItems] = useState<NavItem[]>([]);
@ -92,7 +91,6 @@ export default function AppShell() {
setDetailViewId(null);
setDetailScreenLayout(null);
setInstanceState(null);
setAudit([]);
} else if (params.instanceId && params.instanceId !== detailInstanceId) {
setDetailInstanceId(params.instanceId);
const sid = params.screenId ?? activeScreenId;
@ -119,18 +117,17 @@ export default function AppShell() {
.catch(() => setDetailScreenLayout(null));
}, [detailViewId]);
// Load instance state + audit
// Load instance state
useEffect(() => {
if (!detailInstanceId) return;
getInstance(WORKFLOW_ID, detailInstanceId)
.then((inst) => setInstanceState(inst.current_state_id))
.catch(() => {});
getAuditLog(detailInstanceId).then(setAudit).catch(() => setAudit([]));
}, [detailInstanceId]);
const handleNavigate = useCallback((id: string) => {
setActiveScreenId(id); setDetailInstanceId(null); setDetailViewId(null);
setDetailScreenLayout(null); setInstanceState(null); setAudit([]);
setDetailScreenLayout(null); setInstanceState(null);
if (RDBMS_SCREENS[id]) setLayout([]);
navigate(`/screen/${id}`);
}, [navigate]);
@ -144,7 +141,7 @@ export default function AppShell() {
const handleBack = () => {
setDetailInstanceId(null); setDetailViewId(null); setDetailScreenLayout(null);
setInstanceState(null); setAudit([]);
setInstanceState(null);
navigate(`/screen/${activeScreenId}`);
};
@ -152,7 +149,6 @@ export default function AppShell() {
setFormModal(null);
if (detailInstanceId) {
const v = detailViewId; setDetailViewId(null); setTimeout(() => setDetailViewId(v), 50);
getAuditLog(detailInstanceId).then(setAudit).catch(() => {});
}
};
@ -215,64 +211,6 @@ export default function AppShell() {
</div>
{detailScreenLayout ? <ScreenRenderer layout={detailScreenLayout} instanceId={detailInstanceId} /> : <DetailViewPanel viewId={detailViewId} instanceId={detailInstanceId} />}
{audit.length > 0 && (
<div className="bg-white dark:bg-zinc-900 rounded-2xl border border-slate-200/80 dark:border-zinc-700/60 overflow-hidden">
<div className="px-5 py-3 border-b border-slate-100 dark:border-zinc-800 flex items-center gap-2.5">
<div className="w-6 h-6 rounded-lg flex items-center justify-center"
style={{ background: "rgba(124, 58, 237, 0.1)" }}>
<Clock size={13} className="text-violet-600 dark:text-violet-400" />
</div>
<h3 className="text-[13px] font-semibold text-slate-700 dark:text-zinc-200">Activity Timeline</h3>
<span className="text-[11px] text-slate-300 dark:text-zinc-600 font-medium">{audit.length} events</span>
</div>
<div className="px-5 py-4">
<div className="relative pl-6">
<div className="absolute left-[7px] top-2 bottom-2 w-px"
style={{ background: "linear-gradient(to bottom, #7c3aed40, #a855f720, transparent)" }} />
<div className="space-y-4">
{audit.map((e, i) => {
const isFirst = i === 0;
const isLast = i === audit.length - 1;
return (
<div key={e.id} className="flex items-start gap-3 relative">
<div
className={`absolute -left-6 w-3.5 h-3.5 rounded-full border-2 border-white dark:border-zinc-900 mt-0.5 shadow-sm ${
isLast
? "ring-2 ring-violet-200 dark:ring-violet-900"
: isFirst
? ""
: ""
}`}
style={{
background: isLast ? "#7c3aed" : isFirst ? "#10b981" : "#d1d5db",
boxShadow: isLast ? "0 0 8px rgba(124, 58, 237, 0.5)" : undefined,
}}
/>
<div className="flex-1 py-0.5">
<div className="flex items-center gap-2">
<span className={`text-[13px] font-medium ${isLast ? "text-violet-700 dark:text-violet-300" : "text-slate-700 dark:text-zinc-200"}`}>
{fmtAct(e.activity_id)}
</span>
{isLast && (
<span className="text-[10px] font-semibold px-1.5 py-0.5 rounded-full"
style={{ background: "rgba(124, 58, 237, 0.1)", color: "#7c3aed" }}>
Latest
</span>
)}
</div>
<span className="text-[11px] text-slate-400 dark:text-zinc-500">
{new Date(e.created_at).toLocaleString("en-IN", { day: "2-digit", month: "short", hour: "2-digit", minute: "2-digit" })}
</span>
</div>
</div>
);
})}
</div>
</div>
</div>
</div>
)}
</div>
) : loading ? (
<><DashboardStats /><TableSkeleton rows={6} cols={6} /></>
@ -287,7 +225,7 @@ export default function AppShell() {
} : undefined}
/>
) : layout.length > 0 ? (
<><DashboardStats key={`stats-${activeScreenId}`} /><ScreenRenderer key={`screen-${activeScreenId}-${refreshKey}`} layout={layout} onRowClick={handleRowClick} onRefresh={() => setRefreshKey((k) => k + 1)} /></>
<><DashboardStats key={`stats-${activeScreenId}-${refreshKey}`} /><ScreenRenderer key={`screen-${activeScreenId}-${refreshKey}`} layout={layout} onRowClick={handleRowClick} onRefresh={() => { setRefreshKey((k) => k + 1); setTimeout(() => setRefreshKey((k) => k + 1), 2500); }} /></>
) : (
<div className="text-center py-20 text-sm text-slate-400 dark:text-zinc-600">Select a screen from the navigation</div>
)}