« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/content
diff options
context:
space:
mode:
Diffstat (limited to 'src/content')
-rw-r--r--src/content/dependencies/generateListAllAdditionalFilesChunk.js77
-rw-r--r--src/content/dependencies/listAllAdditionalFiles.js9
-rw-r--r--src/content/dependencies/listAllAdditionalFilesTemplate.js206
-rw-r--r--src/content/dependencies/listAllMidiProjectFiles.js29
-rw-r--r--src/content/dependencies/listAllSheetMusicFiles.js29
5 files changed, 302 insertions, 48 deletions
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'),
 };