mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2025-10-14 11:38:18 +00:00
progress
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
<script lang="ts">
|
||||
import '../app.pcss';
|
||||
import '../app.css';
|
||||
import { ModeWatcher } from 'mode-watcher';
|
||||
import { _, locale, isLoadingInitialLocale, isLoadingLocale } from '$lib/i18n';
|
||||
import { i18n } from '$lib/i18n.svelte';
|
||||
import { page } from '$app/state';
|
||||
import Nav from '$lib/components/Nav.svelte';
|
||||
import Footer from '$lib/components/Footer.svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import { onMount, type Snippet } from 'svelte';
|
||||
import { convertOldEmbeddingOptions } from '$lib/components/embedding/Embedding';
|
||||
import { base } from '$app/paths';
|
||||
import { languages } from '$lib/languages';
|
||||
@@ -13,9 +13,15 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { getURLForLanguage } from '$lib/utils';
|
||||
|
||||
export let data: {
|
||||
guideTitles: Record<string, string>;
|
||||
};
|
||||
let {
|
||||
data,
|
||||
children,
|
||||
}: {
|
||||
data: {
|
||||
guideTitles: Record<string, string>;
|
||||
};
|
||||
children: Snippet;
|
||||
} = $props();
|
||||
|
||||
const appRoutes = ['/[[language]]/app', '/[[language]]/embed'];
|
||||
|
||||
@@ -29,41 +35,46 @@
|
||||
}
|
||||
});
|
||||
|
||||
$: if (page.route.id?.includes('[[language]]')) {
|
||||
if (page.params.language) {
|
||||
let lang = page.params.language.replace('/', '');
|
||||
if ($locale !== lang) {
|
||||
if (languages.hasOwnProperty(lang)) {
|
||||
$locale = lang;
|
||||
} else if (browser) {
|
||||
goto(`${base}/404`);
|
||||
$effect(() => {
|
||||
if (page.route.id?.includes('[[language]]')) {
|
||||
if (page.params.language) {
|
||||
let lang = page.params.language.replace('/', '');
|
||||
if (i18n.lang !== lang) {
|
||||
if (languages.hasOwnProperty(lang)) {
|
||||
i18n.lang = lang;
|
||||
} else if (browser) {
|
||||
goto(`${base}/404`);
|
||||
}
|
||||
}
|
||||
} else if (i18n.lang !== 'en') {
|
||||
i18n.lang = 'en';
|
||||
}
|
||||
} else if ($locale !== 'en') {
|
||||
$locale = 'en';
|
||||
} else if (i18n.lang === '') {
|
||||
i18n.lang = 'en';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$: if (browser && !$isLoadingLocale && $locale) {
|
||||
let title = `gpx.studio — ${$_(`metadata.${page.route.id?.replace('/[[language]]', '').split('/')[1] ?? 'home'}_title`)}`;
|
||||
$effect(() => {
|
||||
let title = `gpx.studio — ${i18n._(`metadata.${page.route.id?.replace('/[[language]]', '').split('/')[1] ?? 'home'}_title`)}`;
|
||||
if (page.params.guide) {
|
||||
document.title = `${title} | ${data.guideTitles[page.params.guide]}`;
|
||||
} else {
|
||||
document.title = title;
|
||||
}
|
||||
}
|
||||
$: showNavAndFooter = page.route.id === null || !appRoutes.includes(page.route.id);
|
||||
});
|
||||
|
||||
let showNavAndFooter = $derived(page.route.id === null || !appRoutes.includes(page.route.id));
|
||||
</script>
|
||||
|
||||
<ModeWatcher />
|
||||
|
||||
<div class="flex flex-col min-h-screen">
|
||||
{#if !$isLoadingInitialLocale}
|
||||
{#if !i18n.isLoadingInitial}
|
||||
{#if showNavAndFooter}
|
||||
<Nav />
|
||||
{/if}
|
||||
<main class="grow flex flex-col">
|
||||
<slot />
|
||||
{@render children()}
|
||||
</main>
|
||||
{#if showNavAndFooter}
|
||||
<Footer />
|
||||
|
@@ -2,35 +2,35 @@
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import Logo from '$lib/components/Logo.svelte';
|
||||
import { getURLForLanguage } from '$lib/utils';
|
||||
import { Home, Map, BookOpenText } from 'lucide-svelte';
|
||||
import { _, locale } from '$lib/i18n';
|
||||
import { Home, Map, BookOpenText } from '@lucide/svelte';
|
||||
import { i18n } from '$lib/i18n.svelte';
|
||||
</script>
|
||||
|
||||
<div class="grow px-12 my-12 flex flex-col items-center justify-center gap-6">
|
||||
<p class="text-7xl font-black">404</p>
|
||||
<p class="text-xl -mt-6">{$_('page_not_found')}</p>
|
||||
<p class="text-xl -mt-6">{i18n._('page_not_found')}</p>
|
||||
<Logo class="h-40 my-3 animate-spin" style="animation-duration: 20000ms" iconOnly={true} />
|
||||
<div class="w-full flex flex-row flex-wrap gap-3 justify-center">
|
||||
<Button
|
||||
href={getURLForLanguage($locale, '/')}
|
||||
href={getURLForLanguage(i18n.lang, '/')}
|
||||
class="text-base w-1/4 min-w-fit rounded-full"
|
||||
>
|
||||
<Home size="18" class="mr-1.5" />
|
||||
{$_('homepage.home')}
|
||||
<Home size="18" />
|
||||
{i18n._('homepage.home')}
|
||||
</Button>
|
||||
<Button
|
||||
href={getURLForLanguage($locale, '/app')}
|
||||
href={getURLForLanguage(i18n.lang, '/app')}
|
||||
class="text-base w-1/4 min-w-fit rounded-full"
|
||||
>
|
||||
<Map size="18" class="mr-1.5" />
|
||||
{$_('homepage.app')}
|
||||
<Map size="18" />
|
||||
{i18n._('homepage.app')}
|
||||
</Button>
|
||||
<Button
|
||||
href={getURLForLanguage($locale, '/help')}
|
||||
href={getURLForLanguage(i18n.lang, '/help')}
|
||||
class="text-base w-1/4 min-w-fit rounded-full"
|
||||
>
|
||||
<BookOpenText size="18" class="mr-1.5" />
|
||||
<span>{$_('menu.help')}</span>
|
||||
<BookOpenText size="18" />
|
||||
<span>{i18n._('menu.help')}</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -2,9 +2,9 @@
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import DocsContainer from '$lib/components/docs/DocsContainer.svelte';
|
||||
import Logo from '$lib/components/Logo.svelte';
|
||||
import ElevationProfile from '$lib/components/ElevationProfile.svelte';
|
||||
import GPXStatistics from '$lib/components/GPXStatistics.svelte';
|
||||
import Routing from '$lib/components/toolbar/tools/routing/Routing.svelte';
|
||||
// import ElevationProfile from '$lib/components/ElevationProfile.svelte';
|
||||
// import GPXStatistics from '$lib/components/GPXStatistics.svelte';
|
||||
// import Routing from '$lib/components/toolbar/tools/routing/Routing.svelte';
|
||||
import {
|
||||
BookOpenText,
|
||||
Heart,
|
||||
@@ -14,35 +14,43 @@
|
||||
PenLine,
|
||||
Route,
|
||||
Scale,
|
||||
} from 'lucide-svelte';
|
||||
import { _, locale } from '$lib/i18n';
|
||||
} from '@lucide/svelte';
|
||||
import { i18n } from '$lib/i18n.svelte';
|
||||
import { getURLForLanguage } from '$lib/utils';
|
||||
import { exampleGPXFile } from '$lib/assets/example';
|
||||
import { writable } from 'svelte/store';
|
||||
import Toolbar from '$lib/components/toolbar/Toolbar.svelte';
|
||||
import { currentTool, Tool } from '$lib/stores';
|
||||
// import Toolbar from '$lib/components/toolbar/Toolbar.svelte';
|
||||
// import { tool, Tool } from '$lib/components/toolbar/utils.svelte';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
|
||||
export let data: {
|
||||
fundingModule: any;
|
||||
translationModule: any;
|
||||
mapboxModule: any;
|
||||
};
|
||||
let {
|
||||
data,
|
||||
}: {
|
||||
data: {
|
||||
fundingModule: Promise<any>;
|
||||
translationModule: Promise<any>;
|
||||
mapboxModule: Promise<any>;
|
||||
};
|
||||
} = $props();
|
||||
|
||||
let gpxStatistics = writable(exampleGPXFile.getStatistics());
|
||||
let slicedGPXStatistics = writable(undefined);
|
||||
let additionalDatasets = writable(['speed', 'atemp']);
|
||||
let elevationFill = writable<'slope' | 'surface' | undefined>(undefined);
|
||||
|
||||
onMount(() => {
|
||||
$currentTool = Tool.SCISSORS;
|
||||
});
|
||||
// onMount(() => {
|
||||
// tool.current = Tool.SCISSORS;
|
||||
// });
|
||||
|
||||
$: $currentTool, ($currentTool = Tool.SCISSORS);
|
||||
// $effect(() => {
|
||||
// if (tool.current !== Tool.SCISSORS) {
|
||||
// tool.current = Tool.SCISSORS;
|
||||
// }
|
||||
// });
|
||||
|
||||
onDestroy(() => {
|
||||
$currentTool = null;
|
||||
});
|
||||
// onDestroy(() => {
|
||||
// tool.current = null;
|
||||
// });
|
||||
</script>
|
||||
|
||||
<div class="space-y-24 my-24">
|
||||
@@ -50,23 +58,23 @@
|
||||
<div class="px-12 w-full flex flex-col items-center">
|
||||
<div class="flex flex-col gap-6 items-center max-w-3xl">
|
||||
<h1 class="text-4xl sm:text-6xl font-black text-center">
|
||||
{$_('metadata.home_title')}
|
||||
{i18n._('metadata.home_title')}
|
||||
</h1>
|
||||
<div class="text-lg sm:text-xl text-muted-foreground text-center">
|
||||
{$_('metadata.description')}
|
||||
{i18n._('metadata.description')}
|
||||
</div>
|
||||
<div class="w-full flex flex-row justify-center gap-3">
|
||||
<Button href={getURLForLanguage($locale, '/app')} class="w-1/3 min-w-fit">
|
||||
<Button href={getURLForLanguage(i18n.lang, '/app')} class="w-1/3 min-w-fit">
|
||||
<Map size="18" class="mr-1.5" />
|
||||
{$_('homepage.app')}
|
||||
{i18n._('homepage.app')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
href={getURLForLanguage($locale, '/help')}
|
||||
href={getURLForLanguage(i18n.lang, '/help')}
|
||||
class="w-1/3 min-w-fit"
|
||||
>
|
||||
<BookOpenText size="18" class="mr-1.5" />
|
||||
<span>{$_('menu.help')}</span>
|
||||
<span>{i18n._('menu.help')}</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -89,12 +97,12 @@
|
||||
<div class="markdown text-center">
|
||||
<h1>
|
||||
<Route size="24" class="mr-1 inline-block align-baseline" />
|
||||
{$_('homepage.route_planning')}
|
||||
{i18n._('homepage.route_planning')}
|
||||
</h1>
|
||||
<p class="text-muted-foreground">{$_('homepage.route_planning_description')}</p>
|
||||
<p class="text-muted-foreground">{i18n._('homepage.route_planning_description')}</p>
|
||||
</div>
|
||||
<div class="p-3 w-fit rounded-md border shadow-xl md:shrink-0">
|
||||
<Routing minimizable={false} />
|
||||
<!-- <Routing minimizable={false} /> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -105,19 +113,23 @@
|
||||
<div class="markdown text-center md:hidden">
|
||||
<h1>
|
||||
<PencilRuler size="24" class="mr-1 inline-block align-baseline" />
|
||||
{$_('homepage.file_processing')}
|
||||
{i18n._('homepage.file_processing')}
|
||||
</h1>
|
||||
<p class="text-muted-foreground">{$_('homepage.file_processing_description')}</p>
|
||||
<p class="text-muted-foreground">
|
||||
{i18n._('homepage.file_processing_description')}
|
||||
</p>
|
||||
</div>
|
||||
<div class="relative md:shrink-0 max-w-[400px]">
|
||||
<Toolbar />
|
||||
<!-- <Toolbar /> -->
|
||||
</div>
|
||||
<div class="markdown text-center hidden md:block">
|
||||
<h1>
|
||||
<PencilRuler size="24" class="mr-1 inline-block align-baseline" />
|
||||
{$_('homepage.file_processing')}
|
||||
{i18n._('homepage.file_processing')}
|
||||
</h1>
|
||||
<p class="text-muted-foreground">{$_('homepage.file_processing_description')}</p>
|
||||
<p class="text-muted-foreground">
|
||||
{i18n._('homepage.file_processing_description')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -128,12 +140,12 @@
|
||||
<div class="markdown text-center">
|
||||
<h1>
|
||||
<Map size="24" class="mr-1 inline-block align-baseline" />
|
||||
{$_('homepage.maps')}
|
||||
{i18n._('homepage.maps')}
|
||||
</h1>
|
||||
<p class="text-muted-foreground">{$_('homepage.maps_description')}</p>
|
||||
<p class="text-muted-foreground">{i18n._('homepage.maps_description')}</p>
|
||||
</div>
|
||||
<div
|
||||
class="relative h-60 xs:h-80 aspect-square rounded-2xl shadow-xl overflow-hidden overflow-clip"
|
||||
class="relative w-full max-w-[320px] aspect-square rounded-2xl shadow-xl overflow-clip"
|
||||
>
|
||||
<enhanced:img
|
||||
src="/src/lib/assets/img/home/mapbox-outdoors.png"
|
||||
@@ -171,28 +183,28 @@
|
||||
<div class="markdown text-center px-4 md:px-12">
|
||||
<h1>
|
||||
<ChartArea size="24" class="mr-1 inline-block align-baseline" />
|
||||
{$_('homepage.data_visualization')}
|
||||
{i18n._('homepage.data_visualization')}
|
||||
</h1>
|
||||
<p class="text-muted-foreground mb-6">
|
||||
{$_('homepage.data_visualization_description')}
|
||||
{i18n._('homepage.data_visualization_description')}
|
||||
</p>
|
||||
</div>
|
||||
<div class="h-48 w-full">
|
||||
<ElevationProfile
|
||||
<!-- <ElevationProfile
|
||||
{gpxStatistics}
|
||||
{slicedGPXStatistics}
|
||||
additionalDatasets={$additionalDatasets}
|
||||
elevationFill={$elevationFill}
|
||||
/>
|
||||
/> -->
|
||||
</div>
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="h-10 w-fit">
|
||||
<GPXStatistics
|
||||
<!-- <GPXStatistics
|
||||
{gpxStatistics}
|
||||
{slicedGPXStatistics}
|
||||
panelSize={192}
|
||||
orientation={'horizontal'}
|
||||
/>
|
||||
/> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -203,9 +215,9 @@
|
||||
<div class="markdown text-center md:hidden">
|
||||
<h1>
|
||||
<Scale size="24" class="mr-1 inline-block align-baseline" />
|
||||
{$_('homepage.identity')}
|
||||
{i18n._('homepage.identity')}
|
||||
</h1>
|
||||
<p class="text-muted-foreground">{$_('homepage.identity_description')}</p>
|
||||
<p class="text-muted-foreground">{i18n._('homepage.identity_description')}</p>
|
||||
</div>
|
||||
<a href="https://github.com/gpxstudio/gpx.studio" target="_blank">
|
||||
<Logo class="h-32" company="github" />
|
||||
@@ -213,9 +225,9 @@
|
||||
<div class="markdown text-center hidden md:block">
|
||||
<h1>
|
||||
<Scale size="24" class="mr-1 inline-block align-baseline" />
|
||||
{$_('homepage.identity')}
|
||||
{i18n._('homepage.identity')}
|
||||
</h1>
|
||||
<p class="text-muted-foreground">{$_('homepage.identity_description')}</p>
|
||||
<p class="text-muted-foreground">{i18n._('homepage.identity_description')}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -244,7 +256,7 @@
|
||||
fill="rgb(var(--support))"
|
||||
color="rgb(var(--support))"
|
||||
/>
|
||||
<span>{$_('homepage.support_button')}</span>
|
||||
<span>{i18n._('homepage.support_button')}</span>
|
||||
</Button>
|
||||
</div>
|
||||
<div
|
||||
@@ -255,7 +267,7 @@
|
||||
{/await}
|
||||
<Button href="https://crowdin.com/project/gpxstudio" target="_blank" class="text-base">
|
||||
<PenLine size="16" class="mr-1" />
|
||||
<span>{$_('homepage.contribute')}</span>
|
||||
<span>{i18n._('homepage.contribute')}</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -267,7 +279,7 @@
|
||||
class="shrink-0 flex flex-col sm:flex-row lg:flex-col items-center gap-x-4 gap-y-2"
|
||||
>
|
||||
<div class="text-lg font-semibold text-muted-foreground">
|
||||
❤️ {$_('homepage.supported_by')}
|
||||
❤️ {i18n._('homepage.supported_by')}
|
||||
</div>
|
||||
<a href="https://www.mapbox.com/" target="_blank">
|
||||
<Logo company="mapbox" class="w-60" />
|
||||
|
@@ -1,24 +1,25 @@
|
||||
<script lang="ts">
|
||||
import GPXLayers from '$lib/components/gpx-layer/GPXLayers.svelte';
|
||||
import ElevationProfile from '$lib/components/ElevationProfile.svelte';
|
||||
import FileList from '$lib/components/file-list/FileList.svelte';
|
||||
import GPXStatistics from '$lib/components/GPXStatistics.svelte';
|
||||
import Map from '$lib/components/Map.svelte';
|
||||
import Menu from '$lib/components/Menu.svelte';
|
||||
import Toolbar from '$lib/components/toolbar/Toolbar.svelte';
|
||||
import StreetViewControl from '$lib/components/street-view-control/StreetViewControl.svelte';
|
||||
import LayerControl from '$lib/components/layer-control/LayerControl.svelte';
|
||||
import CoordinatesPopup from '$lib/components/CoordinatesPopup.svelte';
|
||||
// import GPXLayers from '$lib/components/map/gpx-layer/GPXLayers.svelte';
|
||||
// import ElevationProfile from '$lib/components/ElevationProfile.svelte';
|
||||
// import FileList from '$lib/components/file-list/FileList.svelte';
|
||||
// import GPXStatistics from '$lib/components/GPXStatistics.svelte';
|
||||
import Map from '$lib/components/map/Map.svelte';
|
||||
// import Menu from '$lib/components/Menu.svelte';
|
||||
// import Toolbar from '$lib/components/toolbar/Toolbar.svelte';
|
||||
import StreetViewControl from '$lib/components/map/street-view-control/StreetViewControl.svelte';
|
||||
import LayerControl from '$lib/components/map/layer-control/LayerControl.svelte';
|
||||
// import CoordinatesPopup from '$lib/components/map/CoordinatesPopup.svelte';
|
||||
import Resizer from '$lib/components/Resizer.svelte';
|
||||
import { Toaster } from '$lib/components/ui/sonner';
|
||||
import { observeFilesFromDatabase, settings } from '$lib/db';
|
||||
import { gpxStatistics, loadFiles, slicedGPXStatistics } from '$lib/stores';
|
||||
import { onMount } from 'svelte';
|
||||
import { page } from '$app/stores';
|
||||
// import { observeFilesFromDatabase } from '$lib/db';
|
||||
// import { gpxStatistics, loadFiles, slicedGPXStatistics } from '$lib/stores';
|
||||
// import { onMount } from 'svelte';
|
||||
// import { page } from '$app/state';
|
||||
import { languages } from '$lib/languages';
|
||||
import { getURLForLanguage } from '$lib/utils';
|
||||
import { getURLForGoogleDriveFile } from '$lib/components/embedding/Embedding';
|
||||
import { _ } from '$lib/i18n';
|
||||
// import { getURLForGoogleDriveFile } from '$lib/components/embedding/Embedding';
|
||||
import { i18n } from '$lib/i18n.svelte';
|
||||
import { settings } from '$lib/logic/settings.svelte';
|
||||
|
||||
const {
|
||||
treeFileView,
|
||||
@@ -29,116 +30,124 @@
|
||||
elevationFill,
|
||||
} = settings;
|
||||
|
||||
onMount(() => {
|
||||
let files: string[] = JSON.parse($page.url.searchParams.get('files') || '[]');
|
||||
let ids: string[] = JSON.parse($page.url.searchParams.get('ids') || '[]');
|
||||
let urls: string[] = files.concat(ids.map(getURLForGoogleDriveFile));
|
||||
// onMount(() => {
|
||||
// let files: string[] = JSON.parse(page.url.searchParams.get('files') || '[]');
|
||||
// let ids: string[] = JSON.parse(page.url.searchParams.get('ids') || '[]');
|
||||
// let urls: string[] = files.concat(ids.map(getURLForGoogleDriveFile));
|
||||
|
||||
observeFilesFromDatabase(urls.length === 0);
|
||||
// observeFilesFromDatabase(urls.length === 0);
|
||||
|
||||
if (urls.length > 0) {
|
||||
let downloads: Promise<File | null>[] = [];
|
||||
urls.forEach((url) => {
|
||||
downloads.push(
|
||||
fetch(url)
|
||||
.then((response) => response.blob())
|
||||
.then((blob) => new File([blob], url.split('/').pop()))
|
||||
);
|
||||
});
|
||||
// if (urls.length > 0) {
|
||||
// let downloads: Promise<File | null>[] = [];
|
||||
// urls.forEach((url) => {
|
||||
// downloads.push(
|
||||
// fetch(url)
|
||||
// .then((response) => response.blob())
|
||||
// .then((blob) => new File([blob], url.split('/').pop() ?? ''))
|
||||
// );
|
||||
// });
|
||||
|
||||
Promise.all(downloads).then((files) => {
|
||||
files = files.filter((file) => file !== null);
|
||||
loadFiles(files);
|
||||
});
|
||||
}
|
||||
});
|
||||
// Promise.all(downloads).then((files) => {
|
||||
// loadFiles(files.filter((file) => file !== null));
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
</script>
|
||||
|
||||
<div class="fixed -z-10 text-transparent">
|
||||
<h1>{$_('metadata.home_title')} — {$_('metadata.app_title')}</h1>
|
||||
<p>{$_('metadata.description')}</p>
|
||||
<h2>{$_('toolbar.routing.tooltip')}</h2>
|
||||
<p>{$_('toolbar.routing.help_no_file')}</p>
|
||||
<p>{$_('toolbar.routing.help')}</p>
|
||||
<h3>{$_('toolbar.routing.reverse.button')}</h3>
|
||||
<p>{$_('toolbar.routing.reverse.tooltip')}</p>
|
||||
<h3>{$_('toolbar.routing.route_back_to_start.button')}</h3>
|
||||
<p>{$_('toolbar.routing.route_back_to_start.tooltip')}</p>
|
||||
<h3>{$_('toolbar.routing.round_trip.button')}</h3>
|
||||
<p>{$_('toolbar.routing.round_trip.tooltip')}</p>
|
||||
<h3>{$_('toolbar.routing.start_loop_here')}</h3>
|
||||
<h2>{$_('toolbar.scissors.tooltip')}</h2>
|
||||
<p>{$_('toolbar.scissors.help')}</p>
|
||||
<h2>{$_('toolbar.time.tooltip')}</h2>
|
||||
<p>{$_('toolbar.time.help')}</p>
|
||||
<h2>{$_('toolbar.merge.tooltip')}</h2>
|
||||
<h3>{$_('toolbar.merge.merge_traces')}</h3>
|
||||
<p>{$_('toolbar.merge.help_merge_traces')}</p>
|
||||
<h3>{$_('toolbar.merge.merge_contents')}</h3>
|
||||
<p>{$_('toolbar.merge.help_merge_contents')}</p>
|
||||
<h2>{$_('toolbar.elevation.button')}</h2>
|
||||
<p>{$_('toolbar.elevation.help')}</p>
|
||||
<h2>{$_('toolbar.waypoint.tooltip')}</h2>
|
||||
<p>{$_('toolbar.waypoint.help')}</p>
|
||||
<h2>{$_('toolbar.reduce.tooltip')}</h2>
|
||||
<p>{$_('toolbar.reduce.help')}</p>
|
||||
<h2>{$_('toolbar.clean.tooltip')}</h2>
|
||||
<p>{$_('toolbar.clean.help')}</p>
|
||||
<h2>{$_('gpx.files')}, {$_('gpx.tracks')}, {$_('gpx.segments')}, {$_('gpx.waypoints')}</h2>
|
||||
<h1>{i18n._('metadata.home_title')} — {i18n._('metadata.app_title')}</h1>
|
||||
<p>{i18n._('metadata.description')}</p>
|
||||
<h2>{i18n._('toolbar.routing.tooltip')}</h2>
|
||||
<p>{i18n._('toolbar.routing.help_no_file')}</p>
|
||||
<p>{i18n._('toolbar.routing.help')}</p>
|
||||
<h3>{i18n._('toolbar.routing.reverse.button')}</h3>
|
||||
<p>{i18n._('toolbar.routing.reverse.tooltip')}</p>
|
||||
<h3>{i18n._('toolbar.routing.route_back_to_start.button')}</h3>
|
||||
<p>{i18n._('toolbar.routing.route_back_to_start.tooltip')}</p>
|
||||
<h3>{i18n._('toolbar.routing.round_trip.button')}</h3>
|
||||
<p>{i18n._('toolbar.routing.round_trip.tooltip')}</p>
|
||||
<h3>{i18n._('toolbar.routing.start_loop_here')}</h3>
|
||||
<h2>{i18n._('toolbar.scissors.tooltip')}</h2>
|
||||
<p>{i18n._('toolbar.scissors.help')}</p>
|
||||
<h2>{i18n._('toolbar.time.tooltip')}</h2>
|
||||
<p>{i18n._('toolbar.time.help')}</p>
|
||||
<h2>{i18n._('toolbar.merge.tooltip')}</h2>
|
||||
<h3>{i18n._('toolbar.merge.merge_traces')}</h3>
|
||||
<p>{i18n._('toolbar.merge.help_merge_traces')}</p>
|
||||
<h3>{i18n._('toolbar.merge.merge_contents')}</h3>
|
||||
<p>{i18n._('toolbar.merge.help_merge_contents')}</p>
|
||||
<h2>{i18n._('toolbar.elevation.button')}</h2>
|
||||
<p>{i18n._('toolbar.elevation.help')}</p>
|
||||
<h2>{i18n._('toolbar.waypoint.tooltip')}</h2>
|
||||
<p>{i18n._('toolbar.waypoint.help')}</p>
|
||||
<h2>{i18n._('toolbar.reduce.tooltip')}</h2>
|
||||
<p>{i18n._('toolbar.reduce.help')}</p>
|
||||
<h2>{i18n._('toolbar.clean.tooltip')}</h2>
|
||||
<p>{i18n._('toolbar.clean.help')}</p>
|
||||
<h2>
|
||||
{i18n._('gpx.files')}, {i18n._('gpx.tracks')}, {i18n._('gpx.segments')}, {i18n._(
|
||||
'gpx.waypoints'
|
||||
)}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="fixed flex flex-row w-screen h-screen supports-dvh:h-dvh">
|
||||
<div class="flex flex-col grow h-full min-w-0">
|
||||
<div class="grow relative">
|
||||
<Menu />
|
||||
<!-- <Menu /> -->
|
||||
<div
|
||||
class="absolute top-0 bottom-0 left-0 z-20 flex flex-col justify-center pointer-events-none"
|
||||
>
|
||||
<Toolbar />
|
||||
<!-- <Toolbar /> -->
|
||||
</div>
|
||||
<Map class="h-full {$treeFileView ? '' : 'horizontal'}" />
|
||||
<Map class="h-full {treeFileView.value ? '' : 'horizontal'}" />
|
||||
<StreetViewControl />
|
||||
<LayerControl />
|
||||
<GPXLayers />
|
||||
<CoordinatesPopup />
|
||||
<!-- <GPXLayers /> -->
|
||||
<!-- <CoordinatesPopup /> -->
|
||||
<Toaster richColors />
|
||||
{#if !$treeFileView}
|
||||
<!-- {#if !treeFileView.value}
|
||||
<div class="h-10 -translate-y-10 w-full pointer-events-none absolute z-30">
|
||||
<FileList orientation="horizontal" />
|
||||
</div>
|
||||
{/if}
|
||||
{/if} -->
|
||||
</div>
|
||||
{#if $elevationProfile}
|
||||
{#if elevationProfile.value}
|
||||
<Resizer
|
||||
orientation="row"
|
||||
bind:after={$bottomPanelSize}
|
||||
bind:after={bottomPanelSize.value}
|
||||
minAfter={100}
|
||||
maxAfter={300}
|
||||
/>
|
||||
{/if}
|
||||
<div
|
||||
class="{$elevationProfile ? '' : 'h-10'} flex flex-row gap-2 px-2 sm:px-4"
|
||||
style={$elevationProfile ? `height: ${$bottomPanelSize}px` : ''}
|
||||
class="{elevationProfile.value ? '' : 'h-10'} flex flex-row gap-2 px-2 sm:px-4"
|
||||
style={elevationProfile.value ? `height: ${bottomPanelSize.value}px` : ''}
|
||||
>
|
||||
<GPXStatistics
|
||||
<!-- <GPXStatistics
|
||||
{gpxStatistics}
|
||||
{slicedGPXStatistics}
|
||||
panelSize={$bottomPanelSize}
|
||||
orientation={$elevationProfile ? 'vertical' : 'horizontal'}
|
||||
/>
|
||||
{#if $elevationProfile}
|
||||
/> -->
|
||||
<!-- {#if $elevationProfile}
|
||||
<ElevationProfile
|
||||
{gpxStatistics}
|
||||
{slicedGPXStatistics}
|
||||
bind:additionalDatasets={$additionalDatasets}
|
||||
bind:elevationFill={$elevationFill}
|
||||
/>
|
||||
{/if}
|
||||
{/if} -->
|
||||
</div>
|
||||
</div>
|
||||
{#if $treeFileView}
|
||||
<Resizer orientation="col" bind:after={$rightPanelSize} minAfter={100} maxAfter={400} />
|
||||
<FileList orientation="vertical" recursive={true} style="width: {$rightPanelSize}px" />
|
||||
{#if treeFileView.value}
|
||||
<Resizer
|
||||
orientation="col"
|
||||
bind:after={rightPanelSize.value}
|
||||
minAfter={100}
|
||||
maxAfter={400}
|
||||
/>
|
||||
<!-- <FileList orientation="vertical" recursive={true} style="width: {$rightPanelSize}px" /> -->
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -152,6 +161,8 @@
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
@reference "tailwindcss";
|
||||
|
||||
div :global(.toaster.group) {
|
||||
@apply absolute;
|
||||
@apply right-2;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { page } from '$app/state';
|
||||
import { onMount } from 'svelte';
|
||||
import Embedding from '$lib/components/embedding/Embedding.svelte';
|
||||
// import Embedding from '$lib/components/embedding/Embedding.svelte';
|
||||
import {
|
||||
getMergedEmbeddingOptions,
|
||||
type EmbeddingOptions,
|
||||
@@ -10,7 +10,7 @@
|
||||
let embeddingOptions: EmbeddingOptions | undefined = undefined;
|
||||
|
||||
onMount(() => {
|
||||
let options = $page.url.searchParams.get('options');
|
||||
let options = page.url.searchParams.get('options');
|
||||
if (options === null) {
|
||||
return;
|
||||
}
|
||||
@@ -23,5 +23,5 @@
|
||||
</script>
|
||||
|
||||
{#if embeddingOptions}
|
||||
<Embedding options={embeddingOptions} hash={$page.url.hash} />
|
||||
<!-- <Embedding options={embeddingOptions} hash={$page.url.hash} /> -->
|
||||
{/if}
|
||||
|
@@ -1,13 +1,20 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { getURLForLanguage } from '$lib/utils';
|
||||
import { locale } from '$lib/i18n';
|
||||
import { page } from '$app/stores';
|
||||
import { i18n } from '$lib/i18n.svelte';
|
||||
import { page } from '$app/state';
|
||||
import { guides } from '$lib/components/docs/docs';
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
export let data: {
|
||||
guideTitles: Record<string, string>;
|
||||
};
|
||||
let {
|
||||
data,
|
||||
children,
|
||||
}: {
|
||||
data: {
|
||||
guideTitles: Record<string, string>;
|
||||
};
|
||||
children: Snippet;
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<div class="grow px-12 pt-6 pb-12 flex flex-row gap-24">
|
||||
@@ -17,8 +24,8 @@
|
||||
{#each Object.keys(guides) as guide}
|
||||
<Button
|
||||
variant="link"
|
||||
href={getURLForLanguage($locale, `/help/${guide}`)}
|
||||
class="min-h-5 h-fit p-0 w-fit text-muted-foreground hover:text-foreground hover:no-underline font-normal hover:font-semibold items-start whitespace-normal {$page
|
||||
href={getURLForLanguage(i18n.lang, `/help/${guide}`)}
|
||||
class="min-h-5 h-fit p-0 w-fit text-muted-foreground hover:text-foreground hover:no-underline font-normal hover:font-semibold items-start whitespace-normal {page
|
||||
.params.guide === guide
|
||||
? 'font-semibold text-foreground'
|
||||
: ''}"
|
||||
@@ -28,8 +35,8 @@
|
||||
{#each guides[guide] as subGuide}
|
||||
<Button
|
||||
variant="link"
|
||||
href={getURLForLanguage($locale, `/help/${guide}/${subGuide}`)}
|
||||
class="min-h-5 h-fit p-0 w-fit text-muted-foreground hover:text-foreground hover:no-underline font-normal hover:font-semibold items-start whitespace-normal ml-3 {$page
|
||||
href={getURLForLanguage(i18n.lang, `/help/${guide}/${subGuide}`)}
|
||||
class="min-h-5 h-fit p-0 w-fit text-muted-foreground hover:text-foreground hover:no-underline font-normal hover:font-semibold items-start whitespace-normal ml-3 {page
|
||||
.params.guide ===
|
||||
guide + '/' + subGuide
|
||||
? 'font-semibold text-foreground'
|
||||
@@ -41,6 +48,6 @@
|
||||
{/each}
|
||||
</div>
|
||||
<div class="grow">
|
||||
<slot />
|
||||
{@render children()}
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,19 +1,23 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { getURLForLanguage } from '$lib/utils';
|
||||
import { locale } from '$lib/i18n';
|
||||
import { i18n } from '$lib/i18n.svelte';
|
||||
import { guides, guideIcons } from '$lib/components/docs/docs';
|
||||
|
||||
export let data: {
|
||||
guideTitles: Record<string, string>;
|
||||
};
|
||||
let {
|
||||
data,
|
||||
}: {
|
||||
data: {
|
||||
guideTitles: Record<string, string>;
|
||||
};
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
||||
{#each Object.keys(guides) as guide}
|
||||
<Button
|
||||
variant="outline"
|
||||
href={getURLForLanguage($locale, `/help/${guide}`)}
|
||||
href={getURLForLanguage(i18n.lang, `/help/${guide}`)}
|
||||
class="min-h-36 h-full pt-6 pb-3 px-0"
|
||||
>
|
||||
<div class="flex flex-col w-full">
|
||||
@@ -27,14 +31,15 @@
|
||||
{#each guides[guide] as subGuide}
|
||||
<Button
|
||||
variant="link"
|
||||
href={getURLForLanguage($locale, `/help/${guide}/${subGuide}`)}
|
||||
href={getURLForLanguage(i18n.lang, `/help/${guide}/${subGuide}`)}
|
||||
class="min-h-8 h-fit min-w-24 px-0 py-1 text-muted-foreground text-base text-center whitespace-normal"
|
||||
>
|
||||
<svelte:component
|
||||
this={guideIcons[subGuide]}
|
||||
size="16"
|
||||
class="mr-1 shrink-0"
|
||||
/>
|
||||
{#if typeof guideIcons[subGuide] === 'string'}
|
||||
{guideIcons[subGuide]}
|
||||
{:else}
|
||||
{@const GuideIcon = guideIcons[subGuide]}
|
||||
<GuideIcon size="16" class="mr-1 shrink-0" />
|
||||
{/if}
|
||||
{data.guideTitles[`${guide}/${subGuide}`]}
|
||||
</Button>
|
||||
{/each}
|
||||
|
@@ -1,19 +1,16 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { page } from '$app/state';
|
||||
import { getNextGuide, getPreviousGuide } from '$lib/components/docs/docs';
|
||||
import DocsContainer from '$lib/components/docs/DocsContainer.svelte';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { getURLForLanguage } from '$lib/utils';
|
||||
import { ChevronLeft, ChevronRight, PenLine, CornerDownRight } from 'lucide-svelte';
|
||||
import { _, locale } from '$lib/i18n';
|
||||
import { ChevronLeft, ChevronRight, PenLine, CornerDownRight } from '@lucide/svelte';
|
||||
import { i18n } from '$lib/i18n.svelte';
|
||||
|
||||
export let data: {
|
||||
guideModule: any;
|
||||
guideTitles: Record<string, string>;
|
||||
};
|
||||
let { data }: { data: { guideModule: any; guideTitles: Record<string, string> } } = $props();
|
||||
|
||||
$: previousGuide = getPreviousGuide($page.params.guide);
|
||||
$: nextGuide = getNextGuide($page.params.guide);
|
||||
let previousGuide = $derived(getPreviousGuide(page.params.guide));
|
||||
let nextGuide = $derived(getNextGuide(page.params.guide));
|
||||
</script>
|
||||
|
||||
<div class="markdown flex flex-col gap-3">
|
||||
@@ -25,9 +22,9 @@
|
||||
<Button
|
||||
variant="outline"
|
||||
class="mr-auto"
|
||||
href={getURLForLanguage($locale, `/help/${previousGuide}`)}
|
||||
href={getURLForLanguage(i18n.lang, `/help/${previousGuide}`)}
|
||||
>
|
||||
<ChevronLeft size="14" class="mr-1 mt-0.5" />
|
||||
<ChevronLeft size="14" class="mt-0.5" />
|
||||
{data.guideTitles[previousGuide]}
|
||||
</Button>
|
||||
{/if}
|
||||
@@ -35,47 +32,47 @@
|
||||
<Button
|
||||
variant="outline"
|
||||
class="ml-auto"
|
||||
href={getURLForLanguage($locale, `/help/${nextGuide}`)}
|
||||
href={getURLForLanguage(i18n.lang, `/help/${nextGuide}`)}
|
||||
>
|
||||
{data.guideTitles[nextGuide]}
|
||||
<ChevronRight size="14" class="ml-1 mt-0.5" />
|
||||
<ChevronRight size="14" class="mt-0.5" />
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row flex-wrap justify-between items-start mt-10 gap-3">
|
||||
<div class="flex flex-col items-start">
|
||||
<p class="text-sm text-muted-foreground">{$_('docs.answer_not_found')}</p>
|
||||
<p class="text-sm text-muted-foreground">{i18n._('docs.answer_not_found')}</p>
|
||||
<Button
|
||||
variant="link"
|
||||
href="https://www.reddit.com/r/gpxstudio/"
|
||||
target="_blank"
|
||||
class="p-0 h-6 text-link"
|
||||
>
|
||||
<CornerDownRight size="16" class="mr-1" />
|
||||
{$_('docs.ask_on_reddit')}
|
||||
<CornerDownRight size="16" />
|
||||
{i18n._('docs.ask_on_reddit')}
|
||||
</Button>
|
||||
</div>
|
||||
{#if $locale === 'en'}
|
||||
{#if i18n.lang === 'en'}
|
||||
<Button
|
||||
variant="link"
|
||||
href="https://github.com/gpxstudio/gpx.studio/edit/dev/website/src/lib/docs/en/{$page
|
||||
href="https://github.com/gpxstudio/gpx.studio/edit/dev/website/src/lib/docs/en/{page
|
||||
.params.guide}.mdx"
|
||||
target="_blank"
|
||||
class="p-0 h-6 ml-auto text-link"
|
||||
>
|
||||
<PenLine size="16" class="mr-1" />
|
||||
<PenLine size="16" />
|
||||
Edit this page on GitHub
|
||||
</Button>
|
||||
{:else}
|
||||
<Button
|
||||
variant="link"
|
||||
href="https://crowdin.com/project/gpxstudio/{$locale}"
|
||||
href="https://crowdin.com/project/gpxstudio/{i18n.lang}"
|
||||
target="_blank"
|
||||
class="p-0 h-6 ml-auto text-link"
|
||||
>
|
||||
<PenLine size="16" class="mr-1" />
|
||||
{$_('docs.translate')}
|
||||
<PenLine size="16" />
|
||||
{i18n._('docs.translate')}
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user