feat: model ordering

This commit is contained in:
Timothy J. Baek 2024-05-31 13:11:04 -07:00
parent 9c67a94542
commit fc2b314c4f
4 changed files with 84 additions and 7 deletions

6
package-lock.json generated
View File

@ -24,6 +24,7 @@
"katex": "^0.16.9",
"marked": "^9.1.0",
"pyodide": "^0.26.0-alpha.4",
"sortablejs": "^1.15.2",
"svelte-sonner": "^0.3.19",
"tippy.js": "^6.3.7",
"uuid": "^9.0.1"
@ -6913,6 +6914,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/sortablejs": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.2.tgz",
"integrity": "sha512-FJF5jgdfvoKn1MAKSdGs33bIqLi3LmsgVTliuX6iITj834F+JRQZN90Z93yql8h0K2t0RwDPBmxwlbZfDcxNZA=="
},
"node_modules/source-map-js": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",

View File

@ -64,6 +64,7 @@
"katex": "^0.16.9",
"marked": "^9.1.0",
"pyodide": "^0.26.0-alpha.4",
"sortablejs": "^1.15.2",
"svelte-sonner": "^0.3.19",
"tippy.js": "^6.3.7",
"uuid": "^9.0.1"

View File

@ -29,8 +29,24 @@ export const getModels = async (token: string = '') => {
models = models
.filter((models) => models)
// Sort the models
.sort((a, b) => {
// Compare case-insensitively
// Check if models have position property
const aHasPosition = a.info?.meta?.position !== undefined;
const bHasPosition = b.info?.meta?.position !== undefined;
// If both a and b have the position property
if (aHasPosition && bHasPosition) {
return a.info.meta.position - b.info.meta.position;
}
// If only a has the position property, it should come first
if (aHasPosition) return -1;
// If only b has the position property, it should come first
if (bHasPosition) return 1;
// Compare case-insensitively by name for models without position property
const lowerA = a.name.toLowerCase();
const lowerB = b.name.toLowerCase();
@ -39,8 +55,8 @@ export const getModels = async (token: string = '') => {
// If same case-insensitively, sort by original strings,
// lowercase will come before uppercase due to ASCII values
if (a < b) return -1;
if (a > b) return 1;
if (a.name < b.name) return -1;
if (a.name > b.name) return 1;
return 0; // They are equal
});

View File

@ -1,9 +1,11 @@
<script lang="ts">
import { toast } from 'svelte-sonner';
import Sortable from 'sortablejs';
import fileSaver from 'file-saver';
const { saveAs } = fileSaver;
import { onMount, getContext } from 'svelte';
import { onMount, getContext, tick } from 'svelte';
import { WEBUI_NAME, modelfiles, models, settings, user } from '$lib/stores';
import { addNewModel, deleteModelById, getModelInfos, updateModelById } from '$lib/apis/models';
@ -12,6 +14,7 @@
import { goto } from '$app/navigation';
import { getModels } from '$lib/apis';
import EllipsisHorizontal from '../icons/EllipsisHorizontal.svelte';
import ModelMenu from './Models/ModelMenu.svelte';
@ -22,6 +25,9 @@
let importFiles;
let modelsImportInputElement: HTMLInputElement;
let _models = [];
let sortable = null;
let searchValue = '';
const deleteModelHandler = async (model) => {
@ -42,6 +48,7 @@
}
await models.set(await getModels(localStorage.token));
_models = $models;
};
const cloneModelHandler = async (model) => {
@ -109,6 +116,7 @@
}
await models.set(await getModels(localStorage.token));
_models = $models;
};
const downloadModels = async (models) => {
@ -118,13 +126,58 @@
saveAs(blob, `models-export-${Date.now()}.json`);
};
onMount(() => {
const positionChangeHanlder = async () => {
// Get the new order of the models
const modelIds = Array.from(document.getElementById('model-list').children).map((child) =>
child.id.replace('model-item-', '')
);
// Update the position of the models
for (const [index, id] of modelIds.entries()) {
const model = $models.find((m) => m.id === id);
if (model) {
let info = model.info;
if (!info) {
info = {
id: model.id,
name: model.name,
meta: {
position: index
},
params: {}
};
}
info.meta = {
...info.meta,
position: index
};
await updateModelById(localStorage.token, info.id, info);
}
}
await tick();
await models.set(await getModels(localStorage.token));
};
onMount(async () => {
// Legacy code to sync localModelfiles with models
_models = $models;
localModelfiles = JSON.parse(localStorage.getItem('modelfiles') ?? '[]');
if (localModelfiles) {
console.log(localModelfiles);
}
// SortableJS
sortable = new Sortable(document.getElementById('model-list'), {
animation: 150,
onUpdate: async (event) => {
console.log(event);
positionChangeHanlder();
}
});
});
</script>
@ -202,12 +255,13 @@
<hr class=" dark:border-gray-850" />
<div class=" my-2 mb-5">
{#each $models.filter((m) => searchValue === '' || m.name
<div class=" my-2 mb-5" id="model-list">
{#each _models.filter((m) => searchValue === '' || m.name
.toLowerCase()
.includes(searchValue.toLowerCase())) as model}
<div
class=" flex space-x-4 cursor-pointer w-full px-3 py-2 dark:hover:bg-white/5 hover:bg-black/5 rounded-xl"
id="model-item-{model.id}"
>
<a
class=" flex flex-1 space-x-3.5 cursor-pointer w-full"