diff --git a/angular.json b/angular.json index c0d44b9..c39ce7d 100644 --- a/angular.json +++ b/angular.json @@ -37,7 +37,8 @@ } ], "styles": [ - "src/styles.scss" + "src/styles.scss", + "node_modules/swiper/swiper-bundle.css" ] }, "configurations": { diff --git a/package-lock.json b/package-lock.json index d0b051d..e8e69be 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "@tsparticles/angular": "~3.0.0", "@tsparticles/engine": "~3.9.1", "rxjs": "^7.8.0", + "swiper": "~12.0.3", "tslib": "^2.3.0", "tsparticles": "~3.9.1" }, @@ -11987,6 +11988,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/swiper": { + "version": "12.0.3", + "resolved": "https://registry.npmjs.org/swiper/-/swiper-12.0.3.tgz", + "integrity": "sha512-BHd6U1VPEIksrXlyXjMmRWO0onmdNPaTAFduzqR3pgjvi7KfmUCAm/0cj49u2D7B0zNjMw02TSeXfinC1hDCXg==", + "funding": [ + { + "type": "patreon", + "url": "https://www.patreon.com/swiperjs" + }, + { + "type": "open_collective", + "url": "http://opencollective.com/swiper" + } + ], + "license": "MIT", + "engines": { + "node": ">= 4.7.0" + } + }, "node_modules/tapable": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", diff --git a/package.json b/package.json index c816163..e466861 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "@tsparticles/angular": "~3.0.0", "@tsparticles/engine": "~3.9.1", "rxjs": "^7.8.0", + "swiper": "~12.0.3", "tslib": "^2.3.0", "tsparticles": "~3.9.1" }, diff --git a/src/app/constants/AssetsConstants.ts b/src/app/constants/AssetsConstants.ts index adaebc7..7d84ed8 100644 --- a/src/app/constants/AssetsConstants.ts +++ b/src/app/constants/AssetsConstants.ts @@ -12,7 +12,7 @@ static readonly COLORDIGITAL_LOGO = '/assets/logos/dmixcloud_logo.jpg'; static readonly TERAPORT_LOGO = '/assets/logos/teraport_gmbh_logo.jpg'; - static readonly CV: 'assets/cv/andreas-dahm-cv.pdf'; + static readonly DIPLOMA= 'assets/projects/diploma/Dahm2010-Diplomarbeit.pdf'; //project images static readonly EL_MUCHO_1 = '/assets/projects/el-mucho/1.jpg'; diff --git a/src/app/layout/imageDialog/image.component.ts b/src/app/layout/imageDialog/image.component.ts new file mode 100644 index 0000000..53e51d9 --- /dev/null +++ b/src/app/layout/imageDialog/image.component.ts @@ -0,0 +1,69 @@ +import { Component, Inject } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog'; +import { MatButtonModule } from '@angular/material/button'; +import { MatIconModule } from '@angular/material/icon'; + +@Component({ + standalone: true, + imports: [MatDialogModule, MatButtonModule, MatIconModule], + template: ` +
+
+
{{ data.title }}
+ +
+ +
+ +
+
+ `, + styles: [` + .dialog { + display: flex; + flex-direction: column; + height: 100%; + } + + .topbar { + flex: 0 0 auto; + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + + padding: 14px 16px; + } + + .title { + font-weight: 600; + line-height: 1.2; + max-width: calc(100% - 56px); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .stage { + flex: 1 1 auto; + padding: 0 16px 16px; + min-height: 0; + display: grid; + place-items: center; + } + + .full { + width: 100%; + height: 100%; + object-fit: contain; + border-radius: 12px; + } + `], +}) +export class ImageDialogComponent { + constructor(@Inject(MAT_DIALOG_DATA) public data: { title: string; src: string }) { + console.log(data.title); + } +} diff --git a/src/app/pages/about/about.component.scss b/src/app/pages/about/about.component.scss index a563749..3957ca7 100644 --- a/src/app/pages/about/about.component.scss +++ b/src/app/pages/about/about.component.scss @@ -169,27 +169,6 @@ opacity: .85; } -.link-row { - grid-row: 2; - grid-column: 2; - margin-top: .1rem; - opacity: .85; - vertical-align: center; -} - -.link-with-icon { - display: inline-flex; - align-items: center; - gap: .35rem; - line-height: 1; -} - -.link-with-icon mat-icon { - font-size: 18px; - height: 18px; - width: 18px; -} - .highlights { margin-top: .4rem; margin-left: .75rem; diff --git a/src/app/pages/about/about.component.ts b/src/app/pages/about/about.component.ts index 58b0b6f..08185d2 100644 --- a/src/app/pages/about/about.component.ts +++ b/src/app/pages/about/about.component.ts @@ -29,7 +29,6 @@ import {SharedFunctions} from '../../shared/SharedFunctions'; styleUrl: './about.component.scss' }) export class AboutComponent { - cvHref = AssetsConstants.CV; xpKeys = [ { @@ -143,13 +142,6 @@ export class AboutComponent { 'ABOUT.TOOLS.GRAFANA', ]; - openMail(event: Event) { - event.preventDefault(); - const user = 'andreas.dahm'; - const domain = 'gmail.com'; - globalThis.location.href = `mailto:${user}@${domain}`; - } - protected readonly UrlConstants = UrlConstants; protected readonly AssetsConstants = AssetsConstants; protected readonly SharedFunctions = SharedFunctions; diff --git a/src/app/pages/projects/projects.component.html b/src/app/pages/projects/projects.component.html index b97aaeb..ed1bacd 100644 --- a/src/app/pages/projects/projects.component.html +++ b/src/app/pages/projects/projects.component.html @@ -9,13 +9,54 @@

{{ project.introduction | translate }}

+ + @if (project.link) + { + + } + + @if(project.assets) + { + + } + @if (project.images.length > 0) { - + } } diff --git a/src/app/pages/projects/projects.component.scss b/src/app/pages/projects/projects.component.scss index 325d60d..5f2be76 100644 --- a/src/app/pages/projects/projects.component.scss +++ b/src/app/pages/projects/projects.component.scss @@ -7,15 +7,34 @@ margin-left: 8px; } -.gallery { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(384px, 1fr)); - gap: 12px; -} - -.gallery-img { +.slide-img { width: 100%; height: auto; + max-height: 512px !important; + object-fit: cover; + border-radius: 12px; display: block; - border-radius: 16px; + cursor: pointer; +} + +.my-swiper::part(button-prev), +.my-swiper::part(button-next) { + width: 35px; + height: 35px; + padding: 5px; + border-radius: 999px; + background: rgba(0,0,0,.5); + + display: flex; + align-items: center; + justify-content: center; +} + +.my-swiper::part(button-prev):hover, +.my-swiper::part(button-next):hover { + background: rgba(0,0,0,.75); +} + +.my-swiper::part(pagination) { + bottom: 12px; } diff --git a/src/app/pages/projects/projects.component.ts b/src/app/pages/projects/projects.component.ts index a5ae98c..a591fdc 100644 --- a/src/app/pages/projects/projects.component.ts +++ b/src/app/pages/projects/projects.component.ts @@ -1,9 +1,12 @@ -import {Component, inject, signal} from '@angular/core'; +import {Component, inject, signal, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import {MatAccordion, MatExpansionPanel, MatExpansionPanelDescription, MatExpansionPanelHeader, MatExpansionPanelTitle} from '@angular/material/expansion'; import {MatIcon} from '@angular/material/icon'; -import {TranslatePipe} from '@ngx-translate/core'; +import {TranslatePipe, TranslateService} from '@ngx-translate/core'; import {ActivatedRoute} from '@angular/router'; import {AssetsConstants} from '../../constants/AssetsConstants'; +import {MatDialog} from '@angular/material/dialog'; +import {ImageDialogComponent} from '../../layout/imageDialog/image.component'; + export interface Projects { identifier: string; @@ -12,7 +15,7 @@ export interface Projects { introduction: string, images: string[], icon: string, - assets: string[], + assets: string, link: string, bulletPoints: string[], } @@ -26,14 +29,18 @@ export interface Projects { MatExpansionPanelTitle, MatExpansionPanelDescription, MatIcon, - TranslatePipe, + TranslatePipe ], templateUrl: './projects.component.html', styleUrl: './projects.component.scss', + schemas: [CUSTOM_ELEMENTS_SCHEMA], }) export class ProjectsComponent { private readonly route = inject(ActivatedRoute); + private readonly dialog = inject(MatDialog); + private readonly translateService = inject(TranslateService); + selectedKey = signal(null); allProjects: Projects[] = [ @@ -44,7 +51,7 @@ export class ProjectsComponent { introduction: 'PROJECTS.PLAYGROUND.INTRODUCTION', images: [], icon: 'web', - assets: [], + assets: '', link: 'https://andreas-dahm.eu', bulletPoints: [] }, @@ -55,7 +62,7 @@ export class ProjectsComponent { introduction: 'PROJECTS.EL_MUCHO.INTRODUCTION', images: [AssetsConstants.EL_MUCHO_1, AssetsConstants.EL_MUCHO_2, AssetsConstants.EL_MUCHO_3, AssetsConstants.EL_MUCHO_4], icon: 'sports_esports', - assets: [], + assets: '', link: 'https://store.steampowered.com/app/1532640/El_Mucho/', bulletPoints: [] }, @@ -66,7 +73,7 @@ export class ProjectsComponent { introduction: 'PROJECTS.GAME_JAMS.INTRODUCTION', images: [AssetsConstants.GAME_JAMS_1, AssetsConstants.GAME_JAMS_2, AssetsConstants.GAME_JAMS_3], icon: 'videogame_asset', - assets: [], + assets: '', link: 'https://itch.io/c/6628860/lobos-collection', bulletPoints: [] }, @@ -77,7 +84,7 @@ export class ProjectsComponent { introduction: 'PROJECTS.DIPLOMA.INTRODUCTION', images: [AssetsConstants.DIPLOMA_1, AssetsConstants.DIPLOMA_2, AssetsConstants.DIPLOMA_3, AssetsConstants.DIPLOMA_4, AssetsConstants.DIPLOMA_5, AssetsConstants.DIPLOMA_6], icon: 'history_edu', - assets: [], + assets: AssetsConstants.DIPLOMA, link: 'https://www.th-bingen.de', bulletPoints: [] } @@ -92,4 +99,18 @@ export class ProjectsComponent { isExpanded(projectKey: string): boolean { return this.selectedKey() === projectKey; } + + openImage(title: string, src: string) { + const translatedTitle = this.translateService.instant(title); + this.dialog.open(ImageDialogComponent, { + data: { title: translatedTitle, src }, + width: '96vw', + height: '96vh', + maxWidth: '96vw', + maxHeight: '96vh', + panelClass: 'image-dialog-panel', + autoFocus: false, + restoreFocus: true, + }); + } } diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index fd23a87..35ef058 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -227,6 +227,7 @@ } }, "PROJECTS": { + "DOWNLOAD": "Herunterladen", "PLAYGROUND": { "TITLE": "Playground Website", "SHORT_DESCRIPTION": "Hier geht es um diese Webseite.", diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index e3659db..ba1757a 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -227,6 +227,7 @@ } }, "PROJECTS": { + "DOWNLOAD": "Download", "PLAYGROUND": { "TITLE": "Playground Website", "SHORT_DESCRIPTION": "This is about this website.", diff --git a/src/main.ts b/src/main.ts index b0ef0a7..f28c38d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,6 +2,9 @@ import { bootstrapApplication } from '@angular/platform-browser'; import { appConfig } from './app/app.config'; import packageJson from '../package.json'; import {AppComponent} from './app/layout/app/app.component'; +import { register } from 'swiper/element/bundle'; +register(); + if (packageJson.version) { console.log(`🌟 Frontend version: ${packageJson.version}`); diff --git a/src/styles.scss b/src/styles.scss index 494e1e8..dc63ed5 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -174,3 +174,40 @@ a { .mat-expansion-panel-body { padding-top: 0; } + +.image-dialog-panel .mat-mdc-dialog-surface { + border-radius: 16px; + overflow: hidden; +} + +.image-dialog-panel .mat-mdc-dialog-content { + padding: 0 !important; + margin: 0 !important; + overflow: hidden !important; + max-height: none !important; +} + +.image-dialog-panel .mat-mdc-dialog-container { + padding: 0; +} + +.link-row { + grid-row: 2; + grid-column: 2; + margin-top: .1rem; + opacity: .85; + vertical-align: center; +} + +.link-with-icon { + display: inline-flex; + align-items: center; + gap: .35rem; + line-height: 1; +} + +.link-with-icon mat-icon { + font-size: 18px; + height: 18px; + width: 18px; +}