diff options
author | (quasar) nebula <qznebula@protonmail.com> | 2024-03-19 19:46:47 -0300 |
---|---|---|
committer | (quasar) nebula <qznebula@protonmail.com> | 2025-02-25 20:03:28 -0400 |
commit | a94150e3fc6d5276310c97a7693a378462a7b393 (patch) | |
tree | 0ff63fa74cd4528d2cf1ccf0ad471a26ea108a6c | |
parent | d91f879aee6cd624256be3cf5ddbcd638cc6c264 (diff) |
content, client: listArtTagNetwork: art tag stat switcher
-rw-r--r-- | src/content/dependencies/listArtTagNetwork.js | 105 | ||||
-rw-r--r-- | src/static/css/site.css | 15 | ||||
-rw-r--r-- | src/static/js/client/art-tag-network.js | 136 | ||||
-rw-r--r-- | src/static/js/client/index.js | 2 | ||||
-rw-r--r-- | src/strings-default.yaml | 14 |
5 files changed, 265 insertions, 7 deletions
diff --git a/src/content/dependencies/listArtTagNetwork.js b/src/content/dependencies/listArtTagNetwork.js index 830c5929..56d72e17 100644 --- a/src/content/dependencies/listArtTagNetwork.js +++ b/src/content/dependencies/listArtTagNetwork.js @@ -27,6 +27,20 @@ export default { {directAncestorArtTags: ancestorsB}) => ancestorsA.length - ancestorsB.length); + const getStats = (artTag) => ({ + directUses: + artTag.directlyTaggedInThings.length, + + totalUses: + unique([ + ...artTag.indirectlyTaggedInThings, + ...artTag.directlyTaggedInThings, + ]).length, + + descendants: + artTag.allDescendantArtTags.length, + }); + const recursive = (artTag, depth) => { const descendantNodes = (empty(artTag.directDescendantArtTags) @@ -52,8 +66,11 @@ export default { ? unique(artTag.directAncestorArtTags.map(recursiveGetRootAncestor)) : null); + const stats = getStats(artTag); + return { artTag, + stats, descendantNodes, ancestorRootArtTags, }; @@ -121,6 +138,15 @@ export default { directory: queryNode.artTag.directory, + directUses: + queryNode.stats.directUses, + + totalUses: + queryNode.stats.totalUses, + + descendants: + queryNode.stats.descendants, + representsRoot: rootArtTags.includes(queryNode.artTag), @@ -148,6 +174,45 @@ export default { generate(data, relations, {html, language}) { const prefix = `listingPage.listArtTags.network`; + const wrapTag = (dataNode, relationsNode) => [ + html.tag('span', {class: 'network-tag'}, + language.$(prefix, 'tag', { + tag: + relationsNode.artTagLink, + })), + + html.tag('span', {class: 'network-tag'}, + {class: 'with-stat'}, + {style: 'display: none'}, + + language.$(prefix, 'tag.withStat', { + tag: + (dataNode.representsRoot + ? relationsNode.artTagLink.slots({ + anchor: true, + hash: dataNode.directory, + }) + : relationsNode.artTagLink), + + stat: + language.$(prefix, 'tag.withStat.stat', { + stat: [ + html.tag('span', {class: 'network-tag-stat'}, + {class: 'network-tag-direct-uses-stat'}, + dataNode.directUses.toString()), + + html.tag('span', {class: 'network-tag-stat'}, + {class: 'network-tag-total-uses-stat'}, + dataNode.totalUses.toString()), + + html.tag('span', {class: 'network-tag-stat'}, + {class: 'network-tag-descendants-stat'}, + dataNode.descendants.toString()), + ], + }) + })) + ]; + const recursive = (dataNode, relationsNode, depth) => [ html.tag('dt', { @@ -158,7 +223,9 @@ export default { (depth === 0 ? (relationsNode.ancestorTagLinks ? language.$(prefix, 'root.withAncestors', { - tag: relationsNode.artTagLink, + tag: + wrapTag(dataNode, relationsNode), + ancestors: language.formatUnitList( stitchArrays({ @@ -171,7 +238,9 @@ export default { }))), }) : language.$(prefix, 'root.jumpToTop', { - tag: relationsNode.artTagLink, + tag: + wrapTag(dataNode, relationsNode), + link: html.tag('a', {href: '#top'}, language.$(prefix, 'root.jumpToTop.link')), @@ -179,13 +248,11 @@ export default { : (dataNode.representsRoot ? language.$(prefix, 'descendant.jumpToRoot', { tag: - relationsNode.artTagLink.slots({ - anchor: true, - hash: dataNode.directory, - }), + wrapTag(dataNode, relationsNode), }) : language.$(prefix, 'descendant', { - tag: relationsNode.artTagLink, + tag: + wrapTag(dataNode, relationsNode), })))), dataNode.descendantNodes && @@ -204,6 +271,30 @@ export default { type: 'custom', content: [ + html.tag('p', {id: 'network-stat-line'}, + language.$(prefix, 'statLine', { + stat: [ + html.tag('a', {id: 'network-stat-none'}, + {href: '#'}, + language.$(prefix, 'statLine.none')), + + html.tag('a', {id: 'network-stat-total-uses'}, + {href: '#'}, + {style: 'display: none'}, + language.$(prefix, 'statLine.totalUses')), + + html.tag('a', {id: 'network-stat-direct-uses'}, + {href: '#'}, + {style: 'display: none'}, + language.$(prefix, 'statLine.directUses')), + + html.tag('a', {id: 'network-stat-descendants'}, + {href: '#'}, + {style: 'display: none'}, + language.$(prefix, 'statLine.descendants')), + ], + })), + html.tag('dl', {id: 'network-top-dl'}, [ html.tag('dt', {id: 'top'}, language.$(prefix, 'jumpToRoot.title')), diff --git a/src/static/css/site.css b/src/static/css/site.css index e8c2b17f..125756cd 100644 --- a/src/static/css/site.css +++ b/src/static/css/site.css @@ -2022,6 +2022,21 @@ html[data-url-key="localized.listing"][data-url-value0="tags/network"] dl dd:not padding-bottom: 20px; } +html[data-url-key="localized.listing"][data-url-value0="tags/network"] #network-stat-line { + padding-left: 10px; + margin-left: 20px; +} + +html[data-url-key="localized.listing"][data-url-value0="tags/network"] #network-stat-line a { + text-decoration: underline; + text-decoration-style: dotted; +} + +/* CSS rule order pls */ +html[data-url-key="localized.listing"][data-url-value0="tags/network"] #network-stat-line a:hover { + text-decoration-style: solid; +} + html[data-url-key="localized.listing"][data-url-value0="tags/network"] dl dt { padding-left: 10px; margin-left: 20px; diff --git a/src/static/js/client/art-tag-network.js b/src/static/js/client/art-tag-network.js new file mode 100644 index 00000000..fc5f6526 --- /dev/null +++ b/src/static/js/client/art-tag-network.js @@ -0,0 +1,136 @@ +/* eslint-env browser */ + +import {cssProp} from '../client-util.js'; + +import {atOffset, stitchArrays} from '../../shared-util/sugar.js'; + +export const info = { + id: 'artTagNetworkInfo', + + noneStatLink: null, + totalUsesStatLink: null, + directUsesStatLink: null, + descendantsStatLink: null, + + tagsWithoutStats: null, + tagsWithStats: null, + + totalUsesStats: null, + directUsesStats: null, + descendantsStats: null, +}; + +export function getPageReferences() { + if ( + document.documentElement.dataset.urlKey !== 'localized.listing' || + document.documentElement.dataset.urlValue0 !== 'tags/network' + ) { + return; + } + + info.noneStatLink = + document.getElementById('network-stat-none'); + + info.totalUsesStatLink = + document.getElementById('network-stat-total-uses'); + + info.directUsesStatLink = + document.getElementById('network-stat-direct-uses'); + + info.descendantsStatLink = + document.getElementById('network-stat-descendants'); + + info.tagsWithoutStats = + document.querySelectorAll('.network-tag:not(.with-stat)'); + + info.tagsWithStats = + document.querySelectorAll('.network-tag.with-stat'); + + info.totalUsesStats = + Array.from(document.getElementsByClassName('network-tag-total-uses-stat')); + + info.directUsesStats = + Array.from(document.getElementsByClassName('network-tag-direct-uses-stat')); + + info.descendantsStats = + Array.from(document.getElementsByClassName('network-tag-descendants-stat')); +} + +export function addPageListeners() { + if (!info.noneStatLink) return; + + const linkOrder = [ + info.noneStatLink, + info.totalUsesStatLink, + info.directUsesStatLink, + info.descendantsStatLink, + ]; + + const statsOrder = [ + null, + info.totalUsesStats, + info.directUsesStats, + info.descendantsStats, + ]; + + const stitched = + stitchArrays({ + link: linkOrder, + stats: statsOrder, + }); + + for (const [index, {link}] of stitched.entries()) { + const next = atOffset(stitched, index, +1, {wrap: true}); + + link.addEventListener('click', domEvent => { + domEvent.preventDefault(); + + cssProp(link, 'display', 'none'); + cssProp(next.link, 'display', null); + + if (next.stats === null) { + hideArtTagNetworkStats(); + } else { + showArtTagNetworkStats(next.stats); + } + }); + } +} + +function showArtTagNetworkStats(stats) { + for (const tagElement of info.tagsWithoutStats) { + cssProp(tagElement, 'display', 'none'); + } + + for (const tagElement of info.tagsWithStats) { + cssProp(tagElement, 'display', null); + } + + const allStats = [ + ...info.totalUsesStats, + ...info.directUsesStats, + ...info.descendantsStats, + ]; + + const otherStats = + allStats + .filter(stat => !stats.includes(stat)); + + for (const statElement of otherStats) { + cssProp(statElement, 'display', 'none'); + } + + for (const statElement of stats) { + cssProp(statElement, 'display', null); + } +} + +function hideArtTagNetworkStats() { + for (const tagElement of info.tagsWithoutStats) { + cssProp(tagElement, 'display', null); + } + + for (const tagElement of info.tagsWithStats) { + cssProp(tagElement, 'display', 'none'); + } +} diff --git a/src/static/js/client/index.js b/src/static/js/client/index.js index 63fbc5d6..81ea3415 100644 --- a/src/static/js/client/index.js +++ b/src/static/js/client/index.js @@ -5,6 +5,7 @@ import '../group-contributions-table.js'; import * as additionalNamesBoxModule from './additional-names-box.js'; import * as albumCommentarySidebarModule from './album-commentary-sidebar.js'; import * as artTagGalleryFilterModule from './art-tag-gallery-filter.js'; +import * as artTagNetworkModule from './art-tag-network.js'; import * as artistExternalLinkTooltipModule from './artist-external-link-tooltip.js'; import * as cssCompatibilityAssistantModule from './css-compatibility-assistant.js'; import * as datetimestampTooltipModule from './datetimestamp-tooltip.js'; @@ -26,6 +27,7 @@ export const modules = [ additionalNamesBoxModule, albumCommentarySidebarModule, artTagGalleryFilterModule, + artTagNetworkModule, artistExternalLinkTooltipModule, cssCompatibilityAssistantModule, datetimestampTooltipModule, diff --git a/src/strings-default.yaml b/src/strings-default.yaml index b94f8b77..a56bacf2 100644 --- a/src/strings-default.yaml +++ b/src/strings-default.yaml @@ -1710,6 +1710,13 @@ listingPage: title: "Jump to one of the upper-most tags:" item: "{TAG}" + statLine: + _: "Displaying tag info: {STAT}" + none: "name only" + directUses: "uses (direct only)" + totalUses: "uses (total)" + descendants: "descendants" + root: _: "{TAG}" @@ -1724,6 +1731,13 @@ listingPage: _: "{TAG}" jumpToRoot: "Jump to: {TAG}" + tag: + _: "{TAG}" + + withStat: + _: "{STAT} {TAG}" + stat: "({STAT})" + orphanArtTags: title: "These tags don't have any descendants or ancestors:" item: "{TAG}" |