Tag Folders: show hidden numbers

- Show hidden counts for folders, and total
- Rework resizing of character names to shrink additional data first
- Better placement for group numbers
This commit is contained in:
Wolfsblvt 2024-03-07 02:15:41 +01:00
parent 18379ec602
commit fb97f563b7
5 changed files with 83 additions and 26 deletions

View File

@ -5000,10 +5000,9 @@
<div class="flex-container wide100pLess70px gap5px group_select_container">
<div class="wide100p group_name_block character_name_block">
<div class="ch_name"></div>
<small class="group_select_unit" data="characters">group of</small>
<small class="character_version group_select_counter">5</small>
<small class="group_select_unit character_unit_name" data="characters">characters</small>
<small class="character_version group_select_counter"></small>
</div>
<small class="character_name_block_sub_line">in this group</small>
<i class='group_fav_icon fa-solid fa-star'></i>
<input class="ch_fav" value="" hidden />
<div class="group_select_block_list"></div>
@ -5020,8 +5019,8 @@
<div class="wide100p character_name_block">
<span class="ch_name"></span>
<small class="character_version bogus_folder_counter"></small>
<small class="bogus_folder_unit character_unit_name" data="characters">characters</small>
</div>
<small class="character_name_block_sub_line bogus_folder_hidden_counter"></small>
<div class="bogus_folder_avatars_block avatars_inline avatars_inline_small tags tags_inline"></div>
</div>
</div>

View File

@ -1175,7 +1175,7 @@ function getEmptyBlock() {
const texts = ['Here be dragons', 'Otterly empty', 'Kiwibunga', 'Pump-a-Rum', 'Croak it'];
const roll = new Date().getMinutes() % icons.length;
const emptyBlock = `
<div class="empty_block">
<div class="text_block empty_block">
<i class="fa-solid ${icons[roll]} fa-4x"></i>
<h1>${texts[roll]}</h1>
<p>There are no items to display.</p>
@ -1183,6 +1183,20 @@ function getEmptyBlock() {
return $(emptyBlock);
}
/**
* @param {number} hidden Number of hidden characters
*/
function getHiddenBlock(hidden) {
const hiddenBlick = `
<div class="text_block hidden_block">
<small>
<p>${hidden} ${hidden > 1 ? 'characters' : 'character'} hidden.</p>
<div class="fa-solid fa-circle-info opacity50p" data-i18n="[title]Characters and groups hidden by filters or closed folders" title="Characters and groups hidden by filters or closed folders"></div>
</small>
</div>`;
return $(hiddenBlick);
}
function getCharacterBlock(item, id) {
let this_avatar = default_avatar;
if (item.avatar != 'none') {
@ -1261,19 +1275,28 @@ async function printCharacters(fullRefresh = false) {
if (!data.length) {
$(listId).append(getEmptyBlock());
}
let displayCount = 0;
for (const i of data) {
switch (i.type) {
case 'character':
$(listId).append(getCharacterBlock(i.item, i.id));
displayCount++;
break;
case 'group':
$(listId).append(getGroupBlock(i.item));
displayCount++;
break;
case 'tag':
$(listId).append(getTagBlock(i.item, i.entities ?? entities));
$(listId).append(getTagBlock(i.item, i.entities, i.hidden));
break;
}
}
const hidden = (characters.length + groups.length) - displayCount;
if (hidden > 0) {
$(listId).append(getHiddenBlock(hidden));
}
eventSource.emit(event_types.CHARACTER_PAGE_LOADED);
},
afterSizeSelectorChange: function (e) {
@ -1327,11 +1350,14 @@ export function getEntitiesList({ doFilter = false, doSort = true } = {}) {
// For folders, we remember the sub entities so they can be displayed later, even if they might be filtered
// Those sub entities should be filtered and have the search filters applied too
if (entity.type === 'tag') {
let subEntities = filterByTagState(entities, { subForEntity: entity });
let subEntities = filterByTagState(entities, { subForEntity: entity, filterHidden: false });
const subCount = subEntities.length;
subEntities = filterByTagState(entities, { subForEntity: entity });
if (doFilter) {
subEntities = entitiesFilter.applyFilters(subEntities);
}
entity.entities = subEntities;
entity.hidden = subCount - subEntities.length;
}
}

View File

@ -542,11 +542,8 @@ export function getGroupBlock(group) {
template.find('.group_fav_icon').css('display', 'none');
template.addClass(group.fav ? 'is_fav' : '');
template.find('.ch_fav').val(group.fav);
template.find('.group_select_counter').text(count);
template.find('.group_select_counter').text(`${count} ${count != 1 ? 'characters' : 'character'}`);
template.find('.group_select_block_list').append(namesList.join(''));
if (count == 1) {
template.find('.character_unit_name').text('character');
}
// Display inline tags
const tags = getTagsList(group.id);

View File

@ -86,9 +86,10 @@ let tag_map = {};
* @param {Object} param1 Optional parameters, explained below.
* @param {Boolean} [param1.globalDisplayFilters] When enabled, applies the final filter for the global list. Icludes filtering out entities in closed/hidden folders and empty folders.
* @param {Object} [param1.subForEntity] When given an entity, the list of entities gets filtered specifically for that one as a "sub list", filtering out other tags, elements not tagged for this and hidden elements.
* @param {Boolean} [param1.filterHidden] Optional switch with which filtering out hidden items (from closed folders) can be disabled.
* @returns The filtered list of entities
*/
function filterByTagState(entities, { globalDisplayFilters = false, subForEntity = undefined } = {}) {
function filterByTagState(entities, { globalDisplayFilters = false, subForEntity = undefined, filterHidden = true } = {}) {
const filterData = structuredClone(entitiesFilter.getFilterData(FILTER_TYPES.TAG));
entities = entities.filter(entity => {
@ -108,7 +109,7 @@ function filterByTagState(entities, { globalDisplayFilters = false, subForEntity
entities = entities.filter(entity => {
// Hide entities that are in a closed folder, unless that one is opened
if (entity.type !== 'tag' && closedFolders.some(f => entitiesFilter.isElementTagged(entity, f.id) && !filterData.selected.includes(f.id))) {
if (filterHidden && entity.type !== 'tag' && closedFolders.some(f => entitiesFilter.isElementTagged(entity, f.id) && !filterData.selected.includes(f.id))) {
return false;
}
@ -123,13 +124,13 @@ function filterByTagState(entities, { globalDisplayFilters = false, subForEntity
}
if (subForEntity !== undefined && subForEntity.type === 'tag') {
entities = filterTagSubEntities(subForEntity.item, entities);
entities = filterTagSubEntities(subForEntity.item, entities, { filterHidden : filterHidden });
}
return entities;
}
function filterTagSubEntities(tag, entities) {
function filterTagSubEntities(tag, entities, { filterHidden = true } = {}) {
const filterData = structuredClone(entitiesFilter.getFilterData(FILTER_TYPES.TAG));
const closedFolders = entities.filter(x => x.type === 'tag' && TAG_FOLDER_TYPES[x.item.folder_type] === TAG_FOLDER_TYPES.CLOSED);
@ -141,7 +142,7 @@ function filterTagSubEntities(tag, entities) {
}
// Hide entities that are in a closed folder, unless the closed folder is opened or we display a closed folder
if (sub.type !== 'tag' && TAG_FOLDER_TYPES[tag.folder_type] !== TAG_FOLDER_TYPES.CLOSED && closedFolders.some(f => entitiesFilter.isElementTagged(sub, f.id) && !filterData.selected.includes(f.id))) {
if (filterHidden && sub.type !== 'tag' && TAG_FOLDER_TYPES[tag.folder_type] !== TAG_FOLDER_TYPES.CLOSED && closedFolders.some(f => entitiesFilter.isElementTagged(sub, f.id) && !filterData.selected.includes(f.id))) {
return false;
}
@ -198,7 +199,14 @@ function chooseBogusFolder(source, tagId, remove = false) {
}
}
function getTagBlock(item, entities) {
/**
* Builds the tag block for the specified item.
* @param {Object} item The tag item
* @param {*} entities The list ob sub items for this tag
* @param {*} hidden A count of how many sub items are hidden
* @returns The html for the tag block
*/
function getTagBlock(item, entities, hidden = 0) {
let count = entities.length;
const tagFolder = TAG_FOLDER_TYPES[item.folder_type];
@ -208,11 +216,9 @@ function getTagBlock(item, entities) {
template.attr({ 'tagid': item.id, 'id': `BogusFolder${item.id}` });
template.find('.avatar').css({ 'background-color': item.color, 'color': item.color2 }).attr('title', `[Folder] ${item.name}`);
template.find('.ch_name').text(item.name).attr('title', `[Folder] ${item.name}`);
template.find('.bogus_folder_counter').text(count);
template.find('.bogus_folder_hidden_counter').text(hidden > 0 ? `${hidden} hidden` : '');
template.find('.bogus_folder_counter').text(`${count} ${count != 1 ? 'characters' : 'character'}`);
template.find('.bogus_folder_icon').addClass(tagFolder.fa_icon);
if (count == 1) {
template.find('.character_unit_name').text('character');
}
// Fill inline character images
buildAvatarList(template.find('.bogus_folder_avatars_block'), entities);

View File

@ -1312,19 +1312,26 @@ input[type="file"] {
align-self: center;
}
#rm_print_characters_block .text_block {
height: 100%;
width: 100%;
opacity: 0.5;
margin: 0 auto 1px auto;
padding: 5px;
}
#rm_print_characters_block .empty_block {
display: flex;
flex-direction: column;
gap: 10px;
flex-wrap: wrap;
text-align: center;
height: 100%;
width: 100%;
opacity: 0.5;
justify-content: center;
margin: 0 auto;
align-items: center;
}
#rm_print_characters_block .hidden_block p {
display: inline;
}
#rm_print_characters_block {
overflow-y: auto;
@ -1626,6 +1633,15 @@ input[type=search]:focus::-webkit-search-cancel-button {
align-items: baseline;
flex-direction: row;
gap: 5px;
margin-bottom: 6px;
}
.character_name_block_sub_line {
position: absolute;
right: 0px;
top: calc(var(--mainFontSize) + 2px);
font-size: calc(var(--mainFontSize) * 0.6);
color: var(--grey7070a);
}
.ch_avatar_url {
@ -1651,15 +1667,28 @@ input[type=search]:focus::-webkit-search-cancel-button {
}
/*applies to both groups and solos chars in the char list*/
#rm_print_characters_block .character_select_container,
#rm_print_characters_block .group_select_container {
position: relative;
}
#rm_print_characters_block .ch_name,
.avatar-container .ch_name {
flex: 1;
flex: 1 1 auto;
white-space: nowrap;
overflow: hidden;
text-wrap: nowrap;
text-overflow: ellipsis;
display: block;
}
#rm_print_characters_block .character_name_block > :last-child {
flex: 0 100000 auto; /* Force shrinking first */
overflow: hidden;
text-wrap: nowrap;
text-overflow: ellipsis;
}
.bogus_folder_select:hover,
.character_select:hover,
.avatar-container:hover {