ctucx.git: trainsearch

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

commit f951410ab5ff2b846ed7eb478718583f1467f9ad
parent fb46f86ab273a99008c5cddacd3971b64181b892
Author: Katja (ctucx) <git@ctu.cx>
Date: Sun, 2 Feb 2025 23:01:36 +0100

journeyView: add share/copy function
4 files changed, 131 insertions(+), 0 deletions(-)
A
nginx.conf
|
99
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
M
src/assets/icons.css
|
7
+++++++
M
src/journeyView.js
|
21
+++++++++++++++++++++
M
src/languages.js
|
4
++++
diff --git a/nginx.conf b/nginx.conf
@@ -0,0 +1,99 @@
+daemon off;
+worker_processes  1;
+
+pid /tmp/nginx.pid;
+
+error_log /dev/stdout debug;
+
+events {
+    use epoll;
+    worker_connections  128;
+}
+
+http {
+	server_tokens off;
+	charset       utf-8;
+
+	map $vendotarget $vendopath {
+		default   no;
+		locations  '/mob/location/search';
+		'location' '/mob/location/details';
+		journeys   '/mob/angebote/fahrplan';
+		journey    '/mob/angebote/recon';
+		departures '/mob/bahnhofstafel/abfahrt';
+		trip       '/mob/zuglauf';
+	}
+
+	map $hafastarget $hafasurl {
+		default no;
+		nahsh   nah.sh.hafas.de;
+		rmv     www.rmv.de;
+		vrn     vrn.hafas.de;
+		bvg     bvg-apps-ext.hafas.de;
+		oebb    fahrplan.oebb.at;
+	}
+
+	map $hafastarget $hafaspath {
+		default no;
+		nahsh   '/bin/mgate.exe';
+		rmv     '/auskunft/bin/jp/mgate.exe';
+		vrn     '/bin/mgate.exe';
+		bvg     '/bin/mgate.exe';
+		oebb    '/bin/mgate.exe';
+	}
+
+	server {
+		server_name   localhost;
+		listen        127.0.0.1:1234;
+
+		access_log /dev/stdout;
+
+		location /db/vehicle-sequence {
+			resolver 8.8.8.8;
+			proxy_ssl_server_name on;
+			proxy_ssl_name www.bahn.de;
+			proxy_set_header Host www.bahn.de;
+			proxy_pass https://www.bahn.de/web/api/reisebegleitung/wagenreihung/vehicle-sequence$is_args$args;
+		}
+
+
+		location ~ ^/db/vendo/(?<vendotarget>[a-z]+)(/([^\r\n].*))?$ {
+			set $vendodomain 'app.vendo.noncd.db.de';
+
+			add_header x-input $1.$2 always;
+
+			if ($vendopath = no) {
+				return 400;
+			}
+
+			if ($vendotarget = 'trip') {
+				set $vendopath '$vendopath$2';
+			}
+
+			if ($vendotarget = 'location') {
+				set $vendopath '$vendopath$2';
+			}
+
+			add_header x-target https://$vendodomain$vendopath always;
+
+			resolver 8.8.8.8; 
+			proxy_ssl_server_name on;
+			proxy_ssl_name $vendodomain;
+			proxy_set_header Host $vendodomain;
+			proxy_pass https://$vendodomain$vendopath;
+		}
+
+		location ~ ^/hafas/(?<hafastarget>.*)$ {
+			if ($hafasurl = no) {
+				return 400;
+			}
+
+			resolver 8.8.8.8;
+			proxy_ssl_server_name on;
+			proxy_ssl_name $hafasurl;
+			proxy_set_header Host $hafasurl;
+			proxy_pass https://$hafasurl$hafaspath;
+		}
+	}
+
+}
diff --git a/src/assets/icons.css b/src/assets/icons.css
@@ -74,3 +74,10 @@
 	content: url('data:image/svg+xml;utf8,<svg version="1.1" viewBox="0 0 24 24" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m11 5v14h2v-14zm-4-2v14h2v-14zm10 4h-2v14h2z" fill="white"/></svg>');
 }
 
+.icon-dots {
+	content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="24" width="24"><path d="M12 16a2 2 0 0 1 2 2 2 2 0 0 1-2 2 2 2 0 0 1-2-2 2 2 0 0 1 2-2m0-6a2 2 0 0 1 2 2 2 2 0 0 1-2 2 2 2 0 0 1-2-2 2 2 0 0 1 2-2m0-6a2 2 0 0 1 2 2 2 2 0 0 1-2 2 2 2 0 0 1-2-2 2 2 0 0 1 2-2" fill="white"/></svg>');
+}
+
+.icon-share {
+	content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="24" width="24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91s2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08" fill="white"/></svg>');
+}
diff --git a/src/journeyView.js b/src/journeyView.js
@@ -9,6 +9,7 @@ import { showAlertModal, showLoader, hideOverlay, showModal } from './overlays.j
 import { go } from './router.js';
 import { t } from './languages.js';
 import { db } from './dataStorage.js';
+import { showSelectModal } from './overlays.js';
 
 const legTemplate = (leg, profile) => {
 	const remarks        = leg.remarks || [];

@@ -129,6 +130,7 @@ const journeyTemplate = (data, profile) => {
 			<header>
 				${data.slug ? html`<a class="icon-back" href="#/${data.slug}/${settings.journeysViewMode}" title="${t('back')}"></a>` : nothing}
 				<div class="container">
+					<a class="icon-dots" title="${t("more")}" @click=${() => moreOverlay()}></a>
 					<h3>${formatName(data.legs[0].origin)} → ${formatName(data.legs[data.legs.length - 1].destination)}</h3>
 					<p><b>${t('duration')}: ${formatDuration(duration)} | ${t('changes')}: ${changes-1} | ${t('date')}: ${formatDateTime(data.legs[0].plannedDeparture, 'date')}${settings.showPrices && settings.profile === 'db' && data.price ? html` | ${t('price')}: <td><span>${formatPrice(data.price)}</span></td>` : nothing}</b></p>
 				</div>

@@ -197,3 +199,21 @@ const refreshJourneyView = async (refreshToken, profile) => {
 	journeyView([profile, refreshToken], true);
 	document.querySelector('.icon-reload').classList.remove('spinning');
 };
+
+const moreOverlay = () => {
+	const options = [
+		{ 'label': !navigator.canShare ? t('copyURL') : t('shareURL'), 'action': () => { shareAction(); hideOverlay(); }},
+	];
+
+	showSelectModal(options);
+};
+
+const shareAction = async () => {
+	try {
+		await navigator.share({
+			url: window.location,
+		});
+	} catch (error) {
+		navigator.clipboard.writeText(window.location);
+	}
+};+
\ No newline at end of file
diff --git a/src/languages.js b/src/languages.js
@@ -106,6 +106,8 @@ const languages = {
 		'walkingSpeedSlow':    'langsam',
 		'walkingSpeedNormal':  'normal',
 		'walkingSpeedFast':    'schnell',
+		'shareURL':            'Link teilen',
+		'copyURL':             'Link kopieren',
 	},
 
 	'nl': {

@@ -252,5 +254,7 @@ const languages = {
 		'walkingSpeedSlow':    'slow',
 		'walkingSpeedNormal':  'normal',
 		'walkingSpeedFast':    'fast',
+		'shareURL':            'Share URL',
+		'copyURL':             'Copy URL',
 	}
 };