mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2025-08-30 23:30:04 +00:00
add faq section
This commit is contained in:
@@ -1,112 +1,112 @@
|
||||
<script lang="ts">
|
||||
import { browser } from '$app/environment';
|
||||
import { goto } from '$app/navigation';
|
||||
import { base } from '$app/paths';
|
||||
import { _, locale } from 'svelte-i18n';
|
||||
import { browser } from '$app/environment';
|
||||
import { goto } from '$app/navigation';
|
||||
import { base } from '$app/paths';
|
||||
import { _, locale } from 'svelte-i18n';
|
||||
|
||||
export let path: string;
|
||||
export let titleOnly: boolean = false;
|
||||
export let path: string;
|
||||
export let titleOnly: boolean = false;
|
||||
|
||||
let module = undefined;
|
||||
let metadata: Record<string, any> = {};
|
||||
let module = undefined;
|
||||
let metadata: Record<string, any> = {};
|
||||
|
||||
const modules = import.meta.glob('/src/lib/docs/**/*.mdx');
|
||||
const modules = import.meta.glob('/src/lib/docs/**/*.mdx');
|
||||
|
||||
function loadModule(path: string) {
|
||||
modules[path]?.().then((mod) => {
|
||||
module = mod.default;
|
||||
metadata = mod.metadata;
|
||||
});
|
||||
}
|
||||
function loadModule(path: string) {
|
||||
modules[path]?.().then((mod) => {
|
||||
module = mod.default;
|
||||
metadata = mod.metadata;
|
||||
});
|
||||
}
|
||||
|
||||
$: if ($locale) {
|
||||
if (modules.hasOwnProperty(`/src/lib/docs/${$locale}/${path}`)) {
|
||||
loadModule(`/src/lib/docs/${$locale}/${path}`);
|
||||
} else if (browser) {
|
||||
goto(`${base}/404`);
|
||||
}
|
||||
}
|
||||
$: if ($locale) {
|
||||
if (modules.hasOwnProperty(`/src/lib/docs/${$locale}/${path}`)) {
|
||||
loadModule(`/src/lib/docs/${$locale}/${path}`);
|
||||
} else if (browser) {
|
||||
goto(`${base}/404`);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if module !== undefined}
|
||||
{#if titleOnly}
|
||||
{metadata.title}
|
||||
{:else}
|
||||
<div class="markdown flex flex-col gap-3">
|
||||
<svelte:component this={module} />
|
||||
</div>
|
||||
{/if}
|
||||
{#if titleOnly}
|
||||
{metadata.title}
|
||||
{:else}
|
||||
<div class="markdown flex flex-col gap-3">
|
||||
<svelte:component this={module} />
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<style lang="postcss">
|
||||
:global(.markdown) {
|
||||
@apply text-muted-foreground;
|
||||
}
|
||||
:global(.markdown) {
|
||||
@apply text-muted-foreground;
|
||||
}
|
||||
|
||||
:global(.markdown h1) {
|
||||
@apply text-foreground;
|
||||
@apply text-3xl;
|
||||
@apply font-semibold;
|
||||
@apply mb-3 pt-6;
|
||||
}
|
||||
:global(.markdown h1) {
|
||||
@apply text-foreground;
|
||||
@apply text-3xl;
|
||||
@apply font-semibold;
|
||||
@apply mb-3 pt-6;
|
||||
}
|
||||
|
||||
:global(.markdown h2) {
|
||||
@apply text-foreground;
|
||||
@apply text-2xl;
|
||||
@apply font-semibold;
|
||||
@apply pt-3;
|
||||
}
|
||||
:global(.markdown h2) {
|
||||
@apply text-foreground;
|
||||
@apply text-2xl;
|
||||
@apply font-semibold;
|
||||
@apply pt-3;
|
||||
}
|
||||
|
||||
:global(.markdown h3) {
|
||||
@apply text-foreground;
|
||||
@apply text-lg;
|
||||
@apply font-semibold;
|
||||
@apply pt-1.5;
|
||||
}
|
||||
:global(.markdown h3) {
|
||||
@apply text-foreground;
|
||||
@apply text-lg;
|
||||
@apply font-semibold;
|
||||
@apply pt-1.5;
|
||||
}
|
||||
|
||||
:global(.markdown p > button) {
|
||||
@apply border;
|
||||
@apply rounded-md;
|
||||
@apply px-1;
|
||||
}
|
||||
:global(.markdown p > button, .markdown li > button) {
|
||||
@apply border;
|
||||
@apply rounded-md;
|
||||
@apply px-1;
|
||||
}
|
||||
|
||||
:global(.markdown > a) {
|
||||
@apply text-blue-500;
|
||||
@apply hover:underline;
|
||||
}
|
||||
:global(.markdown > a) {
|
||||
@apply text-blue-500;
|
||||
@apply hover:underline;
|
||||
}
|
||||
|
||||
:global(.markdown p > a) {
|
||||
@apply text-blue-500;
|
||||
@apply hover:underline;
|
||||
}
|
||||
:global(.markdown p > a) {
|
||||
@apply text-blue-500;
|
||||
@apply hover:underline;
|
||||
}
|
||||
|
||||
:global(.markdown li > a) {
|
||||
@apply text-blue-500;
|
||||
@apply hover:underline;
|
||||
}
|
||||
:global(.markdown li > a) {
|
||||
@apply text-blue-500;
|
||||
@apply hover:underline;
|
||||
}
|
||||
|
||||
:global(.markdown kbd) {
|
||||
@apply p-1;
|
||||
@apply rounded-md;
|
||||
@apply border;
|
||||
}
|
||||
:global(.markdown kbd) {
|
||||
@apply p-1;
|
||||
@apply rounded-md;
|
||||
@apply border;
|
||||
}
|
||||
|
||||
:global(.markdown ul) {
|
||||
@apply list-disc;
|
||||
@apply pl-4;
|
||||
}
|
||||
:global(.markdown ul) {
|
||||
@apply list-disc;
|
||||
@apply pl-4;
|
||||
}
|
||||
|
||||
:global(.markdown ol) {
|
||||
@apply list-decimal;
|
||||
@apply pl-4;
|
||||
}
|
||||
:global(.markdown ol) {
|
||||
@apply list-decimal;
|
||||
@apply pl-4;
|
||||
}
|
||||
|
||||
:global(.markdown li) {
|
||||
@apply mt-1;
|
||||
@apply first:mt-0;
|
||||
}
|
||||
:global(.markdown li) {
|
||||
@apply mt-1;
|
||||
@apply first:mt-0;
|
||||
}
|
||||
|
||||
:global(.markdown hr) {
|
||||
@apply my-5;
|
||||
}
|
||||
:global(.markdown hr) {
|
||||
@apply my-5;
|
||||
}
|
||||
</style>
|
||||
|
@@ -9,6 +9,7 @@ export const guides: Record<string, string[]> = {
|
||||
'map-controls': [],
|
||||
'gpx': [],
|
||||
'integration': [],
|
||||
'faq': [],
|
||||
};
|
||||
|
||||
export const guideIcons: Record<string, string | ComponentType<Icon>> = {
|
||||
@@ -31,6 +32,7 @@ export const guideIcons: Record<string, string | ComponentType<Icon>> = {
|
||||
"map-controls": "🗺",
|
||||
"gpx": "💾",
|
||||
"integration": "{ 👩💻 }",
|
||||
"faq": "🔮",
|
||||
};
|
||||
|
||||
export function getPreviousGuide(currentGuide: string): string | undefined {
|
||||
|
39
website/src/lib/docs/en/faq.mdx
Normal file
39
website/src/lib/docs/en/faq.mdx
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
title: FAQ
|
||||
---
|
||||
|
||||
<script>
|
||||
import DocsNote from '$lib/components/docs/DocsNote.svelte';
|
||||
</script>
|
||||
|
||||
# { title }
|
||||
|
||||
### Do I need to donate to use the website?
|
||||
|
||||
No, you don't need to donate to use the website or unlock any features.
|
||||
The website is free to use and always will be (as long as it is financially sustainable).
|
||||
However, donations are appreciated and help keep the website running.
|
||||
|
||||
### Why is this route chosen over that one? *Or* how can I add something to the map?
|
||||
|
||||
**gpx.studio** uses data from <a href="https://www.openstreetmap.org/" target="_blank">OpenStreetMap</a>, which is a crowd-sourced map of the world.
|
||||
This means you can contribute to the map by adding or editing data on OpenStreetMap.
|
||||
|
||||
If you have never used OpenStreetMap before, you can:
|
||||
1. Go to the location where you want to add or edit data on the <a href="https://www.openstreetmap.org/" target="_blank">map</a>.
|
||||
2. Use the <button>Query features</button> tool on the right to inspect the existing data.
|
||||
3. Right-click on the location and select <button>Add a note here</button>.
|
||||
4. Explain what is incorrect or missing in the note and click <button>Add note</button> to submit it.
|
||||
|
||||
Someone more experienced with OpenStreetMap will then review your note and take the necessary action.
|
||||
|
||||
<DocsNote>
|
||||
|
||||
More information on how to contribute to OpenStreetMap can be found <a href="https://wiki.openstreetmap.org/wiki/How_to_contribute" target="_blank">here</a>.
|
||||
|
||||
</DocsNote>
|
||||
|
||||
### Why is the elevation profile for my GPX file empty?
|
||||
|
||||
If the elevation profile for your GPX file is empty, it means that the GPX file does not contain elevation data.
|
||||
You can add elevation data to your GPX file by using <a href="https://www.gpsvisualizer.com/elevation" target="_blank">GPS Visualizer</a>.
|
@@ -1,62 +1,63 @@
|
||||
<script lang="ts">
|
||||
import '../app.pcss';
|
||||
import { ModeWatcher } from 'mode-watcher';
|
||||
import { isLoading, _, locale } from 'svelte-i18n';
|
||||
import { page } from '$app/stores';
|
||||
import Nav from '$lib/components/Nav.svelte';
|
||||
import Footer from '$lib/components/Footer.svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import { convertOldEmbeddingOptions } from '$lib/components/embedding/Embedding';
|
||||
import { base } from '$app/paths';
|
||||
import { languages } from '$lib/languages';
|
||||
import { browser } from '$app/environment';
|
||||
import { goto } from '$app/navigation';
|
||||
import { getURLForLanguage } from '$lib/utils';
|
||||
import '../app.pcss';
|
||||
import { ModeWatcher } from 'mode-watcher';
|
||||
import { isLoading, _, locale } from 'svelte-i18n';
|
||||
import { page } from '$app/stores';
|
||||
import Nav from '$lib/components/Nav.svelte';
|
||||
import Footer from '$lib/components/Footer.svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import { convertOldEmbeddingOptions } from '$lib/components/embedding/Embedding';
|
||||
import { base } from '$app/paths';
|
||||
import { languages } from '$lib/languages';
|
||||
import { browser } from '$app/environment';
|
||||
import { goto } from '$app/navigation';
|
||||
import { getURLForLanguage } from '$lib/utils';
|
||||
|
||||
const appRoutes = ['/[[language]]/app', '/[[language]]/embed'];
|
||||
const appRoutes = ['/[[language]]/app', '/[[language]]/embed'];
|
||||
|
||||
onMount(() => {
|
||||
if ($page.url.searchParams.has('embed')) {
|
||||
// convert old embedding options to new format and redirect to new embed page
|
||||
let folders = $page.url.pathname.split('/');
|
||||
let locale = folders.indexOf('l') >= 0 ? folders[folders.indexOf('l') + 1] ?? 'en' : 'en';
|
||||
window.location.href = `${getURLForLanguage(locale, '/embed')}?options=${encodeURIComponent(JSON.stringify(convertOldEmbeddingOptions($page.url.searchParams)))}`;
|
||||
}
|
||||
});
|
||||
onMount(() => {
|
||||
if ($page.url.searchParams.has('embed')) {
|
||||
// convert old embedding options to new format and redirect to new embed page
|
||||
let folders = $page.url.pathname.split('/');
|
||||
let locale =
|
||||
folders.indexOf('l') >= 0 ? folders[folders.indexOf('l') + 1] ?? 'en' : 'en';
|
||||
window.location.href = `${getURLForLanguage(locale, '/embed')}?options=${encodeURIComponent(JSON.stringify(convertOldEmbeddingOptions($page.url.searchParams)))}`;
|
||||
}
|
||||
});
|
||||
|
||||
$: if ($page.params.language) {
|
||||
if ($page.params.language === '' && $locale !== 'en') {
|
||||
locale.set('en');
|
||||
} else if ($page.params.language) {
|
||||
let lang = $page.params.language.replace('/', '');
|
||||
if ($locale !== lang) {
|
||||
if (languages.hasOwnProperty(lang)) {
|
||||
locale.set(lang);
|
||||
} else if (browser) {
|
||||
goto(`${base}/404`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$: if ($page.route.id.includes('[[language]]')) {
|
||||
if ($page.params.language) {
|
||||
let lang = $page.params.language.replace('/', '');
|
||||
if ($locale !== lang) {
|
||||
if (languages.hasOwnProperty(lang)) {
|
||||
locale.set(lang);
|
||||
} else if (browser) {
|
||||
goto(`${base}/404`);
|
||||
}
|
||||
}
|
||||
} else if ($locale !== 'en') {
|
||||
locale.set('en');
|
||||
}
|
||||
}
|
||||
|
||||
$: if (browser && !$isLoading && $_) {
|
||||
document.title = `gpx.studio — ${$_(`metadata.${$page.route.id?.replace('/[[language]]', '').split('/')[1] ?? 'home'}_title`)}`;
|
||||
}
|
||||
$: showNavAndFooter = $page.route.id === null || !appRoutes.includes($page.route.id);
|
||||
$: if (browser && !$isLoading && $_) {
|
||||
document.title = `gpx.studio — ${$_(`metadata.${$page.route.id?.replace('/[[language]]', '').split('/')[1] ?? 'home'}_title`)}`;
|
||||
}
|
||||
$: showNavAndFooter = $page.route.id === null || !appRoutes.includes($page.route.id);
|
||||
</script>
|
||||
|
||||
<ModeWatcher />
|
||||
|
||||
<div class="flex flex-col min-h-screen">
|
||||
{#if !$isLoading}
|
||||
{#if showNavAndFooter}
|
||||
<Nav />
|
||||
{/if}
|
||||
<main class="grow flex flex-col">
|
||||
<slot />
|
||||
</main>
|
||||
{#if showNavAndFooter}
|
||||
<Footer />
|
||||
{/if}
|
||||
{/if}
|
||||
{#if !$isLoading}
|
||||
{#if showNavAndFooter}
|
||||
<Nav />
|
||||
{/if}
|
||||
<main class="grow flex flex-col">
|
||||
<slot />
|
||||
</main>
|
||||
{#if showNavAndFooter}
|
||||
<Footer />
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
|
@@ -1,41 +1,43 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { getURLForLanguage } from '$lib/utils';
|
||||
import { locale } from 'svelte-i18n';
|
||||
import DocsLoader from '$lib/components/docs/DocsLoader.svelte';
|
||||
import { page } from '$app/stores';
|
||||
import { guides } from '$lib/components/docs/docs';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { getURLForLanguage } from '$lib/utils';
|
||||
import { locale } from 'svelte-i18n';
|
||||
import DocsLoader from '$lib/components/docs/DocsLoader.svelte';
|
||||
import { page } from '$app/stores';
|
||||
import { guides } from '$lib/components/docs/docs';
|
||||
</script>
|
||||
|
||||
<div class="px-12 pt-6 pb-12 flex flex-row gap-24">
|
||||
<div class="hidden md:flex flex-col gap-2 w-40 sticky top-[108px] self-start shrink-0">
|
||||
{#each Object.keys(guides) as guide}
|
||||
<Button
|
||||
variant="link"
|
||||
href={getURLForLanguage($locale, `/help/${guide}`)}
|
||||
class="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'
|
||||
: ''}"
|
||||
>
|
||||
<DocsLoader path={`${guide}.mdx`} titleOnly={true} />
|
||||
</Button>
|
||||
{#each guides[guide] as subGuide}
|
||||
<Button
|
||||
variant="link"
|
||||
href={getURLForLanguage($locale, `/help/${guide}/${subGuide}`)}
|
||||
class="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'
|
||||
: ''}"
|
||||
>
|
||||
<DocsLoader path={`${guide}/${subGuide}.mdx`} titleOnly={true} />
|
||||
</Button>
|
||||
{/each}
|
||||
{/each}
|
||||
</div>
|
||||
<div class="grow">
|
||||
<slot />
|
||||
</div>
|
||||
<div class="grow px-12 pt-6 pb-12 flex flex-row gap-24">
|
||||
<div
|
||||
class="hidden md:flex flex-col gap-2 w-40 sticky mt-[27px] top-[108px] self-start shrink-0"
|
||||
>
|
||||
{#each Object.keys(guides) as guide}
|
||||
<Button
|
||||
variant="link"
|
||||
href={getURLForLanguage($locale, `/help/${guide}`)}
|
||||
class="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'
|
||||
: ''}"
|
||||
>
|
||||
<DocsLoader path={`${guide}.mdx`} titleOnly={true} />
|
||||
</Button>
|
||||
{#each guides[guide] as subGuide}
|
||||
<Button
|
||||
variant="link"
|
||||
href={getURLForLanguage($locale, `/help/${guide}/${subGuide}`)}
|
||||
class="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'
|
||||
: ''}"
|
||||
>
|
||||
<DocsLoader path={`${guide}/${subGuide}.mdx`} titleOnly={true} />
|
||||
</Button>
|
||||
{/each}
|
||||
{/each}
|
||||
</div>
|
||||
<div class="grow">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user