diff --git a/content/images/test.jpg b/content/images/test.jpg new file mode 100644 index 0000000..5ec42e5 Binary files /dev/null and b/content/images/test.jpg differ diff --git a/content/projects/kevink-dev.de.json b/content/projects/kevink-dev.de.json new file mode 100644 index 0000000..16da776 --- /dev/null +++ b/content/projects/kevink-dev.de.json @@ -0,0 +1,12 @@ +{ + "urlname": "kevink-dev", + "lang": "de", + "name": "KevinK.dev", + "shortDescription": "Diese Seite und der Code dahinter.", + "longDescription": "Schon so lange ich im Internet unterwegs bin war ich fasziniert von der Idee eine eigene Website zu haben. Deshalb habe ich mich an diese Seite gesetzt um mich selbst und meine Projekte zu repräsentieren. Wenn du interessiert an dem Code hinter der Seite bist, schau doch gerne auf GitHub vorbei!", + "links": { + "website": "https://kevink.dev", + "github": "https://github.com" + }, + "image": "../images/test.jpg" +} \ No newline at end of file diff --git a/content/projects/kevink-dev.en.json b/content/projects/kevink-dev.en.json new file mode 100644 index 0000000..3e4c192 --- /dev/null +++ b/content/projects/kevink-dev.en.json @@ -0,0 +1,12 @@ +{ + "urlname": "kevink-dev", + "lang": "en", + "name": "KevinK.dev", + "shortDescription": "This site and the code behind the scenes.", + "longDescription": "For as long as I've been poking around the internet I've always been facinated by the idea to have my own website. This is why I've created this site to showcase myself and my projects. If you are interested in the code behind the scenes feel free to look at it on GitHub!", + "links": { + "website": "https://kevink.dev", + "github": "https://github.com" + }, + "image": "../images/test.jpg" +} \ No newline at end of file diff --git a/gatsby-config.js b/gatsby-config.js index 19a0454..3998ae9 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -6,6 +6,13 @@ module.exports = { }, plugins: [ `gatsby-plugin-sharp`, + `gatsby-transformer-json`, + { + resolve: `gatsby-source-filesystem`, + options: { + path: `./content/`, + }, + }, `gatsby-plugin-sass`, { resolve: `gatsby-plugin-manifest`, @@ -45,7 +52,14 @@ module.exports = { }, keySeparator: false, nsSeparator: false - } + }, + pages: [ + { + matchPath: '/:lang/projects/:urlname', + getLanguageFromPath: true, + excludeLanguages: ['en', 'de'] + } + ] } } ] diff --git a/gatsby-node.js b/gatsby-node.js new file mode 100644 index 0000000..4f79f4a --- /dev/null +++ b/gatsby-node.js @@ -0,0 +1,38 @@ +const path = require(`path`); + +exports.createPages = async ({ actions, graphql, reporter }) => { + const { createPage } = actions + + const projectTemplate = path.resolve(`src/templates/project.js`) + + const result = await graphql(` + query AllPagesQuery { + allProjectsJson { + nodes { + lang + urlname + } + } + } + + `) + + if (result.errors) { + reporter.panicOnBuild(`Error while running GraphQL query.`) + return + } + + result.data.allProjectsJson.nodes.forEach((node) => { + console.log("Creating Page: ", `/${node.lang}/projects/${node.urlname}`); + + createPage({ + path: `/${node.lang}/projects/${node.urlname}`, + component: projectTemplate, + context: { + lang: node.lang, + urlname: node.urlname + } + }) + }); + +} \ No newline at end of file diff --git a/locales/de/translation.json b/locales/de/translation.json index 522819a..d9b1a58 100644 --- a/locales/de/translation.json +++ b/locales/de/translation.json @@ -4,6 +4,7 @@ "datasec": "Datenschutz", "disclaimer": "Disclaimer", "projects": "Projekte", + "project": "Projekt", "social": "Soziales", "homeHello": "Hallo, ich bin", "homeMe": "Ich bin", @@ -15,5 +16,10 @@ "donationCatchphrase": "Gefällt dir was du siehst? Spende doch etwas.", "homeImageCredit": "Portrait aufgenommen von Jannik Kiel", "de": "Deutsch", - "en": "Englisch" + "en": "Englisch", + "projectAboutHeader": "Über {{projectName}}", + "projectViewGitHub": "Auf GitHub anschauen", + "projectViewWebsite": "Projekt-Website anschauen", + "projectsDescription": "Das ist woran ich grade arbeite oder woran ich gearbeitet habe.", + "projectView": "Anschauen" } \ No newline at end of file diff --git a/locales/en/translation.json b/locales/en/translation.json index 35f3c84..c6db5b4 100644 --- a/locales/en/translation.json +++ b/locales/en/translation.json @@ -4,6 +4,7 @@ "datasec": "Data Protection", "disclaimer": "Disclaimer", "projects": "Projects", + "project": "Project", "social": "Social", "homeHello": "Hello, I am", "homeMe": "I am", @@ -15,5 +16,10 @@ "donationCatchphrase": "Like what you're seeing? Consider donating.", "homeImageCredit": "Portrait taken by Jannik Kiel", "de": "German", - "en": "English" + "en": "English", + "projectAboutHeader": "About {{projectName}}", + "projectViewGitHub": "View on GitHub", + "projectViewWebsite": "View Project-Website", + "projectsDescription": "This is what I am working on or have worked on.", + "projectView": "View" } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 02d8b90..c738044 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2137,6 +2137,11 @@ "defer-to-connect": "^1.0.1" } }, + "@tokenizer/token": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.1.1.tgz", + "integrity": "sha512-XO6INPbZCxdprl+9qa/AAbFFOMzzwqYxpjPgLICrMD6C2FCw6qfJOPcBk6JqqPLSaZ/Qx87qn4rpPmPMwaAK6w==" + }, "@turist/fetch": { "version": "7.1.7", "resolved": "https://registry.npmjs.org/@turist/fetch/-/fetch-7.1.7.tgz", @@ -2345,6 +2350,15 @@ "csstype": "^3.0.2" } }, + "@types/readable-stream": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.9.tgz", + "integrity": "sha512-sqsgQqFT7HmQz/V5jH1O0fvQQnXAJO46Gg9LRO/JPfjmVmGUlcx831TZZO3Y3HtWhIkzf3kTsNT0Z0kzIhIvZw==", + "requires": { + "@types/node": "*", + "safe-buffer": "*" + } + }, "@types/responselike": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", @@ -8832,6 +8846,65 @@ } } }, + "gatsby-source-filesystem": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/gatsby-source-filesystem/-/gatsby-source-filesystem-2.8.0.tgz", + "integrity": "sha512-wZXwL/B+PvgSAi4Fkrw33yBk6FdDoz6g2mRfS6NxVVQotbA2oNe+jFc+IL0j9/cUMTItP3rW+8V8U9ufASQfAw==", + "requires": { + "@babel/runtime": "^7.12.5", + "better-queue": "^3.8.10", + "chokidar": "^3.4.3", + "file-type": "^16.0.0", + "fs-extra": "^8.1.0", + "gatsby-core-utils": "^1.7.0", + "got": "^9.6.0", + "md5-file": "^5.0.0", + "mime": "^2.4.6", + "pretty-bytes": "^5.4.1", + "progress": "^2.0.3", + "valid-url": "^1.0.9", + "xstate": "^4.14.0" + }, + "dependencies": { + "file-type": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.1.0.tgz", + "integrity": "sha512-G4Klqf6tuprtG0pC4r9kni4Wv8XhAAsfHphVqsQGA+YiOlPAO40BZduDqKfv0RFsu9q9ZbFObWfwszY/NqhEZw==", + "requires": { + "readable-web-to-node-stream": "^3.0.0", + "strtok3": "^6.0.3", + "token-types": "^2.0.0", + "typedarray-to-buffer": "^3.1.5" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + } + } + }, "gatsby-telemetry": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/gatsby-telemetry/-/gatsby-telemetry-1.7.0.tgz", @@ -8853,6 +8926,15 @@ "uuid": "3.4.0" } }, + "gatsby-transformer-json": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/gatsby-transformer-json/-/gatsby-transformer-json-2.8.0.tgz", + "integrity": "sha512-fKexGFE5omoubberI2LkM9nI73F0TZuVdZsywkyaeTZgv71SftHjiq3xHh4e8PuKjhvR+MIPPsn1owmVb+UMCw==", + "requires": { + "@babel/runtime": "^7.12.5", + "bluebird": "^3.7.2" + } + }, "gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", @@ -13165,6 +13247,11 @@ "sha.js": "^2.4.8" } }, + "peek-readable": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-3.1.0.tgz", + "integrity": "sha512-KGuODSTV6hcgdZvDrIDBUkN0utcAVj1LL7FfGbM0viKTtCHmtZcuEJ+lGqsp0fTFkGqesdtemV2yUSMeyy3ddA==" + }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -14787,6 +14874,27 @@ "util-deprecate": "~1.0.1" } }, + "readable-web-to-node-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.0.tgz", + "integrity": "sha512-HNmLb3n0SteGAs8HQlErYPGeO+y7cvL/mVUKtXeUkl0iCZ/2GIgKGrCFHyS7UXFnO8uc9U+0y3pYIzAPsjFfvA==", + "requires": { + "@types/readable-stream": "^2.3.9", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "readdirp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", @@ -16861,6 +16969,23 @@ "escape-string-regexp": "^1.0.2" } }, + "strtok3": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.0.4.tgz", + "integrity": "sha512-rqWMKwsbN9APU47bQTMEYTPcwdpKDtmf1jVhHzNW2cL1WqAxaM9iBb9t5P2fj+RV2YsErUWgQzHD5JwV0uCTEQ==", + "requires": { + "@tokenizer/token": "^0.1.1", + "@types/debug": "^4.1.5", + "peek-readable": "^3.1.0" + }, + "dependencies": { + "@types/debug": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz", + "integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==" + } + } + }, "style-loader": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", @@ -17356,6 +17481,15 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" }, + "token-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-2.0.0.tgz", + "integrity": "sha512-WWvu8sGK8/ZmGusekZJJ5NM6rRVTTDO7/bahz4NGiSDb/XsmdYBn6a1N/bymUHuWYTWeuLUg98wUzvE4jPdCZw==", + "requires": { + "@tokenizer/token": "^0.1.0", + "ieee754": "^1.1.13" + } + }, "tough-cookie": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", diff --git a/package.json b/package.json index 6a5260a..ccb929f 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,8 @@ "gatsby-plugin-sass": "^2.8.0", "gatsby-plugin-sharp": "^2.11.1", "gatsby-plugin-sitemap": "^2.9.0", + "gatsby-source-filesystem": "^2.8.0", + "gatsby-transformer-json": "^2.8.0", "i18next": "^19.8.4", "jquery": "^3.5.1", "node-sass": "^4.14.1", diff --git a/src/pages/projects.js b/src/pages/projects.js index d6367a9..ba104a1 100644 --- a/src/pages/projects.js +++ b/src/pages/projects.js @@ -2,16 +2,55 @@ import React from "react" import Layout from "../layouts/default"; import { Trans, Link, useI18next } from "gatsby-plugin-react-i18next" -export default function ProjectsPage() { +import styles from "./projects.module.scss"; + +export const query = graphql` +query GetProjects($language: String!) { + allProjectsJson(filter: {lang: {eq: $language}}) { + nodes { + lang + urlname + name + image { + publicURL + } + shortDescription + } + } +} +` + +export default function ProjectsPage({data}) { const {t} = useI18next(); return ( - +
-
+

projects

-
+

projectsDescription

+ +
+ {data.allProjectsJson.nodes.map((project) => { + return ( +
+ {/*
Live
*/} +
+
+ {project.name} + {project.shortDescription} +
+
+
projectView
+
+
+ ); + })} +
+ + {/*
{JSON.stringify(data, null, 2)}
*/} +
); diff --git a/src/pages/projects.module.scss b/src/pages/projects.module.scss new file mode 100644 index 0000000..83b690e --- /dev/null +++ b/src/pages/projects.module.scss @@ -0,0 +1,127 @@ +@import "../variables"; + +.projectList { + display: flex; + flex-direction: row; + justify-content: center; + flex-wrap: wrap; + margin: 15px 0; +} + +.projectCard { + background: $background; + border-radius: 4px; + overflow: hidden; + margin: 15px; + color: var(--text-color); + display: flex; + flex-direction: column; + flex-grow: 1; + width: calc(100% / 4); + box-shadow: -1px 11px 33px -10px rgba(127,127,127,0.3); + max-width: 300px; + transition: transform .25s, box-shadow .25s; +} + +.projectCard:hover { + transform: scale(1.05); + box-shadow: -1px 11px 33px -10px rgba(127,127,127,0.4); +} + +@media(max-width: 800px) { + .projectCard { + width: calc((100% / 2) - 30px); + } +} + +@media(max-width: 500px) { + .projectCard { + width: 100%; + } +} + +.projectCardActivityIndicator { + position: absolute; + margin: 12px; + padding: 2px 5px; + border-radius: 3px; +} + +.activityIndicatorGreen { + background: #26de81; +} + +.activityIndicatorYellow { + background: #f7b731; +} + +.activityIndicatorRed { + background: #fc5c65; +} + +.activityIndicatorBlue { + background: #45aaf2; +} + +.projectCardImage { + display: block; + height: 150px; + background-position: center; + background-size: cover; +} + +.projectCardMeta { + padding: 10px; + flex-grow: 1; +} + +.projectCardTitle { + display: block; + font-size: 1.2em; +} + +.projectCardCTA { + display: block; +} + +.projectCardCTA a { + display: block; + padding: 10px; + text-align: center; + background: var(--accent-color); + color: white; + text-decoration: none; +} + +.projectCardCTAContainer { + display: flex; +} + +@media(max-width: 900px) { + .projectCardCTAContainer { + flex-direction: column; + } + + .projectCardCTA:nth-child(2) { + border-left: none; + } + + +} + +.projectCardCTAContainer > * { + flex-grow: 1; +} + +.projectCardCTA { + display: block; +} + +.projectCardCTA a { + display: block; + padding: 10px; + text-align: center; + background: $accentColor; + color: white; + text-decoration: none; +} \ No newline at end of file diff --git a/src/templates/project.js b/src/templates/project.js new file mode 100644 index 0000000..c011cac --- /dev/null +++ b/src/templates/project.js @@ -0,0 +1,75 @@ +import React from "react" +import {graphql} from "gatsby" +import {Link, Trans, useTranslation} from 'gatsby-plugin-react-i18next'; +import Layout from "../layouts/default"; + +import styles from "./project.module.scss"; + +export const query = graphql` +query GetProject($urlname: String!, $lang: String!) { + allProjectsJson(filter: {urlname: {eq: $urlname}, lang: {eq: $lang}}) { + nodes { + lang + urlname + name + links { + github + website + } + image { + publicURL + } + longDescription + shortDescription + } + } +} +` + +export default function ProjectTemplate({data}) { + let project = data.allProjectsJson.nodes[0]; + let projectName = project.name; + + return ( + +
+
+
+
+
+

project: {projectName}

+ {project.shortDescription} +
+
+
+
+
+ {project.longDescription != null ? +
+
+

projectAboutHeader{{projectName}}

+

{project.longDescription}

+
+
+ : null} + {project.links.github !== null || project.links.website !== null ? +
+
+

Links

+
+ {project.links.github !== null ? projectViewGitHub : null} + {project.links.website !== null ? projectViewWebsite : null} + +
+
+
+ : null} + {/*
+
+ +
{JSON.stringify(data, null, 2)}
+
+
*/} +
+ ); +} \ No newline at end of file diff --git a/src/templates/project.module.scss b/src/templates/project.module.scss new file mode 100644 index 0000000..8aaddfe --- /dev/null +++ b/src/templates/project.module.scss @@ -0,0 +1,74 @@ +@import "../variables"; + +.projectHeader .headerBackground { + position: absolute; + left: 0; + width: 100%; + height: 200px; + background-position: center; + background-size: cover; +} + +.projectHeader header { + position: absolute; + left: 0; + width: 100%; + height: 200px; + background: rgba(0, 0, 0, .5); +} + +.projectHeader .headerInner { + max-width: $layoutWidth; + width: 100%; + margin: 0 auto; + padding: 65px 20px 0; +} + +.projectHeader .headerInner * { + margin: 0; + color: white; +} + +.headerPlaceholder { + width: 100%; + height: 225px; +} + +.projectHeader .headerPlaceholder { + width: 100%; + height: 200px; +} + +.projectHeader h1 { + font-size: 2em; +} + +.projectHeader > div { + padding-bottom: 0 !important; +} + +.projectAbout { + background: #060606; + color: white; +} + +.projectLinks .linkList { + display: flex; + justify-content: center; + flex-wrap: wrap; +} + +.projectLinks a { + display: inline-block; + border: thin solid rgb(200, 200, 200); + border-radius: 5px; + padding: 10px 15px; + margin: 5px; + color: $textColor; + text-decoration-skip: none; + text-decoration: underline dotted currentColor; +} + +.projectLinks a i.fab, .projectLinks a i.fas, .projectLinks a i.fa, .projectLinks a i.far, .projectLinks a i.fal { + display: inline; +} \ No newline at end of file