new trail view options: create copy & change visibility (#571)
* change visibility of multiple trails in trails view (multi-select) * error handling * create copy option added * wait for meilisearch when updating trail * remove toggles from dropdown * change public/private logic * adds loading spinner for bulk operations * fixes trail duplicate * fixes tags delete on visiblility change * fix conflict resolving issue * edit labels & german translation --------- Co-authored-by: Christian Beutel <> Co-authored-by: Flomp <Flomp@users.noreply.github.com>
This commit is contained in:
@@ -346,11 +346,11 @@ func IndexTrails(app core.App, trails []*core.Record, client meilisearch.Service
|
|||||||
func UpdateTrail(app core.App, r *core.Record, author *core.Record, client meilisearch.ServiceManager) error {
|
func UpdateTrail(app core.App, r *core.Record, author *core.Record, client meilisearch.ServiceManager) error {
|
||||||
errs := app.ExpandRecord(r, []string{"tags"}, nil)
|
errs := app.ExpandRecord(r, []string{"tags"}, nil)
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
return fmt.Errorf("failed to expand tags: %v", errs)
|
return fmt.Errorf("meilisearch update trail: failed to expand tags: %v", errs)
|
||||||
}
|
}
|
||||||
errs = app.ExpandRecord(r, []string{"category"}, nil)
|
errs = app.ExpandRecord(r, []string{"category"}, nil)
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
return fmt.Errorf("failed to expand category: %v", errs)
|
return fmt.Errorf("meilisearch update trail: failed to expand category: %v", errs)
|
||||||
}
|
}
|
||||||
|
|
||||||
doc, err := documentFromTrailRecord(app, r, author, false)
|
doc, err := documentFromTrailRecord(app, r, author, false)
|
||||||
@@ -359,10 +359,18 @@ func UpdateTrail(app core.App, r *core.Record, author *core.Record, client meili
|
|||||||
}
|
}
|
||||||
documents := []map[string]interface{}{doc}
|
documents := []map[string]interface{}{doc}
|
||||||
|
|
||||||
if _, err := client.Index("trails").UpdateDocuments(documents); err != nil {
|
task, err := client.Index("trails").UpdateDocuments(documents)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interval := 500 * time.Millisecond
|
||||||
|
_, err = client.WaitForTask(task.TaskUID, interval)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("meilisearch update trail: error waiting for task completion: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,10 @@
|
|||||||
isOpen = false;
|
isOpen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleItemClick(e: MouseEvent, item: { text: string; value: any }) {
|
function handleItemClick(
|
||||||
|
e: MouseEvent,
|
||||||
|
item: { text: string; value: any },
|
||||||
|
) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
onchange?.(item);
|
onchange?.(item);
|
||||||
|
|||||||
@@ -1,28 +1,29 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { goto } from "$app/navigation";
|
import { goto } from "$app/navigation";
|
||||||
|
import { page } from "$app/state";
|
||||||
import type { List } from "$lib/models/list";
|
import type { List } from "$lib/models/list";
|
||||||
import type { Trail } from "$lib/models/trail";
|
import type { Trail } from "$lib/models/trail";
|
||||||
|
import { categories } from "$lib/stores/category_store.js";
|
||||||
import {
|
import {
|
||||||
lists_add_trail,
|
lists_add_trail,
|
||||||
lists_index,
|
lists_index,
|
||||||
lists_remove_trail,
|
lists_remove_trail,
|
||||||
} from "$lib/stores/list_store";
|
} from "$lib/stores/list_store";
|
||||||
import { show_toast } from "$lib/stores/toast_store.svelte";
|
import { show_toast } from "$lib/stores/toast_store.svelte";
|
||||||
import { trails_delete } from "$lib/stores/trail_store";
|
import { trails_delete, trails_update } from "$lib/stores/trail_store";
|
||||||
import { currentUser } from "$lib/stores/user_store";
|
import { currentUser } from "$lib/stores/user_store";
|
||||||
|
import { handleFromRecordWithIRI } from "$lib/util/activitypub_util";
|
||||||
import { getFileURL, saveAs } from "$lib/util/file_util";
|
import { getFileURL, saveAs } from "$lib/util/file_util";
|
||||||
import { trail2gpx } from "$lib/util/gpx_util";
|
import { trail2gpx } from "$lib/util/gpx_util";
|
||||||
import { gpx } from "$lib/vendor/toGeoJSON/toGeoJSON";
|
import { gpx } from "$lib/vendor/toGeoJSON/toGeoJSON";
|
||||||
import JSZip from "jszip";
|
import JSZip from "jszip";
|
||||||
|
import type { Snippet } from "svelte";
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import Dropdown, { type DropdownItem } from "../base/dropdown.svelte";
|
import Dropdown, { type DropdownItem } from "../base/dropdown.svelte";
|
||||||
import ConfirmModal from "../confirm_modal.svelte";
|
import ConfirmModal from "../confirm_modal.svelte";
|
||||||
import ListSearchModal from "../list/list_search_modal.svelte";
|
import ListSearchModal from "../list/list_search_modal.svelte";
|
||||||
import TrailExportModal from "./trail_export_modal.svelte";
|
import TrailExportModal from "./trail_export_modal.svelte";
|
||||||
import TrailShareModal from "./trail_share_modal.svelte";
|
import TrailShareModal from "./trail_share_modal.svelte";
|
||||||
import { handleFromRecordWithIRI } from "$lib/util/activitypub_util";
|
|
||||||
import type { Snippet } from "svelte";
|
|
||||||
import { page } from "$app/state";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
trails?: Set<Trail> | undefined;
|
trails?: Set<Trail> | undefined;
|
||||||
@@ -30,9 +31,10 @@
|
|||||||
toggle?: Snippet<[any]>;
|
toggle?: Snippet<[any]>;
|
||||||
onDelete?: () => void;
|
onDelete?: () => void;
|
||||||
onShare?: () => void;
|
onShare?: () => void;
|
||||||
|
onUpdate?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { trails, mode, toggle, onDelete, onShare }: Props = $props();
|
let { trails, mode, toggle, onDelete, onShare, onUpdate }: Props = $props();
|
||||||
|
|
||||||
let confirmModal: ConfirmModal;
|
let confirmModal: ConfirmModal;
|
||||||
let listSelectModal: ListSearchModal;
|
let listSelectModal: ListSearchModal;
|
||||||
@@ -41,6 +43,8 @@
|
|||||||
|
|
||||||
let lists: List[] = $state([]);
|
let lists: List[] = $state([]);
|
||||||
|
|
||||||
|
let loading: boolean = $state(false);
|
||||||
|
|
||||||
function allowEdit(): boolean {
|
function allowEdit(): boolean {
|
||||||
return (
|
return (
|
||||||
hasTrail() &&
|
hasTrail() &&
|
||||||
@@ -53,6 +57,61 @@
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function majorityOfSelectedTrailsArePublic(): boolean {
|
||||||
|
if (trails === undefined || trails.size === 0) return false;
|
||||||
|
|
||||||
|
if (!Boolean($currentUser)) return false;
|
||||||
|
|
||||||
|
let publicCount = 0;
|
||||||
|
|
||||||
|
for (const cTrail of trails) {
|
||||||
|
if (cTrail.expand?.author === undefined) return false;
|
||||||
|
if (
|
||||||
|
cTrail.expand!.author!.id !== $currentUser?.actor &&
|
||||||
|
!cTrail.expand?.trail_share_via_trail?.some(
|
||||||
|
(s) => s.permission == "edit",
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cTrail.public) {
|
||||||
|
publicCount += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return publicCount >= trails.size / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
function allowCopy(): boolean {
|
||||||
|
if ((trails?.size ?? 0) > 1) return false;
|
||||||
|
|
||||||
|
return !isMultiselectMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
function allowPublish(): boolean {
|
||||||
|
if (mode !== "multi-select") return false;
|
||||||
|
|
||||||
|
if (trails === undefined || trails.size === 0) return false;
|
||||||
|
|
||||||
|
if (!Boolean($currentUser)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const cTrail of trails) {
|
||||||
|
if (cTrail.expand?.author === undefined) return false;
|
||||||
|
if (
|
||||||
|
cTrail.expand!.author!.id !== $currentUser?.actor &&
|
||||||
|
!cTrail.expand?.trail_share_via_trail?.some(
|
||||||
|
(s) => s.permission == "edit",
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
function dropdownItems(): DropdownItem[] {
|
function dropdownItems(): DropdownItem[] {
|
||||||
return [
|
return [
|
||||||
...(!isMultiselectMode()
|
...(!isMultiselectMode()
|
||||||
@@ -71,7 +130,13 @@
|
|||||||
]
|
]
|
||||||
: []),
|
: []),
|
||||||
...(!isMultiselectMode()
|
...(!isMultiselectMode()
|
||||||
? [{ text: $_("directions"), value: "direction", icon: "car" }]
|
? [
|
||||||
|
{
|
||||||
|
text: $_("directions"),
|
||||||
|
value: "direction",
|
||||||
|
icon: "car",
|
||||||
|
},
|
||||||
|
]
|
||||||
: []),
|
: []),
|
||||||
...(canExport()
|
...(canExport()
|
||||||
? [
|
? [
|
||||||
@@ -83,25 +148,69 @@
|
|||||||
]
|
]
|
||||||
: []),
|
: []),
|
||||||
...(!isMultiselectMode()
|
...(!isMultiselectMode()
|
||||||
? [{ text: $_("print"), value: "print", icon: "print" }]
|
? [
|
||||||
|
{
|
||||||
|
text: $_("print"),
|
||||||
|
value: "print",
|
||||||
|
icon: "print",
|
||||||
|
},
|
||||||
|
]
|
||||||
: []),
|
: []),
|
||||||
...(!isFromCurrentUser()
|
...(!isFromCurrentUser()
|
||||||
? []
|
? []
|
||||||
: [
|
: [
|
||||||
{
|
{
|
||||||
text: $_("add-to-list"),
|
text: $_("add-to-list"),
|
||||||
value: "list",
|
value: "print",
|
||||||
icon: "bookmark",
|
icon: "bookmark",
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
...(isMultiselectMode() || !isFromCurrentUser()
|
...(isMultiselectMode() || !isFromCurrentUser()
|
||||||
? []
|
? []
|
||||||
: [{ text: $_("share"), value: "share", icon: "share" }]),
|
: [
|
||||||
|
{
|
||||||
|
text: $_("share"),
|
||||||
|
value: "share",
|
||||||
|
icon: "share",
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
...(allowCopy()
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
text: $_("duplicate"),
|
||||||
|
value: "copy",
|
||||||
|
icon: "copy",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
...(allowPublish()
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
text: `${majorityOfSelectedTrailsArePublic() ? $_("set-private") : $_("set-public")}`,
|
||||||
|
value: "publish",
|
||||||
|
icon: majorityOfSelectedTrailsArePublic()
|
||||||
|
? "lock"
|
||||||
|
: "globe",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
...(allowEdit()
|
...(allowEdit()
|
||||||
? [{ text: $_("edit"), value: "edit", icon: "pen" }]
|
? [
|
||||||
|
{
|
||||||
|
text: $_("edit"),
|
||||||
|
value: "edit",
|
||||||
|
icon: "pen",
|
||||||
|
},
|
||||||
|
]
|
||||||
: []),
|
: []),
|
||||||
...(allowDelete()
|
...(allowDelete()
|
||||||
? [{ text: $_("delete"), value: "delete", icon: "trash" }]
|
? [
|
||||||
|
{
|
||||||
|
text: $_("delete"),
|
||||||
|
value: "delete",
|
||||||
|
icon: "trash",
|
||||||
|
},
|
||||||
|
]
|
||||||
: []),
|
: []),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -174,19 +283,20 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const handle = page.params.handle ?? handleFromRecordWithIRI(trail())
|
const handle = page.params.handle ?? handleFromRecordWithIRI(trail());
|
||||||
|
|
||||||
if (item.value == "show") {
|
const ddVal = item.value as string;
|
||||||
|
|
||||||
|
if (ddVal == "show") {
|
||||||
if (hasTrail()) {
|
if (hasTrail()) {
|
||||||
const url = mode == "overview" || mode == "multi-select"
|
const url =
|
||||||
|
mode == "overview" || mode == "multi-select"
|
||||||
? `/map/trail/${handle}/${trailId()}`
|
? `/map/trail/${handle}/${trailId()}`
|
||||||
: `/trail/view/${handle}/${trailId()}`
|
: `/trail/view/${handle}/${trailId()}`;
|
||||||
|
|
||||||
goto(
|
goto(url + "?" + page.url.searchParams);
|
||||||
url + '?' + page.url.searchParams
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else if (item.value == "list") {
|
} else if (ddVal == "list") {
|
||||||
lists = (
|
lists = (
|
||||||
await lists_index(
|
await lists_index(
|
||||||
{ q: "", author: $currentUser?.actor ?? "" },
|
{ q: "", author: $currentUser?.actor ?? "" },
|
||||||
@@ -195,7 +305,7 @@
|
|||||||
)
|
)
|
||||||
).items;
|
).items;
|
||||||
listSelectModal.openModal();
|
listSelectModal.openModal();
|
||||||
} else if (item.value == "direction") {
|
} else if (ddVal == "direction") {
|
||||||
if (hasTrail()) {
|
if (hasTrail()) {
|
||||||
window
|
window
|
||||||
.open(
|
.open(
|
||||||
@@ -204,23 +314,72 @@
|
|||||||
)
|
)
|
||||||
?.focus();
|
?.focus();
|
||||||
}
|
}
|
||||||
} else if (item.value == "print") {
|
} else if (ddVal == "print") {
|
||||||
if (hasTrail()) {
|
if (hasTrail()) {
|
||||||
goto(`/map/trail/${handle}/${trailId()}/print?${page.url.searchParams}`);
|
goto(
|
||||||
|
`/map/trail/${handle}/${trailId()}/print?${page.url.searchParams}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else if (item.value == "share") {
|
} else if (ddVal == "share") {
|
||||||
trailShareModal.openModal();
|
trailShareModal.openModal();
|
||||||
} else if (item.value == "download") {
|
} else if (ddVal == "download") {
|
||||||
trailExportModal.openModal();
|
trailExportModal.openModal();
|
||||||
} else if (item.value == "edit") {
|
} else if (ddVal == "edit") {
|
||||||
if (hasTrail()) {
|
if (hasTrail()) {
|
||||||
goto(`/trail/edit/${trailId()}`);
|
goto(`/trail/edit/${trailId()}`);
|
||||||
}
|
}
|
||||||
} else if (item.value == "delete") {
|
} else if (ddVal == "copy") {
|
||||||
|
if (hasTrail()) {
|
||||||
|
goto("/trail/edit/new?orig=" + trail()?.id);
|
||||||
|
}
|
||||||
|
} else if (ddVal == "publish") {
|
||||||
|
updateTrailsVisibility();
|
||||||
|
} else if (ddVal == "delete") {
|
||||||
confirmModal.openModal();
|
confirmModal.openModal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function updateTrailsVisibility() {
|
||||||
|
const newVisibility = !majorityOfSelectedTrailsArePublic();
|
||||||
|
|
||||||
|
loading = true;
|
||||||
|
for (const cTrail of trails ?? []) {
|
||||||
|
if (!cTrail) continue;
|
||||||
|
|
||||||
|
if (!cTrail.expand?.author?.id) continue;
|
||||||
|
|
||||||
|
const origTrail: Trail = {
|
||||||
|
...cTrail,
|
||||||
|
author: cTrail.expand!.author!.id,
|
||||||
|
};
|
||||||
|
const updatedTrail: Trail = {
|
||||||
|
...origTrail,
|
||||||
|
public: newVisibility,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await trails_update(
|
||||||
|
origTrail,
|
||||||
|
updatedTrail,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
["tags", "category"],
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
|
||||||
|
show_toast({
|
||||||
|
type: "error",
|
||||||
|
icon: "close",
|
||||||
|
text: `${$_("error-saving-trail")}: ${cTrail.name}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loading = false;
|
||||||
|
onUpdate?.();
|
||||||
|
}
|
||||||
|
|
||||||
async function exportTrails(exportSettings: {
|
async function exportTrails(exportSettings: {
|
||||||
fileFormat: "gpx" | "json";
|
fileFormat: "gpx" | "json";
|
||||||
photos: boolean;
|
photos: boolean;
|
||||||
@@ -308,9 +467,12 @@
|
|||||||
|
|
||||||
async function deleteTrails() {
|
async function deleteTrails() {
|
||||||
if (hasTrail()) {
|
if (hasTrail()) {
|
||||||
|
loading = true;
|
||||||
|
|
||||||
for (const dTrail of trails!) {
|
for (const dTrail of trails!) {
|
||||||
await doDeleteTrail(dTrail);
|
await doDeleteTrail(dTrail);
|
||||||
}
|
}
|
||||||
|
loading = false;
|
||||||
|
|
||||||
onDelete?.();
|
onDelete?.();
|
||||||
}
|
}
|
||||||
@@ -407,7 +569,11 @@
|
|||||||
{#snippet children({ toggleMenu: openDropdown })}
|
{#snippet children({ toggleMenu: openDropdown })}
|
||||||
{#if toggle}{@render toggle({
|
{#if toggle}{@render toggle({
|
||||||
toggleMenu: openDropdown,
|
toggleMenu: openDropdown,
|
||||||
})}{:else if mode == "multi-select"}
|
})}
|
||||||
|
{:else if loading}
|
||||||
|
<div class:w-16={isMultiselectMode()}></div>
|
||||||
|
<div class="spinner light:spinner-dark"></div>
|
||||||
|
{:else if mode == "multi-select"}
|
||||||
<button
|
<button
|
||||||
aria-label="Open dropdown"
|
aria-label="Open dropdown"
|
||||||
class="btn-primary shrink-0 font-medium!"
|
class="btn-primary shrink-0 font-medium!"
|
||||||
|
|||||||
@@ -282,7 +282,7 @@
|
|||||||
|
|
||||||
async function handleTrailsEditDone(resetSelection: boolean = false) {
|
async function handleTrailsEditDone(resetSelection: boolean = false) {
|
||||||
if (resetSelection) {
|
if (resetSelection) {
|
||||||
selection?.clear();
|
selection = new Set<Trail>();
|
||||||
hoveredTrail = undefined;
|
hoveredTrail = undefined;
|
||||||
}
|
}
|
||||||
await tick();
|
await tick();
|
||||||
@@ -319,6 +319,7 @@
|
|||||||
mode={"multi-select"}
|
mode={"multi-select"}
|
||||||
onDelete={() => handleTrailsEditDone(true)}
|
onDelete={() => handleTrailsEditDone(true)}
|
||||||
onShare={() => handleTrailsEditDone(false)}
|
onShare={() => handleTrailsEditDone(false)}
|
||||||
|
onUpdate={() => handleTrailsEditDone(true)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
"alphabetical": "Alphabetisch",
|
"alphabetical": "Alphabetisch",
|
||||||
"already-account": "Du hast bereits ein Konto?",
|
"already-account": "Du hast bereits ein Konto?",
|
||||||
"altitude": "Höhe",
|
"altitude": "Höhe",
|
||||||
|
"amenity": "",
|
||||||
"ammenity": "Einrichtung",
|
"ammenity": "Einrichtung",
|
||||||
"api-documentation": "API Dokumentation",
|
"api-documentation": "API Dokumentation",
|
||||||
"apply-user-settings": "",
|
"apply-user-settings": "",
|
||||||
@@ -113,7 +114,7 @@
|
|||||||
"download": "Herunterladen",
|
"download": "Herunterladen",
|
||||||
"draw-a-route": "Route zeichnen",
|
"draw-a-route": "Route zeichnen",
|
||||||
"driving": "Auto",
|
"driving": "Auto",
|
||||||
"duplicate": "Duplikat",
|
"duplicate": "Duplizieren",
|
||||||
"duration": "Dauer",
|
"duration": "Dauer",
|
||||||
"dutch": "Niederländisch",
|
"dutch": "Niederländisch",
|
||||||
"easy": "Einfach",
|
"easy": "Einfach",
|
||||||
@@ -136,6 +137,7 @@
|
|||||||
"enable-auto-routing": "Auto-Routing aktivieren",
|
"enable-auto-routing": "Auto-Routing aktivieren",
|
||||||
"english": "Englisch",
|
"english": "Englisch",
|
||||||
"entry": "Eintrag",
|
"entry": "Eintrag",
|
||||||
|
"error-copying-trail": "Fehler beim Kopieren der Route",
|
||||||
"error-creating-user": "Fehler beim Erstellen des Nutzers",
|
"error-creating-user": "Fehler beim Erstellen des Nutzers",
|
||||||
"error-disabling-strava-integration": "Fehler beim Deaktivieren der Stravaintegration",
|
"error-disabling-strava-integration": "Fehler beim Deaktivieren der Stravaintegration",
|
||||||
"error-during-login": "Fehler beim Login",
|
"error-during-login": "Fehler beim Login",
|
||||||
@@ -358,6 +360,8 @@
|
|||||||
"search-trails": "Route suchen",
|
"search-trails": "Route suchen",
|
||||||
"select-list": "Liste auswählen",
|
"select-list": "Liste auswählen",
|
||||||
"selected": "ausgewählt",
|
"selected": "ausgewählt",
|
||||||
|
"set-private": "Verbergen",
|
||||||
|
"set-public": "Veröffentlichen",
|
||||||
"settings": "Einstellungen",
|
"settings": "Einstellungen",
|
||||||
"settings-notification-comment-mention": "Jemand hat dich in einem Kommentar erwähnt",
|
"settings-notification-comment-mention": "Jemand hat dich in einem Kommentar erwähnt",
|
||||||
"settings-notification-list-create": "Ein Benutzer, dem Du folgst, hat eine Liste erstellt",
|
"settings-notification-list-create": "Ein Benutzer, dem Du folgst, hat eine Liste erstellt",
|
||||||
@@ -413,6 +417,7 @@
|
|||||||
"top-speed": "Höchstgeschwindigkeit",
|
"top-speed": "Höchstgeschwindigkeit",
|
||||||
"tourism": "Tourismus",
|
"tourism": "Tourismus",
|
||||||
"trail": "{n, plural, =1 {Route} other {Routen}}",
|
"trail": "{n, plural, =1 {Route} other {Routen}}",
|
||||||
|
"trail-copied-successfully": "Route erfolgreich kopiert",
|
||||||
"trail-not-in-list": "Trail gehört zu keiner Liste.",
|
"trail-not-in-list": "Trail gehört zu keiner Liste.",
|
||||||
"trail-not-shared": "Mit niemandem geteilt",
|
"trail-not-shared": "Mit niemandem geteilt",
|
||||||
"trail-saved-successfully": "Route gespeichert",
|
"trail-saved-successfully": "Route gespeichert",
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
"already-account": "Already have an account?",
|
"already-account": "Already have an account?",
|
||||||
"altitude": "Altitude",
|
"altitude": "Altitude",
|
||||||
"amenity": "Amenity",
|
"amenity": "Amenity",
|
||||||
|
"ammenity": "",
|
||||||
"api-documentation": "API Documentation",
|
"api-documentation": "API Documentation",
|
||||||
"apply-user-settings": "Apply user settings",
|
"apply-user-settings": "Apply user settings",
|
||||||
"attraction": "Attraction",
|
"attraction": "Attraction",
|
||||||
@@ -136,6 +137,7 @@
|
|||||||
"enable-auto-routing": "Enable auto-routing",
|
"enable-auto-routing": "Enable auto-routing",
|
||||||
"english": "English",
|
"english": "English",
|
||||||
"entry": "Entry",
|
"entry": "Entry",
|
||||||
|
"error-copying-trail": "Error copying trail",
|
||||||
"error-creating-user": "Error creating user",
|
"error-creating-user": "Error creating user",
|
||||||
"error-disabling-strava-integration": "Error disabling strava integration",
|
"error-disabling-strava-integration": "Error disabling strava integration",
|
||||||
"error-during-login": "Error during login",
|
"error-during-login": "Error during login",
|
||||||
@@ -358,6 +360,8 @@
|
|||||||
"search-trails": "Search trails",
|
"search-trails": "Search trails",
|
||||||
"select-list": "Select List",
|
"select-list": "Select List",
|
||||||
"selected": "selected",
|
"selected": "selected",
|
||||||
|
"set-private": "Set private",
|
||||||
|
"set-public": "Set public",
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
"settings-notification-comment-mention": "Someone mentioned you in a comment",
|
"settings-notification-comment-mention": "Someone mentioned you in a comment",
|
||||||
"settings-notification-list-create": "A user who you follow has created a list",
|
"settings-notification-list-create": "A user who you follow has created a list",
|
||||||
@@ -413,6 +417,7 @@
|
|||||||
"top-speed": "Top Speed",
|
"top-speed": "Top Speed",
|
||||||
"tourism": "Tourism",
|
"tourism": "Tourism",
|
||||||
"trail": "{n, plural, =1 {Trail} other {Trails}}",
|
"trail": "{n, plural, =1 {Trail} other {Trails}}",
|
||||||
|
"trail-copied-successfully": "trail copied successfully",
|
||||||
"trail-not-in-list": "Trail is not in any list",
|
"trail-not-in-list": "Trail is not in any list",
|
||||||
"trail-not-shared": "Not shared with anyone",
|
"trail-not-shared": "Not shared with anyone",
|
||||||
"trail-saved-successfully": "Trail saved successfully",
|
"trail-saved-successfully": "Trail saved successfully",
|
||||||
@@ -430,6 +435,7 @@
|
|||||||
"username": "Username",
|
"username": "Username",
|
||||||
"view": "View",
|
"view": "View",
|
||||||
"viewpoint": "Viewpoint",
|
"viewpoint": "Viewpoint",
|
||||||
|
"visibilty": "Visibility",
|
||||||
"visibilty-status": "Visibility status",
|
"visibilty-status": "Visibility status",
|
||||||
"walking-speed": "Walking speed",
|
"walking-speed": "Walking speed",
|
||||||
"water": "Water",
|
"water": "Water",
|
||||||
|
|||||||
@@ -21,8 +21,10 @@
|
|||||||
"alphabetical": "Alfabético",
|
"alphabetical": "Alfabético",
|
||||||
"already-account": "¿Ya tienes una cuenta?",
|
"already-account": "¿Ya tienes una cuenta?",
|
||||||
"altitude": "Altitud",
|
"altitude": "Altitud",
|
||||||
|
"amenity": "",
|
||||||
"ammenity": "Servicios",
|
"ammenity": "Servicios",
|
||||||
"api-documentation": "Documentación API",
|
"api-documentation": "Documentación API",
|
||||||
|
"apply-user-settings": "",
|
||||||
"attraction": "Atracción",
|
"attraction": "Atracción",
|
||||||
"author": "Autor",
|
"author": "Autor",
|
||||||
"avatar": "Avatar",
|
"avatar": "Avatar",
|
||||||
@@ -134,6 +136,7 @@
|
|||||||
"enable-auto-routing": "Habilitar auto-ruta",
|
"enable-auto-routing": "Habilitar auto-ruta",
|
||||||
"english": "Inglés",
|
"english": "Inglés",
|
||||||
"entry": "Entrada",
|
"entry": "Entrada",
|
||||||
|
"error-copying-trail": "",
|
||||||
"error-creating-user": "Error creando el usuario",
|
"error-creating-user": "Error creando el usuario",
|
||||||
"error-disabling-strava-integration": "Error al desactivar la integración de strava",
|
"error-disabling-strava-integration": "Error al desactivar la integración de strava",
|
||||||
"error-during-login": "Error durante el acceso",
|
"error-during-login": "Error durante el acceso",
|
||||||
@@ -356,6 +359,8 @@
|
|||||||
"search-trails": "Buscar ruta",
|
"search-trails": "Buscar ruta",
|
||||||
"select-list": "Seleccionar Lista",
|
"select-list": "Seleccionar Lista",
|
||||||
"selected": "seleccionado",
|
"selected": "seleccionado",
|
||||||
|
"set-private": "",
|
||||||
|
"set-public": "",
|
||||||
"settings": "Configuración",
|
"settings": "Configuración",
|
||||||
"settings-notification-comment-mention": "Alguien te mencionó en un comentario",
|
"settings-notification-comment-mention": "Alguien te mencionó en un comentario",
|
||||||
"settings-notification-list-create": "Un usuario al que sigues ha creado una nueva lista",
|
"settings-notification-list-create": "Un usuario al que sigues ha creado una nueva lista",
|
||||||
@@ -411,6 +416,7 @@
|
|||||||
"top-speed": "Velocidad máxima",
|
"top-speed": "Velocidad máxima",
|
||||||
"tourism": "Turismo",
|
"tourism": "Turismo",
|
||||||
"trail": "{n, plural, one {}=1 {Ruta} other {Rutas}}",
|
"trail": "{n, plural, one {}=1 {Ruta} other {Rutas}}",
|
||||||
|
"trail-copied-successfully": "",
|
||||||
"trail-not-in-list": "",
|
"trail-not-in-list": "",
|
||||||
"trail-not-shared": "No compartida con nadie",
|
"trail-not-shared": "No compartida con nadie",
|
||||||
"trail-saved-successfully": "Ruta guardada con éxito",
|
"trail-saved-successfully": "Ruta guardada con éxito",
|
||||||
@@ -428,6 +434,7 @@
|
|||||||
"username": "Nombre de usuario",
|
"username": "Nombre de usuario",
|
||||||
"view": "Ver",
|
"view": "Ver",
|
||||||
"viewpoint": "Mirador",
|
"viewpoint": "Mirador",
|
||||||
|
"visibilty": "Visibilidad",
|
||||||
"visibilty-status": "Estado de visibilidad",
|
"visibilty-status": "Estado de visibilidad",
|
||||||
"walking-speed": "Velocidad al caminar",
|
"walking-speed": "Velocidad al caminar",
|
||||||
"water": "Agua",
|
"water": "Agua",
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
"already-account": "Baduzu kontua lehendik?",
|
"already-account": "Baduzu kontua lehendik?",
|
||||||
"altitude": "Altuera",
|
"altitude": "Altuera",
|
||||||
"amenity": "Altimetria",
|
"amenity": "Altimetria",
|
||||||
|
"ammenity": "",
|
||||||
"api-documentation": "API dokumentazioa",
|
"api-documentation": "API dokumentazioa",
|
||||||
"apply-user-settings": "",
|
"apply-user-settings": "",
|
||||||
"attraction": "Erakarmena",
|
"attraction": "Erakarmena",
|
||||||
@@ -135,6 +136,7 @@
|
|||||||
"enable-auto-routing": "Aktibatu bideratze automatikoa",
|
"enable-auto-routing": "Aktibatu bideratze automatikoa",
|
||||||
"english": "Ingelesa",
|
"english": "Ingelesa",
|
||||||
"entry": "Sarrera",
|
"entry": "Sarrera",
|
||||||
|
"error-copying-trail": "",
|
||||||
"error-creating-user": "Errorea erabiltzailea sortzen",
|
"error-creating-user": "Errorea erabiltzailea sortzen",
|
||||||
"error-disabling-strava-integration": "Errorea stravarekin integrazioa desaktibatzean",
|
"error-disabling-strava-integration": "Errorea stravarekin integrazioa desaktibatzean",
|
||||||
"error-during-login": "Errorea sartzean",
|
"error-during-login": "Errorea sartzean",
|
||||||
@@ -357,6 +359,8 @@
|
|||||||
"search-trails": "Bilatu ibilaldiak",
|
"search-trails": "Bilatu ibilaldiak",
|
||||||
"select-list": "Aukeratu zerrenda",
|
"select-list": "Aukeratu zerrenda",
|
||||||
"selected": "aukeratuta",
|
"selected": "aukeratuta",
|
||||||
|
"set-private": "",
|
||||||
|
"set-public": "",
|
||||||
"settings": "Ezarpenak",
|
"settings": "Ezarpenak",
|
||||||
"settings-notification-comment-mention": "Norbaitek iruzkin baten aipatu zaitu",
|
"settings-notification-comment-mention": "Norbaitek iruzkin baten aipatu zaitu",
|
||||||
"settings-notification-list-create": "Jarraitzen duzun erabiltzaile batek zerrenda bat sortu du",
|
"settings-notification-list-create": "Jarraitzen duzun erabiltzaile batek zerrenda bat sortu du",
|
||||||
@@ -412,6 +416,7 @@
|
|||||||
"top-speed": "Gehienezko abiadura",
|
"top-speed": "Gehienezko abiadura",
|
||||||
"tourism": "Turismoa",
|
"tourism": "Turismoa",
|
||||||
"trail": "{n, plural, one {}=1 {ibilbide} other {ibilbide}}",
|
"trail": "{n, plural, one {}=1 {ibilbide} other {ibilbide}}",
|
||||||
|
"trail-copied-successfully": "",
|
||||||
"trail-not-in-list": "",
|
"trail-not-in-list": "",
|
||||||
"trail-not-shared": "Inorekin partekatu gabe",
|
"trail-not-shared": "Inorekin partekatu gabe",
|
||||||
"trail-saved-successfully": "Ibilbidea ondo gorde da",
|
"trail-saved-successfully": "Ibilbidea ondo gorde da",
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
"alphabetical": "Alphabétique",
|
"alphabetical": "Alphabétique",
|
||||||
"already-account": "Déjà un compte ?",
|
"already-account": "Déjà un compte ?",
|
||||||
"altitude": "Altitude",
|
"altitude": "Altitude",
|
||||||
|
"amenity": "",
|
||||||
"ammenity": "Aménagement",
|
"ammenity": "Aménagement",
|
||||||
"api-documentation": "Documentation API",
|
"api-documentation": "Documentation API",
|
||||||
"apply-user-settings": "",
|
"apply-user-settings": "",
|
||||||
@@ -135,6 +136,7 @@
|
|||||||
"enable-auto-routing": "Activer le routage automatique",
|
"enable-auto-routing": "Activer le routage automatique",
|
||||||
"english": "Anglais",
|
"english": "Anglais",
|
||||||
"entry": "Entrée",
|
"entry": "Entrée",
|
||||||
|
"error-copying-trail": "",
|
||||||
"error-creating-user": "Erreur durant la création de l'utilisateur",
|
"error-creating-user": "Erreur durant la création de l'utilisateur",
|
||||||
"error-disabling-strava-integration": "Erreur lors de la désactivation de l'intégration Strava",
|
"error-disabling-strava-integration": "Erreur lors de la désactivation de l'intégration Strava",
|
||||||
"error-during-login": "Erreur durant la connexion",
|
"error-during-login": "Erreur durant la connexion",
|
||||||
@@ -357,6 +359,8 @@
|
|||||||
"search-trails": "Chercher un itinéraire",
|
"search-trails": "Chercher un itinéraire",
|
||||||
"select-list": "Liste de choix",
|
"select-list": "Liste de choix",
|
||||||
"selected": "sélectionné(s)",
|
"selected": "sélectionné(s)",
|
||||||
|
"set-private": "",
|
||||||
|
"set-public": "",
|
||||||
"settings": "Paramètres",
|
"settings": "Paramètres",
|
||||||
"settings-notification-comment-mention": "Quelqu’un vous a mentionné dans un commentaire",
|
"settings-notification-comment-mention": "Quelqu’un vous a mentionné dans un commentaire",
|
||||||
"settings-notification-list-create": "Un utilisateur que vous suivez à créé une nouvelle liste",
|
"settings-notification-list-create": "Un utilisateur que vous suivez à créé une nouvelle liste",
|
||||||
@@ -412,6 +416,7 @@
|
|||||||
"top-speed": "Vitesse maximale",
|
"top-speed": "Vitesse maximale",
|
||||||
"tourism": "Tourisme",
|
"tourism": "Tourisme",
|
||||||
"trail": "{n, plural, =1 {Itinéraire} other {Itinéraires}}",
|
"trail": "{n, plural, =1 {Itinéraire} other {Itinéraires}}",
|
||||||
|
"trail-copied-successfully": "",
|
||||||
"trail-not-in-list": "",
|
"trail-not-in-list": "",
|
||||||
"trail-not-shared": "L'itinéraire n'a pas été partagé",
|
"trail-not-shared": "L'itinéraire n'a pas été partagé",
|
||||||
"trail-saved-successfully": "Itinéraire enregistrée",
|
"trail-saved-successfully": "Itinéraire enregistrée",
|
||||||
@@ -429,6 +434,7 @@
|
|||||||
"username": "Nom d'utilisateur",
|
"username": "Nom d'utilisateur",
|
||||||
"view": "Afficher",
|
"view": "Afficher",
|
||||||
"viewpoint": "Point de vue",
|
"viewpoint": "Point de vue",
|
||||||
|
"visibilty": "Visibilité",
|
||||||
"visibilty-status": "État de visibilité",
|
"visibilty-status": "État de visibilité",
|
||||||
"walking-speed": "Vitesse de marche",
|
"walking-speed": "Vitesse de marche",
|
||||||
"water": "Eau",
|
"water": "Eau",
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
"already-account": "Már rendelkezik fiókkal?",
|
"already-account": "Már rendelkezik fiókkal?",
|
||||||
"altitude": "Magasság",
|
"altitude": "Magasság",
|
||||||
"amenity": "Amenity",
|
"amenity": "Amenity",
|
||||||
|
"ammenity": "",
|
||||||
"api-documentation": "API Dokumentáció",
|
"api-documentation": "API Dokumentáció",
|
||||||
"apply-user-settings": "",
|
"apply-user-settings": "",
|
||||||
"attraction": "Attraction",
|
"attraction": "Attraction",
|
||||||
@@ -135,6 +136,7 @@
|
|||||||
"enable-auto-routing": "Enable auto-routing",
|
"enable-auto-routing": "Enable auto-routing",
|
||||||
"english": "Angol",
|
"english": "Angol",
|
||||||
"entry": "Bejegyzés",
|
"entry": "Bejegyzés",
|
||||||
|
"error-copying-trail": "",
|
||||||
"error-creating-user": "Hiba felhasználó hozzáadása közben",
|
"error-creating-user": "Hiba felhasználó hozzáadása közben",
|
||||||
"error-disabling-strava-integration": "Error disabling strava integration",
|
"error-disabling-strava-integration": "Error disabling strava integration",
|
||||||
"error-during-login": "Hiba bejelentkezés közben",
|
"error-during-login": "Hiba bejelentkezés közben",
|
||||||
@@ -357,6 +359,8 @@
|
|||||||
"search-trails": "Nyomvonalak keresése",
|
"search-trails": "Nyomvonalak keresése",
|
||||||
"select-list": "Lista kiválasztása",
|
"select-list": "Lista kiválasztása",
|
||||||
"selected": "selected",
|
"selected": "selected",
|
||||||
|
"set-private": "",
|
||||||
|
"set-public": "",
|
||||||
"settings": "Beállítások",
|
"settings": "Beállítások",
|
||||||
"settings-notification-comment-mention": "Someone mentioned you in a comment",
|
"settings-notification-comment-mention": "Someone mentioned you in a comment",
|
||||||
"settings-notification-list-create": "A user who you follow has created a list",
|
"settings-notification-list-create": "A user who you follow has created a list",
|
||||||
@@ -412,6 +416,7 @@
|
|||||||
"top-speed": "Top Speed",
|
"top-speed": "Top Speed",
|
||||||
"tourism": "Tourism",
|
"tourism": "Tourism",
|
||||||
"trail": "{n, plural, =1 {Útvonal} other {Útvonalak}}",
|
"trail": "{n, plural, =1 {Útvonal} other {Útvonalak}}",
|
||||||
|
"trail-copied-successfully": "",
|
||||||
"trail-not-in-list": "",
|
"trail-not-in-list": "",
|
||||||
"trail-not-shared": "Not shared with anyone",
|
"trail-not-shared": "Not shared with anyone",
|
||||||
"trail-saved-successfully": "Trail saved successfully",
|
"trail-saved-successfully": "Trail saved successfully",
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
"already-account": "Hai già un account?",
|
"already-account": "Hai già un account?",
|
||||||
"altitude": "Altitudine",
|
"altitude": "Altitudine",
|
||||||
"amenity": "Amenity",
|
"amenity": "Amenity",
|
||||||
|
"ammenity": "",
|
||||||
"api-documentation": "Documentazione API",
|
"api-documentation": "Documentazione API",
|
||||||
"apply-user-settings": "",
|
"apply-user-settings": "",
|
||||||
"attraction": "Attraction",
|
"attraction": "Attraction",
|
||||||
@@ -135,6 +136,7 @@
|
|||||||
"enable-auto-routing": "Enable auto-routing",
|
"enable-auto-routing": "Enable auto-routing",
|
||||||
"english": "Inglese",
|
"english": "Inglese",
|
||||||
"entry": "Voce",
|
"entry": "Voce",
|
||||||
|
"error-copying-trail": "",
|
||||||
"error-creating-user": "Errore nella creazione dell'utente",
|
"error-creating-user": "Errore nella creazione dell'utente",
|
||||||
"error-disabling-strava-integration": "Error disabling strava integration",
|
"error-disabling-strava-integration": "Error disabling strava integration",
|
||||||
"error-during-login": "Errore durante il login",
|
"error-during-login": "Errore durante il login",
|
||||||
@@ -357,6 +359,8 @@
|
|||||||
"search-trails": "Cerca percorsi",
|
"search-trails": "Cerca percorsi",
|
||||||
"select-list": "Seleziona lista",
|
"select-list": "Seleziona lista",
|
||||||
"selected": "selected",
|
"selected": "selected",
|
||||||
|
"set-private": "",
|
||||||
|
"set-public": "",
|
||||||
"settings": "Impostazioni",
|
"settings": "Impostazioni",
|
||||||
"settings-notification-comment-mention": "Someone mentioned you in a comment",
|
"settings-notification-comment-mention": "Someone mentioned you in a comment",
|
||||||
"settings-notification-list-create": "Un utente che segui ha creato una lista",
|
"settings-notification-list-create": "Un utente che segui ha creato una lista",
|
||||||
@@ -412,6 +416,7 @@
|
|||||||
"top-speed": "Top Speed",
|
"top-speed": "Top Speed",
|
||||||
"tourism": "Tourism",
|
"tourism": "Tourism",
|
||||||
"trail": "{n, plural, =1 {Percorso} other {Percorsi}}",
|
"trail": "{n, plural, =1 {Percorso} other {Percorsi}}",
|
||||||
|
"trail-copied-successfully": "",
|
||||||
"trail-not-in-list": "",
|
"trail-not-in-list": "",
|
||||||
"trail-not-shared": "Percorso non condiviso con nessuno",
|
"trail-not-shared": "Percorso non condiviso con nessuno",
|
||||||
"trail-saved-successfully": "Percorso salvato con successo",
|
"trail-saved-successfully": "Percorso salvato con successo",
|
||||||
|
|||||||
@@ -136,6 +136,7 @@
|
|||||||
"enable-auto-routing": "Automatische routering inschakelen",
|
"enable-auto-routing": "Automatische routering inschakelen",
|
||||||
"english": "Engels",
|
"english": "Engels",
|
||||||
"entry": "Item",
|
"entry": "Item",
|
||||||
|
"error-copying-trail": "",
|
||||||
"error-creating-user": "Fout bij aanmaken gebruiker",
|
"error-creating-user": "Fout bij aanmaken gebruiker",
|
||||||
"error-disabling-strava-integration": "Fout bij het uitschakelen van Strava-integratie",
|
"error-disabling-strava-integration": "Fout bij het uitschakelen van Strava-integratie",
|
||||||
"error-during-login": "Het inloggen is mislukt",
|
"error-during-login": "Het inloggen is mislukt",
|
||||||
@@ -358,6 +359,8 @@
|
|||||||
"search-trails": "Zoek routes",
|
"search-trails": "Zoek routes",
|
||||||
"select-list": "Kies een lijst",
|
"select-list": "Kies een lijst",
|
||||||
"selected": "geselecteerd",
|
"selected": "geselecteerd",
|
||||||
|
"set-private": "",
|
||||||
|
"set-public": "",
|
||||||
"settings": "Instellingen",
|
"settings": "Instellingen",
|
||||||
"settings-notification-comment-mention": "Iemand vermeldt je in een reactie",
|
"settings-notification-comment-mention": "Iemand vermeldt je in een reactie",
|
||||||
"settings-notification-list-create": "Een gebruiker die je volgt, heeft een lijst gecreëerd",
|
"settings-notification-list-create": "Een gebruiker die je volgt, heeft een lijst gecreëerd",
|
||||||
@@ -413,6 +416,7 @@
|
|||||||
"top-speed": "Topsnelheid",
|
"top-speed": "Topsnelheid",
|
||||||
"tourism": "Toerisme",
|
"tourism": "Toerisme",
|
||||||
"trail": "{n, plural, =1 {Route} other {Routes}}",
|
"trail": "{n, plural, =1 {Route} other {Routes}}",
|
||||||
|
"trail-copied-successfully": "",
|
||||||
"trail-not-in-list": "",
|
"trail-not-in-list": "",
|
||||||
"trail-not-shared": "Niet gedeeld met iemand",
|
"trail-not-shared": "Niet gedeeld met iemand",
|
||||||
"trail-saved-successfully": "Route succesvol bewaard",
|
"trail-saved-successfully": "Route succesvol bewaard",
|
||||||
@@ -430,6 +434,7 @@
|
|||||||
"username": "Gebruikersnaam",
|
"username": "Gebruikersnaam",
|
||||||
"view": "Weergave",
|
"view": "Weergave",
|
||||||
"viewpoint": "Uitzichtpunt",
|
"viewpoint": "Uitzichtpunt",
|
||||||
|
"visibilty": "Zichtbaarheid",
|
||||||
"visibilty-status": "Zichtbaarheid status",
|
"visibilty-status": "Zichtbaarheid status",
|
||||||
"walking-speed": "Wandelsnelheid",
|
"walking-speed": "Wandelsnelheid",
|
||||||
"water": "Water",
|
"water": "Water",
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
"already-account": "Czy masz już konto?",
|
"already-account": "Czy masz już konto?",
|
||||||
"altitude": "Wysokość",
|
"altitude": "Wysokość",
|
||||||
"amenity": "Amenity",
|
"amenity": "Amenity",
|
||||||
|
"ammenity": "",
|
||||||
"api-documentation": "Dokumentacja API",
|
"api-documentation": "Dokumentacja API",
|
||||||
"apply-user-settings": "",
|
"apply-user-settings": "",
|
||||||
"attraction": "Attraction",
|
"attraction": "Attraction",
|
||||||
@@ -135,6 +136,7 @@
|
|||||||
"enable-auto-routing": "Włącz auto-trasowanie",
|
"enable-auto-routing": "Włącz auto-trasowanie",
|
||||||
"english": "Angielski",
|
"english": "Angielski",
|
||||||
"entry": "Pozycja",
|
"entry": "Pozycja",
|
||||||
|
"error-copying-trail": "",
|
||||||
"error-creating-user": "Błąd tworzenia użytkownika",
|
"error-creating-user": "Błąd tworzenia użytkownika",
|
||||||
"error-disabling-strava-integration": "Błąd przy wyłączaniu integracji strava",
|
"error-disabling-strava-integration": "Błąd przy wyłączaniu integracji strava",
|
||||||
"error-during-login": "Błąd podczas logowania",
|
"error-during-login": "Błąd podczas logowania",
|
||||||
@@ -357,6 +359,8 @@
|
|||||||
"search-trails": "Szukaj szlaków",
|
"search-trails": "Szukaj szlaków",
|
||||||
"select-list": "Wybierz Listę",
|
"select-list": "Wybierz Listę",
|
||||||
"selected": "selected",
|
"selected": "selected",
|
||||||
|
"set-private": "",
|
||||||
|
"set-public": "",
|
||||||
"settings": "Ustawienia",
|
"settings": "Ustawienia",
|
||||||
"settings-notification-comment-mention": "Ktoś wspomniał o tobie w komentarzu",
|
"settings-notification-comment-mention": "Ktoś wspomniał o tobie w komentarzu",
|
||||||
"settings-notification-list-create": "Użytkownik, którego obserwujesz, utworzył listę",
|
"settings-notification-list-create": "Użytkownik, którego obserwujesz, utworzył listę",
|
||||||
@@ -412,6 +416,7 @@
|
|||||||
"top-speed": "Maksymalna prędkość",
|
"top-speed": "Maksymalna prędkość",
|
||||||
"tourism": "Tourism",
|
"tourism": "Tourism",
|
||||||
"trail": "{n, plural, one {Szlak} few {Szlaki} many {Szlaków}=1 {Szlak} other {Szlaki}}",
|
"trail": "{n, plural, one {Szlak} few {Szlaki} many {Szlaków}=1 {Szlak} other {Szlaki}}",
|
||||||
|
"trail-copied-successfully": "",
|
||||||
"trail-not-in-list": "",
|
"trail-not-in-list": "",
|
||||||
"trail-not-shared": "Szlak nie udostępniony",
|
"trail-not-shared": "Szlak nie udostępniony",
|
||||||
"trail-saved-successfully": "Szlak pomyślnie zapisany",
|
"trail-saved-successfully": "Szlak pomyślnie zapisany",
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
"already-account": "Já tem uma conta?",
|
"already-account": "Já tem uma conta?",
|
||||||
"altitude": "Altitude",
|
"altitude": "Altitude",
|
||||||
"amenity": "Amenity",
|
"amenity": "Amenity",
|
||||||
|
"ammenity": "",
|
||||||
"api-documentation": "Documentação da API",
|
"api-documentation": "Documentação da API",
|
||||||
"apply-user-settings": "",
|
"apply-user-settings": "",
|
||||||
"attraction": "Attraction",
|
"attraction": "Attraction",
|
||||||
@@ -135,6 +136,7 @@
|
|||||||
"enable-auto-routing": "Enable auto-routing",
|
"enable-auto-routing": "Enable auto-routing",
|
||||||
"english": "Inglês",
|
"english": "Inglês",
|
||||||
"entry": "Entrada",
|
"entry": "Entrada",
|
||||||
|
"error-copying-trail": "",
|
||||||
"error-creating-user": "Erro ao criar utilizador",
|
"error-creating-user": "Erro ao criar utilizador",
|
||||||
"error-disabling-strava-integration": "Error disabling strava integration",
|
"error-disabling-strava-integration": "Error disabling strava integration",
|
||||||
"error-during-login": "Erro durante o ‘login’",
|
"error-during-login": "Erro durante o ‘login’",
|
||||||
@@ -357,6 +359,8 @@
|
|||||||
"search-trails": "Procurar trilhos",
|
"search-trails": "Procurar trilhos",
|
||||||
"select-list": "Selecionar lista",
|
"select-list": "Selecionar lista",
|
||||||
"selected": "selected",
|
"selected": "selected",
|
||||||
|
"set-private": "",
|
||||||
|
"set-public": "",
|
||||||
"settings": "Definições",
|
"settings": "Definições",
|
||||||
"settings-notification-comment-mention": "Someone mentioned you in a comment",
|
"settings-notification-comment-mention": "Someone mentioned you in a comment",
|
||||||
"settings-notification-list-create": "A user who you follow has created a list",
|
"settings-notification-list-create": "A user who you follow has created a list",
|
||||||
@@ -412,6 +416,7 @@
|
|||||||
"top-speed": "Top Speed",
|
"top-speed": "Top Speed",
|
||||||
"tourism": "Tourism",
|
"tourism": "Tourism",
|
||||||
"trail": "{n, plural, =1 {Percurso} other {Percursos}}",
|
"trail": "{n, plural, =1 {Percurso} other {Percursos}}",
|
||||||
|
"trail-copied-successfully": "",
|
||||||
"trail-not-in-list": "",
|
"trail-not-in-list": "",
|
||||||
"trail-not-shared": "Não partilhado com ninguém",
|
"trail-not-shared": "Não partilhado com ninguém",
|
||||||
"trail-saved-successfully": "Percurso gravado com sucesso",
|
"trail-saved-successfully": "Percurso gravado com sucesso",
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
"already-account": "Уже есть аккаунт?",
|
"already-account": "Уже есть аккаунт?",
|
||||||
"altitude": "Высота",
|
"altitude": "Высота",
|
||||||
"amenity": "Amenity",
|
"amenity": "Amenity",
|
||||||
|
"ammenity": "",
|
||||||
"api-documentation": "Документация API",
|
"api-documentation": "Документация API",
|
||||||
"apply-user-settings": "",
|
"apply-user-settings": "",
|
||||||
"attraction": "Attraction",
|
"attraction": "Attraction",
|
||||||
@@ -135,6 +136,7 @@
|
|||||||
"enable-auto-routing": "Авто-маршрутизация",
|
"enable-auto-routing": "Авто-маршрутизация",
|
||||||
"english": "Английский",
|
"english": "Английский",
|
||||||
"entry": "Запись",
|
"entry": "Запись",
|
||||||
|
"error-copying-trail": "",
|
||||||
"error-creating-user": "Ошибка создания пользователя",
|
"error-creating-user": "Ошибка создания пользователя",
|
||||||
"error-disabling-strava-integration": "Ошибка отключения Strava",
|
"error-disabling-strava-integration": "Ошибка отключения Strava",
|
||||||
"error-during-login": "Ошибка входа",
|
"error-during-login": "Ошибка входа",
|
||||||
@@ -357,6 +359,8 @@
|
|||||||
"search-trails": "Поиск треков",
|
"search-trails": "Поиск треков",
|
||||||
"select-list": "Выбрать список",
|
"select-list": "Выбрать список",
|
||||||
"selected": "selected",
|
"selected": "selected",
|
||||||
|
"set-private": "",
|
||||||
|
"set-public": "",
|
||||||
"settings": "Настройки",
|
"settings": "Настройки",
|
||||||
"settings-notification-comment-mention": "Кто-то упомянул вас в комментариях",
|
"settings-notification-comment-mention": "Кто-то упомянул вас в комментариях",
|
||||||
"settings-notification-list-create": "Пользователь, на которого вы подписаны, создал список",
|
"settings-notification-list-create": "Пользователь, на которого вы подписаны, создал список",
|
||||||
@@ -412,6 +416,7 @@
|
|||||||
"top-speed": "Макс. скорость",
|
"top-speed": "Макс. скорость",
|
||||||
"tourism": "Туризм",
|
"tourism": "Туризм",
|
||||||
"trail": "{n, plural, =1 {Трек} other {Треки}}",
|
"trail": "{n, plural, =1 {Трек} other {Треки}}",
|
||||||
|
"trail-copied-successfully": "",
|
||||||
"trail-not-in-list": "",
|
"trail-not-in-list": "",
|
||||||
"trail-not-shared": "Нет общего доступа",
|
"trail-not-shared": "Нет общего доступа",
|
||||||
"trail-saved-successfully": "Трек сохранён",
|
"trail-saved-successfully": "Трек сохранён",
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
"already-account": "已注册账户?",
|
"already-account": "已注册账户?",
|
||||||
"altitude": "海拔",
|
"altitude": "海拔",
|
||||||
"amenity": "友好性",
|
"amenity": "友好性",
|
||||||
|
"ammenity": "",
|
||||||
"api-documentation": "API 文档",
|
"api-documentation": "API 文档",
|
||||||
"apply-user-settings": "",
|
"apply-user-settings": "",
|
||||||
"attraction": "景点",
|
"attraction": "景点",
|
||||||
@@ -135,6 +136,7 @@
|
|||||||
"enable-auto-routing": "启用自动路由",
|
"enable-auto-routing": "启用自动路由",
|
||||||
"english": "英语",
|
"english": "英语",
|
||||||
"entry": "日程",
|
"entry": "日程",
|
||||||
|
"error-copying-trail": "",
|
||||||
"error-creating-user": "创建用户错误",
|
"error-creating-user": "创建用户错误",
|
||||||
"error-disabling-strava-integration": "禁用strava集成时出错",
|
"error-disabling-strava-integration": "禁用strava集成时出错",
|
||||||
"error-during-login": "登录错误",
|
"error-during-login": "登录错误",
|
||||||
@@ -357,6 +359,8 @@
|
|||||||
"search-trails": "搜索路线",
|
"search-trails": "搜索路线",
|
||||||
"select-list": "选择列表",
|
"select-list": "选择列表",
|
||||||
"selected": "已选",
|
"selected": "已选",
|
||||||
|
"set-private": "",
|
||||||
|
"set-public": "",
|
||||||
"settings": "设置",
|
"settings": "设置",
|
||||||
"settings-notification-comment-mention": "有人在评论中提到您",
|
"settings-notification-comment-mention": "有人在评论中提到您",
|
||||||
"settings-notification-list-create": "您关注的用户创建了一个列表",
|
"settings-notification-list-create": "您关注的用户创建了一个列表",
|
||||||
@@ -412,6 +416,7 @@
|
|||||||
"top-speed": "最高速度",
|
"top-speed": "最高速度",
|
||||||
"tourism": "旅游",
|
"tourism": "旅游",
|
||||||
"trail": "{n, plural, =1 {路线} other {路线}}",
|
"trail": "{n, plural, =1 {路线} other {路线}}",
|
||||||
|
"trail-copied-successfully": "",
|
||||||
"trail-not-in-list": "",
|
"trail-not-in-list": "",
|
||||||
"trail-not-shared": "未与任何人分享",
|
"trail-not-shared": "未与任何人分享",
|
||||||
"trail-saved-successfully": "路线保存成功",
|
"trail-saved-successfully": "路线保存成功",
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import cryptoRandomString from "crypto-random-string";
|
||||||
import type { Actor } from "./activitypub/actor";
|
import type { Actor } from "./activitypub/actor";
|
||||||
import type { Category } from "./category";
|
import type { Category } from "./category";
|
||||||
import type { Comment } from "./comment";
|
import type { Comment } from "./comment";
|
||||||
@@ -6,7 +7,7 @@ import type { SummitLog } from "./summit_log";
|
|||||||
import type { Tag } from "./tag";
|
import type { Tag } from "./tag";
|
||||||
import type { TrailLike } from "./trail_like";
|
import type { TrailLike } from "./trail_like";
|
||||||
import type { TrailShare } from "./trail_share";
|
import type { TrailShare } from "./trail_share";
|
||||||
import type { Waypoint } from "./waypoint";
|
import { Waypoint } from "./waypoint";
|
||||||
|
|
||||||
class Trail {
|
class Trail {
|
||||||
id?: string;
|
id?: string;
|
||||||
@@ -64,12 +65,13 @@ class Trail {
|
|||||||
thumbnail?: number,
|
thumbnail?: number,
|
||||||
photos?: string[],
|
photos?: string[],
|
||||||
gpx?: string,
|
gpx?: string,
|
||||||
|
gpx_data?: string,
|
||||||
category?: Category,
|
category?: Category,
|
||||||
waypoints?: Waypoint[],
|
waypoints?: Waypoint[],
|
||||||
summit_logs?: SummitLog[],
|
summit_logs?: SummitLog[],
|
||||||
comments?: Comment[],
|
comments?: Comment[],
|
||||||
shares?: TrailShare[],
|
shares?: TrailShare[],
|
||||||
tags?: string[],
|
tags?: Tag[],
|
||||||
description?: string
|
description?: string
|
||||||
created?: string
|
created?: string
|
||||||
}
|
}
|
||||||
@@ -89,7 +91,7 @@ class Trail {
|
|||||||
this.lon = params?.lon;
|
this.lon = params?.lon;
|
||||||
this.thumbnail = params?.thumbnail ?? 0;
|
this.thumbnail = params?.thumbnail ?? 0;
|
||||||
this.photos = params?.photos ?? [];
|
this.photos = params?.photos ?? [];
|
||||||
this.tags = []
|
this.tags = [];
|
||||||
this.gpx = params?.gpx;
|
this.gpx = params?.gpx;
|
||||||
this.like_count = 0
|
this.like_count = 0
|
||||||
this.expand = {
|
this.expand = {
|
||||||
@@ -97,12 +99,39 @@ class Trail {
|
|||||||
waypoints_via_trail: params?.waypoints ?? [],
|
waypoints_via_trail: params?.waypoints ?? [],
|
||||||
summit_logs_via_trail: params?.summit_logs ?? [],
|
summit_logs_via_trail: params?.summit_logs ?? [],
|
||||||
comments_via_trail: params?.comments ?? [],
|
comments_via_trail: params?.comments ?? [],
|
||||||
trail_share_via_trail: params?.shares ?? []
|
trail_share_via_trail: params?.shares ?? [],
|
||||||
|
gpx_data: params?.gpx_data,
|
||||||
|
tags: params?.tags
|
||||||
}
|
}
|
||||||
this.description = params?.description ?? "";
|
this.description = params?.description ?? "";
|
||||||
this.created = params?.created;
|
this.created = params?.created;
|
||||||
this.author = "000000000000000"
|
this.author = "000000000000000"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static from(orig: Trail): Trail {
|
||||||
|
return new Trail(orig.name, {
|
||||||
|
date: orig.date,
|
||||||
|
description: orig.description,
|
||||||
|
difficulty: orig.difficulty,
|
||||||
|
distance: orig.distance,
|
||||||
|
duration: orig.duration,
|
||||||
|
elevation_gain: orig.elevation_gain,
|
||||||
|
elevation_loss: orig.elevation_loss,
|
||||||
|
lat: orig.lat,
|
||||||
|
lon: orig.lon,
|
||||||
|
location: orig.location,
|
||||||
|
public: orig.public,
|
||||||
|
tags: orig.expand?.tags,
|
||||||
|
category: orig.expand?.category,
|
||||||
|
gpx_data: orig.expand?.gpx_data,
|
||||||
|
waypoints: orig.expand?.waypoints_via_trail?.map(wp => new Waypoint(wp.lat, wp.lon, {
|
||||||
|
id: cryptoRandomString({ length: 15 }),
|
||||||
|
description: wp.description,
|
||||||
|
icon: wp.icon,
|
||||||
|
name: wp.name,
|
||||||
|
})),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TrailFilter {
|
interface TrailFilter {
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ export async function trails_create(trail: Trail, photos: File[], gpx: File | Bl
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function trails_update(oldTrail: Trail, newTrail: Trail, photos?: File[], gpx?: File | Blob | null) {
|
export async function trails_update(oldTrail: Trail, newTrail: Trail, photos?: File[], gpx?: File | Blob | null, exclude?: (keyof Trail)[]) {
|
||||||
newTrail.author = oldTrail.author
|
newTrail.author = oldTrail.author
|
||||||
|
|
||||||
const waypointUpdates = compareObjectArrays<Waypoint>(oldTrail.expand?.waypoints_via_trail ?? [], newTrail.expand?.waypoints_via_trail ?? []);
|
const waypointUpdates = compareObjectArrays<Waypoint>(oldTrail.expand?.waypoints_via_trail ?? [], newTrail.expand?.waypoints_via_trail ?? []);
|
||||||
@@ -295,7 +295,7 @@ export async function trails_update(oldTrail: Trail, newTrail: Trail, photos?: F
|
|||||||
newTrail.tags = newTrail.tags.filter(t => t != tag.id);
|
newTrail.tags = newTrail.tags.filter(t => t != tag.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
const formData = objectToFormData(newTrail, ["expand"])
|
const formData = objectToFormData(newTrail, ["expand", ...(exclude ?? [])])
|
||||||
|
|
||||||
if (gpx) {
|
if (gpx) {
|
||||||
formData.append("gpx", gpx);
|
formData.append("gpx", gpx);
|
||||||
|
|||||||
@@ -272,6 +272,7 @@
|
|||||||
clearUndoRedoStack();
|
clearUndoRedoStack();
|
||||||
|
|
||||||
if ($formData.expand!.gpx_data) {
|
if ($formData.expand!.gpx_data) {
|
||||||
|
$formData.id ??= cryptoRandomString({ length: 15 });
|
||||||
const gpx = GPX.parse($formData.expand!.gpx_data);
|
const gpx = GPX.parse($formData.expand!.gpx_data);
|
||||||
if (!(gpx instanceof Error)) {
|
if (!(gpx instanceof Error)) {
|
||||||
if (gpx.rte && !gpx.trk) {
|
if (gpx.rte && !gpx.trk) {
|
||||||
|
|||||||
@@ -17,7 +17,14 @@ export const load: Load = async ({ params, fetch, url }) => {
|
|||||||
|
|
||||||
let trail: Trail;
|
let trail: Trail;
|
||||||
if (params.id === "new") {
|
if (params.id === "new") {
|
||||||
|
// duplicate trail
|
||||||
|
if (url.searchParams.has("orig")) {
|
||||||
|
const originalId = url.searchParams.get("orig")!;
|
||||||
|
const originalTrail = await trails_show(originalId, undefined, undefined, true, fetch);
|
||||||
|
trail = Trail.from(originalTrail)
|
||||||
|
} else {
|
||||||
trail = new Trail("", { category: categories[0] });
|
trail = new Trail("", { category: categories[0] });
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
trail = await trails_show(params.id, undefined, url.searchParams.get("share") ?? undefined, true, fetch);
|
trail = await trails_show(params.id, undefined, url.searchParams.get("share") ?? undefined, true, fetch);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,11 +81,11 @@
|
|||||||
localStorage.removeItem(TRAIL_LIST_FILTER_STORAGE_KEY);
|
localStorage.removeItem(TRAIL_LIST_FILTER_STORAGE_KEY);
|
||||||
});
|
});
|
||||||
|
|
||||||
async function handleFilterUpdate() {
|
async function handleFilterUpdate(resetPagination: boolean = true) {
|
||||||
loading = true;
|
loading = true;
|
||||||
persistFilter();
|
persistFilter();
|
||||||
|
|
||||||
await paginate(1, pagination.items, false);
|
await paginate(resetPagination ? 1 : pagination.page, pagination.items);
|
||||||
|
|
||||||
loading = false;
|
loading = false;
|
||||||
}
|
}
|
||||||
@@ -97,11 +97,13 @@
|
|||||||
await doPaginate(newPage, items);
|
await doPaginate(newPage, items);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
let apiError: APIError = err;
|
let apiError: APIError = err;
|
||||||
if (apiError.status == 413) { // content too large
|
if (apiError.status == 413) {
|
||||||
|
// content too large
|
||||||
|
|
||||||
let newItems = 10;
|
let newItems = 10;
|
||||||
|
|
||||||
if (items == 12 || items == 24 || items == 48 || items == 96) { // cards view
|
if (items == 12 || items == 24 || items == 48 || items == 96) {
|
||||||
|
// cards view
|
||||||
if (items > 96) {
|
if (items > 96) {
|
||||||
newItems = 96;
|
newItems = 96;
|
||||||
} else if (items > 48) {
|
} else if (items > 48) {
|
||||||
@@ -153,14 +155,14 @@
|
|||||||
categories={page.data.categories}
|
categories={page.data.categories}
|
||||||
bind:filter
|
bind:filter
|
||||||
{filterExpanded}
|
{filterExpanded}
|
||||||
onupdate={handleFilterUpdate}
|
onupdate={() => handleFilterUpdate()}
|
||||||
></TrailFilterPanel>
|
></TrailFilterPanel>
|
||||||
<TrailList
|
<TrailList
|
||||||
bind:filter
|
bind:filter
|
||||||
{loading}
|
{loading}
|
||||||
{trails}
|
{trails}
|
||||||
{pagination}
|
{pagination}
|
||||||
onupdate={handleFilterUpdate}
|
onupdate={() => handleFilterUpdate(false)}
|
||||||
onpagination={paginate}
|
onpagination={paginate}
|
||||||
></TrailList>
|
></TrailList>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
Reference in New Issue
Block a user