« 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/data/things.js24
-rw-r--r--src/data/validators.js8
-rw-r--r--src/data/yaml.js24
3 files changed, 55 insertions, 1 deletions
diff --git a/src/data/things.js b/src/data/things.js
index 0695b0d3..80e22e3e 100644
--- a/src/data/things.js
+++ b/src/data/things.js
@@ -4,6 +4,7 @@
 import CacheableObject from './cacheable-object.js';
 
 import {
+    isAdditionalFileList,
     isBoolean,
     isColor,
     isCommentary,
@@ -207,6 +208,26 @@ Thing.common = {
         update: {validate: isCommentary}
     }),
 
+    // This is a somewhat more involved data structure - it's for additional
+    // or "bonus" files associated with albums or tracks (or anything else).
+    // It's got this form:
+    //
+    //     [
+    //         {title: 'Booklet', files: ['Booklet.pdf']},
+    //         {
+    //             title: 'Wallpaper',
+    //             description: 'Cool Wallpaper!',
+    //             files: ['1440x900.png', '1920x1080.png']
+    //         },
+    //         {title: 'Alternate Covers', description: null, files: [...]},
+    //         ...
+    //     ]
+    //
+    additionalFiles: () => ({
+        flags: {update: true, expose: true},
+        update: {validate: isAdditionalFileList}
+    }),
+
     // A reference list! Keep in mind this is for general references to wiki
     // objects of (usually) other Thing subclasses, not specifically leitmotif
     // references in tracks (although that property uses referenceList too!).
@@ -497,6 +518,7 @@ Album.propertyDescriptors = {
     isListedOnHomepage: Thing.common.flag(true),
 
     commentary: Thing.common.commentary(),
+    additionalFiles: Thing.common.additionalFiles(),
 
     // Update only
 
@@ -566,6 +588,7 @@ Album[S.serializeDescriptors] = {
     isListedOnHomepage: S.id,
 
     commentary: S.id,
+    additionalFiles: S.id,
 
     tracks: S.toRefs,
     groups: S.toRefs,
@@ -712,6 +735,7 @@ Track.propertyDescriptors = {
 
     commentary: Thing.common.commentary(),
     lyrics: Thing.common.simpleString(),
+    additionalFiles: Thing.common.additionalFiles(),
 
     // Update only
 
diff --git a/src/data/validators.js b/src/data/validators.js
index c0e41c98..0d325aed 100644
--- a/src/data/validators.js
+++ b/src/data/validators.js
@@ -235,6 +235,14 @@ export const isContribution = validateProperties({
 
 export const isContributionList = validateArrayItems(isContribution);
 
+export const isAdditionalFile = validateProperties({
+    title: isString,
+    description: value => (value === undefined || value === null || isString(value)),
+    files: validateArrayItems(isString)
+});
+
+export const isAdditionalFileList = validateArrayItems(isAdditionalFile);
+
 export function isDimensions(dimensions) {
     isArray(dimensions);
 
diff --git a/src/data/yaml.js b/src/data/yaml.js
index 21b56d43..e9212764 100644
--- a/src/data/yaml.js
+++ b/src/data/yaml.js
@@ -190,6 +190,8 @@ export const processAlbumDocument = makeProcessDocument(Album, {
         'Default Track Cover Art Date': value => new Date(value),
 
         'Banner Dimensions': parseDimensions,
+
+        'Additional Files': parseAdditionalFiles,
     },
 
     propertyFieldMapping: {
@@ -229,6 +231,8 @@ export const processAlbumDocument = makeProcessDocument(Album, {
         groupsByRef: 'Groups',
         artTagsByRef: 'Art Tags',
         commentary: 'Commentary',
+
+        additionalFiles: 'Additional Files',
     }
 });
 
@@ -254,6 +258,8 @@ export const processTrackDocument = makeProcessDocument(Track, {
         'Artists': parseContributors,
         'Contributors': parseContributors,
         'Cover Artists': parseContributors,
+
+        'Additional Files': parseAdditionalFiles,
     },
 
     propertyFieldMapping: {
@@ -277,7 +283,9 @@ export const processTrackDocument = makeProcessDocument(Track, {
         originalReleaseTrackByRef: 'Originally Released As',
 
         commentary: 'Commentary',
-        lyrics: 'Lyrics'
+        lyrics: 'Lyrics',
+
+        additionalFiles: 'Additional Files',
     },
 
     ignoredFields: ['Sampled Tracks']
@@ -465,6 +473,20 @@ export function getDurationInSeconds(string) {
     }
 }
 
+export function parseAdditionalFiles(array) {
+    if (!array) return null;
+    if (!Array.isArray(array)) {
+        // Error will be caught when validating against whatever this value is
+        return array;
+    }
+
+    return array.map(item => ({
+        title: item['Title'],
+        description: item['Description'] ?? null,
+        files: item['Files']
+    }));
+}
+
 export function parseCommentary(text) {
     if (text) {
         const lines = String(text).split('\n');