From ad7c99605b2683c1426aacf857a6136130993815 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Tue, 4 Jul 2023 11:37:07 -0300 Subject: content: listArtistsByLatestContribution (stub) This doesn't quite include the updates to this listing discussed in #199 and #208 yet. Flash contributions are divided into their own list just like in the updated "by Contributions" listing, though. --- .../listArtistsByLatestContribution.js | 179 +++++++++++++++++++++ src/listing-spec.js | 153 +----------------- 2 files changed, 180 insertions(+), 152 deletions(-) create mode 100644 src/content/dependencies/listArtistsByLatestContribution.js diff --git a/src/content/dependencies/listArtistsByLatestContribution.js b/src/content/dependencies/listArtistsByLatestContribution.js new file mode 100644 index 0000000..c0135dc --- /dev/null +++ b/src/content/dependencies/listArtistsByLatestContribution.js @@ -0,0 +1,179 @@ +import {stitchArrays} from '../../util/sugar.js'; +import { + compareDates, + filterMultipleArrays, + getLatestDate, + sortAlphabetically, + sortMultipleArrays, +} from '../../util/wiki-data.js'; + +export default { + contentDependencies: ['generateListingPage', 'linkArtist'], + extraDependencies: ['html', 'language', 'wikiData'], + + sprawl({artistData, wikiInfo}) { + return { + artistData, + enableFlashesAndGames: wikiInfo.enableFlashesAndGames, + }; + }, + + query(sprawl, spec) { + const query = { + spec, + enableFlashesAndGames: sprawl.enableFlashesAndGames, + }; + + const queryContributionInfo = (artistsKey, datesKey, datelessArtistsKey, fn) => { + const artists = sortAlphabetically(sprawl.artistData.slice()); + const dates = artists.map(artist => fn(artist)); + + const {removed: [datelessArtists]} = + filterMultipleArrays(artists, dates, (artist, date) => date); + + sortMultipleArrays(artists, dates, + (a, b, dateA, dateB) => + compareDates(dateA, dateB, {latestFirst: true})); + + query[artistsKey] = artists; + query[datesKey] = dates.map(dateNumber => new Date(dateNumber)); + query[datelessArtistsKey] = datelessArtists; + }; + + queryContributionInfo( + 'artistsByTrackContributions', + 'datesByTrackContributions', + 'datelessArtistsByTrackContributions', + artist => + getLatestDate([ + ...artist.tracksAsContributor.map(track => +track.date), + ...artist.tracksAsArtist.map(track => +track.date), + ])); + + queryContributionInfo( + 'artistsByArtworkContributions', + 'datesByArtworkContributions', + 'datelessArtistsByArtworkContributions', + artist => + getLatestDate([ + // TODO: Per-artwork dates, see #90. + ...artist.tracksAsCoverArtist.map(track => +track.coverArtDate), + ...artist.albumsAsCoverArtist.map(album => +album.coverArtDate), + ...artist.albumsAsWallpaperArtist.map(album => +album.coverArtDate), + ...artist.albumsAsBannerArtist.map(album => +album.coverArtDate), + ])); + + if (sprawl.enableFlashesAndGames) { + queryContributionInfo( + 'artistsByFlashContributions', + 'datesByFlashContributions', + 'datelessArtistsByFlashContributions', + artist => + getLatestDate([ + ...artist.flashesAsContributor.map(flash => +flash.date), + ])); + } + + return query; + }, + + relations(relation, query) { + const relations = {}; + + relations.page = + relation('generateListingPage', query.spec); + + relations.artistLinksByTrackContributions = + query.artistsByTrackContributions + .map(artist => relation('linkArtist', artist)); + + relations.artistLinksByArtworkContributions = + query.artistsByArtworkContributions + .map(artist => relation('linkArtist', artist)); + + if (query.enableFlashesAndGames) { + relations.artistLinksByFlashContributions = + query.artistsByFlashContributions + .map(artist => relation('linkArtist', artist)); + } + + return relations; + }, + + data(query) { + const data = {}; + + data.enableFlashesAndGames = query.enableFlashesAndGames; + + data.datesByTrackContributions = query.datesByTrackContributions; + data.datesByArtworkContributions = query.datesByArtworkContributions; + + if (query.enableFlashesAndGames) { + data.datesByFlashContributions = query.datesByFlashContributions; + } + + return data; + }, + + generate(data, relations, {html, language}) { + const lists = Object.fromEntries( + ([ + ['tracks', [ + relations.artistLinksByTrackContributions, + data.datesByTrackContributions, + ]], + + ['artworks', [ + relations.artistLinksByArtworkContributions, + data.datesByArtworkContributions, + ]], + + data.enableFlashesAndGames && + ['flashes', [ + relations.artistLinksByFlashContributions, + data.datesByFlashContributions, + ]], + ]).filter(Boolean) + .map(([key, [artistLinks, dates]]) => [ + key, + html.tag('ul', + stitchArrays({ + artistLink: artistLinks, + date: dates, + }).map(({artistLink, date}) => + html.tag('li', + language.$('listingPage.listArtists.byLatest.item', { + artist: artistLink, + date: language.formatDate(date), + })))), + ])); + + return relations.page.slots({ + type: 'custom', + content: + html.tag('div', {class: 'content-columns'}, [ + html.tag('div', {class: 'column'}, [ + html.tag('h2', + language.$('listingPage.misc.trackContributors')), + + lists.tracks, + ]), + + html.tag('div', {class: 'column'}, [ + html.tag('h2', + language.$( + 'listingPage.misc.artContributors')), + + lists.artworks, + + lists.flashes && [ + html.tag('h2', + language.$('listingPage.misc.flashContributors')), + + lists.flashes, + ], + ]), + ]), + }); + }, +}; diff --git a/src/listing-spec.js b/src/listing-spec.js index 352f89d..17cde53 100644 --- a/src/listing-spec.js +++ b/src/listing-spec.js @@ -83,158 +83,7 @@ listingSpec.push({ listingSpec.push({ directory: 'artists/by-latest', stringsKey: 'listArtists.byLatest', - - data({wikiData: { - albumData, - flashData, - trackData, - wikiInfo, - }}) { - const processContribs = values => { - const filteredValues = values - .filter(value => value.date && !empty(value.contribs)); - - const datedArtistLists = sortByDate(filteredValues) - .map(({ - contribs, - date, - }) => ({ - artists: contribs.map(({who}) => who), - date, - })); - - const remainingArtists = new Set(datedArtistLists.flatMap(({artists}) => artists)); - const artistEntries = []; - - for (let i = datedArtistLists.length - 1; i >= 0; i--) { - const {artists, date} = datedArtistLists[i]; - for (const artist of artists) { - if (!remainingArtists.has(artist)) - continue; - - remainingArtists.delete(artist); - artistEntries.push({ - artist, - date, - - // For sortChronologically! - directory: artist.directory, - name: artist.name, - }); - } - - // Early exit: If we've gotten every artist, there's no need to keep - // going. - if (remainingArtists.size === 0) - break; - } - - return sortChronologically(artistEntries, {latestFirst: true}); - }; - - // Tracks are super easy to sort because they only have one pertinent - // date: the date the track was released on. - - const toTracks = processContribs( - trackData.map(({ - artistContribs, - date, - }) => ({ - contribs: artistContribs, - date, - }))); - - // Artworks are a bit more involved because there are multiple dates - // involved - cover artists correspond to one date, wallpaper artists to - // another, etc. - - const toArtAndFlashes = processContribs([ - ...trackData.map(({ - coverArtistContribs, - coverArtDate, - }) => ({ - contribs: coverArtistContribs, - date: coverArtDate, - })), - - ...flashData - ? flashData.map(({ - contributorContribs, - date, - }) => ({ - contribs: contributorContribs, - date, - })) - : [], - - ...albumData.flatMap(({ - bannerArtistContribs, - coverArtistContribs, - coverArtDate, - date, - wallpaperArtistContribs, - }) => [ - { - contribs: coverArtistContribs, - date: coverArtDate, - }, - { - contribs: bannerArtistContribs, - date, // TODO: bannerArtDate (see issue #90) - }, - { - contribs: wallpaperArtistContribs, - date, // TODO: wallpaperArtDate (see issue #90) - }, - ]), - ]); - - return { - toArtAndFlashes, - toTracks, - - // (Ok we did it again.) - // This is a kinda naughty hack, 8ut like, it's the only place - // we'd 8e passing wikiData to html() otherwise, so like.... - showAsFlashes: wikiInfo.enableFlashesAndGames, - }; - }, - - html: ( - {toTracks, toArtAndFlashes, showAsFlashes}, - {html, language, link} - ) => - html.tag('div', {class: 'content-columns'}, [ - html.tag('div', {class: 'column'}, [ - html.tag('h2', - language.$('listingPage.misc.trackContributors')), - - html.tag('ul', - toTracks.map(({artist, date}) => - html.tag('li', - language.$('listingPage.listArtists.byLatest.item', { - artist: link.artist(artist), - date: language.formatDate(date), - })))), - ]), - - html.tag('div', {class: 'column'}, [ - html.tag('h2', - language.$( - 'listingPage.misc' + - (showAsFlashes - ? '.artAndFlashContributors' - : '.artContributors'))), - - html.tag('ul', - toArtAndFlashes.map(({artist, date}) => - html.tag('li', - language.$('listingPage.listArtists.byLatest.item', { - artist: link.artist(artist), - date: language.formatDate(date), - })))), - ]), - ]), + contentFunction: 'listArtistsByLatestContribution', }); listingSpec.push({ -- cgit 1.3.0-6-gf8a5