Improves multiselect (#921)
* initial commit * fixes open in new tab --------- Co-authored-by: Christian Beutel <>
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
import { onMount, tick } from "svelte";
|
||||
import type { Snippet } from "svelte";
|
||||
import TrailDropdown from "$lib/components/trail/trail_dropdown.svelte";
|
||||
import { goto } from "$app/navigation";
|
||||
|
||||
interface Props {
|
||||
filter?: TrailFilter | null;
|
||||
@@ -313,6 +314,15 @@
|
||||
handleHoverUpdate(trail);
|
||||
}
|
||||
|
||||
function handleTrailClick(e: Event, trail: Trail) {
|
||||
if (selection && selection.size > 0) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
handleSelectionUpdate(trail);
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
function setItemsPerPage() {
|
||||
localStorage.setItem("paginationItems", pagination.items.toString());
|
||||
onpagination?.(1, pagination.items);
|
||||
@@ -420,6 +430,7 @@
|
||||
<a
|
||||
class="max-w-full flex-1"
|
||||
class:basis-full={selectedDisplayOption === "list"}
|
||||
onclick={(e) => handleTrailClick(e,trail)}
|
||||
href="/trail/view/@{trail.author}{trail.domain
|
||||
? `@${trail.domain}`
|
||||
: ''}/{trail.id}"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { goto } from "$app/navigation";
|
||||
import type { Trail, TrailFilter } from "$lib/models/trail";
|
||||
import {
|
||||
formatDistance,
|
||||
@@ -7,21 +8,27 @@
|
||||
} from "$lib/util/format_util";
|
||||
import { _ } from "svelte-i18n";
|
||||
import type { SelectItem } from "../base/select.svelte";
|
||||
import { goto } from "$app/navigation";
|
||||
import { getFileURL } from "$lib/util/file_util";
|
||||
import ShareInfo from "../share_info.svelte";
|
||||
|
||||
|
||||
interface Props {
|
||||
tableHeader: SelectItem[];
|
||||
trails?: Trail[] | null;
|
||||
selection: Set<Trail> | undefined;
|
||||
filter?: TrailFilter | null;
|
||||
items: number;
|
||||
onsort?: (value: any) => void
|
||||
onTrailSelect?: (value: any) => void
|
||||
onsort?: (value: any) => void;
|
||||
onTrailSelect?: (value: any) => void;
|
||||
}
|
||||
|
||||
let { tableHeader, trails = null, selection, filter = null, items, onsort, onTrailSelect: onselect }: Props = $props();
|
||||
let {
|
||||
tableHeader,
|
||||
trails = null,
|
||||
selection,
|
||||
filter = null,
|
||||
items,
|
||||
onsort,
|
||||
onTrailSelect: onselect,
|
||||
}: Props = $props();
|
||||
|
||||
function getColumnWidth(columnValue: string): string {
|
||||
switch (columnValue) {
|
||||
@@ -44,31 +51,29 @@
|
||||
}
|
||||
|
||||
function setSelectedTrail(e: Event, trail: Trail) {
|
||||
e.stopPropagation()
|
||||
e.stopPropagation();
|
||||
|
||||
if (trail !== undefined) {
|
||||
if (onselect !== undefined) {
|
||||
onselect(trail)
|
||||
onselect(trail);
|
||||
} else {
|
||||
console.error("undefined event handler");
|
||||
}
|
||||
else {
|
||||
console.error("undefined event handler")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setSelectedAllTrails(e: Event) {
|
||||
onselect?.(undefined)
|
||||
onselect?.(undefined);
|
||||
}
|
||||
|
||||
function isSelected(trail: Trail): boolean {
|
||||
if (selection === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (trail !== undefined) {
|
||||
for (const strail of selection) {
|
||||
if (strail !== undefined && strail.id === trail.id)
|
||||
return true;
|
||||
if (strail !== undefined && strail.id === trail.id) return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,13 +81,26 @@
|
||||
}
|
||||
|
||||
function allSelected(): boolean {
|
||||
if (selection === undefined || trails === undefined || trails === null) {
|
||||
if (
|
||||
selection === undefined ||
|
||||
trails === undefined ||
|
||||
trails === null
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return selection.size === trails.length;
|
||||
}
|
||||
|
||||
function handleTrailClick(trail: Trail) {
|
||||
if (selection && selection.size > 0) {
|
||||
onselect?.(trail);
|
||||
} else {
|
||||
goto(
|
||||
`/trail/view/@${trail.author}${trail.domain ? `@${trail.domain}` : ""}/${trail.id}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
@@ -92,7 +110,9 @@
|
||||
<thead>
|
||||
<tr class="bg-secondary-hover">
|
||||
<th
|
||||
class="p-4 text-left text-sm font-medium {getColumnWidth("select")}"
|
||||
class="p-4 text-left text-sm font-medium {getColumnWidth(
|
||||
'select',
|
||||
)}"
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<input
|
||||
@@ -130,12 +150,7 @@
|
||||
{#each trails as trail}
|
||||
<tr
|
||||
class="border-t border-input-border cursor-pointer hover:bg-secondary-hover transition-colors"
|
||||
onclick={() =>
|
||||
goto(
|
||||
`/trail/view/@${trail.author}${
|
||||
trail.domain ? `@${trail.domain}` : ""
|
||||
}/${trail.id}`,
|
||||
)}
|
||||
onclick={() => handleTrailClick(trail)}
|
||||
>
|
||||
<td class="p-4 text-sm">
|
||||
<div class="flex items-center">
|
||||
@@ -143,14 +158,18 @@
|
||||
type="checkbox"
|
||||
class="w-4 h-4 bg-input-background accent-primary border-input-border focus:ring-input-ring focus:ring-2"
|
||||
checked={isSelected(trail)}
|
||||
onclick={(e: Event) => setSelectedTrail(e, trail)}
|
||||
onclick={(e: Event) =>
|
||||
setSelectedTrail(e, trail)}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="flex justify-between items-center text-sm relative"
|
||||
>
|
||||
<div class="p-4 w-[75%] line-clamp-2 wrap-anywhere" title={trail.name}>
|
||||
<div
|
||||
class="p-4 w-[75%] line-clamp-2 wrap-anywhere"
|
||||
title={trail.name}
|
||||
>
|
||||
{trail.name}
|
||||
</div>
|
||||
<div class="flex flex-col items-center">
|
||||
|
||||
Reference in New Issue
Block a user