« get me outta code hell

module-ify listing pages - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/page
diff options
context:
space:
mode:
author(quasar) nebula <towerofnix@gmail.com>2021-06-04 15:56:59 -0300
committer(quasar) nebula <towerofnix@gmail.com>2021-06-04 15:56:59 -0300
commit0ab01d4bdced28527007c2f26d13610f1730906c (patch)
tree6cf8dabc54a9561c5e2084e4e2897b91c2835c2c /src/page
parent1343a0e1e70994909dbcdd943ed7a53f61ea3b2b (diff)
module-ify listing pages
Diffstat (limited to 'src/page')
-rw-r--r--src/page/index.js1
-rw-r--r--src/page/listing.js157
2 files changed, 158 insertions, 0 deletions
diff --git a/src/page/index.js b/src/page/index.js
index c5e1063..aa115c9 100644
--- a/src/page/index.js
+++ b/src/page/index.js
@@ -44,6 +44,7 @@ export * as artist from './artist.js';
 export * as artistAlias from './artist-alias.js';
 export * as group from './group.js';
 export * as homepage from './homepage.js';
+export * as listing from './listing.js';
 export * as static from './static.js';
 export * as news from './news.js';
 export * as track from './track.js';
diff --git a/src/page/listing.js b/src/page/listing.js
new file mode 100644
index 0000000..b0766b2
--- /dev/null
+++ b/src/page/listing.js
@@ -0,0 +1,157 @@
+// Listing page specification.
+//
+// The targets here are a bit different than for most pages: rather than data
+// objects loaded from text files in the wiki data directory, they're hard-
+// coded specifications, with various JS functions for processing wiki data
+// and turning it into user-readable HTML listings.
+//
+// Individual listing specs are described in src/listing-spec.js, but are
+// provided via wikiData like other (normal) data objects.
+
+// Imports
+
+import fixWS from 'fix-whitespace';
+
+import * as html from '../util/html.js';
+
+import {
+    UNRELEASED_TRACKS_DIRECTORY
+} from '../util/magic-constants.js';
+
+import {
+    getTotalDuration
+} from '../util/wiki-data.js';
+
+// Page exports
+
+export function condition({wikiData}) {
+    return wikiData.wikiInfo.features.listings;
+}
+
+export function targets({wikiData}) {
+    return wikiData.listingSpec;
+}
+
+export function write(listing, {wikiData}) {
+    if (listing.condition && !listing.condition({wikiData})) {
+        return null;
+    }
+
+    const { wikiInfo } = wikiData;
+
+    const data = (listing.data
+        ? listing.data({wikiData})
+        : null);
+
+    const page = {
+        type: 'page',
+        path: ['listing', listing.directory],
+        page: ({
+            link,
+            strings
+        }) => ({
+            title: listing.title({strings}),
+
+            main: {
+                content: fixWS`
+                    <h1>${listing.title({strings})}</h1>
+                    ${listing.html && (listing.data
+                        ? listing.html(data, {link, strings})
+                        : listing.html({link, strings}))}
+                    ${listing.row && fixWS`
+                        <ul>
+                            ${(data
+                                .map(item => listing.row(item, {link, strings}))
+                                .map(row => `<li>${row}</li>`)
+                                .join('\n'))}
+                        </ul>
+                    `}
+                `
+            },
+
+            sidebarLeft: {
+                content: generateSidebarForListings(listing, {link, strings, wikiData})
+            },
+
+            nav: {
+                links: [
+                    {toHome: true},
+                    {
+                        path: ['localized.listingIndex'],
+                        title: strings('listingIndex.title')
+                    },
+                    {toCurrentPage: true}
+                ]
+            }
+        })
+    };
+
+    return [page];
+}
+
+export function writeTargetless({wikiData}) {
+    const { albumData, trackData, wikiInfo } = wikiData;
+
+    const releasedTracks = trackData.filter(track => track.album.directory !== UNRELEASED_TRACKS_DIRECTORY);
+    const releasedAlbums = albumData.filter(album => album.directory !== UNRELEASED_TRACKS_DIRECTORY);
+    const duration = getTotalDuration(releasedTracks);
+
+    const page = {
+        type: 'page',
+        path: ['listingIndex'],
+        page: ({
+            strings,
+            link
+        }) => ({
+            title: strings('listingIndex.title'),
+
+            main: {
+                content: fixWS`
+                    <h1>${strings('listingIndex.title')}</h1>
+                    <p>${strings('listingIndex.infoLine', {
+                        wiki: wikiInfo.name,
+                        tracks: `<b>${strings.count.tracks(releasedTracks.length, {unit: true})}</b>`,
+                        albums: `<b>${strings.count.albums(releasedAlbums.length, {unit: true})}</b>`,
+                        duration: `<b>${strings.count.duration(duration, {approximate: true, unit: true})}</b>`
+                    })}</p>
+                    <hr>
+                    <p>${strings('listingIndex.exploreList')}</p>
+                    ${generateLinkIndexForListings(null, {link, strings, wikiData})}
+                `
+            },
+
+            sidebarLeft: {
+                content: generateSidebarForListings(null, {link, strings, wikiData})
+            },
+
+            nav: {simple: true}
+        })
+    };
+
+    return [page];
+};
+
+// Utility functions
+
+function generateSidebarForListings(currentListing, {link, strings, wikiData}) {
+    return fixWS`
+        <h1>${link.listingIndex('', {text: strings('listingIndex.title')})}</h1>
+        ${generateLinkIndexForListings(currentListing, {link, strings, wikiData})}
+    `;
+}
+
+function generateLinkIndexForListings(currentListing, {link, strings, wikiData}) {
+    const { listingSpec } = wikiData;
+
+    return fixWS`
+        <ul>
+            ${(listingSpec
+                .filter(({ condition }) => !condition || condition({wikiData}))
+                .map(listing => html.tag('li',
+                    {class: [listing === currentListing && 'current']},
+                    link.listing(listing, {text: listing.title({strings})})
+                ))
+                .join('\n'))}
+        </ul>
+    `;
+}