« get me outta code hell

content, client, css: generateGroupGalleryPage: series view - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/content/dependencies
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2025-05-04 19:16:15 -0300
committer(quasar) nebula <qznebula@protonmail.com>2025-05-06 15:20:24 -0300
commit72f6fc9659fe4cc6ea60229e636421a78fe98f29 (patch)
treef5f073bec80c68e543015aadd6d6a4384ac5a8b7 /src/content/dependencies
parentfedd22c523ec5c20b098cc478170ef096ab1b58e (diff)
content, client, css: generateGroupGalleryPage: series view
Diffstat (limited to 'src/content/dependencies')
-rw-r--r--src/content/dependencies/generateExpandableGallerySection.js92
-rw-r--r--src/content/dependencies/generateGroupGalleryPage.js93
-rw-r--r--src/content/dependencies/generateGroupGalleryPageAlbumsByDateView.js37
-rw-r--r--src/content/dependencies/generateGroupGalleryPageAlbumsBySeriesView.js26
-rw-r--r--src/content/dependencies/generateGroupGalleryPageSeriesSection.js129
5 files changed, 358 insertions, 19 deletions
diff --git a/src/content/dependencies/generateExpandableGallerySection.js b/src/content/dependencies/generateExpandableGallerySection.js
new file mode 100644
index 00000000..122ca4b1
--- /dev/null
+++ b/src/content/dependencies/generateExpandableGallerySection.js
@@ -0,0 +1,92 @@
+export default {
+  contentDependencies: ['generateContentHeading'],
+  extraDependencies: ['html', 'language'],
+
+  relations: (relation) => ({
+    contentHeading:
+      relation('generateContentHeading'),
+  }),
+
+  slots: {
+    title: {
+      type: 'html',
+      mutable: false,
+    },
+
+    contentAboveCut: {
+      type: 'html',
+      mutable: false,
+    },
+
+    contentBelowCut: {
+      type: 'html',
+      mutable: false,
+    },
+
+    caption: {
+      type: 'html',
+      mutable: false,
+    },
+
+    expandCue: {
+      type: 'html',
+      mutable: false,
+    },
+
+    collapseCue: {
+      type: 'html',
+      mutable: false,
+    },
+  },
+
+  generate: (relations, slots, {html, language}) =>
+    html.tag('section', {class: 'expandable-gallery-section'}, [
+      relations.contentHeading.slots({
+        tag: 'h2',
+        title: slots.title,
+      }),
+
+      html.tag('div', {class: 'section-content-above-cut'},
+        {[html.onlyIfContent]: true},
+
+        slots.contentAboveCut),
+
+      html.tag('div', {class: 'section-content-below-cut'},
+        {[html.onlyIfContent]: true},
+
+        !html.isBlank(slots.contentBelowCut) &&
+          {style: 'display: none'},
+
+        slots.contentBelowCut),
+
+      html.tag('div', {class: 'section-expando'},
+        {[html.onlyIfSiblings]: true},
+
+        html.tag('div', {class: 'section-expando-content'},
+          {[html.joinChildren]: html.tag('br')},
+
+          [
+            html.tag('span', {class: 'section-caption'},
+              slots.caption),
+
+            !html.isBlank(slots.contentBelowCut) &&
+              language.$('misc.coverGrid.expandCollapseCue', {
+                cue:
+                  html.tag('a', {class: 'section-expando-toggle'},
+                    {href: '#'},
+
+                    {[html.joinChildren]: ''},
+                    {[html.noEdgeWhitespace]: true},
+
+                    [
+                      html.tag('span', {class: 'section-expand-cue'},
+                        slots.expandCue),
+
+                      html.tag('span', {class: 'section-collapse-cue'},
+                        {style: 'display: none'},
+                        slots.collapseCue),
+                    ]),
+              }),
+          ])),
+    ]),
+};
diff --git a/src/content/dependencies/generateGroupGalleryPage.js b/src/content/dependencies/generateGroupGalleryPage.js
index 453155cb..535a2bc9 100644
--- a/src/content/dependencies/generateGroupGalleryPage.js
+++ b/src/content/dependencies/generateGroupGalleryPage.js
@@ -4,10 +4,11 @@ import {filterItemsForCarousel, getTotalDuration} from '#wiki-data';
 export default {
   contentDependencies: [
     'generateCoverCarousel',
-    'generateGroupGalleryPageAlbumGrid',
+    'generateGroupGalleryPageAlbumsByDateView',
+    'generateGroupGalleryPageAlbumsBySeriesView',
     'generateGroupNavLinks',
     'generateGroupSecondaryNav',
-    'generateGroupSidebar',
+    'generateIntrapageDotSwitcher',
     'generatePageLayout',
     'generateQuickDescription',
     'image',
@@ -47,11 +48,6 @@ export default {
         ? relation('generateGroupSecondaryNav', group)
         : null),
 
-    sidebar:
-      (sprawl.enableGroupUI
-        ? relation('generateGroupSidebar', group)
-        : null),
-
     coverCarousel:
       relation('generateCoverCarousel'),
 
@@ -66,8 +62,14 @@ export default {
     quickDescription:
       relation('generateQuickDescription', group),
 
-    albumGrid:
-      relation('generateGroupGalleryPageAlbumGrid', query.allAlbums),
+    albumViewSwitcher:
+      relation('generateIntrapageDotSwitcher'),
+
+    albumsBySeriesView:
+      relation('generateGroupGalleryPageAlbumsBySeriesView', group),
+
+    albumsByDateView:
+      relation('generateGroupGalleryPageAlbumsByDateView', group),
   }),
 
   data: (query, _sprawl, group) => ({
@@ -125,23 +127,76 @@ export default {
                   })),
             })),
 
-          relations.albumGrid,
+          ([
+            !html.isBlank(relations.albumsBySeriesView),
+            !html.isBlank(relations.albumsByDateView)
+          ]).filter(Boolean).length > 1 &&
+
+            language.encapsulate(pageCapsule, 'albumViewSwitcher', capsule =>
+              html.tag('p', {class: 'gallery-view-switcher'},
+                {[html.onlyIfContent]: true},
+                {[html.joinChildren]: html.tag('br')},
+
+                [
+                  language.$(capsule),
+
+                  relations.albumViewSwitcher.slots({
+                    initialOptionIndex: 0,
+
+                    titles: [
+                      !html.isBlank(relations.albumsBySeriesView) &&
+                        language.$(capsule, 'bySeries'),
+
+                      !html.isBlank(relations.albumsByDateView) &&
+                        language.$(capsule, 'byDate'),
+                    ].filter(Boolean),
+
+                    targetIDs: [
+                      !html.isBlank(relations.albumsBySeriesView) &&
+                        'group-album-gallery-by-series',
+
+                      !html.isBlank(relations.albumsByDateView) &&
+                        'group-album-gallery-by-date',
+                    ].filter(Boolean),
+                  }),
+                ])),
+
+          /*
+          data.trackGridLabels.some(value => value !== null) &&
+            html.tag('p', {class: 'gallery-set-switcher'},
+              language.encapsulate(pageCapsule, 'setSwitcher', switcherCapsule =>
+                language.$(switcherCapsule, {
+                  sets:
+                    relations.setSwitcher.slots({
+                      initialOptionIndex: 0,
+
+                      titles:
+                        data.trackGridLabels.map(label =>
+                          label ??
+                          language.$(switcherCapsule, 'unlabeledSet')),
+
+                      targetIDs:
+                        data.trackGridIDs,
+                    }),
+                }))),
+          */
+
+          relations.albumsBySeriesView,
+
+          relations.albumsByDateView.slots({
+            attributes: [
+              !html.isBlank(relations.albumsBySeriesView) &&
+                {style: 'display: none'},
+            ],
+          }),
         ],
 
-        leftSidebar:
-          (relations.sidebar
-            ? relations.sidebar
-                .slot('currentExtra', 'gallery')
-                .content /* TODO: Kludge. */
-            : null),
-
         navLinkStyle: 'hierarchical',
         navLinks:
           relations.navLinks
             .slot('currentExtra', 'gallery')
             .content,
 
-        secondaryNav:
-          relations.secondaryNav ?? null,
+        secondaryNav: relations.secondaryNav,
       })),
 };
diff --git a/src/content/dependencies/generateGroupGalleryPageAlbumsByDateView.js b/src/content/dependencies/generateGroupGalleryPageAlbumsByDateView.js
new file mode 100644
index 00000000..54f4b8cb
--- /dev/null
+++ b/src/content/dependencies/generateGroupGalleryPageAlbumsByDateView.js
@@ -0,0 +1,37 @@
+import {sortChronologically} from '#sort';
+
+export default {
+  contentDependencies: ['generateGroupGalleryPageAlbumGrid'],
+  extraDependencies: ['html', 'language'],
+
+  query: (group) => ({
+    albums:
+      sortChronologically(group.albums, {latestFirst: true}),
+  }),
+
+  relations: (relation, query, _group) => ({
+    albumGrid:
+      relation('generateGroupGalleryPageAlbumGrid', query.albums),
+  }),
+
+  slots: {
+    attributes: {
+      type: 'attributes',
+      mutable: false,
+    },
+  },
+
+  generate: (relations, slots, {html, language}) =>
+    language.encapsulate('groupGalleryPage.albumsByDate', capsule =>
+      html.tag('div', {id: 'group-album-gallery-by-date'},
+        slots.attributes,
+
+        {[html.onlyIfContent]: true},
+
+        html.tag('section', [
+          html.tag('h2',
+            language.$(capsule, 'title')),
+
+          relations.albumGrid,
+        ]))),
+};
diff --git a/src/content/dependencies/generateGroupGalleryPageAlbumsBySeriesView.js b/src/content/dependencies/generateGroupGalleryPageAlbumsBySeriesView.js
new file mode 100644
index 00000000..0337275f
--- /dev/null
+++ b/src/content/dependencies/generateGroupGalleryPageAlbumsBySeriesView.js
@@ -0,0 +1,26 @@
+export default {
+  contentDependencies: ['generateGroupGalleryPageSeriesSection'],
+  extraDependencies: ['html'],
+
+  relations: (relation, group) => ({
+    seriesSections:
+      group.serieses
+        .map(series =>
+          relation('generateGroupGalleryPageSeriesSection', series)),
+  }),
+
+  slots: {
+    attributes: {
+      type: 'attributes',
+      mutable: false,
+    },
+  },
+
+  generate: (relations, slots, {html}) =>
+    html.tag('div', {id: 'group-album-gallery-by-series'},
+      slots.attributes,
+
+      {[html.onlyIfContent]: true},
+
+      relations.seriesSections),
+};
diff --git a/src/content/dependencies/generateGroupGalleryPageSeriesSection.js b/src/content/dependencies/generateGroupGalleryPageSeriesSection.js
new file mode 100644
index 00000000..3fe3fb45
--- /dev/null
+++ b/src/content/dependencies/generateGroupGalleryPageSeriesSection.js
@@ -0,0 +1,129 @@
+import {sortChronologically} from '#sort';
+
+export default {
+  contentDependencies: [
+    'generateExpandableGallerySection',
+    'generateGroupGalleryPageAlbumGrid',
+  ],
+
+  extraDependencies: ['html', 'language'],
+
+  query(series) {
+    const query = {};
+
+    // Includes undated albums.
+    const albumsLatestFirst =
+      sortChronologically(series.albums, {latestFirst: true});
+
+    query.albumsAboveCut = albumsLatestFirst.slice(0, 4);
+    query.albumsBelowCut = albumsLatestFirst.slice(4);
+
+    query.allAlbumsDated =
+      series.albums.every(album => album.date);
+
+    query.latestAlbum =
+      albumsLatestFirst
+        .filter(album => album.date)
+        .at(0) ??
+      null;
+
+    query.earliestAlbum =
+      albumsLatestFirst
+        .filter(album => album.date)
+        .at(-1) ??
+      null;
+
+    return query;
+  },
+
+  relations: (relation, query, _series) => ({
+    gallerySection:
+      relation('generateExpandableGallerySection'),
+
+    gridAboveCut:
+      relation('generateGroupGalleryPageAlbumGrid', query.albumsAboveCut),
+
+    gridBelowCut:
+      relation('generateGroupGalleryPageAlbumGrid', query.albumsBelowCut),
+  }),
+
+  data: (query, series) => ({
+    name:
+      series.name,
+
+    albums:
+      series.albums.length,
+
+    tracks:
+      series.albums
+        .flatMap(album => album.tracks)
+        .length,
+
+    allAlbumsDated:
+      query.allAlbumsDated,
+
+    earliestAlbumDate:
+      (query.earliestAlbum
+        ? query.earliestAlbum.date
+        : null),
+
+    latestAlbumDate:
+      (query.latestAlbum
+        ? query.latestAlbum.date
+        : null),
+  }),
+
+  generate: (data, relations, {html, language}) =>
+    language.encapsulate('groupGalleryPage.albumSection', capsule =>
+      relations.gallerySection.slots({
+        title: data.name,
+
+        contentAboveCut: relations.gridAboveCut,
+        contentBelowCut: relations.gridBelowCut,
+
+        caption:
+          language.encapsulate(capsule, 'caption', workingCapsule => {
+            const workingOptions = {};
+
+            workingOptions.tracks =
+              html.tag('b',
+                language.countTracks(data.tracks, {unit: true}));
+
+            workingOptions.albums =
+              html.tag('b',
+                language.countAlbums(data.albums, {unit: true}));
+
+            if (data.allAlbumsDated) {
+              const earliestDate = data.earliestAlbumDate;
+              const latestDate = data.latestAlbumDate;
+
+              const earliestYear = earliestDate.getFullYear();
+              const latestYear = latestDate.getFullYear();
+
+              if (earliestYear === latestYear) {
+                if (data.albums === 1) {
+                  workingCapsule += '.withDate';
+                  workingOptions.date =
+                    language.formatDate(earliestDate);
+                } else {
+                  workingCapsule += '.withYear';
+                  workingOptions.year =
+                    language.formatYear(earliestDate);
+                }
+              } else {
+                workingCapsule += '.withYearRange';
+                workingOptions.yearRange =
+                  language.formatYearRange(earliestDate, latestDate);
+              }
+            }
+
+            return language.$(workingCapsule, workingOptions);
+          }),
+
+        expandCue:
+          language.$(capsule, 'expand'),
+
+        collapseCue:
+          language.$(capsule, 'collapse'),
+      })),
+};