Refactor pathfinding/sorting UI and update i18n

Replace plain container with Angular Material mat-card in pathfinding view and reorganize UI: add mat-card header/content, algorithm explanation block, control buttons, node-type toggle group, grid-size inputs, legend and results display (path length & execution time). Import and wire MatCard modules in the pathfinding component. Move .algo-info styling from the component SCSS into global styles.scss and remove it from the component stylesheet. Update sorting template to use new SORTING translation keys and add an UrlConstants reference in the sorting component TS for external links. Add/adjust i18n keys in en.json and de.json for sorting and grid labels to match the updated templates.
This commit is contained in:
2026-02-04 12:17:54 +01:00
parent 450ab0b837
commit a10f62f2dd
8 changed files with 160 additions and 125 deletions

View File

@@ -1,6 +1,8 @@
<div class="container">
<h1>{{ 'PATHFINDING.TITLE' | translate }}</h1>
<mat-card class="container">
<mat-card-header>
<mat-card-title>{{ 'PATHFINDING.TITLE' | translate }}</mat-card-title>
</mat-card-header>
<mat-card-content>
<div class="algo-info">
<h3>{{ 'PATHFINDING.EXPLANATION.TITLE' | translate }}</h3>
@@ -42,7 +44,7 @@
<div class="controls">
<div class="grid-size">
<mat-form-field appearance="outline" class="grid-field">
<mat-label>{{ 'ALGORITHM.PATHFINDING.GRID_HEIGHT' | translate }}</mat-label>
<mat-label>{{ 'PATHFINDING.GRID_HEIGHT' | translate }}</mat-label>
<input
matInput
type="number"
@@ -55,7 +57,7 @@
</mat-form-field>
<mat-form-field appearance="outline" class="grid-field">
<mat-label>{{ 'ALGORITHM.PATHFINDING.GRID_WIDTH' | translate }}</mat-label>
<mat-label>{{ 'PATHFINDING.GRID_WIDTH' | translate }}</mat-label>
<input
matInput
type="number"
@@ -84,4 +86,4 @@
</div>
<canvas #gridCanvas></canvas>
</div>
</mat-card-content>

View File

@@ -2,25 +2,6 @@
padding: 2rem;
}
.algo-info {
margin: 0 0 1rem 0;
padding: 0.75rem 1rem;
border: 1px solid #ddd;
border-radius: 8px;
h3 {
margin: 0 0 0.5rem 0;
}
p {
margin: 0.5rem 0;
}
a {
margin-left: 0.25rem;
}
}
.controls-container {
display: flex;
flex-direction: column;

View File

@@ -12,6 +12,7 @@ import {TranslateModule, TranslateService} from '@ngx-translate/core';
import {DEFAULT_GRID_COLS, DEFAULT_GRID_ROWS, MAX_GRID_PX, MAX_GRID_SIZE, MIN_GRID_SIZE, Node} from './pathfinding.models';
import {PathfindingService} from './service/pathfinding.service';
import {UrlConstants} from '../../../constants/UrlConstants';
import {MatCard, MatCardContent, MatCardHeader, MatCardTitle} from '@angular/material/card';
enum NodeType {
Start = 'start',
@@ -32,7 +33,11 @@ interface GridPos { row: number; col: number }
MatButtonToggleModule,
MatFormFieldModule,
MatInputModule,
TranslateModule
TranslateModule,
MatCard,
MatCardHeader,
MatCardTitle,
MatCardContent
],
templateUrl: './pathfinding.component.html',
styleUrls: ['./pathfinding.component.scss']

View File

@@ -1,12 +1,29 @@
<div class="sorting-container">
<mat-card class="sorting-card">
<mat-card-header>
<mat-card-title>{{ 'ALGORITHM.SORTING.TITLE' | translate }}</mat-card-title>
<mat-card-title>{{ 'SORTING.TITLE' | translate }}</mat-card-title>
</mat-card-header>
<mat-card-content>
<div class="algo-info">
<h3>{{ 'SORTING.EXPLANATION.TITLE' | translate }}</h3>
<p>
<strong>Dijkstra</strong> {{ 'SORTING.EXPLANATION.DIJKSTRA_EXPLANATION' | translate }}
<a href="{{UrlConstants.DIJKSTRA_WIKI}}" target="_blank" rel="noopener noreferrer">Wikipedia</a>
</p>
<p>
<strong>A*</strong> {{ 'SORTING.EXPLANATION.ASTAR_EXPLANATION' | translate}}
<a href="{{UrlConstants.ASTAR_WIKI}}" target="_blank" rel="noopener noreferrer">Wikipedia</a>
</p>
<p>
<strong>{{ 'SORTING.EXPLANATION.NOTE' | translate}}</strong> {{ 'SORTING.EXPLANATION.DISCLAIMER' | translate}}
</p>
</div>
<div class="controls-panel">
<mat-form-field appearance="fill">
<mat-label>{{ 'ALGORITHM.SORTING.ALGORITHM' | translate }}</mat-label>
<mat-label>{{ 'SORTING.ALGORITHM' | translate }}</mat-label>
<mat-select [(ngModel)]="selectedAlgorithm">
@for (algo of availableAlgorithms; track algo.value) {
<mat-option [value]="algo.value">{{ algo.name }}</mat-option>
@@ -15,7 +32,7 @@
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>{{ 'ALGORITHM.SORTING.ARRAY_SIZE' | translate }}</mat-label>
<mat-label>{{ 'SORTING.ARRAY_SIZE' | translate }}</mat-label>
<input
matInput
type="number"
@@ -29,18 +46,18 @@
</div>
<div class="controls-panel">
<button mat-raised-button color="primary" (click)="startSorting()">
<mat-icon>play_arrow</mat-icon> {{ 'ALGORITHM.SORTING.START' | translate }}
<mat-icon>play_arrow</mat-icon> {{ 'SORTING.START' | translate }}
</button>
<button mat-raised-button color="warn" (click)="resetSorting()">
<mat-icon>refresh</mat-icon> {{ 'ALGORITHM.SORTING.RESET' | translate }}
<mat-icon>refresh</mat-icon> {{ 'SORTING.RESET' | translate }}
</button>
<button mat-raised-button (click)="generateNewArray()">
<mat-icon>add_box</mat-icon> {{ 'ALGORITHM.SORTING.GENERATE_NEW_ARRAY' | translate }}
<mat-icon>add_box</mat-icon> {{ 'SORTING.GENERATE_NEW_ARRAY' | translate }}
</button>
</div>
<div class="info-panel">
<p>{{ 'ALGORITHM.SORTING.EXECUTION_TIME' | translate }}: {{ executionTime }} ms</p>
<p>{{ 'SORTING.EXECUTION_TIME' | translate }}: {{ executionTime }} ms</p>
</div>
<div class="visualization-area">
@for (item of sortArray; track $index) {

View File

@@ -10,6 +10,7 @@ import { SortingService } from './service/sorting.service';
import {SortData, SortSnapshot} from './sorting.models';
import { FormsModule } from '@angular/forms';
import {MatInput} from '@angular/material/input';
import {UrlConstants} from '../../../constants/UrlConstants';
@Component({
selector: 'app-sorting',
standalone: true,
@@ -137,4 +138,6 @@ export class SortingComponent implements OnInit {
this.stopAnimations();
this.resetSortState();
}
protected readonly UrlConstants = UrlConstants;
}

View File

@@ -317,25 +317,29 @@
},
"ALERT": {
"START_END_NODES": "Bitte wählen Sie einen Start- und Endknoten aus, bevor Sie den Algorithmus starten."
}
},
"ALGORITHM": {
"TITLE": "Algorithmen",
"PATHFINDING": {
"TITLE": "Wegfindung",
"DESCRIPTION": "Vergleich von Dijkstra vs. A*.",
"GRID_HEIGHT": "Höhe",
"GRID_WIDTH": "Beite"
},
"SORTING": {
"TITLE": "Sortieralgorithmen",
"DESCRIPTION": "Visualisierung verschiedener Sortieralgorithmen.",
"ALGORITHM": "Algorithmus",
"ALGORITHM": "Algorithmen",
"START": "Sortierung starten",
"RESET": "Zurücksetzen",
"GENERATE_NEW_ARRAY": "Neues Array generieren",
"EXECUTION_TIME": "Ausführungszeit",
"ARRAY_SIZE": "Anzahl der Balken"
},
"ALGORITHM": {
"TITLE": "Algorithmen",
"PATHFINDING": {
"TITLE": "Wegfindung",
"DESCRIPTION": "Vergleich von Dijkstra vs. A*."
},
"SORTING": {
"TITLE": "Sortierung",
"DESCRIPTION": "Visualisierung verschiedener Sortieralgorithmen."
}
}
}

View File

@@ -317,25 +317,28 @@
},
"ALERT": {
"START_END_NODES": "Please select a start and end node before running the algorithm."
}
},
"ALGORITHM": {
"TITLE": "Algorithms",
"PATHFINDING": {
"TITLE": "Pathfinding",
"DESCRIPTION": "Comparing of Dijkstra vs. A*.",
"GRID_HEIGHT": "Height",
"GRID_WIDTH": "Width"
},
"SORTING": {
"TITLE": "Sorting Algorithms",
"DESCRIPTION": "Visualizing various sorting algorithms.",
"ALGORITHM": "Algorithm",
"START": "Start Sorting",
"RESET": "Reset",
"GENERATE_NEW_ARRAY": "Generate New Array",
"EXECUTION_TIME": "Execution Time",
"ARRAY_SIZE": "Number of Bars"
},
"ALGORITHM": {
"TITLE": "Algorithms",
"PATHFINDING": {
"TITLE": "Pathfinding",
"DESCRIPTION": "Comparing of Dijkstra vs. A*."
},
"SORTING": {
"TITLE": "Sorting",
"DESCRIPTION": "Visualizing various sorting algorithms.",
}
}
}

View File

@@ -211,3 +211,23 @@ a {
height: 18px;
width: 18px;
}
// algos
.algo-info {
margin: 0 0 1rem 0;
padding: 0.75rem 1rem;
border: 1px solid #ddd;
border-radius: 8px;
h3 {
margin: 0 0 0.5rem 0;
}
p {
margin: 0.5rem 0;
}
a {
margin-left: 0.25rem;
}
}