Bump deps and refactor layouts/styles
All checks were successful
Build, Test & Push Frontend / quality-check (push) Successful in 1m40s
Build, Test & Push Frontend / docker (push) Successful in 1m8s

Update package-lock with multiple dependency bumps (Angular CLI/DevKit/schematics to 21.1.5, ajv to 8.18.0, minimatch/brace-expansion updates, tar, qs, swiper, hono, etc.). Wrap the generic grid canvas in a container and clean up HTML structure/indentation in algorithms and pathfinding templates (add card-grid wrapper and reformat content). Adjust global styles: refine .algo-container and app-root margins/gaps, and refactor hero/photo/intro styles for responsive layout. Changes are primarily dependency updates and UI/layout refinements.
This commit is contained in:
2026-02-25 08:50:28 +01:00
parent 28bde29c8b
commit f4104d02e8
5 changed files with 251 additions and 217 deletions

View File

@@ -1,5 +1,7 @@
<div class="card-grid">
<h1>{{ 'ALGORITHM.TITLE' |translate }}</h1>
<div class="card-grid">
</div>
<div class="card-grid">
@for (category of categories$ | async; track category.id) {
<mat-card class="algo-card" [routerLink]="[category.routerLink]">
<mat-card-header>

View File

@@ -1,80 +1,80 @@
<mat-card class="algo-container">
<mat-card-header>
<mat-card-title>{{ 'PATHFINDING.TITLE' | translate }}</mat-card-title>
</mat-card-header>
<mat-card-content>
<app-information [algorithmInformation]="algoInformation"/>
<mat-card class="algo-container">
<mat-card-header>
<mat-card-title>{{ 'PATHFINDING.TITLE' | translate }}</mat-card-title>
</mat-card-header>
<mat-card-content>
<app-information [algorithmInformation]="algoInformation"/>
<div class="controls-container">
<div class="controls-panel">
<button matButton="filled" (click)="visualize('dijkstra')">{{ 'PATHFINDING.DIJKSTRA' | translate }}</button>
<button matButton="filled" (click)="visualize('astar')">{{ 'PATHFINDING.ASTAR' | translate }}</button>
</div>
<div class="controls-panel">
<button matButton="filled" (click)="createCase({withWalls: true, scenario: 'normal'})">{{ 'PATHFINDING.NORMAL_CASE' | translate }}</button>
<button matButton="filled" (click)="createCase({withWalls: true, scenario: 'random'})">{{ 'PATHFINDING.RANDOM_CASE' | translate }}</button>
<button matButton="filled" (click)="createCase({withWalls: true, scenario: 'edge'})">{{ 'PATHFINDING.EDGE_CASE' | translate }}</button>
<button matButton="filled" (click)="createCase({withWalls: false, scenario: 'normal'})">{{ 'PATHFINDING.CLEAR_BOARD' | translate }}</button>
</div>
<div class="controls-container">
<div class="controls-panel">
<button matButton="filled" (click)="visualize('dijkstra')">{{ 'PATHFINDING.DIJKSTRA' | translate }}</button>
<button matButton="filled" (click)="visualize('astar')">{{ 'PATHFINDING.ASTAR' | translate }}</button>
</div>
<div class="controls-panel">
<button matButton="filled" (click)="createCase({withWalls: true, scenario: 'normal'})">{{ 'PATHFINDING.NORMAL_CASE' | translate }}</button>
<button matButton="filled" (click)="createCase({withWalls: true, scenario: 'random'})">{{ 'PATHFINDING.RANDOM_CASE' | translate }}</button>
<button matButton="filled" (click)="createCase({withWalls: true, scenario: 'edge'})">{{ 'PATHFINDING.EDGE_CASE' | translate }}</button>
<button matButton="filled" (click)="createCase({withWalls: false, scenario: 'normal'})">{{ 'PATHFINDING.CLEAR_BOARD' | translate }}</button>
</div>
<div class="controls-panel">
<mat-button-toggle-group [(ngModel)]="selectedNodeType" aria-label="Node Type Selection">
<mat-button-toggle [value]="NodeType.Start">{{ 'PATHFINDING.START_NODE' | translate }}</mat-button-toggle>
<mat-button-toggle [value]="NodeType.End">{{ 'PATHFINDING.END_NODE' | translate }}</mat-button-toggle>
<mat-button-toggle [value]="NodeType.Wall">{{ 'PATHFINDING.WALL' | translate }}</mat-button-toggle>
<mat-button-toggle [value]="NodeType.None">{{ 'PATHFINDING.CLEAR_NODE' | translate }}</mat-button-toggle>
</mat-button-toggle-group>
</div>
<div class="controls-panel">
<div class="input-container">
<mat-form-field appearance="outline" class="input-field">
<mat-label>{{ 'ALGORITHM.GRID_HEIGHT' | translate }}</mat-label>
<input
matInput
type="number"
[min]="MIN_GRID_SIZE"
[max]="MAX_GRID_SIZE"
[(ngModel)]="gridRows"
(ngModelChange)="genericGridComponent.gridRows = gridRows; genericGridComponent.applyGridSize()"
/> </mat-form-field>
<div class="controls-panel">
<mat-button-toggle-group [(ngModel)]="selectedNodeType" aria-label="Node Type Selection">
<mat-button-toggle [value]="NodeType.Start">{{ 'PATHFINDING.START_NODE' | translate }}</mat-button-toggle>
<mat-button-toggle [value]="NodeType.End">{{ 'PATHFINDING.END_NODE' | translate }}</mat-button-toggle>
<mat-button-toggle [value]="NodeType.Wall">{{ 'PATHFINDING.WALL' | translate }}</mat-button-toggle>
<mat-button-toggle [value]="NodeType.None">{{ 'PATHFINDING.CLEAR_NODE' | translate }}</mat-button-toggle>
</mat-button-toggle-group>
</div>
<div class="controls-panel">
<div class="input-container">
<mat-form-field appearance="outline" class="input-field">
<mat-label>{{ 'ALGORITHM.GRID_HEIGHT' | translate }}</mat-label>
<input
matInput
type="number"
[min]="MIN_GRID_SIZE"
[max]="MAX_GRID_SIZE"
[(ngModel)]="gridRows"
(ngModelChange)="genericGridComponent.gridRows = gridRows; genericGridComponent.applyGridSize()"
/> </mat-form-field>
<mat-form-field appearance="outline" class="input-field">
<mat-label>{{ 'ALGORITHM.GRID_WIDTH' | translate }}</mat-label>
<input
matInput
type="number"
[min]="MIN_GRID_SIZE"
[max]="MAX_GRID_SIZE"
[(ngModel)]="gridCols"
(ngModelChange)="genericGridComponent.gridCols = gridCols; genericGridComponent.applyGridSize()"
/> </mat-form-field>
<mat-form-field appearance="outline" class="input-field">
<mat-label>{{ 'ALGORITHM.GRID_WIDTH' | translate }}</mat-label>
<input
matInput
type="number"
[min]="MIN_GRID_SIZE"
[max]="MAX_GRID_SIZE"
[(ngModel)]="gridCols"
(ngModelChange)="genericGridComponent.gridCols = gridCols; genericGridComponent.applyGridSize()"
/> </mat-form-field>
</div>
</div>
<div class="legend">
<span><span class="legend-color start"></span> {{ 'PATHFINDING.START_NODE' | translate }}</span>
<span><span class="legend-color end"></span> {{ 'PATHFINDING.END_NODE' | translate }}</span>
<span><span class="legend-color wall"></span> {{ 'PATHFINDING.WALL' | translate }}</span>
<span><span class="legend-color visited"></span> {{ 'PATHFINDING.VISITED' | translate }}</span>
<span><span class="legend-color path"></span> {{ 'PATHFINDING.PATH' | translate }}</span>
</div>
<div class="controls-panel">
<p>{{ 'PATHFINDING.PATH_LENGTH' | translate }}: {{ pathLength }}</p>
<p>{{ 'PATHFINDING.EXECUTION_TIME' | translate }}: {{ executionTime | number:'1.2-2' }} ms</p>
</div>
</div>
<div class="legend">
<span><span class="legend-color start"></span> {{ 'PATHFINDING.START_NODE' | translate }}</span>
<span><span class="legend-color end"></span> {{ 'PATHFINDING.END_NODE' | translate }}</span>
<span><span class="legend-color wall"></span> {{ 'PATHFINDING.WALL' | translate }}</span>
<span><span class="legend-color visited"></span> {{ 'PATHFINDING.VISITED' | translate }}</span>
<span><span class="legend-color path"></span> {{ 'PATHFINDING.PATH' | translate }}</span>
</div>
<div class="controls-panel">
<p>{{ 'PATHFINDING.PATH_LENGTH' | translate }}: {{ pathLength }}</p>
<p>{{ 'PATHFINDING.EXECUTION_TIME' | translate }}: {{ executionTime | number:'1.2-2' }} ms</p>
</div>
</div>
<app-generic-grid
[gridRows]="gridRows"
[gridCols]="gridCols"
[minGridSize]="MIN_GRID_SIZE"
[maxGridSize]="MAX_GRID_SIZE"
[maxGridPx]="MAX_GRID_PX"
[createNodeFn]="createPathfindingNode"
[getNodeColorFn]="getPathfindingNodeColor"
[applySelectionFn]="applyPathfindingSelection"
[backgroundColor]="'lightgray'"
(gridChange)="grid = $event"
></app-generic-grid>
</mat-card-content>
</mat-card>
<app-generic-grid
[gridRows]="gridRows"
[gridCols]="gridCols"
[minGridSize]="MIN_GRID_SIZE"
[maxGridSize]="MAX_GRID_SIZE"
[maxGridPx]="MAX_GRID_PX"
[createNodeFn]="createPathfindingNode"
[getNodeColorFn]="getPathfindingNodeColor"
[applySelectionFn]="applyPathfindingSelection"
[backgroundColor]="'lightgray'"
(gridChange)="grid = $event"
></app-generic-grid>
</mat-card-content>
</mat-card>

View File

@@ -1 +1,3 @@
<canvas #gridCanvas></canvas>
<div class="canvas-container">
<canvas #gridCanvas></canvas>
</div>

View File

@@ -230,10 +230,11 @@ a {
// algos
.algo-container {
width: 100%;
max-width: var(--app-maxWidth);
margin: 0 auto;
padding: clamp(1rem, 4vw, 2rem);
gap: clamp(1rem, 3vw, 1.5rem);
margin-right: 1rem;
margin-left: 0.5rem;
margin-top: auto;
}
.algo-info {
@@ -473,7 +474,9 @@ app-root {
display: grid;
gap: clamp(1rem, 3vw, 1.5rem);
max-width: var(--app-maxWidth);
margin: 0 auto;
margin-right: 1rem;
margin-left: 1rem;
margin-top: auto;
}
.hero {
@@ -488,40 +491,26 @@ app-root {
gap: clamp(1rem, 4vw, 2rem);
padding: clamp(1rem, 3vw, 1.5rem);
align-items: flex-start;
}
.hero .photo {
flex: 0 0 auto;
max-width: 100%;
}
.hero .photo img {
display: block;
width: 100%;
height: auto;
max-width: 425px;
border-radius: 12px;
box-shadow: 0 6px 24px rgba(0, 0, 0, .25);
object-fit: cover;
}
.hero .intro {
flex: 1 1 400px;
}
@media (max-width: 850px) {
.hero-flex-container {
justify-content: center;
}
.hero .photo {
width: 100%;
.photo {
flex: 1 1 min(100%, 425px);
max-width: 100%;
display: flex;
justify-content: center;
img {
display: block;
width: 100%;
height: auto;
max-width: 425px;
border-radius: 12px;
box-shadow: 0 6px 24px rgba(0, 0, 0, .25);
object-fit: cover;
}
}
.hero .intro {
flex-basis: 100%;
.intro {
flex: 999 1 min(100%, 400px);
}
}