Rework folder structure in frontend
Pages are now grouped per group they appear in on in the header (where possible) Utilities used by multiple pages in the project are grouped in folders such as services/pipes/etc
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
<div class="card-div">
|
||||
<mat-card class="particle-card">
|
||||
<mat-card-header>
|
||||
<mat-card-title>Particle Properties</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<div class="particle-properties">
|
||||
<div class="property-row">
|
||||
<div class="color-picker">
|
||||
<input type="color" [(ngModel)]="selectedColor">
|
||||
<span>Current color: {{ selectedColor }}</span>
|
||||
</div>
|
||||
<mat-form-field appearance="fill" class="type-field">
|
||||
<mat-label>Select Particle Type</mat-label>
|
||||
<input type="text"
|
||||
placeholder="Search for a particle type"
|
||||
matInput
|
||||
[formControl]="particleTypeControl"
|
||||
[matAutocomplete]="auto">
|
||||
<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
|
||||
<mat-option *ngFor="let type of filteredParticleTypes | async" [value]="type">
|
||||
{{ type }}
|
||||
</mat-option>
|
||||
</mat-autocomplete>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="size-slider">
|
||||
<mat-slider min="0.1" max="4" step="0.1" class="full-width">
|
||||
<input matSliderThumb [(ngModel)]="selectedSize">
|
||||
</mat-slider>
|
||||
<span>Size: {{ selectedSize }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
@@ -0,0 +1,61 @@
|
||||
.particle-card {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.particle-properties {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.property-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.type-field {
|
||||
flex: 1;
|
||||
min-width: 20ch;
|
||||
max-width: 40ch;
|
||||
}
|
||||
|
||||
.color-picker {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.color-picker input[type="color"] {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.card-div {
|
||||
mat-card {
|
||||
background-color: var(--color-primary);
|
||||
color: var(--font-color);
|
||||
}
|
||||
}
|
||||
|
||||
.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.size-slider {
|
||||
width: 95%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: var(--font-color);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import {ParticleComponent} from './particle.component';
|
||||
|
||||
describe('ParticleComponent', () => {
|
||||
let component: ParticleComponent;
|
||||
let fixture: ComponentFixture<ParticleComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ParticleComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ParticleComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,115 @@
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {MatCard, MatCardContent, MatCardHeader, MatCardTitle} from '@angular/material/card';
|
||||
import {FormControl, FormsModule, ReactiveFormsModule} from '@angular/forms';
|
||||
import {ParticleManagerService} from '../../services/particle-manager.service';
|
||||
import {Particle} from '../../models/particle.model';
|
||||
import {MatSliderModule} from '@angular/material/slider';
|
||||
import {MatSelectModule} from '@angular/material/select';
|
||||
import {MatFormFieldModule} from '@angular/material/form-field';
|
||||
import {MatInputModule} from '@angular/material/input';
|
||||
import {MatAutocompleteModule} from '@angular/material/autocomplete';
|
||||
import {Observable} from 'rxjs';
|
||||
import {map, startWith} from 'rxjs/operators';
|
||||
import {AsyncPipe, NgForOf} from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'app-particle',
|
||||
imports: [
|
||||
MatCard,
|
||||
MatCardContent,
|
||||
MatCardHeader,
|
||||
MatCardTitle,
|
||||
ReactiveFormsModule,
|
||||
FormsModule,
|
||||
MatSliderModule,
|
||||
MatSelectModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatAutocompleteModule,
|
||||
NgForOf,
|
||||
AsyncPipe
|
||||
],
|
||||
templateUrl: './particle.component.html',
|
||||
styleUrl: './particle.component.scss'
|
||||
})
|
||||
export class ParticleComponent implements OnInit {
|
||||
// Available particle types from the enum
|
||||
particleTypes = Object.values(Particle);
|
||||
|
||||
// Form control for the particle type dropdown with filtering
|
||||
particleTypeControl = new FormControl();
|
||||
filteredParticleTypes: Observable<string[]>;
|
||||
|
||||
constructor(
|
||||
private particleManagerService: ParticleManagerService,
|
||||
) {
|
||||
this.filteredParticleTypes = this.particleTypeControl.valueChanges.pipe(
|
||||
startWith(''),
|
||||
map(value => this._filterParticleTypes(value || ''))
|
||||
);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
// Initialize the particle type control with the current value
|
||||
this.particleTypeControl.setValue(this.selectedParticle);
|
||||
|
||||
// Update the selected particle when the control value changes
|
||||
this.particleTypeControl.valueChanges.subscribe(value => {
|
||||
if (value && Object.values(Particle).includes(value)) {
|
||||
this.selectedParticle = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _filterParticleTypes(value: string): string[] {
|
||||
const filterValue = value.toLowerCase();
|
||||
return this.particleTypes.filter(type => type.toLowerCase().includes(filterValue));
|
||||
}
|
||||
|
||||
// Display function for the autocomplete
|
||||
displayFn(particle: string): string {
|
||||
return particle ? particle : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the selected color
|
||||
*/
|
||||
public get selectedColor(): string {
|
||||
return this.particleManagerService.getSelectedColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the selected color
|
||||
*/
|
||||
public set selectedColor(color: string) {
|
||||
this.particleManagerService.setSelectedColor(color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the selected particle type
|
||||
*/
|
||||
public get selectedParticle(): Particle {
|
||||
return this.particleManagerService.particle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the selected particle type
|
||||
*/
|
||||
public set selectedParticle(particle: Particle) {
|
||||
this.particleManagerService.particle = particle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the selected particle size
|
||||
*/
|
||||
public get selectedSize(): number {
|
||||
return this.particleManagerService.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the selected particle size
|
||||
*/
|
||||
public set selectedSize(size: number) {
|
||||
this.particleManagerService.size = size;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user