« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/content/dependencies/generateGroupGalleryPage.js7
-rw-r--r--src/content/dependencies/generateQuickDescription.js120
-rw-r--r--src/static/css/site.css45
-rw-r--r--src/static/js/client.js66
-rw-r--r--src/strings-default.yaml8
5 files changed, 205 insertions, 41 deletions
diff --git a/src/content/dependencies/generateGroupGalleryPage.js b/src/content/dependencies/generateGroupGalleryPage.js
index 6f23710d..34c789b3 100644
--- a/src/content/dependencies/generateGroupGalleryPage.js
+++ b/src/content/dependencies/generateGroupGalleryPage.js
@@ -13,7 +13,6 @@ export default {
     'generateQuickDescription',
     'image',
     'linkAlbum',
-    'linkGroup',
     'linkListing',
   ],
 
@@ -60,9 +59,6 @@ export default {
     relations.quickDescription =
       relation('generateQuickDescription', group);
 
-    relations.quickDescriptionInfoLink =
-      relation('linkGroup', group);
-
     relations.coverGrid =
       relation('generateCoverGrid');
 
@@ -136,8 +132,7 @@ export default {
                     image.slot('path', path)),
             }),
 
-          relations.quickDescription
-            .slot('infoPageLink', relations.quickDescriptionInfoLink),
+          relations.quickDescription,
 
           html.tag('p', {class: 'quick-info'},
             language.$('groupGalleryPage.infoLine', {
diff --git a/src/content/dependencies/generateQuickDescription.js b/src/content/dependencies/generateQuickDescription.js
index 3dadfbcf..f555af28 100644
--- a/src/content/dependencies/generateQuickDescription.js
+++ b/src/content/dependencies/generateQuickDescription.js
@@ -2,40 +2,92 @@ export default {
   contentDependencies: ['transformContent'],
   extraDependencies: ['html', 'language'],
 
-  relations: (relation, thing) =>
-    ({description:
-        (thing.descriptionShort || thing.description
-          ? relation('transformContent',
-              thing.descriptionShort ?? thing.description)
-          : null)}),
-
-  data: (thing) =>
-    ({hasLongerDescription:
-        thing.description &&
-        thing.descriptionShort &&
-        thing.descriptionShort !== thing.description}),
-
-  slots: {
-    infoPageLink: {
-      type: 'html',
-      mutable: true,
-    },
-  },
-
-  generate: (data, relations, slots, {html, language}) =>
-    html.tag('p', {class: 'quick-info'},
-      {[html.joinChildren]: html.tag('br')},
-      {[html.onlyIfContent]: true},
-
-      [
-        relations.description?.slot('mode', 'inline'),
+  query: (thing) => ({
+    hasDescription:
+      !!thing.description,
+
+    hasLongerDescription:
+      thing.description &&
+      thing.descriptionShort &&
+      thing.descriptionShort !== thing.description,
+  }),
+
+  relations: (relation, query, thing) => ({
+    description:
+      (query.hasLongerDescription || !thing.description
+        ? null
+        : relation('transformContent', thing.description)),
+
+    descriptionShort:
+      (query.hasLongerDescription
+        ? relation('transformContent', thing.descriptionShort)
+        : null),
+
+    descriptionLong:
+      (query.hasLongerDescription
+        ? relation('transformContent', thing.description)
+        : null),
+  }),
+
+  data: (query) => ({
+    hasDescription: query.hasDescription,
+    hasLongerDescription: query.hasLongerDescription,
+  }),
+
+  generate(data, relations, {html, language}) {
+    const prefix = 'misc.quickDescription';
+
+    const wrapExpandCollapseLink = (expandCollapse, content) =>
+      html.tag('a', {class: `${expandCollapse}-link`},
+        {href: '#'},
+        content);
+
+    const actionsWhenCollapsed =
+      (data.hasLongerDescription
+        ? language.$(prefix, 'expandDescription', {
+            expand:
+              wrapExpandCollapseLink('expand',
+                language.$(prefix, 'expandDescription.expand')),
+          })
+        : null);
+
+    const actionsWhenExpanded =
+      (data.hasLongerDescription
+        ? language.$(prefix, 'collapseDescription', {
+            collapse:
+              wrapExpandCollapseLink('collapse',
+                language.$(prefix, 'collapseDescription.collapse')),
+          })
+        : null);
+
+    const wrapActions = (attributes, children) =>
+      html.tag('p', {class: 'quick-description-actions'},
+        {[html.onlyIfContent]: true},
+        attributes,
+
+        children);
+
+    const wrapContent = (attributes, content) =>
+      html.tag('div', {class: 'description-content'},
+        {[html.onlyIfContent]: true},
+        attributes,
+
+        content?.slot('mode', 'multiline'));
+
+    return (
+      html.tag('div', {class: 'quick-description'},
+        {[html.onlyIfContent]: true},
 
         data.hasLongerDescription &&
-        slots.infoPageLink &&
-          language.$('misc.quickDescription.moreInfo', {
-            link:
-              slots.infoPageLink
-                .slot('content', language.$('misc.quickDescription.moreInfo.link')),
-          }),
-      ]),
+          {class: 'collapsed'},
+
+        [
+          wrapContent(null, relations.description),
+          wrapContent({class: 'short'}, relations.descriptionShort),
+          wrapContent({class: 'long'}, relations.descriptionLong),
+
+          wrapActions({class: 'when-collapsed'}, actionsWhenCollapsed),
+          wrapActions({class: 'when-expanded'}, actionsWhenExpanded),
+        ]));
+  }
 };
diff --git a/src/static/css/site.css b/src/static/css/site.css
index e297993c..173c7910 100644
--- a/src/static/css/site.css
+++ b/src/static/css/site.css
@@ -1258,10 +1258,53 @@ ul.quick-info li:not(:last-child)::after {
   font-weight: 800;
 }
 
-.carousel-container + .quick-info {
+.carousel-container + .quick-info,
+.carousel-container + .quick-description {
   margin-top: 25px;
 }
 
+.quick-description {
+  margin-left: 8%;
+  margin-right: 8%;
+  padding-left: 4%;
+  padding-right: 4%;
+  padding-top: 0.25em;
+  padding-bottom: 0.5em;
+  border-left: 1px solid var(--dim-color);
+  border-right: 1px solid var(--dim-color);
+  line-height: 1.25em;
+}
+
+.quick-description p {
+  text-align: center;
+}
+
+.quick-description .description-content.long hr ~ p {
+  text-align: left;
+}
+
+.quick-description > .description-content :first-child {
+  margin-top: 0;
+}
+
+.quick-description > .quick-description-actions,
+.quick-description.has-content-only .description-content :last-child {
+  margin-bottom: 0;
+}
+
+.quick-description:not(.collapsed) .description-content.short,
+.quick-description:not(.collapsed) .quick-description-actions.when-collapsed,
+.quick-description:not(.expanded) .description-content.long,
+.quick-description:not(.expanded) .quick-description-actions.when-expanded {
+  display: none;
+}
+
+.quick-description .quick-description-actions .expand-link,
+.quick-description .quick-description-actions .collapse-link {
+  text-decoration: underline;
+  text-decoration-style: dotted;
+}
+
 #intro-menu {
   margin: 24px 0;
   padding: 10px;
diff --git a/src/static/js/client.js b/src/static/js/client.js
index 68b1a013..935a9d87 100644
--- a/src/static/js/client.js
+++ b/src/static/js/client.js
@@ -3524,6 +3524,72 @@ clientSteps.getPageReferences.push(getArtistExternalLinkTooltipPageReferences);
 clientSteps.addInternalListeners.push(addArtistExternalLinkTooltipInternalListeners);
 clientSteps.addPageListeners.push(addArtistExternalLinkTooltipPageListeners);
 
+// Quick description --------------------------------------
+
+const quickDescriptionInfo = initInfo('quickDescriptionInfo', {
+  quickDescriptionContainers: null,
+
+  quickDescriptionsAreExpandable: null,
+
+  expandDescriptionLinks: null,
+  collapseDescriptionLinks: null,
+});
+
+function getQuickDescriptionReferences() {
+  const info = quickDescriptionInfo;
+
+  info.quickDescriptionContainers =
+    Array.from(document.querySelectorAll('#content .quick-description'));
+
+  info.quickDescriptionsAreExpandable =
+    info.quickDescriptionContainers
+      .map(container =>
+        container.querySelector('.quick-description-actions.when-expanded'));
+
+  info.expandDescriptionLinks =
+    info.quickDescriptionContainers
+      .map(container =>
+        container.querySelector('.quick-description-actions .expand-link'));
+
+  info.collapseDescriptionLinks =
+    info.quickDescriptionContainers
+      .map(container =>
+        container.querySelector('.quick-description-actions .collapse-link'));
+}
+
+function addQuickDescriptionListeners() {
+  const info = quickDescriptionInfo;
+
+  for (const {
+    isExpandable,
+    container,
+    expandLink,
+    collapseLink,
+  } of stitchArrays({
+    isExpandable: info.quickDescriptionsAreExpandable,
+    container: info.quickDescriptionContainers,
+    expandLink: info.expandDescriptionLinks,
+    collapseLink: info.collapseDescriptionLinks,
+  })) {
+    if (!isExpandable) continue;
+
+    expandLink.addEventListener('click', event => {
+      event.preventDefault();
+      container.classList.add('expanded');
+      container.classList.remove('collapsed');
+    });
+
+    collapseLink.addEventListener('click', event => {
+      event.preventDefault();
+      container.classList.add('collapsed');
+      container.classList.remove('expanded');
+    });
+  }
+}
+
+clientSteps.getPageReferences.push(getQuickDescriptionReferences);
+clientSteps.addPageListeners.push(addQuickDescriptionListeners);
+
 // Internal search functionality --------------------------
 
 const wikiSearchInfo = initInfo('wikiSearchInfo', {
diff --git a/src/strings-default.yaml b/src/strings-default.yaml
index c9152434..96ec36ad 100644
--- a/src/strings-default.yaml
+++ b/src/strings-default.yaml
@@ -630,6 +630,14 @@ misc:
       _: "({LINK})"
       link: "More info..."
 
+    expandDescription:
+      _: "({EXPAND})"
+      expand: "Expand description..."
+
+    collapseDescription:
+      _: "({COLLAPSE})"
+      collapse: "Collapse description"
+
   # nav:
   #   Generic navigational elements. These usually only appear in the
   #   wiki's nav bar, at the top of the page.