= ({ className, course }) => {
diff --git a/src/components/InterventionsMapSection.astro b/src/components/InterventionsMapSection.astro
index c675b234..3552a90d 100644
--- a/src/components/InterventionsMapSection.astro
+++ b/src/components/InterventionsMapSection.astro
@@ -28,7 +28,13 @@ const trimmedAndSorted = trimAndSortInterventions(
Latest Interventions
- When we go to place to support a project, build a maker space or perform a workshop, we call that an intervention. Every intervention has its unique partners, goals and outcomes, but every intervention helps to strengthen the ecosystem of the Ukraine.
+ When we go to place to support a project, build a maker space or perform a workshop, we call
+ that an intervention. Every intervention has its unique partners, goals and outcomes, but
+ every intervention helps to strengthen the ecosystem of the Ukraine.
(
))
}
diff --git a/src/components/NewsSliderDataWrapper.astro b/src/components/NewsSliderDataWrapper.astro
index 33d4d150..b0bdd912 100644
--- a/src/components/NewsSliderDataWrapper.astro
+++ b/src/components/NewsSliderDataWrapper.astro
@@ -1,62 +1,32 @@
---
import { NewsSliderComponent } from "@components";
-import { writeFileSync } from "fs";
+import { getNewsItems } from "@util/AirTable";
+import type { INewsItem } from "@interfaces/INews";
const { headline, id, ...rest } = Astro.props;
-const AIRTABLE_BASE_URL = "https://api.airtable.com/v0/";
-const token = import.meta.env.PUBLIC_AIRTABLE_TOKEN;
-
-const options = {
- method: "GET",
- headers: {
- Authorization: `Bearer ${token}`,
- },
-};
-
-const response = await fetch(
- AIRTABLE_BASE_URL + "appy8mE1ZpLXfYzEQ/tblvfXTgnme0tqIQD",
- options
-);
-
-const data = await response.json();
-
-let news = [];
-
-if (data.records && data.records.length > 0) {
- try {
- writeFileSync(
- "./fetch.json",
- JSON.stringify(data.records)
- );
- // file written successfully
- } catch (err) {
- console.error("Error while writing file", err);
- }
- news = data.records
- // has Instagram URL
- .filter((record) => record.fields?.["Instagram URL"])
- // has status "live"
- .filter((record) => record.fields?.["Status"] === "live")
- // is of media type "photo"
- .filter((record) => record.fields?.["Media type"]?.includes("photo"))
- // has images
- .filter((record) => record.fields?.["Selected Photos (from Event)"]?.length)
- .map((record) => {
- return {
- title: record.fields.Name,
- target: record.fields?.["Instagram URL"],
- instagram: true,
- image:
- record.fields?.["Selected Photos (from Event)"]?.[0].thumbnails?.[
- "large"
- ]?.url,
- };
- });
- console.log("NEWS", news);
-} else {
- console.log("Error");
-}
+const data = await getNewsItems();
+
+const news = data
+ // has Instagram URL
+ ?.filter((record) => record.fields?.["Instagram URL"])
+ // has status "live"
+ .filter((record) => record.fields?.["Status"] === "live")
+ // is of media type "photo"
+ .filter((record) => record.fields?.["Media type"]?.includes("photo"))
+ // has images
+ .filter((record) => record.fields?.["Selected Photos (from Event)"]?.length)
+ .map((record) => {
+ return {
+ title: record.fields.Name,
+ target: record.fields?.["Instagram URL"],
+ instagram: true,
+ image:
+ record.fields?.["Selected Photos (from Event)"]?.[0].thumbnails?.[
+ "large"
+ ]?.url,
+ } as INewsItem;
+ }).splice(30);
---
-
+
diff --git a/src/layouts/AcademyContent.astro b/src/layouts/AcademyContent.astro
index 231125e3..5d359ea9 100644
--- a/src/layouts/AcademyContent.astro
+++ b/src/layouts/AcademyContent.astro
@@ -46,7 +46,7 @@ const localeFromUrl =
title={frontmatter?.title}
teaser={frontmatter?.teaser}
category={parentPage?.frontmatter?.title}
- img={frontmatter?.img || parentPage.frontmatter?.img}
+ img={frontmatter?.img || parentPage?.frontmatter?.img}
/>
("../pages/**/_menu.mdx");
-const translatedMenu = rawMenus.find((rawMenu) =>
- rawMenu.url
- .split("/")
+const translatedMenu = rawMenus?.find((rawMenu) =>
+ rawMenu?.url
+ ?.split("/")
.filter(Boolean)
.map((urlPart) => urlPart.toLowerCase())
.includes(localeFromUrl)
-).frontmatter?.menu;
+)?.frontmatter?.menu;
-const translatedAndRebasedMenu = translatedMenu.map((menuItem) => ({
+const translatedAndRebasedMenu = translatedMenu?.map((menuItem) => ({
...menuItem,
target: baseUrl === "/" ? menuItem.target : baseUrl + menuItem.target,
}));
@@ -39,7 +39,7 @@ const translatedAndRebasedMenu = translatedMenu.map((menuItem) => ({
const isProduction = import.meta.env.MODE === "production";
---
-
+
diff --git a/src/layouts/InterventionIndex.astro b/src/layouts/InterventionIndex.astro
index 6d1abe8c..c173a4f2 100644
--- a/src/layouts/InterventionIndex.astro
+++ b/src/layouts/InterventionIndex.astro
@@ -37,8 +37,8 @@ const trimmedAndSorted = trimAndSortInterventions(rawInterventionsContent);
title={intervention.frontmatter?.title}
teaser={intervention.frontmatter?.teaser}
tags={[
- intervention.frontmatter?.tags?.[0],
- intervention.frontmatter?.tags?.[1],
+ intervention.frontmatter?.tags?.[0] || "",
+ intervention.frontmatter?.tags?.[1] || "",
]}
date={intervention.frontmatter?.date}
location={intervention.frontmatter?.location}
@@ -66,18 +66,20 @@ const trimmedAndSorted = trimAndSortInterventions(rawInterventionsContent);
bg={4}
target="mailto:info@tolocar.org"
actionCaption="Get in contact"
- >Schools, universities, NGOs, Startups and other organizations can reach
- out to us to request the Tolocars for projects, workshops and trainings.
+ Schools, universities, NGOs, Startups and other organizations can reach
+ out to us to request the Tolocars for projects, workshops and trainings.
+
We are looking for Makers, FabLabs, Hackerspaces, Makerspaces and other
- Communities who wants to partner with us in the Ukraine and
- internationally over the internet.
+ We are looking for Makers, FabLabs, Hackerspaces, Makerspaces and other
+ Communities who wants to partner with us in the Ukraine and
+ internationally over the internet.
+
diff --git a/src/layouts/InterventionSingleView.astro b/src/layouts/InterventionSingleView.astro
index fffcccea..ae4d4ce0 100644
--- a/src/layouts/InterventionSingleView.astro
+++ b/src/layouts/InterventionSingleView.astro
@@ -8,7 +8,7 @@ import {
InterventionSingleViewHeading,
} from "@components";
-const { frontmatter, url, file, headings } = Astro.props;
+const { frontmatter } = Astro.props;
const rawInterventionsContent = await Astro.glob
(
"../pages/en/interventions/*.mdx"
@@ -20,7 +20,7 @@ const rawInterventionsContentWithoutIndex = rawInterventionsContent.filter(
const relatedInterventions = rawInterventionsContentWithoutIndex.filter(
(interventionFromFilesystem) =>
- frontmatter.related?.some((slug) =>
+ frontmatter.related?.some((slug: string) =>
interventionFromFilesystem.url?.includes(slug)
)
);
@@ -55,12 +55,12 @@ const relatedInterventions = rawInterventionsContentWithoutIndex.filter(
{
relatedInterventions.map((intervention) => (
))
}
diff --git a/src/util/AirTable.ts b/src/util/AirTable.ts
new file mode 100644
index 00000000..63710797
--- /dev/null
+++ b/src/util/AirTable.ts
@@ -0,0 +1,73 @@
+import fs from "node:fs";
+
+const AIRTABLE_BASE_URL = "https://api.airtable.com/v0/";
+const AIRTABLE_BASE_ID = "appy8mE1ZpLXfYzEQ/tblvfXTgnme0tqIQD";
+
+const token = import.meta.env.PUBLIC_AIRTABLE_TOKEN;
+
+const commonHeaders = {
+ "content-type": "application/json",
+ Authorization: `Bearer ${token}`,
+};
+
+interface AirtableResponse {
+ records: Array<{
+ id?: string;
+ createdTime?: string;
+ fields: {
+ Name?: string;
+ "Instagram URL"?: string;
+ Status?: string;
+ "Media type"?: Array;
+ "Selected Photos (from Event)"?: Array<{
+ id?: string;
+ url?: string;
+ thumbnails?: {
+ small?: { url?: string };
+ medium?: { url?: string };
+ large?: { url?: string };
+ };
+ }>;
+ Type?: Array;
+ };
+ }>;
+}
+
+const fetchAndHandleErrors = async (
+ resource: RequestInfo,
+ options?: RequestInit
+): Promise => {
+ const response = await fetch(AIRTABLE_BASE_URL + resource, {
+ ...options,
+ headers: {
+ ...options?.headers,
+ ...commonHeaders,
+ },
+ });
+
+ console.log(JSON.stringify(response));
+
+ if (!response.ok) {
+ const text = await response.text();
+ console.error("Server returned Error: " + text);
+ throw new Error("Server returned Error: " + text);
+ }
+
+ return response.json();
+};
+
+export const getNewsItems = async () => {
+ const { records } = await fetchAndHandleErrors(
+ AIRTABLE_BASE_ID
+ );
+
+ if (records && records.length > 0) {
+ try {
+ fs.writeFileSync("./fetch.json", JSON.stringify(records));
+ // file written successfully
+ } catch (err) {
+ console.error("Error while writing file", err);
+ }
+ return records;
+ }
+};
diff --git a/tsconfig.json b/tsconfig.json
index 70bd0777..68685fa7 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,8 +1,9 @@
{
- "extends": "astro/tsconfigs/base",
+ "extends": "astro/tsconfigs/strict",
"compilerOptions": {
"jsx": "react",
"baseUrl": ".",
+ "verbatimModuleSyntax": true,
"paths": {
"@components": ["src/components"],
"@components/*": ["src/components/*"],