Skip to content

Commit 4e77097

Browse files
authored
Merge pull request #275 from CivicDataLab/273-add-preview-for-pdf-files
Fix bugs and add features
2 parents b045982 + 281a87a commit 4e77097

File tree

52 files changed

+1381
-975
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1381
-975
lines changed

app/[locale]/(user)/components/ListingComponent.tsx

Lines changed: 67 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useEffect, useReducer, useState } from 'react';
1+
import React, { useEffect, useReducer, useRef, useState } from 'react';
22
import Image from 'next/image';
33
import { useRouter } from 'next/navigation';
44
import GraphqlPagination from '@/app/[locale]/dashboard/components/GraphqlPagination/graphqlPagination';
@@ -219,12 +219,18 @@ const ListingComponent: React.FC<ListingProps> = ({
219219
const datasetDetails = facets?.results ?? [];
220220

221221
useUrlParams(queryParams, setQueryParams, setVariables);
222+
const latestFetchId = useRef(0);
222223

223224
useEffect(() => {
224225
if (variables) {
226+
const currentFetchId = ++latestFetchId.current;
227+
225228
fetchDatasets(variables)
226229
.then((res) => {
227-
setFacets(res);
230+
// Only set if this is the latest call
231+
if (currentFetchId === latestFetchId.current) {
232+
setFacets(res);
233+
}
228234
})
229235
.catch((err) => {
230236
console.error(err);
@@ -471,36 +477,71 @@ const ListingComponent: React.FC<ListingProps> = ({
471477
: item?.organization?.logo
472478
? `${process.env.NEXT_PUBLIC_BACKEND_URL}/${item.organization.logo}`
473479
: '/org.png';
480+
const Geography = item.metadata.filter(
481+
(item: any) => item.metadata_item.label === 'Geography'
482+
)[0]?.value;
483+
484+
const MetadataContent = [
485+
{
486+
icon: Icons.calendar,
487+
label: 'Date',
488+
value: formatDate(item.modified),
489+
tooltip: 'Date',
490+
},
491+
{
492+
icon: Icons.download,
493+
label: 'Download',
494+
value: item.download_count.toString(),
495+
tooltip: 'Download',
496+
},
497+
];
498+
if (Geography) {
499+
MetadataContent.push({
500+
icon: Icons.globe,
501+
label: 'Geography',
502+
value: Geography,
503+
tooltip: 'Geography',
504+
});
505+
}
506+
507+
if (item.has_charts && view === 'expanded') {
508+
MetadataContent.push({
509+
icon: Icons.chart,
510+
label: '',
511+
value: 'With Charts',
512+
tooltip: 'Charts',
513+
});
514+
}
515+
516+
const FooterContent = [
517+
{
518+
icon: `/Sectors/${item.sectors[0]}.svg`,
519+
label: 'Sectors',
520+
tooltip: `${item.sectors[0]}`,
521+
},
522+
...(item.has_charts && view !== 'expanded'
523+
? [
524+
{
525+
icon: `/chart-bar.svg`,
526+
label: 'Charts',
527+
tooltip: 'Charts',
528+
},
529+
]
530+
: []),
531+
{
532+
icon: image,
533+
label: 'Published by',
534+
tooltip: `${item.is_individual_dataset ? item.user?.name : item.organization?.name}`,
535+
},
536+
];
474537

475538
const commonProps = {
476539
title: item.title,
477540
description: item.description,
478-
metadataContent: [
479-
{
480-
icon: Icons.calendar,
481-
label: 'Date',
482-
value: formatDate(item.modified),
483-
},
484-
{
485-
icon: Icons.download,
486-
label: 'Download',
487-
value: item.download_count.toString(),
488-
},
489-
{
490-
icon: Icons.globe,
491-
label: 'Geography',
492-
value: 'India',
493-
},
494-
],
541+
metadataContent: MetadataContent,
495542
tag: item.tags,
496543
formats: item.formats,
497-
footerContent: [
498-
{
499-
icon: `/Sectors/${item.sectors[0]}.svg`,
500-
label: 'Sectors',
501-
},
502-
{ icon: image, label: 'Published by' },
503-
],
544+
footerContent: FooterContent,
504545
};
505546

506547
return (
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
'use client';
2+
3+
import { useEffect, useState } from 'react';
4+
5+
interface PdfPreviewProps {
6+
url: string;
7+
}
8+
9+
export default function PdfPreview({ url }: PdfPreviewProps) {
10+
const [previewUrl, setPreviewUrl] = useState<string | null>(null);
11+
12+
useEffect(() => {
13+
const fetchPdf = async () => {
14+
try {
15+
const response = await fetch(url);
16+
const blobData = await response.blob();
17+
18+
// Manually set MIME type to PDF (in case it's sent as octet-stream)
19+
const pdfBlob = new Blob([blobData], { type: 'application/pdf' });
20+
const objectUrl = URL.createObjectURL(pdfBlob);
21+
setPreviewUrl(objectUrl);
22+
} catch (error) {
23+
console.error('Failed to load PDF:', error);
24+
}
25+
};
26+
27+
fetchPdf();
28+
29+
return () => {
30+
if (previewUrl) {
31+
URL.revokeObjectURL(previewUrl);
32+
}
33+
};
34+
}, [url]);
35+
36+
if (!previewUrl) return <p>Loading PDF preview...</p>;
37+
38+
return (
39+
<object
40+
data={previewUrl}
41+
type="application/pdf"
42+
width="100%"
43+
height="500px"
44+
>
45+
<p>PDF preview not available</p>
46+
</object>
47+
);
48+
}

app/[locale]/(user)/components/Sectors.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ const Sectors = () => {
6363
<div className="mt-12 grid w-full grid-cols-1 gap-6 px-4 md:grid-cols-2 md:px-12 lg:grid-cols-3 lg:px-12">
6464
{data?.sectors.map((sectors: any) => (
6565
<Link
66-
href={`/sectors/${sectors.slug}?sectors=${capitalizeWords(sectors.slug)}`}
66+
href={`/sectors/${sectors.slug}?size=9&page=1&sort=recent&sectors=${capitalizeWords(sectors.slug)}`}
6767
key={sectors.id}
6868
>
6969
<div className="flex w-full items-center gap-5 rounded-4 bg-surfaceDefault p-7 shadow-card">

app/[locale]/(user)/datasets/[datasetIdentifier]/components/Details/index.tsx

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -98,21 +98,6 @@ const Details: React.FC<DetailsProps> = ({ setShowcharts }) => {
9898
{data?.getChartData.map((item: any, index: any) => (
9999
<CarouselItem key={index} className="m-auto">
100100
<div className="w-full border-2 border-solid border-baseGraySlateSolid4 bg-surfaceDefault p-6 text-center shadow-basicLg max-sm:p-2">
101-
<div className="lg:p-10">
102-
{item.__typename === 'TypeResourceChart' &&
103-
item?.chart?.options ? (
104-
renderChart(item)
105-
) : (
106-
<Image
107-
src={`${process.env.NEXT_PUBLIC_BACKEND_URL}/api/download/chart_image/${item.id}`}
108-
alt={''}
109-
width={300}
110-
height={300}
111-
unoptimized
112-
/>
113-
)}
114-
{/* Call the renderChart function */}
115-
</div>
116101
<div className="flex items-center justify-between gap-2 max-sm:flex-wrap">
117102
<div className="flex flex-col gap-1 py-2 text-start">
118103
<Text className="font-semi-bold">{item.name}</Text>
@@ -133,13 +118,6 @@ const Details: React.FC<DetailsProps> = ({ setShowcharts }) => {
133118
</Text>
134119
</div>
135120
<div className="flex gap-2">
136-
<Button kind="secondary" className="p-2">
137-
<Icon
138-
source={Icons.diagonal}
139-
size={20}
140-
color="default"
141-
/>
142-
</Button>
143121
<Link
144122
href={`${process.env.NEXT_PUBLIC_BACKEND_URL}/api/download/chart/${item.id}`}
145123
target="_blank"
@@ -155,6 +133,22 @@ const Details: React.FC<DetailsProps> = ({ setShowcharts }) => {
155133
</Link>
156134
</div>
157135
</div>
136+
<div className="lg:p-10">
137+
{item.__typename === 'TypeResourceChart' &&
138+
item?.chart?.options ? (
139+
renderChart(item)
140+
) : (
141+
<Image
142+
src={`${process.env.NEXT_PUBLIC_BACKEND_URL}/api/download/chart_image/${item.id}`}
143+
alt={''}
144+
width={300}
145+
height={300}
146+
unoptimized
147+
/>
148+
)}
149+
{/* Call the renderChart function */}
150+
</div>
151+
158152
</div>
159153
</CarouselItem>
160154
))}

app/[locale]/(user)/datasets/[datasetIdentifier]/components/Metadata/index.tsx

Lines changed: 49 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import React, { useEffect, useState } from 'react';
22
import Image from 'next/image';
33
import Link from 'next/link';
4-
import { Button, Divider, Icon, Text } from 'opub-ui';
4+
import { Button, Divider, Icon, Text, Tooltip } from 'opub-ui';
55

6-
import { getWebsiteTitle } from '@/lib/utils';
6+
import { formatDate, getWebsiteTitle } from '@/lib/utils';
77
import { Icons } from '@/components/icons';
88

99
interface MetadataProps {
@@ -17,6 +17,7 @@ const MetadataComponent: React.FC<MetadataProps> = ({ data, setOpen }) => {
1717
value: item.value,
1818
type: item.metadataItem.dataType,
1919
}));
20+
2021
const [isexpanded, setIsexpanded] = useState(false);
2122
const toggleDescription = () => setIsexpanded(!isexpanded);
2223

@@ -115,35 +116,45 @@ const MetadataComponent: React.FC<MetadataProps> = ({ data, setOpen }) => {
115116
<Text className="min-w-[120px] basis-1/4 uppercase" variant="bodyMd">
116117
{data.isIndividualDataset ? 'Publisher' : 'Organization'}
117118
</Text>
118-
<Text
119-
className="max-w-xs truncate "
120-
variant="bodyLg"
121-
fontWeight="medium"
119+
<Tooltip
120+
content={
121+
data.isIndividualDataset
122+
? data.user.fullName
123+
: data.organization.name
124+
}
122125
>
123-
{data.isIndividualDataset
124-
? data.user.fullName
125-
: data.organization.name}
126-
</Text>
126+
<Text
127+
className="line-clamp-2 "
128+
variant="bodyLg"
129+
fontWeight="medium"
130+
>
131+
{data.isIndividualDataset
132+
? data.user.fullName
133+
: data.organization.name}
134+
</Text>
135+
</Tooltip>
127136
</div>
128137
<div className="flex gap-2 ">
129138
<Text className="min-w-[120px] basis-1/4 uppercase" variant="bodyMd">
130139
Sector
131140
</Text>
132141
<div className="flex flex-wrap gap-2">
133-
{data.sectors.length > 0 ? (
134-
data.sectors.map((sector: any, index: number) => (
135-
<Image
136-
key={index}
137-
src={`/Sectors/${sector.name}.svg`}
138-
alt={sector.name || ''}
139-
width={52}
140-
height={52}
141-
className="border-1 border-solid border-greyExtralight p-1"
142-
/>
143-
))
144-
) : (
145-
<span>N/A</span>
146-
)}
142+
{data.sectors.length > 0 ? (
143+
data.sectors.map((sector: any, index: number) => (
144+
<Tooltip content={sector.name} key={index}>
145+
<Image
146+
key={index}
147+
src={`/Sectors/${sector.name}.svg`}
148+
alt={sector.name || ''}
149+
width={52}
150+
height={52}
151+
className="border-1 border-solid border-greyExtralight p-1"
152+
/>
153+
</Tooltip>
154+
))
155+
) : (
156+
<span>N/A</span>
157+
)}
147158
</div>
148159
</div>
149160
{Metadata.map((item: any, index: any) => (
@@ -154,16 +165,20 @@ const MetadataComponent: React.FC<MetadataProps> = ({ data, setOpen }) => {
154165
>
155166
{item.label}
156167
</Text>
157-
{item.type !== 'URL' ? (
158-
<Text className="max-w-xs " variant="bodyLg" fontWeight="medium">
159-
{item.value}
160-
</Text>
161-
) : (
168+
{item.type === 'URL' ? (
162169
<Link href={item.value} target="_blank">
163-
<Text className="underline" color="highlight">
170+
<Text className="underline" color="highlight" variant="bodyLg">
164171
{sourceTitle?.trim() ? sourceTitle : 'Visit Website'}
165172
</Text>
166173
</Link>
174+
) : item.type === 'DATE' ? (
175+
<Text className="max-w-xs " variant="bodyLg" fontWeight="medium">
176+
{formatDate(item.value)}
177+
</Text>
178+
) : (
179+
<Text className="max-w-xs " variant="bodyLg" fontWeight="medium">
180+
{item.value}
181+
</Text>
167182
)}
168183
</div>
169184
))}
@@ -189,8 +204,10 @@ const MetadataComponent: React.FC<MetadataProps> = ({ data, setOpen }) => {
189204
</div>
190205
)}
191206
<div className="flex flex-col gap-4">
192-
<Text variant="bodyMd">Description</Text>
193-
<Text variant="bodyMd">
207+
<Text variant="bodyMd" className="uppercase">
208+
Description
209+
</Text>
210+
<Text variant="bodyLg">
194211
{data.description?.length > 260 && !isexpanded
195212
? `${data.description.slice(0, 260)}...`
196213
: data.description}

app/[locale]/(user)/datasets/[datasetIdentifier]/components/PrimaryData/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const PrimaryData: React.FC<PrimaryDataProps> = ({ data, isLoading }) => {
1818
<div>
1919
<div className="flex flex-col gap-4">
2020
<Text variant="heading2xl">{data?.title}</Text>
21-
<div className="flex gap-2">
21+
<div className="flex flex-wrap gap-2">
2222
{data?.tags.map((item: any, index: any) => (
2323
<Tag
2424
key={index}

0 commit comments

Comments
 (0)