Add WI entry sorting. Add new entry flash

This commit is contained in:
Cohee 2023-10-05 23:30:18 +03:00
parent 96be2ebf35
commit 85a63b3bb3
4 changed files with 94 additions and 17 deletions

View File

@ -2750,19 +2750,19 @@
<div id="world_popup_delete" class="menu_button fa-solid fa-trash-can redWarningBG" title="Delete World Info" data-i18n="[title]Delete World Info"></div>
<input type="search" class="text_pole textarea_compact" data-i18n="[placeholder]Search..." id="world_info_search" placeholder="Search...">
<select id="world_info_sort_order" class="margin0">
<option data-order="asc" data-field="comment" value="0">Title A-Z</option>
<option data-order="desc" data-field="comment" value="1">Title Z-A</option>
<option data-rule="priority" value="2">Priority</option>
<option data-order="asc" data-field="content" data-rule="length" value="3">Content size</option>
<option data-order="desc" data-field="content" data-rule="length" value="4">Content size</option>
<option data-rule="priority" value="0">Priority</option>
<option data-order="asc" data-field="comment" value="1">Title A-Z</option>
<option data-order="desc" data-field="comment" value="2">Title Z-A</option>
<option data-order="asc" data-field="content" data-rule="length" value="3">Tokens</option>
<option data-order="desc" data-field="content" data-rule="length" value="4">Tokens</option>
<option data-order="asc" data-field="depth" value="5">Depth ↗</option>
<option data-order="desc" data-field="depth" value="6">Depth ↘</option>
<option data-order="asc" data-field="order" value="7">Order ↗</option>
<option data-order="desc" data-field="order" value="8">Order ↘</option>
<option data-order="asc" data-field="uid" value="9">UID ↗</option>
<option data-order="desc" data-field="uid" value="10">UID ↘</option>
<option data-order="asc" data-field="order" value="11">Probability</option>
<option data-order="desc" data-field="order" value="12">Probability</option>
<option data-order="asc" data-field="probability" value="11">Trigger%</option>
<option data-order="desc" data-field="probability" value="12">Trigger%</option>
</select>
<div id="world_info_pagination"></div>
</div>

View File

@ -596,6 +596,7 @@ function getCurrentChatId() {
const talkativeness_default = 0.5;
const depth_prompt_depth_default = 4;
const per_page_default = 50;
var is_advanced_char_open = false;
@ -922,7 +923,7 @@ async function printCharacters(fullRefresh = false) {
const storageKey = 'Characters_PerPage';
$("#rm_print_characters_pagination").pagination({
dataSource: getEntitiesList({ doFilter: true }),
pageSize: Number(localStorage.getItem(storageKey)) || 50,
pageSize: Number(localStorage.getItem(storageKey)) || per_page_default,
sizeChangerOptions: [10, 25, 50, 100, 250, 500, 1000],
pageRange: 1,
pageNumber: saveCharactersPage || 1,
@ -5487,7 +5488,7 @@ function select_rm_info(type, charId, previousCharId = null) {
}
try {
const perPage = Number(localStorage.getItem('Characters_PerPage'));
const perPage = Number(localStorage.getItem('Characters_PerPage')) || per_page_default;
const page = Math.floor(charIndex / perPage) + 1;
const selector = `#rm_print_characters_block [title^="${charId}"]`;
$('#rm_print_characters_pagination').pagination('go', page);
@ -5522,7 +5523,7 @@ function select_rm_info(type, charId, previousCharId = null) {
return;
}
const perPage = Number(localStorage.getItem('Characters_PerPage'));
const perPage = Number(localStorage.getItem('Characters_PerPage')) || per_page_default;
const page = Math.floor(charIndex / perPage) + 1;
$('#rm_print_characters_pagination').pagination('go', page);
const selector = `#rm_print_characters_block [grid="${charId}"]`;

View File

@ -12,7 +12,7 @@ export const PAGINATION_TEMPLATE = '<%= rangeStart %>-<%= rangeEnd %> of <%= tot
* Navigation options for pagination.
* @enum {number}
*/
export const navigation_option = { none: 0, previous: 1, last: 2, };
export const navigation_option = { none: -2000, previous: -1000, };
export function escapeHtml(str) {
return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');

View File

@ -1,5 +1,5 @@
import { saveSettings, callPopup, substituteParams, getRequestHeaders, chat_metadata, this_chid, characters, saveCharacterDebounced, menu_type, eventSource, event_types } from "../script.js";
import { download, debounce, initScrollHeight, resetScrollHeight, parseJsonFile, extractDataFromPng, getFileBuffer, getCharaFilename, getSortableDelay, escapeRegex, PAGINATION_TEMPLATE, navigation_option } from "./utils.js";
import { download, debounce, initScrollHeight, resetScrollHeight, parseJsonFile, extractDataFromPng, getFileBuffer, getCharaFilename, getSortableDelay, escapeRegex, PAGINATION_TEMPLATE, navigation_option, waitUntilCondition } from "./utils.js";
import { getContext } from "./extensions.js";
import { NOTE_MODULE_NAME, metadata_keys, shouldWIAddPrompt } from "./authors-note.js";
import { registerSlashCommand } from "./slash-commands.js";
@ -51,6 +51,7 @@ let updateEditor = (navigation) => { navigation; };
// Do not optimize. updateEditor is a function that is updated by the displayWorldEntries with new data.
const worldInfoFilter = new FilterHelper(() => updateEditor());
const SORT_ORDER_KEY = 'world_info_sort_order';
const InputWidthReference = $("#WIInputWidthReference");
@ -163,6 +164,7 @@ function setWorldInfoSettings(settings, data) {
$("#world_editor_select").append(`<option value='${i}'>${item}</option>`);
});
$('#world_info_sort_order').val(localStorage.getItem(SORT_ORDER_KEY) || '0');
$("#world_editor_select").trigger("change");
}
@ -234,6 +236,49 @@ function getWIElement(name) {
return wiElement;
}
/**
* @param {any[]} data WI entries
* @returns {any[]} Sorted data
*/
function sortEntries(data) {
const option = $('#world_info_sort_order').find(":selected");
const sortField = option.data('field');
const sortOrder = option.data('order');
const sortRule = option.data('rule');
const orderSign = sortOrder === 'asc' ? 1 : -1;
if (sortRule === 'priority') {
// First constant, then normal, then disabled. Then sort by order
data.sort((a, b) => {
const aValue = a.constant ? 0 : a.disable ? 2 : 1;
const bValue = b.constant ? 0 : b.disable ? 2 : 1;
return (aValue - bValue || b.order - a.order);
});
} else {
data.sort((a, b) => {
const aValue = a[sortField];
const bValue = b[sortField];
// Sort strings
if (typeof aValue === 'string' && typeof bValue === 'string') {
if (sortRule === 'length') {
// Sort by string length
return orderSign * (aValue.length - bValue.length);
} else {
// Sort by A-Z ordinal
return orderSign * aValue.localeCompare(bValue);
}
}
// Sort numbers
return orderSign * (Number(aValue) - Number(bValue));
});
}
return data;
}
function nullWorldInfo() {
toastr.info("Create or import a new World Info file first.", "World Info is not set", { timeOut: 10000, preventDuplicates: true });
}
@ -263,8 +308,9 @@ function displayWorldEntries(name, data, navigation = navigation_option.none) {
// Sort the entries array by displayIndex and uid
entriesArray.sort((a, b) => a.displayIndex - b.displayIndex || a.uid - b.uid);
entriesArray = sortEntries(entriesArray);
entriesArray = worldInfoFilter.applyFilters(entriesArray);
callback(entriesArray);
typeof callback === 'function' && callback(entriesArray);
return entriesArray;
}
@ -275,9 +321,10 @@ function displayWorldEntries(name, data, navigation = navigation_option.none) {
}
const storageKey = 'WI_PerPage';
const perPageDefault = 25;
$("#world_info_pagination").pagination({
dataSource: getDataArray,
pageSize: Number(localStorage.getItem(storageKey)) || 25,
pageSize: Number(localStorage.getItem(storageKey)) || perPageDefault,
sizeChangerOptions: [10, 25, 50, 100],
showSizeChanger: true,
pageRange: 1,
@ -320,8 +367,28 @@ function displayWorldEntries(name, data, navigation = navigation_option.none) {
}
});
if (navigation === navigation_option.last) {
$("#world_info_pagination").pagination('go', $("#world_info_pagination").pagination('getTotalPage'));
if (typeof navigation === 'number' && Number(navigation) >= 0) {
const selector = `#world_popup_entries_list [uid="${navigation}"]`;
const data = getDataArray();
const uidIndex = data.findIndex(x => x.uid === navigation);
const perPage = Number(localStorage.getItem(storageKey)) || perPageDefault;
const page = Math.floor(uidIndex / perPage) + 1;
$("#world_info_pagination").pagination('go', page);
waitUntilCondition(() => document.querySelector(selector) !== null).finally(() => {
const element = $(selector);
if (element.length === 0) {
console.log(`Could not find element for uid ${navigation}`);
return;
}
const elementOffset = element.offset();
const parentOffset = element.parent().offset();
const scrollOffset = elementOffset.top - parentOffset.top;
$('#WorldInfo').scrollTop(scrollOffset);
element.addClass('flash animated');
setTimeout(() => element.removeClass('flash animated'), 2000);
});
}
$("#world_popup_new").off('click').on('click', () => {
@ -437,6 +504,7 @@ function deleteOriginalDataValue(data, uid) {
function getWorldEntry(name, data, entry) {
const template = $("#entry_edit_template .world_entry").clone();
template.data("uid", entry.uid);
template.attr("uid", entry.uid);
// key
const keyInput = template.find('textarea[name="key"]');
@ -1004,7 +1072,7 @@ function createWorldInfoEntry(name, data) {
const newEntry = { uid: newUid, ...newEntryTemplate };
data.entries[newUid] = newEntry;
updateEditor(navigation_option.last);
updateEditor(newUid);
}
async function _save(name, data) {
@ -1907,6 +1975,14 @@ jQuery(() => {
worldInfoFilter.setFilterData(FILTER_TYPES.WORLD_INFO_SEARCH, term);
});
$('#world_info_sort_order').on('change', function(e) {
if (e.target instanceof HTMLOptionElement) {
localStorage.setItem(SORT_ORDER_KEY, e.target.value);
}
updateEditor(navigation_option.none);
})
// Not needed on mobile
const deviceInfo = getDeviceInfo();
if (deviceInfo && deviceInfo.device.type === 'desktop') {