From c4b40f4b7fa7ef5439845538af22cc9076e4cb9c Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Wed, 9 Aug 2023 09:42:15 -0300 Subject: content: listAll{Additional,SheetMusic,MidiProject}Files --- .../generateListAllAdditionalFilesChunk.js | 77 ++++++++ src/content/dependencies/listAllAdditionalFiles.js | 9 + .../dependencies/listAllAdditionalFilesTemplate.js | 206 +++++++++++++++++++++ .../dependencies/listAllMidiProjectFiles.js | 29 +-- src/content/dependencies/listAllSheetMusicFiles.js | 29 +-- 5 files changed, 302 insertions(+), 48 deletions(-) create mode 100644 src/content/dependencies/generateListAllAdditionalFilesChunk.js create mode 100644 src/content/dependencies/listAllAdditionalFiles.js create mode 100644 src/content/dependencies/listAllAdditionalFilesTemplate.js (limited to 'src/content') diff --git a/src/content/dependencies/generateListAllAdditionalFilesChunk.js b/src/content/dependencies/generateListAllAdditionalFilesChunk.js new file mode 100644 index 00000000..29ef2c05 --- /dev/null +++ b/src/content/dependencies/generateListAllAdditionalFilesChunk.js @@ -0,0 +1,77 @@ +import {empty, stitchArrays} from '../../util/sugar.js'; + +export default { + extraDependencies: ['html', 'language'], + + slots: { + title: {type: 'html'}, + + additionalFileTitles: { + validate: v => v.strictArrayOf(v.isHTML), + }, + + additionalFileLinks: { + validate: v => v.strictArrayOf(v.strictArrayOf(v.isHTML)), + }, + + additionalFileFiles: { + validate: v => v.strictArrayOf(v.strictArrayOf(v.isString)), + }, + + stringsKey: {type: 'string'}, + }, + + generate(slots, {html, language}) { + if (empty(slots.additionalFileLinks)) { + return html.blank(); + } + + return html.tags([ + html.tag('dt', slots.title), + html.tag('dd', + html.tag('ul', + stitchArrays({ + additionalFileTitle: slots.additionalFileTitles, + additionalFileLinks: slots.additionalFileLinks, + additionalFileFiles: slots.additionalFileFiles, + }).map(({ + additionalFileTitle, + additionalFileLinks, + additionalFileFiles, + }) => + (additionalFileLinks.length === 1 + ? html.tag('li', + additionalFileLinks[0].slots({ + content: + language.$(`listingPage.${slots.stringsKey}.file`, { + title: additionalFileTitle, + }), + })) + + : html.tag('li', {class: 'has-details'}, + html.tag('details', [ + html.tag('summary', + html.tag('span', + language.$(`listingPage.${slots.stringsKey}.file.withMultipleFiles`, { + title: + html.tag('span', {class: 'group-name'}, additionalFileTitle), + files: + language.countAdditionalFiles(additionalFileLinks.length, {unit: true}), + }))), + + html.tag('ul', + stitchArrays({ + additionalFileLink: additionalFileLinks, + additionalFileFile: additionalFileFiles, + }).map(({additionalFileLink, additionalFileFile}) => + html.tag('li', + additionalFileLink.slots({ + content: + language.$(`listingPage.${slots.stringsKey}.file`, { + title: additionalFileFile, + }), + })))), + ])))))), + ]); + }, +}; diff --git a/src/content/dependencies/listAllAdditionalFiles.js b/src/content/dependencies/listAllAdditionalFiles.js new file mode 100644 index 00000000..a6e34b9a --- /dev/null +++ b/src/content/dependencies/listAllAdditionalFiles.js @@ -0,0 +1,9 @@ +export default { + contentDependencies: ['listAllAdditionalFilesTemplate'], + + relations: (relation, spec) => + ({page: relation('listAllAdditionalFilesTemplate', spec, 'additionalFiles')}), + + generate: (relations) => + relations.page.slot('stringsKey', 'other.allAdditionalFiles'), +}; diff --git a/src/content/dependencies/listAllAdditionalFilesTemplate.js b/src/content/dependencies/listAllAdditionalFilesTemplate.js new file mode 100644 index 00000000..258442f1 --- /dev/null +++ b/src/content/dependencies/listAllAdditionalFilesTemplate.js @@ -0,0 +1,206 @@ +import {empty, stitchArrays} from '../../util/sugar.js'; +import {filterMultipleArrays, sortChronologically} from '../../util/wiki-data.js'; + +export default { + contentDependencies: [ + 'generateListingPage', + 'generateListAllAdditionalFilesChunk', + 'linkAlbum', + 'linkTrack', + 'linkAlbumAdditionalFile', + ], + + extraDependencies: ['html', 'language', 'wikiData'], + + sprawl: ({albumData}) => ({albumData}), + + query(sprawl, spec, property) { + const albums = + sortChronologically(sprawl.albumData.slice()); + + const tracks = + albums + .map(album => album.tracks.slice()); + + // Get additional file objects from albums and their tracks. + // There's a possibility that albums and tracks don't both implement + // the same additional file fields - in this case, just treat them + // as though they do implement those fields, but don't have any + // additional files of that type. + + const albumAdditionalFileObjects = + albums + .map(album => album[property] ?? []); + + const trackAdditionalFileObjects = + tracks + .map(byAlbum => byAlbum + .map(track => track[property] ?? [])); + + // Filter out tracks that don't have any additional files. + + stitchArrays({tracks, trackAdditionalFileObjects}) + .forEach(({tracks, trackAdditionalFileObjects}) => { + filterMultipleArrays(tracks, trackAdditionalFileObjects, + (track, trackAdditionalFileObjects) => !empty(trackAdditionalFileObjects)); + }); + + // Filter out albums that don't have any tracks, + // nor any additional files of their own. + + filterMultipleArrays(albums, albumAdditionalFileObjects, tracks, trackAdditionalFileObjects, + (album, albumAdditionalFileObjects, tracks, trackAdditionalFileObjects) => + !empty(albumAdditionalFileObjects) || + !empty(trackAdditionalFileObjects)); + + // Map additional file objects into titles and lists of file names. + + const albumAdditionalFileTitles = + albumAdditionalFileObjects + .map(byAlbum => byAlbum + .map(({title}) => title)); + + const albumAdditionalFileFiles = + albumAdditionalFileObjects + .map(byAlbum => byAlbum + .map(({files}) => files)); + + const trackAdditionalFileTitles = + trackAdditionalFileObjects + .map(byAlbum => byAlbum + .map(byTrack => byTrack + .map(({title}) => title))); + + const trackAdditionalFileFiles = + trackAdditionalFileObjects + .map(byAlbum => byAlbum + .map(byTrack => byTrack + .map(({files}) => files))); + + return { + spec, + albums, + tracks, + albumAdditionalFileTitles, + albumAdditionalFileFiles, + trackAdditionalFileTitles, + trackAdditionalFileFiles, + }; + }, + + relations: (relation, query) => ({ + page: + relation('generateListingPage', query.spec), + + albumLinks: + query.albums + .map(album => relation('linkAlbum', album)), + + trackLinks: + query.tracks + .map(byAlbum => byAlbum + .map(track => relation('linkTrack', track))), + + albumChunks: + query.albums + .map(() => relation('generateListAllAdditionalFilesChunk')), + + trackChunks: + query.tracks + .map(byAlbum => byAlbum + .map(() => relation('generateListAllAdditionalFilesChunk'))), + + albumAdditionalFileLinks: + stitchArrays({ + album: query.albums, + files: query.albumAdditionalFileFiles, + }).map(({album, files: byAlbum}) => + byAlbum.map(files => files + .map(file => + relation('linkAlbumAdditionalFile', album, file)))), + + trackAdditionalFileLinks: + stitchArrays({ + album: query.albums, + files: query.trackAdditionalFileFiles, + }).map(({album, files: byAlbum}) => + byAlbum + .map(byTrack => byTrack + .map(files => files + .map(file => relation('linkAlbumAdditionalFile', album, file))))), + }), + + data: (query) => ({ + albumAdditionalFileTitles: query.albumAdditionalFileTitles, + trackAdditionalFileTitles: query.trackAdditionalFileTitles, + albumAdditionalFileFiles: query.albumAdditionalFileFiles, + trackAdditionalFileFiles: query.trackAdditionalFileFiles, + }), + + slots: { + stringsKey: {type: 'string'}, + }, + + generate: (data, relations, slots, {html, language}) => + relations.page.slots({ + type: 'custom', + + content: + stitchArrays({ + albumLink: relations.albumLinks, + trackLinks: relations.trackLinks, + albumChunk: relations.albumChunks, + trackChunks: relations.trackChunks, + albumAdditionalFileTitles: data.albumAdditionalFileTitles, + trackAdditionalFileTitles: data.trackAdditionalFileTitles, + albumAdditionalFileLinks: relations.albumAdditionalFileLinks, + trackAdditionalFileLinks: relations.trackAdditionalFileLinks, + albumAdditionalFileFiles: data.albumAdditionalFileFiles, + trackAdditionalFileFiles: data.trackAdditionalFileFiles, + }).map(({ + albumLink, + trackLinks, + albumChunk, + trackChunks, + albumAdditionalFileTitles, + trackAdditionalFileTitles, + albumAdditionalFileLinks, + trackAdditionalFileLinks, + albumAdditionalFileFiles, + trackAdditionalFileFiles, + }) => [ + html.tag('h3', {class: 'content-heading'}, albumLink), + + html.tag('dl', [ + albumChunk.slots({ + title: language.$(`listingPage.${slots.stringsKey}.albumFiles`), + additionalFileTitles: albumAdditionalFileTitles, + additionalFileLinks: albumAdditionalFileLinks, + additionalFileFiles: albumAdditionalFileFiles, + stringsKey: slots.stringsKey, + }), + + stitchArrays({ + trackLink: trackLinks, + trackChunk: trackChunks, + trackAdditionalFileTitles, + trackAdditionalFileLinks, + trackAdditionalFileFiles, + }).map(({ + trackLink, + trackChunk, + trackAdditionalFileTitles, + trackAdditionalFileLinks, + trackAdditionalFileFiles, + }) => + trackChunk.slots({ + title: trackLink, + additionalFileTitles: trackAdditionalFileTitles, + additionalFileLinks: trackAdditionalFileLinks, + additionalFileFiles: trackAdditionalFileFiles, + stringsKey: slots.stringsKey, + })), + ]), + ]), + }), +}; diff --git a/src/content/dependencies/listAllMidiProjectFiles.js b/src/content/dependencies/listAllMidiProjectFiles.js index 28a925ac..31a70ef0 100644 --- a/src/content/dependencies/listAllMidiProjectFiles.js +++ b/src/content/dependencies/listAllMidiProjectFiles.js @@ -1,28 +1,9 @@ export default { - contentDependencies: ['generateListingPage'], - extraDependencies: ['html', 'wikiData'], + contentDependencies: ['listAllAdditionalFilesTemplate'], - sprawl() { - return {}; - }, + relations: (relation, spec) => + ({page: relation('listAllAdditionalFilesTemplate', spec, 'midiProjectFiles')}), - query(sprawl, spec) { - return { - spec, - }; - }, - - relations(relation, query) { - return { - page: relation('generateListingPage', query.spec), - }; - }, - - generate(relations, {html}) { - return relations.page.slots({ - type: 'custom', - content: - html.tag('p', `Alright alright, this is a stub page! Coming soon!`), - }); - }, + generate: (relations) => + relations.page.slot('stringsKey', 'other.allMidiProjectFiles'), }; diff --git a/src/content/dependencies/listAllSheetMusicFiles.js b/src/content/dependencies/listAllSheetMusicFiles.js index 28a925ac..166b2068 100644 --- a/src/content/dependencies/listAllSheetMusicFiles.js +++ b/src/content/dependencies/listAllSheetMusicFiles.js @@ -1,28 +1,9 @@ export default { - contentDependencies: ['generateListingPage'], - extraDependencies: ['html', 'wikiData'], + contentDependencies: ['listAllAdditionalFilesTemplate'], - sprawl() { - return {}; - }, + relations: (relation, spec) => + ({page: relation('listAllAdditionalFilesTemplate', spec, 'sheetMusicFiles')}), - query(sprawl, spec) { - return { - spec, - }; - }, - - relations(relation, query) { - return { - page: relation('generateListingPage', query.spec), - }; - }, - - generate(relations, {html}) { - return relations.page.slots({ - type: 'custom', - content: - html.tag('p', `Alright alright, this is a stub page! Coming soon!`), - }); - }, + generate: (relations) => + relations.page.slot('stringsKey', 'other.allSheetMusic'), }; -- cgit 1.3.0-6-gf8a5