From a6047093ae0a4631862946d2abc7f17be9106050 Mon Sep 17 00:00:00 2001
From: meyer <meyer@astron.nl>
Date: Fri, 13 Nov 2020 21:41:03 +0100
Subject: [PATCH] add thumbnail or DS9 view in page

---
 src/App.css                              | 71 -----------------------
 src/components/FitsViewer.js             | 20 -------
 src/components/query/ASTRONVOResults.js  | 73 ++++++++++--------------
 src/components/query/ApertifResults.js   | 20 +++----
 src/components/query/HandlePreview.js    | 34 +++++++++++
 src/components/query/Preview.js          | 31 ++++++++++
 src/components/query/VOServiceResults.js | 66 +++++++++++----------
 src/contexts/QueryContext.js             | 12 +++-
 src/routes/Routes.js                     |  4 --
 9 files changed, 146 insertions(+), 185 deletions(-)
 delete mode 100644 src/components/FitsViewer.js
 create mode 100644 src/components/query/HandlePreview.js
 create mode 100644 src/components/query/Preview.js

diff --git a/src/App.css b/src/App.css
index 03377a9..eaffbec 100644
--- a/src/App.css
+++ b/src/App.css
@@ -20,74 +20,3 @@
 .App-link {
   color: #1315c4;
 }
-
-.Observations-header {
-  background-color: #282c34;
-  min-height: 100vh;
-  display: flex;
-  flex-direction: column;
-  align-items: flex-start;
-  justify-content: inherit;
-  font-size: calc(10px + 2vmin);
-  color: white;
-}
-
-.card-img-top {
-  width: 30vh;
-  height: 15vw;
-  object-fit: cover;
-  background-color: darkgrey;
-}
-
-.card-datasource {
-  display: flex;
-  object-fit: cover;
-  background-color: #d4d4d4;
-}
-
-.card-description {
-  display: flex;
-
-  //background-color: #BBDEFB;
-  font-family: Raleway;
-  //font-size: 14pt;
-}
-
-.card-telescope {
-  display: flex;
-  width: 40vh;
-  height: 35vw;
-}
-
-.card-query {
-  display: inline;
-  align-items: flex-start;
-  justify-content: inherit;
-  background-color: lightgrey;
-}
-
-.key {
-  font-weight: bold;
-}
-
-.value {
-  font-style: italic;
-}
-
-@media (min-width:400px) {
-  .card-columns {
-    column-count: 1;
-  }
-}
-
-@media (min-width:800px) {
-  .card-columns {
-    column-count: 2;
-  }
-}
-
-@media (min-width:1200px) {
-  .card-columns {
-    column-count: 3;
-  }
-}
diff --git a/src/components/FitsViewer.js b/src/components/FitsViewer.js
deleted file mode 100644
index 239b20b..0000000
--- a/src/components/FitsViewer.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import React, { useContext } from "react";
-import { QueryContext } from "../contexts/QueryContext";
-
-export default function FitsViewer() {
-  const { fits } = useContext(QueryContext)
-  const url = "https://js9.si.edu/js9/js9.html?url="+JSON.parse(JSON.stringify(fits))+"&colormap=viridis&scale=log"
-
-  console.log(fits);
-  console.log("fits url: ", url);
-
-  return (
-    <div className="embed-responsive embed-responsive-16by9">
-      <iframe
-        className="embed-responsive-item"
-        src={url}
-        allowFullScreen
-      ></iframe>
-    </div>
-  );
-}
diff --git a/src/components/query/ASTRONVOResults.js b/src/components/query/ASTRONVOResults.js
index fda627c..4456145 100644
--- a/src/components/query/ASTRONVOResults.js
+++ b/src/components/query/ASTRONVOResults.js
@@ -1,13 +1,13 @@
 import React, { useContext } from "react";
-import { Table, Alert, Button } from "react-bootstrap";
-import { useHistory } from "react-router-dom";
+import { Table, Alert } from "react-bootstrap";
 import { QueryContext } from "../../contexts/QueryContext";
 import LoadingSpinner from "../LoadingSpinner";
 import Paginate from "../Paginate";
+import HandlePreview from "./HandlePreview";
+import Preview from "./Preview";
 
 export default function ASTRONVOResults({ catalog }) {
-  const { queryMap, page, setPage, setFits } = useContext(QueryContext);
-  const history = useHistory();
+  const { queryMap, page, setPage, preview } = useContext(QueryContext);
   if (!queryMap) return null;
   if (queryMap.get(catalog).status === "fetched") {
     if (!("results" in queryMap.get(catalog).results))
@@ -49,46 +49,31 @@ export default function ASTRONVOResults({ catalog }) {
           <tbody>
             {queryMap.get(catalog).results.results.map((result) => {
               return (
-                <tr key={result.result}>
-                  {/* <th>
-                  <InputGroup>
-                    <InputGroup.Checkbox />
-                  </InputGroup>
-                </th> */}
-                  <td>{result.obs_collection}</td>
-                  <td>{Number(result.ra).toFixed(1)}</td>
-                  <td>{Number(result.dec).toFixed(1)}</td>
-                  <td>{Number(result.fov).toFixed(1)}</td>
-                  <td>{result.dataproduct_type}</td>
-                  <td>{result.calibration_level}</td>
-                  <td>{Number((result.size / 1024).toFixed(1))} MB</td>
-                  <td>
-                    <a href={result.url} rel="noopener noreferrer" download>
-                      Download data
-                    </a>
-                  </td>
-                  <td>
-                    {/* if results is in .fits format and is smaller than 10 MB,
-                      display it with js9 */}
-                    {((result.url.includes('fits')  || (result.url.includes('FITS'))) && 
-                      Number(result.size) < 10000) ? 
-                      (<Button 
-                        onClick={() => {
-                          setFits(result.result);
-                          history.push('/fitsviewer');
-                        }}
-                      >View fits with DS9</Button>) :
-                      (result.thumbnail && (
-                        <a
-                          href={result.thumbnail}
-                          target="_blank"
-                          rel="noopener noreferrer"
-                          className="ml-3"
-                        >
-                          View Thumbnail
-                        </a>))}
-                  </td>
-                </tr>
+                <>
+                  <tr key={result.url}>
+                    {/* <th>
+                      <InputGroup>
+                        <InputGroup.Checkbox />
+                      </InputGroup>
+                      </th> */}
+                    <td>{result.obs_collection}</td>
+                    <td>{Number(result.ra).toFixed(1)}</td>
+                    <td>{Number(result.dec).toFixed(1)}</td>
+                    <td>{Number(result.fov).toFixed(1)}</td>
+                    <td>{result.dataproduct_type}</td>
+                    <td>{result.calibration_level}</td>
+                    <td>{Number((result.size / 1024).toFixed(1))} MB</td>
+                    <td>
+                      <a href={result.url} rel="noopener noreferrer" download>
+                        Download data
+                      </a>
+                    </td>
+                    <td>
+                      <HandlePreview result={result} />
+                    </td>
+                  </tr>
+                  {preview === result.url && <tr key={result.url}><Preview /></tr>}
+                </>
               );
             })}
           </tbody>
diff --git a/src/components/query/ApertifResults.js b/src/components/query/ApertifResults.js
index b262289..13a67f7 100644
--- a/src/components/query/ApertifResults.js
+++ b/src/components/query/ApertifResults.js
@@ -1,11 +1,13 @@
 import React, { useContext } from "react";
-import { Table, Alert } from "react-bootstrap";
+import { Table, Alert, Row } from "react-bootstrap";
 import { QueryContext } from "../../contexts/QueryContext";
 import LoadingSpinner from "../LoadingSpinner";
 import Paginate from "../Paginate";
+import HandlePreview from "./HandlePreview";
+import Preview from "./Preview";
 
 export default function ApertifResults({ catalog }) {
-  const { queryMap, page, setPage } = useContext(QueryContext);
+  const { queryMap, page, setPage, preview } = useContext(QueryContext);
   if (!queryMap) return null;
   if (queryMap.get(catalog).status === "fetched") {
     if (!("results" in queryMap.get(catalog).results))
@@ -47,6 +49,7 @@ export default function ApertifResults({ catalog }) {
           <tbody>
             {queryMap.get(catalog).results.results.map((result) => {
               return (
+                <>
                 <tr key={result.PID}>
                   {/* <th>
                   <InputGroup>
@@ -71,18 +74,11 @@ export default function ApertifResults({ catalog }) {
                     </a>
                   </td>
                   <td>
-                    {result.thumbnail ? (
-                      <a
-                        href={result.thumbnail}
-                        target="_blank"
-                        rel="noopener noreferrer"
-                        className="ml-3"
-                      >
-                        View Thumbnail
-                      </a>
-                    ) : null}
+                      <HandlePreview result={result} />
                   </td>
                 </tr>
+                {preview === result.url && <tr key={result.url}><Preview /></tr>}
+                </>
               );
             })}
           </tbody>
diff --git a/src/components/query/HandlePreview.js b/src/components/query/HandlePreview.js
new file mode 100644
index 0000000..04946bb
--- /dev/null
+++ b/src/components/query/HandlePreview.js
@@ -0,0 +1,34 @@
+import React, { useContext } from 'react';
+import { Button } from 'react-bootstrap';
+import { QueryContext } from '../../contexts/QueryContext';
+
+export default function HandlePreview({ result }) {
+    const { preview, setPreview, setDS9, setURL } = useContext(QueryContext);
+    return (
+        <>
+            {/* if results is in .fits format and is smaller than 10 MB,
+            display it with js9 */}
+            {((result.url.includes('fits')  || (result.url.includes('FITS'))) && 
+                Number(result.size) < 10000) ? 
+                (<Button 
+                    onClick={() => {
+                        preview ? setPreview("") : setPreview(result.url);
+                        setURL(result.url);
+                        setDS9(true);
+                    }}
+                >View fits with DS9</Button>) :
+                (result.thumbnail && (
+                    <Button
+                        onClick={()=>{
+                            preview ? setPreview("") : setPreview(result.url);
+                            setURL(result.thumbnail);
+                        }}
+                    >
+                        View Thumbnail
+                    </Button>
+                ))
+            }
+        </>
+    )
+}
+
diff --git a/src/components/query/Preview.js b/src/components/query/Preview.js
new file mode 100644
index 0000000..05cb708
--- /dev/null
+++ b/src/components/query/Preview.js
@@ -0,0 +1,31 @@
+import React, { useContext } from 'react';
+import { Image } from 'react-bootstrap';
+import { QueryContext } from '../../contexts/QueryContext';
+
+export default function Preview() {
+    const { preview, ds9, url, key  } = useContext(QueryContext);
+    return (
+        <>
+        {console.log("key: ", key)}
+        {console.log("url: ", url)}
+        {(preview &&
+            (ds9 ? 
+            <iframe
+                className="embed-responsive-item"
+                height="700"
+                width="700"
+                src={"https://js9.si.edu/js9/js9.html?url="+JSON.parse(JSON.stringify(url))+"&colormap=viridis&scale=log"}
+                allowFullScreen
+            ></iframe>
+            :
+            <Image 
+                width={700}
+                className={"mt-3"}
+                src={url}
+                alt=""
+            />)
+        )}
+        </>
+    )
+}
+
diff --git a/src/components/query/VOServiceResults.js b/src/components/query/VOServiceResults.js
index 1183589..f0c8f2d 100644
--- a/src/components/query/VOServiceResults.js
+++ b/src/components/query/VOServiceResults.js
@@ -1,13 +1,12 @@
 import React, { useContext } from "react";
-import { Redirect, useHistory } from "react-router-dom";
 import { Alert, Table, Button } from "react-bootstrap";
 import { QueryContext } from "../../contexts/QueryContext";
 import LoadingSpinner from "../LoadingSpinner";
 import Paginate from "../Paginate";
+import Preview from "./Preview";
 
 export default function VORegistryResults({ catalog }) {
-  const { queryMap, page, setPage, setFits } = useContext(QueryContext);
-  const history = useHistory();
+  const { queryMap, page, setPage, preview, setPreview, setURL, setDS9 } = useContext(QueryContext);
 
   if (!queryMap.get(catalog)) return null;
   console.log("VO service queryMap:", queryMap.get(catalog));
@@ -43,34 +42,39 @@ export default function VORegistryResults({ catalog }) {
           <tbody>
             {queryMap.get(catalog).results.results.map((result) => {
               return (
-                <tr key={result.result}>
-                  <td>
-                    <a href={result.result} rel="noopener noreferrer" download>
-                      {result.result}
-                    </a>
-                  </td>
-                  <td>
-                    {/* if results is in .fits format and is smaller than 10 MB,
-                    display it with js9 */}
-                    {((result.result.includes('fits')  || (result.result.includes('FITS'))) && 
-                      Number(result.size) < 10000) ? 
-                      (<Button 
-                        onClick={() => {
-                          setFits(result.result);
-                          history.push('/fitsviewer');
-                        }}
-                      >View fits with DS9</Button>) :
-                      (result.thumbnail && (
-                        <a
-                          href={result.thumbnail}
-                          target="_blank"
-                          rel="noopener noreferrer"
-                          className="ml-3"
-                        >
-                          View Thumbnail
-                        </a>))}
-                  </td>
-                </tr>
+                <>
+                  <tr key={result.result}>
+                    <td>
+                      <a href={result.result} rel="noopener noreferrer" download>
+                        {result.result}
+                      </a>
+                    </td>
+                    <td>
+                      {/* if results is in .fits format and is smaller than 10 MB,
+                      display it with js9 */}
+                      {((result.result.includes('fits')  || (result.result.includes('FITS'))) && 
+                        Number(result.size) < 10000) ? 
+                        (<Button 
+                          onClick={() => {
+                            preview ? setPreview("") : setPreview(result.result);
+                            setURL(result.result);
+                            setDS9(true);
+                          }}
+                        >View fits with DS9</Button>) :
+                        (result.thumbnail && (
+                          <Button
+                              onClick={()=>{
+                                  preview ? setPreview("") : setPreview(result.result);
+                                  setURL(result.thumbnail);
+                              }}
+                          >
+                              View Thumbnail
+                          </Button>
+                      ))}
+                    </td>
+                  </tr>
+                  {preview === result.url && <tr key={result.url}><Preview /></tr>}
+                </>
               );
             })}
           </tbody>
diff --git a/src/contexts/QueryContext.js b/src/contexts/QueryContext.js
index 602e881..65e2330 100644
--- a/src/contexts/QueryContext.js
+++ b/src/contexts/QueryContext.js
@@ -10,12 +10,14 @@ export function QueryContextProvider({ children }) {
   const queryMap = useMap();
   const [formData, setFormData] = useState();
   const [page, setPage] = useState(1);
-  const [fits, setFits] = useState("https://uilennest.net/astrobase/data/191231001/3836665.fits");
+  const [url, setURL] = useState("https://uilennest.net/astrobase/data/191231001/3836665.fits");
   const [dplevel, setDPLevel] = useState();
   const [collection, setCollection] = useState();
   const [config, setConfig] = useState();
   const [configName, setConfigName] = useState(defaultConf);
   const { api_host } = useContext(GlobalContext);
+  const [preview, setPreview] = useState(false);
+  const [ds9, setDS9] = useState(false);
 
   useEffect(() => {
     let configNameString = "";
@@ -53,8 +55,8 @@ export function QueryContextProvider({ children }) {
         queryMap,
         formData,
         setFormData,
-        fits,
-        setFits,
+        url,
+        setURL,
         dplevel,
         setDPLevel,
         collection,
@@ -62,6 +64,10 @@ export function QueryContextProvider({ children }) {
         config,
         setConfigName,
         defaultConf,
+        ds9,
+        setDS9,
+        preview,
+        setPreview,
       }}
     >
       {children}
diff --git a/src/routes/Routes.js b/src/routes/Routes.js
index b915d4a..b70b60d 100644
--- a/src/routes/Routes.js
+++ b/src/routes/Routes.js
@@ -11,7 +11,6 @@ import { QueryContext } from "../contexts/QueryContext";
 import Rucio from "../components/Rucio";
 import Interactive from "../components/Interactive";
 import { IVOAContextProvider } from "../contexts/IVOAContext";
-import FitsViewer from "../components/FitsViewer";
 
 export default function Routes() {
   const { handleLogin, handleLogout, handleError } = useContext(GlobalContext);
@@ -31,9 +30,6 @@ export default function Routes() {
         <Route exact path="/interactive">
           <Interactive />
         </Route>
-        <Route exact path="/fitsviewer">
-          <FitsViewer />
-        </Route>
         <Route exact path="/login" component={handleLogin} />
         <Route exact path="/logout" component={handleLogout} />
         <Route exact path="/error" component={handleError} />
-- 
GitLab