« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/content/dependencies/generateListingPage.js7
-rw-r--r--src/content/dependencies/listArtistsByContributions.js159
-rw-r--r--src/data/things/language.js1
-rw-r--r--src/listing-spec.js72
-rw-r--r--src/strings-default.json7
5 files changed, 174 insertions, 72 deletions
diff --git a/src/content/dependencies/generateListingPage.js b/src/content/dependencies/generateListingPage.js
index 93b35497..cab80a7f 100644
--- a/src/content/dependencies/generateListingPage.js
+++ b/src/content/dependencies/generateListingPage.js
@@ -58,12 +58,14 @@ export default {
   },
 
   slots: {
-    type: {validate: v => v.is('rows', 'chunks'),},
+    type: {validate: v => v.is('rows', 'chunks', 'custom')},
 
     rows: {validate: v => v.arrayOf(v.isObject)},
 
     chunkTitles: {validate: v => v.arrayOf(v.isObject)},
     chunkRows: {validate: v => v.arrayOf(v.isObject)},
+
+    content: {type: 'html'},
   },
 
   generate(data, relations, slots, {html, language}) {
@@ -122,6 +124,9 @@ export default {
                       html.tag('li',
                         language.$(`listingPage.${data.stringsKey}.chunk.item`, row))))),
               ])),
+
+        slots.type === 'custom' &&
+          slots.content,
       ],
 
       navLinkStyle: 'hierarchical',
diff --git a/src/content/dependencies/listArtistsByContributions.js b/src/content/dependencies/listArtistsByContributions.js
new file mode 100644
index 00000000..78c8c1aa
--- /dev/null
+++ b/src/content/dependencies/listArtistsByContributions.js
@@ -0,0 +1,159 @@
+import {stitchArrays, unique} from '../../util/sugar.js';
+
+export default {
+  contentDependencies: ['generateListingPage', 'linkArtist'],
+  extraDependencies: ['html', 'language', 'wikiData'],
+
+  sprawl({artistData, wikiInfo}) {
+    return {
+      artistData,
+      enableFlashesAndGames: wikiInfo.enableFlashesAndGames,
+    };
+  },
+
+  query(sprawl, spec) {
+    const query = {spec};
+
+    const queryContributionInfo = fn =>
+      sprawl.artistData
+        .map(artist => ({artist, contributions: fn(artist)}))
+        .filter(({contributions}) => contributions)
+        .sort((a, b) => b.contributions - a.contributions);
+
+    query.enableFlashesAndGames =
+      sprawl.enableFlashesAndGames;
+
+    query.trackContributionInfo =
+      queryContributionInfo(artist =>
+        unique([
+          ...artist.tracksAsContributor,
+          ...artist.tracksAsArtist,
+        ]).length);
+
+    query.artworkContributionInfo =
+      queryContributionInfo(artist =>
+        artist.tracksAsCoverArtist.length +
+        artist.albumsAsCoverArtist.length +
+        artist.albumsAsWallpaperArtist.length +
+        artist.albumsAsBannerArtist.length);
+
+    if (sprawl.enableFlashesAndGames) {
+      query.flashContributionInfo =
+        queryContributionInfo(artist =>
+          artist.flashesAsContributor.length);
+    }
+
+    return query;
+  },
+
+  relations(relation, query) {
+    const relations = {};
+
+    relations.page =
+      relation('generateListingPage', query.spec);
+
+    relations.artistLinksByTrackContributions =
+      query.trackContributionInfo
+        .map(({artist}) => relation('linkArtist', artist));
+
+    relations.artistLinksByArtworkContributions =
+      query.artworkContributionInfo
+        .map(({artist}) => relation('linkArtist', artist));
+
+    if (query.enableFlashesAndGames) {
+      relations.artistLinksByFlashContributions =
+        query.flashContributionInfo
+          .map(({artist}) => relation('linkArtist', artist));
+    }
+
+    return relations;
+  },
+
+  data(query) {
+    const data = {};
+
+    data.enableFlashesAndGames =
+      query.enableFlashesAndGames;
+
+    data.countsByTrackContributions =
+      query.trackContributionInfo
+        .map(({contributions}) => contributions);
+
+    data.countsByArtworkContributions =
+      query.artworkContributionInfo
+        .map(({contributions}) => contributions);
+
+    if (query.enableFlashesAndGames) {
+      data.countsByFlashContributions =
+        query.flashContributionInfo
+          .map(({contributions}) => contributions);
+    }
+
+    return data;
+  },
+
+  generate(data, relations, {html, language}) {
+    const lists = Object.fromEntries(
+      ([
+        ['tracks', [
+          relations.artistLinksByTrackContributions,
+          data.countsByTrackContributions,
+          'countTracks',
+        ]],
+
+        ['artworks', [
+          relations.artistLinksByArtworkContributions,
+          data.countsByArtworkContributions,
+          'countArtworks',
+        ]],
+
+        data.enableFlashesAndGames &&
+          ['flashes', [
+            relations.artistLinksByFlashContributions,
+            data.countsByFlashContributions,
+            'countFlashes',
+          ]],
+      ]).filter(Boolean)
+        .map(([key, [artistLinks, counts, countFunction]]) => [
+          key,
+          html.tag('ul',
+            stitchArrays({
+              artistLink: artistLinks,
+              count: counts,
+            }).map(({artistLink, count}) =>
+                html.tag('li',
+                  language.$('listingPage.listArtists.byContribs.item', {
+                    artist: artistLink,
+                    contributions: language[countFunction](count, {unit: true}),
+                  })))),
+        ]));
+
+    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.artAndFlashContributors')),
+
+              lists.flashes,
+            ],
+          ]),
+        ]),
+    });
+  },
+};
diff --git a/src/data/things/language.js b/src/data/things/language.js
index 004678de..7755c505 100644
--- a/src/data/things/language.js
+++ b/src/data/things/language.js
@@ -312,6 +312,7 @@ Object.assign(Language.prototype, {
   countAdditionalFiles: countHelper('additionalFiles', 'files'),
   countAlbums: countHelper('albums'),
   countArtworks: countHelper('artworks'),
+  countFlashes: countHelper('flashes'),
   countCommentaryEntries: countHelper('commentaryEntries', 'entries'),
   countContributions: countHelper('contributions'),
   countCoverArts: countHelper('coverArts'),
diff --git a/src/listing-spec.js b/src/listing-spec.js
index 844d241d..f0f2c8e8 100644
--- a/src/listing-spec.js
+++ b/src/listing-spec.js
@@ -79,77 +79,7 @@ listingSpec.push({
 listingSpec.push({
   directory: 'artists/by-contribs',
   stringsKey: 'listArtists.byContribs',
-
-  data: ({wikiData: {artistData, wikiInfo}}) => ({
-    toTracks: artistData
-      .map(artist => ({
-        artist,
-        contributions:
-          artist.tracksAsContributor.length +
-          artist.tracksAsArtist.length,
-      }))
-      .sort((a, b) => b.contributions - a.contributions)
-      .filter(({contributions}) => contributions),
-
-    toArtAndFlashes: artistData
-      .map(artist => ({
-        artist,
-        contributions:
-          artist.tracksAsCoverArtist.length +
-          artist.albumsAsCoverArtist.length +
-          artist.albumsAsWallpaperArtist.length +
-          artist.albumsAsBannerArtist.length +
-          (wikiInfo.enableFlashesAndGames
-            ? artist.flashesAsContributor.length
-            : 0),
-      }))
-      .sort((a, b) => b.contributions - a.contributions)
-      .filter(({contributions}) => contributions),
-
-    // This is a kinda naughty hack, 8ut like, it's the only place
-    // we'd 8e passing wikiData to html() otherwise, so like....
-    // (Ok we do do this again once later.)
-    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, contributions}) =>
-            html.tag('li',
-              language.$('listingPage.listArtists.byContribs.item', {
-                artist: link.artist(artist),
-                contributions: language.countContributions(contributions, {
-                  unit: true,
-                }),
-              })))),
-      ]),
-
-      html.tag('div', {class: 'column'}, [
-        html.tag('h2',
-          language.$(
-            'listingPage.misc' +
-              (showAsFlashes
-                ? '.artAndFlashContributors'
-                : '.artContributors'))),
-
-        html.tag('ul',
-          toArtAndFlashes.map(({artist, contributions}) =>
-            html.tag('li',
-              language.$('listingPage.listArtists.byContribs.item', {
-                artist: link.artist(artist),
-                contributions:
-                  language.countContributions(contributions, {unit: true}),
-              })))),
-      ]),
-  ]),
+  contentFunction: 'listArtistsByContributions',
 });
 
 listingSpec.push({
diff --git a/src/strings-default.json b/src/strings-default.json
index 4db11053..d0b186d8 100644
--- a/src/strings-default.json
+++ b/src/strings-default.json
@@ -50,6 +50,13 @@
   "count.coverArts.withUnit.few": "",
   "count.coverArts.withUnit.many": "",
   "count.coverArts.withUnit.other": "{COVER_ARTS} cover arts",
+  "count.flashes": "{FLASHES}",
+  "count.flashes.withUnit.zero": "",
+  "count.flashes.withUnit.one": "{FLASHES} flashes & games",
+  "count.flashes.withUnit.two": "",
+  "count.flashes.withUnit.few": "",
+  "count.flashes.withUnit.many": "",
+  "count.flashes.withUnit.other": "{FLASHES} flashes & games",
   "count.timesReferenced": "{TIMES_REFERENCED}",
   "count.timesReferenced.withUnit.zero": "",
   "count.timesReferenced.withUnit.one": "{TIMES_REFERENCED} time referenced",