Skip to content

Commit

Permalink
Merge pull request #421 from JonathanBout/master
Browse files Browse the repository at this point in the history
Release
  • Loading branch information
JonathanBout authored Feb 4, 2025
2 parents d909009 + 159e4ec commit 9fd7bfc
Show file tree
Hide file tree
Showing 15 changed files with 515 additions and 1,488 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ name: Build
on:
pull_request:
branches: [ "master", "release" ]
push:
branches: [ "master" ]
workflow_dispatch:
workflow_call:

Expand Down
9 changes: 8 additions & 1 deletion compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,12 @@ services:
- ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_URLS=http://+:5000
- CORS_ALLOWED_ORIGINS=http://localhost:50000,http://localhost:50001
- ConnectionStrings__Postgres=Host=db;Port=5432;Database=portfolio;Username=postgres;Password=postgres
ports:
- 32769:5000
- 3998:5000
db:
image: postgres
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=portfolio
3 changes: 3 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
<link rel="alternate" href="https://jonathanbout.com" hreflang="en" />
<link rel="alternate" href="https://jonathanbout.com" hreflang="x-default" />
<link rel="alternate" href="https://jonathanbout.nl" hreflang="nl" />

<link rel="preconnect" href="https://gstatic.com" />

<!-- disallow translating the page -->
<meta name="google" content="notranslate" />

Expand Down
1,766 changes: 367 additions & 1,399 deletions package-lock.json

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,35 @@
"compose-up": "docker compose up --build"
},
"dependencies": {
"@typescript-eslint/parser": "^8.19.1",
"@typescript-eslint/parser": "^8.21.0",
"axios": "^1.7.9",
"bootstrap-icons": "^1.11.3",
"eslint-plugin-vue": "^9.32.0",
"npm-run-all": "^4.1.5",
"parse-css-color": "^0.2.1",
"read-last-lines": "^1.8.0",
"typescript-eslint": "^8.19.1",
"typescript-eslint": "^8.22.0",
"vue": "^3.5.13",
"vue-eslint-parser": "^9.4.3",
"vue-i18n": "^11.0.1",
"vue-i18n": "^11.1.0",
"vue-router": "^4.4.5"
},
"devDependencies": {
"@babel/types": "^7.26.5",
"@babel/types": "^7.26.7",
"@tsconfig/node18": "^18.2.4",
"@types/node": "^22.10.5",
"@types/node": "^22.13.0",
"@vitejs/plugin-vue": "^5.2.0",
"@vue/tsconfig": "^0.7.0",
"autoprefixer": "^10.4.20",
"eslint-config-prettier": "^9.1.0",
"less": "^4.2.0",
"eslint-config-prettier": "^10.0.1",
"less": "^4.2.2",
"less-loader": "^12.2.0",
"prettier": "^3.4.2",
"typescript": "~5.7.3",
"vite": "^6.0.7",
"vite": "^6.0.11",
"vite-plugin-mkcert": "^1.17.6",
"vite-plugin-vue-devtools": "^7.7.0",
"vitest": "^2.1.8",
"vite-plugin-vue-devtools": "^7.7.1",
"vitest": "^3.0.5",
"vue-tsc": "^2.2.0"
}
}
8 changes: 6 additions & 2 deletions plugins/gitrev.plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@ export default function gitrevPlugin(): Plugin {
return {
name: "gitrev",
resolveId(id) {
// This is a virtual module, so we need to resolve it to a unique ID.
// We use a null byte prefix to avoid conflicts with real modules.
if (id == moduleId) return resolvedModuleId
},
async load(id) {
if (id == resolvedModuleId) {
const lastLog = await lastLines.read(".git/logs/HEAD", 1)
const currentHash = lastLog.split(" ")[1]
return `export const rev = "${currentHash}"`
// if any error occurs, we don't know the git revision hash which means the project is untracked.
if (!lastLog) return `export const rev = "untracked"`
const currentHash = lastLog.split(" ")[1] // The current git revision hash is the second word in the last line of the log.
return `export const rev = "${currentHash || "untracked"}"`
}
}
}
Expand Down
47 changes: 18 additions & 29 deletions src/components/ProjectComponent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import TagComponent from "@/components/TagComponent.vue"
import ProjectImageComponent from "@/components/ProjectImageComponent.vue"
import { useI18n } from "vue-i18n"
import { formatDate } from "@/localizer/dates"
import type { Locale } from "@/localizer"
import { localize, currentLocale } from "@/localizer"
const props = defineProps<{
project: Project
}>()
const { t, locale: lang } = useI18n()
const { t } = useI18n()
const timeframeText = computed(() => {
const { start, end } = props.project.timeframe ?? {}
Expand All @@ -22,13 +22,11 @@ const timeframeText = computed(() => {
includeYear = start.getFullYear() != end.getFullYear()
}
const startString = formatDate(start, lang.value as Locale, false, false, true, includeYear)
const startString = formatDate(start, currentLocale.value, false, false, true, includeYear)
const endString =
end == "present"
end == "present" || end == "maintenance"
? t("projects.present")
: end == "maintenance"
? t("projects.maintenance") + "*"
: formatDate(end, lang.value as Locale, false, false, true, true)
: formatDate(end, currentLocale.value, false, false, true, true)
if (start && end && end != "present") {
return startString + " - " + endString
Expand All @@ -41,12 +39,14 @@ const timeframeText = computed(() => {
return ""
})
const isMaintenance = computed(() => props.project.timeframe?.end == "maintenance")
const projectName = computed(() => {
if (typeof props.project.name === "string") {
return props.project.name
}
return (props.project.name as unknown as { [K: string]: string })[lang.value]
return localize(props.project.name)
})
</script>

Expand All @@ -64,31 +64,17 @@ const projectName = computed(() => {
{{ projectName }}
</div>
<div v-if="project.description" class="description">
{{ (project.description as any)[lang] }}
{{ localize(project.description) }}
</div>
<ul class="links">
<li v-if="project.github">
<a
:href="project.github"
:aria-label="$t('projects.view-on-gh', { name: projectName })"
target="_blank"
class="bi bi-github big no-external-icon"
/>
</li>
<li v-if="project.demo">
<a
:href="project.demo"
:aria-label="$t('projects.view-demo', { name: projectName })"
target="_blank"
class="bi bi-box-arrow-up-right big no-external-icon"
/>
</li>
<li v-if="project.playStore">
<li v-for="iconLink in [...(project.iconLinks ?? [])].sort((a, b) => a.bootstrapIcon.localeCompare(b.bootstrapIcon))" :key="iconLink.bootstrapIcon">
<a
:href="project.playStore"
:aria-label="$t('projects.view-on-play-store', { name: projectName })"
:title="$t(iconLink.ariaLabel, { name: projectName })"
:href="iconLink.url"
:aria-label="$t(iconLink.ariaLabel, { name: projectName })"
target="_blank"
class="bi bi-google-play big no-external-icon"
class="bi"
:class="'bi bi-' + iconLink.bootstrapIcon + ' big no-external-icon'"
/>
</li>
<li v-for="tag in project.tags" :key="tag" class="tag">
Expand All @@ -97,6 +83,9 @@ const projectName = computed(() => {
</ul>
<div v-if="project.timeframe" class="timeframe">
{{ timeframeText }}
<template v-if="isMaintenance">
(<abbr :title="$t('projects.maintenance-note')"> {{ $t("projects.maintenance") }} </abbr>)
</template>
</div>
</div>
</component>
Expand Down
16 changes: 9 additions & 7 deletions src/components/ProjectImageComponent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ defineProps<{
class="image-wrapper"
:style="'--image-count: ' + (project.image ? 1 : project.images ? project.images.length : 0).toString()"
>
<img v-if="project.image" class="image" :src="project.image" alt="Project preview" />
<img v-for="image in project.images" v-else :key="image" class="image" :src="image" alt="Project preview" />
</div>
<img v-if="project.image" class="image" :src="project.image" alt="Project preview" />
<img v-for="image in project.images" v-else-if="project.images" :key="image" class="image" :src="image" alt="Project preview" />
</div>
</template>

<style lang="less" scoped>
Expand All @@ -31,14 +31,16 @@ defineProps<{
flex-direction: row;
overflow: hidden;
width: fit-content;
align-items: center;
align-items: start;
justify-content: start;
& > img {
animation: step infinite steps(calc(var(--image-count)));
animation-duration: calc(var(--image-count) * 4s);
animation: step infinite steps(var(--image-count));
animation-duration: calc(var(--image-count) * 1s);
/* slow down the animation if the user prefers reduced motion */
@media (prefers-reduced-motion: reduce) {
animation-duration: 6s;
animation-duration: calc(var(--image-count) * 6s);
}
}
Expand Down
15 changes: 10 additions & 5 deletions src/localizer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import localizedStrings from "./locales"

import { createI18n } from "vue-i18n"

import { type Plugin as VuePlugin, type App as VueApp } from "vue"
import { type Plugin as VuePlugin, type App as VueApp, type WritableComputedRef } from "vue"

export const LOCALES = ["nl", "en"] as const

Expand All @@ -16,6 +16,10 @@ export type Locale = (typeof LOCALES)[number]
*/
export type Localized<V = unknown> = { [K in Locale]: V }

export function localize<T>(localized: Localized<T>): T {
return localized[currentLocale.value]
}

/**
* A list of the domains for each locale the app supports.
* @warn Do not use this in href attributes, as it won't work during development. For redirects, use the `changeLanguage` function.
Expand All @@ -25,12 +29,12 @@ export const domainsByLocale: Localized<`https://${string}`> = {
nl: "https://jonathanbout.nl"
}

const localizerPlugin = {
const localizerPlugin : VuePlugin = {
install(app: VueApp) {
app.provide("locale", currentLocale)
app.use(i18n)
}
} as VuePlugin
}

/**
* Change the language of the site by setting the locale in local storage and reloading the page. This may also redirect to the other domain if the locale is changed.
Expand Down Expand Up @@ -71,7 +75,7 @@ export function createLocalizer(): VuePlugin {
* 3. If the locale is set in local storage, use that
* 4. If the browser language is set to Dutch, use the Dutch locale
* 5. If the browser language is set to English, use the English locale
* 6. If none of the above, use the locale for the current domain (.com is English, .nl is Dutch)
* 6. If none of the above, use the locale for the current domain (English for .com, Dutch for .nl)
*/

let locale: Locale = window.app.locale
Expand Down Expand Up @@ -141,8 +145,9 @@ export const i18n = createI18n({
fallbackLocale: ["common", "en"],
messages: localizedStrings,
legacy: false,
// only warn in development mode
fallbackWarn: import.meta.env.DEV,
missingWarn: import.meta.env.DEV
})

export const currentLocale = i18n.global.locale
export const currentLocale = i18n.global.locale as WritableComputedRef<Locale>
7 changes: 4 additions & 3 deletions src/localizer/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
"see-more": "See more on my GitHub!",
"view-on-gh": "View project '{name}' on GitHub",
"view-demo": "View a live demo of project '{name}'",
"view-on-play-store": "View the app on the Google Play Store",
"view-on-playstore": "View the '{name}' app on the Google Play Store",
"view-on-nuget": "View the '{name}' package on NuGet",
"github-stats": {
"text": "GitHub Statistics",
"error": "Something went wrong.",
Expand All @@ -55,8 +56,8 @@
"description": "The languages I use most in my projects, in bytes. All this data comes directly from GitHub."
}
},
"maintenance": "present, maintenance",
"maintenance-note": "Maintenance phase: this project is no longer actively developed, but I still keep it up to date with the latest dependency versions and security updates."
"maintenance": "maintenance",
"maintenance-note": "This project is no longer actively developed, but I still keep it up to date with the latest dependency versions and security updates."
},
"version": "version",
"pathName": {
Expand Down
7 changes: 4 additions & 3 deletions src/localizer/locales/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
"see-more": "Bekijk meer van mijn projecten op GitHub!",
"view-on-gh": "Bekijk het project '{name}' op GitHub",
"view-demo": "Bekijk de live demo van project '{name}'",
"view-on-play-store": "Bekijk de app op de Google Play Store",
"view-on-playstore": "Bekijk '{name}' op de Google Play Store",
"view-on-nuget": "Bekijk het '{name}' pakket op NuGet",
"github-stats": {
"text": "GitHub Statistieken",
"error": "Er ging wat mis.",
Expand All @@ -55,8 +56,8 @@
"description": "De talen die ik het meest gebruikt heb in projecten, in bytes. Alle data komt direct van GitHub."
}
},
"maintenance": "nu, onderhoud",
"maintenance-note": "Onderhoudsfase: dit project wordt niet meer actief ontwikkeld, maar ik houd het nog steeds up-to-date met de nieuwste dependencyversies en beveiligingsupdates."
"maintenance": "onderhoud",
"maintenance-note": "Dit project wordt niet meer actief ontwikkeld, maar ik houd het nog steeds up-to-date met de nieuwste dependencyversies en beveiligingsupdates."
},
"version": "versie",
"pathName": {
Expand Down
Loading

0 comments on commit 9fd7bfc

Please sign in to comment.