Skip to content

Commit

Permalink
Merge pull request #1 from lsst-dm/tickets/DM-44957
Browse files Browse the repository at this point in the history
DM-44957: Initial development of v3
  • Loading branch information
ctslater authored Sep 26, 2024
2 parents dfd2d99 + 8e4edd8 commit 567a57a
Show file tree
Hide file tree
Showing 21 changed files with 656 additions and 317 deletions.
8 changes: 6 additions & 2 deletions .github/workflows/build-plot-navigator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,22 @@ on:
push:
tags:
- "*"
branches:
- "tickets/**"


jobs:
docker:
runs-on: ubuntu-latest

if: >
startsWith(github.ref, 'refs/tags/')
startsWith(github.ref, 'refs/tags/') ||
startsWith(github.ref, 'refs/heads/tickets/')
steps:

- name: Get tag name
run: echo "IMG_TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
run: echo "IMG_TAG=${GITHUB_REF_NAME#tickets/}" >> $GITHUB_ENV

-
name: Set up QEMU
Expand Down
40 changes: 40 additions & 0 deletions app/_components/TabNav.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
'use client'

import React from 'react'
import { useState } from 'react'
import Link from "next/link";
import { useSearchParams } from "next/navigation";


export default function TabNav({panes}) {
const searchParams = useSearchParams();

const [currentPane, setCurrentPane] = useState(searchParams.get("t") || 0)


const buttonClass = "p-2 border-t-2 border-x-2 float-left w-48 text-center hover:underline hover:cursor-pointer mx-2"
const buttons = panes.map((pane, n) => (
<Link replace scroll={false} key={n} href={`?t=${n}`} onClick={() => setCurrentPane(n)}>
<div className={currentPane == n ? buttonClass + " font-bold" : buttonClass} >
{pane.title}
</div>
</Link>
))

return (
<div className="p-4">
<div className="flow-root">
{buttons}
</div>
<div className="border-2 p-2 inline-block">
{panes[currentPane].content}
</div>
</div>

)


}



32 changes: 32 additions & 0 deletions app/_components/plotDisplay.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

import React from 'react';

export default async function PlotDisplay({plotEntry, showDataId = true, showDatasetType = false, showPermalink = false}) {

const {instrument, skymap, ...dataId} = JSON.parse(plotEntry.dataId)
const uuid = plotEntry.id
const repo = plotEntry.repo
const permalink = plotEntry.permalink ?? ''
const datasetType = plotEntry.datasetType ?? ''

const splitType = [...datasetType.matchAll(/[a-zA-Z0-9]*(_|$)/g)].map((x) => x[0])
const typeWithWbr = splitType.join('\u00ad')
/*
const typeWithWbr = splitType.map((x) => [x, <wbr/>]).flat()
console.log(typeWithWbr)
*/

const dataIdString = Object.entries(dataId).map(([k,v]) => `${k}: ${v}`).join(', ')

return (
<div className="m-2">
<div className="text-1xl my-5 text-wrap float-left">
{ showDataId ? dataIdString : "" }
{ showDatasetType ? typeWithWbr : "" }
</div>
{ showPermalink ? <div className="text-1xl float-right"><a href={`${process.env.BASE_URL ?? ''}/${permalink}`}>Plot link</a></div> : "" }
<img src={`${process.env.BASE_URL ?? '' }/image/${encodeURIComponent(repo)}/${uuid}`} />
</div>

)
}
100 changes: 100 additions & 0 deletions app/_components/plotPager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@

'use client'

import React from 'react';
import { useState } from 'react'

export default function PlotPager({plotEntries, plotsPerPage = 10}) {


const [currentPage, setCurrentPage] = useState(1)
const [inLightbox, setInLightbox] = useState(false)
const [displayedEntry, setDisplayedEntry] = useState(0)

const totalPages = Math.ceil(plotEntries.length/plotsPerPage)


const previousPage = () => {
if(currentPage > 1) {
setCurrentPage(currentPage - 1)
}
}

const nextPage = () => {
if(currentPage < totalPages) {
setCurrentPage(currentPage + 1)
}
}

const showLightboxEntry = (entry) => {
setDisplayedEntry(entry)
setInLightbox(true)
}

const exitLightbox = () => {
setInLightbox(false)
}
const doNothing = (e) => {
e.stopPropagation();
}

const advanceLeft = (e) => {
e.stopPropagation();
if(displayedEntry > 0) {
setDisplayedEntry(displayedEntry - 1)
}
}

const advanceRight = (e) => {
e.stopPropagation();
if(displayedEntry < (plotEntries.length - 1)) {
setDisplayedEntry(displayedEntry + 1)
}
}

return (
<div>
<div className="flex flex-row justify-center">
<div className="m-3">
{ currentPage > 1 ? <button className="p-2 rounded-md text-white bg-sky-600" onClick={previousPage}>Prev</button> :
<div>Prev</div> }
</div>
<div className="m-3">Page {currentPage}/{totalPages}</div>
<div className="m-3">
{ currentPage < totalPages ? <button className="p-2 rounded-md text-white bg-sky-600" onClick={nextPage}>Next</button> :
<div>Next</div> }
</div>
</div>
<div className="flex flex-row flex-wrap justify-center">
{plotEntries.slice((currentPage - 1) * plotsPerPage, currentPage * plotsPerPage).map((plotEntry, n) =>
<div key={n} className=" w-[28rem] p-1 m-0" onClick={() => showLightboxEntry(n + (currentPage - 1) * plotsPerPage)}>
{plotEntry}
</div>
)}
</div>
{ inLightbox ?
<div className="fixed top-0 left-0 w-screen h-screen bg-slate-500/75" onClick={exitLightbox}>
<div className="h-32"></div>
<div className="w-1/4 float-left h-1">
{displayedEntry > 0 ?
<div className="float-right flex items-center justify-center m-8 h-64 w-16 bg-indigo-100 hover:bg-indigo-600 hover:cursor-pointer" onClick={advanceLeft}>
<div>&lt;&lt;</div>
</div>
: "" }
</div>
<div className="w-1/2 float-left bg-white" onClick={doNothing}>
{plotEntries[displayedEntry]}
</div>
<div className="w-1/4 float-left">
{displayedEntry < (plotEntries.length - 1) ?
<div className="flex items-center justify-center m-8 h-64 w-16 bg-indigo-100 hover:bg-indigo-600 hover:cursor-pointer" onClick={advanceRight}>
<div>&gt;&gt;</div>
</div>
: "" }
</div>
</div>
: ""}
</div>
)

}
File renamed without changes.
57 changes: 48 additions & 9 deletions app/summaries.js → app/_lib/summaries.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ const zlib = require('zlib');

const { readFile } = require("fs/promises")

function GetButlerURL(repoName) {

const repoUrls = (() => {
try {
return JSON.parse(process.env.REPO_URLS)
} catch (err) {
console.error(`Could not parse REPO_URLS env var, ${err}`)
console.error(`REPO_URLS='${process.env.REPO_URLS}'`)
return {}
}
})()

return repoUrls[repoName]

}

function _getClient() {

const client = new S3Client({
Expand All @@ -18,6 +34,7 @@ function _getClient() {
secretAccessKey: process.env.S3_SECRET,
},
})

return client
}

Expand All @@ -26,7 +43,7 @@ async function _GetSummaryS3(repoName, collectionName) {
const client = _getClient()
const command = new GetObjectCommand({
Bucket: process.env.BUCKET_NAME,
Key: `${repoName}/collection_${encodeURIComponent(collectionName)}.json.gz`
Key: `${encodeURIComponent(repoName)}/collection_${encodeURIComponent(collectionName)}.json.gz`
})

try {
Expand All @@ -48,7 +65,7 @@ async function GetSummary(repoName, collectionName) {
return await _GetSummaryS3(repoName, collectionName)

} else {
const gzData = await readFile(`data/${repoName}/collection_${encodeURIComponent(collectionName)}.json.gz`)
const gzData = await readFile(`data/${encodeURIComponent(repoName)}/collection_${encodeURIComponent(collectionName)}.json.gz`)
const collectionData = JSON.parse(zlib.gunzipSync(gzData))
return collectionData
}
Expand All @@ -60,7 +77,7 @@ async function _ListSummariesS3(repoName) {
const client = _getClient()
const command = new ListObjectsV2Command({
Bucket: process.env.BUCKET_NAME,
Prefix: `${repoName}/`
Prefix: `${encodeURIComponent(repoName)}/`,
});

try {
Expand All @@ -72,7 +89,7 @@ async function _ListSummariesS3(repoName) {
const { Contents, IsTruncated, NextContinuationToken } =
await client.send(command)
if(Contents) {
filenameArrays.push(Contents.map((entry) => entry.Key))
filenameArrays.push(Contents)
}
isTruncated = IsTruncated
command.input.ContinuationToken = NextContinuationToken
Expand All @@ -86,7 +103,7 @@ async function _ListSummariesS3(repoName) {
}

async function _ListSummariesFilesystem(repoName) {
const repoDir = `data/${repoName}`
const repoDir = `data/${encodeURIComponent(repoName)}`
try {
return fs.readdirSync(repoDir).filter(
(filename) => filename.match("collection_(.*).json.gz"));
Expand All @@ -97,19 +114,41 @@ async function _ListSummariesFilesystem(repoName) {

async function ListSummaries() {

const repos = process.env.REPOS.split(',')
const decodeFilename = (filename) => {
const uriEncodedCollection = filename.match("collection_(.*).json.gz")[1]
return decodeURIComponent(uriEncodedCollection)
}

const repoUrls = (() => {
try {
return JSON.parse(process.env.REPO_URLS)
} catch (err) {
console.error(`Could not parse REPO_URLS env var, ${err}`)
console.error(`REPO_URLS='${process.env.REPO_URLS}'`)
return {}
}
})()

const repos = Object.keys(repoUrls)

if(process.env.BUCKET_NAME) {
const res = await Promise.all(repos.map(repo => _ListSummariesS3(repo)))
const res = await Promise.all(repos.map(repo =>
{
return _ListSummariesS3(repo).then((entries) => entries.map(entry => ({repo: repo, collection: decodeFilename(entry.Key), filename: entry.Key, lastModified: entry.LastModified})))
}))
return res.flat()
} else {
const res = await Promise.all(repos.map(repo => _ListSummariesFilesystem(repo)))
const res = await Promise.all(
repos.map(repo => _ListSummariesFilesystem(repo)
.then((filenames) => filenames.map(filename => ({repo: repo, collection: decodeFilename(filename), filename: filename}))))
)
return res.flat()
}

}

async function ListReports() {
return []

const client = _getClient()

Expand Down Expand Up @@ -161,4 +200,4 @@ async function GetReport(filename) {

}

export {ListSummaries, GetSummary, ListReports, GetReport}
export {ListSummaries, GetSummary, ListReports, GetReport, GetButlerURL}
Loading

0 comments on commit 567a57a

Please sign in to comment.