Add documentation

Minor refactoring
This commit is contained in:
artisticMink 2023-11-05 18:23:14 +01:00
parent 36cf68a9f4
commit 99ee1b887a
1 changed files with 112 additions and 42 deletions

View File

@ -10,10 +10,12 @@ import {
getRequestHeaders, getRequestHeaders,
this_chid this_chid
} from "../script.js"; } from "../script.js";
import {favsToHotswap} from "./RossAscends-mods.js"; import {favsToHotswap} from "./RossAscends-mods.js";
import {convertCharacterToPersona} from "./personas.js"; import {convertCharacterToPersona} from "./personas.js";
import {createTagInput, getTagKeyForCharacter, tag_map} from "./tags.js"; import {createTagInput, getTagKeyForCharacter, tag_map} from "./tags.js";
// Utility object for popup messages.
const popupMessage = { const popupMessage = {
deleteChat(characterCount) { deleteChat(characterCount) {
return `<h3>Delete ${characterCount} characters?</h3> return `<h3>Delete ${characterCount} characters?</h3>
@ -25,29 +27,29 @@ const popupMessage = {
}, },
} }
const toggleFavoriteHighlight = (characterId) => { /**
const element = document.getElementById(`CharID${characterId}`); * Static object representing the actions of the
element.classList.toggle('is_fav'); * character context menu override.
} */
class CharacterGroupOverlayState {
static browse = 0;
static select = 1;
}
class CharacterContextMenu { class CharacterContextMenu {
/**
* Tag one or more characters,
* opens a popup.
*
* @param selectedCharacters
*/
static tag = (selectedCharacters) => { static tag = (selectedCharacters) => {
BulkTagPopupHandler.show(selectedCharacters); BulkTagPopupHandler.show(selectedCharacters);
} }
/** /**
* Duplicate a character * Duplicate one or more characters
* *
* @param characterId * @param characterId
* @returns {Promise<Response>} * @returns {Promise<Response>}
*/ */
static duplicate = async (characterId) => { static duplicate = async (characterId) => {
const character = CharacterContextMenu.getCharacter(characterId); const character = CharacterContextMenu.#getCharacter(characterId);
return fetch('/dupecharacter', { return fetch('/dupecharacter', {
method: 'POST', method: 'POST',
@ -58,13 +60,15 @@ class CharacterContextMenu {
/** /**
* Favorite a character * Favorite a character
* and toggle its ui element. * and highlight it.
* *
* @param characterId * @param characterId
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
static favorite = async (characterId) => { static favorite = async (characterId) => {
const character = CharacterContextMenu.getCharacter(characterId); const character = CharacterContextMenu.#getCharacter(characterId);
// Only set fav for V2 spec
const data = { const data = {
name: character.name, name: character.name,
avatar: character.avatar, avatar: character.avatar,
@ -80,22 +84,34 @@ class CharacterContextMenu {
headers: getRequestHeaders(), headers: getRequestHeaders(),
body: JSON.stringify(data), body: JSON.stringify(data),
}).then((response) => { }).then((response) => {
if (response.ok) toggleFavoriteHighlight(characterId) if (response.ok) {
else response.json().then(json => toastr.error('Character not saved. Error: ' + json.message + '. Field: ' + json.error)); const element = document.getElementById(`CharID${characterId}`);
element.classList.toggle('is_fav');
} else {
response.json().then(json => toastr.error('Character not saved. Error: ' + json.message + '. Field: ' + json.error));
}
}); });
} }
/** /**
* Convert the given characters to personas. * Convert one or more characters to persona,
* Shows popup for each. * may open a popup for one or more characters.
* *
* @param characterId * @param characterId
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
static persona = async (characterId) => await convertCharacterToPersona(characterId); static persona = async (characterId) => await convertCharacterToPersona(characterId);
/**
* Delete one or more characters,
* opens a popup.
*
* @param characterId
* @param deleteChats
* @returns {Promise<void>}
*/
static delete = async (characterId, deleteChats = false) => { static delete = async (characterId, deleteChats = false) => {
const character = CharacterContextMenu.getCharacter(characterId); const character = CharacterContextMenu.#getCharacter(characterId);
return fetch('/deletecharacter', { return fetch('/deletecharacter', {
method: 'POST', method: 'POST',
@ -123,12 +139,19 @@ class CharacterContextMenu {
} }
}) })
} }
eventSource.emit('characterDeleted', { id: this_chid, character: characters[this_chid] }); eventSource.emit('characterDeleted', { id: this_chid, character: characters[this_chid] });
}); });
} }
static getCharacter = (characterId) => characters[characterId] ?? null; static #getCharacter = (characterId) => characters[characterId] ?? null;
/**
* Show the context menu at the given position
*
* @param positionX
* @param positionY
*/
static show = (positionX, positionY) => { static show = (positionX, positionY) => {
let contextMenu = document.getElementById(BulkEditOverlay.contextMenuId); let contextMenu = document.getElementById(BulkEditOverlay.contextMenuId);
contextMenu.style.left = `${positionX}px`; contextMenu.style.left = `${positionX}px`;
@ -137,8 +160,16 @@ class CharacterContextMenu {
document.getElementById(BulkEditOverlay.contextMenuId).classList.remove('hidden'); document.getElementById(BulkEditOverlay.contextMenuId).classList.remove('hidden');
} }
/**
* Hide the context menu
*/
static hide = () => document.getElementById(BulkEditOverlay.contextMenuId).classList.add('hidden'); static hide = () => document.getElementById(BulkEditOverlay.contextMenuId).classList.add('hidden');
/**
* Sets up the context menu for the given overlay
*
* @param characterGroupOverlay
*/
constructor(characterGroupOverlay) { constructor(characterGroupOverlay) {
const contextMenuItems = [ const contextMenuItems = [
{id: 'character_context_menu_favorite', callback: characterGroupOverlay.handleContextMenuFavorite}, {id: 'character_context_menu_favorite', callback: characterGroupOverlay.handleContextMenuFavorite},
@ -153,7 +184,7 @@ class CharacterContextMenu {
} }
/** /**
* Appends/Removes the bulk tag popup * Represents a tag control not bound to a single character
*/ */
class BulkTagPopupHandler { class BulkTagPopupHandler {
static #getHtml = (characterIds) => { static #getHtml = (characterIds) => {
@ -180,6 +211,11 @@ class BulkTagPopupHandler {
` `
}; };
/**
* Append and show the tag control
*
* @param characters - The characters assigned to this control
*/
static show(characters) { static show(characters) {
document.body.insertAdjacentHTML('beforeend', this.#getHtml(characters)); document.body.insertAdjacentHTML('beforeend', this.#getHtml(characters));
createTagInput('#bulkTagInput', '#bulkTagList'); createTagInput('#bulkTagInput', '#bulkTagList');
@ -187,6 +223,9 @@ class BulkTagPopupHandler {
document.querySelector('#bulk_tag_popup_reset').addEventListener('click', this.resetTags.bind(this, characters)); document.querySelector('#bulk_tag_popup_reset').addEventListener('click', this.resetTags.bind(this, characters));
} }
/**
* Hide and remove the tag control
*/
static hide() { static hide() {
let popupElement = document.querySelector('#bulk_tag_shadow_popup'); let popupElement = document.querySelector('#bulk_tag_shadow_popup');
if (popupElement) { if (popupElement) {
@ -194,6 +233,11 @@ class BulkTagPopupHandler {
} }
} }
/**
* Empty the tag map for the given characters
*
* @param characterIds
*/
static resetTags(characterIds) { static resetTags(characterIds) {
characterIds.forEach((characterId) => { characterIds.forEach((characterId) => {
const key = getTagKeyForCharacter(characterId); const key = getTagKeyForCharacter(characterId);
@ -202,6 +246,20 @@ class BulkTagPopupHandler {
} }
} }
class CharacterGroupOverlayState {
/**
*
* @type {number}
*/
static browse = 0;
/**
*
* @type {number}
*/
static select = 1;
}
/** /**
* Implement a SingletonPattern, allowing access to the group overlay instance * Implement a SingletonPattern, allowing access to the group overlay instance
* from everywhere via (new CharacterGroupOverlay()) * from everywhere via (new CharacterGroupOverlay())
@ -273,7 +331,14 @@ class BulkEditOverlay {
bulkEditOverlayInstance = Object.freeze(this); bulkEditOverlayInstance = Object.freeze(this);
} }
/**
* Set the overlay to browse mode
*/
browseState = () => this.state = CharacterGroupOverlayState.browse; browseState = () => this.state = CharacterGroupOverlayState.browse;
/**
* Set the overlay to select mode
*/
selectState = () => this.state = CharacterGroupOverlayState.select; selectState = () => this.state = CharacterGroupOverlayState.select;
/** /**
@ -294,6 +359,32 @@ class BulkEditOverlay {
grid.addEventListener('click', this.handleCancelClick); grid.addEventListener('click', this.handleCancelClick);
} }
/**
* Handle state changes
*
*
*/
handleStateChange = () => {
switch (this.state) {
case CharacterGroupOverlayState.browse:
this.container.classList.remove(BulkEditOverlay.selectModeClass);
this.#enableClickEventsForCharacters();
this.clearSelectedCharacters();
this.disableContextMenu();
this.#disableBulkEditButtonHighlight();
CharacterContextMenu.hide();
break;
case CharacterGroupOverlayState.select:
this.container.classList.add(BulkEditOverlay.selectModeClass);
this.#disableClickEventsForCharacters();
this.enableContextMenu();
this.#enableBulkEditButtonHighlight();
break;
}
this.stateChangeCallbacks.forEach(callback => callback(this.state));
}
/** /**
* Block the browsers native context menu and * Block the browsers native context menu and
* set a click event to hide the custom context menu. * set a click event to hide the custom context menu.
@ -331,27 +422,6 @@ class BulkEditOverlay {
this.state = CharacterGroupOverlayState.browse; this.state = CharacterGroupOverlayState.browse;
} }
handleStateChange = () => {
switch (this.state) {
case CharacterGroupOverlayState.browse:
this.container.classList.remove(BulkEditOverlay.selectModeClass);
this.#enableClickEventsForCharacters();
this.clearSelectedCharacters();
this.disableContextMenu();
this.#disableBulkEditButtonHighlight();
CharacterContextMenu.hide();
break;
case CharacterGroupOverlayState.select:
this.container.classList.add(BulkEditOverlay.selectModeClass);
this.#disableClickEventsForCharacters();
this.enableContextMenu();
this.#enableBulkEditButtonHighlight();
break;
}
this.stateChangeCallbacks.forEach(callback => callback(this.state));
}
#enableClickEventsForCharacters = () => [...this.container.getElementsByClassName(BulkEditOverlay.characterClass)] #enableClickEventsForCharacters = () => [...this.container.getElementsByClassName(BulkEditOverlay.characterClass)]
.forEach(element => element.removeEventListener('click', this.toggleCharacterSelected)); .forEach(element => element.removeEventListener('click', this.toggleCharacterSelected));