Run prettier on code

This commit is contained in:
Kevin Kandlbinder 2021-04-12 13:02:38 +00:00 committed by GitHub
parent d542206091
commit b8057f0e25
51 changed files with 28270 additions and 26529 deletions

View file

@ -1,17 +1,18 @@
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
module.exports = { module.exports = {
"siteName": "KevinK.dev", siteName: "KevinK.dev",
"siteAuthor": "@Unkn0wnKevin", siteAuthor: "@Unkn0wnKevin",
"siteURL": "https://kevink.dev", siteURL: "https://kevink.dev",
"payPalMail": "kevin@1in9.net", payPalMail: "kevin@1in9.net",
"siteKeywords": "Kevin Kandlbinder, Kevin, Kandlbinder, Web, Web Developer, Developer, JavaScript, PHP, Java, Photos, Fotos", siteKeywords:
"iconPath": "src/images/fullbglogo@10x.png", "Kevin Kandlbinder, Kevin, Kandlbinder, Web, Web Developer, Developer, JavaScript, PHP, Java, Photos, Fotos",
"languages": ["en", "de"], iconPath: "src/images/fullbglogo@10x.png",
"contactEmail": "kevin@kevink.dev", languages: ["en", "de"],
"contactPhone": "+4941068068004", contactEmail: "kevin@kevink.dev",
"mapsLink": "https://goo.gl/maps/KVq9z1PVaVP2", contactPhone: "+4941068068004",
"contactTwitter": "Unkn0wnKevin", mapsLink: "https://goo.gl/maps/KVq9z1PVaVP2",
"contactGitHub": "Unkn0wnCat", contactTwitter: "Unkn0wnKevin",
"contactMastodon": "@kevin@1in1.net", contactGitHub: "Unkn0wnCat",
"contactMastodonHref": "https://mastodon.1in1.net/@kevin" contactMastodon: "@kevin@1in1.net",
contactMastodonHref: "https://mastodon.1in1.net/@kevin",
}; };

View file

@ -1,5 +1,5 @@
/* eslint-disable no-undef */ /* eslint-disable no-undef */
const extConfig = require("./config") const extConfig = require("./config");
module.exports = { module.exports = {
siteMetadata: { siteMetadata: {
@ -14,13 +14,13 @@ module.exports = {
contactTwitter: extConfig.contactTwitter, contactTwitter: extConfig.contactTwitter,
contactGitHub: extConfig.contactGitHub, contactGitHub: extConfig.contactGitHub,
contactMastodon: extConfig.contactMastodon, contactMastodon: extConfig.contactMastodon,
contactMastodonHref: extConfig.contactMastodonHref contactMastodonHref: extConfig.contactMastodonHref,
}, },
assetPrefix: "/assets", assetPrefix: "/assets",
plugins: [ plugins: [
`gatsby-plugin-eslint`, `gatsby-plugin-eslint`,
{ {
resolve: "gatsby-plugin-asset-path" resolve: "gatsby-plugin-asset-path",
}, },
`gatsby-plugin-sharp`, `gatsby-plugin-sharp`,
`gatsby-transformer-sharp`, `gatsby-transformer-sharp`,
@ -35,7 +35,7 @@ module.exports = {
resolve: `gatsby-source-filesystem`, resolve: `gatsby-source-filesystem`,
options: { options: {
path: `${__dirname}/locales`, path: `${__dirname}/locales`,
name: `locale` name: `locale`,
}, },
}, },
`gatsby-plugin-sass`, `gatsby-plugin-sass`,
@ -49,7 +49,7 @@ module.exports = {
theme_color: `#000710`, theme_color: `#000710`,
display: `minimal-ui`, display: `minimal-ui`,
icon: extConfig.iconPath, // This path is relative to the root of the site. icon: extConfig.iconPath, // This path is relative to the root of the site.
cache_busting_mode: 'none', cache_busting_mode: "none",
}, },
}, },
`gatsby-plugin-robots-txt`, `gatsby-plugin-robots-txt`,
@ -58,8 +58,8 @@ module.exports = {
options: { options: {
precachePages: ["/", "/en", "/en/projects", "/de", "/de/projects"], precachePages: ["/", "/en", "/en/projects", "/de", "/de/projects"],
workboxConfig: { workboxConfig: {
globPatterns: ['**/*'] globPatterns: ["**/*"],
} },
}, },
}, },
`gatsby-plugin-sitemap`, `gatsby-plugin-sitemap`,
@ -74,19 +74,19 @@ module.exports = {
siteUrl: extConfig.siteURL, siteUrl: extConfig.siteURL,
i18nextOptions: { i18nextOptions: {
interpolation: { interpolation: {
escapeValue: false // not needed for react as it escapes by default escapeValue: false, // not needed for react as it escapes by default
}, },
keySeparator: false, keySeparator: false,
nsSeparator: false nsSeparator: false,
}, },
pages: [ pages: [
{ {
matchPath: '/:lang/projects/:urlname', matchPath: "/:lang/projects/:urlname",
getLanguageFromPath: true, getLanguageFromPath: true,
excludeLanguages: extConfig.languages excludeLanguages: extConfig.languages,
} },
] ],
} },
} },
] ],
} };

View file

@ -1,11 +1,11 @@
/* eslint-disable no-undef */ /* eslint-disable no-undef */
const path = require(`path`); const path = require(`path`);
const fs = require("fs") const fs = require("fs");
exports.createPages = async ({ actions, graphql, reporter }) => { 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(` const result = await graphql(`
query AllPagesQuery { query AllPagesQuery {
@ -16,65 +16,68 @@ exports.createPages = async ({ actions, graphql, reporter }) => {
} }
} }
} }
`);
`)
if (result.errors) { if (result.errors) {
reporter.panicOnBuild(`Error while running GraphQL query.`) reporter.panicOnBuild(`Error while running GraphQL query.`);
return return;
} }
result.data.allProjectsJson.nodes.forEach((node) => { result.data.allProjectsJson.nodes.forEach((node) => {
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
console.log("Creating Page: ", `/${node.lang}/projects/${node.urlname}`); console.log("Creating Page: ", `/${node.lang}/projects/${node.urlname}`);
if (node.lang !== "ignoreme") createPage({ if (node.lang !== "ignoreme")
createPage({
path: `/${node.lang}/projects/${node.urlname}`, path: `/${node.lang}/projects/${node.urlname}`,
component: projectTemplate, component: projectTemplate,
context: { context: {
lang: node.lang, lang: node.lang,
urlname: node.urlname urlname: node.urlname,
} },
})
}); });
});
} };
const config = require("./config.js"); const config = require("./config.js");
exports.onPostBuild = async ({graphql, reporter}) => { 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) if (!fs.existsSync(apiPrefix)) fs.mkdirSync(apiPrefix);
fs.writeFileSync(`${apiPrefix}.json`, JSON.stringify({ fs.writeFileSync(
`${apiPrefix}.json`,
JSON.stringify({
success: true, success: true,
endpoints: { endpoints: {
projects: [ projects: [
{ {
name: "Projects Overview", name: "Projects Overview",
description: "Returns overview of all available projects", description: "Returns overview of all available projects",
path: "/api/projects.json" path: "/api/projects.json",
}, },
{ {
name: "Projects Overview for Language", name: "Projects Overview for Language",
description: "Returns overview of all available projects in a specified language", description:
path: "/api/projects/:lang.json" "Returns overview of all available projects in a specified language",
path: "/api/projects/:lang.json",
}, },
{ {
name: "Get specific Project", name: "Get specific Project",
description: "Returns specific project in specified language", description: "Returns specific project in specified language",
path: "/api/projects/:lang/:slug.json" path: "/api/projects/:lang/:slug.json",
} },
] ],
} },
})); })
);
const projectsPrefix = apiPrefix+"/projects"; const projectsPrefix = apiPrefix + "/projects";
if (!fs.existsSync(projectsPrefix)) fs.mkdirSync(projectsPrefix) if (!fs.existsSync(projectsPrefix)) fs.mkdirSync(projectsPrefix);
await graphql(` await graphql(`
query { query {
@ -96,30 +99,57 @@ exports.onPostBuild = async ({graphql, reporter}) => {
} }
} }
} }
`).then(res => { `).then((res) => {
if (res.errors) { if (res.errors) {
reporter.panicOnBuild(`Error while running GraphQL query.`) reporter.panicOnBuild(`Error while running GraphQL query.`);
return return;
} }
let projects = res.data.allProjectsJson.nodes.filter((project => { return project.lang !== "ignoreme" })); let projects = res.data.allProjectsJson.nodes.filter((project) => {
return project.lang !== "ignoreme";
});
fs.writeFileSync(`${projectsPrefix}.json`, JSON.stringify({ fs.writeFileSync(
`${projectsPrefix}.json`,
JSON.stringify({
success: true, success: true,
projects: projects.map((project) => {return {slug: project.urlname, lang: project.lang, api: `/api/projects/${project.lang}/${project.urlname}.json`};}) projects: projects.map((project) => {
})); return {
slug: project.urlname,
lang: project.lang,
api: `/api/projects/${project.lang}/${project.urlname}.json`,
};
}),
})
);
config.languages.forEach((lang) => { config.languages.forEach((lang) => {
if (!fs.existsSync(`${projectsPrefix}/${lang}`)) fs.mkdirSync(`${projectsPrefix}/${lang}`) if (!fs.existsSync(`${projectsPrefix}/${lang}`))
fs.mkdirSync(`${projectsPrefix}/${lang}`);
fs.writeFileSync(`${projectsPrefix}/${lang}.json`, JSON.stringify({ fs.writeFileSync(
`${projectsPrefix}/${lang}.json`,
JSON.stringify({
success: true, 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: 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) => { projects.forEach((project) => {
fs.writeFileSync(`${projectsPrefix}/${project.lang}/${project.urlname}.json`, JSON.stringify({ fs.writeFileSync(
`${projectsPrefix}/${project.lang}/${project.urlname}.json`,
JSON.stringify({
success: true, success: true,
project: { project: {
slug: project.urlname, slug: project.urlname,
@ -127,15 +157,19 @@ exports.onPostBuild = async ({graphql, reporter}) => {
name: project.name, name: project.name,
shortDescription: project.shortDescription, shortDescription: project.shortDescription,
longDescription: project.longDescription, longDescription: project.longDescription,
links: project.links !== null ? { links:
project.links !== null
? {
github: project.links.github, github: project.links.github,
website: project.links.website website: project.links.website,
} : null, }
: null,
image: project.image.publicURL, image: project.image.publicURL,
featured: project.featured, featured: project.featured,
frontend: `/${project.lang}/projects/${project.urlname}` frontend: `/${project.lang}/projects/${project.urlname}`,
} },
}));
});
}) })
} );
});
});
};

View file

@ -1,12 +1,6 @@
{ {
"extends": [ "extends": ["config:base"],
"config:base" "assignees": ["Unkn0wnCat"],
],
"assignees": [
"Unkn0wnCat"
],
"automerge": true, "automerge": true,
"baseBranches": [ "baseBranches": ["main"]
"main"
]
} }

View file

@ -4,14 +4,13 @@
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: center; justify-content: center;
} }
@mixin cardGeneric { @mixin cardGeneric {
border-radius: 5px; border-radius: 5px;
overflow: hidden; overflow: hidden;
box-shadow: -1px 11px 33px -10px rgba(127, 127, 127, 0.3); box-shadow: -1px 11px 33px -10px rgba(127, 127, 127, 0.3);
transition: transform .25s, box-shadow .25s; transition: transform 0.25s, box-shadow 0.25s;
color: $textColor; color: $textColor;
text-decoration: none; text-decoration: none;
margin: 20px; margin: 20px;
@ -21,7 +20,8 @@
&:active, &:active,
&:focus { &:focus {
transform: scale(1.05); transform: scale(1.05);
box-shadow: -1px 11px 33px -10px rgba(127, 127, 127, 0.2), -1px 11px 33px -10px rgba($accentColor, .75); box-shadow: -1px 11px 33px -10px rgba(127, 127, 127, 0.2),
-1px 11px 33px -10px rgba($accentColor, 0.75);
} }
} }
@ -32,13 +32,13 @@
background: $accentColor; background: $accentColor;
color: white; color: white;
text-decoration: none; text-decoration: none;
box-shadow: 0 0 33px -10px rgba($accentColor, .5); box-shadow: 0 0 33px -10px rgba($accentColor, 0.5);
transition: box-shadow .25s; transition: box-shadow 0.25s;
&:hover, &:hover,
&:active, &:active,
&:hover { &:hover {
box-shadow: 0 0 33px -10px rgba($accentColor, .9); box-shadow: 0 0 33px -10px rgba($accentColor, 0.9);
} }
} }
@ -58,7 +58,7 @@
height: 50px; height: 50px;
} }
>div { > div {
display: flex; display: flex;
height: 100%; height: 100%;
padding: 20px !important; padding: 20px !important;
@ -66,13 +66,12 @@
font-size: 1.7em; font-size: 1.7em;
color: white; color: white;
>span { > span {
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
} }
>i { > i {
display: inline-flex; display: inline-flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;

View file

@ -4,5 +4,4 @@ $background: #070707;
$textColor: white; $textColor: white;
$layoutPadding: 20px; $layoutPadding: 20px;
$mainFont: 'Anonymous Pro', $mainFont: "Anonymous Pro", monospace;
monospace;

View file

@ -1,5 +1,5 @@
import React from "react" import React from "react";
import { Link, Trans, useI18next } from 'gatsby-plugin-react-i18next'; import { Link, Trans, useI18next } from "gatsby-plugin-react-i18next";
import * as styles from "./languageSwitcher.module.scss"; import * as styles from "./languageSwitcher.module.scss";
@ -9,7 +9,13 @@ export default function LanguageSwitcher() {
return ( return (
<div className={styles.languageModal} id="languageChooser"> <div className={styles.languageModal} id="languageChooser">
<div className={styles.languageModalInner}> <div className={styles.languageModalInner}>
<h2>Languages (<a href="#top" className={styles.modalCloseLink}>&times;</a>)</h2> <h2>
Languages (
<a href="#top" className={styles.modalCloseLink}>
&times;
</a>
)
</h2>
<ul> <ul>
{languages.map((lng) => ( {languages.map((lng) => (
<li key={lng}> <li key={lng}>

View file

@ -7,11 +7,11 @@
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
background: rgba(0, 0, 0, .7); background: rgba(0, 0, 0, 0.7);
z-index: 1000; z-index: 1000;
opacity: 0; opacity: 0;
pointer-events: none; pointer-events: none;
transition: opacity .25s; transition: opacity 0.25s;
&:target { &:target {
opacity: 1; opacity: 1;
@ -33,7 +33,6 @@
color: white; color: white;
text-decoration-style: dotted; text-decoration-style: dotted;
} }
} }
.modalCloseLink { .modalCloseLink {

View file

@ -1,26 +1,26 @@
import React, { useEffect, useState } from "react" import React, { useEffect, useState } from "react";
import PropTypes from "prop-types" import PropTypes from "prop-types";
import { Trans, Link } from "gatsby-plugin-react-i18next" import { Trans, Link } from "gatsby-plugin-react-i18next";
import { graphql, StaticQuery } from 'gatsby' import { graphql, StaticQuery } from "gatsby";
import * as styles from './navigation.module.scss' import * as styles from "./navigation.module.scss";
const Navigation = ({ isHome }) => { const Navigation = ({ isHome }) => {
let [atTop, setAtTop] = useState(false); let [atTop, setAtTop] = useState(false);
const updateTransparency = () => { const updateTransparency = () => {
if(typeof window === "undefined") return; if (typeof window === "undefined") return;
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
if (window.scrollY < 15) { if (window.scrollY < 15) {
if(!atTop) setAtTop(true); if (!atTop) setAtTop(true);
} else { } else {
if(atTop) setAtTop(false); if (atTop) setAtTop(false);
}
} }
};
useEffect(() => { useEffect(() => {
if(typeof window === "undefined") return; if (typeof window === "undefined") return;
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
window.addEventListener("scroll", updateTransparency); window.addEventListener("scroll", updateTransparency);
@ -30,7 +30,7 @@ const Navigation = ({ isHome }) => {
updateTransparency(); updateTransparency();
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
let int = window.setInterval(updateTransparency, 10000) let int = window.setInterval(updateTransparency, 10000);
return () => { return () => {
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
@ -40,13 +40,20 @@ const Navigation = ({ isHome }) => {
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
window.clearInterval(int); window.clearInterval(int);
} };
}); });
return ( return (
<div className={styles.topBar + (isHome ? " "+styles.homeBar : "") + (atTop ? " "+styles.homeBarTransparent : "")}> <div
className={
styles.topBar +
(isHome ? " " + styles.homeBar : "") +
(atTop ? " " + styles.homeBarTransparent : "")
}
>
<nav className={styles.topBarInner}> <nav className={styles.topBarInner}>
<StaticQuery query={graphql` <StaticQuery
query={graphql`
query { query {
site { site {
siteMetadata { siteMetadata {
@ -54,19 +61,31 @@ const Navigation = ({ isHome }) => {
} }
} }
} }
`} render={data => ( `}
<Link to="/" activeClassName={styles.active}>{data.site.siteMetadata.title}</Link> render={(data) => (
)} /> <Link to="/" activeClassName={styles.active}>
{data.site.siteMetadata.title}
</Link>
)}
/>
<div className="flexSpacer"></div> <div className="flexSpacer"></div>
<Link id="navBtnProjects" to="/projects" activeClassName={styles.active}><Trans>projects</Trans></Link> <Link
<Link id="navBtnSocial" to="/social" activeClassName={styles.active}><Trans>social</Trans></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> </nav>
</div> </div>
); );
} };
Navigation.propTypes = { Navigation.propTypes = {
isHome: PropTypes.bool.isRequired isHome: PropTypes.bool.isRequired,
} };
export default Navigation; export default Navigation;

View file

@ -7,13 +7,13 @@
left: 0; left: 0;
display: flex; display: flex;
width: 100%; width: 100%;
background: rgba($background, .95); background: rgba($background, 0.95);
backdrop-filter: blur(5px); backdrop-filter: blur(5px);
z-index: 999; z-index: 999;
transition: background .25s; transition: background 0.25s;
@supports(backdrop-filter: blur(5px)) { @supports (backdrop-filter: blur(5px)) {
background: rgba($background, .9); background: rgba($background, 0.9);
} }
.topBarInner { .topBarInner {
@ -38,7 +38,7 @@
border-top: 2px solid transparent; border-top: 2px solid transparent;
&:hover { &:hover {
border-color: rgba(255, 255, 255, .25); border-color: rgba(255, 255, 255, 0.25);
} }
&.active { &.active {
@ -53,8 +53,6 @@
backdrop-filter: blur(0); backdrop-filter: blur(0);
} }
.flexSpacer { .flexSpacer {
flex-grow: 1; flex-grow: 1;
text-align: center; text-align: center;

View file

@ -1,8 +1,8 @@
import React from "react" import React from "react";
import PropTypes from "prop-types" import PropTypes from "prop-types";
import { Helmet } from "gatsby-plugin-react-i18next" import { Helmet } from "gatsby-plugin-react-i18next";
import { useStaticQuery, graphql } from "gatsby" import { useStaticQuery, graphql } from "gatsby";
import { useTranslation } from 'gatsby-plugin-react-i18next'; import { useTranslation } from "gatsby-plugin-react-i18next";
function SEO({ description, meta, title }) { function SEO({ description, meta, title }) {
const { t } = useTranslation(); const { t } = useTranslation();
@ -18,7 +18,7 @@ function SEO({ description, meta, title }) {
} }
} }
` `
) );
const metaDescription = description || t("siteDescription"); const metaDescription = description || t("siteDescription");
@ -61,26 +61,32 @@ function SEO({ description, meta, title }) {
}, },
{ {
name: "keywords", name: "keywords",
content: site.siteMetadata.keywords content: site.siteMetadata.keywords,
} },
].concat(meta)} ].concat(meta)}
> >
<script src="https://kit.fontawesome.com/1377f925e0.js" crossOrigin="anonymous"></script> <script
src="https://kit.fontawesome.com/1377f925e0.js"
crossOrigin="anonymous"
></script>
<link rel="preconnect" href="https://fonts.gstatic.com" /> <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" /> <link
href="https://fonts.googleapis.com/css2?family=Anonymous+Pro:wght@400;700&family=Roboto&display=swap"
rel="stylesheet"
/>
</Helmet> </Helmet>
) );
} }
SEO.defaultProps = { SEO.defaultProps = {
meta: [], meta: [],
description: ``, description: ``,
} };
SEO.propTypes = { SEO.propTypes = {
description: PropTypes.string, description: PropTypes.string,
meta: PropTypes.arrayOf(PropTypes.object), meta: PropTypes.arrayOf(PropTypes.object),
title: PropTypes.string.isRequired, title: PropTypes.string.isRequired,
} };
export default SEO export default SEO;

View file

@ -1,22 +1,41 @@
import React from "react" import React from "react";
import PropTypes from "prop-types" import PropTypes from "prop-types";
import Navigation from "../components/navigation" import Navigation from "../components/navigation";
import SEO from "../components/seo"; import SEO from "../components/seo";
import "./default.scss"; import "./default.scss";
import { Link, Trans } from 'gatsby-plugin-react-i18next'; import { Link, Trans } from "gatsby-plugin-react-i18next";
import LanguageSwitcher from "../components/languageSwitcher"; import LanguageSwitcher from "../components/languageSwitcher";
class Layout extends React.Component { class Layout extends React.Component {
render() { render() {
return ( return (
<> <>
<SEO description={this.props.description} lang={this.props.lang} meta={this.props.meta} title={this.props.title} /> <SEO
description={this.props.description}
lang={this.props.lang}
meta={this.props.meta}
title={this.props.title}
/>
<Navigation isHome={this.props.transparentTopbar} /> <Navigation isHome={this.props.transparentTopbar} />
<div id="content" role="main"> <div id="content" role="main">
{this.props.children} {this.props.children}
</div> </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> <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 />
</> </>
@ -28,8 +47,8 @@ Layout.defaultProps = {
module: `none`, module: `none`,
meta: [], meta: [],
description: ``, description: ``,
transparentTopbar: false transparentTopbar: false,
} };
Layout.propTypes = { Layout.propTypes = {
description: PropTypes.string, description: PropTypes.string,
@ -37,7 +56,7 @@ Layout.propTypes = {
meta: PropTypes.arrayOf(PropTypes.object), meta: PropTypes.arrayOf(PropTypes.object),
title: PropTypes.string.isRequired, title: PropTypes.string.isRequired,
transparentTopbar: PropTypes.bool, transparentTopbar: PropTypes.bool,
children: PropTypes.any.isRequired children: PropTypes.any.isRequired,
} };
export default Layout; export default Layout;

View file

@ -41,16 +41,15 @@ footer {
flex-direction: column; flex-direction: column;
} }
.flexSpacer { .flexSpacer {
flex-grow: 1; flex-grow: 1;
text-align: center; text-align: center;
} }
section>div:not(.profile), section > div:not(.profile),
section>article, section > article,
.section>div:not(.profile), .section > div:not(.profile),
.section>article { .section > article {
max-width: $layoutWidth; max-width: $layoutWidth;
width: 100%; width: 100%;
padding: 39px 20px; padding: 39px 20px;
@ -72,4 +71,3 @@ article {
h1 { h1 {
font-size: 2em; font-size: 2em;
} }

View file

@ -1,6 +1,6 @@
import * as React from "react" import * as React from "react";
import { Link } from "gatsby-plugin-react-i18next" import { Link } from "gatsby-plugin-react-i18next";
import Layout from "../layouts/default" import Layout from "../layouts/default";
const NotFoundPage = () => { const NotFoundPage = () => {
return ( return (
@ -9,12 +9,13 @@ const NotFoundPage = () => {
<article> <article>
<h1>Page not found</h1> <h1>Page not found</h1>
<p> <p>
Whoops... That page doesn&apos;t exist, so you may as well <Link to="/">go home</Link>. Whoops... That page doesn&apos;t exist, so you may as well{" "}
<Link to="/">go home</Link>.
</p> </p>
</article> </article>
</section> </section>
</Layout> </Layout>
) );
} };
export default NotFoundPage export default NotFoundPage;

View file

@ -1,14 +1,14 @@
import React, { useState } from "react" import React, { useState } from "react";
import Layout from "../layouts/default"; import Layout from "../layouts/default";
import { graphql } from "gatsby"; import { graphql } from "gatsby";
import { Trans, useI18next, I18nextContext } from "gatsby-plugin-react-i18next" import { Trans, useI18next, I18nextContext } from "gatsby-plugin-react-i18next";
import PropTypes from "prop-types" import PropTypes from "prop-types";
import GitHubButton from 'react-github-btn' import GitHubButton from "react-github-btn";
import * as styles from "./donate.module.scss"; import * as styles from "./donate.module.scss";
export const query = graphql` export const query = graphql`
query ($language: String!) { query($language: String!) {
site { site {
siteMetadata { siteMetadata {
title title
@ -17,14 +17,14 @@ query ($language: String!) {
contactGitHub contactGitHub
} }
} }
file(relativePath: {eq: "images/pplogo.png"}) { file(relativePath: { eq: "images/pplogo.png" }) {
childImageSharp { childImageSharp {
resize(width: 240, height: 240, fit: CONTAIN) { resize(width: 240, height: 240, fit: CONTAIN) {
src src
} }
} }
} }
locales: allLocale(filter: {language: {eq: $language}}) { locales: allLocale(filter: { language: { eq: $language } }) {
edges { edges {
node { node {
ns ns
@ -33,7 +33,7 @@ query ($language: String!) {
} }
} }
} }
} }
`; `;
function DonatePage(props) { function DonatePage(props) {
@ -47,23 +47,81 @@ function DonatePage(props) {
<Layout title={t("donate")} description={t("donationCatchphrase")}> <Layout title={t("donate")} description={t("donationCatchphrase")}>
<section> <section>
<article> <article>
<h1><Trans>donate</Trans></h1> <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}> <div className={styles.priceAmount}>
<label htmlFor="priceInput" className={styles.sronly}>Amount</label> <label htmlFor="priceInput" className={styles.sronly}>
<input type="number" min="1" placeholder="10.00" step="1" value={amount} onChange={(ev) => { setAmount(ev.target.value) }} name="priceInput" id="priceInput" /> 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>
</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) + "&currency_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> <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) +
"&currency_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> </article>
</section> </section>
</Layout> </Layout>
@ -71,7 +129,7 @@ function DonatePage(props) {
} }
DonatePage.propTypes = { DonatePage.propTypes = {
data: PropTypes.object.isRequired data: PropTypes.object.isRequired,
}; };
export default DonatePage; export default DonatePage;

View file

@ -5,7 +5,7 @@
display: flex; display: flex;
width: 150px; width: 150px;
margin: 20px auto; margin: 20px auto;
border: thin solid rgba(0, 0, 0, .25); border: thin solid rgba(0, 0, 0, 0.25);
border-radius: 5px; border-radius: 5px;
overflow: hidden; overflow: hidden;
line-height: 40px; line-height: 40px;
@ -15,7 +15,7 @@
border: none; border: none;
padding-left: 10px; padding-left: 10px;
width: 1px; width: 1px;
border-right: thin solid rgba(0, 0, 0, .25); border-right: thin solid rgba(0, 0, 0, 0.25);
} }
div { div {

View file

@ -1,8 +1,8 @@
import React from "react" import React from "react";
import Layout from "../../layouts/default"; import Layout from "../../layouts/default";
import { Trans, useI18next } from "gatsby-plugin-react-i18next" import { Trans, useI18next } from "gatsby-plugin-react-i18next";
import { graphql } from "gatsby"; import { graphql } from "gatsby";
import PropTypes from "prop-types" import PropTypes from "prop-types";
export const query = graphql` export const query = graphql`
query GetThankYouPage($language: String!) { query GetThankYouPage($language: String!) {
@ -11,7 +11,7 @@ export const query = graphql`
contactEmail contactEmail
} }
} }
locales: allLocale(filter: {language: {eq: $language}}) { locales: allLocale(filter: { language: { eq: $language } }) {
edges { edges {
node { node {
ns ns
@ -21,10 +21,10 @@ export const query = graphql`
} }
} }
} }
` `;
function ThankYouPage(props) { function ThankYouPage(props) {
const { site } = props.data const { site } = props.data;
let contactEmail = site.siteMetadata.contactEmail; let contactEmail = site.siteMetadata.contactEmail;
const { t } = useI18next(); const { t } = useI18next();
@ -32,9 +32,16 @@ function ThankYouPage(props) {
<Layout title={t("donate")}> <Layout title={t("donate")}>
<section> <section>
<article> <article>
<h1><Trans>donateThanks</Trans></h1> <h1>
<Trans>donateThanks</Trans>
</h1>
<p><Trans contactEmail={contactEmail} i18nKey="donateThanksText">donateThanksText<a href={"mailto:" + contactEmail}>{{ contactEmail }}</a></Trans></p> <p>
<Trans contactEmail={contactEmail} i18nKey="donateThanksText">
donateThanksText
<a href={"mailto:" + contactEmail}>{{ contactEmail }}</a>
</Trans>
</p>
</article> </article>
</section> </section>
</Layout> </Layout>
@ -42,7 +49,7 @@ function ThankYouPage(props) {
} }
ThankYouPage.propTypes = { ThankYouPage.propTypes = {
data: PropTypes.object.isRequired data: PropTypes.object.isRequired,
}; };
export default ThankYouPage; export default ThankYouPage;

View file

@ -1,13 +1,13 @@
import React from "react" import React from "react";
import Layout from "../layouts/default"; import Layout from "../layouts/default";
import { Trans, useI18next } from "gatsby-plugin-react-i18next" import { Trans, useI18next } from "gatsby-plugin-react-i18next";
import { graphql } from 'gatsby' import { graphql } from "gatsby";
import PropTypes from "prop-types" import PropTypes from "prop-types";
import * as styles from "./friends.module.scss"; import * as styles from "./friends.module.scss";
export const query = graphql` export const query = graphql`
query AllFriendsQuery($language: String!) { query AllFriendsQuery($language: String!) {
allFriendsJson { allFriendsJson {
nodes { nodes {
name name
@ -16,7 +16,7 @@ query AllFriendsQuery($language: String!) {
imageURL imageURL
} }
} }
locales: allLocale(filter: {language: {eq: $language}}) { locales: allLocale(filter: { language: { eq: $language } }) {
edges { edges {
node { node {
ns ns
@ -26,11 +26,9 @@ query AllFriendsQuery($language: String!) {
} }
} }
} }
`;
`
const FriendsPage = ({ data }) => { const FriendsPage = ({ data }) => {
const { t } = useI18next(); const { t } = useI18next();
function shuffle(a) { function shuffle(a) {
@ -45,36 +43,54 @@ const FriendsPage = ({ data }) => {
<Layout title={t("friends")} description={t("friendsDescription")}> <Layout title={t("friends")} description={t("friendsDescription")}>
<section> <section>
<article> <article>
<h1><Trans>social</Trans></h1> <h1>
<Trans>social</Trans>
</h1>
<p><Trans>friendsDescription</Trans></p> <p>
<Trans>friendsDescription</Trans>
</p>
<div className={styles.friendsList}> <div className={styles.friendsList}>
{ {shuffle(data.allFriendsJson.nodes).map((friend) => {
shuffle(data.allFriendsJson.nodes).map((friend) => {
return ( return (
<div className={styles.friendProfile} key={friend.url + "#" + friend.name}> <div
<div className={styles.friendImage} style={{ backgroundImage: "url(" + friend.imageURL + ")" }}> className={styles.friendProfile}
key={friend.url + "#" + friend.name}
>
<div
className={styles.friendImage}
style={{ backgroundImage: "url(" + friend.imageURL + ")" }}
>
<span className={styles.friendName}>{friend.name}</span> <span className={styles.friendName}>{friend.name}</span>
<span className={styles.friendTitle}>{friend.profession}</span> <span className={styles.friendTitle}>
{friend.profession}
</span>
</div> </div>
<div className={styles.contactLinks}> <div className={styles.contactLinks}>
<a className={styles.contactLink} href={friend.url} target="_blank" rel="noreferrer"><i className="fas fa-globe-europe" aria-hidden="true"></i> {friend.url}</a> <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> </div>
); );
}) })}
}
</div> </div>
</article> </article>
</section> </section>
</Layout> </Layout>
); );
} };
FriendsPage.propTypes = { FriendsPage.propTypes = {
data: PropTypes.object.isRequired data: PropTypes.object.isRequired,
}; };
export default FriendsPage; export default FriendsPage;

View file

@ -46,12 +46,12 @@
flex-direction: column; flex-direction: column;
.contactLink { .contactLink {
transition: text-decoration .5s; transition: text-decoration 0.5s;
text-decoration: underline dotted rgba(0, 0, 0, 0); text-decoration: underline dotted rgba(0, 0, 0, 0);
padding: 6px 0 6px 25px; padding: 6px 0 6px 25px;
color: $textColor; color: $textColor;
>i { > i {
color: $accentColor; color: $accentColor;
margin-left: -25px; margin-left: -25px;
margin-right: 5px; margin-right: 5px;

View file

@ -1,16 +1,15 @@
import * as React from "react" import * as React from "react";
import Layout from "../layouts/default" import Layout from "../layouts/default";
import PropTypes from "prop-types" import PropTypes from "prop-types";
import * as styles from "./index.module.scss" import * as styles from "./index.module.scss";
import * as projectStyles from "./projects.module.scss" import * as projectStyles from "./projects.module.scss";
import { Trans, Link } from "gatsby-plugin-react-i18next" import { Trans, Link } from "gatsby-plugin-react-i18next";
import { graphql } from "gatsby"; import { graphql } from "gatsby";
import anime from "animejs"; import anime from "animejs";
export const query = graphql` export const query = graphql`
query GetMetaAndProjects($language: String) { query GetMetaAndProjects($language: String) {
site { site {
@ -24,7 +23,10 @@ export const query = graphql`
contactMastodonHref contactMastodonHref
} }
} }
allProjectsJson(filter: {lang: {eq: $language}, featured: {gte: 0}}, sort: {fields: featured, order: ASC}) { allProjectsJson(
filter: { lang: { eq: $language }, featured: { gte: 0 } }
sort: { fields: featured, order: ASC }
) {
nodes { nodes {
lang lang
urlname urlname
@ -40,7 +42,7 @@ export const query = graphql`
featured featured
} }
} }
locales: allLocale(filter: {language: {eq: $language}}) { locales: allLocale(filter: { language: { eq: $language } }) {
edges { edges {
node { node {
ns ns
@ -55,26 +57,29 @@ export const query = graphql`
class IndexPage extends React.Component { class IndexPage extends React.Component {
componentDidMount() { componentDidMount() {
anime({ anime({
targets: ["."+styles.profileCard+" > span", "."+styles.profileCard+" a"], targets: [
"." + styles.profileCard + " > span",
"." + styles.profileCard + " a",
],
opacity: [0, 1], opacity: [0, 1],
translateX: [100, 0], translateX: [100, 0],
duration: 250, duration: 250,
delay: anime.stagger(20), delay: anime.stagger(20),
easing: 'easeInOutCirc' easing: "easeInOutCirc",
}); });
anime({ anime({
targets: ["."+styles.profileImageDummy], targets: ["." + styles.profileImageDummy],
translateX: [0, -3], translateX: [0, -3],
translateY: [0, 3], translateY: [0, 3],
duration: 250, duration: 250,
easing: 'easeInOutCirc' easing: "easeInOutCirc",
}); });
anime({ anime({
targets: ["."+styles.profileImage], targets: ["." + styles.profileImage],
translateX: [0, 4], translateX: [0, 4],
translateY: [0, -4], translateY: [0, -4],
duration: 250, duration: 250,
easing: 'easeInOutCirc' easing: "easeInOutCirc",
}); });
} }
@ -85,45 +90,128 @@ class IndexPage extends React.Component {
<Layout title="Kevin Kandlbinder" transparentTopbar={true}> <Layout title="Kevin Kandlbinder" transparentTopbar={true}>
<section className={styles.heroSection}> <section className={styles.heroSection}>
<div className={styles.profile + " profile"}> <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
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.profileImageDummy}></div>
<div className={styles.profileCard}> <div className={styles.profileCard}>
<span className={styles.hello}><Trans>homeHello</Trans></span> <span className={styles.hello}>
<Trans>homeHello</Trans>
</span>
<span className={styles.name}>Kevin Kandlbinder</span> <span className={styles.name}>Kevin Kandlbinder</span>
<span className={styles.description}><Trans>homeMe</Trans> <span id="descriptionType"><Trans>homeWebDeveloper</Trans></span>.</span> <span className={styles.description}>
<Trans>homeMe</Trans>{" "}
<span id="descriptionType">
<Trans>homeWebDeveloper</Trans>
</span>
.
</span>
<div className={styles.contactLinks}> <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
<a className={styles.contactLink} href={"mailto:" + meta.contactEmail} rel="me"><i className="far fa-fw fa-envelope"></i>{meta.contactEmail}</a> className={styles.contactLink}
<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> href={"tel:" + meta.contactPhone}
<a className={styles.contactLink} href={meta.contactMastodonHref} rel="noreferrer me" target="_blank"><i className="fab fa-fw fa-mastodon"></i>{meta.contactMastodon}</a> rel="me"
<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> >
<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> </div>
</div> </div>
</section> </section>
<section className="aboutSection"> <section className="aboutSection">
<article> <article>
<h1><Trans>homeAboutMe</Trans></h1> <h1>
<p><Trans>homeAboutMeHello</Trans><br /><Trans>homeAboutMeText</Trans></p> <Trans>homeAboutMe</Trans>
</h1>
<p>
<Trans>homeAboutMeHello</Trans>
<br />
<Trans>homeAboutMeText</Trans>
</p>
</article> </article>
</section> </section>
<a className={styles.creditSection} href="https://unsplash.com/@jannikkiel" target="_blank" rel="noreferrer"> <a
className={styles.creditSection}
href="https://unsplash.com/@jannikkiel"
target="_blank"
rel="noreferrer"
>
<div> <div>
<span><i className="fas fa-fw fa-camera"></i> <Trans>homeImageCredit</Trans></span> <span>
<i className="fas fa-fw fa-camera"></i>{" "}
<Trans>homeImageCredit</Trans>
</span>
<i className="fas fa-fw fa-chevron-right"></i> <i className="fas fa-fw fa-chevron-right"></i>
</div> </div>
</a> </a>
<section className="featuredSection"> <section className="featuredSection">
<article> <article>
<h1><Trans>featuredProjects</Trans></h1> <h1>
<Trans>featuredProjects</Trans>
</h1>
<div className={projectStyles.projectList}> <div className={projectStyles.projectList}>
{this.props.data.allProjectsJson.nodes.map((project) => { {this.props.data.allProjectsJson.nodes.map((project) => {
return ( return (
<Link className={projectStyles.projectCard} key={project.lang + "/" + project.urlname} to={"/projects/" + project.urlname}> <Link
<div className={projectStyles.projectCardImage} style={{ backgroundImage: "url(" + project.image.childImageSharp.resize.src + ")" }}> 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}> <div className={projectStyles.projectCardMeta}>
<span className={projectStyles.projectCardTitle}>{project.name}</span> <span className={projectStyles.projectCardTitle}>
{project.name}
</span>
<span>{project.shortDescription}</span> <span>{project.shortDescription}</span>
</div> </div>
</div> </div>
@ -131,22 +219,27 @@ class IndexPage extends React.Component {
); );
})} })}
</div> </div>
<Link to="/projects" className={styles.seeMoreButton}><Trans>seeMore</Trans> <i className="fas fa-fw fa-chevron-right"></i></Link> <Link to="/projects" className={styles.seeMoreButton}>
<Trans>seeMore</Trans>{" "}
<i className="fas fa-fw fa-chevron-right"></i>
</Link>
</article> </article>
</section> </section>
<Link className={styles.donationSection} to="/donate"> <Link className={styles.donationSection} to="/donate">
<div> <div>
<span><Trans>donationCatchphrase</Trans></span> <span>
<Trans>donationCatchphrase</Trans>
</span>
<i className="fas fa-fw fa-chevron-right"></i> <i className="fas fa-fw fa-chevron-right"></i>
</div> </div>
</Link> </Link>
</Layout> </Layout>
) );
} }
} }
IndexPage.propTypes = { IndexPage.propTypes = {
data: PropTypes.object.isRequired data: PropTypes.object.isRequired,
} };
export default IndexPage export default IndexPage;

View file

@ -7,10 +7,11 @@
min-height: 600px; min-height: 600px;
padding-top: 100px; padding-top: 100px;
overflow: hidden; overflow: hidden;
background: linear-gradient(to bottom, transparent 80%, $background), radial-gradient(ellipse at top left, #1f0ba659, transparent), radial-gradient(ellipse at bottom right, #4a086829, transparent); background: linear-gradient(to bottom, transparent 80%, $background),
radial-gradient(ellipse at top left, #1f0ba659, transparent),
radial-gradient(ellipse at bottom right, #4a086829, transparent);
@media(pointer: coarse), @media (pointer: coarse), (pointer: none) {
(pointer: none) {
min-height: 700px; min-height: 700px;
} }
@ -24,7 +25,7 @@
.hello { .hello {
font-weight: 100; font-weight: 100;
opacity: .75; opacity: 0.75;
display: block; display: block;
margin-bottom: -5px; margin-bottom: -5px;
} }
@ -47,13 +48,12 @@
} }
.contactLink { .contactLink {
transition: text-decoration .5s; transition: text-decoration 0.5s;
text-decoration: underline dotted rgba(0, 0, 0, 0); text-decoration: underline dotted rgba(0, 0, 0, 0);
padding: 6px 0 6px 25px; padding: 6px 0 6px 25px;
color: $textColor; color: $textColor;
@media(pointer: coarse), @media (pointer: coarse), (pointer: none) {
(pointer: none) {
padding-top: 15px; padding-top: 15px;
padding-bottom: 15px; padding-bottom: 15px;
} }
@ -61,10 +61,10 @@
.contactLink:hover, .contactLink:hover,
.contactLink:active { .contactLink:active {
text-decoration: underline dotted rgba(0, 0, 0, .5); text-decoration: underline dotted rgba(0, 0, 0, 0.5);
} }
.contactLink>i { .contactLink > i {
color: $accentColor; color: $accentColor;
margin-left: -25px; margin-left: -25px;
margin-right: 5px; margin-right: 5px;
@ -90,7 +90,7 @@
background-color: #1c1c1c; background-color: #1c1c1c;
background-size: cover; background-size: cover;
background-position: center; background-position: center;
transition: transform .25s; transition: transform 0.25s;
} }
.profileImage { .profileImage {
@ -101,11 +101,10 @@
.profileImageDummy { .profileImageDummy {
z-index: 10; z-index: 10;
background: $accentColor; background: $accentColor;
opacity: .2; opacity: 0.2;
} }
@media (max-width: 590px) { @media (max-width: 590px) {
.profileImage, .profileImage,
.profileImageDummy { .profileImageDummy {
display: none; display: none;
@ -115,11 +114,8 @@
padding: 20px 20px 20px 20px; padding: 20px 20px 20px 20px;
transform: translate(20px, 20px); transform: translate(20px, 20px);
} }
} }
} }
} }
.amazonAlexaSection, .amazonAlexaSection,
@ -131,13 +127,13 @@
.creditSection { .creditSection {
@include homeBanner; @include homeBanner;
>div { > div {
padding: 15px !important; padding: 15px !important;
line-height: 15px; line-height: 15px;
font-size: 1.2em; font-size: 1.2em;
color: white; color: white;
>span>i { > span > i {
line-height: 15px !important; line-height: 15px !important;
} }
} }

View file

@ -1,11 +1,11 @@
import React from "react" import React from "react";
import Layout from "../../layouts/default"; import Layout from "../../layouts/default";
import { Trans, useI18next } from "gatsby-plugin-react-i18next" import { Trans, useI18next } from "gatsby-plugin-react-i18next";
import { graphql } from "gatsby"; import { graphql } from "gatsby";
export const query = graphql` export const query = graphql`
query ($language: String!) { query($language: String!) {
locales: allLocale(filter: {language: {eq: $language}}) { locales: allLocale(filter: { language: { eq: $language } }) {
edges { edges {
node { node {
ns ns
@ -15,25 +15,40 @@ export const query = graphql`
} }
} }
} }
` `;
export default function ImprintPage() { export default function ImprintPage() {
const { t } = useI18next(); const { t } = useI18next();
return ( return (
<Layout title={t("imprint")}> <Layout title={t("imprint")}>
<section> <section>
<article> <article>
<h1><Trans>imprint</Trans></h1> <h1>
<Trans>imprint</Trans>
</h1>
<p>Angaben gemäß § 5 TMG</p><p>Kevin Kandlbinder<br /> <p>Angaben gemäß § 5 TMG</p>
Eichenweg 48<br /> <p>
Kevin Kandlbinder
<br />
Eichenweg 48
<br />
25451 Quickborn <br /> 25451 Quickborn <br />
</p><p> <strong>Vertreten durch: </strong><br /> </p>
Kevin Kandlbinder<br /> <p>
</p><p><strong>Kontakt:</strong> <br /> {" "}
Telefon: +49 4106 8068004<br /> <strong>Vertreten durch: </strong>
E-Mail: <a href='mailto:contact@kevink.dev'>contact@kevink.dev</a><br /></p> <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> </article>
</section> </section>
</Layout> </Layout>

File diff suppressed because one or more lines are too long

View file

@ -1,11 +1,11 @@
import React from "react" import React from "react";
import Layout from "../../layouts/default"; import Layout from "../../layouts/default";
import { Trans, useI18next } from "gatsby-plugin-react-i18next" import { Trans, useI18next } from "gatsby-plugin-react-i18next";
import { graphql } from "gatsby"; import { graphql } from "gatsby";
export const query = graphql` export const query = graphql`
query ($language: String!) { query($language: String!) {
locales: allLocale(filter: {language: {eq: $language}}) { locales: allLocale(filter: { language: { eq: $language } }) {
edges { edges {
node { node {
ns ns
@ -15,34 +15,78 @@ export const query = graphql`
} }
} }
} }
` `;
export default function DisclaimerPage() { export default function DisclaimerPage() {
const { t } = useI18next(); const { t } = useI18next();
return ( return (
<Layout title={t("disclaimer")}> <Layout title={t("disclaimer")}>
<section> <section>
<article> <article>
<h1><Trans>disclaimer</Trans></h1> <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> <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> </article>
</section> </section>
</Layout> </Layout>

View file

@ -1,14 +1,14 @@
import React from "react" import React from "react";
import Layout from "../layouts/default"; import Layout from "../layouts/default";
import { Trans, Link, useI18next } from "gatsby-plugin-react-i18next" import { Trans, Link, useI18next } from "gatsby-plugin-react-i18next";
import { graphql } from 'gatsby' import { graphql } from "gatsby";
import PropTypes from "prop-types" import PropTypes from "prop-types";
import * as styles from "./projects.module.scss"; import * as styles from "./projects.module.scss";
export const query = graphql` export const query = graphql`
query GetProjects($language: String) { query GetProjects($language: String) {
allProjectsJson(filter: {lang: {eq: $language}}) { allProjectsJson(filter: { lang: { eq: $language } }) {
nodes { nodes {
lang lang
urlname urlname
@ -23,7 +23,7 @@ query GetProjects($language: String) {
shortDescription shortDescription
} }
} }
locales: allLocale(filter: {language: {eq: $language}}) { locales: allLocale(filter: { language: { eq: $language } }) {
edges { edges {
node { node {
ns ns
@ -32,27 +32,42 @@ query GetProjects($language: String) {
} }
} }
} }
} }
` `;
const ProjectsPage = ({ data }) => { const ProjectsPage = ({ data }) => {
const { t } = useI18next(); const { t } = useI18next();
return ( return (
<Layout title={t("projects")} description={t("projectsDescription")}> <Layout title={t("projects")} description={t("projectsDescription")}>
<section> <section>
<article> <article>
<h1><Trans>projects</Trans></h1> <h1>
<Trans>projects</Trans>
</h1>
<p><Trans>projectsDescription</Trans></p> <p>
<Trans>projectsDescription</Trans>
</p>
<div className={styles.projectList}> <div className={styles.projectList}>
{data.allProjectsJson.nodes.map((project) => { {data.allProjectsJson.nodes.map((project) => {
return ( return (
<Link className={styles.projectCard} key={project.lang + project.urlname} to={"/projects/" + project.urlname}> <Link
<div className={styles.projectCardImage} style={{ backgroundImage: "url(" + project.image.childImageSharp.resize.src + ")" }}> 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}> <div className={styles.projectCardMeta}>
<span className={styles.projectCardTitle}>{project.name}</span> <span className={styles.projectCardTitle}>
{project.name}
</span>
<span>{project.shortDescription}</span> <span>{project.shortDescription}</span>
</div> </div>
</div> </div>
@ -64,10 +79,10 @@ const ProjectsPage = ({ data }) => {
</section> </section>
</Layout> </Layout>
); );
} };
ProjectsPage.propTypes = { ProjectsPage.propTypes = {
data: PropTypes.object data: PropTypes.object,
} };
export default ProjectsPage; export default ProjectsPage;

View file

@ -73,7 +73,7 @@
display: flex; display: flex;
} }
@media(max-width: 900px) { @media (max-width: 900px) {
.projectCardCTAContainer { .projectCardCTAContainer {
flex-direction: column; flex-direction: column;
} }
@ -83,7 +83,7 @@
} }
} }
.projectCardCTAContainer>* { .projectCardCTAContainer > * {
flex-grow: 1; flex-grow: 1;
} }
} }

View file

@ -1,13 +1,13 @@
import React from "react" import React from "react";
import Layout from "../layouts/default"; import Layout from "../layouts/default";
import { Trans, Link, useI18next } from "gatsby-plugin-react-i18next" import { Trans, Link, useI18next } from "gatsby-plugin-react-i18next";
import { graphql } from 'gatsby' import { graphql } from "gatsby";
import PropTypes from "prop-types" import PropTypes from "prop-types";
import * as styles from "./social.module.scss"; import * as styles from "./social.module.scss";
export const query = graphql` export const query = graphql`
query AllSocialsQuery($language: String!) { query AllSocialsQuery($language: String!) {
allSocialsJson { allSocialsJson {
nodes { nodes {
image image
@ -16,7 +16,7 @@ query AllSocialsQuery($language: String!) {
url url
} }
} }
locales: allLocale(filter: {language: {eq: $language}}) { locales: allLocale(filter: { language: { eq: $language } }) {
edges { edges {
node { node {
ns ns
@ -26,41 +26,57 @@ query AllSocialsQuery($language: String!) {
} }
} }
} }
` `;
const SocialPage = ({ data }) => { const SocialPage = ({ data }) => {
const { t } = useI18next(); const { t } = useI18next();
return ( return (
<Layout title={t("social")} description={t("socialDescription")}> <Layout title={t("social")} description={t("socialDescription")}>
<section> <section>
<article> <article>
<h1><Trans>social</Trans></h1> <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}> <div className={styles.socialList}>
{ {data.allSocialsJson.nodes.map((social) => {
data.allSocialsJson.nodes.map((social) => {
return ( return (
<a className={styles.socialCard} href={social.url} target="_blank" rel="noreferrer me" key={social.url}> <a
<div className={styles.socialImage} style={{ backgroundImage: "url(" + social.image + ")" }}> className={styles.socialCard}
<span className={styles.socialName}>{social.platformName}</span> href={social.url}
<span className={styles.socialUsername}>{social.platformHandle}</span> 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> </div>
</a> </a>
); );
}) })}
}
</div> </div>
</article> </article>
</section> </section>
</Layout> </Layout>
); );
} };
SocialPage.propTypes = { SocialPage.propTypes = {
data: PropTypes.object.isRequired data: PropTypes.object.isRequired,
}; };
export default SocialPage; export default SocialPage;

View file

@ -1,14 +1,16 @@
import React from "react" import React from "react";
import { graphql } from "gatsby" import { graphql } from "gatsby";
import { Trans, useTranslation } from 'gatsby-plugin-react-i18next'; import { Trans, useTranslation } from "gatsby-plugin-react-i18next";
import Layout from "../layouts/default"; import Layout from "../layouts/default";
import PropTypes from "prop-types" import PropTypes from "prop-types";
import * as styles from "./project.module.scss"; import * as styles from "./project.module.scss";
export const query = graphql` export const query = graphql`
query GetProject($urlname: String!, $lang: String!, $language: String!) { query GetProject($urlname: String!, $lang: String!, $language: String!) {
allProjectsJson(filter: {urlname: {eq: $urlname}, lang: {eq: $lang}}) { allProjectsJson(
filter: { urlname: { eq: $urlname }, lang: { eq: $lang } }
) {
nodes { nodes {
lang lang
urlname urlname
@ -24,7 +26,7 @@ query GetProject($urlname: String!, $lang: String!, $language: String!) {
shortDescription shortDescription
} }
} }
locales: allLocale(filter: {language: {eq: $language}}) { locales: allLocale(filter: { language: { eq: $language } }) {
edges { edges {
node { node {
ns ns
@ -33,8 +35,8 @@ query GetProject($urlname: String!, $lang: String!, $language: String!) {
} }
} }
} }
} }
` `;
const ProjectTemplate = ({ data }) => { const ProjectTemplate = ({ data }) => {
const { t } = useTranslation(); const { t } = useTranslation();
@ -42,45 +44,74 @@ const ProjectTemplate = ({ data }) => {
let projectName = project.name; let projectName = project.name;
return ( return (
<Layout description={project.shortDescription} title={t("project") + ": " + projectName} transparentTopbar={true}> <Layout
description={project.shortDescription}
title={t("project") + ": " + projectName}
transparentTopbar={true}
>
<section className={styles.projectHeader}> <section className={styles.projectHeader}>
<div style={{ paddingTop: 0 }}> <div style={{ paddingTop: 0 }}>
<div className={styles.headerBackground} style={{ backgroundImage: "url(" + project.image.publicURL + ")" }}></div> <div
className={styles.headerBackground}
style={{ backgroundImage: "url(" + project.image.publicURL + ")" }}
></div>
<header> <header>
<div className={styles.headerInner}> <div className={styles.headerInner}>
<h1><Trans>project</Trans>: {projectName}</h1> <h1>
<Trans>project</Trans>: {projectName}
</h1>
<span>{project.shortDescription}</span> <span>{project.shortDescription}</span>
</div> </div>
</header> </header>
<div className={styles.headerPlaceholder}></div> <div className={styles.headerPlaceholder}></div>
</div> </div>
</section> </section>
{project.longDescription != null ? {project.longDescription != null ? (
<section className={styles.projectAbout}> <section className={styles.projectAbout}>
<article> <article>
<h1><Trans projectName={projectName} i18nKey="projectAboutHeader">projectAboutHeader{{ projectName }}</Trans></h1> <h1>
<Trans projectName={projectName} i18nKey="projectAboutHeader">
projectAboutHeader{{ projectName }}
</Trans>
</h1>
<p>{project.longDescription}</p> <p>{project.longDescription}</p>
</article> </article>
</section> </section>
: null} ) : null}
{project.links !== null ? {project.links !== null ? (
<section className={styles.projectLinks}> <section className={styles.projectLinks}>
<div> <div>
<h1>Links</h1> <h1>Links</h1>
<div className={styles.linkList}> <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.github !== 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} <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>
</div> </div>
</section> </section>
: null} ) : null}
</Layout> </Layout>
); );
} };
ProjectTemplate.propTypes = { ProjectTemplate.propTypes = {
data: PropTypes.object.isRequired data: PropTypes.object.isRequired,
} };
export default ProjectTemplate; export default ProjectTemplate;

View file

@ -1,7 +1,7 @@
@import "../variables"; @import "../variables";
.projectHeader { .projectHeader {
>div { > div {
padding-bottom: 0 !important; padding-bottom: 0 !important;
} }
@ -19,7 +19,13 @@
left: 0; left: 0;
width: 100%; width: 100%;
height: 400px; height: 400px;
background: linear-gradient(to bottom, rgba($background, .95), rgba($background, .25) 20%, rgba($background, .35) 80%, rgba($background, 1) 100%); background: linear-gradient(
to bottom,
rgba($background, 0.95),
rgba($background, 0.25) 20%,
rgba($background, 0.35) 80%,
rgba($background, 1) 100%
);
.headerInner { .headerInner {
max-width: $layoutWidth; max-width: $layoutWidth;
@ -42,7 +48,6 @@
margin-top: auto; margin-top: auto;
} }
} }
} }
.headerPlaceholder { .headerPlaceholder {
@ -51,9 +56,11 @@
} }
} }
.projectAbout, .projectLinks { .projectAbout,
.projectLinks {
&:nth-of-type(2) { &:nth-of-type(2) {
> div, > article { > div,
> article {
padding-top: 20px; padding-top: 20px;
} }
} }