Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash details: make change log collapsible #1655

Merged
merged 4 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 68 additions & 50 deletions app/components/ChangeLog.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { useMemo, useState } from "react";
import Card from "react-bootstrap/Card";
import Table from "react-bootstrap/Table";
import Accordion from "react-bootstrap/Accordion";
import { formatDateTime } from "@/utils/formatters";
import ChangeLogDetails from "./ChangeLogDetails";
import ChangeLogDetails from "@/components/ChangeLogDetails";
import {
ChangeLogEntry,
ChangeLogDiff,
ChangeLogEntryEnriched,
} from "@/types/changeLog";

// used to track the accordion expanded state of the change log
const localStorageKey = "crashHistoryCardExpandedItem";
const recordHistoryItemName = "recordHistory";

const KEYS_TO_IGNORE = ["updated_at", "updated_by", "position"];

/**
Expand Down Expand Up @@ -77,59 +81,73 @@ const isNewRecordEvent = (change: ChangeLogEntryEnriched) =>
export default function ChangeLog({ logs }: { logs: ChangeLogEntry[] }) {
const [selectedChange, setSelectedChange] =
useState<ChangeLogEntryEnriched | null>(null);
// tracks the accordion expanded state, if null then the accordion is closed
const [expandedItem, setExpandedItem] = useState<string | null>(
localStorage.getItem(localStorageKey)
);

const changes = useChangeLogData(logs);

return (
<Card>
<Card.Header>Record history</Card.Header>
<Card.Body>
<Table striped hover>
<thead>
<tr>
<th>Record type</th>
<th>Event</th>
<th>Affected fields</th>
<th>Edited by</th>
<th>Date</th>
</tr>
</thead>
<tbody className="font-monospace">
{changes.length === 0 && (
// this should only happen in local dev where change log is not downloaded from replica
<Accordion
activeKey={expandedItem}
// on accordion click save new expanded item state to local storage
onSelect={(eventKey) => {
const localStorageValue = String(eventKey); // local storage value must be a string type
localStorage.setItem(localStorageKey, localStorageValue);
setExpandedItem(localStorageValue);
}}
>
<Accordion.Item eventKey={recordHistoryItemName}>
<Accordion.Header>Record history</Accordion.Header>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This header gets a baby blue color when it's expanded, and it's the only header row in on the page to get that color. Can it be rgba(33, 37, 41, 0.03) like the rest of of the card headers?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed—and i created cityofaustin/atd-data-tech#20606 to follow-up on this 🙏

<Accordion.Body>
<Table striped hover>
<thead>
<tr>
<td colSpan={5} className="text-center">
No changes found
</td>
</tr>
)}
{changes.map((change) => (
<tr
key={change.id}
onClick={() => setSelectedChange(change)}
style={{ cursor: "pointer" }}
>
<td>{change.record_type}</td>
<td>{change.operation_type}</td>
<td>
{isNewRecordEvent(change)
? ""
: change.affected_fields.join(", ")}
</td>
<td>{change.created_by}</td>
<td>{formatDateTime(change.created_at)}</td>
<th>Record type</th>
<th>Event</th>
<th>Affected fields</th>
<th>Edited by</th>
<th>Date</th>
</tr>
))}
</tbody>
</Table>
{/* Modal with change details table */}
{selectedChange && (
<ChangeLogDetails
selectedChange={selectedChange}
setSelectedChange={setSelectedChange}
/>
)}
</Card.Body>
</Card>
</thead>
<tbody className="font-monospace">
{changes.length === 0 && (
// this should only happen in local dev where change log is not downloaded from replica
<tr>
<td colSpan={5} className="text-center">
No changes found
</td>
</tr>
)}
{changes.map((change) => (
<tr
key={change.id}
onClick={() => setSelectedChange(change)}
style={{ cursor: "pointer" }}
>
<td>{change.record_type}</td>
<td>{change.operation_type}</td>
<td>
{isNewRecordEvent(change)
? ""
: change.affected_fields.join(", ")}
</td>
<td>{change.created_by}</td>
<td>{formatDateTime(change.created_at)}</td>
</tr>
))}
</tbody>
</Table>
{/* Modal with change details table */}
{selectedChange && (
<ChangeLogDetails
selectedChange={selectedChange}
setSelectedChange={setSelectedChange}
/>
)}
</Accordion.Body>
</Accordion.Item>
</Accordion>
);
}
6 changes: 3 additions & 3 deletions app/components/SidebarLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ export default function SidebarLayout({ children }: { children: ReactNode }) {

const toggleSidebar = useCallback(
() =>
setIsCollapsed((prevSate) => {
localStorage.setItem(localStorageKey, String(!prevSate));
return !prevSate;
setIsCollapsed((prevState) => {
localStorage.setItem(localStorageKey, String(!prevState));
return !prevState;
}),
[]
);
Expand Down