Skip to content

Commit

Permalink
Added a basic route panel for the online map
Browse files Browse the repository at this point in the history
  • Loading branch information
jonafanho committed Dec 8, 2024
1 parent 889c20c commit 596b553
Show file tree
Hide file tree
Showing 21 changed files with 395 additions and 98 deletions.
36 changes: 20 additions & 16 deletions buildSrc/src/main/resources/website/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
<app-sidenav #sideDirections (closed)="onCloseDirections()">
<app-sidenav #sideStation (closed)="onCloseStation()">
<app-sidenav #sideMain>
<app-map (stationClicked)="onClickStation($event, sideStation, sideDirections, false)"/>
<button mat-fab class="button-corner" aria-label="Menu" (click)="sideMain.open()" matTooltip="Menu">
<mat-icon>menu</mat-icon>
</button>
<div sidenav class="column gap wrapper">
<app-search label="Search for anything..." [includeRoutes]="true" (stationClicked)="onClickStation($event, sideStation, sideDirections, true)" (routeClicked)="onClickRoute($event)"/>
<app-main-panel class="wrapper"/>
</div>
<div title>{{ getTitle() }}</div>
<app-sidenav #sideRoute (closed)="onCloseRoute()">
<app-sidenav #sideDirections (closed)="onCloseDirections()">
<app-sidenav #sideStation (closed)="onCloseStation()">
<app-sidenav #sideMain>
<app-map (stationClicked)="onClickStation($event, sideMain, sideStation, sideDirections, sideRoute, false)"/>
<button mat-fab class="button-corner" aria-label="Menu" (click)="onClickMain(sideMain, sideStation, sideDirections, sideRoute)" matTooltip="Menu">
<mat-icon>menu</mat-icon>
</button>
<div sidenav class="column gap wrapper">
<app-search label="Search for anything..." [includeRoutes]="true" (stationClicked)="onClickStation($event, sideMain, sideStation, sideDirections, sideRoute, true)" (routeClicked)="onClickRoute($event, sideMain, sideStation, sideDirections, sideRoute)"/>
<app-main-panel class="wrapper"/>
</div>
<div title>{{ getTitle() }}</div>
</app-sidenav>
<app-station-panel sidenav (stationClicked)="onClickStation($event, sideMain, sideStation, sideDirections, sideRoute, true)" (routeClicked)="onClickRoute($event, sideMain, sideStation, sideDirections, sideRoute)" (directionsOpened)="sideDirections.open()"/>
<div title>Station Details</div>
</app-sidenav>
<app-station-panel sidenav (stationClicked)="onClickStation($event, sideStation, sideDirections, true)" (routeClicked)="onClickRoute($event)" (directionsOpened)="sideDirections.open()"/>
<div title>Station Details</div>
<app-directions sidenav/>
<div title>Directions</div>
</app-sidenav>
<app-directions sidenav/>
<div title>Directions</div>
<app-route-panel sidenav (stationClicked)="onClickStation($event, sideMain, sideStation, sideDirections, sideRoute, true)" (routeClicked)="onClickRoute($event, sideMain, sideStation, sideDirections, sideRoute)"/>
<div title>Route Details</div>
</app-sidenav>
28 changes: 24 additions & 4 deletions buildSrc/src/main/resources/website/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {DirectionsService} from "./service/directions.service";
import {MatTooltipModule} from "@angular/material/tooltip";
import {MatIconModule} from "@angular/material/icon";
import {MainPanelComponent} from "./component/panel/main-panel.component";
import {RouteService} from "./service/route.service";
import {RoutePanelComponent} from "./component/route-panel/route-panel.component";

@Component({
selector: "app-root",
Expand All @@ -24,27 +26,41 @@ import {MainPanelComponent} from "./component/panel/main-panel.component";
DirectionsComponent,
MatTooltipModule,
MainPanelComponent,
RoutePanelComponent,
],
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent {

constructor(private readonly stationService: StationService, private readonly directionsService: DirectionsService) {
constructor(private readonly stationService: StationService, private readonly routeService: RouteService, private readonly directionsService: DirectionsService) {
}

getTitle() {
return document.title;
}

onClickStation(stationId: string, sideStation: SidenavComponent, sideDirections: SidenavComponent, zoomToStation: boolean) {
onClickMain(sideMain: SidenavComponent, sideStation: SidenavComponent, sideDirections: SidenavComponent, sideRoute: SidenavComponent) {
sideMain.open();
sideStation.close();
sideDirections.close();
sideRoute.close();
}

onClickStation(stationId: string, sideMain: SidenavComponent, sideStation: SidenavComponent, sideDirections: SidenavComponent, sideRoute: SidenavComponent, zoomToStation: boolean) {
this.stationService.setStation(stationId, zoomToStation);
sideMain.close();
sideStation.open();
sideDirections.close();
sideRoute.close();
}

onClickRoute(routeColor: string) {
console.log(routeColor);
onClickRoute(routeId: string, sideMain: SidenavComponent, sideStation: SidenavComponent, sideDirections: SidenavComponent, sideRoute: SidenavComponent) {
this.routeService.setRoute(routeId);
sideMain.close();
sideStation.close();
sideDirections.close();
sideRoute.open();
}

onCloseStation() {
Expand All @@ -55,4 +71,8 @@ export class AppComponent {
console.log(this);
this.directionsService.clear();
}

onCloseRoute() {
this.routeService.clear();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
transition: background-color 0.2s;
}

.clickable:hover {
background-color: rgba(127, 127, 127, 10%);
.icon {
margin: 0;
}

.arrival {
padding: 0.4em 0;
.clickable:hover {
background-color: rgba(127, 127, 127, 10%);
}

.title {
Expand All @@ -20,10 +20,10 @@
}

.light-color {
color: rgba(127, 127, 127, 50%);
color: rgba(127, 127, 127, 80%);
}

.arrival-color {
.color {
border-left: 4px solid;
padding-left: 4px;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
<div matRipple class="column arrival clickable {{useLightColor ? 'light-color' : ''}}" (click)="entryClicked.emit()">
<div class="row gap center title arrival-color" [style.border-left-color]="color">
@if (clickable) {
<div matRipple class="column padding-top-bottom-small clickable {{useLightColor ? 'light-color' : ''}}" (click)="entryClicked.emit()">
<div *ngTemplateOutlet="content"></div>
</div>
} @else {
<div class="column padding-top-bottom-small {{useLightColor ? 'light-color' : ''}}" (click)="entryClicked.emit()">
<div *ngTemplateOutlet="content"></div>
</div>
}

<ng-template #content>
<div class="row gap center title color" [style.border-left-color]="color ? color : 'transparent'">
<div class="row center">
@for (icon of icons; track $index) {
@if (icon) {
<mat-icon>{{ icon }}</mat-icon>
<mat-icon class="icon">{{ icon }}</mat-icon>
}
}
<div>{{ title[0] }}</div>
Expand All @@ -12,10 +22,10 @@
<div class="align-right">{{ title[1] }}</div>
</div>
@for (subtitle of subtitles; track $index) {
<div class="row gap center subtitle arrival-color" [style.border-left-color]="color">
<div class="row gap center subtitle color" [style.border-left-color]="color ? color : 'transparent'">
<div>{{ subtitle[0] }}</div>
<div class="spacing"></div>
<div class="align-right">{{ subtitle[1] }}</div>
</div>
}
</div>
</ng-template>
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import {Component, EventEmitter, Input, Output} from "@angular/core";
import {MatIconModule} from "@angular/material/icon";
import {MatRipple} from "@angular/material/core";
import {NgTemplateOutlet} from "@angular/common";

@Component({
selector: "app-data-list-entry",
standalone: true,
imports: [
MatIconModule,
MatRipple,
NgTemplateOutlet,
],
templateUrl: "./data-list-entry.component.html",
styleUrl: "./data-list-entry.component.css",
Expand All @@ -16,7 +18,8 @@ export class DataListEntryComponent {
@Input({required: true}) icons: string[] = [];
@Input({required: true}) title: [string, string] = ["", ""];
@Input({required: true}) subtitles: [string, string][] = [];
@Input({required: true}) color = "";
@Input() color = "";
@Input({required: true}) useLightColor = false;
@Input({required: true}) clickable = true;
@Output() entryClicked = new EventEmitter<void>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {MatTooltipModule} from "@angular/material/tooltip";
MatIconModule,
MatSelectModule,
MatTooltipModule,

],
templateUrl: "./main-panel.component.html",
styleUrl: "./main-panel.component.css",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
.display-container {
display: flex;
position: relative;
min-width: 14px;
}

.line {
left: 4px;
position: absolute;
width: 6px;
}

.line.middle {
height: 100%;
top: 0;
}

.line.above {
height: 50%;
top: 0;
}

.line.below {
bottom: 0;
height: 50%;
}

.circle {
background-color: white;
border: 2px solid black;
border-radius: 8px;
box-sizing: border-box;
position: absolute;
top: 50%;
transform: translate(0, -50%);
width: 14px;
height: 14px;
}

.full {
width: 100%;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<div class="row center">
<div class="display-container" [style.height]="(getHeight() + 4) + 'px'">
@if (colorAbove === colorBelow) {
@if (colorAbove !== undefined) {
<div class="line middle" [style.background-color]="colorAbove | formatColor"></div>
}
} @else {
@if (colorAbove !== undefined) {
<div class="line above" [style.background-color]="colorAbove | formatColor"></div>
}
@if (colorBelow !== undefined) {
<div class="line below" [style.background-color]="colorBelow | formatColor"></div>
}
}
@if (isStation) {
<div class="circle"></div>
}
</div>
<div class="full" #text>
<ng-content/>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {AfterViewInit, Component, ElementRef, Input, ViewChild} from "@angular/core";
import {MatSelectModule} from "@angular/material/select";
import {FormatColorPipe} from "../../pipe/formatColorPipe";

@Component({
selector: "app-route-display",
standalone: true,
imports: [
MatSelectModule,
FormatColorPipe,
],
templateUrl: "./route-display.component.html",
styleUrl: "./route-display.component.css",
})
export class RouteDisplayComponent implements AfterViewInit {
@Input() colorAbove?: number;
@Input() colorBelow?: number;
@Input({required: true}) isStation = false;
@ViewChild("text") private readonly textRef!: ElementRef<HTMLDivElement>;
private height = 0;

ngAfterViewInit(): void {
new ResizeObserver(entries => entries.forEach(entry => this.height = entry.target.clientHeight)).observe(this.textRef.nativeElement);
}

getHeight() {
return this.height;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.route-name {
font-family: "Noto Sans", "Noto Serif TC", "Noto Serif SC", "Noto Serif JP", "Noto Serif KR", sans-serif;
font-size: 1.5em;
font-weight: 600;
text-align: center;
}

.route-name.cjk {
font-size: 3em;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<div class="column gap wrapper">
<div class="column padding-sides">
@for (routeNamePart of getRouteName() | splitName; track $index) {
<div class="route-name {{routeNamePart.isCjk ? 'cjk' : ''}}">{{ routeNamePart.text }}</div>
}
</div>
<mat-form-field class="padding-sides" subscriptSizing="dynamic">
<mat-label>Route Variation</mat-label>
<mat-select #dropdown (selectionChange)="selectRoute(dropdown.value)" [value]="getRandomSeed()">
@for (name of getNames(); track $index) {
<mat-option [value]="'id_' + $index">{{ name | formatName }}</mat-option>
}
</mat-select>
</mat-form-field>

<div class="column padding-sides content">
@for (station of getStations(); track $index) {
<app-route-display [colorAbove]="$index > 0 ? getRouteColor() : undefined" [colorBelow]="$index < $count - 1 ? getRouteColor() : undefined" [isStation]="true">
<app-data-list-entry [icons]="[]" [title]="[station.name | formatName, '']" [subtitles]="[]" [useLightColor]="false" [clickable]="true" (entryClicked)="stationClicked.emit(station.id)"/>
</app-route-display>
}
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {Component, EventEmitter, Output} from "@angular/core";
import {MatSelectModule} from "@angular/material/select";
import {RouteService} from "../../service/route.service";
import {FormatNamePipe} from "../../pipe/formatNamePipe";
import {SplitNamePipe} from "../../pipe/splitNamePipe";
import {RouteDisplayComponent} from "../route-display/route-display.component";
import {DataListEntryComponent} from "../data-list-entry/data-list-entry.component";

@Component({
selector: "app-route-panel",
standalone: true,
imports: [
MatSelectModule,
FormatNamePipe,
SplitNamePipe,
RouteDisplayComponent,
DataListEntryComponent,
],
templateUrl: "./route-panel.component.html",
styleUrl: "./route-panel.component.css",
})
export class RoutePanelComponent {
@Output() stationClicked = new EventEmitter<string>();
@Output() routeClicked = new EventEmitter<string>();
@Output() directionsOpened = new EventEmitter<void>;

constructor(private readonly routeService: RouteService) {
}

getNames() {
return this.routeService.getNames().map(name => name.split("||")[1] ?? "(Untitled)");
}

getRandomSeed() {
return this.routeService.getRandomSeed();
}

selectRoute(id: string) {
this.routeService.selectRoute(parseInt(id.split("_")[1]));
}

getRouteName() {
const route = this.routeService.getSelectedRoute();
return route ? route.name.split("||")[0] : "";
}

getRouteColor() {
const route = this.routeService.getSelectedRoute();
return route ? parseInt(route.color, 16) : undefined;
}

getStations() {
const route = this.routeService.getSelectedRoute();
return route ? route.stations : [];
}
}
Loading

0 comments on commit 596b553

Please sign in to comment.