Skip to content

Commit cddfa9e

Browse files
authored
Use OpenProcessing api for sketches pages (#117)
* add open processing api based sketches index * add single sketch page * remove sketches collection * add LinkButton component placeholder * add sketch layout * add localized versions * support multiline page title * move api helper file * remove references to sketch collection * support limiting number of sketches returned by openprocessing api * fix props * add icons * some linkbutton styles * remove unneeded copy string * limit number of sketches until we have a real curation source * remove translation error log
1 parent 36fe19c commit cddfa9e

23 files changed

+304
-142
lines changed

src/api/OpenProcessing.ts

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// HELPER FUNCTIONS TO USE THE OPENPROCESSING API
2+
// SEE https://documenter.getpostman.com/view/16936458/2s9YC1Xa6X#intro
3+
4+
const openProcessingEndpoint = "https://openprocessing.org/api/";
5+
/**
6+
* ID of the OpenProcessing Curation we pull sketches from.
7+
* Currently a placeholder (https://openprocessing.org/curation/78544/)
8+
*/
9+
const curationId = "78544";
10+
11+
/**
12+
* API Response from a call to the Curation Sketches endpoint
13+
*
14+
* see https://documenter.getpostman.com/view/16936458/2s9YC1Xa6X#7cd344f6-6e87-426a-969b-2b4a79701dd1
15+
*/
16+
export type OpenProcessingCurationResponse = ReadonlyArray<{
17+
/** Sketch ID used for constructing URLs */
18+
visualID: string;
19+
/** Title of sketch */
20+
title: string;
21+
/** Description of sketch */
22+
description: string;
23+
userID: string;
24+
submittedOn: string;
25+
/** Author's name */
26+
fullname: string;
27+
}>;
28+
29+
/**
30+
* Get basic info for the sketches contained in a Curation
31+
* from the OpenProcessing API
32+
*
33+
* @param limit max number of sketches to return
34+
* @returns sketches
35+
*/
36+
export const getCurationSketches = async (
37+
// TODO: Remove when we have real data
38+
limit: number = 25,
39+
): Promise<OpenProcessingCurationResponse> => {
40+
const limitParam = limit ? `limit=${limit}` : "";
41+
const response = await fetch(
42+
`${openProcessingEndpoint}curation/${curationId}/sketches?${limitParam}`,
43+
);
44+
const payload = await response.json();
45+
return payload as OpenProcessingCurationResponse;
46+
};
47+
48+
/**
49+
* API Response from a call to the Sketch endpoint
50+
*
51+
* see https://documenter.getpostman.com/view/16936458/2s9YC1Xa6X#7cd344f6-6e87-426a-969b-2b4a79701dd1
52+
*/
53+
export type OpenProcessingSketchResponse = {
54+
/** Sketch ID used for constructing URLs */
55+
visualID: string;
56+
/** Title of sketch */
57+
title: string;
58+
/** Description of sketch */
59+
description: string;
60+
instructions: string;
61+
license: string;
62+
userID: string;
63+
submittedOn: string;
64+
createdOn: string;
65+
};
66+
67+
/**
68+
* Get info about a specific sketch from the OpenProcessing API
69+
*
70+
* https://documenter.getpostman.com/view/16936458/2s9YC1Xa6X#7cd344f6-6e87-426a-969b-2b4a79701dd1
71+
* @param id
72+
* @returns
73+
*/
74+
export const getSketch = async (
75+
id: string,
76+
): Promise<OpenProcessingSketchResponse> => {
77+
const response = await fetch(`${openProcessingEndpoint}sketch/${id}`);
78+
const payload = await response.json();
79+
return payload as OpenProcessingSketchResponse;
80+
};
81+
82+
export const makeSketchLinkUrl = (id: string) =>
83+
`https://openprocessing.org/sketch/${id}`;
84+
85+
export const makeThumbnailUrl = (id: string) =>
86+
`https://openprocessing-usercontent.s3.amazonaws.com/thumbnails/visualThumbnail${id}.jpg`;

src/components/Icon/index.tsx

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
interface IconProps {
2+
kind: "arrow" | "code-brackets";
3+
className?: string;
4+
}
5+
/**
6+
* Renders an icon
7+
*/
8+
export const Icon = (props: IconProps) => {
9+
switch (props.kind) {
10+
case "arrow":
11+
return (
12+
<svg
13+
width="21"
14+
height="11"
15+
viewBox="0 0 21 11"
16+
fill="none"
17+
xmlns="http://www.w3.org/2000/svg"
18+
aria-hidden
19+
className={props.className}
20+
>
21+
<path
22+
d="M15.353 0.146446L20.7065 5.5L15.353 10.8536C15.1577 11.0488 14.8411 11.0488 14.6459 10.8536C14.4506 10.6583 14.4506 10.3417 14.6459 10.1464L18.7923 6L4.99951 6C4.72337 6 4.49951 5.77614 4.49951 5.5C4.49951 5.22386 4.72337 5 4.99951 5L18.7923 5L14.6459 0.853553C14.4506 0.658291 14.4506 0.341708 14.6459 0.146446C14.8411 -0.0488155 15.1577 -0.0488155 15.353 0.146446Z"
23+
fill="black"
24+
/>
25+
</svg>
26+
);
27+
case "code-brackets":
28+
return (
29+
<svg
30+
width="22"
31+
height="18"
32+
viewBox="0 0 22 18"
33+
fill="none"
34+
xmlns="http://www.w3.org/2000/svg"
35+
aria-hidden
36+
className={props.className}
37+
>
38+
<path
39+
d="M13.9764 0.718843C14.0606 0.455859 13.9105 0.193701 13.641 0.133296C13.3716 0.0728911 13.0848 0.237114 13.0006 0.500098L7.87626 16.5001C7.79204 16.7631 7.94219 17.0252 8.21165 17.0856C8.4811 17.146 8.76782 16.9818 8.85205 16.7188L13.9764 0.718843Z"
40+
fill="black"
41+
/>
42+
<path
43+
d="M21.707 8.49999L16.3535 3.14644C16.1582 2.95118 15.8416 2.95118 15.6464 3.14644C15.4511 3.3417 15.4511 3.65828 15.6464 3.85355L20.2928 8.49999L15.6464 13.1464C15.4511 13.3417 15.4511 13.6583 15.6464 13.8535C15.8416 14.0488 16.1582 14.0488 16.3535 13.8535L21.707 8.49999Z"
44+
fill="black"
45+
/>
46+
<path
47+
d="M0.292969 8.49999L5.64652 13.8535C5.84178 14.0488 6.15837 14.0488 6.35363 13.8535C6.54889 13.6583 6.54889 13.3417 6.35363 13.1464L1.70718 8.49999L6.35363 3.85355C6.54889 3.65828 6.54889 3.3417 6.35363 3.14644C6.15837 2.95118 5.84178 2.95118 5.64652 3.14644L0.292969 8.49999Z"
48+
fill="black"
49+
/>
50+
</svg>
51+
);
52+
default:
53+
return null;
54+
}
55+
};

src/components/ItemPageHeader/index.astro

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ const { title } = Astro.props;
1313
<span>{">"}</span>
1414
<span>{title}</span>
1515
</div>
16-
<h1>{title}</h1>
16+
<h1 class="whitespace-pre-line">{title}</h1>
1717
</div>

src/components/LinkButton/index.astro

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
import { Icon } from "../Icon";
3+
interface Props {
4+
variant?: "link" | "code" | "bare";
5+
url: string;
6+
}
7+
8+
const { variant = "bare", url } = Astro.props;
9+
---
10+
11+
<a
12+
class="outline py-2 px-4 flex flex-nowrap w-fit items-center rounded-full"
13+
href={url}
14+
>
15+
<slot />
16+
{
17+
variant !== "bare" ? (
18+
<Icon
19+
className="ml-4"
20+
kind={variant === "link" ? "arrow" : "code-brackets"}
21+
/>
22+
) : null
23+
}
24+
</a>

src/components/RootPageHeader/index.astro

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ const { title, subtitle } = Astro.props;
33
---
44

55
<div class="bg-accent-color text-accent-type-color p-md pt-2xl">
6-
<h1>{title}</h1>
6+
<h1 class="whitespace-pre-line">{title}</h1>
77
<h2>{subtitle}</h2>
88
</div>

src/content/config.ts

-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { tutorialsCollection } from "./tutorials/config";
22
import { pastEventsCollection } from "./past-events/config";
33
import { librariesCollection } from "./libraries/config";
44
import { peopleCollection } from "./people/config";
5-
import { sketchesCollection } from "./sketches/config";
65
import { referenceCollection } from "./reference/config";
76
import { textDetailCollection } from "./text-detail/config";
87
import { examplesCollection } from "./examples/config";
@@ -19,7 +18,6 @@ export const collections = {
1918
"past-events": pastEventsCollection,
2019
libraries: librariesCollection,
2120
people: peopleCollection,
22-
sketches: sketchesCollection,
2321
reference: referenceCollection,
2422
"text-detail": textDetailCollection,
2523
examples: examplesCollection,

src/content/sketches/config.ts

-38
This file was deleted.

src/content/sketches/en/example.yaml

-12
This file was deleted.
-1.27 MB
Binary file not shown.

src/content/types.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,4 @@ export type ExampleDocContentItem = AstroBaseContentType<ExampleData>;
2424
*/
2525
export type ArchiveCollectionEntry =
2626
| CollectionEntry<"contributor-docs">
27-
| CollectionEntry<"past-events">
28-
| CollectionEntry<"sketches">;
27+
| CollectionEntry<"past-events">;

src/content/ui/en.yaml

+10-10
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,14 @@ Community Libraries: Community Libraries
3131
Parameters: Parameters
3232
Related References: Related References
3333
Related Examples: Related Examples
34+
Show Code: Show Code
3435
briefPageDescriptions:
35-
Reference: Find easy explanations for every piece of p5.js code.
36-
Examples: Explore the possibilities of p5.js with short examples.
37-
Tutorials: Start from scratch or expand your skills with step-by-step lessons in p5.js.
38-
Contribute: Get involved with p5.js—create, code, document, donate, teach, and more!
39-
Community: See what people around the world are making with p5.js, and share what you’re building
40-
Sketches: Get inspired by sketches from the p5.js community.
41-
Events: See how p5.js brings people together—or organize your own event.
42-
Libraries: Expand the possibilities of p5.js with community-created libraries.
43-
About: Learn about the mission, values, and people behind p5.js.
44-
People: Get to know the p5.js team.
36+
Reference: Further documentation of the p5.js language.
37+
Examples: Short, prototypical programs exploring the basics of programming with p5.js.
38+
Tutorials: A collection of lessons covering beginner, intermediate, and advanced topics
39+
Contribute: Ways to get involved with p5.js through code or donations.
40+
Community: p5.js is a community interested in exploring the creation of art and design with technology.
41+
Sketches Archive: FINAL COPY NEEDED
42+
Event Archive: FINAL COPY NEEDED
43+
Libraries Archive: FINAL COPY NEEDED
44+
People: FINAL COPY NEEDED

src/content/ui/es.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Community Libraries: Bibliotecas de la Comunidad
3131
Parameters: Parámetros
3232
Related References: Referencias Relacionadas
3333
Related Examples: Ejemplos Relacionados
34+
Show Code: Mostrar Código
3435
briefPageDescriptions:
3536
Reference: Documentación adicional del lenguaje p5.js.
3637
Examples: Programas prototípicos cortos que exploran los fundamentos de la programación con p5.js.

src/i18n/utils.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ export const useTranslations = async (
144144

145145
// If still not found, log a warning and return the last key as a fallback.
146146
if (val === undefined) {
147-
console.warn(`Translation key not found: ${args.join(".")}`);
147+
// console.warn(`Translation key not found: ${args.join(".")}`);
148148
return args[args.length - 1];
149149
}
150150

src/layouts/BaseLayout.astro

+4-8
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,19 @@
11
---
2-
import Footer from "@/src/components/Footer/index.astro";
2+
import Footer from "@components/Footer/index.astro";
33
import Nav from "@components/Nav/index.astro";
44
import Settings from "@components/Settings/index.astro";
55
import RootPageHeader from "@components/RootPageHeader/index.astro";
66
import ItemPageHeader from "@components/ItemPageHeader/index.astro";
77
import { getCurrentLocale, useTranslations } from "@i18n/utils";
88
import "@styles/base.scss";
99
10-
interface BaseLayoutProps {
10+
interface Props {
1111
title: string;
1212
className?: string;
13-
variant: "root" | "item";
13+
variant?: "root" | "item";
1414
}
1515
16-
const {
17-
title,
18-
className = "",
19-
variant = "root",
20-
} = Astro.props as BaseLayoutProps;
16+
const { title, className = "", variant = "root" } = Astro.props;
2117
const currentLocale = getCurrentLocale(Astro.url.pathname);
2218
const t = await useTranslations(currentLocale);
2319
const localizedTitle = t(title);

src/layouts/CommunityLayout.astro

+17-7
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,20 @@ import { getLibraryLink, removeLocaleAndExtension } from "../pages/_utils";
44
import BaseLayout from "./BaseLayout.astro";
55
import { Image } from "astro:assets";
66
import { getCurrentLocale, useTranslations } from "@i18n/utils";
7+
import {
8+
makeThumbnailUrl,
9+
type OpenProcessingCurationResponse,
10+
} from "../api/OpenProcessing";
711
812
interface Props {
9-
sketches: CollectionEntry<"sketches">[];
13+
sketches: OpenProcessingCurationResponse;
1014
libraries: CollectionEntry<"libraries">[];
1115
pastEvents: CollectionEntry<"past-events">[];
1216
}
1317
18+
// Max number of sketches we will show on this page
19+
const sketchLimit = 10;
20+
1421
const { sketches, libraries, pastEvents } = Astro.props;
1522
const currentLocale = getCurrentLocale(Astro.url.pathname);
1623
const t = await useTranslations(currentLocale);
@@ -19,17 +26,20 @@ const t = await useTranslations(currentLocale);
1926
<BaseLayout title="Community">
2027
<h2>{t("Sketches")}</h2>
2128
{
22-
sketches.map((entry) => (
29+
sketches.slice(0, sketchLimit).map((sk) => (
2330
<li>
31+
{
32+
// This isn't alt text ideal but we have no way of knowing what
33+
// the thumbnail looks like, and the OpenProcessing API
34+
// doesn't include that information
35+
}
2436
<Image
25-
src={entry.data.thumbnailImage}
26-
alt={entry.data.thumbnailImageAlt}
37+
src={makeThumbnailUrl(sk.visualID)}
38+
alt="Screenshot of sketch"
2739
width={200}
2840
height={200}
2941
/>
30-
<a href={`/sketches/${removeLocaleAndExtension(entry.id)}`}>
31-
{removeLocaleAndExtension(entry.id)}
32-
</a>
42+
<a href={`/sketches/${sk.visualID}`}>{sk.title}</a>
3343
</li>
3444
))
3545
}

0 commit comments

Comments
 (0)