Skip to content

Commit

Permalink
add /api page to inspect AWS Open Data schema
Browse files Browse the repository at this point in the history
improve database_IDs rendering in MaterialCard
  • Loading branch information
janosh committed Jul 10, 2023
1 parent 58cf060 commit 83bc866
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 18 deletions.
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,3 @@ coverage

# secrets
.env

# needs server
/src/routes/api
2 changes: 1 addition & 1 deletion src/lib/api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const aws_bucket = `https://materialsproject-build.s3.amazonaws.com/collections/2022-10-28`
export const mp_build_bucket = `https://materialsproject-build.s3.amazonaws.com/collections/2022-10-28`

export async function decompress(blob: ReadableStream<Uint8Array> | null) {
// @ts-expect-error - TS doesn't know about DecompressionStream yet
Expand Down
30 changes: 20 additions & 10 deletions src/lib/material/MaterialCard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -44,24 +44,29 @@
value: material.origins,
condition: material.origins?.length,
},
{
title: `Database IDs`,
value: material.database_IDs.icsd,
condition: material.database_IDs?.icsd?.length ?? false,
},
].filter((itm) => itm?.condition ?? true)
</script>

<InfoCard {data} {...$$restProps} />

{#if material.task_ids?.length}
<details>
<summary>Related materials IDs</summary>
{#if material.task_ids?.length}
<p>
Task IDs: {@html material.task_ids
.filter((id) => id != material.material_id)
.map((id) => `<a href="https://materialsproject.org/tasks/${id}">${id}</a>`)
.join(`, `)}
Task IDs: {#each material.task_ids as id}
<a href="https://materialsproject.org/tasks/{id}">{id}</a>
{/each}
</p>
{/if}
{#if material.database_IDs.icsd?.length}

<p>
ICSD IDs: {#each material.database_IDs.icsd as id}
<a href="https://ccdc.cam.ac.uk/structures/Search?Ccdcid={id}&DatabaseToSearch=ICSD">{id}</a>
{/each}
</p>
{/if}
</details>

<p class="warning">
{material.warnings}
Expand All @@ -71,4 +76,9 @@
.warning {
color: var(--warning-color, darkred);
}
p {
display: flex;
flex-wrap: wrap;
gap: 0 1em;
}
</style>
98 changes: 98 additions & 0 deletions src/routes/api/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<script lang="ts">
import { fetch_zipped, mp_build_bucket } from '$lib/api'
import { url_param_store } from 'svelte-zoo'
export let data
const mp_id = url_param_store(`id`, `mp-1`)
$: aws_url = `${mp_build_bucket}/summary/${$mp_id}.json.gz`
const responses: Record<string, unknown> = {}
</script>

<main>
<h1>API Explorer</h1>
<center>
<input
placeholder="Enter MP material ID"
bind:value={$mp_id}
on:keydown={async (event) => {
if (event.key === `Enter`) data.summary = await fetch_zipped(aws_url)
}}
/>
<button on:click={async () => (data.summary = await fetch_zipped(aws_url))}>
Fetch material
</button>
</center>

<h2>Available AWS Open Data Buckets</h2>
<ol style="columns: 3;">
{#each data.buckets as bucket_name}
<li>
<code>{bucket_name}</code>
</li>
{/each}
</ol>
{#each data.buckets as bucket_name, idx}
<details
on:toggle={async () => {
let err = true
let id = 1
while (err && id < 20) {
try {
responses[bucket_name] = await fetch_zipped(
`${mp_build_bucket}/${bucket_name}/mp-${id}.json.gz`
)
err = false
} catch (err) {
id++
}
}
}}
>
<summary>
<h3>{idx+1}. <code>{bucket_name}</code> bucket</h3>
</summary>
<details open>
<summary><h4>Top-level keys</h4> </summary>
<ul>
{#each Object.entries(responses[bucket_name] ?? {}) as [key, val]}
<li><span class="key">{key}</span>: <small>{typeof val}</small></li>
{/each}
</ul>
</details>
<details>
<summary><h4>Full Response</h4></summary>

<pre>{JSON.stringify(data[bucket_name], null, 2)}</pre>
</details>
</details>
{/each}
</main>

<style>
h1 {
text-align: center;
}
ul {
list-style: none;
padding: 0;
display: flex;
flex-wrap: wrap;
gap: 5pt 3ex;
}
ul li .key {
font-weight: bold;
font-family: monospace;
}
ul li small {
font-weight: lighter;
}
summary :is(h3, h4) {
margin: 1ex;
display: inline-block;
}
details > :not(summary) {
padding-left: 1em;
}
</style>
23 changes: 23 additions & 0 deletions src/routes/api/+page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { fetch_zipped, mp_build_bucket } from '$lib/api'
import type { SummaryDoc } from '$lib/material/index'

export const ssr = false
const mp_build_url = `https://materialsproject-build.s3.amazonaws.com?delimiter=%2F&prefix=collections%2F2022-10-28%2F`

async function fetch_bucket_names() {
const text = await fetch(mp_build_url).then((res) => res.text())
const doc = new window.DOMParser().parseFromString(text, `text/xml`)
return [...doc.querySelectorAll(`Prefix`)]
.map((el) => el.textContent?.split(`/`)[2])
.filter(Boolean)
}

export const load = async () => {
const file = `mp-756175.json.gz`
const summary_url = `${mp_build_bucket}/summary/${file}`

return {
summary: fetch_zipped<SummaryDoc>(summary_url),
buckets: fetch_bucket_names(),
}
}
4 changes: 2 additions & 2 deletions src/routes/mp-[slug]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
import { goto } from '$app/navigation'
import { page } from '$app/stores'
import { MaterialCard, Structure, StructureCard } from '$lib'
import { aws_bucket, download, fetch_zipped } from '$lib/api'
import { download, fetch_zipped, mp_build_bucket } from '$lib/api'
export let data
let mp_id: string = `mp-${$page.params.slug}`
$: href = `https://materialsproject.org/materials/${mp_id}`
$: aws_url = `${aws_bucket}/summary/${mp_id}.json.gz`
$: aws_url = `${mp_build_bucket}/summary/${mp_id}.json.gz`
</script>

<main>
Expand Down
6 changes: 4 additions & 2 deletions src/routes/mp-[slug]/+page.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { aws_bucket, fetch_zipped } from '$lib/api.ts'
import { fetch_zipped, mp_build_bucket } from '$lib/api.ts'
import type { SummaryDoc } from '$lib/material/index.ts'

export const prerender = false

export const load = async ({ params }) => {
const file = `mp-${params.slug}.json.gz`
const summary_url = `${aws_bucket}/summary/${file}`
const summary_url = `${mp_build_bucket}/summary/${file}`
const similarity_url = `${mp_build_bucket}/similarity/${file}`

return {
summary: fetch_zipped<SummaryDoc>(summary_url),
similarity: fetch_zipped<SimilarityDoc>(similarity_url),
}
}

0 comments on commit 83bc866

Please sign in to comment.