mirror of
https://github.com/open-webui/open-webui
synced 2025-06-25 17:57:20 +00:00
Merge pull request #14944 from silentoplayz/sort-feedbacks
feat: Implement Client-Side Sorting for Feedback History Table
This commit is contained in:
commit
c2b4b76a90
@ -21,10 +21,16 @@
|
|||||||
import FeedbackModal from './FeedbackModal.svelte';
|
import FeedbackModal from './FeedbackModal.svelte';
|
||||||
import EllipsisHorizontal from '$lib/components/icons/EllipsisHorizontal.svelte';
|
import EllipsisHorizontal from '$lib/components/icons/EllipsisHorizontal.svelte';
|
||||||
|
|
||||||
|
import ChevronUp from '$lib/components/icons/ChevronUp.svelte';
|
||||||
|
import ChevronDown from '$lib/components/icons/ChevronDown.svelte';
|
||||||
|
|
||||||
export let feedbacks = [];
|
export let feedbacks = [];
|
||||||
|
|
||||||
let page = 1;
|
let page = 1;
|
||||||
$: paginatedFeedbacks = feedbacks.slice((page - 1) * 10, page * 10);
|
$: paginatedFeedbacks = sortedFeedbacks.slice((page - 1) * 10, page * 10);
|
||||||
|
|
||||||
|
let orderBy: string = 'updated_at';
|
||||||
|
let direction: 'asc' | 'desc' = 'desc';
|
||||||
|
|
||||||
type Feedback = {
|
type Feedback = {
|
||||||
id: string;
|
id: string;
|
||||||
@ -49,6 +55,45 @@
|
|||||||
lost: number;
|
lost: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function setSortKey(key: string) {
|
||||||
|
if (orderBy === key) {
|
||||||
|
direction = direction === 'asc' ? 'desc' : 'asc';
|
||||||
|
} else {
|
||||||
|
orderBy = key;
|
||||||
|
if (key === 'user' || key === 'model_id') {
|
||||||
|
direction = 'asc';
|
||||||
|
} else {
|
||||||
|
direction = 'desc';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
page = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$: sortedFeedbacks = [...feedbacks].sort((a, b) => {
|
||||||
|
let aVal, bVal;
|
||||||
|
|
||||||
|
switch (orderBy) {
|
||||||
|
case 'user':
|
||||||
|
aVal = a.user?.name || '';
|
||||||
|
bVal = b.user?.name || '';
|
||||||
|
return direction === 'asc' ? aVal.localeCompare(bVal) : bVal.localeCompare(aVal);
|
||||||
|
case 'model_id':
|
||||||
|
aVal = a.data.model_id || '';
|
||||||
|
bVal = b.data.model_id || '';
|
||||||
|
return direction === 'asc' ? aVal.localeCompare(bVal) : bVal.localeCompare(aVal);
|
||||||
|
case 'rating':
|
||||||
|
aVal = a.data.rating;
|
||||||
|
bVal = b.data.rating;
|
||||||
|
return direction === 'asc' ? aVal - bVal : bVal - aVal;
|
||||||
|
case 'updated_at':
|
||||||
|
aVal = a.updated_at;
|
||||||
|
bVal = b.updated_at;
|
||||||
|
return direction === 'asc' ? aVal - bVal : bVal - aVal;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let showFeedbackModal = false;
|
let showFeedbackModal = false;
|
||||||
let selectedFeedback = null;
|
let selectedFeedback = null;
|
||||||
|
|
||||||
@ -162,20 +207,96 @@
|
|||||||
class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-850 dark:text-gray-400 -translate-y-0.5"
|
class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-850 dark:text-gray-400 -translate-y-0.5"
|
||||||
>
|
>
|
||||||
<tr class="">
|
<tr class="">
|
||||||
<th scope="col" class="px-3 text-right cursor-pointer select-none w-0">
|
<th
|
||||||
{$i18n.t('User')}
|
scope="col"
|
||||||
|
class="px-3 py-1.5 cursor-pointer select-none w-3"
|
||||||
|
on:click={() => setSortKey('user')}
|
||||||
|
>
|
||||||
|
<div class="flex gap-1.5 items-center justify-end">
|
||||||
|
{$i18n.t('User')}
|
||||||
|
{#if orderBy === 'user'}
|
||||||
|
<span class="font-normal">
|
||||||
|
{#if direction === 'asc'}
|
||||||
|
<ChevronUp className="size-2" />
|
||||||
|
{:else}
|
||||||
|
<ChevronDown className="size-2" />
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
{:else}
|
||||||
|
<span class="invisible">
|
||||||
|
<ChevronUp className="size-2" />
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
<th scope="col" class="px-3 pr-1.5 cursor-pointer select-none">
|
<th
|
||||||
{$i18n.t('Models')}
|
scope="col"
|
||||||
|
class="px-3 pr-1.5 cursor-pointer select-none"
|
||||||
|
on:click={() => setSortKey('model_id')}
|
||||||
|
>
|
||||||
|
<div class="flex gap-1.5 items-center">
|
||||||
|
{$i18n.t('Models')}
|
||||||
|
{#if orderBy === 'model_id'}
|
||||||
|
<span class="font-normal">
|
||||||
|
{#if direction === 'asc'}
|
||||||
|
<ChevronUp className="size-2" />
|
||||||
|
{:else}
|
||||||
|
<ChevronDown className="size-2" />
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
{:else}
|
||||||
|
<span class="invisible">
|
||||||
|
<ChevronUp className="size-2" />
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
<th scope="col" class="px-3 py-1.5 text-right cursor-pointer select-none w-fit">
|
<th
|
||||||
{$i18n.t('Result')}
|
scope="col"
|
||||||
|
class="px-3 py-1.5 text-right cursor-pointer select-none w-fit"
|
||||||
|
on:click={() => setSortKey('rating')}
|
||||||
|
>
|
||||||
|
<div class="flex gap-1.5 items-center justify-end">
|
||||||
|
{$i18n.t('Result')}
|
||||||
|
{#if orderBy === 'rating'}
|
||||||
|
<span class="font-normal">
|
||||||
|
{#if direction === 'asc'}
|
||||||
|
<ChevronUp className="size-2" />
|
||||||
|
{:else}
|
||||||
|
<ChevronDown className="size-2" />
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
{:else}
|
||||||
|
<span class="invisible">
|
||||||
|
<ChevronUp className="size-2" />
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
<th scope="col" class="px-3 py-1.5 text-right cursor-pointer select-none w-0">
|
<th
|
||||||
{$i18n.t('Updated At')}
|
scope="col"
|
||||||
|
class="px-3 py-1.5 text-right cursor-pointer select-none w-0"
|
||||||
|
on:click={() => setSortKey('updated_at')}
|
||||||
|
>
|
||||||
|
<div class="flex gap-1.5 items-center justify-end">
|
||||||
|
{$i18n.t('Updated At')}
|
||||||
|
{#if orderBy === 'updated_at'}
|
||||||
|
<span class="font-normal">
|
||||||
|
{#if direction === 'asc'}
|
||||||
|
<ChevronUp className="size-2" />
|
||||||
|
{:else}
|
||||||
|
<ChevronDown className="size-2" />
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
{:else}
|
||||||
|
<span class="invisible">
|
||||||
|
<ChevronUp className="size-2" />
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
<th scope="col" class="px-3 py-1.5 text-right cursor-pointer select-none w-0"> </th>
|
<th scope="col" class="px-3 py-1.5 text-right cursor-pointer select-none w-0"> </th>
|
||||||
|
Loading…
Reference in New Issue
Block a user