Skip to content

Commit

Permalink
feat(page.tsx, Backtrace.tsx, ClipboardButton.tsx): add CustomTimeAgo…
Browse files Browse the repository at this point in the history
… component to display occurrence creation and update time, add ClipboardButton component to copy occurrence backtrace to clipboard
  • Loading branch information
masterkain committed May 18, 2023
1 parent 5a07370 commit 4eaf18a
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import OccurrenceCounterLabel from '@/components/CounterLabel';
import CustomTimeAgo from '@/components/CustomTimeAgo';
import EnvironmentLabel from '@/components/EnvironmentLabel';
import ProjectHeader from '@/components/ProjectHeader';
import SidebarDesktop from '@/components/SidebarDesktop';
Expand Down Expand Up @@ -134,8 +135,18 @@ export default async function Occurrence({
</h3>
<EnvironmentLabel env={notice.env} />
</div>
<div className="mt-2 text-sm text-indigo-200">

<div className="mt-2 space-y-1 text-sm text-indigo-200">
<p>{occurrence.message}</p>
<div className="flex items-center space-x-2 text-xs">
<span>First seen:</span>
<CustomTimeAgo datetime={occurrence.created_at} locale="en_US" />
<svg viewBox="0 0 2 2" className="h-0.5 w-0.5 fill-gray-300">
<circle cx={1} cy={1} r={1} />
</svg>
<span>Last seen:</span>
<CustomTimeAgo datetime={occurrence.updated_at} locale="en_US" />
</div>
</div>
</div>
</div>
Expand Down
49 changes: 30 additions & 19 deletions components/occurrence/Backtrace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import classNames from '@/lib/classNames';
import { BacktraceItem } from '@/types/airbroke';
import { Prisma, occurrence, project } from '@prisma/client';
import LinkedBacktraceLine from './BacktraceLine';
import ClipboardButton from './ClipboardButton';

function isBacktraceItem(item: any): item is BacktraceItem {
return item && typeof item.file === 'string' && typeof item.line === 'number' && typeof item.function === 'string';
Expand All @@ -12,25 +13,35 @@ export default function Backtrace({ occurrence, project }: { occurrence: occurre
<>
{occurrence.backtrace && typeof occurrence.backtrace === 'object' && Array.isArray(occurrence.backtrace) && (
<div className="px-4 sm:px-6 lg:px-8">
{(occurrence.backtrace as Prisma.JsonArray).map(
(trace, index) =>
isBacktraceItem(trace) && (
<div key={index} className="flex flex-row flex-wrap justify-start pb-1 font-mono text-xs">
<p
className={classNames(
trace.file.includes('PROJECT_ROOT') ? 'font-semibold' : '',
'text-xs text-gray-400'
)}
>
<LinkedBacktraceLine file={trace.file} line={trace.line} project={project} />
</p>
<p className="mx-1 text-gray-400">:</p>
<p className="text-xs font-semibold text-indigo-400">{trace.line}</p>
<p className="mx-1 text-gray-400"></p>
<p className="text-xs font-semibold text-red-600">{trace.function}</p>
</div>
)
)}
<div className="flex items-start justify-between">
<div className="flex-1">
{(occurrence.backtrace as Prisma.JsonArray).map(
(trace, index) =>
isBacktraceItem(trace) && (
<div
key={index}
className="flex flex-row flex-wrap justify-start pb-1 font-mono text-xs md:text-xs"
>
<p
className={classNames(
trace.file.includes('PROJECT_ROOT') ? 'font-semibold' : '',
'text-xs text-gray-400'
)}
>
<LinkedBacktraceLine file={trace.file} line={trace.line} project={project} />
</p>
<p className="mx-1 text-gray-400">:</p>
<p className="text-xs font-semibold text-indigo-400">{trace.line}</p>
<p className="mx-1 text-gray-400"></p>
<p className="text-xs font-semibold text-red-600">{trace.function}</p>
</div>
)
)}
</div>
<div>
<ClipboardButton json={occurrence.backtrace} />
</div>
</div>
</div>
)}
</>
Expand Down
29 changes: 29 additions & 0 deletions components/occurrence/ClipboardButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use client';

import { Prisma } from '@prisma/client';
import { useState } from 'react';
import { HiClipboardCopy } from 'react-icons/hi';

export default function ClipboardButton({ json }: { json: Prisma.JsonValue }) {
const [isCopied, setIsCopied] = useState(false);

const handleCopy = () => {
navigator.clipboard.writeText(JSON.stringify(json, null, 2));
setIsCopied(true);

// Reset copied status after 3 seconds
setTimeout(() => {
setIsCopied(false);
}, 3000);
};

return (
<button
onClick={handleCopy}
className="group flex items-center gap-x-1 rounded-lg border border-indigo-500 px-4 py-2 text-xs font-semibold text-indigo-500 shadow-sm transition-colors duration-200 hover:bg-indigo-500 hover:text-white md:gap-x-3 md:text-sm"
>
<HiClipboardCopy className="h-4 w-4 md:h-5 md:w-5" aria-hidden="true" />
{isCopied ? 'Copied!' : 'Copy to Clipboard'}
</button>
);
}

0 comments on commit 4eaf18a

Please sign in to comment.