Extended project page a little bit
All checks were successful
Build & Push Frontend A / docker (push) Successful in 42s

This commit is contained in:
2026-01-01 12:57:23 +01:00
parent 9771d7a38d
commit 93b2a0fed7
14 changed files with 235 additions and 50 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -9,13 +9,54 @@
</mat-panel-description>
</mat-expansion-panel-header>
<p>{{ project.introduction | translate }}</p>
@if (project.link)
{
<div class="link-row">
<a class="link-with-icon"
href="{{project.link}}"
target="_blank"
rel="noopener noreferrer">
<mat-icon>open_in_new</mat-icon>
{{project.link}}
</a>
</div>
}
@if(project.assets)
{
<div class="link-row">
<a class="link-with-icon"
href="{{project.assets}}"
rel="noopener noreferrer">
<mat-icon>download</mat-icon>
{{ 'PROJECTS.DOWNLOAD' | translate}}
</a>
</div>
}
@if (project.images.length > 0)
{
<div class="gallery">
<swiper-container
class="my-swiper"
[attr.slides-per-view]="1.2"
[attr.space-between]="12"
[attr.navigation]="true"
[attr.pagination]="true"
[attr.keyboard]="true"
style="width: 100%;"
>
@for (img of project.images; track img) {
<img class="gallery-img" [src]="img" [alt]="project.title | translate" />
<swiper-slide>
<img
class="slide-img"
[src]="img"
[alt]="project.title | translate"
(click)="openImage(project.title, img)"
/>
</swiper-slide>
}
</div>
</swiper-container>
}
</mat-expansion-panel>
}

View File

@@ -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;
}

View File

@@ -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<string | null>(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,
});
}
}