Skip to content

Commit dbffc5e

Browse files
Merge pull request #212 from CivicDataLab/209-enable-pagination-in-schema-and-add-preview-options
209 enable pagination in schema and add preview options
2 parents 18f3f8e + 25061ca commit dbffc5e

File tree

7 files changed

+311
-132
lines changed

7 files changed

+311
-132
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ interface MetadataProps {
1010
}
1111

1212
const MetadataComponent: React.FC<MetadataProps> = ({ data, setOpen }) => {
13-
const filteredMetadataArray = data.metadata.filter(
13+
const filteredMetadataArray = data?.metadata.filter(
1414
(item: any) =>
1515
item.metadataItem.label !== 'Source Website' &&
1616
item.metadataItem.label !== 'Github Repo Link' &&
@@ -31,7 +31,7 @@ const MetadataComponent: React.FC<MetadataProps> = ({ data, setOpen }) => {
3131
)}
3232
</div>
3333
<div className="flex flex-col gap-5 align-baseline">
34-
{filteredMetadataArray.map((item: any, index: any) => (
34+
{filteredMetadataArray?.map((item: any, index: any) => (
3535
<div
3636
className="flex items-center gap-2 border-b-2 border-solid border-baseGraySlateSolid6 pb-2"
3737
key={index}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ interface PrimaryDataProps {
1414
}
1515

1616
const PrimaryData: React.FC<PrimaryDataProps> = ({ data, isLoading }) => {
17-
const sourceMetadata = data.metadata.find(
17+
const sourceMetadata = data?.metadata.find(
1818
(item: any) => item.metadataItem.label === 'Source'
1919
);
20-
const sourceLink = data.metadata.find(
20+
const sourceLink = data?.metadata.find(
2121
(item: any) => item.metadataItem.label === 'Source Website'
2222
);
23-
const githubLink = data.metadata.find(
23+
const githubLink = data?.metadata.find(
2424
(item: any) => item.metadataItem.label === 'Github Repo Link'
2525
);
2626

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

Lines changed: 191 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,18 @@ import Link from 'next/link';
55
import { useParams } from 'next/navigation';
66
import { graphql } from '@/gql';
77
import { useQuery } from '@tanstack/react-query';
8-
import { Button, Spinner, Tag, Text } from 'opub-ui';
8+
import {
9+
Accordion,
10+
AccordionContent,
11+
AccordionItem,
12+
AccordionTrigger,
13+
Button,
14+
Dialog,
15+
Spinner,
16+
Table,
17+
Tag,
18+
Text,
19+
} from 'opub-ui';
920

1021
import { GraphQL } from '@/lib/api';
1122
import { formatDate } from '@/lib/utils';
@@ -19,7 +30,11 @@ const datasetResourceQuery: any = graphql(`
1930
type
2031
name
2132
description
22-
33+
previewData {
34+
columns
35+
rows
36+
}
37+
previewEnabled
2338
schema {
2439
fieldName
2540
id
@@ -28,6 +43,7 @@ const datasetResourceQuery: any = graphql(`
2843
}
2944
fileDetails {
3045
format
46+
size
3147
}
3248
}
3349
}
@@ -78,6 +94,118 @@ const Resources = () => {
7894
});
7995
}, [getResourceDetails.data]);
8096

97+
const generateColumnData = () => {
98+
return [
99+
{
100+
accessorKey: 'schema',
101+
header: 'Columns',
102+
cell: ({ row }: any) => {
103+
return (
104+
<Dialog>
105+
<Dialog.Trigger>
106+
<Button kind="tertiary">View All Columns</Button>
107+
</Dialog.Trigger>
108+
<Dialog.Content title={'Fields'} limitHeight>
109+
<Table
110+
columns={[
111+
{
112+
accessorKey: 'name',
113+
header: 'Name of the Field',
114+
},
115+
{
116+
accessorKey: 'format',
117+
header: 'Format',
118+
},
119+
]}
120+
rows={row.original.schema.map((item: any) => ({
121+
name: item.fieldName,
122+
format: item.format,
123+
}))}
124+
/>
125+
</Dialog.Content>
126+
</Dialog>
127+
);
128+
},
129+
},
130+
{
131+
accessorKey: 'rowsLength',
132+
header: 'No.of Rows',
133+
cell: ({ row }: any) => {
134+
return (
135+
<p>
136+
{row.original.rowsLength === 0
137+
? 'NA'
138+
: `${row.original.rowsLength}`}
139+
</p>
140+
);
141+
},
142+
},
143+
{
144+
accessorKey: 'format',
145+
header: 'Format',
146+
},
147+
{
148+
accessorKey: 'size',
149+
header: 'Size',
150+
},
151+
{
152+
accessorKey: 'preview',
153+
header: 'Preview',
154+
cell: ({ row }: any) => {
155+
const previewData = row.original.preview;
156+
157+
// Generate columns dynamically from previewData.columns
158+
const previewColumns =
159+
previewData?.columns?.map((column: string) => ({
160+
accessorKey: column,
161+
header: column,
162+
cell: ({ cell }: any) => {
163+
const value = cell.getValue();
164+
return <span>{value !== null ? value.toString() : 'N/A'}</span>;
165+
},
166+
})) || [];
167+
168+
// Transform rows data to match column structure
169+
const previewRows =
170+
previewData?.rows?.map((row: any[]) => {
171+
const rowData: Record<string, any> = {};
172+
previewData.columns.forEach((column: string, index: number) => {
173+
rowData[column] = row[index];
174+
});
175+
return rowData;
176+
}) || [];
177+
178+
return (
179+
<Dialog>
180+
<Dialog.Trigger>
181+
<Button kind="tertiary" disabled={!previewData}>
182+
Preview
183+
</Button>
184+
</Dialog.Trigger>
185+
<Dialog.Content title={'Fields'} limitHeight large>
186+
{previewData && (
187+
<Table columns={previewColumns} rows={previewRows} />
188+
)}
189+
</Dialog.Content>
190+
</Dialog>
191+
);
192+
},
193+
},
194+
];
195+
};
196+
197+
const generateTableData = (data: any) => {
198+
return [
199+
{
200+
schema: data?.schema,
201+
rowsLength: data?.previewData?.rows?.length || 'Na',
202+
format: data?.fileDetails?.format || 'Na',
203+
size: Math.round(data?.fileDetails?.size / 1024).toFixed(2) + 'KB',
204+
preview: data?.previewData,
205+
},
206+
];
207+
};
208+
81209
return (
82210
<div className="w-full">
83211
{getResourceDetails.isLoading ? (
@@ -90,51 +218,77 @@ const Resources = () => {
90218
<Text variant="bodyLg" className="mx-6 lg:mx-0">
91219
Downloadable Resources
92220
</Text>
93-
<div className="mx-6 mt-5 flex flex-col gap-8 bg-surfaceDefault p-6 lg:mx-0">
221+
<div>
94222
{getResourceDetails.data?.datasetResources.map(
95223
(item: any, index: number) => (
96224
<div
97225
key={index}
98-
className="flex flex-wrap justify-between gap-4"
226+
className="mx-6 mt-5 flex flex-col gap-6 bg-surfaceDefault p-6 lg:mx-0"
99227
>
100-
<div className="gap flex flex-col lg:w-4/5">
101-
<div className="item flex items-center gap-2">
102-
<Text variant="headingMd">{item.name}</Text>
103-
<Tag>{item.fileDetails.format}</Tag>
228+
<div className="flex flex-wrap justify-between gap-4">
229+
<div className="gap flex flex-col lg:w-4/5">
230+
<div className="item flex items-center gap-2">
231+
<Text variant="headingMd">{item.name}</Text>
232+
{item.fileDetails?.format && (
233+
<Tag>{item.fileDetails?.format}</Tag>
234+
)}
235+
</div>
236+
<div>
237+
<Text>Updated:</Text>
238+
<Text>{formatDate(item.modified)}</Text>
239+
</div>
104240
</div>
105241
<div>
106-
<Text>Updated:</Text>
107-
<Text>{formatDate(item.modified)}</Text>
108-
</div>
109-
<div className="flex flex-col">
110-
<div
111-
ref={(el) => (descriptionRefs.current[index] = el)}
112-
className={!showMore[index] ? 'line-clamp-2' : ''}
242+
<Link
243+
href={`${process.env.NEXT_PUBLIC_BACKEND_URL}/api/download/resource/${item.id}`}
244+
target="_blank"
245+
className="flex justify-center"
113246
>
114-
<Text>{item.description}</Text>
115-
</div>
116-
{isDescriptionLong[index] && (
117-
<Button
118-
className="self-start p-2"
119-
onClick={() => toggleShowMore(index)}
120-
variant="interactive"
121-
size="slim"
122-
kind="tertiary"
123-
>
124-
{showMore[index] ? 'Show less' : 'Show more'}
125-
</Button>
126-
)}
247+
<Button>Download</Button>
248+
</Link>
127249
</div>
128250
</div>
129-
<div>
130-
<Link
131-
href={`${process.env.NEXT_PUBLIC_BACKEND_URL}/api/download/resource/${item.id}`}
132-
target="_blank"
133-
className="flex justify-center"
134-
>
135-
<Button>Download</Button>
136-
</Link>
137-
</div>
251+
<Accordion type="single" collapsible className="w-full">
252+
<AccordionItem value="item-1" className=" border-none">
253+
<div className="flex flex-wrap items-center justify-between gap-4">
254+
<div className="flex flex-col lg:w-3/4">
255+
<div
256+
ref={(el) => (descriptionRefs.current[index] = el)}
257+
className={!showMore[index] ? 'line-clamp-2' : ''}
258+
>
259+
<Text>{item.description}</Text>
260+
</div>
261+
{isDescriptionLong[index] && (
262+
<Button
263+
className="self-start p-2"
264+
onClick={() => toggleShowMore(index)}
265+
variant="interactive"
266+
size="slim"
267+
kind="tertiary"
268+
>
269+
{showMore[index] ? 'Show less' : 'Show more'}
270+
</Button>
271+
)}
272+
</div>
273+
<AccordionTrigger className="flex w-full flex-wrap items-center gap-2 p-0 hover:no-underline">
274+
View Details
275+
</AccordionTrigger>
276+
</div>
277+
<AccordionContent
278+
className="flex w-full flex-col py-5"
279+
style={{
280+
backgroundColor: 'var( --base-pure-white)',
281+
outline: '1px solid var( --base-pure-white)',
282+
}}
283+
>
284+
<Table
285+
columns={generateColumnData()}
286+
rows={generateTableData(item)}
287+
hideFooter
288+
/>
289+
</AccordionContent>
290+
</AccordionItem>
291+
</Accordion>
138292
</div>
139293
)
140294
)}

0 commit comments

Comments
 (0)