Skip to content
Merged
40 changes: 35 additions & 5 deletions src/api/OpenProcessing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ export type OpenProcessingCurationResponse = Array<{
title: string;
/** Description of sketch */
description: string;
instructions: string;
mode: string;
createdOn: string;
userID: string;
submittedOn: string;
/** Author's name */
Expand All @@ -36,16 +39,19 @@ export type OpenProcessingCurationResponse = Array<{
* @param limit max number of sketches to return
* @returns sketches
*/
export const getCurationSketches = async (
export const getCurationSketches = memoize(async (
limit?: number,
): Promise<OpenProcessingCurationResponse> => {
const limitParam = limit ? `limit=${limit}` : "";
const response = await fetch(
`${openProcessingEndpoint}curation/${curationId}/sketches?${limitParam}`,
);
if(!response.ok){ //log error instead of throwing error to not cache result in memoize
console.error('getCurationSketches', response.status, response.statusText)
}
const payload = await response.json();
return payload as OpenProcessingCurationResponse;
};
});

/**
* API Response from a call to the Sketch endpoint
Expand All @@ -69,26 +75,50 @@ export type OpenProcessingSketchResponse = {

/**
* Get info about a specific sketch from the OpenProcessing API
* First checks if the sketch is in the memoized curated sketches and returns the data if so,
* Otherwise calls OpenProcessing API for this specific sketch
*
* https://documenter.getpostman.com/view/16936458/2s9YC1Xa6X#7cd344f6-6e87-426a-969b-2b4a79701dd1
* @param id
* @returns
*/
export const getSketch = memoize(async (
id: string,
): Promise<OpenProcessingSketchResponse> => {
export const getSketch = memoize(
async (id: string): Promise<OpenProcessingSketchResponse> => {
// check for memoized sketch in curation sketches
const curationSketches = await getCurationSketches();
const memoizedSketch = curationSketches.find((el) => el.visualID === id);
if (memoizedSketch) {
return {
...memoizedSketch,
license: "",
} as OpenProcessingSketchResponse;
}

// check for sketch data in Open Processing API
const response = await fetch(`${openProcessingEndpoint}sketch/${id}`);
if (!response.ok) {
//log error instead of throwing error to not cache result in memoize
console.error("getSketch", id, response.status, response.statusText);
}
const payload = await response.json();
return payload as OpenProcessingSketchResponse;
});

/**
* Note: this currently calls `/api/sketch/:id/code`
* But only uses the width and height properties from this call
* Width and height should instead be added to properties for `/api/sketch/:id` or `api/curation/:curationId/sketches` instead
*/
export const getSketchSize = memoize(async (id: string) => {
const sketch = await getSketch(id)
if (sketch.mode !== 'p5js') {
return { width: undefined, height: undefined };
}

const response = await fetch(`${openProcessingEndpoint}sketch/${id}/code`);
if(!response.ok){ //log error instead of throwing error to not cache result in memoize
console.error('getSketchSize', id, response.status, response.statusText)
}
const payload = await response.json();

for (const tab of payload) {
Expand Down
94 changes: 48 additions & 46 deletions src/layouts/SketchLayout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -21,76 +21,83 @@ interface Props {
}

const { sketchId, authorName } = Astro.props;
const sketchInfo = await getSketch(sketchId);
const { title, createdOn, instructions } = await getSketch(sketchId);

const currentLocale = getCurrentLocale(Astro.url.pathname);
const t = await getUiTranslator(currentLocale);
const dateString = new Date(sketchInfo.createdOn).toLocaleDateString(
currentLocale,
{
year: "numeric",
month: "long",
day: "numeric",
}
);
const dateString = new Date(createdOn).toLocaleDateString(currentLocale, {
year: "numeric",
month: "long",
day: "numeric",
});

setJumpToState(null);
const moreSketches = await getRandomCurationSketches(4);
const featuredImageURL = makeThumbnailUrl(sketchInfo.visualID);
const featuredImageURL = makeThumbnailUrl(sketchId);

let { width, height } = await getSketchSize(sketchInfo.visualID);
let { width, height } = await getSketchSize(sketchId);
let heightOverWidth = 1 / 1.5;
if (width && height) {
// Account for OP header bar
height += 50;
heightOverWidth = height / width;
}

const iframeTitle = `OpenProcessing Sketch: ${sketchInfo.title} by ${authorName}`;
const iframeTitle = `OpenProcessing Sketch: ${title} by ${authorName}`;
---

<Head
title={sketchInfo.title}
title={title}
locale={currentLocale}
featuredImageSrc={featuredImageURL}
description={sketchInfo.instructions}
description={instructions}
/>

<BaseLayout
title={sketchInfo.title}
title={title}
titleAuthor={authorName}
subtitle={dateString}
variant="item"
topic={"community"}
>
<div class="max-w-[770px]">
<div style={{
position: 'relative',
width: '100%',
paddingBottom: `${(heightOverWidth * 100).toFixed(4)}%`,
}}>
{width ? (
<ScalingIframe
client:load
src={makeSketchEmbedUrl(sketchInfo.visualID)}
width={width}
height={height}
title={iframeTitle}
/>
) : (
<iframe
src={makeSketchEmbedUrl(sketchInfo.visualID)}
width="100%"
height="100%"
style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }}
title={iframeTitle}
/>
)}
<div
style={{
position: "relative",
width: "100%",
paddingBottom: `${(heightOverWidth * 100).toFixed(4)}%`,
}}
>
{
width ? (
<ScalingIframe
client:load
src={makeSketchEmbedUrl(sketchId)}
width={width}
height={height}
title={iframeTitle}
/>
) : (
<iframe
src={makeSketchEmbedUrl(sketchId)}
width="100%"
height="100%"
style={{
position: "absolute",
top: 0,
left: 0,
right: 0,
bottom: 0,
}}
title={iframeTitle}
/>
)
}
</div>
<div class="py-md grid gap-y-sm md:gap-y-md">
<LinkButton
variant="code"
url={`${makeSketchLinkUrl(sketchInfo.visualID)}/#code`}
url={`${makeSketchLinkUrl(sketchId)}/#code`}
class="min-w-[184px] lg:min-w-[220px]">{t("Show Code")}</LinkButton
>
<LinkButton
Expand All @@ -100,16 +107,11 @@ const iframeTitle = `OpenProcessing Sketch: ${sketchInfo.title} by ${authorName}
>
</div>

{
sketchInfo.instructions && (
<p class="text-md my-sm md:my-lg">{sketchInfo.instructions}</p>
)
}
{instructions && <p class="text-md my-sm md:my-lg">{instructions}</p>}

<p class="text-xs md:text-base mb-3xl">
This <a
class="text-type-magenta"
href={makeSketchLinkUrl(sketchInfo.visualID)}>sketch</a
This <a class="text-type-magenta" href={makeSketchLinkUrl(sketchId)}
>sketch</a
> is ported from the <a
class="text-type-magenta"
href="https://openprocessing.org">OpenProcessing</a
Expand Down
3 changes: 2 additions & 1 deletion src/pages/[locale]/community.astro
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import CommunityLayout from "@layouts/CommunityLayout.astro";
import { getCollectionInLocaleWithFallbacks } from "@pages/_utils";

export const getStaticPaths = async () => {
const sketches = await getCurationSketches(10);
const allSketches = await getCurationSketches();
const sketches = allSketches.slice(0, 10);
return await Promise.all(
nonDefaultSupportedLocales.map(async (locale) => {
const libraries = await getCollectionInLocaleWithFallbacks(
Expand Down
3 changes: 2 additions & 1 deletion src/pages/community.astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { getCurationSketches } from "../api/OpenProcessing";
import CommunityLayout from "../layouts/CommunityLayout.astro";
import { getCollectionInDefaultLocale } from "./_utils";

const sketches = await getCurationSketches(10);
const allSketches = await getCurationSketches(10);
const sketches = allSketches.slice(0, 10);
const libraries = await getCollectionInDefaultLocale("libraries");
const pastEvents = await getCollectionInDefaultLocale("events");
---
Expand Down