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