11import PreviewModal from "../components/PreviewModal" ;
22import CloudDownloadIcon from "@mui/icons-material/CloudDownload" ;
3+ import ContentCopyIcon from "@mui/icons-material/ContentCopy" ;
34import DescriptionIcon from "@mui/icons-material/Description" ;
45import ExpandLess from "@mui/icons-material/ExpandLess" ;
56import ExpandMore from "@mui/icons-material/ExpandMore" ;
@@ -12,6 +13,7 @@ import {
1213 Alert ,
1314 Button ,
1415 Collapse ,
16+ Snackbar ,
1517} from "@mui/material" ;
1618import FileTree from "components/DatasetDetailPage/FileTree/FileTree" ;
1719import {
@@ -93,20 +95,16 @@ const UpdatedDatasetDetailPage: React.FC = () => {
9395 const [ isExternalExpanded , setIsExternalExpanded ] = useState ( true ) ;
9496 const [ jsonSize , setJsonSize ] = useState < number > ( 0 ) ;
9597 const [ previewIndex , setPreviewIndex ] = useState < number > ( 0 ) ;
98+ const [ copiedToast , setCopiedToast ] = useState < {
99+ open : boolean ;
100+ text : string ;
101+ } > ( {
102+ open : false ,
103+ text : "" ,
104+ } ) ;
96105 const aiSummary = datasetDocument ?. [ ".datainfo" ] ?. AISummary ?? "" ;
97106
98- // useEffect(() => {
99- // if (!datasetDocument) {
100- // setJsonSize(0);
101- // return;
102- // }
103- // const bytes = new TextEncoder().encode(
104- // JSON.stringify(datasetDocument)
105- // ).length;
106- // setJsonSize(bytes);
107- // }, [datasetDocument]);
108-
109- const linkMap = useMemo ( ( ) => makeLinkMap ( externalLinks ) , [ externalLinks ] ) ;
107+ const linkMap = useMemo ( ( ) => makeLinkMap ( externalLinks ) , [ externalLinks ] ) ; // => external Link Map
110108
111109 const treeData = useMemo (
112110 ( ) => buildTreeFromDoc ( datasetDocument || { } , linkMap , "" ) ,
@@ -262,6 +260,32 @@ const UpdatedDatasetDetailPage: React.FC = () => {
262260
263261 return internalLinks ;
264262 } ;
263+ // Build a shareable preview URL for a JSON path in this dataset
264+ const buildPreviewUrl = ( path : string ) => {
265+ const origin = window . location . origin ;
266+ const revPart = rev ? `rev=${ encodeURIComponent ( rev ) } &` : "" ;
267+ return `${ origin } /db/${ dbName } /${ docId } ?${ revPart } preview=${ encodeURIComponent (
268+ path
269+ ) } `;
270+ } ;
271+
272+ // Copy helper
273+ const copyPreviewUrl = async ( path : string ) => {
274+ const url = buildPreviewUrl ( path ) ;
275+ try {
276+ await navigator . clipboard . writeText ( url ) ;
277+ setCopiedToast ( { open : true , text : "Preview link copied" } ) ;
278+ } catch {
279+ // fallback
280+ const ta = document . createElement ( "textarea" ) ;
281+ ta . value = url ;
282+ document . body . appendChild ( ta ) ;
283+ ta . select ( ) ;
284+ document . execCommand ( "copy" ) ;
285+ document . body . removeChild ( ta ) ;
286+ setCopiedToast ( { open : true , text : "Preview link copied" } ) ;
287+ }
288+ } ;
265289
266290 // useEffect(() => {
267291 // const fetchData = async () => {
@@ -386,6 +410,13 @@ const UpdatedDatasetDetailPage: React.FC = () => {
386410 }
387411 } , [ datasetDocument , docId ] ) ;
388412
413+ // const externalMap = React.useMemo(() => {
414+ // const m = new Map<string, { url: string; index: number }>();
415+ // for (const it of externalLinks)
416+ // m.set(it.path, { url: it.url, index: it.index });
417+ // return m;
418+ // }, [externalLinks]);
419+
389420 const [ previewOpen , setPreviewOpen ] = useState ( false ) ;
390421 const [ previewDataKey , setPreviewDataKey ] = useState < any > ( null ) ;
391422
@@ -563,6 +594,34 @@ const UpdatedDatasetDetailPage: React.FC = () => {
563594 [ datasetDocument ]
564595 ) ;
565596
597+ useEffect ( ( ) => {
598+ const p = searchParams . get ( "preview" ) ;
599+ if ( ! p || ! datasetDocument ) return ;
600+
601+ const previewPath = decodeURIComponent ( p ) ;
602+
603+ // Try internal data first
604+ const internal = internalMap . get ( previewPath ) ;
605+ if ( internal ) {
606+ handlePreview ( internal . data , internal . index , true ) ;
607+ return ;
608+ }
609+
610+ // Then try external data by JSON path
611+ const external = linkMap . get ( previewPath ) ;
612+ if ( external ) {
613+ handlePreview ( external . url , external . index , false ) ;
614+ }
615+ } , [
616+ datasetDocument ,
617+ internalLinks ,
618+ externalLinks ,
619+ searchParams ,
620+ internalMap ,
621+ // externalMap,
622+ linkMap ,
623+ ] ) ;
624+
566625 const handleClosePreview = ( ) => {
567626 setPreviewOpen ( false ) ;
568627 setPreviewDataKey ( null ) ;
@@ -976,26 +1035,48 @@ const UpdatedDatasetDetailPage: React.FC = () => {
9761035 { link . name } { " " }
9771036 { link . arraySize ? `[${ link . arraySize . join ( "x" ) } ]` : "" }
9781037 </ Typography >
979- < Button
980- variant = "contained"
981- size = "small"
982- sx = { {
983- backgroundColor : Colors . purple ,
984- flexShrink : 0 ,
985- minWidth : "70px" ,
986- fontSize : "0.7rem" ,
987- padding : "2px 6px" ,
988- lineHeight : 1 ,
989- "&:hover" : {
990- backgroundColor : Colors . secondaryPurple ,
991- } ,
992- } }
993- onClick = { ( ) =>
994- handlePreview ( link . data , link . index , true )
995- }
996- >
997- Preview
998- </ Button >
1038+ < Box sx = { { display : "flex" , flexShrink : 0 , gap : 1 } } >
1039+ < Button
1040+ variant = "contained"
1041+ size = "small"
1042+ sx = { {
1043+ backgroundColor : Colors . purple ,
1044+ flexShrink : 0 ,
1045+ minWidth : "70px" ,
1046+ fontSize : "0.7rem" ,
1047+ padding : "2px 6px" ,
1048+ lineHeight : 1 ,
1049+ "&:hover" : {
1050+ backgroundColor : Colors . secondaryPurple ,
1051+ } ,
1052+ } }
1053+ onClick = { ( ) =>
1054+ handlePreview ( link . data , link . index , true )
1055+ }
1056+ >
1057+ Preview
1058+ </ Button >
1059+ { /* <Button
1060+ variant="outlined"
1061+ size="small"
1062+ sx={{
1063+ color: Colors.purple,
1064+ borderColor: Colors.purple,
1065+ minWidth: "90px",
1066+ fontSize: "0.7rem",
1067+ padding: "2px 6px",
1068+ lineHeight: 1,
1069+ "&:hover": {
1070+ color: Colors.secondaryPurple,
1071+ borderColor: Colors.secondaryPurple,
1072+ },
1073+ }}
1074+ onClick={() => copyPreviewUrl(link.path)}
1075+ >
1076+ <ContentCopyIcon sx={{ fontSize: 16, mr: 0.5 }} />
1077+ Copy URL
1078+ </Button> */ }
1079+ </ Box >
9991080 </ Box >
10001081 ) )
10011082 ) : (
@@ -1129,6 +1210,28 @@ const UpdatedDatasetDetailPage: React.FC = () => {
11291210 Preview
11301211 </ Button >
11311212 ) }
1213+ { /* {isPreviewable && (
1214+ <Button
1215+ variant="outlined"
1216+ size="small"
1217+ sx={{
1218+ color: Colors.purple,
1219+ borderColor: Colors.purple,
1220+ minWidth: "90px",
1221+ fontSize: "0.7rem",
1222+ padding: "2px 6px",
1223+ lineHeight: 1,
1224+ "&:hover": {
1225+ color: Colors.secondaryPurple,
1226+ borderColor: Colors.secondaryPurple,
1227+ },
1228+ }}
1229+ onClick={() => copyPreviewUrl(link.path)} // <-- use the JSON path
1230+ >
1231+ <ContentCopyIcon sx={{ fontSize: 16, mr: 0.5 }} />
1232+ Copy URL
1233+ </Button>
1234+ )} */ }
11321235 </ Box >
11331236 </ Box >
11341237 ) ;
0 commit comments