« 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/dependencies/generateAlbumSecondaryNav.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/content/dependencies/generateAlbumSecondaryNav.js')
-rw-r--r--src/content/dependencies/generateAlbumSecondaryNav.js168
1 files changed, 168 insertions, 0 deletions
diff --git a/src/content/dependencies/generateAlbumSecondaryNav.js b/src/content/dependencies/generateAlbumSecondaryNav.js
new file mode 100644
index 0000000..400420b
--- /dev/null
+++ b/src/content/dependencies/generateAlbumSecondaryNav.js
@@ -0,0 +1,168 @@
+import {sortChronologically} from '#sort';
+import {atOffset, stitchArrays} from '#sugar';
+
+export default {
+  contentDependencies: [
+    'generateColorStyleAttribute',
+    'generatePreviousNextLinks',
+    'generateSecondaryNav',
+    'linkAlbumDynamically',
+    'linkGroup',
+    'linkTrack',
+  ],
+
+  extraDependencies: ['html', 'language'],
+
+  query(album) {
+    const query = {};
+
+    query.groups =
+      album.groups;
+
+    if (album.date) {
+      // Sort by latest first. This matches the sorting order used on group
+      // gallery pages, ensuring that previous/next matches moving up/down
+      // the gallery. Note that this makes the index offsets "backwards"
+      // compared to how latest-last chronological lists are accessed.
+      const groupAlbums =
+        query.groups.map(group =>
+          sortChronologically(
+            group.albums.filter(album => album.date),
+            {latestFirst: true}));
+
+      const groupCurrentIndex =
+        groupAlbums.map(albums =>
+          albums.indexOf(album));
+
+      query.groupPreviousAlbum =
+        stitchArrays({
+          albums: groupAlbums,
+          index: groupCurrentIndex,
+        }).map(({albums, index}) =>
+            atOffset(albums, index, +1));
+
+      query.groupNextAlbum =
+        stitchArrays({
+          albums: groupAlbums,
+          index: groupCurrentIndex,
+        }).map(({albums, index}) =>
+            atOffset(albums, index, -1));
+    }
+
+    return query;
+  },
+
+  relations(relation, query, album) {
+    const relations = {};
+
+    relations.secondaryNav =
+      relation('generateSecondaryNav');
+
+    relations.groupLinks =
+      album.groups
+        .map(group => relation('linkGroup', group));
+
+    relations.colorStyles =
+      album.groups
+        .map(group => relation('generateColorStyleAttribute', group.color));
+
+    if (album.date) {
+      relations.previousNextLinks =
+        stitchArrays({
+          previousAlbum: query.groupPreviousAlbum,
+          nextAlbum: query.groupNextAlbum
+        }).map(({previousAlbum, nextAlbum}) =>
+            (previousAlbum || nextAlbum
+              ? relation('generatePreviousNextLinks')
+              : null));
+
+      relations.previousAlbumLinks =
+        query.groupPreviousAlbum.map(previousAlbum =>
+          (previousAlbum
+            ? relation('linkAlbumDynamically', previousAlbum)
+            : null));
+
+      relations.nextAlbumLinks =
+        query.groupNextAlbum.map(nextAlbum =>
+          (nextAlbum
+            ? relation('linkAlbumDynamically', nextAlbum)
+            : null));
+    }
+
+    return relations;
+  },
+
+  slots: {
+    mode: {
+      validate: v => v.is('album', 'track'),
+      default: 'album',
+    },
+  },
+
+  generate(relations, slots, {html, language}) {
+    const navLinksShouldShowPreviousNext =
+      (slots.mode === 'track'
+        ? Array.from(relations.previousNextLinks, () => false)
+        : stitchArrays({
+            previousAlbumLink: relations.previousAlbumLinks ?? null,
+            nextAlbumLink: relations.nextAlbumLinks ?? null,
+          }).map(({previousAlbumLink, nextAlbumLink}) =>
+              previousAlbumLink ||
+              nextAlbumLink));
+
+    const navLinkPreviousNextLinks =
+      stitchArrays({
+        showPreviousNext: navLinksShouldShowPreviousNext,
+        previousNextLinks: relations.previousNextLinks ?? null,
+        previousAlbumLink: relations.previousAlbumLinks ?? null,
+        nextAlbumLink: relations.nextAlbumLinks ?? null,
+      }).map(({
+          showPreviousNext,
+          previousNextLinks,
+          previousAlbumLink,
+          nextAlbumLink,
+        }) =>
+          (showPreviousNext
+            ? previousNextLinks.slots({
+                previousLink: previousAlbumLink,
+                nextLink: nextAlbumLink,
+                id: false,
+              })
+            : null));
+
+    for (const groupLink of relations.groupLinks) {
+      groupLink.setSlot('color', false);
+    }
+
+    const navLinkContents =
+      stitchArrays({
+        groupLink: relations.groupLinks,
+        previousNextLinks: navLinkPreviousNextLinks,
+      }).map(({groupLink, previousNextLinks}) => [
+          language.$('albumSidebar.groupBox.title', {
+            group: groupLink,
+          }),
+
+          previousNextLinks &&
+            `(${language.formatUnitList(previousNextLinks.content)})`,
+        ]);
+
+    const navLinks =
+      stitchArrays({
+        content: navLinkContents,
+        colorStyle: relations.colorStyles,
+      }).map(({content, colorStyle}, index) =>
+          html.tag('span', {class: 'nav-link'},
+            index > 0 &&
+              {class: 'has-divider'},
+
+            colorStyle.slot('context', 'primary-only'),
+
+            content));
+
+    return relations.secondaryNav.slots({
+      class: 'nav-links-groups',
+      content: navLinks,
+    });
+  },
+};