Skip to content

Commit

Permalink
fix: 🐛 added support for multiple attachments for single test (#62)
Browse files Browse the repository at this point in the history
* fix: 🐛 added support for multiple attachments for single test

* fix: 🐛 fixed issue when displaying image attachment
  • Loading branch information
WasiqB authored Oct 21, 2024
1 parent b9179b9 commit 5ecb1b5
Show file tree
Hide file tree
Showing 8 changed files with 679 additions and 89 deletions.
56 changes: 0 additions & 56 deletions .cursorrules

This file was deleted.

111 changes: 81 additions & 30 deletions components/data-table/attachment.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import {
Dialog,
DialogContent,
Expand All @@ -11,29 +11,46 @@ import {
} from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Link } from 'lucide-react';
import {
Carousel,
CarouselApi,
CarouselContent,
CarouselItem,
} from '../ui/carousel';
import { Card, CardContent } from '../ui/card';
import { isBase64Image, isJson, isXml, prettifyJson } from '@/lib/string-util';
import { CopyBlock, dracula } from 'react-code-blocks';

interface AttachmentDialogProps {
content: string;
attachment: string | string[];
title: string;
description?: string;
}

/* eslint-disable @typescript-eslint/no-unused-vars */
const isBase64Image = (str: string): boolean => {
try {
return btoa(atob(str)) === str;
} catch (err) {
return false;
}
};

export function AttachmentDialog({
content,
attachment,
title,
description,
}: AttachmentDialogProps): JSX.Element {
const [isOpen, setIsOpen] = useState(false);
const isImage = isBase64Image(content);
const isArray = Array.isArray(attachment);
const content = isArray ? attachment : [attachment];
const [api, setApi] = useState<CarouselApi>();
const [current, setCurrent] = useState(0);
const [count, setCount] = useState(0);

useEffect(() => {
if (!api) {
return;
}

setCount(api.scrollSnapList().length);
setCurrent(api.selectedScrollSnap() + 1);

api.on('select', () => {
setCurrent(api.selectedScrollSnap() + 1);
});
}, [api]);

return (
<Dialog open={isOpen} onOpenChange={setIsOpen}>
Expand All @@ -42,27 +59,61 @@ export function AttachmentDialog({
<Link className='h-4 w-4' />
</Button>
</DialogTrigger>
<DialogContent className='flex flex-col sm:max-h-[90vh] sm:max-w-[90vw]'>
<DialogContent className='flex w-full flex-col sm:max-h-[90vh] sm:max-w-[90vw]'>
<DialogHeader>
<DialogTitle>{title}</DialogTitle>
{description && <DialogDescription>{description}</DialogDescription>}
</DialogHeader>
<div className='mt-4 flex-grow overflow-auto'>
{isImage ? (
<div className='relative h-full min-h-[300px] w-full border border-gray-500'>
<img
src={`data:image/png;base64,${content}`}
alt='Attachment'
className='h-full w-full object-contain'
/>
</div>
) : (
<div className='max-h-[60vh] overflow-y-auto'>
<p className='whitespace-pre-wrap text-lg text-foreground'>
{content}
</p>
</div>
)}
<div className='mt-4 flex w-full flex-grow flex-col items-center justify-center'>
<Carousel setApi={setApi} className='relative w-full'>
<CarouselContent className='w-full'>
{content
.map((item) => item.trim())
.map((item, index) => (
<CarouselItem key={index} className='w-full'>
<Card className='w-full'>
<CardContent className='p-6'>
{isBase64Image(item) ? (
// eslint-disable-next-line @stylistic/js/max-len
<div className='relative h-full min-h-[300px] w-full border border-gray-500'>
<img
src={`data:image/png;base64,${item}`}
alt='Attachment'
className='h-full w-full object-contain'
/>
</div>
) : (
<div className='w-full overflow-hidden'>
<CopyBlock
text={
isJson(item) ? prettifyJson(item) : item.trim()
}
theme={dracula}
language={
isJson(item)
? 'json'
: isXml(item)
? 'xml'
: 'text'
}
customStyle={{
height: '300px',
overflow: 'auto',
}}
showLineNumbers
wrapLongLines
/>
</div>
)}
</CardContent>
</Card>
</CarouselItem>
))}
</CarouselContent>
</Carousel>
<div className='py-2 text-center text-sm text-muted-foreground'>
Slide {current} of {count}. (Use arrow keys to navigate)
</div>
</div>
</DialogContent>
</Dialog>
Expand Down
3 changes: 1 addition & 2 deletions components/data-table/columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -242,13 +242,12 @@ export const columns: ColumnDef<TestResultData>[] = [
),
cell: ({ row }) => {
const attachment = row.getValue('attachment') as TestLog;
const content = attachment.line?.trim();
return (
attachment && (
<AttachmentDialog
title='Attachment'
description='Below is the attachment from your Test'
content={content}
attachment={attachment.line}
/>
)
);
Expand Down
2 changes: 1 addition & 1 deletion components/ui/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '@/lib/utils';

const buttonVariants = cva(
'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
{
variants: {
variant: {
Expand Down
Loading

0 comments on commit 5ecb1b5

Please sign in to comment.