« get me outta code hell

content, css, test: generateAlbumSecondaryNav: new prev/next - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2024-08-15 11:44:46 -0300
committer(quasar) nebula <qznebula@protonmail.com>2024-11-02 22:25:46 -0300
commitdf1d07633d344e278b4e5d10a2f1629ccb8ef7df (patch)
tree7f7d0311ed3f38f3742a9d1223a87b8375a3dc7a
parente77262e34657164b5c194d2e639ff4ce627134a9 (diff)
content, css, test: generateAlbumSecondaryNav: new prev/next
-rw-r--r--src/content/dependencies/generateAlbumSecondaryNav.js52
-rw-r--r--src/content/dependencies/generateAlbumSecondaryNavGroupPart.js48
-rw-r--r--src/content/dependencies/generateAlbumSecondaryNavSeriesPart.js64
-rw-r--r--src/content/dependencies/generateSecondaryNavParentSiblingsPart.js103
-rw-r--r--src/static/css/site.css33
-rw-r--r--tap-snapshots/test/snapshot/generateAlbumSecondaryNav.js.test.cjs29
-rw-r--r--test/snapshot/generateAlbumSecondaryNav.js45
7 files changed, 263 insertions, 111 deletions
diff --git a/src/content/dependencies/generateAlbumSecondaryNav.js b/src/content/dependencies/generateAlbumSecondaryNav.js
index a5dc0ba8..ed43e51f 100644
--- a/src/content/dependencies/generateAlbumSecondaryNav.js
+++ b/src/content/dependencies/generateAlbumSecondaryNav.js
@@ -4,6 +4,7 @@ export default {
   contentDependencies: [
     'generateAlbumSecondaryNavGroupPart',
     'generateAlbumSecondaryNavSeriesPart',
+    'generateDotSwitcherTemplate',
     'generateSecondaryNav',
   ],
 
@@ -28,6 +29,12 @@ export default {
     secondaryNav:
       relation('generateSecondaryNav'),
 
+    // Just use a generic dot switcher here. We want the common behavior,
+    // but the "options" may each contain multiple links (group + series),
+    // so this is a different use than typical interpage dot switchers.
+    switcher:
+      relation('generateDotSwitcherTemplate'),
+
     groupParts:
       query.groups
         .map(group =>
@@ -51,18 +58,37 @@ export default {
     },
   },
 
-  generate: (relations, slots) =>
-    relations.secondaryNav.slots({
-      class: 'nav-links-groups',
+  generate(relations, slots, {html}) {
+    const allParts =
+      stitchArrays({
+        groupPart: relations.groupParts,
+        seriesParts: relations.seriesParts,
+      }).map(({groupPart, seriesParts}) => {
+          for (const part of [groupPart, ...seriesParts]) {
+            part.setSlot('mode', slots.mode);
+          }
+
+          if (html.isBlank(seriesParts)) {
+            return groupPart;
+          } else {
+            return (
+              html.tag('span', {class: 'group-with-series'},
+                [groupPart, ...seriesParts]));
+          }
+        });
+
+    return relations.secondaryNav.slots({
+      class: [
+        'album-secondary-nav',
+
+        slots.mode === 'album' &&
+          'with-previous-next',
+      ],
+
       content:
-        stitchArrays({
-          groupPart: relations.groupParts,
-          seriesParts: relations.seriesParts,
-        }).map(({groupPart, seriesParts}) => [
-            groupPart.slot('mode', slots.mode),
-
-            seriesParts
-              .map(part => part.slot('mode', slots.mode)),
-          ]),
-    }),
+        (slots.mode === 'album'
+          ? allParts
+          : relations.switcher.slot('options', allParts)),
+    });
+  },
 };
diff --git a/src/content/dependencies/generateAlbumSecondaryNavGroupPart.js b/src/content/dependencies/generateAlbumSecondaryNavGroupPart.js
index 81b0c75a..58a31630 100644
--- a/src/content/dependencies/generateAlbumSecondaryNavGroupPart.js
+++ b/src/content/dependencies/generateAlbumSecondaryNavGroupPart.js
@@ -4,12 +4,12 @@ import {atOffset} from '#sugar';
 export default {
   contentDependencies: [
     'generateColorStyleAttribute',
-    'generatePreviousNextLinks',
+    'generateSecondaryNavParentSiblingsPart',
     'linkAlbumDynamically',
     'linkGroup',
   ],
 
-  extraDependencies: ['html', 'language'],
+  extraDependencies: ['html'],
 
   query(group, album) {
     const query = {};
@@ -38,15 +38,15 @@ export default {
   },
 
   relations: (relation, query, group, _album) => ({
+    parentSiblingsPart:
+      relation('generateSecondaryNavParentSiblingsPart'),
+
     groupLink:
       relation('linkGroup', group),
 
     colorStyle:
       relation('generateColorStyleAttribute', group.color),
 
-    previousNextLinks:
-      relation('generatePreviousNextLinks'),
-
     previousAlbumLink:
       (query.previousAlbum
         ? relation('linkAlbumDynamically', query.previousAlbum)
@@ -65,34 +65,16 @@ export default {
     },
   },
 
-  generate: (relations, slots, {html, language}) =>
-    html.tag('span', {class: 'nav-link'},
-      relations.colorStyle
-        .slot('context', 'primary-only'),
-
-      language.encapsulate('albumSecondaryNav.group', workingCapsule => {
-        const workingOptions = {};
-
-        workingOptions.group =
-          relations.groupLink
-            .slot('color', false);
-
-        if (slots.mode === 'album') {
-          const {previousNextLinks} = relations;
-
-          previousNextLinks.setSlots({
-            previousLink: relations.previousAlbumLink,
-            nextLink: relations.nextAlbumLink,
-            id: false,
-          });
+  generate: (relations, slots) =>
+    relations.parentSiblingsPart.slots({
+      mode: slots.mode,
 
-          if (!html.isBlank(previousNextLinks)) {
-            workingCapsule += '.withPreviousNext';
-            workingOptions.previousNext =
-              language.formatUnitList(previousNextLinks.content);
-          }
-        }
+      colorStyle: relations.colorStyle,
+      mainLink: relations.groupLink,
+      previousLink: relations.previousAlbumLink,
+      nextLink: relations.nextAlbumLink,
 
-        return language.$(workingCapsule, workingOptions);
-      })),
+      stringsKey: 'albumSecondaryNav.group',
+      mainLinkOption: 'group',
+    }),
 };
diff --git a/src/content/dependencies/generateAlbumSecondaryNavSeriesPart.js b/src/content/dependencies/generateAlbumSecondaryNavSeriesPart.js
index 47ba6ef6..12c72fd4 100644
--- a/src/content/dependencies/generateAlbumSecondaryNavSeriesPart.js
+++ b/src/content/dependencies/generateAlbumSecondaryNavSeriesPart.js
@@ -3,7 +3,7 @@ import {atOffset} from '#sugar';
 export default {
   contentDependencies: [
     'generateColorStyleAttribute',
-    'generatePreviousNextLinks',
+    'generateSecondaryNavParentSiblingsPart',
     'linkAlbumDynamically',
     'linkGroup',
   ],
@@ -29,15 +29,15 @@ export default {
   },
 
   relations: (relation, query, series, _album) => ({
+    parentSiblingsPart:
+      relation('generateSecondaryNavParentSiblingsPart'),
+
     groupLink:
       relation('linkGroup', series.group),
 
     colorStyle:
       relation('generateColorStyleAttribute', series.group.color),
 
-    previousNextLinks:
-      relation('generatePreviousNextLinks'),
-
     previousAlbumLink:
       (query.previousAlbum
         ? relation('linkAlbumDynamically', query.previousAlbum)
@@ -60,40 +60,24 @@ export default {
     },
   },
 
-  generate: (data, relations, slots, {html, language}) =>
-    html.tag('span',
-      {class: 'nav-link'},
-      {class: 'series-nav-link'},
-
-      relations.colorStyle
-        .slot('context', 'primary-only'),
-
-      language.encapsulate('albumSecondaryNav.series', workingCapsule => {
-        const workingOptions = {};
-
-        workingOptions.series =
-          relations.groupLink.slots({
-            attributes: {class: 'series'},
-            color: false,
-            content: language.sanitize(data.name),
-          });
-
-        if (slots.mode === 'album') {
-          const {previousNextLinks} = relations;
-
-          previousNextLinks.setSlots({
-            previousLink: relations.previousAlbumLink,
-            nextLink: relations.nextAlbumLink,
-            id: false,
-          });
-
-          if (!html.isBlank(previousNextLinks)) {
-            workingCapsule += '.withPreviousNext';
-            workingOptions.previousNext =
-              language.formatUnitList(previousNextLinks.content);
-          }
-        }
-
-        return language.$(workingCapsule, workingOptions);
-      })),
+  generate: (data, relations, slots, {language}) =>
+    relations.parentSiblingsPart.slots({
+      mode: slots.mode,
+
+      attributes: {class: 'series-nav-link'},
+
+      colorStyle: relations.colorStyle,
+
+      mainLink:
+        relations.groupLink.slots({
+          attributes: {class: 'series'},
+          content: language.sanitize(data.name),
+        }),
+
+      previousLink: relations.previousAlbumLink,
+      nextLink: relations.nextAlbumLink,
+
+      stringsKey: 'albumSecondaryNav.series',
+      mainLinkOption: 'series',
+    }),
 };
diff --git a/src/content/dependencies/generateSecondaryNavParentSiblingsPart.js b/src/content/dependencies/generateSecondaryNavParentSiblingsPart.js
new file mode 100644
index 00000000..c5f1df84
--- /dev/null
+++ b/src/content/dependencies/generateSecondaryNavParentSiblingsPart.js
@@ -0,0 +1,103 @@
+export default {
+  contentDependencies: [
+    'generateColorStyleAttribute',
+    'generateInterpageDotSwitcher',
+    'generateNextLink',
+    'generatePreviousLink',
+    'linkAlbumDynamically',
+    'linkGroup',
+  ],
+
+  extraDependencies: ['html', 'language'],
+
+  relations: (relation) => ({
+    switcher:
+      relation('generateInterpageDotSwitcher'),
+
+    previousLink:
+      relation('generatePreviousLink'),
+
+    nextLink:
+      relation('generateNextLink'),
+  }),
+
+  slots: {
+    mode: {
+      validate: v => v.is('album', 'track'),
+      default: 'album',
+    },
+
+    attributes: {
+      type: 'attributes',
+      mutable: false,
+    },
+
+    colorStyle: {
+      type: 'html',
+      mutable: true,
+    },
+
+    mainLink: {
+      type: 'html',
+      mutable: true,
+    },
+
+    previousLink: {
+      type: 'html',
+      mutable: false,
+    },
+
+    nextLink: {
+      type: 'html',
+      mutable: false,
+    },
+
+    stringsKey: {
+      type: 'string',
+    },
+
+    mainLinkOption: {
+      type: 'string',
+    },
+  },
+
+  generate: (relations, slots, {html, language}) =>
+    html.tag('span',
+      slots.attributes,
+
+      !html.isBlank(slots.colorStyle) &&
+        slots.colorStyle
+          .slot('context', 'primary-only'),
+
+      language.encapsulate(slots.stringsKey, workingCapsule => {
+        const workingOptions = {};
+
+        workingOptions[slots.mainLinkOption] =
+          slots.mainLink
+            .slot('color', false);
+
+        if (slots.mode === 'album') addPreviousNext: {
+          if (html.isBlank(slots.previousLink) && html.isBlank(slots.nextLink)) {
+            break addPreviousNext;
+          }
+
+          workingCapsule += '.withPreviousNext';
+          workingOptions.previousNext =
+            relations.switcher.slots({
+              links: [
+                relations.previousLink.slots({
+                  id: false,
+                  link: slots.previousLink,
+                }),
+
+                relations.nextLink.slots({
+                  id: false,
+                  link: slots.nextLink,
+                }),
+              ],
+            });
+        }
+
+        return language.$(workingCapsule, workingOptions);
+      })),
+};
diff --git a/src/static/css/site.css b/src/static/css/site.css
index a46c0927..081c184b 100644
--- a/src/static/css/site.css
+++ b/src/static/css/site.css
@@ -842,7 +842,7 @@ a:not([href]):hover {
   content: "\0020/\0020";
 }
 
-.nav-links-groups .series-nav-link:not(:first-child)::before {
+.series-nav-link:not(:first-child)::before {
   content: "\0020»\0020";
   font-weight: normal;
 }
@@ -868,6 +868,33 @@ a:not([href]):hover {
 
 #secondary-nav {
   text-align: center;
+
+  /* Default to visible. It'll automatically be hidden
+   * in layouts where the sidebar is visible.
+   */
+  display: block;
+}
+
+#secondary-nav.album-secondary-nav.with-previous-next {
+  display: flex;
+  justify-content: space-around;
+  padding-left: 15% !important;
+  padding-right: 15% !important;
+  flex-wrap: wrap;
+  line-height: 1.4;
+}
+
+#secondary-nav.album-secondary-nav.with-previous-next .group-with-series {
+  width: 100%;
+}
+
+#secondary-nav.album-secondary-nav.with-previous-next > * {
+  margin-left: 5px;
+  margin-right: 5px;
+}
+
+#secondary-nav.album-secondary-nav .dot-switcher {
+  white-space: nowrap;
 }
 
 .inert-previous-next-link {
@@ -2942,10 +2969,6 @@ html[data-language-code="preview-en"][data-url-key="localized.home"] #content
     display: none;
   }
 
-  #secondary-nav {
-    display: block;
-  }
-
   .layout-columns {
     flex-direction: column;
   }
diff --git a/tap-snapshots/test/snapshot/generateAlbumSecondaryNav.js.test.cjs b/tap-snapshots/test/snapshot/generateAlbumSecondaryNav.js.test.cjs
index de35048c..145dd0f7 100644
--- a/tap-snapshots/test/snapshot/generateAlbumSecondaryNav.js.test.cjs
+++ b/tap-snapshots/test/snapshot/generateAlbumSecondaryNav.js.test.cjs
@@ -6,28 +6,29 @@
  */
 'use strict'
 exports[`test/snapshot/generateAlbumSecondaryNav.js > TAP > generateAlbumSecondaryNav (snapshot) > basic behavior, mode: album 1`] = `
-<nav id="secondary-nav" class="nav-links-groups">
-    <span class="nav-link" style="--primary-color: #abcdef">
-        <a href="group/vcg/">VCG</a>
-        (<a title="First" href="album/first/">Previous</a>, <a title="Last" href="album/last/">Next</a>)
-    </span>
-    <span class="nav-link" style="--primary-color: #123456">
-        <a href="group/bepis/">Bepis</a>
-        (<a title="Second" href="album/second/">Next</a>)
+<nav id="secondary-nav" class="album-secondary-nav with-previous-next">
+    <span class="group-with-series">
+        <span style="--primary-color: #abcdef"><a href="group/vcg/">VCG</a> (<span class="dot-switcher interpage"><span><a title="First" href="album/first/">Previous</a></span><span><a title="Last" href="album/last/">Next</a></span></span>)</span>
+        <span class="series-nav-link" style="--primary-color: #abcdef"><a class="series" href="group/vcg/">Series</a> (<span class="dot-switcher interpage"><span><a class="inert-previous-next-link">Previous</a></span><span><a title="Last" href="album/last/">Next</a></span></span>)</span>
     </span>
+    <span style="--primary-color: #123456"><a href="group/bepis/">Bepis</a> (<span class="dot-switcher interpage"><span><a class="inert-previous-next-link">Previous</a></span><span><a title="Second" href="album/second/">Next</a></span></span>)</span>
 </nav>
 `
 
 exports[`test/snapshot/generateAlbumSecondaryNav.js > TAP > generateAlbumSecondaryNav (snapshot) > basic behavior, mode: track 1`] = `
-<nav id="secondary-nav" class="nav-links-groups">
-    <span class="nav-link" style="--primary-color: #abcdef"><a href="group/vcg/">VCG</a></span>
-    <span class="nav-link" style="--primary-color: #123456"><a href="group/bepis/">Bepis</a></span>
+<nav id="secondary-nav" class="album-secondary-nav">
+    <span class="dot-switcher"><span>
+            <span class="group-with-series">
+                <span style="--primary-color: #abcdef"><a href="group/vcg/">VCG</a></span>
+                <span class="series-nav-link" style="--primary-color: #abcdef"><a class="series" href="group/vcg/">Series</a></span>
+            </span>
+        </span><span><span style="--primary-color: #123456"><a href="group/bepis/">Bepis</a></span></span></span>
 </nav>
 `
 
 exports[`test/snapshot/generateAlbumSecondaryNav.js > TAP > generateAlbumSecondaryNav (snapshot) > dateless album in mixed group 1`] = `
-<nav id="secondary-nav" class="nav-links-groups">
-    <span class="nav-link" style="--primary-color: #abcdef"><a href="group/vcg/">VCG</a></span>
-    <span class="nav-link" style="--primary-color: #123456"><a href="group/bepis/">Bepis</a></span>
+<nav id="secondary-nav" class="album-secondary-nav with-previous-next">
+    <span style="--primary-color: #abcdef"><a href="group/vcg/">VCG</a></span>
+    <span style="--primary-color: #123456"><a href="group/bepis/">Bepis</a></span>
 </nav>
 `
diff --git a/test/snapshot/generateAlbumSecondaryNav.js b/test/snapshot/generateAlbumSecondaryNav.js
index 57618f2f..2495bc4a 100644
--- a/test/snapshot/generateAlbumSecondaryNav.js
+++ b/test/snapshot/generateAlbumSecondaryNav.js
@@ -4,10 +4,21 @@ import {testContentFunctions} from '#test-lib';
 testContentFunctions(t, 'generateAlbumSecondaryNav (snapshot)', async (t, evaluate) => {
   await evaluate.load();
 
-  let album, group1, group2;
+  let album, anotherAlbum, group1, group2;
 
-  group1 = {name: 'VCG', directory: 'vcg', color: '#abcdef'};
-  group2 = {name: 'Bepis', directory: 'bepis', color: '#123456'};
+  group1 = {
+    name: 'VCG',
+    directory: 'vcg',
+    color: '#abcdef',
+    serieses: [],
+  };
+
+  group2 = {
+    name: 'Bepis',
+    directory: 'bepis',
+    color: '#123456',
+    serieses: [],
+  };
 
   album = {
     name: 'Album',
@@ -16,15 +27,37 @@ testContentFunctions(t, 'generateAlbumSecondaryNav (snapshot)', async (t, evalua
     groups: [group1, group2],
   };
 
+  anotherAlbum = {
+    name: 'Last',
+    directory: 'last',
+    date: new Date('2010-06-12'),
+  };
+
   group1.albums = [
-    {name: 'First', directory: 'first', date: new Date('2010-04-10')},
+    {
+      name: 'First',
+      directory: 'first',
+      date: new Date('2010-04-10'),
+    },
     album,
-    {name: 'Last', directory: 'last', date: new Date('2010-06-12')},
+    anotherAlbum,
+  ];
+
+  group1.serieses = [
+    {
+      name: 'Series',
+      albums: [album, anotherAlbum],
+      group: group1,
+    },
   ];
 
   group2.albums = [
     album,
-    {name: 'Second', directory: 'second', date: new Date('2011-04-13')},
+    {
+      name: 'Second',
+      directory: 'second',
+      date: new Date('2011-04-13'),
+    },
   ];
 
   evaluate.snapshot('basic behavior, mode: album', {