Skip to content

Commit 3756a83

Browse files
committed
Added global train list and multiple timetable view modes
1 parent 83d98bf commit 3756a83

27 files changed

+2549
-551
lines changed

smo-backend/Controllers/StatusController.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Text.Json;
2+
using Marvin.Cache.Headers;
23
using Microsoft.AspNetCore.Mvc;
34
using SMOBackend.Analytics;
45
using SMOBackend.Models;
@@ -152,6 +153,8 @@ public ActionResult<Dictionary<int, int>> GetTrainDelays(string serverCode, stri
152153
/// <param name="serverCode">The server code</param>
153154
/// <param name="trainNoLocal">The local train number</param>
154155
[HttpGet("{serverCode}/trains/{trainNoLocal:int:min(1000)}/timetable")]
156+
[HttpCacheExpiration(CacheLocation = CacheLocation.Public, MaxAge = 3600)] // 1 hour, same as TimetableDataService.FetchInterval
157+
[HttpCacheValidation(MustRevalidate = false, ProxyRevalidate = true)]
155158
[ProducesResponseType(StatusCodes.Status200OK)]
156159
[ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(NotFoundError))]
157160
public async Task<ActionResult<Timetable>> GetTrainTimetable(string serverCode, string trainNoLocal)

smo-backend/Program.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
); // Maximum value most browsers support
3434
});
3535

36+
builder.Services.AddHttpCacheHeaders();
37+
3638
builder.Services.AddControllers()
3739
.AddNewtonsoftJson(options =>
3840
{

smo-backend/smo-backend.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
<ItemGroup>
1414
<PackageReference Include="EFCore.NamingConventions" Version="9.0.0" />
15+
<PackageReference Include="Marvin.Cache.Headers" Version="7.2.0" />
1516
<PackageReference Include="MessagePack" Version="3.1.4" />
1617
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="9.0.9" />
1718
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.9" />

smo-frontend/src/assets/translations.json

Lines changed: 155 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,29 @@
9595
"reduceBackgroundUpdates": {
9696
"Label": "Reduce background updates",
9797
"Description": "Reduce map update frequency when the browser tab is hidden to improve performance and reduce lag."
98+
},
99+
"stationTimetableDefaultViewMode": {
100+
"Label": "Default timetable view",
101+
"Description": "Choose how the station timetable opens by default.",
102+
"Options": {
103+
"table": "Table view",
104+
"cards": "Card view",
105+
"grouped": "Grouped view",
106+
"lastUsed": "Last used"
107+
}
98108
}
99109
},
110+
"ServerTrainList": {
111+
"Title": "All trains - {{server}}",
112+
"SearchPlaceholder": "Search trains (by number, name, type, start/end station, vehicles...)",
113+
"ButtonTooltip": "Open train list",
114+
"PlayerControlled": "Player",
115+
"AIControlled": "AI",
116+
"PanToTrain": "Pan to train",
117+
"TimetableUnavailable": "Timetable data unavailable",
118+
"EmptyState": "No trains found",
119+
"ConsistLabel": "Consist: {{summary}}"
120+
},
100121
"TrainMakerPopup": {
101122
"NextSignal": "Next Signal:",
102123
"Consist": "Consist",
@@ -289,8 +310,8 @@
289310
"To": "To",
290311
"Line": "Line",
291312
"Stop": "Stop",
292-
"PassedEarly": "(Left early)",
293-
"Delayed": "(Delayed)",
313+
"PassedEarly": "Left early",
314+
"Delayed": "Delayed",
294315
"PrevStationIsNext": {
295316
"Short": "PREV",
296317
"Full": "The next station for this train is {{stationName}}."
@@ -301,10 +322,16 @@
301322
},
302323
"InsideStation": {
303324
"Short": "HERE",
304-
"Full": "This train is currently inside the station."
325+
"Full": "This train is currently inside the station.",
326+
"ShortGlobal": "AT STATION"
305327
},
306328
"N/A": "N/A",
307-
"PanToTrain": "Go to train"
329+
"PanToTrain": "Go to train",
330+
"NextStationLabel": "Next station",
331+
"PrevStationLabel": "Previous station",
332+
"MoreTrains": "+{{count}} more train",
333+
"MoreTrains_other": "+{{count}} more trains",
334+
"BidirectionalRoute": "Bidirectional route"
308335
},
309336
"PrivacyPolicy": {
310337
"Title": "Privacy Policy",
@@ -410,8 +437,29 @@
410437
"reduceBackgroundUpdates": {
411438
"Label": "Hintergrund-Updates reduzieren",
412439
"Description": "Reduzieren Sie die Aktualisierungsfrequenz der Karte, wenn die Browser-Registerkarte ausgeblendet ist, um die Leistung zu verbessern und Verzögerungen zu reduzieren."
440+
},
441+
"stationTimetableDefaultViewMode": {
442+
"Label": "Standardfahrplanansicht",
443+
"Description": "Wählen Sie, wie der Stationsfahrplan standardmäßig geöffnet wird.",
444+
"Options": {
445+
"table": "Tabellenansicht",
446+
"cards": "Kartenansicht",
447+
"grouped": "Gruppierte Ansicht",
448+
"lastUsed": "Zuletzt verwendet"
449+
}
413450
}
414451
},
452+
"ServerTrainList": {
453+
"Title": "Alle Züge - {{server}}",
454+
"SearchPlaceholder": "Züge suchen (nach Nummer, Name, Typ, Start-/Endbahnhof, Fahrzeuge...)",
455+
"ButtonTooltip": "Zugliste öffnen",
456+
"PlayerControlled": "Spieler",
457+
"AIControlled": "KI",
458+
"PanToTrain": "Zum Zug springen",
459+
"TimetableUnavailable": "Fahrplandaten nicht verfügbar",
460+
"EmptyState": "Keine Züge gefunden",
461+
"ConsistLabel": "Zuggarnitur: {{summary}}"
462+
},
415463
"TrainMakerPopup": {
416464
"NextSignal": "Nächstes Signal:",
417465
"Consist": "Zuggarnitur",
@@ -605,8 +653,8 @@
605653
"To": "Nach",
606654
"Line": "Linie",
607655
"Stop": "Halt",
608-
"PassedEarly": "(Zu früh)",
609-
"Delayed": "(Verspätet)",
656+
"PassedEarly": "Zu früh",
657+
"Delayed": "Verspätet",
610658
"PrevStationIsNext": {
611659
"Short": "ZUV",
612660
"Full": "Die nächste Station für diesen Zug ist {{stationName}}."
@@ -617,10 +665,16 @@
617665
},
618666
"InsideStation": {
619667
"Short": "HIER",
620-
"Full": "Dieser Zug befindet sich derzeit im Bahnhof."
668+
"Full": "Dieser Zug befindet sich derzeit im Bahnhof.",
669+
"ShortGlobal": "IM BAHNHOF"
621670
},
622671
"N/A": "k.A.",
623-
"PanToTrain": "Zum Zug gehen"
672+
"PanToTrain": "Zum Zug gehen",
673+
"NextStationLabel": "Nächste Station",
674+
"PrevStationLabel": "Vorherige Station",
675+
"MoreTrains": "+{{count}} weiterer Zug",
676+
"MoreTrains_other": "+{{count}} weitere Züge",
677+
"BidirectionalRoute": "Bidirektionale Route"
624678
},
625679
"PrivacyPolicy": {
626680
"Title": "Datenschutzrichtlinie",
@@ -726,8 +780,29 @@
726780
"reduceBackgroundUpdates": {
727781
"Label": "Háttérben történő frissítések csökkentése",
728782
"Description": "Csökkentse a térkép frissítési gyakoriságát, amikor a böngésző lap rejtve van, a teljesítmény javítása és a késleltetés csökkentése érdekében."
783+
},
784+
"stationTimetableDefaultViewMode": {
785+
"Label": "Alapértelmezett menetrend nézet",
786+
"Description": "Válaszd ki, hogyan jelenjen meg alapból az állomási menetrend.",
787+
"Options": {
788+
"table": "Táblázatos nézet",
789+
"cards": "Kártyanézet",
790+
"grouped": "Csoportosított nézet",
791+
"lastUsed": "Utoljára használt"
792+
}
729793
}
730794
},
795+
"ServerTrainList": {
796+
"Title": "Összes vonat - {{server}}",
797+
"SearchPlaceholder": "Vonatok keresése (szám, név, típus, induló/érkező állomás, járművek szerint...)",
798+
"ButtonTooltip": "Vonatlista megnyitása",
799+
"PlayerControlled": "Játékos",
800+
"AIControlled": "AI",
801+
"PanToTrain": "Ugrás a vonatra",
802+
"TimetableUnavailable": "Menetrendi adat nem érhető el",
803+
"EmptyState": "Nem található vonat",
804+
"ConsistLabel": "Vonatösszeállítás: {{summary}}"
805+
},
731806
"TrainMakerPopup": {
732807
"NextSignal": "Következő jelző:",
733808
"Consist": "Vonatösszeállítás",
@@ -925,8 +1000,8 @@
9251000
"To": "Hova",
9261001
"Line": "Vonal",
9271002
"Stop": "Várakozás",
928-
"PassedEarly": "(Elhaladt)",
929-
"Delayed": "(Késik)",
1003+
"PassedEarly": "Elhaladt",
1004+
"Delayed": "Késik",
9301005
"PrevStationIsNext": {
9311006
"Short": "ELŐZŐ",
9321007
"Full": "A következő állomás: {{stationName}}."
@@ -937,10 +1012,16 @@
9371012
},
9381013
"InsideStation": {
9391014
"Short": "ITT",
940-
"Full": "Ez a vonat jelenleg az állomáson tartózkodik."
1015+
"Full": "Ez a vonat jelenleg az állomáson tartózkodik.",
1016+
"ShortGlobal": "ÁLLOMÁSON"
9411017
},
9421018
"N/A": "n/a",
943-
"PanToTrain": "Vonathoz navigálás"
1019+
"PanToTrain": "Vonathoz navigálás",
1020+
"NextStationLabel": "Következő állomás",
1021+
"PrevStationLabel": "Előző állomás",
1022+
"MoreTrains": "+{{count}} további vonat",
1023+
"MoreTrains_other": "+{{count}} további vonat",
1024+
"BidirectionalRoute": "Kétirányú útvonal"
9441025
},
9451026
"PrivacyPolicy": {
9461027
"Title": "Adatvédelmi irányelvek",
@@ -1046,8 +1127,29 @@
10461127
"reduceBackgroundUpdates": {
10471128
"Label": "Arka plan güncellemelerini azalt",
10481129
"Description": "Tarayıcı sekmesi gizlendiğinde harita güncelleme sıklığını azaltarak performansı artırır ve gecikmeyi azaltır."
1130+
},
1131+
"stationTimetableDefaultViewMode": {
1132+
"Label": "Varsayılan zaman çizelgesi görünümü",
1133+
"Description": "İstasyon zaman çizelgesi varsayılan olarak nasıl açılsın?",
1134+
"Options": {
1135+
"table": "Tablo görünümü",
1136+
"cards": "Kart görünümü",
1137+
"grouped": "Gruplandırılmış görünüm",
1138+
"lastUsed": "Son kullanılan"
1139+
}
10491140
}
10501141
},
1142+
"ServerTrainList": {
1143+
"Title": "Tüm trenler - {{server}}",
1144+
"SearchPlaceholder": "Tren arayın (numara, ad, tür, kalkış/varış istasyonu, araçlar...)",
1145+
"ButtonTooltip": "Tren listesini aç",
1146+
"PlayerControlled": "Oyuncu",
1147+
"AIControlled": "Yapay zeka",
1148+
"PanToTrain": "Trene git",
1149+
"TimetableUnavailable": "Sefer verisi mevcut değil",
1150+
"EmptyState": "Tren bulunamadı",
1151+
"ConsistLabel": "Tren yapısı: {{summary}}"
1152+
},
10511153
"TrainMakerPopup": {
10521154
"NextSignal": "Bir Sonraki Sinyal:",
10531155
"Consist": "Tren Yapısı (Motor ve Vagonlar)",
@@ -1243,8 +1345,8 @@
12431345
"To": "Nereye",
12441346
"Line": "Hat",
12451347
"Stop": "Durur",
1246-
"PassedEarly": "(Erken)",
1247-
"Delayed": "(Gecikme)",
1348+
"PassedEarly": "Erken",
1349+
"Delayed": "Gecikme",
12481350
"PrevStationIsNext": {
12491351
"Short": "ÖNC",
12501352
"Full": "Bu trenin bir sonraki durağı {{stationName}}."
@@ -1255,10 +1357,16 @@
12551357
},
12561358
"InsideStation": {
12571359
"Short": "İÇERİ",
1258-
"Full": "Bu tren şu anda istasyonda."
1360+
"Full": "Bu tren şu anda istasyonda.",
1361+
"ShortGlobal": "İSTASYON"
12591362
},
12601363
"N/A": "n/a",
1261-
"PanToTrain": "Trene git"
1364+
"PanToTrain": "Trene git",
1365+
"NextStationLabel": "Sonraki İstasyon",
1366+
"PrevStationLabel": "Önceki İstasyon",
1367+
"MoreTrains": "+{{count}} tren daha",
1368+
"MoreTrains_other": "+{{count}} tren daha",
1369+
"BidirectionalRoute": "Çift yönlü rota"
12621370
},
12631371
"PrivacyPolicy": {
12641372
"Title": "Gizlilik Politikası",
@@ -1364,8 +1472,29 @@
13641472
"reduceBackgroundUpdates": {
13651473
"Label": "Ogranicz aktualizacje w tle",
13661474
"Description": "Zmniejsz częstotliwość aktualizacji mapy, gdy karta przeglądarki jest ukryta, aby poprawić wydajność i zmniejszyć opóźnienia."
1475+
},
1476+
"stationTimetableDefaultViewMode": {
1477+
"Label": "Domyślny widok rozkładu",
1478+
"Description": "Wybierz, jak domyślnie otwierać rozkład stacji.",
1479+
"Options": {
1480+
"table": "Widok tabeli",
1481+
"cards": "Widok kart",
1482+
"grouped": "Widok grupowany",
1483+
"lastUsed": "Ostatnio używany"
1484+
}
13671485
}
13681486
},
1487+
"ServerTrainList": {
1488+
"Title": "Wszystkie pociągi - {{server}}",
1489+
"SearchPlaceholder": "Szukaj pociągów (po numerze, nazwie, typie, stacji początkowej/końcowej, pojazdach...)",
1490+
"ButtonTooltip": "Otwórz listę pociągów",
1491+
"PlayerControlled": "Gracz",
1492+
"AIControlled": "SI",
1493+
"PanToTrain": "Przejdź do pociągu",
1494+
"TimetableUnavailable": "Brak danych rozkładu jazdy",
1495+
"EmptyState": "Nie znaleziono pociągów",
1496+
"ConsistLabel": "Skład: {{summary}}"
1497+
},
13691498
"TrainMakerPopup": {
13701499
"NextSignal": "Następny Sygnał:",
13711500
"Consist": "Skład",
@@ -1558,8 +1687,8 @@
15581687
"To": "Do",
15591688
"Line": "Linia",
15601689
"Stop": "Postój",
1561-
"PassedEarly": "(Za wcześnie)",
1562-
"Delayed": "(Opóźniony)",
1690+
"PassedEarly": "Za wcześnie",
1691+
"Delayed": "Opóźniony",
15631692
"PrevStationIsNext": {
15641693
"Short": "POP",
15651694
"Full": "Następna stacja to {{stationName}}."
@@ -1570,10 +1699,16 @@
15701699
},
15711700
"InsideStation": {
15721701
"Short": "W STACJI",
1573-
"Full": "Pociąg znajduje się w stacji."
1702+
"Full": "Pociąg znajduje się w stacji.",
1703+
"ShortGlobal": "STACJA"
15741704
},
15751705
"N/A": "n/d",
1576-
"PanToTrain": "Przejdź do pociągu"
1706+
"PanToTrain": "Przejdź do pociągu",
1707+
"NextStationLabel": "Następna Stacja",
1708+
"PrevStationLabel": "Poprzednia Stacja",
1709+
"MoreTrains": "+{{count}} pociąg więcej",
1710+
"MoreTrains_other": "+{{count}} pociągów więcej",
1711+
"BidirectionalRoute": "Trasa dwukierunkowa"
15771712
},
15781713
"PrivacyPolicy": {
15791714
"Title": "Polityka Prywatności",

0 commit comments

Comments
 (0)