« get me outta code hell

content: generateArtistInfoPageFirstReleaseTooltip - 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>2025-02-21 08:07:25 -0400
committer(quasar) nebula <qznebula@protonmail.com>2025-03-02 08:24:13 -0400
commit4b9550a2d8dda5d58861c8f2c2c2a7b7ec803059 (patch)
tree728de9061b6124934392bcb0d8c686e4a0f1e9b0
parent5580640828d71d3c17f1c1f3ac51b42a9082d663 (diff)
content: generateArtistInfoPageFirstReleaseTooltip
Also rescue hr.cute
-rw-r--r--src/content/dependencies/generateArtistInfoPageChunkItem.js17
-rw-r--r--src/content/dependencies/generateArtistInfoPageFirstReleaseTooltip.js80
-rw-r--r--src/content/dependencies/generateArtistInfoPageTracksChunkItem.js34
-rw-r--r--src/content/dependencies/generatePageSidebarConjoinedBox.js6
-rw-r--r--src/static/css/site.css25
-rw-r--r--src/strings-default.yaml2
6 files changed, 144 insertions, 20 deletions
diff --git a/src/content/dependencies/generateArtistInfoPageChunkItem.js b/src/content/dependencies/generateArtistInfoPageChunkItem.js
index af24e150..7987b642 100644
--- a/src/content/dependencies/generateArtistInfoPageChunkItem.js
+++ b/src/content/dependencies/generateArtistInfoPageChunkItem.js
@@ -28,6 +28,11 @@ export default {
       type: 'html',
       mutable: false,
     },
+
+    firstReleaseTooltip: {
+      type: 'html',
+      mutable: false,
+    },
   },
 
   generate: (relations, slots, {html, language}) =>
@@ -50,6 +55,18 @@ export default {
             return language.$(workingCapsule, workingOptions);
           }
 
+          if (!html.isBlank(slots.firstReleaseTooltip)) {
+            workingCapsule += '.firstRelease';
+            workingOptions.firstRelease =
+              relations.textWithTooltip.slots({
+                attributes: {class: 'first-release'},
+                text: language.$(entryCapsule, 'firstRelease.term'),
+                tooltip: slots.firstReleaseTooltip,
+              });
+
+            return language.$(workingCapsule, workingOptions);
+          }
+
           let anyAccent = false;
 
           if (!empty(slots.otherArtistLinks)) {
diff --git a/src/content/dependencies/generateArtistInfoPageFirstReleaseTooltip.js b/src/content/dependencies/generateArtistInfoPageFirstReleaseTooltip.js
new file mode 100644
index 00000000..e5ea3065
--- /dev/null
+++ b/src/content/dependencies/generateArtistInfoPageFirstReleaseTooltip.js
@@ -0,0 +1,80 @@
+import {sortChronologically} from '#sort';
+import {stitchArrays} from '#sugar';
+
+export default {
+  contentDependencies: ['generateColorStyleAttribute', 'generateTooltip'],
+  extraDependencies: ['html', 'language'],
+
+  query: (track) => ({
+    rereleases:
+      sortChronologically(track.allReleases).slice(1),
+  }),
+
+  relations: (relation, query, track) => ({
+    tooltip:
+      relation('generateTooltip'),
+
+    firstReleaseColorStyle:
+      relation('generateColorStyleAttribute', track.color),
+
+    rereleaseColorStyles:
+      query.rereleases
+        .map(rerelease =>
+          relation('generateColorStyleAttribute', rerelease.album.color)),
+  }),
+
+  data: (query, track) => ({
+    firstReleaseDate:
+      track.dateFirstReleased ??
+      track.album.date,
+
+    rereleaseAlbumNames:
+      query.rereleases
+        .map(rerelease => rerelease.album.name),
+
+    rereleaseDates:
+      query.rereleases
+        .map(rerelease =>
+          rerelease.dateFirstReleased ??
+          rerelease.album.date),
+  }),
+
+  generate: (data, relations, {html, language}) =>
+    language.encapsulate('artistPage.creditList.entry.firstRelease', capsule =>
+      relations.tooltip.slots({
+        attributes: [
+          {class: 'first-release-tooltip'},
+          relations.firstReleaseColorStyle,
+        ],
+
+        contentAttributes: [
+          {[html.joinChildren]: html.tag('hr', {class: 'cute'})},
+        ],
+
+        content:
+          stitchArrays({
+            colorStyle: relations.rereleaseColorStyles,
+            albumName: data.rereleaseAlbumNames,
+            date: data.rereleaseDates,
+          }).map(({colorStyle, albumName, date}) =>
+              html.tags([
+                language.$(capsule, 'rerelease', {
+                  album:
+                    html.metatag('blockwrap',
+                      html.tag('a',
+                        {href: '#'},
+                        colorStyle.slot('context', 'primary-only'),
+
+                        language.sanitize(albumName))),
+                }),
+
+                html.tag('br'),
+
+                language.formatRelativeDate(date, data.firstReleaseDate, {
+                  considerRoundingDays: true,
+                  approximate: true,
+                  absolute: true,
+                }),
+              ])),
+      })),
+};
diff --git a/src/content/dependencies/generateArtistInfoPageTracksChunkItem.js b/src/content/dependencies/generateArtistInfoPageTracksChunkItem.js
index 8be3f404..744e7c5f 100644
--- a/src/content/dependencies/generateArtistInfoPageTracksChunkItem.js
+++ b/src/content/dependencies/generateArtistInfoPageTracksChunkItem.js
@@ -4,6 +4,7 @@ import {empty} from '#sugar';
 export default {
   contentDependencies: [
     'generateArtistInfoPageChunkItem',
+    'generateArtistInfoPageFirstReleaseTooltip',
     'generateArtistInfoPageOtherArtistLinks',
     'generateArtistInfoPageRereleaseTooltip',
     'linkTrack',
@@ -63,16 +64,25 @@ export default {
       ];
     }
 
+    // It's kinda awkward to perform this chronological sort here,
+    // per track, rather than just reusing the one that's done to
+    // sort all the items on the page altogether... but then, the
+    // sort for the page is actually *a different* sort, on purpsoe.
+    // That sort is according to the dates of the contributions;
+    // this is according to the dates of the tracks. Those can be
+    // different - and it's the latter that determines whether the
+    // track is a rerelease!
+    const allReleasesChronologically =
+      sortChronologically(query.track.allReleases);
+
+    query.isFirstRelease =
+      allReleasesChronologically[0] === query.track;
+
     query.isRerelease =
-      // It's kinda awkward to perform this chronological sort here,
-      // per track, rather than just reusing the one that's done to
-      // sort all the items on the page altogether... but then, the
-      // sort for the page is actually *a different* sort, on purpsoe.
-      // That sort is according to the dates of the contributions;
-      // this is according to the dates of the tracks. Those can be
-      // different - and it's the latter that determines whether the
-      // track is a rerelease!
-      sortChronologically(query.track.allReleases)[0] !== query.track;
+      allReleasesChronologically[0] !== query.track;
+
+    query.hasOtherReleases =
+      !empty(query.track.otherReleases);
 
     return query;
   },
@@ -91,6 +101,11 @@ export default {
       (query.isRerelease
         ? relation('generateArtistInfoPageRereleaseTooltip', query.track)
         : null),
+
+    firstReleaseTooltip:
+      (query.isFirstRelease && query.hasOtherReleases
+        ? relation('generateArtistInfoPageFirstReleaseTooltip', query.track)
+        : null),
   }),
 
   data: (query) => ({
@@ -108,6 +123,7 @@ export default {
     relations.template.slots({
       otherArtistLinks: relations.otherArtistLinks,
       rereleaseTooltip: relations.rereleaseTooltip,
+      firstReleaseTooltip: relations.firstReleaseTooltip,
 
       annotation:
         (data.contribAnnotations
diff --git a/src/content/dependencies/generatePageSidebarConjoinedBox.js b/src/content/dependencies/generatePageSidebarConjoinedBox.js
index 05b1d469..7974c707 100644
--- a/src/content/dependencies/generatePageSidebarConjoinedBox.js
+++ b/src/content/dependencies/generatePageSidebarConjoinedBox.js
@@ -32,11 +32,7 @@ export default {
           .map((content, index, {length}) => [
             content,
             index < length - 1 &&
-              html.tag('hr', {
-                style:
-                  `border-color: var(--primary-color); ` +
-                  `border-style: none none dotted none`,
-              }),
+              html.tag('hr', {class: 'cute'}),
           ]),
     }),
 };
diff --git a/src/static/css/site.css b/src/static/css/site.css
index 82122251..177dc5d1 100644
--- a/src/static/css/site.css
+++ b/src/static/css/site.css
@@ -1023,7 +1023,8 @@ a:not([href]):hover {
 .text-with-tooltip.missing-duration .text-with-tooltip-interaction-cue,
 .text-with-tooltip.commentary-date .text-with-tooltip-interaction-cue,
 .text-with-tooltip.wiki-edits .text-with-tooltip-interaction-cue,
-.text-with-tooltip.rerelease .text-with-tooltip-interaction-cue {
+.text-with-tooltip.rerelease .text-with-tooltip-interaction-cue,
+.text-with-tooltip.first-release .text-with-tooltip-interaction-cue {
   cursor: default;
 }
 
@@ -1081,7 +1082,8 @@ li:not(:first-child:last-child) .tooltip,
 .datetimestamp-tooltip,
 .missing-duration-tooltip,
 .commentary-date-tooltip,
-.rerelease-tooltip {
+.rerelease-tooltip,
+.first-release-tooltip {
   padding: 3px 4px 2px 2px;
   left: -10px;
 }
@@ -1176,11 +1178,16 @@ li:not(:first-child:last-child) .tooltip,
   font-size: 0.85em;
 }
 
-.contribution-tooltip .tooltip-divider {
+.contribution-tooltip .tooltip-divider,
+.tooltip-content hr.cute {
   grid-column-start: icon-start;
   grid-column-end: platform-end;
-
   border-top: 1px dotted var(--primary-color);
+}
+
+/* Don't mind me... */
+.tooltip-content .tooltip-divider,
+.tooltip-content hr.cute {
   margin-top: 3px;
   margin-bottom: 4px;
 }
@@ -1246,7 +1253,8 @@ li:not(:first-child:last-child) .tooltip,
   padding: 3px 4.5px;
 }
 
-.rerelease-tooltip .tooltip-content {
+.rerelease-tooltip .tooltip-content,
+.first-release-tooltip .tooltip-content {
   padding: 3px 4.5px;
   width: 260px;
   font-size: 0.9em;
@@ -1323,6 +1331,13 @@ p .current {
   font-weight: 800;
 }
 
+hr.cute,
+#content hr.cute,
+.sidebar hr.cute {
+  border-color: var(--primary-color);
+  border-style: none none dotted none;
+}
+
 #cover-art-container {
   font-size: 0.8em;
   border: 2px solid var(--primary-color);
diff --git a/src/strings-default.yaml b/src/strings-default.yaml
index 887f4fbb..259e01bb 100644
--- a/src/strings-default.yaml
+++ b/src/strings-default.yaml
@@ -1214,7 +1214,7 @@ artistPage:
         term: "first release"
 
         rerelease: >-
-          {WHEN}: {ALBUM}
+          Also released on {ALBUM}
 
       # track:
       #   The string without duration is used in both the artist's