ctucx.git: trainsearch

web based trip-planner, fork of https://cyberchaos.dev/yuka/trainsearch

commit cd75b5f0a8f6cfeb04b1dc9809a96a8e108a403b
parent 6287fea466b5227140d46f06ef3fec26a0522dbf
Author: Yureka <yuka@yuka.dev>
Date: Tue, 28 May 2024 12:42:20 +0200

deduplicate some code & fix crashes
5 files changed, 63 insertions(+), 112 deletions(-)
M
src/canvas.js
|
5
++---
M
src/departuresView.js
|
21
---------------------
M
src/helpers.js
|
47
+++++++++++++++++++++++++++++++++++++++++++++++
M
src/journeyView.js
|
46
++++------------------------------------------
M
src/tripView.js
|
56
++++++++++----------------------------------------------
diff --git a/src/canvas.js b/src/canvas.js
@@ -1,13 +1,12 @@
 import { moreJourneys } from './journeysView.js';
 import { go } from './router.js';
-import { padZeros, formatTrainTypes } from './helpers.js';
+import { padZeros, formatTrainTypes, lineDisplayName } from './helpers.js';
 import { cachedCoachSequence, coachSequenceCache, coachSequenceCacheKey } from './reihung';
 
 const formatTime = (date) => {
 	return `${padZeros(date.getHours())}:${padZeros(date.getMinutes())}`;
 };
 
-const textFor = (leg) => leg.line && leg.line.name || '';
 const colorFor = (leg, type) => {
 	const product = leg.line?.product || 'walk';
 	return colors[type][product] || colors[type].default;

@@ -277,7 +276,7 @@ const renderJourneys = () => {
 			}
 			//ctx.shadowBlur = 0;
 
-			let preRenderedText = getTextCache(textFor(leg), colorFor(leg, 'text'));
+			let preRenderedText = getTextCache(lineDisplayName(leg.line), colorFor(leg, 'text'));
 			let offset = duration / 2;
 			if ((offset + preRenderedText.height / dpr) < duration - 5) {
 				ctx.scale(1 / dpr, 1 / dpr);
diff --git a/src/departuresView.js b/src/departuresView.js
@@ -6,27 +6,6 @@ import { go } from './router.js';
 import { html, render } from 'lit-html';
 import { getHafasClient, client } from './hafas_client';
 
-const remarksModalTemplate = (type, remarks) => html`
-	<table class="remarks">
-		${remarks.map(element => html`
-			<tr>
-			<td>
-				<span class="remark icon-${type}"></span>
-				<span>${element.text}</span>
-			</td>
-			</tr>
-		`)}
-	</table>
-`;
-
-const getAdditionalName = (line) => {
-	const splitName = line.name.split(' ');
-	if (splitName.length === 2 && line.fahrtNr && line.fahrtNr != splitName[1])
-		return `${splitName[0]} ${line.fahrtNr}`;
-	else
-		return null;
-};
-
 const departuresTemplate = (data, profile) => {
 	let changes = 0;
 	let lastArrival;
diff --git a/src/helpers.js b/src/helpers.js
@@ -1,3 +1,6 @@
+import { html } from 'lit-html';
+import { settings } from './settings.js';
+
 export const ElementById = (id) => {
 	return document.getElementById(id);
 };

@@ -123,3 +126,47 @@ export const formatTrainTypes = info => {
 		return text;
 	}).join(" + ");
 };
+
+export const lineAdditionalName = (line) => {
+	if (!line.name) return null;
+	const splitName = line.name.split(' ');
+	if (splitName.length === 2 && line.fahrtNr && line.fahrtNr != splitName[1])
+		return `${splitName[0]} ${line.fahrtNr}`;
+	else
+		return null;
+};
+export const lineDisplayName = (line) => {
+	return line?.name || line?.operator?.name || "???";
+};
+export const remarksModalTemplate = (type, remarks) => html`
+	<table class="remarks">
+		${remarks.map(element => html`
+			<tr>
+			<td>
+				<span class="remark icon-${type}"></span>
+				<span>${element.text}</span>
+			</td>
+			</tr>
+		`)}
+	</table>
+`;
+
+export const travelynxTemplate = (element) => {
+	if (settings.travelynx && element.line && element.line.mode === 'train') {
+		const trainName = lineAdditionalName(element.line) || element.line?.name;
+
+		if (trainName) {
+			return html`
+				<a class="link icon-travelynx" href="https://travelynx.de/s/${element.origin.id}?train=${encodeURIComponent(trainName)}"></a>
+			`;
+		}
+	}
+};
+
+export const showRemarksModal = (type, remarks) => {
+	showModal(t('remarks'), remarksModalTemplate(type, remarks));
+};
+export const remarksTemplate = ([type, remarks]) => !!remarks.length ? html`
+	<a class="link icon-${type}" @click=${() => showRemarksModal(type, remarks)}></a>
+` : '';
+
diff --git a/src/journeyView.js b/src/journeyView.js
@@ -1,49 +1,11 @@
 import { cachedCoachSequence, coachSequenceCache, coachSequenceCacheKey } from './reihung';
 import { settings } from './settings.js';
-import { showDiv, hideDiv, ElementById, formatDateTime, formatDuration, formatPrice, formatTrainTypes } from './helpers.js';
+import { showDiv, hideDiv, ElementById, formatDateTime, formatDuration, formatPrice, formatTrainTypes, lineAdditionalName, lineDisplayName, remarksTemplate, travelynxTemplate } from './helpers.js';
 import { ConsoleLog, parseName, t, timeTemplate, getJourney, refreshJourney, platformTemplate, stopTemplate } from './app_functions.js';
 import { showAlertModal, showLoader, hideOverlay, showModal } from './overlays.js';
 import { go } from './router.js';
 import { html, render } from 'lit-html';
 
-const remarksModalTemplate = (type, remarks) => html`
-	<table class="remarks">
-		${remarks.map(element => html`
-			<tr>
-			<td>
-				<span class="remark icon-${type}"></span>
-				<span>${element.text}</span>
-			</td>
-			</tr>
-		`)}
-	</table>
-`;
-
-const getAdditionalName = (line) => {
-	const splitName = line.name.split(' ');
-	if (splitName.length === 2 && line.fahrtNr && line.fahrtNr != splitName[1])
-		return `${splitName[0]} ${line.fahrtNr}`;
-	else
-		return null;
-};
-
-const travelynxTemplate = (element) => {
-	if (settings.travelynx && element.line && element.line.mode === 'train') {
-		const trainName = getAdditionalName(element.line) || element.line.name;
-
-		return html`
-			<a class="link icon-travelynx" href="https://travelynx.de/s/${element.origin.id}?train=${encodeURIComponent(trainName)}"></a>
-		`;
-	}
-};
-
-const showRemarksModal = (type, remarks) => {
-	showModal(t('remarks'), remarksModalTemplate(type, remarks));
-};
-const remarksTemplate = ([type, remarks]) => !!remarks.length ? html`
-	<a class="link icon-${type}" @click=${() => showRemarksModal(type, remarks)}></a>
-` : '';
-
 const legTemplate = (leg, profile) => {
 	const allRemarks = leg.remarks || [];
 	const remarks = {

@@ -65,7 +27,7 @@ const legTemplate = (leg, profile) => {
 				<thead>
 					<tr>
 						<td colspan="4">
-							<span><a href="#/t/${profile}/${leg.tripId}">${leg.line.name}${leg.direction ? html` → ${leg.direction}` : ''}</a>
+							<span><a href="#/t/${profile}/${leg.tripId}">${lineDisplayName(leg.line)}${leg.direction ? html` → ${leg.direction}` : ''}</a>
 							${leg.cancelled ? html`<b class="cancelled-text">${t('cancelled-ride')}</b>` : ''}
 							${Object.entries(remarks).map(remarksTemplate)}
 							${travelynxTemplate(leg)}</span>

@@ -74,9 +36,9 @@ const legTemplate = (leg, profile) => {
 					<tr>
 						<td colspan="4">
 							<div class="train-details">
-								${getAdditionalName(leg.line) ? html`
+								${lineAdditionalName(leg.line) ? html`
 									<div class="train-detail">
-										Trip: ${getAdditionalName(leg.line)}
+										Trip: ${lineAdditionalName(leg.line)}
 									</div>
 								` : ''}
 								${leg.line.trainType ? html`
diff --git a/src/tripView.js b/src/tripView.js
@@ -1,50 +1,11 @@
 import { settings } from './settings.js';
-import { showDiv, hideDiv, ElementById, formatDateTime, formatDuration, formatPrice } from './helpers.js';
+import { showDiv, hideDiv, ElementById, formatDateTime, formatDuration, formatPrice, remarksTemplate, travelynxTemplate, lineAdditionalName, lineDisplayName } from './helpers.js';
 import { ConsoleLog, parseName, t, timeTemplate, processLeg, platformTemplate, stopTemplate } from './app_functions.js';
 import { showAlertModal, showLoader, hideOverlay, showModal } from './overlays.js';
 import { go } from './router.js';
 import { html, render } from 'lit-html';
 import { getHafasClient, client } from './hafas_client';
 
-const remarksModalTemplate = (type, remarks) => html`
-	<table class="remarks">
-		${remarks.map(element => html`
-			<tr>
-			<td>
-				<span class="remark icon-${type}"></span>
-				<span>${element.text}</span>
-			</td>
-			</tr>
-		`)}
-	</table>
-`;
-
-const getAdditionalName = (line) => {
-	if (!line) return null;
-	const splitName = line.name.split(' ');
-	if (splitName.length === 2 && line.fahrtNr && line.fahrtNr != splitName[1])
-		return `${splitName[0]} ${line.fahrtNr}`;
-	else
-		return null;
-};
-
-const travelynxTemplate = (element) => {
-	if (settings.travelynx && element.line && element.line.mode === 'train') {
-		const trainName = getAdditionalName(element.line) || element.line.name;
-
-		return html`
-			<a class="link icon-travelynx" href="https://travelynx.de/s/${element.origin.id}?train=${encodeURIComponent(trainName)}"></a>
-		`;
-	}
-};
-
-const showRemarksModal = (type, remarks) => {
-	showModal(t('remarks'), remarksModalTemplate(type, remarks));
-};
-const remarksTemplate = ([type, remarks]) => !!remarks.length ? html`
-	<a class="link icon-${type}" @click=${() => showRemarksModal(type, remarks)}></a>
-` : '';
-
 const tripTemplate = (data, profile) => {
 	let changes = 0;
 	let lastArrival;

@@ -58,7 +19,10 @@ const tripTemplate = (data, profile) => {
 
 	let bahnExpertUrl = null;
 	if (data.line && (data.line.product == 'nationalExpress' || data.line.product == 'national' || data.line.product == 'regionalExpress' || data.line.product == 'regional')) {
-		bahnExpertUrl = 'https://bahn.expert/details/' + encodeURIComponent(getAdditionalName(data.line) || data.line.name) + '/' + Number(data.plannedDeparture);
+		const trainName = lineAdditionalName(data.line) || data.line?.name;
+		if (trainName) {
+			bahnExpertUrl = 'https://bahn.expert/details/' + encodeURIComponent(trainName) + '/' + Number(data.plannedDeparture);
+		}
 	}
 
 					//<p>b>${t('duration')}: ${formatDuration(duration)} | ${t('changes')}: ${changes-1} | ${t('date')}: ${formatDateTime(data.plannedDeparture, 'date')}${settings.showPrices && data.price ? html` | ${t('price')}: <td><span>${formatPrice(data.price)}</span></td>` : ''}</b></p>

@@ -67,7 +31,7 @@ const tripTemplate = (data, profile) => {
 			<header>
 				<a class="back icon-back invisible"></a>
 				<div class="header-content">
-					<h3>Trip of ${data.line.name}</h3>
+					<h3>Trip of ${lineDisplayName(data.line)}</h3>
 				</div>
 				<a class="reload icon-reload invisible">${t("reload")}</a>
 			</header>

@@ -78,9 +42,9 @@ const tripTemplate = (data, profile) => {
 					<tr>
 						<td colspan="4">
 							<span>${bahnExpertUrl ? html`
-								<a href="${bahnExpertUrl}">${data.line.name}${data.direction ? html` → ${data.direction}` : ''}</a>
+								<a href="${bahnExpertUrl}">${lineDisplayName(line)}${data.direction ? html` → ${data.direction}` : ''}</a>
 							` : html `
-								${data.line.name}${data.direction ? html` → ${data.direction}` : ''}
+								${lineDisplayName(data.line)}${data.direction ? html` → ${data.direction}` : ''}
 							`}
 							${data.cancelled ? html`<b class="cancelled-text">${t('cancelled-ride')}</b>` : ''}
 							${Object.entries(remarks).map(remarksTemplate)}

@@ -90,9 +54,9 @@ const tripTemplate = (data, profile) => {
 					<tr>
 						<td colspan="4">
 							<div class="train-details">
-								${getAdditionalName(data.line) ? html`
+								${lineAdditionalName(data.line) ? html`
 									<div class="train-detail">
-										Trip: ${getAdditionalName(data.line)}
+										Trip: ${lineAdditionalName(data.line)}
 									</div>
 								` : ''}
 								${data.line.trainType ? html`