« get me outta code hell

data: WikiInfo: contributionPresets - 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>2024-03-04 20:27:24 -0400
committer(quasar) nebula <qznebula@protonmail.com>2024-06-12 17:26:32 -0300
commit5826cb1f9a21825f4998013a67ae7c9aa6bcb102 (patch)
treeeb3fc986aaf4d0073a855b1898c0cd1032a98e07
parentbe402bfcad9a8ab5287ed15f942f5d4730d7490e (diff)
data: WikiInfo: contributionPresets
-rw-r--r--src/data/things/wiki-info.js21
-rw-r--r--src/data/validators.js52
-rw-r--r--src/data/yaml.js67
3 files changed, 139 insertions, 1 deletions
diff --git a/src/data/things/wiki-info.js b/src/data/things/wiki-info.js
index 2a2c9986..b7b7b01c 100644
--- a/src/data/things/wiki-info.js
+++ b/src/data/things/wiki-info.js
@@ -3,7 +3,16 @@ export const WIKI_INFO_FILE = 'wiki-info.yaml';
 import {input} from '#composite';
 import find from '#find';
 import Thing from '#thing';
-import {isBoolean, isColor, isLanguageCode, isName, isURL} from '#validators';
+import {parseContributionPresets} from '#yaml';
+
+import {
+  isBoolean,
+  isColor,
+  isContributionPresetList,
+  isLanguageCode,
+  isName,
+  isURL,
+} from '#validators';
 
 import {exitWithoutDependency} from '#composite/control-flow';
 import {contentString, flag, name, referenceList, wikiData}
@@ -58,6 +67,11 @@ export class WikiInfo extends Thing {
       data: 'groupData',
     }),
 
+    contributionPresets: {
+      flags: {update: true, expose: true},
+      update: {validate: isContributionPresetList},
+    },
+
     // Feature toggles
     enableFlashesAndGames: flag(false),
     enableListings: flag(false),
@@ -105,6 +119,11 @@ export class WikiInfo extends Thing {
       'Enable News': {property: 'enableNews'},
       'Enable Art Tag UI': {property: 'enableArtTagUI'},
       'Enable Group UI': {property: 'enableGroupUI'},
+
+      'Contribution Presets': {
+        property: 'contributionPresets',
+        transform: parseContributionPresets,
+      },
     },
   };
 
diff --git a/src/data/validators.js b/src/data/validators.js
index 5d681311..0f1d2e62 100644
--- a/src/data/validators.js
+++ b/src/data/validators.js
@@ -640,6 +640,58 @@ export const isContribution = validateProperties({
 
 export const isContributionList = validateArrayItems(isContribution);
 
+export const contributionPresetPropertySpec = {
+  album: [
+    'artistContribs',
+  ],
+
+  flash: [
+    'contributorContribs',
+  ],
+
+  track: [
+    'artistContribs',
+    'contributorContribs',
+  ],
+};
+
+// TODO: This validator basically constructs itself as it goes.
+// This is definitely some shenanigans!
+export function isContributionPresetContext(list) {
+  isArray(list);
+
+  if (empty(list)) {
+    throw new TypeError(`Expected at least one item`);
+  }
+
+  const isTarget =
+    is(...Object.keys(contributionPresetPropertySpec));
+
+  const [target, ...properties] = list;
+
+  isTarget(target);
+
+  const isProperty =
+    is(...contributionPresetPropertySpec[target]);
+
+  const isPropertyList =
+    validateArrayItems(isProperty);
+
+  isPropertyList(properties);
+
+  return true;
+}
+
+export const isContributionPreset = validateProperties({
+  annotation: isStringNonEmpty,
+  context: isContributionPresetContext,
+
+  countInDurationTotals: optional(isBoolean),
+  countInContributionTotals: optional(isBoolean),
+});
+
+export const isContributionPresetList = validateArrayItems(isContributionPreset);
+
 export const isAdditionalFile = validateProperties({
   title: isName,
   description: optional(isContentString),
diff --git a/src/data/yaml.js b/src/data/yaml.js
index 7e470531..d3c77b9e 100644
--- a/src/data/yaml.js
+++ b/src/data/yaml.js
@@ -482,6 +482,73 @@ export function parseDimensions(string) {
   return nums;
 }
 
+export const contributionPresetYAMLSpec = [
+  {from: 'Album', to: 'album', fields: [
+    {from: 'Artists', to: 'artistContribs'},
+  ]},
+
+  {from: 'Flash', to: 'flash', fields: [
+    {from: 'Contributors', to: 'contributorContribs'},
+  ]},
+
+  {from: 'Track', to: 'track', fields: [
+    {from: 'Artists', to: 'artistContribs'},
+    {from: 'Contributors', to: 'contributorContribs'},
+  ]},
+];
+
+export function parseContributionPresetContext(context) {
+  if (!Array.isArray(context)) {
+    return context;
+  }
+
+  const [target, ...fields] = context;
+
+  const targetEntry =
+    contributionPresetYAMLSpec
+      .find(({from}) => from === target);
+
+  if (!targetEntry) {
+    return context;
+  }
+
+  const properties =
+    fields.map(field => {
+      const fieldEntry =
+        targetEntry.fields
+          .find(({from}) => from === field);
+
+      if (!fieldEntry) return field;
+
+      return fieldEntry.to;
+    });
+
+  return [targetEntry.to, ...properties];
+}
+
+export function parseContributionPresets(list) {
+  if (!Array.isArray(list)) return list;
+
+  return list.map(item => {
+    if (typeof item !== 'object') return item;
+
+    return {
+      annotation:
+        item['Annotation'] ?? null,
+
+      context:
+        parseContributionPresetContext(
+          item['Context'] ?? null),
+
+      countInContributionTotals:
+        item['Count In Contribution Totals'] ?? null,
+
+      countInDurationTotals:
+        item['Count In Duration Totals'] ?? null,
+    };
+  });
+}
+
 // documentModes: Symbols indicating sets of behavior for loading and processing
 // data files.
 export const documentModes = {