mirror of
https://github.com/Unkn0wnCat/KevinK.dev.js.git
synced 2025-05-09 23:16:57 +02:00
Configure & Run prettier
This commit is contained in:
parent
79ab0bb9af
commit
420f8930fd
66 changed files with 31825 additions and 31500 deletions
|
@ -28,9 +28,7 @@
|
|||
"EditorConfig.EditorConfig"
|
||||
],
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
"forwardPorts": [
|
||||
8000
|
||||
],
|
||||
"forwardPorts": [8000],
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
"postCreateCommand": "npm install",
|
||||
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
|
||||
|
|
21
.eslintrc
21
.eslintrc
|
@ -1,15 +1,12 @@
|
|||
{
|
||||
"parser": "babel-eslint",
|
||||
"rules": {
|
||||
"strict": 0
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:react/recommended"
|
||||
],
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "detect"
|
||||
"parser": "babel-eslint",
|
||||
"rules": {
|
||||
"strict": 0
|
||||
},
|
||||
"extends": ["eslint:recommended", "plugin:react/recommended"],
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "detect"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
40
.github/workflows/build.yaml
vendored
40
.github/workflows/build.yaml
vendored
|
@ -1,30 +1,30 @@
|
|||
name: Build Site
|
||||
|
||||
on:
|
||||
push:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
update:
|
||||
name: Build Site
|
||||
runs-on: ubuntu-latest
|
||||
update:
|
||||
name: Build Site
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
name: Checkout Repo
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
name: Checkout Repo
|
||||
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '12.x'
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "12.x"
|
||||
|
||||
- run: npm install
|
||||
name: Install Dependencies
|
||||
- run: npm install
|
||||
name: Install Dependencies
|
||||
|
||||
- run: npm run build
|
||||
name: Build Site
|
||||
- run: npm run build
|
||||
name: Build Site
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
name: Upload Artifacts
|
||||
with:
|
||||
name: site
|
||||
path: public
|
||||
- uses: actions/upload-artifact@v2
|
||||
name: Upload Artifacts
|
||||
with:
|
||||
name: site
|
||||
path: public
|
||||
|
|
4
.prettierignore
Normal file
4
.prettierignore
Normal file
|
@ -0,0 +1,4 @@
|
|||
/.cache
|
||||
/.vscode
|
||||
/node_modules
|
||||
/public
|
8
.prettierrc.json
Normal file
8
.prettierrc.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 4,
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"jsxBracketSameLine": true,
|
||||
"endOfLine": "lf"
|
||||
}
|
30
config.js
30
config.js
|
@ -1,18 +1,18 @@
|
|||
// eslint-disable-next-line no-undef
|
||||
module.exports = {
|
||||
siteName: "KevinK.dev",
|
||||
siteAuthor: "@Unkn0wnKevin",
|
||||
siteURL: "https://kevink.dev",
|
||||
payPalMail: "kevin@1in9.net",
|
||||
siteKeywords:
|
||||
"Kevin Kandlbinder, Kevin, Kandlbinder, Web, Web Developer, Developer, JavaScript, PHP, Java, Photos, Fotos",
|
||||
iconPath: "src/images/fullbglogo@10x.png",
|
||||
languages: ["en", "de"],
|
||||
contactEmail: "kevin@kevink.dev",
|
||||
contactPhone: "+4941068068004",
|
||||
mapsLink: "https://goo.gl/maps/KVq9z1PVaVP2",
|
||||
contactTwitter: "Unkn0wnKevin",
|
||||
contactGitHub: "Unkn0wnCat",
|
||||
contactMastodon: "@kevin@1in1.net",
|
||||
contactMastodonHref: "https://mastodon.1in1.net/@kevin",
|
||||
siteName: "KevinK.dev",
|
||||
siteAuthor: "@Unkn0wnKevin",
|
||||
siteURL: "https://kevink.dev",
|
||||
payPalMail: "kevin@1in9.net",
|
||||
siteKeywords:
|
||||
"Kevin Kandlbinder, Kevin, Kandlbinder, Web, Web Developer, Developer, JavaScript, PHP, Java, Photos, Fotos",
|
||||
iconPath: "src/images/fullbglogo@10x.png",
|
||||
languages: ["en", "de"],
|
||||
contactEmail: "kevin@kevink.dev",
|
||||
contactPhone: "+4941068068004",
|
||||
mapsLink: "https://goo.gl/maps/KVq9z1PVaVP2",
|
||||
contactTwitter: "Unkn0wnKevin",
|
||||
contactGitHub: "Unkn0wnCat",
|
||||
contactMastodon: "@kevin@1in1.net",
|
||||
contactMastodonHref: "https://mastodon.1in1.net/@kevin",
|
||||
};
|
||||
|
|
206
gatsby-config.js
206
gatsby-config.js
|
@ -2,106 +2,112 @@
|
|||
const extConfig = require("./config");
|
||||
|
||||
module.exports = {
|
||||
siteMetadata: {
|
||||
title: extConfig.siteName,
|
||||
author: extConfig.siteAuthor,
|
||||
siteUrl: extConfig.siteURL,
|
||||
keywords: extConfig.siteKeywords,
|
||||
payPalMail: extConfig.payPalMail,
|
||||
contactEmail: extConfig.contactEmail,
|
||||
contactPhone: extConfig.contactPhone,
|
||||
mapsLink: extConfig.mapsLink,
|
||||
contactTwitter: extConfig.contactTwitter,
|
||||
contactGitHub: extConfig.contactGitHub,
|
||||
contactMastodon: extConfig.contactMastodon,
|
||||
contactMastodonHref: extConfig.contactMastodonHref,
|
||||
},
|
||||
assetPrefix: "/assets",
|
||||
plugins: [
|
||||
`gatsby-plugin-eslint`,
|
||||
{
|
||||
resolve: "gatsby-plugin-asset-path",
|
||||
},
|
||||
`gatsby-plugin-sharp`,
|
||||
`gatsby-transformer-sharp`,
|
||||
`gatsby-transformer-json`,
|
||||
{
|
||||
resolve: `gatsby-source-filesystem`,
|
||||
options: {
|
||||
path: `${__dirname}/content/textblocks`,
|
||||
name: `textblocks`,
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-source-filesystem`,
|
||||
options: {
|
||||
path: `${__dirname}/content/projectTextblocks`,
|
||||
name: `projectTextblocks`,
|
||||
},
|
||||
},
|
||||
"gatsby-plugin-mdx",
|
||||
{
|
||||
resolve: `gatsby-source-filesystem`,
|
||||
options: {
|
||||
path: `./content/`,
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-source-filesystem`,
|
||||
options: {
|
||||
path: `${__dirname}/locales`,
|
||||
name: `locale`,
|
||||
},
|
||||
},
|
||||
`gatsby-plugin-sass`,
|
||||
{
|
||||
resolve: `gatsby-plugin-manifest`,
|
||||
options: {
|
||||
name: extConfig.siteName,
|
||||
short_name: extConfig.siteName,
|
||||
start_url: `/`,
|
||||
background_color: `#000710`,
|
||||
theme_color: `#000710`,
|
||||
display: `minimal-ui`,
|
||||
icon: extConfig.iconPath, // This path is relative to the root of the site.
|
||||
cache_busting_mode: "none",
|
||||
},
|
||||
},
|
||||
`gatsby-plugin-robots-txt`,
|
||||
{
|
||||
resolve: `gatsby-plugin-offline`,
|
||||
options: {
|
||||
precachePages: ["/", "/en", "/en/projects", "/de", "/de/projects"],
|
||||
workboxConfig: {
|
||||
globPatterns: ["**/*"],
|
||||
},
|
||||
},
|
||||
},
|
||||
`gatsby-plugin-sitemap`,
|
||||
`gatsby-plugin-react-helmet`,
|
||||
{
|
||||
resolve: `gatsby-plugin-react-i18next`,
|
||||
options: {
|
||||
localeJsonSourceName: `locale`,
|
||||
languages: extConfig.languages,
|
||||
defaultLanguage: `en`,
|
||||
generateDefaultLanguagePage: true,
|
||||
siteMetadata: {
|
||||
title: extConfig.siteName,
|
||||
author: extConfig.siteAuthor,
|
||||
siteUrl: extConfig.siteURL,
|
||||
i18nextOptions: {
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
keySeparator: false,
|
||||
nsSeparator: false,
|
||||
},
|
||||
pages: [
|
||||
{
|
||||
matchPath: "/:lang/projects/:urlname",
|
||||
getLanguageFromPath: true,
|
||||
excludeLanguages: extConfig.languages,
|
||||
},
|
||||
],
|
||||
},
|
||||
keywords: extConfig.siteKeywords,
|
||||
payPalMail: extConfig.payPalMail,
|
||||
contactEmail: extConfig.contactEmail,
|
||||
contactPhone: extConfig.contactPhone,
|
||||
mapsLink: extConfig.mapsLink,
|
||||
contactTwitter: extConfig.contactTwitter,
|
||||
contactGitHub: extConfig.contactGitHub,
|
||||
contactMastodon: extConfig.contactMastodon,
|
||||
contactMastodonHref: extConfig.contactMastodonHref,
|
||||
},
|
||||
],
|
||||
assetPrefix: "/assets",
|
||||
plugins: [
|
||||
`gatsby-plugin-eslint`,
|
||||
{
|
||||
resolve: "gatsby-plugin-asset-path",
|
||||
},
|
||||
`gatsby-plugin-sharp`,
|
||||
`gatsby-transformer-sharp`,
|
||||
`gatsby-transformer-json`,
|
||||
{
|
||||
resolve: `gatsby-source-filesystem`,
|
||||
options: {
|
||||
path: `${__dirname}/content/textblocks`,
|
||||
name: `textblocks`,
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-source-filesystem`,
|
||||
options: {
|
||||
path: `${__dirname}/content/projectTextblocks`,
|
||||
name: `projectTextblocks`,
|
||||
},
|
||||
},
|
||||
"gatsby-plugin-mdx",
|
||||
{
|
||||
resolve: `gatsby-source-filesystem`,
|
||||
options: {
|
||||
path: `./content/`,
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-source-filesystem`,
|
||||
options: {
|
||||
path: `${__dirname}/locales`,
|
||||
name: `locale`,
|
||||
},
|
||||
},
|
||||
`gatsby-plugin-sass`,
|
||||
{
|
||||
resolve: `gatsby-plugin-manifest`,
|
||||
options: {
|
||||
name: extConfig.siteName,
|
||||
short_name: extConfig.siteName,
|
||||
start_url: `/`,
|
||||
background_color: `#000710`,
|
||||
theme_color: `#000710`,
|
||||
display: `minimal-ui`,
|
||||
icon: extConfig.iconPath, // This path is relative to the root of the site.
|
||||
cache_busting_mode: "none",
|
||||
},
|
||||
},
|
||||
`gatsby-plugin-robots-txt`,
|
||||
{
|
||||
resolve: `gatsby-plugin-offline`,
|
||||
options: {
|
||||
precachePages: [
|
||||
"/",
|
||||
"/en",
|
||||
"/en/projects",
|
||||
"/de",
|
||||
"/de/projects",
|
||||
],
|
||||
workboxConfig: {
|
||||
globPatterns: ["**/*"],
|
||||
},
|
||||
},
|
||||
},
|
||||
`gatsby-plugin-sitemap`,
|
||||
`gatsby-plugin-react-helmet`,
|
||||
{
|
||||
resolve: `gatsby-plugin-react-i18next`,
|
||||
options: {
|
||||
localeJsonSourceName: `locale`,
|
||||
languages: extConfig.languages,
|
||||
defaultLanguage: `en`,
|
||||
generateDefaultLanguagePage: true,
|
||||
siteUrl: extConfig.siteURL,
|
||||
i18nextOptions: {
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
keySeparator: false,
|
||||
nsSeparator: false,
|
||||
},
|
||||
pages: [
|
||||
{
|
||||
matchPath: "/:lang/projects/:urlname",
|
||||
getLanguageFromPath: true,
|
||||
excludeLanguages: extConfig.languages,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
299
gatsby-node.js
299
gatsby-node.js
|
@ -3,172 +3,177 @@ const path = require(`path`);
|
|||
const fs = require("fs");
|
||||
|
||||
exports.createPages = async ({ actions, graphql, reporter }) => {
|
||||
const { createPage } = actions;
|
||||
const { createPage } = actions;
|
||||
|
||||
const projectTemplate = path.resolve(`src/templates/project.js`);
|
||||
const projectTemplate = path.resolve(`src/templates/project.js`);
|
||||
|
||||
const result = await graphql(`
|
||||
query AllPagesQuery {
|
||||
allProjectsJson {
|
||||
nodes {
|
||||
lang
|
||||
urlname
|
||||
const result = await graphql(`
|
||||
query AllPagesQuery {
|
||||
allProjectsJson {
|
||||
nodes {
|
||||
lang
|
||||
urlname
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
if (result.errors) {
|
||||
reporter.panicOnBuild(`Error while running GraphQL query.`);
|
||||
return;
|
||||
}
|
||||
`);
|
||||
|
||||
if (result.errors) {
|
||||
reporter.panicOnBuild(`Error while running GraphQL query.`);
|
||||
return;
|
||||
}
|
||||
result.data.allProjectsJson.nodes.forEach((node) => {
|
||||
// eslint-disable-next-line no-undef
|
||||
console.log(
|
||||
"Creating Page: ",
|
||||
`/${node.lang}/projects/${node.urlname}`
|
||||
);
|
||||
|
||||
result.data.allProjectsJson.nodes.forEach((node) => {
|
||||
// eslint-disable-next-line no-undef
|
||||
console.log("Creating Page: ", `/${node.lang}/projects/${node.urlname}`);
|
||||
|
||||
if (node.lang !== "ignoreme")
|
||||
createPage({
|
||||
path: `/${node.lang}/projects/${node.urlname}`,
|
||||
component: projectTemplate,
|
||||
context: {
|
||||
lang: node.lang,
|
||||
urlname: node.urlname,
|
||||
},
|
||||
});
|
||||
});
|
||||
if (node.lang !== "ignoreme")
|
||||
createPage({
|
||||
path: `/${node.lang}/projects/${node.urlname}`,
|
||||
component: projectTemplate,
|
||||
context: {
|
||||
lang: node.lang,
|
||||
urlname: node.urlname,
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const config = require("./config.js");
|
||||
|
||||
exports.onPostBuild = async ({ graphql, reporter }) => {
|
||||
console.log("Building static api...");
|
||||
console.log("Building static api...");
|
||||
|
||||
const apiPrefix = "./public/api";
|
||||
const apiPrefix = "./public/api";
|
||||
|
||||
if (!fs.existsSync(apiPrefix)) fs.mkdirSync(apiPrefix);
|
||||
|
||||
fs.writeFileSync(
|
||||
`${apiPrefix}.json`,
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
endpoints: {
|
||||
projects: [
|
||||
{
|
||||
name: "Projects Overview",
|
||||
description: "Returns overview of all available projects",
|
||||
path: "/api/projects.json",
|
||||
},
|
||||
{
|
||||
name: "Projects Overview for Language",
|
||||
description:
|
||||
"Returns overview of all available projects in a specified language",
|
||||
path: "/api/projects/:lang.json",
|
||||
},
|
||||
{
|
||||
name: "Get specific Project",
|
||||
description: "Returns specific project in specified language",
|
||||
path: "/api/projects/:lang/:slug.json",
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
const projectsPrefix = apiPrefix + "/projects";
|
||||
|
||||
if (!fs.existsSync(projectsPrefix)) fs.mkdirSync(projectsPrefix);
|
||||
|
||||
await graphql(`
|
||||
query {
|
||||
allProjectsJson {
|
||||
nodes {
|
||||
urlname
|
||||
shortDescription
|
||||
name
|
||||
links {
|
||||
github
|
||||
website
|
||||
}
|
||||
lang
|
||||
image {
|
||||
publicURL
|
||||
}
|
||||
featured
|
||||
}
|
||||
}
|
||||
}
|
||||
`).then((res) => {
|
||||
if (res.errors) {
|
||||
reporter.panicOnBuild(`Error while running GraphQL query.`);
|
||||
return;
|
||||
}
|
||||
|
||||
let projects = res.data.allProjectsJson.nodes.filter((project) => {
|
||||
return project.lang !== "ignoreme";
|
||||
});
|
||||
if (!fs.existsSync(apiPrefix)) fs.mkdirSync(apiPrefix);
|
||||
|
||||
fs.writeFileSync(
|
||||
`${projectsPrefix}.json`,
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
projects: projects.map((project) => {
|
||||
return {
|
||||
slug: project.urlname,
|
||||
lang: project.lang,
|
||||
api: `/api/projects/${project.lang}/${project.urlname}.json`,
|
||||
};
|
||||
}),
|
||||
})
|
||||
`${apiPrefix}.json`,
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
endpoints: {
|
||||
projects: [
|
||||
{
|
||||
name: "Projects Overview",
|
||||
description:
|
||||
"Returns overview of all available projects",
|
||||
path: "/api/projects.json",
|
||||
},
|
||||
{
|
||||
name: "Projects Overview for Language",
|
||||
description:
|
||||
"Returns overview of all available projects in a specified language",
|
||||
path: "/api/projects/:lang.json",
|
||||
},
|
||||
{
|
||||
name: "Get specific Project",
|
||||
description:
|
||||
"Returns specific project in specified language",
|
||||
path: "/api/projects/:lang/:slug.json",
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
config.languages.forEach((lang) => {
|
||||
if (!fs.existsSync(`${projectsPrefix}/${lang}`))
|
||||
fs.mkdirSync(`${projectsPrefix}/${lang}`);
|
||||
const projectsPrefix = apiPrefix + "/projects";
|
||||
|
||||
fs.writeFileSync(
|
||||
`${projectsPrefix}/${lang}.json`,
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
projects: projects
|
||||
.filter((project) => {
|
||||
return project.lang == lang;
|
||||
if (!fs.existsSync(projectsPrefix)) fs.mkdirSync(projectsPrefix);
|
||||
|
||||
await graphql(`
|
||||
query {
|
||||
allProjectsJson {
|
||||
nodes {
|
||||
urlname
|
||||
shortDescription
|
||||
name
|
||||
links {
|
||||
github
|
||||
website
|
||||
}
|
||||
lang
|
||||
image {
|
||||
publicURL
|
||||
}
|
||||
featured
|
||||
}
|
||||
}
|
||||
}
|
||||
`).then((res) => {
|
||||
if (res.errors) {
|
||||
reporter.panicOnBuild(`Error while running GraphQL query.`);
|
||||
return;
|
||||
}
|
||||
|
||||
let projects = res.data.allProjectsJson.nodes.filter((project) => {
|
||||
return project.lang !== "ignoreme";
|
||||
});
|
||||
|
||||
fs.writeFileSync(
|
||||
`${projectsPrefix}.json`,
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
projects: projects.map((project) => {
|
||||
return {
|
||||
slug: project.urlname,
|
||||
lang: project.lang,
|
||||
api: `/api/projects/${project.lang}/${project.urlname}.json`,
|
||||
};
|
||||
}),
|
||||
})
|
||||
.map((project) => {
|
||||
return {
|
||||
slug: project.urlname,
|
||||
lang: project.lang,
|
||||
api: `/api/projects/${project.lang}/${project.urlname}.json`,
|
||||
};
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
);
|
||||
|
||||
projects.forEach((project) => {
|
||||
fs.writeFileSync(
|
||||
`${projectsPrefix}/${project.lang}/${project.urlname}.json`,
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
project: {
|
||||
slug: project.urlname,
|
||||
lang: project.lang,
|
||||
name: project.name,
|
||||
shortDescription: project.shortDescription,
|
||||
longDescription: project.longDescription,
|
||||
links:
|
||||
project.links !== null
|
||||
? {
|
||||
github: project.links.github,
|
||||
website: project.links.website,
|
||||
}
|
||||
: null,
|
||||
image: project.image.publicURL,
|
||||
featured: project.featured,
|
||||
frontend: `/${project.lang}/projects/${project.urlname}`,
|
||||
},
|
||||
})
|
||||
);
|
||||
config.languages.forEach((lang) => {
|
||||
if (!fs.existsSync(`${projectsPrefix}/${lang}`))
|
||||
fs.mkdirSync(`${projectsPrefix}/${lang}`);
|
||||
|
||||
fs.writeFileSync(
|
||||
`${projectsPrefix}/${lang}.json`,
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
projects: projects
|
||||
.filter((project) => {
|
||||
return project.lang == lang;
|
||||
})
|
||||
.map((project) => {
|
||||
return {
|
||||
slug: project.urlname,
|
||||
lang: project.lang,
|
||||
api: `/api/projects/${project.lang}/${project.urlname}.json`,
|
||||
};
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
projects.forEach((project) => {
|
||||
fs.writeFileSync(
|
||||
`${projectsPrefix}/${project.lang}/${project.urlname}.json`,
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
project: {
|
||||
slug: project.urlname,
|
||||
lang: project.lang,
|
||||
name: project.name,
|
||||
shortDescription: project.shortDescription,
|
||||
longDescription: project.longDescription,
|
||||
links:
|
||||
project.links !== null
|
||||
? {
|
||||
github: project.links.github,
|
||||
website: project.links.website,
|
||||
}
|
||||
: null,
|
||||
image: project.image.publicURL,
|
||||
featured: project.featured,
|
||||
frontend: `/${project.lang}/projects/${project.urlname}`,
|
||||
},
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
@ -11,9 +11,7 @@
|
|||
"develop": "gatsby develop",
|
||||
"start": "gatsby develop",
|
||||
"build": "gatsby build --prefix-paths",
|
||||
"build:fab": "npm run build && npm run fab:build",
|
||||
"fab:build": "fab build",
|
||||
"fab:serve": "fab serve fab.zip",
|
||||
"prettier": "npx prettier --write .",
|
||||
"serve": "gatsby serve",
|
||||
"clean": "gatsby clean"
|
||||
},
|
||||
|
@ -63,6 +61,7 @@
|
|||
"eslint-loader": "4.0.2",
|
||||
"eslint-plugin-import": "2.23.4",
|
||||
"eslint-plugin-react": "7.24.0",
|
||||
"gatsby-plugin-eslint": "2.0.8"
|
||||
"gatsby-plugin-eslint": "2.0.8",
|
||||
"prettier": "2.3.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,28 +4,28 @@ import { Link, Trans, useI18next } from "gatsby-plugin-react-i18next";
|
|||
import * as styles from "./languageSwitcher.module.scss";
|
||||
|
||||
export default function LanguageSwitcher() {
|
||||
const { languages, originalPath } = useI18next();
|
||||
const { languages, originalPath } = useI18next();
|
||||
|
||||
return (
|
||||
<div className={styles.languageModal} id="languageChooser">
|
||||
<div className={styles.languageModalInner}>
|
||||
<h2>
|
||||
Languages (
|
||||
<a href="#top" className={styles.modalCloseLink}>
|
||||
×
|
||||
</a>
|
||||
)
|
||||
</h2>
|
||||
<ul>
|
||||
{languages.map((lng) => (
|
||||
<li key={lng}>
|
||||
<Link to={originalPath} language={lng}>
|
||||
<Trans>{lng}</Trans>
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div className={styles.languageModal} id="languageChooser">
|
||||
<div className={styles.languageModalInner}>
|
||||
<h2>
|
||||
Languages (
|
||||
<a href="#top" className={styles.modalCloseLink}>
|
||||
×
|
||||
</a>
|
||||
)
|
||||
</h2>
|
||||
<ul>
|
||||
{languages.map((lng) => (
|
||||
<li key={lng}>
|
||||
<Link to={originalPath} language={lng}>
|
||||
<Trans>{lng}</Trans>
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,86 +6,87 @@ import { graphql, StaticQuery } from "gatsby";
|
|||
import * as styles from "./navigation.module.scss";
|
||||
|
||||
const Navigation = ({ isHome }) => {
|
||||
let [atTop, setAtTop] = useState(false);
|
||||
let [atTop, setAtTop] = useState(false);
|
||||
|
||||
const updateTransparency = () => {
|
||||
if (typeof window === "undefined") return;
|
||||
const updateTransparency = () => {
|
||||
if (typeof window === "undefined") return;
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
if (window.scrollY < 15) {
|
||||
if (!atTop) setAtTop(true);
|
||||
} else {
|
||||
if (atTop) setAtTop(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window === "undefined") return;
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
window.addEventListener("scroll", updateTransparency);
|
||||
// eslint-disable-next-line no-undef
|
||||
window.addEventListener("navigate", updateTransparency);
|
||||
|
||||
updateTransparency();
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
let int = window.setInterval(updateTransparency, 10000);
|
||||
|
||||
return () => {
|
||||
// eslint-disable-next-line no-undef
|
||||
window.removeEventListener("scroll", updateTransparency);
|
||||
// eslint-disable-next-line no-undef
|
||||
window.removeEventListener("navigate", updateTransparency);
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
window.clearInterval(int);
|
||||
// eslint-disable-next-line no-undef
|
||||
if (window.scrollY < 15) {
|
||||
if (!atTop) setAtTop(true);
|
||||
} else {
|
||||
if (atTop) setAtTop(false);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
styles.topBar +
|
||||
(isHome ? " " + styles.homeBar : "") +
|
||||
(atTop ? " " + styles.homeBarTransparent : "")
|
||||
}
|
||||
>
|
||||
<nav className={styles.topBarInner}>
|
||||
<StaticQuery
|
||||
query={graphql`
|
||||
query {
|
||||
site {
|
||||
siteMetadata {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
`}
|
||||
render={(data) => (
|
||||
<Link to="/" activeClassName={styles.active}>
|
||||
{data.site.siteMetadata.title}
|
||||
</Link>
|
||||
)}
|
||||
/>
|
||||
<div className="flexSpacer"></div>
|
||||
<Link
|
||||
id="navBtnProjects"
|
||||
to="/projects"
|
||||
activeClassName={styles.active}
|
||||
>
|
||||
<Trans>projects</Trans>
|
||||
</Link>
|
||||
<Link id="navBtnSocial" to="/social" activeClassName={styles.active}>
|
||||
<Trans>social</Trans>
|
||||
</Link>
|
||||
</nav>
|
||||
</div>
|
||||
);
|
||||
useEffect(() => {
|
||||
if (typeof window === "undefined") return;
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
window.addEventListener("scroll", updateTransparency);
|
||||
// eslint-disable-next-line no-undef
|
||||
window.addEventListener("navigate", updateTransparency);
|
||||
|
||||
updateTransparency();
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
let int = window.setInterval(updateTransparency, 10000);
|
||||
|
||||
return () => {
|
||||
// eslint-disable-next-line no-undef
|
||||
window.removeEventListener("scroll", updateTransparency);
|
||||
// eslint-disable-next-line no-undef
|
||||
window.removeEventListener("navigate", updateTransparency);
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
window.clearInterval(int);
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
styles.topBar +
|
||||
(isHome ? " " + styles.homeBar : "") +
|
||||
(atTop ? " " + styles.homeBarTransparent : "")
|
||||
}>
|
||||
<nav className={styles.topBarInner}>
|
||||
<StaticQuery
|
||||
query={graphql`
|
||||
query {
|
||||
site {
|
||||
siteMetadata {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
`}
|
||||
render={(data) => (
|
||||
<Link to="/" activeClassName={styles.active}>
|
||||
{data.site.siteMetadata.title}
|
||||
</Link>
|
||||
)}
|
||||
/>
|
||||
<div className="flexSpacer"></div>
|
||||
<Link
|
||||
id="navBtnProjects"
|
||||
to="/projects"
|
||||
activeClassName={styles.active}>
|
||||
<Trans>projects</Trans>
|
||||
</Link>
|
||||
<Link
|
||||
id="navBtnSocial"
|
||||
to="/social"
|
||||
activeClassName={styles.active}>
|
||||
<Trans>social</Trans>
|
||||
</Link>
|
||||
</nav>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Navigation.propTypes = {
|
||||
isHome: PropTypes.bool.isRequired,
|
||||
isHome: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
export default Navigation;
|
||||
|
|
|
@ -5,89 +5,89 @@ import { useStaticQuery, graphql } from "gatsby";
|
|||
import { useTranslation } from "gatsby-plugin-react-i18next";
|
||||
|
||||
function SEO({ description, meta, title }) {
|
||||
const { t } = useTranslation();
|
||||
const { site } = useStaticQuery(
|
||||
graphql`
|
||||
query {
|
||||
site {
|
||||
siteMetadata {
|
||||
title
|
||||
author
|
||||
keywords
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
);
|
||||
const { t } = useTranslation();
|
||||
const { site } = useStaticQuery(
|
||||
graphql`
|
||||
query {
|
||||
site {
|
||||
siteMetadata {
|
||||
title
|
||||
author
|
||||
keywords
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
const metaDescription = description || t("siteDescription");
|
||||
const metaDescription = description || t("siteDescription");
|
||||
|
||||
return (
|
||||
<Helmet
|
||||
title={title}
|
||||
titleTemplate={`%s | ${site.siteMetadata.title}`}
|
||||
meta={[
|
||||
{
|
||||
name: `description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
{
|
||||
property: `og:title`,
|
||||
content: title,
|
||||
},
|
||||
{
|
||||
property: `og:description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
{
|
||||
property: `og:type`,
|
||||
content: `website`,
|
||||
},
|
||||
{
|
||||
name: `twitter:card`,
|
||||
content: `summary`,
|
||||
},
|
||||
{
|
||||
name: `twitter:creator`,
|
||||
content: site.siteMetadata.author,
|
||||
},
|
||||
{
|
||||
name: `twitter:title`,
|
||||
content: title,
|
||||
},
|
||||
{
|
||||
name: `twitter:description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
{
|
||||
name: "keywords",
|
||||
content: site.siteMetadata.keywords,
|
||||
},
|
||||
].concat(meta)}
|
||||
>
|
||||
<script
|
||||
src="https://kit.fontawesome.com/1377f925e0.js"
|
||||
crossOrigin="anonymous"
|
||||
></script>
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Anonymous+Pro:wght@400;700&family=Roboto&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<meta name="battery-savings" content="allow-reduced-framerate"></meta>
|
||||
</Helmet>
|
||||
);
|
||||
return (
|
||||
<Helmet
|
||||
title={title}
|
||||
titleTemplate={`%s | ${site.siteMetadata.title}`}
|
||||
meta={[
|
||||
{
|
||||
name: `description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
{
|
||||
property: `og:title`,
|
||||
content: title,
|
||||
},
|
||||
{
|
||||
property: `og:description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
{
|
||||
property: `og:type`,
|
||||
content: `website`,
|
||||
},
|
||||
{
|
||||
name: `twitter:card`,
|
||||
content: `summary`,
|
||||
},
|
||||
{
|
||||
name: `twitter:creator`,
|
||||
content: site.siteMetadata.author,
|
||||
},
|
||||
{
|
||||
name: `twitter:title`,
|
||||
content: title,
|
||||
},
|
||||
{
|
||||
name: `twitter:description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
{
|
||||
name: "keywords",
|
||||
content: site.siteMetadata.keywords,
|
||||
},
|
||||
].concat(meta)}>
|
||||
<script
|
||||
src="https://kit.fontawesome.com/1377f925e0.js"
|
||||
crossOrigin="anonymous"></script>
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Anonymous+Pro:wght@400;700&family=Roboto&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<meta
|
||||
name="battery-savings"
|
||||
content="allow-reduced-framerate"></meta>
|
||||
</Helmet>
|
||||
);
|
||||
}
|
||||
|
||||
SEO.defaultProps = {
|
||||
meta: [],
|
||||
description: ``,
|
||||
meta: [],
|
||||
description: ``,
|
||||
};
|
||||
|
||||
SEO.propTypes = {
|
||||
description: PropTypes.string,
|
||||
meta: PropTypes.arrayOf(PropTypes.object),
|
||||
title: PropTypes.string.isRequired,
|
||||
description: PropTypes.string,
|
||||
meta: PropTypes.arrayOf(PropTypes.object),
|
||||
title: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default SEO;
|
||||
|
|
|
@ -8,55 +8,55 @@ import { Link, Trans } from "gatsby-plugin-react-i18next";
|
|||
import LanguageSwitcher from "../components/languageSwitcher";
|
||||
|
||||
class Layout extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
<SEO
|
||||
description={this.props.description}
|
||||
lang={this.props.lang}
|
||||
meta={this.props.meta}
|
||||
title={this.props.title}
|
||||
/>
|
||||
<Navigation isHome={this.props.transparentTopbar} />
|
||||
<div id="content" role="main">
|
||||
{this.props.children}
|
||||
</div>
|
||||
<footer role="contentinfo">
|
||||
CC-BY 4.0 Kevin Kandlbinder,{" "}
|
||||
<Link to="/legal/about" className="spf-link">
|
||||
<Trans i18nKey="imprint">Imprint</Trans>
|
||||
</Link>{" "}
|
||||
|{" "}
|
||||
<Link to="/legal/datasec" className="spf-link">
|
||||
<Trans i18nKey="datasec">Data Protection</Trans>
|
||||
</Link>{" "}
|
||||
|{" "}
|
||||
<Link to="/legal/disclaimer" className="spf-link">
|
||||
<Trans i18nKey="disclaimer">Disclaimer</Trans>
|
||||
</Link>{" "}
|
||||
| <a href="#languageChooser">Language</a>
|
||||
</footer>
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
<SEO
|
||||
description={this.props.description}
|
||||
lang={this.props.lang}
|
||||
meta={this.props.meta}
|
||||
title={this.props.title}
|
||||
/>
|
||||
<Navigation isHome={this.props.transparentTopbar} />
|
||||
<div id="content" role="main">
|
||||
{this.props.children}
|
||||
</div>
|
||||
<footer role="contentinfo">
|
||||
CC-BY 4.0 Kevin Kandlbinder,{" "}
|
||||
<Link to="/legal/about" className="spf-link">
|
||||
<Trans i18nKey="imprint">Imprint</Trans>
|
||||
</Link>{" "}
|
||||
|{" "}
|
||||
<Link to="/legal/datasec" className="spf-link">
|
||||
<Trans i18nKey="datasec">Data Protection</Trans>
|
||||
</Link>{" "}
|
||||
|{" "}
|
||||
<Link to="/legal/disclaimer" className="spf-link">
|
||||
<Trans i18nKey="disclaimer">Disclaimer</Trans>
|
||||
</Link>{" "}
|
||||
| <a href="#languageChooser">Language</a>
|
||||
</footer>
|
||||
|
||||
<LanguageSwitcher />
|
||||
</>
|
||||
);
|
||||
}
|
||||
<LanguageSwitcher />
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Layout.defaultProps = {
|
||||
module: `none`,
|
||||
meta: [],
|
||||
description: ``,
|
||||
transparentTopbar: false,
|
||||
module: `none`,
|
||||
meta: [],
|
||||
description: ``,
|
||||
transparentTopbar: false,
|
||||
};
|
||||
|
||||
Layout.propTypes = {
|
||||
description: PropTypes.string,
|
||||
lang: PropTypes.string,
|
||||
meta: PropTypes.arrayOf(PropTypes.object),
|
||||
title: PropTypes.string.isRequired,
|
||||
transparentTopbar: PropTypes.bool,
|
||||
children: PropTypes.any.isRequired,
|
||||
description: PropTypes.string,
|
||||
lang: PropTypes.string,
|
||||
meta: PropTypes.arrayOf(PropTypes.object),
|
||||
title: PropTypes.string.isRequired,
|
||||
transparentTopbar: PropTypes.bool,
|
||||
children: PropTypes.any.isRequired,
|
||||
};
|
||||
|
||||
export default Layout;
|
||||
|
|
|
@ -3,19 +3,19 @@ import { Link } from "gatsby-plugin-react-i18next";
|
|||
import Layout from "../layouts/default";
|
||||
|
||||
const NotFoundPage = () => {
|
||||
return (
|
||||
<Layout title="Not found">
|
||||
<section>
|
||||
<article>
|
||||
<h1>Page not found</h1>
|
||||
<p>
|
||||
Whoops... That page doesn't exist, so you may as well{" "}
|
||||
<Link to="/">go home</Link>.
|
||||
</p>
|
||||
</article>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
return (
|
||||
<Layout title="Not found">
|
||||
<section>
|
||||
<article>
|
||||
<h1>Page not found</h1>
|
||||
<p>
|
||||
Whoops... That page doesn't exist, so you may as
|
||||
well <Link to="/">go home</Link>.
|
||||
</p>
|
||||
</article>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotFoundPage;
|
||||
|
|
|
@ -8,128 +8,135 @@ import GitHubButton from "react-github-btn";
|
|||
import * as styles from "./donate.module.scss";
|
||||
|
||||
export const query = graphql`
|
||||
query($language: String!) {
|
||||
site {
|
||||
siteMetadata {
|
||||
title
|
||||
siteUrl
|
||||
payPalMail
|
||||
contactGitHub
|
||||
}
|
||||
}
|
||||
file(relativePath: { eq: "images/pplogo.png" }) {
|
||||
childImageSharp {
|
||||
resize(width: 240, height: 240, fit: CONTAIN) {
|
||||
src
|
||||
query ($language: String!) {
|
||||
site {
|
||||
siteMetadata {
|
||||
title
|
||||
siteUrl
|
||||
payPalMail
|
||||
contactGitHub
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
locales: allLocale(filter: { language: { eq: $language } }) {
|
||||
edges {
|
||||
node {
|
||||
ns
|
||||
data
|
||||
language
|
||||
file(relativePath: { eq: "images/pplogo.png" }) {
|
||||
childImageSharp {
|
||||
resize(width: 240, height: 240, fit: CONTAIN) {
|
||||
src
|
||||
}
|
||||
}
|
||||
}
|
||||
locales: allLocale(filter: { language: { eq: $language } }) {
|
||||
edges {
|
||||
node {
|
||||
ns
|
||||
data
|
||||
language
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const DonatePage = (props) => {
|
||||
const [amount, setAmount] = useState(5);
|
||||
const { t } = useI18next();
|
||||
const { path } = React.useContext(I18nextContext);
|
||||
const [amount, setAmount] = useState(5);
|
||||
const { t } = useI18next();
|
||||
const { path } = React.useContext(I18nextContext);
|
||||
|
||||
const { site, file } = props.data;
|
||||
const { site, file } = props.data;
|
||||
|
||||
return (
|
||||
<Layout title={t("donate")} description={t("donationCatchphrase")}>
|
||||
<section>
|
||||
<article>
|
||||
<h1>
|
||||
<Trans>donate</Trans>
|
||||
</h1>
|
||||
return (
|
||||
<Layout title={t("donate")} description={t("donationCatchphrase")}>
|
||||
<section>
|
||||
<article>
|
||||
<h1>
|
||||
<Trans>donate</Trans>
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
<Trans>donateDescription</Trans>
|
||||
</p>
|
||||
<p>
|
||||
<Trans>donateDescription</Trans>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<Trans>donateGitHub</Trans>
|
||||
</p>
|
||||
<p>
|
||||
<Trans>donateGitHub</Trans>
|
||||
</p>
|
||||
|
||||
<p style={{ display: "block", textAlign: "center" }}>
|
||||
<GitHubButton
|
||||
href={
|
||||
"https://github.com/sponsors/" + site.siteMetadata.contactGitHub
|
||||
}
|
||||
data-color-scheme="no-preference: light; light: dark; dark: dark;"
|
||||
data-icon="octicon-heart"
|
||||
data-size="large"
|
||||
aria-label="Sponsor @Unkn0wnCat on GitHub"
|
||||
>
|
||||
<Trans>sponsorGitHub</Trans>
|
||||
</GitHubButton>
|
||||
</p>
|
||||
<p style={{ display: "block", textAlign: "center" }}>
|
||||
<GitHubButton
|
||||
href={
|
||||
"https://github.com/sponsors/" +
|
||||
site.siteMetadata.contactGitHub
|
||||
}
|
||||
data-color-scheme="no-preference: light; light: dark; dark: dark;"
|
||||
data-icon="octicon-heart"
|
||||
data-size="large"
|
||||
aria-label="Sponsor @Unkn0wnCat on GitHub">
|
||||
<Trans>sponsorGitHub</Trans>
|
||||
</GitHubButton>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<Trans>donatePayPal</Trans>
|
||||
</p>
|
||||
<p>
|
||||
<Trans>donatePayPal</Trans>
|
||||
</p>
|
||||
|
||||
<div className={styles.priceAmount}>
|
||||
<label htmlFor="priceInput" className={styles.sronly}>
|
||||
Amount
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
min="1"
|
||||
placeholder="10.00"
|
||||
step="1"
|
||||
value={amount}
|
||||
onChange={(ev) => {
|
||||
setAmount(ev.target.value);
|
||||
}}
|
||||
name="priceInput"
|
||||
id="priceInput"
|
||||
/>
|
||||
<div>€</div>
|
||||
</div>
|
||||
<div className={styles.priceAmount}>
|
||||
<label htmlFor="priceInput" className={styles.sronly}>
|
||||
Amount
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
min="1"
|
||||
placeholder="10.00"
|
||||
step="1"
|
||||
value={amount}
|
||||
onChange={(ev) => {
|
||||
setAmount(ev.target.value);
|
||||
}}
|
||||
name="priceInput"
|
||||
id="priceInput"
|
||||
/>
|
||||
<div>€</div>
|
||||
</div>
|
||||
|
||||
<a
|
||||
className={styles.donateButton}
|
||||
rel="noopener"
|
||||
id="payPalBtn"
|
||||
href={
|
||||
"https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=" +
|
||||
encodeURIComponent(site.siteMetadata.payPalMail) +
|
||||
"&item_name=" +
|
||||
encodeURIComponent(site.siteMetadata.title) +
|
||||
"¤cy_code=EUR&image_url=" +
|
||||
encodeURIComponent(
|
||||
site.siteMetadata.siteUrl + file.childImageSharp.resize.src
|
||||
) +
|
||||
"&return=" +
|
||||
encodeURIComponent(
|
||||
site.siteMetadata.siteUrl + "/" + path + "thank-you/"
|
||||
) +
|
||||
"&rm=0&cancel_return=" +
|
||||
encodeURIComponent(site.siteMetadata.siteUrl + "/" + path) +
|
||||
"&amount=" +
|
||||
amount
|
||||
}
|
||||
>
|
||||
<span>Donate using PayPal</span>
|
||||
<i className="fas fa-fw fa-chevron-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
</article>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
<a
|
||||
className={styles.donateButton}
|
||||
rel="noopener"
|
||||
id="payPalBtn"
|
||||
href={
|
||||
"https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=" +
|
||||
encodeURIComponent(site.siteMetadata.payPalMail) +
|
||||
"&item_name=" +
|
||||
encodeURIComponent(site.siteMetadata.title) +
|
||||
"¤cy_code=EUR&image_url=" +
|
||||
encodeURIComponent(
|
||||
site.siteMetadata.siteUrl +
|
||||
file.childImageSharp.resize.src
|
||||
) +
|
||||
"&return=" +
|
||||
encodeURIComponent(
|
||||
site.siteMetadata.siteUrl +
|
||||
"/" +
|
||||
path +
|
||||
"thank-you/"
|
||||
) +
|
||||
"&rm=0&cancel_return=" +
|
||||
encodeURIComponent(
|
||||
site.siteMetadata.siteUrl + "/" + path
|
||||
) +
|
||||
"&amount=" +
|
||||
amount
|
||||
}>
|
||||
<span>Donate using PayPal</span>
|
||||
<i
|
||||
className="fas fa-fw fa-chevron-right"
|
||||
aria-hidden="true"></i>
|
||||
</a>
|
||||
</article>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
DonatePage.propTypes = {
|
||||
data: PropTypes.object.isRequired,
|
||||
data: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default DonatePage;
|
||||
|
|
|
@ -5,51 +5,55 @@ import { graphql } from "gatsby";
|
|||
import PropTypes from "prop-types";
|
||||
|
||||
export const query = graphql`
|
||||
query GetThankYouPage($language: String!) {
|
||||
site {
|
||||
siteMetadata {
|
||||
contactEmail
|
||||
}
|
||||
}
|
||||
locales: allLocale(filter: { language: { eq: $language } }) {
|
||||
edges {
|
||||
node {
|
||||
ns
|
||||
data
|
||||
language
|
||||
query GetThankYouPage($language: String!) {
|
||||
site {
|
||||
siteMetadata {
|
||||
contactEmail
|
||||
}
|
||||
}
|
||||
locales: allLocale(filter: { language: { eq: $language } }) {
|
||||
edges {
|
||||
node {
|
||||
ns
|
||||
data
|
||||
language
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const ThankYouPage = (props) => {
|
||||
const { site } = props.data;
|
||||
const { site } = props.data;
|
||||
|
||||
let contactEmail = site.siteMetadata.contactEmail;
|
||||
const { t } = useI18next();
|
||||
return (
|
||||
<Layout title={t("donate")}>
|
||||
<section>
|
||||
<article>
|
||||
<h1>
|
||||
<Trans>donateThanks</Trans>
|
||||
</h1>
|
||||
let contactEmail = site.siteMetadata.contactEmail;
|
||||
const { t } = useI18next();
|
||||
return (
|
||||
<Layout title={t("donate")}>
|
||||
<section>
|
||||
<article>
|
||||
<h1>
|
||||
<Trans>donateThanks</Trans>
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
<Trans contactEmail={contactEmail} i18nKey="donateThanksText">
|
||||
donateThanksText
|
||||
<a href={"mailto:" + contactEmail}>{{ contactEmail }}</a>
|
||||
</Trans>
|
||||
</p>
|
||||
</article>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
<p>
|
||||
<Trans
|
||||
contactEmail={contactEmail}
|
||||
i18nKey="donateThanksText">
|
||||
donateThanksText
|
||||
<a href={"mailto:" + contactEmail}>
|
||||
{{ contactEmail }}
|
||||
</a>
|
||||
</Trans>
|
||||
</p>
|
||||
</article>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
ThankYouPage.propTypes = {
|
||||
data: PropTypes.object.isRequired,
|
||||
data: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default ThankYouPage;
|
||||
|
|
|
@ -7,31 +7,31 @@ import PropTypes from "prop-types";
|
|||
import * as styles from "./friends.module.scss";
|
||||
|
||||
export const query = graphql`
|
||||
query AllFriendsQuery($language: String!) {
|
||||
allFriendsJson {
|
||||
nodes {
|
||||
name
|
||||
profession
|
||||
url
|
||||
imageURL
|
||||
}
|
||||
}
|
||||
locales: allLocale(filter: { language: { eq: $language } }) {
|
||||
edges {
|
||||
node {
|
||||
ns
|
||||
data
|
||||
language
|
||||
query AllFriendsQuery($language: String!) {
|
||||
allFriendsJson {
|
||||
nodes {
|
||||
name
|
||||
profession
|
||||
url
|
||||
imageURL
|
||||
}
|
||||
}
|
||||
locales: allLocale(filter: { language: { eq: $language } }) {
|
||||
edges {
|
||||
node {
|
||||
ns
|
||||
data
|
||||
language
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const FriendsPage = ({ data }) => {
|
||||
const { t } = useI18next();
|
||||
const { t } = useI18next();
|
||||
|
||||
/*function shuffle(a) {
|
||||
/*function shuffle(a) {
|
||||
for (let i = a.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[a[i], a[j]] = [a[j], a[i]];
|
||||
|
@ -39,59 +39,102 @@ const FriendsPage = ({ data }) => {
|
|||
return a;
|
||||
}*/
|
||||
|
||||
return (
|
||||
<Layout title={t("friends")} description={t("friendsDescription")}>
|
||||
<section>
|
||||
<article>
|
||||
<h1>
|
||||
<Trans>social</Trans>
|
||||
</h1>
|
||||
return (
|
||||
<Layout title={t("friends")} description={t("friendsDescription")}>
|
||||
<section>
|
||||
<article>
|
||||
<h1>
|
||||
<Trans>social</Trans>
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
<Trans>friendsDescription</Trans>
|
||||
</p>
|
||||
<p>
|
||||
<Trans>friendsDescription</Trans>
|
||||
</p>
|
||||
|
||||
<div className={styles.friendsList}>
|
||||
{/*shuffle(*/data.allFriendsJson.nodes/*)*/.map((friend) => {
|
||||
return (
|
||||
<div
|
||||
className={styles.friendProfile}
|
||||
key={friend.url + "#" + friend.name}
|
||||
>
|
||||
<div
|
||||
className={styles.friendImage}
|
||||
style={{ backgroundImage: "url(" + friend.imageURL + ")" }}
|
||||
key={friend.url + "#" + friend.name + "#image"}
|
||||
>
|
||||
<span className={styles.friendName} key={friend.url + "#" + friend.name + "#name"}>{friend.name}</span>
|
||||
<span className={styles.friendTitle} key={friend.url + "#" + friend.name + "#profession"}>
|
||||
{friend.profession}
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.friendsList}>
|
||||
{
|
||||
/*shuffle(*/ data.allFriendsJson.nodes /*)*/
|
||||
.map((friend) => {
|
||||
return (
|
||||
<div
|
||||
className={styles.friendProfile}
|
||||
key={
|
||||
friend.url + "#" + friend.name
|
||||
}>
|
||||
<div
|
||||
className={styles.friendImage}
|
||||
style={{
|
||||
backgroundImage:
|
||||
"url(" +
|
||||
friend.imageURL +
|
||||
")",
|
||||
}}
|
||||
key={
|
||||
friend.url +
|
||||
"#" +
|
||||
friend.name +
|
||||
"#image"
|
||||
}>
|
||||
<span
|
||||
className={
|
||||
styles.friendName
|
||||
}
|
||||
key={
|
||||
friend.url +
|
||||
"#" +
|
||||
friend.name +
|
||||
"#name"
|
||||
}>
|
||||
{friend.name}
|
||||
</span>
|
||||
<span
|
||||
className={
|
||||
styles.friendTitle
|
||||
}
|
||||
key={
|
||||
friend.url +
|
||||
"#" +
|
||||
friend.name +
|
||||
"#profession"
|
||||
}>
|
||||
{friend.profession}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className={styles.contactLinks} key={friend.url + "#" + friend.name + "#links"}>
|
||||
<a
|
||||
className={styles.contactLink}
|
||||
href={friend.url}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<i className="fas fa-globe-europe" aria-hidden="true"></i>{" "}
|
||||
{friend.url}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
<div
|
||||
className={styles.contactLinks}
|
||||
key={
|
||||
friend.url +
|
||||
"#" +
|
||||
friend.name +
|
||||
"#links"
|
||||
}>
|
||||
<a
|
||||
className={
|
||||
styles.contactLink
|
||||
}
|
||||
href={friend.url}
|
||||
target="_blank"
|
||||
rel="noreferrer">
|
||||
<i
|
||||
className="fas fa-globe-europe"
|
||||
aria-hidden="true"></i>{" "}
|
||||
{friend.url}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
FriendsPage.propTypes = {
|
||||
data: PropTypes.object.isRequired,
|
||||
data: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default FriendsPage;
|
||||
|
|
|
@ -12,244 +12,253 @@ import { MDXRenderer } from "gatsby-plugin-mdx";
|
|||
import anime from "animejs";
|
||||
import { tsParticles } from "tsparticles";
|
||||
|
||||
|
||||
import * as particleConfig from "./index.particles.json";
|
||||
|
||||
export const query = graphql`
|
||||
query GetMetaAndProjects($language: String) {
|
||||
site {
|
||||
siteMetadata {
|
||||
contactEmail
|
||||
contactPhone
|
||||
mapsLink
|
||||
contactTwitter
|
||||
contactGitHub
|
||||
contactMastodon
|
||||
contactMastodonHref
|
||||
}
|
||||
}
|
||||
allProjectsJson(
|
||||
filter: { lang: { eq: $language }, featured: { gte: 0 } }
|
||||
sort: { fields: featured, order: ASC }
|
||||
) {
|
||||
nodes {
|
||||
lang
|
||||
urlname
|
||||
name
|
||||
image {
|
||||
childImageSharp {
|
||||
resize(width: 400, quality: 90) {
|
||||
src
|
||||
query GetMetaAndProjects($language: String) {
|
||||
site {
|
||||
siteMetadata {
|
||||
contactEmail
|
||||
contactPhone
|
||||
mapsLink
|
||||
contactTwitter
|
||||
contactGitHub
|
||||
contactMastodon
|
||||
contactMastodonHref
|
||||
}
|
||||
}
|
||||
}
|
||||
shortDescription
|
||||
featured
|
||||
}
|
||||
}
|
||||
locales: allLocale(filter: { language: { eq: $language } }) {
|
||||
edges {
|
||||
node {
|
||||
ns
|
||||
data
|
||||
language
|
||||
allProjectsJson(
|
||||
filter: { lang: { eq: $language }, featured: { gte: 0 } }
|
||||
sort: { fields: featured, order: ASC }
|
||||
) {
|
||||
nodes {
|
||||
lang
|
||||
urlname
|
||||
name
|
||||
image {
|
||||
childImageSharp {
|
||||
resize(width: 400, quality: 90) {
|
||||
src
|
||||
}
|
||||
}
|
||||
}
|
||||
shortDescription
|
||||
featured
|
||||
}
|
||||
}
|
||||
locales: allLocale(filter: { language: { eq: $language } }) {
|
||||
edges {
|
||||
node {
|
||||
ns
|
||||
data
|
||||
language
|
||||
}
|
||||
}
|
||||
}
|
||||
file(
|
||||
sourceInstanceName: { eq: "textblocks" }
|
||||
relativeDirectory: { eq: "home/about" }
|
||||
name: { eq: $language }
|
||||
) {
|
||||
id
|
||||
childMdx {
|
||||
body
|
||||
}
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
file(
|
||||
sourceInstanceName: {eq: "textblocks"}, relativeDirectory: {eq: "home/about"}, name: {eq: $language}
|
||||
) {
|
||||
id
|
||||
childMdx {
|
||||
body
|
||||
}
|
||||
name
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const IndexPage = (props) => {
|
||||
React.useEffect(() => {
|
||||
if (typeof window === "undefined") return;
|
||||
React.useEffect(() => {
|
||||
if (typeof window === "undefined") return;
|
||||
|
||||
anime({
|
||||
targets: [
|
||||
"." + styles.profileCard + " > span",
|
||||
"." + styles.profileCard + " a",
|
||||
],
|
||||
opacity: [0, 1],
|
||||
translateX: [100, 0],
|
||||
duration: 250,
|
||||
delay: anime.stagger(20),
|
||||
easing: "easeInOutCirc",
|
||||
});
|
||||
anime({
|
||||
targets: ["." + styles.profileImageDummy],
|
||||
translateX: [0, -3],
|
||||
translateY: [0, 3],
|
||||
duration: 250,
|
||||
easing: "easeInOutCirc",
|
||||
});
|
||||
anime({
|
||||
targets: ["." + styles.profileImage],
|
||||
translateX: [0, 4],
|
||||
translateY: [0, -4],
|
||||
duration: 250,
|
||||
easing: "easeInOutCirc",
|
||||
});
|
||||
anime({
|
||||
targets: [
|
||||
"." + styles.profileCard + " > span",
|
||||
"." + styles.profileCard + " a",
|
||||
],
|
||||
opacity: [0, 1],
|
||||
translateX: [100, 0],
|
||||
duration: 250,
|
||||
delay: anime.stagger(20),
|
||||
easing: "easeInOutCirc",
|
||||
});
|
||||
anime({
|
||||
targets: ["." + styles.profileImageDummy],
|
||||
translateX: [0, -3],
|
||||
translateY: [0, 3],
|
||||
duration: 250,
|
||||
easing: "easeInOutCirc",
|
||||
});
|
||||
anime({
|
||||
targets: ["." + styles.profileImage],
|
||||
translateX: [0, 4],
|
||||
translateY: [0, -4],
|
||||
duration: 250,
|
||||
easing: "easeInOutCirc",
|
||||
});
|
||||
|
||||
tsParticles.load("particle-container", particleConfig);
|
||||
}, []);
|
||||
tsParticles.load("particle-container", particleConfig);
|
||||
}, []);
|
||||
|
||||
let meta = props.data.site.siteMetadata;
|
||||
let file = props.data.file;
|
||||
let meta = props.data.site.siteMetadata;
|
||||
let file = props.data.file;
|
||||
|
||||
return (
|
||||
<Layout title="Kevin Kandlbinder" transparentTopbar={true}>
|
||||
<section className={styles.heroSection}>
|
||||
<div className={styles.heroSectionBg} id="particle-container"></div>
|
||||
<div className={styles.heroSectionBgOver}></div>
|
||||
<div className={styles.profile + " profile"}>
|
||||
<div
|
||||
data-bg="url(https://cdn.kevink.dev/images/kevin/kevin-kandlbinder-03.jpg)"
|
||||
style={{
|
||||
backgroundImage:
|
||||
"url(https://cdn.kevink.dev/images/kevin/kevin-kandlbinder-03.jpg)",
|
||||
}}
|
||||
className={styles.profileImage + " lazy"}
|
||||
></div>
|
||||
<div className={styles.profileImageDummy}></div>
|
||||
<div className={styles.profileCard}>
|
||||
<span className={styles.hello}>
|
||||
<Trans>homeHello</Trans>
|
||||
</span>
|
||||
<span className={styles.name}>Kevin Kandlbinder</span>
|
||||
<span className={styles.description}>
|
||||
<Trans>homeMe</Trans>{" "}
|
||||
<span id="descriptionType">
|
||||
<Trans>homeWebDeveloper</Trans>
|
||||
</span>
|
||||
.
|
||||
</span>
|
||||
return (
|
||||
<Layout title="Kevin Kandlbinder" transparentTopbar={true}>
|
||||
<section className={styles.heroSection}>
|
||||
<div
|
||||
className={styles.heroSectionBg}
|
||||
id="particle-container"></div>
|
||||
<div className={styles.heroSectionBgOver}></div>
|
||||
<div className={styles.profile + " profile"}>
|
||||
<div
|
||||
data-bg="url(https://cdn.kevink.dev/images/kevin/kevin-kandlbinder-03.jpg)"
|
||||
style={{
|
||||
backgroundImage:
|
||||
"url(https://cdn.kevink.dev/images/kevin/kevin-kandlbinder-03.jpg)",
|
||||
}}
|
||||
className={styles.profileImage + " lazy"}></div>
|
||||
<div className={styles.profileImageDummy}></div>
|
||||
<div className={styles.profileCard}>
|
||||
<span className={styles.hello}>
|
||||
<Trans>homeHello</Trans>
|
||||
</span>
|
||||
<span className={styles.name}>Kevin Kandlbinder</span>
|
||||
<span className={styles.description}>
|
||||
<Trans>homeMe</Trans>{" "}
|
||||
<span id="descriptionType">
|
||||
<Trans>homeWebDeveloper</Trans>
|
||||
</span>
|
||||
.
|
||||
</span>
|
||||
|
||||
<div className={styles.contactLinks}>
|
||||
<a
|
||||
className={styles.contactLink}
|
||||
href={"tel:" + meta.contactPhone}
|
||||
rel="me"
|
||||
>
|
||||
<i className="fas fa-fw fa-phone"></i>
|
||||
{meta.contactPhone}
|
||||
</a>
|
||||
<a
|
||||
className={styles.contactLink}
|
||||
href={"mailto:" + meta.contactEmail}
|
||||
rel="me"
|
||||
>
|
||||
<i className="far fa-fw fa-envelope"></i>
|
||||
{meta.contactEmail}
|
||||
</a>
|
||||
<a
|
||||
className={styles.contactLink}
|
||||
href={meta.mapsLink}
|
||||
rel="noreferrer "
|
||||
target="_blank"
|
||||
>
|
||||
<i className="fas fa-fw fa-map-marker-alt"></i>
|
||||
<Trans>homeMyLocation</Trans>
|
||||
</a>
|
||||
<a
|
||||
className={styles.contactLink}
|
||||
href={meta.contactMastodonHref}
|
||||
rel="noreferrer me"
|
||||
target="_blank"
|
||||
>
|
||||
<i className="fab fa-fw fa-mastodon"></i>
|
||||
{meta.contactMastodon}
|
||||
</a>
|
||||
<a
|
||||
className={styles.contactLink}
|
||||
href={"https://github.com/" + meta.contactGitHub}
|
||||
rel="noreferrer me"
|
||||
target="_blank"
|
||||
>
|
||||
<i className="fab fa-fw fa-github"></i>
|
||||
{meta.contactGitHub}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section className="aboutSection">
|
||||
<article>
|
||||
<MDXRenderer>{file.childMdx.body}</MDXRenderer>
|
||||
</article>
|
||||
</section>
|
||||
<a
|
||||
className={styles.creditSection}
|
||||
href="https://unsplash.com/@jannikkiel"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<div>
|
||||
<span>
|
||||
<i className="fas fa-fw fa-camera"></i>{" "}
|
||||
<Trans>homeImageCredit</Trans>
|
||||
</span>
|
||||
<i className="fas fa-fw fa-chevron-right"></i>
|
||||
</div>
|
||||
</a>
|
||||
<section className="featuredSection">
|
||||
<article>
|
||||
<h1>
|
||||
<Trans>featuredProjects</Trans>
|
||||
</h1>
|
||||
<div className={projectStyles.projectList}>
|
||||
{props.data.allProjectsJson.nodes.map((project) => {
|
||||
return (
|
||||
<Link
|
||||
className={projectStyles.projectCard}
|
||||
key={project.lang + "/" + project.urlname}
|
||||
to={"/projects/" + project.urlname}
|
||||
>
|
||||
<div
|
||||
className={projectStyles.projectCardImage}
|
||||
style={{
|
||||
backgroundImage:
|
||||
"url(" + project.image.childImageSharp.resize.src + ")",
|
||||
}}
|
||||
>
|
||||
<div className={projectStyles.projectCardMeta}>
|
||||
<span className={projectStyles.projectCardTitle}>
|
||||
{project.name}
|
||||
</span>
|
||||
<span>{project.shortDescription}</span>
|
||||
<div className={styles.contactLinks}>
|
||||
<a
|
||||
className={styles.contactLink}
|
||||
href={"tel:" + meta.contactPhone}
|
||||
rel="me">
|
||||
<i className="fas fa-fw fa-phone"></i>
|
||||
{meta.contactPhone}
|
||||
</a>
|
||||
<a
|
||||
className={styles.contactLink}
|
||||
href={"mailto:" + meta.contactEmail}
|
||||
rel="me">
|
||||
<i className="far fa-fw fa-envelope"></i>
|
||||
{meta.contactEmail}
|
||||
</a>
|
||||
<a
|
||||
className={styles.contactLink}
|
||||
href={meta.mapsLink}
|
||||
rel="noreferrer "
|
||||
target="_blank">
|
||||
<i className="fas fa-fw fa-map-marker-alt"></i>
|
||||
<Trans>homeMyLocation</Trans>
|
||||
</a>
|
||||
<a
|
||||
className={styles.contactLink}
|
||||
href={meta.contactMastodonHref}
|
||||
rel="noreferrer me"
|
||||
target="_blank">
|
||||
<i className="fab fa-fw fa-mastodon"></i>
|
||||
{meta.contactMastodon}
|
||||
</a>
|
||||
<a
|
||||
className={styles.contactLink}
|
||||
href={
|
||||
"https://github.com/" + meta.contactGitHub
|
||||
}
|
||||
rel="noreferrer me"
|
||||
target="_blank">
|
||||
<i className="fab fa-fw fa-github"></i>
|
||||
{meta.contactGitHub}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<Link to="/projects" className={styles.seeMoreButton}>
|
||||
<Trans>seeMore</Trans>{" "}
|
||||
<i className="fas fa-fw fa-chevron-right"></i>
|
||||
</Link>
|
||||
</article>
|
||||
</section>
|
||||
<Link className={styles.donationSection} to="/donate">
|
||||
<div>
|
||||
<span>
|
||||
<Trans>donationCatchphrase</Trans>
|
||||
</span>
|
||||
<i className="fas fa-fw fa-chevron-right"></i>
|
||||
</div>
|
||||
</Link>
|
||||
</Layout>
|
||||
);
|
||||
</div>
|
||||
</section>
|
||||
<section className="aboutSection">
|
||||
<article>
|
||||
<MDXRenderer>{file.childMdx.body}</MDXRenderer>
|
||||
</article>
|
||||
</section>
|
||||
<a
|
||||
className={styles.creditSection}
|
||||
href="https://unsplash.com/@jannikkiel"
|
||||
target="_blank"
|
||||
rel="noreferrer">
|
||||
<div>
|
||||
<span>
|
||||
<i className="fas fa-fw fa-camera"></i>{" "}
|
||||
<Trans>homeImageCredit</Trans>
|
||||
</span>
|
||||
<i className="fas fa-fw fa-chevron-right"></i>
|
||||
</div>
|
||||
</a>
|
||||
<section className="featuredSection">
|
||||
<article>
|
||||
<h1>
|
||||
<Trans>featuredProjects</Trans>
|
||||
</h1>
|
||||
<div className={projectStyles.projectList}>
|
||||
{props.data.allProjectsJson.nodes.map((project) => {
|
||||
return (
|
||||
<Link
|
||||
className={projectStyles.projectCard}
|
||||
key={project.lang + "/" + project.urlname}
|
||||
to={"/projects/" + project.urlname}>
|
||||
<div
|
||||
className={
|
||||
projectStyles.projectCardImage
|
||||
}
|
||||
style={{
|
||||
backgroundImage:
|
||||
"url(" +
|
||||
project.image.childImageSharp
|
||||
.resize.src +
|
||||
")",
|
||||
}}>
|
||||
<div
|
||||
className={
|
||||
projectStyles.projectCardMeta
|
||||
}>
|
||||
<span
|
||||
className={
|
||||
projectStyles.projectCardTitle
|
||||
}>
|
||||
{project.name}
|
||||
</span>
|
||||
<span>
|
||||
{project.shortDescription}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<Link to="/projects" className={styles.seeMoreButton}>
|
||||
<Trans>seeMore</Trans>{" "}
|
||||
<i className="fas fa-fw fa-chevron-right"></i>
|
||||
</Link>
|
||||
</article>
|
||||
</section>
|
||||
<Link className={styles.donationSection} to="/donate">
|
||||
<div>
|
||||
<span>
|
||||
<Trans>donationCatchphrase</Trans>
|
||||
</span>
|
||||
<i className="fas fa-fw fa-chevron-right"></i>
|
||||
</div>
|
||||
</Link>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
IndexPage.propTypes = {
|
||||
data: PropTypes.object.isRequired,
|
||||
data: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default IndexPage;
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
height: 600px;
|
||||
overflow: hidden;
|
||||
|
||||
.heroSectionBg, .heroSectionBgOver {
|
||||
.heroSectionBg,
|
||||
.heroSectionBgOver {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
max-width: unset;
|
||||
|
@ -22,7 +23,20 @@
|
|||
/*background: radial-gradient(ellipse at top left, #1f0ba659, transparent),
|
||||
radial-gradient(ellipse at bottom right, #4a086829, transparent);*/
|
||||
|
||||
background: linear-gradient(45deg, #000850 0%, #000320 100%), radial-gradient(100% 225% at 100% 0%, #FF6928 0%, #000000 100%), linear-gradient(225deg, #FF7A00 0%, #000000 100%), linear-gradient(135deg, #CDFFEB 10%, #CDFFEB 35%, #009F9D 35%, #009F9D 60%, #07456F 60%, #07456F 67%, #0F0A3C 67%, #0F0A3C 100%);
|
||||
background: linear-gradient(45deg, #000850 0%, #000320 100%),
|
||||
radial-gradient(100% 225% at 100% 0%, #ff6928 0%, #000000 100%),
|
||||
linear-gradient(225deg, #ff7a00 0%, #000000 100%),
|
||||
linear-gradient(
|
||||
135deg,
|
||||
#cdffeb 10%,
|
||||
#cdffeb 35%,
|
||||
#009f9d 35%,
|
||||
#009f9d 60%,
|
||||
#07456f 60%,
|
||||
#07456f 67%,
|
||||
#0f0a3c 67%,
|
||||
#0f0a3c 100%
|
||||
);
|
||||
background-blend-mode: screen, overlay, hard-light, normal;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,107 +1,107 @@
|
|||
{
|
||||
"particles": {
|
||||
"number": {
|
||||
"value": 33,
|
||||
"density": {
|
||||
"enable": true,
|
||||
"value_area": 800
|
||||
}
|
||||
},
|
||||
"color": {
|
||||
"value": "#1b1e34"
|
||||
},
|
||||
"shape": {
|
||||
"type": "circle",
|
||||
"stroke": {
|
||||
"width": 0,
|
||||
"color": "#000"
|
||||
},
|
||||
"polygon": {
|
||||
"nb_sides": 3
|
||||
}
|
||||
},
|
||||
"opacity": {
|
||||
"value": 0.4,
|
||||
"random": true,
|
||||
"anim": {
|
||||
"enable": false,
|
||||
"speed": 1,
|
||||
"opacity_min": 0.1,
|
||||
"sync": false
|
||||
}
|
||||
},
|
||||
"size": {
|
||||
"value": 27.620603391810075,
|
||||
"random": true,
|
||||
"anim": {
|
||||
"enable": false,
|
||||
"speed": 10,
|
||||
"size_min": 40,
|
||||
"sync": false
|
||||
}
|
||||
},
|
||||
"line_linked": {
|
||||
"enable": false,
|
||||
"distance": 200,
|
||||
"color": "#ffffff",
|
||||
"opacity": 0.14994041841268327,
|
||||
"width": 2
|
||||
},
|
||||
"move": {
|
||||
"enable": true,
|
||||
"speed": 0.2,
|
||||
"direction": "top",
|
||||
"random": true,
|
||||
"straight": false,
|
||||
"out_mode": "out",
|
||||
"bounce": false,
|
||||
"attract": {
|
||||
"enable": false,
|
||||
"rotateX": 600,
|
||||
"rotateY": 1200
|
||||
}
|
||||
}
|
||||
},
|
||||
"interactivity": {
|
||||
"detect_on": "window",
|
||||
"events": {
|
||||
"onhover": {
|
||||
"enable": false,
|
||||
"mode": "repulse"
|
||||
},
|
||||
"onclick": {
|
||||
"enable": false,
|
||||
"mode": "push"
|
||||
},
|
||||
"resize": true
|
||||
},
|
||||
"modes": {
|
||||
"grab": {
|
||||
"distance": 400,
|
||||
"particles": {
|
||||
"number": {
|
||||
"value": 33,
|
||||
"density": {
|
||||
"enable": true,
|
||||
"value_area": 800
|
||||
}
|
||||
},
|
||||
"color": {
|
||||
"value": "#1b1e34"
|
||||
},
|
||||
"shape": {
|
||||
"type": "circle",
|
||||
"stroke": {
|
||||
"width": 0,
|
||||
"color": "#000"
|
||||
},
|
||||
"polygon": {
|
||||
"nb_sides": 3
|
||||
}
|
||||
},
|
||||
"opacity": {
|
||||
"value": 0.4,
|
||||
"random": true,
|
||||
"anim": {
|
||||
"enable": false,
|
||||
"speed": 1,
|
||||
"opacity_min": 0.1,
|
||||
"sync": false
|
||||
}
|
||||
},
|
||||
"size": {
|
||||
"value": 27.620603391810075,
|
||||
"random": true,
|
||||
"anim": {
|
||||
"enable": false,
|
||||
"speed": 10,
|
||||
"size_min": 40,
|
||||
"sync": false
|
||||
}
|
||||
},
|
||||
"line_linked": {
|
||||
"opacity": 1
|
||||
"enable": false,
|
||||
"distance": 200,
|
||||
"color": "#ffffff",
|
||||
"opacity": 0.14994041841268327,
|
||||
"width": 2
|
||||
},
|
||||
"move": {
|
||||
"enable": true,
|
||||
"speed": 0.2,
|
||||
"direction": "top",
|
||||
"random": true,
|
||||
"straight": false,
|
||||
"out_mode": "out",
|
||||
"bounce": false,
|
||||
"attract": {
|
||||
"enable": false,
|
||||
"rotateX": 600,
|
||||
"rotateY": 1200
|
||||
}
|
||||
}
|
||||
},
|
||||
"bubble": {
|
||||
"distance": 400,
|
||||
"size": 40,
|
||||
"duration": 2,
|
||||
"opacity": 8,
|
||||
"speed": 3
|
||||
},
|
||||
"repulse": {
|
||||
"distance": 200,
|
||||
"duration": 0.4
|
||||
},
|
||||
"push": {
|
||||
"particles_nb": 4
|
||||
},
|
||||
"remove": {
|
||||
"particles_nb": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"detectRetina": true,
|
||||
"pauseOnBlur": true,
|
||||
"pauseOnOutsideViewport": true
|
||||
},
|
||||
"interactivity": {
|
||||
"detect_on": "window",
|
||||
"events": {
|
||||
"onhover": {
|
||||
"enable": false,
|
||||
"mode": "repulse"
|
||||
},
|
||||
"onclick": {
|
||||
"enable": false,
|
||||
"mode": "push"
|
||||
},
|
||||
"resize": true
|
||||
},
|
||||
"modes": {
|
||||
"grab": {
|
||||
"distance": 400,
|
||||
"line_linked": {
|
||||
"opacity": 1
|
||||
}
|
||||
},
|
||||
"bubble": {
|
||||
"distance": 400,
|
||||
"size": 40,
|
||||
"duration": 2,
|
||||
"opacity": 8,
|
||||
"speed": 3
|
||||
},
|
||||
"repulse": {
|
||||
"distance": 200,
|
||||
"duration": 0.4
|
||||
},
|
||||
"push": {
|
||||
"particles_nb": 4
|
||||
},
|
||||
"remove": {
|
||||
"particles_nb": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"detectRetina": true,
|
||||
"pauseOnBlur": true,
|
||||
"pauseOnOutsideViewport": true
|
||||
}
|
|
@ -4,53 +4,56 @@ import { Trans, useI18next } from "gatsby-plugin-react-i18next";
|
|||
import { graphql } from "gatsby";
|
||||
|
||||
export const query = graphql`
|
||||
query($language: String!) {
|
||||
locales: allLocale(filter: { language: { eq: $language } }) {
|
||||
edges {
|
||||
node {
|
||||
ns
|
||||
data
|
||||
language
|
||||
query ($language: String!) {
|
||||
locales: allLocale(filter: { language: { eq: $language } }) {
|
||||
edges {
|
||||
node {
|
||||
ns
|
||||
data
|
||||
language
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default function ImprintPage() {
|
||||
const { t } = useI18next();
|
||||
return (
|
||||
<Layout title={t("imprint")}>
|
||||
<section>
|
||||
<article>
|
||||
<h1>
|
||||
<Trans>imprint</Trans>
|
||||
</h1>
|
||||
const { t } = useI18next();
|
||||
return (
|
||||
<Layout title={t("imprint")}>
|
||||
<section>
|
||||
<article>
|
||||
<h1>
|
||||
<Trans>imprint</Trans>
|
||||
</h1>
|
||||
|
||||
<p>Angaben gemäß § 5 TMG</p>
|
||||
<p>
|
||||
Kevin Kandlbinder
|
||||
<br />
|
||||
Eichenweg 48
|
||||
<br />
|
||||
25451 Quickborn <br />
|
||||
</p>
|
||||
<p>
|
||||
{" "}
|
||||
<strong>Vertreten durch: </strong>
|
||||
<br />
|
||||
Kevin Kandlbinder
|
||||
<br />
|
||||
</p>
|
||||
<p>
|
||||
<strong>Kontakt:</strong> <br />
|
||||
Telefon: +49 4106 8068004
|
||||
<br />
|
||||
E-Mail: <a href="mailto:contact@kevink.dev">contact@kevink.dev</a>
|
||||
<br />
|
||||
</p>
|
||||
</article>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
<p>Angaben gemäß § 5 TMG</p>
|
||||
<p>
|
||||
Kevin Kandlbinder
|
||||
<br />
|
||||
Eichenweg 48
|
||||
<br />
|
||||
25451 Quickborn <br />
|
||||
</p>
|
||||
<p>
|
||||
{" "}
|
||||
<strong>Vertreten durch: </strong>
|
||||
<br />
|
||||
Kevin Kandlbinder
|
||||
<br />
|
||||
</p>
|
||||
<p>
|
||||
<strong>Kontakt:</strong> <br />
|
||||
Telefon: +49 4106 8068004
|
||||
<br />
|
||||
E-Mail:{" "}
|
||||
<a href="mailto:contact@kevink.dev">
|
||||
contact@kevink.dev
|
||||
</a>
|
||||
<br />
|
||||
</p>
|
||||
</article>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -4,91 +4,98 @@ import { Trans, useI18next } from "gatsby-plugin-react-i18next";
|
|||
import { graphql } from "gatsby";
|
||||
|
||||
export const query = graphql`
|
||||
query($language: String!) {
|
||||
locales: allLocale(filter: { language: { eq: $language } }) {
|
||||
edges {
|
||||
node {
|
||||
ns
|
||||
data
|
||||
language
|
||||
query ($language: String!) {
|
||||
locales: allLocale(filter: { language: { eq: $language } }) {
|
||||
edges {
|
||||
node {
|
||||
ns
|
||||
data
|
||||
language
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default function DisclaimerPage() {
|
||||
const { t } = useI18next();
|
||||
return (
|
||||
<Layout title={t("disclaimer")}>
|
||||
<section>
|
||||
<article>
|
||||
<h1>
|
||||
<Trans>disclaimer</Trans>
|
||||
</h1>
|
||||
const { t } = useI18next();
|
||||
return (
|
||||
<Layout title={t("disclaimer")}>
|
||||
<section>
|
||||
<article>
|
||||
<h1>
|
||||
<Trans>disclaimer</Trans>
|
||||
</h1>
|
||||
|
||||
<h2>Haftung für Inhalte</h2>
|
||||
<h2>Haftung für Inhalte</h2>
|
||||
|
||||
<p>
|
||||
Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte
|
||||
auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach
|
||||
§§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht
|
||||
verpflichtet, übermittelte oder gespeicherte fremde Informationen zu
|
||||
überwachen oder nach Umständen zu forschen, die auf eine
|
||||
rechtswidrige Tätigkeit hinweisen.
|
||||
</p>
|
||||
<p>
|
||||
Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für
|
||||
eigene Inhalte auf diesen Seiten nach den allgemeinen
|
||||
Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir
|
||||
als Diensteanbieter jedoch nicht verpflichtet,
|
||||
übermittelte oder gespeicherte fremde Informationen zu
|
||||
überwachen oder nach Umständen zu forschen, die auf eine
|
||||
rechtswidrige Tätigkeit hinweisen.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Verpflichtungen zur Entfernung oder Sperrung der Nutzung von
|
||||
Informationen nach den allgemeinen Gesetzen bleiben hiervon
|
||||
unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem
|
||||
Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei
|
||||
Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese
|
||||
Inhalte umgehend entfernen.
|
||||
</p>
|
||||
<p>
|
||||
Verpflichtungen zur Entfernung oder Sperrung der Nutzung
|
||||
von Informationen nach den allgemeinen Gesetzen bleiben
|
||||
hiervon unberührt. Eine diesbezügliche Haftung ist
|
||||
jedoch erst ab dem Zeitpunkt der Kenntnis einer
|
||||
konkreten Rechtsverletzung möglich. Bei Bekanntwerden
|
||||
von entsprechenden Rechtsverletzungen werden wir diese
|
||||
Inhalte umgehend entfernen.
|
||||
</p>
|
||||
|
||||
<h2>Haftung für Links</h2>
|
||||
<h2>Haftung für Links</h2>
|
||||
|
||||
<p>
|
||||
Unser Angebot enthält Links zu externen Websites Dritter, auf deren
|
||||
Inhalte wir keinen Einfluss haben. Deshalb können wir für diese
|
||||
fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der
|
||||
verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber
|
||||
der Seiten verantwortlich. Die verlinkten Seiten wurden zum
|
||||
Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft.
|
||||
Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht
|
||||
erkennbar.
|
||||
</p>
|
||||
<p>
|
||||
Unser Angebot enthält Links zu externen Websites
|
||||
Dritter, auf deren Inhalte wir keinen Einfluss haben.
|
||||
Deshalb können wir für diese fremden Inhalte auch keine
|
||||
Gewähr übernehmen. Für die Inhalte der verlinkten Seiten
|
||||
ist stets der jeweilige Anbieter oder Betreiber der
|
||||
Seiten verantwortlich. Die verlinkten Seiten wurden zum
|
||||
Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße
|
||||
überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der
|
||||
Verlinkung nicht erkennbar.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist
|
||||
jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht
|
||||
zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir
|
||||
derartige Links umgehend entfernen.
|
||||
</p>
|
||||
<p>
|
||||
Eine permanente inhaltliche Kontrolle der verlinkten
|
||||
Seiten ist jedoch ohne konkrete Anhaltspunkte einer
|
||||
Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von
|
||||
Rechtsverletzungen werden wir derartige Links umgehend
|
||||
entfernen.
|
||||
</p>
|
||||
|
||||
<h2>Urheberrecht</h2>
|
||||
<h2>Urheberrecht</h2>
|
||||
|
||||
<p>
|
||||
Die durch die Seitenbetreiber erstellten Inhalte und Werke auf
|
||||
diesen Seiten unterliegen dem deutschen Urheberrecht. Die
|
||||
Vervielfältigung, Bearbeitung, Verbreitung und jede Art der
|
||||
Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der
|
||||
schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers.
|
||||
Downloads und Kopien dieser Seite sind nur für den privaten, nicht
|
||||
kommerziellen Gebrauch gestattet.
|
||||
</p>
|
||||
<p>
|
||||
Die durch die Seitenbetreiber erstellten Inhalte und
|
||||
Werke auf diesen Seiten unterliegen dem deutschen
|
||||
Urheberrecht. Die Vervielfältigung, Bearbeitung,
|
||||
Verbreitung und jede Art der Verwertung außerhalb der
|
||||
Grenzen des Urheberrechtes bedürfen der schriftlichen
|
||||
Zustimmung des jeweiligen Autors bzw. Erstellers.
|
||||
Downloads und Kopien dieser Seite sind nur für den
|
||||
privaten, nicht kommerziellen Gebrauch gestattet.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt
|
||||
wurden, werden die Urheberrechte Dritter beachtet. Insbesondere
|
||||
werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie
|
||||
trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten
|
||||
wir um einen entsprechenden Hinweis. Bei Bekanntwerden von
|
||||
Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen.
|
||||
</p>
|
||||
</article>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
<p>
|
||||
Soweit die Inhalte auf dieser Seite nicht vom Betreiber
|
||||
erstellt wurden, werden die Urheberrechte Dritter
|
||||
beachtet. Insbesondere werden Inhalte Dritter als solche
|
||||
gekennzeichnet. Sollten Sie trotzdem auf eine
|
||||
Urheberrechtsverletzung aufmerksam werden, bitten wir um
|
||||
einen entsprechenden Hinweis. Bei Bekanntwerden von
|
||||
Rechtsverletzungen werden wir derartige Inhalte umgehend
|
||||
entfernen.
|
||||
</p>
|
||||
</article>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,82 +7,88 @@ import PropTypes from "prop-types";
|
|||
import * as styles from "./projects.module.scss";
|
||||
|
||||
export const query = graphql`
|
||||
query GetProjects($language: String) {
|
||||
allProjectsJson(filter: { lang: { eq: $language } }) {
|
||||
nodes {
|
||||
lang
|
||||
urlname
|
||||
name
|
||||
image {
|
||||
childImageSharp {
|
||||
resize(width: 400, quality: 90) {
|
||||
src
|
||||
query GetProjects($language: String) {
|
||||
allProjectsJson(filter: { lang: { eq: $language } }) {
|
||||
nodes {
|
||||
lang
|
||||
urlname
|
||||
name
|
||||
image {
|
||||
childImageSharp {
|
||||
resize(width: 400, quality: 90) {
|
||||
src
|
||||
}
|
||||
}
|
||||
}
|
||||
shortDescription
|
||||
}
|
||||
}
|
||||
}
|
||||
shortDescription
|
||||
}
|
||||
}
|
||||
locales: allLocale(filter: { language: { eq: $language } }) {
|
||||
edges {
|
||||
node {
|
||||
ns
|
||||
data
|
||||
language
|
||||
locales: allLocale(filter: { language: { eq: $language } }) {
|
||||
edges {
|
||||
node {
|
||||
ns
|
||||
data
|
||||
language
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const ProjectsPage = ({ data }) => {
|
||||
const { t } = useI18next();
|
||||
return (
|
||||
<Layout title={t("projects")} description={t("projectsDescription")}>
|
||||
<section>
|
||||
<article>
|
||||
<h1>
|
||||
<Trans>projects</Trans>
|
||||
</h1>
|
||||
const { t } = useI18next();
|
||||
return (
|
||||
<Layout title={t("projects")} description={t("projectsDescription")}>
|
||||
<section>
|
||||
<article>
|
||||
<h1>
|
||||
<Trans>projects</Trans>
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
<Trans>projectsDescription</Trans>
|
||||
</p>
|
||||
<p>
|
||||
<Trans>projectsDescription</Trans>
|
||||
</p>
|
||||
|
||||
<div className={styles.projectList}>
|
||||
{data.allProjectsJson.nodes.map((project) => {
|
||||
return (
|
||||
<Link
|
||||
className={styles.projectCard}
|
||||
key={project.lang + project.urlname}
|
||||
to={"/projects/" + project.urlname}
|
||||
>
|
||||
<div
|
||||
className={styles.projectCardImage}
|
||||
style={{
|
||||
backgroundImage:
|
||||
"url(" + project.image.childImageSharp.resize.src + ")",
|
||||
}}
|
||||
>
|
||||
<div className={styles.projectCardMeta}>
|
||||
<span className={styles.projectCardTitle}>
|
||||
{project.name}
|
||||
</span>
|
||||
<span>{project.shortDescription}</span>
|
||||
<div className={styles.projectList}>
|
||||
{data.allProjectsJson.nodes.map((project) => {
|
||||
return (
|
||||
<Link
|
||||
className={styles.projectCard}
|
||||
key={project.lang + project.urlname}
|
||||
to={"/projects/" + project.urlname}>
|
||||
<div
|
||||
className={styles.projectCardImage}
|
||||
style={{
|
||||
backgroundImage:
|
||||
"url(" +
|
||||
project.image.childImageSharp
|
||||
.resize.src +
|
||||
")",
|
||||
}}>
|
||||
<div className={styles.projectCardMeta}>
|
||||
<span
|
||||
className={
|
||||
styles.projectCardTitle
|
||||
}>
|
||||
{project.name}
|
||||
</span>
|
||||
<span>
|
||||
{project.shortDescription}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
</article>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
ProjectsPage.propTypes = {
|
||||
data: PropTypes.object,
|
||||
data: PropTypes.object,
|
||||
};
|
||||
|
||||
export default ProjectsPage;
|
||||
|
|
|
@ -7,76 +7,77 @@ import PropTypes from "prop-types";
|
|||
import * as styles from "./social.module.scss";
|
||||
|
||||
export const query = graphql`
|
||||
query AllSocialsQuery($language: String!) {
|
||||
allSocialsJson {
|
||||
nodes {
|
||||
image
|
||||
platformHandle
|
||||
platformName
|
||||
url
|
||||
}
|
||||
}
|
||||
locales: allLocale(filter: { language: { eq: $language } }) {
|
||||
edges {
|
||||
node {
|
||||
ns
|
||||
data
|
||||
language
|
||||
query AllSocialsQuery($language: String!) {
|
||||
allSocialsJson {
|
||||
nodes {
|
||||
image
|
||||
platformHandle
|
||||
platformName
|
||||
url
|
||||
}
|
||||
}
|
||||
locales: allLocale(filter: { language: { eq: $language } }) {
|
||||
edges {
|
||||
node {
|
||||
ns
|
||||
data
|
||||
language
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const SocialPage = ({ data }) => {
|
||||
const { t } = useI18next();
|
||||
return (
|
||||
<Layout title={t("social")} description={t("socialDescription")}>
|
||||
<section>
|
||||
<article>
|
||||
<h1>
|
||||
<Trans>social</Trans>
|
||||
</h1>
|
||||
const { t } = useI18next();
|
||||
return (
|
||||
<Layout title={t("social")} description={t("socialDescription")}>
|
||||
<section>
|
||||
<article>
|
||||
<h1>
|
||||
<Trans>social</Trans>
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
<Trans i18nKey="socialDescriptionWithLink">
|
||||
socialDescriptionWith<Link to="/friends">Link</Link>
|
||||
</Trans>
|
||||
</p>
|
||||
<p>
|
||||
<Trans i18nKey="socialDescriptionWithLink">
|
||||
socialDescriptionWith<Link to="/friends">Link</Link>
|
||||
</Trans>
|
||||
</p>
|
||||
|
||||
<div className={styles.socialList}>
|
||||
{data.allSocialsJson.nodes.map((social) => {
|
||||
return (
|
||||
<a
|
||||
className={styles.socialCard}
|
||||
href={social.url}
|
||||
target="_blank"
|
||||
rel="noreferrer me"
|
||||
key={social.url}
|
||||
>
|
||||
<div
|
||||
className={styles.socialImage}
|
||||
style={{ backgroundImage: "url(" + social.image + ")" }}
|
||||
>
|
||||
<span className={styles.socialName}>
|
||||
{social.platformName}
|
||||
</span>
|
||||
<span className={styles.socialUsername}>
|
||||
{social.platformHandle}
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
<div className={styles.socialList}>
|
||||
{data.allSocialsJson.nodes.map((social) => {
|
||||
return (
|
||||
<a
|
||||
className={styles.socialCard}
|
||||
href={social.url}
|
||||
target="_blank"
|
||||
rel="noreferrer me"
|
||||
key={social.url}>
|
||||
<div
|
||||
className={styles.socialImage}
|
||||
style={{
|
||||
backgroundImage:
|
||||
"url(" + social.image + ")",
|
||||
}}>
|
||||
<span className={styles.socialName}>
|
||||
{social.platformName}
|
||||
</span>
|
||||
<span className={styles.socialUsername}>
|
||||
{social.platformHandle}
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
SocialPage.propTypes = {
|
||||
data: PropTypes.object.isRequired,
|
||||
data: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default SocialPage;
|
||||
|
|
|
@ -8,115 +8,121 @@ import * as styles from "./project.module.scss";
|
|||
import { MDXRenderer } from "gatsby-plugin-mdx";
|
||||
|
||||
export const query = graphql`
|
||||
query GetProject($urlname: String!, $lang: String!, $language: String!) {
|
||||
allProjectsJson(
|
||||
filter: { urlname: { eq: $urlname }, lang: { eq: $lang } }
|
||||
) {
|
||||
nodes {
|
||||
lang
|
||||
urlname
|
||||
name
|
||||
links {
|
||||
github
|
||||
website
|
||||
query GetProject($urlname: String!, $lang: String!, $language: String!) {
|
||||
allProjectsJson(
|
||||
filter: { urlname: { eq: $urlname }, lang: { eq: $lang } }
|
||||
) {
|
||||
nodes {
|
||||
lang
|
||||
urlname
|
||||
name
|
||||
links {
|
||||
github
|
||||
website
|
||||
}
|
||||
image {
|
||||
publicURL
|
||||
}
|
||||
shortDescription
|
||||
}
|
||||
}
|
||||
image {
|
||||
publicURL
|
||||
locales: allLocale(filter: { language: { eq: $language } }) {
|
||||
edges {
|
||||
node {
|
||||
ns
|
||||
data
|
||||
language
|
||||
}
|
||||
}
|
||||
}
|
||||
shortDescription
|
||||
}
|
||||
}
|
||||
locales: allLocale(filter: { language: { eq: $language } }) {
|
||||
edges {
|
||||
node {
|
||||
ns
|
||||
data
|
||||
language
|
||||
file(
|
||||
sourceInstanceName: { eq: "projectTextblocks" }
|
||||
relativeDirectory: { eq: $urlname }
|
||||
name: { eq: $language }
|
||||
) {
|
||||
id
|
||||
childMdx {
|
||||
body
|
||||
}
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
file(
|
||||
sourceInstanceName: {eq: "projectTextblocks"}, relativeDirectory: {eq: $urlname}, name: {eq: $language}
|
||||
) {
|
||||
id
|
||||
childMdx {
|
||||
body
|
||||
}
|
||||
name
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const ProjectTemplate = ({ data }) => {
|
||||
const { t } = useTranslation();
|
||||
let project = data.allProjectsJson.nodes[0];
|
||||
let projectName = project.name;
|
||||
let file = data.file;
|
||||
const { t } = useTranslation();
|
||||
let project = data.allProjectsJson.nodes[0];
|
||||
let projectName = project.name;
|
||||
let file = data.file;
|
||||
|
||||
return (
|
||||
<Layout
|
||||
description={project.shortDescription}
|
||||
title={t("project") + ": " + projectName}
|
||||
transparentTopbar={true}
|
||||
>
|
||||
<section className={styles.projectHeader}>
|
||||
<div style={{ paddingTop: 0 }}>
|
||||
<div
|
||||
className={styles.headerBackground}
|
||||
style={{ backgroundImage: "url(" + project.image.publicURL + ")" }}
|
||||
></div>
|
||||
<header>
|
||||
<div className={styles.headerInner}>
|
||||
<h1>
|
||||
<Trans>project</Trans>: {projectName}
|
||||
</h1>
|
||||
<span>{project.shortDescription}</span>
|
||||
</div>
|
||||
</header>
|
||||
<div className={styles.headerPlaceholder}></div>
|
||||
</div>
|
||||
</section>
|
||||
{file != null && file.childMdx != null ? (
|
||||
<section className={styles.projectAbout}>
|
||||
<article>
|
||||
<MDXRenderer>{file.childMdx.body}</MDXRenderer>
|
||||
</article>
|
||||
</section>
|
||||
) : null}
|
||||
{project.links !== null ? (
|
||||
<section className={styles.projectLinks}>
|
||||
<div>
|
||||
<h1>Links</h1>
|
||||
<div className={styles.linkList}>
|
||||
{project.links.github !== null ? (
|
||||
<a href={project.links.github} target="_blank" rel="noreferrer">
|
||||
<i className="fab fa-github" aria-hidden="true"></i>{" "}
|
||||
<Trans>projectViewGitHub</Trans>
|
||||
</a>
|
||||
) : null}
|
||||
{project.links.website !== null ? (
|
||||
<a
|
||||
href={project.links.website}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<i
|
||||
className="fas fa-external-link-alt"
|
||||
aria-hidden="true"
|
||||
></i>{" "}
|
||||
<Trans>projectViewWebsite</Trans>
|
||||
</a>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
) : null}
|
||||
</Layout>
|
||||
);
|
||||
return (
|
||||
<Layout
|
||||
description={project.shortDescription}
|
||||
title={t("project") + ": " + projectName}
|
||||
transparentTopbar={true}>
|
||||
<section className={styles.projectHeader}>
|
||||
<div style={{ paddingTop: 0 }}>
|
||||
<div
|
||||
className={styles.headerBackground}
|
||||
style={{
|
||||
backgroundImage:
|
||||
"url(" + project.image.publicURL + ")",
|
||||
}}></div>
|
||||
<header>
|
||||
<div className={styles.headerInner}>
|
||||
<h1>
|
||||
<Trans>project</Trans>: {projectName}
|
||||
</h1>
|
||||
<span>{project.shortDescription}</span>
|
||||
</div>
|
||||
</header>
|
||||
<div className={styles.headerPlaceholder}></div>
|
||||
</div>
|
||||
</section>
|
||||
{file != null && file.childMdx != null ? (
|
||||
<section className={styles.projectAbout}>
|
||||
<article>
|
||||
<MDXRenderer>{file.childMdx.body}</MDXRenderer>
|
||||
</article>
|
||||
</section>
|
||||
) : null}
|
||||
{project.links !== null ? (
|
||||
<section className={styles.projectLinks}>
|
||||
<div>
|
||||
<h1>Links</h1>
|
||||
<div className={styles.linkList}>
|
||||
{project.links.github !== null ? (
|
||||
<a
|
||||
href={project.links.github}
|
||||
target="_blank"
|
||||
rel="noreferrer">
|
||||
<i
|
||||
className="fab fa-github"
|
||||
aria-hidden="true"></i>{" "}
|
||||
<Trans>projectViewGitHub</Trans>
|
||||
</a>
|
||||
) : null}
|
||||
{project.links.website !== null ? (
|
||||
<a
|
||||
href={project.links.website}
|
||||
target="_blank"
|
||||
rel="noreferrer">
|
||||
<i
|
||||
className="fas fa-external-link-alt"
|
||||
aria-hidden="true"></i>{" "}
|
||||
<Trans>projectViewWebsite</Trans>
|
||||
</a>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
) : null}
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
ProjectTemplate.propTypes = {
|
||||
data: PropTypes.object.isRequired,
|
||||
data: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default ProjectTemplate;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue