11import Link from "next/link" ;
2- import { Resource , Tag } from "@portaljs/ckan" ;
3- import { ArrowDownTrayIcon } from "@heroicons/react/20/solid" ;
2+ import { Resource , Tag } from "@portaljs/ckan" ;
3+ import {
4+ ArrowDownTrayIcon ,
5+ ChevronDownIcon ,
6+ ChevronUpIcon ,
7+ } from "@heroicons/react/20/solid" ;
48import { getTimeAgo } from "@/lib/utils" ;
59import { Dataset } from "@/schemas/dataset.interface" ;
610import { RiExternalLinkLine } from "react-icons/ri" ;
11+ import { useEffect , useRef , useState } from "react" ;
12+ import MarkdownRenderer from "@/components/_shared/MarkdownRenderer" ;
713
814function uniqueFormat ( resources ) {
915 const formats = resources . map ( ( item : Resource ) => item . format ) ;
@@ -15,12 +21,28 @@ export default function DatasetInfo({
1521} : {
1622 dataset : Dataset ;
1723} ) {
24+ const [ isTruncated , setIsTruncated ] = useState ( false ) ;
25+ const [ showFullDescription , setShowFullDescription ] = useState ( false ) ;
26+ const textRef = useRef < HTMLParagraphElement > ( null ) ;
27+
28+ const description =
29+ dataset . notes ?. replace ( / < \/ ? [ ^ > ] + ( > | $ ) / g, "" ) || "No description" ;
30+
1831 const metaFormats = [
1932 { format : "jsonld" , label : "JSON-LD" } ,
2033 { format : "rdf" , label : "RDF" } ,
2134 { format : "ttl" , label : "TTL" } ,
2235 ] ;
2336
37+ useEffect ( ( ) => {
38+ const el = textRef . current ;
39+ if ( el ) {
40+ requestAnimationFrame ( ( ) => {
41+ setIsTruncated ( el . scrollHeight > el . clientHeight ) ;
42+ } ) ;
43+ }
44+ } , [ dataset . notes ] ) ;
45+
2446 return (
2547 < div className = "flex flex-col" >
2648 < div className = "flex flex-col gap-y-3" >
@@ -92,6 +114,43 @@ export default function DatasetInfo({
92114 Created:{ " " }
93115 { dataset . metadata_created && getTimeAgo ( dataset . metadata_created ) }
94116 </ span >
117+ { dataset . source && dataset . source . length > 0 && (
118+ < div className = "font-medium text-gray-500" >
119+ < div className = "flex items-start gap-1" >
120+ < svg
121+ xmlns = "http://www.w3.org/2000/svg"
122+ fill = "none"
123+ viewBox = "0 0 24 24"
124+ strokeWidth = { 1.5 }
125+ stroke = "currentColor"
126+ className = "w-5 h-5 text-accent inline-block mt-0.5 flex-shrink-0"
127+ >
128+ < path
129+ strokeLinecap = "round"
130+ strokeLinejoin = "round"
131+ d = "M13.19 8.688a4.5 4.5 0 011.242 7.244l-4.5 4.5a4.5 4.5 0 01-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 00-6.364-6.364l-4.5 4.5a4.5 4.5 0 001.242 7.244"
132+ />
133+ </ svg >
134+ < div className = "flex flex-col gap-1" >
135+ < span > Source{ dataset . source . length > 1 ? "s" : "" } :</ span >
136+ < div className = "flex flex-col gap-1.5" >
137+ { dataset . source . map ( ( url , index ) => (
138+ < a
139+ key = { index }
140+ href = { url }
141+ target = "_blank"
142+ rel = "noopener noreferrer"
143+ className = "text-accent hover:text-darkaccent flex items-center gap-1 break-all transition"
144+ >
145+ < RiExternalLinkLine className = "w-4 h-4 flex-shrink-0" />
146+ < span className = "underline" > { url } </ span >
147+ </ a >
148+ ) ) }
149+ </ div >
150+ </ div >
151+ </ div >
152+ </ div >
153+ ) }
95154 < span className = "font-medium text-gray-500 inline" >
96155 < svg
97156 xmlns = "http://www.w3.org/2000/svg"
@@ -112,9 +171,30 @@ export default function DatasetInfo({
112171 </ span >
113172 </ div >
114173 < div className = "py-4 my-4 border-y" >
115- < p className = "text-sm font-normal text-stone-500 line-clamp-4" >
116- { dataset . notes ?. replace ( / < \/ ? [ ^ > ] + ( > | $ ) / g, "" ) || "No description" }
117- </ p >
174+ < div
175+ ref = { textRef }
176+ className = { `text-sm font-normal text-stone-500 transition-all ${
177+ ! showFullDescription ? "line-clamp-4" : ""
178+ } `}
179+ >
180+ < MarkdownRenderer content = { description } />
181+ </ div >
182+ { isTruncated && (
183+ < button
184+ onClick = { ( ) => setShowFullDescription ( ! showFullDescription ) }
185+ className = "mt-2 border-b border-accent text-stone-500 hover:text-accent"
186+ >
187+ { showFullDescription ? (
188+ < span className = "flex items-center" >
189+ Read less < ChevronUpIcon className = "text-accent w-4" />
190+ </ span >
191+ ) : (
192+ < span className = "flex items-center" >
193+ Read more < ChevronDownIcon className = "text-accent w-4" />
194+ </ span >
195+ ) }
196+ </ button >
197+ ) }
118198 </ div >
119199 < div className = "flex flex-wrap gap-1" >
120200 { dataset . tags ?. map ( ( tag : Tag ) => (
0 commit comments