« 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/composite/wiki-data/index.js1
-rw-r--r--src/data/composite/wiki-data/withResolvedSeriesList.js83
-rw-r--r--src/data/composite/wiki-properties/index.js1
-rw-r--r--src/data/composite/wiki-properties/seriesList.js23
-rw-r--r--src/data/things/group.js9
-rw-r--r--src/data/validators.js8
-rw-r--r--src/data/yaml.js12
7 files changed, 137 insertions, 0 deletions
diff --git a/src/data/composite/wiki-data/index.js b/src/data/composite/wiki-data/index.js
index d9112467..afd8bdd2 100644
--- a/src/data/composite/wiki-data/index.js
+++ b/src/data/composite/wiki-data/index.js
@@ -17,6 +17,7 @@ export {default as withRedatedContributionList} from './withRedatedContributionL
 export {default as withResolvedContribs} from './withResolvedContribs.js';
 export {default as withResolvedReference} from './withResolvedReference.js';
 export {default as withResolvedReferenceList} from './withResolvedReferenceList.js';
+export {default as withResolvedSeriesList} from './withResolvedSeriesList.js';
 export {default as withReverseContributionList} from './withReverseContributionList.js';
 export {default as withReverseReferenceList} from './withReverseReferenceList.js';
 export {default as withReverseSingleReferenceList} from './withReverseSingleReferenceList.js';
diff --git a/src/data/composite/wiki-data/withResolvedSeriesList.js b/src/data/composite/wiki-data/withResolvedSeriesList.js
new file mode 100644
index 00000000..97d71f3a
--- /dev/null
+++ b/src/data/composite/wiki-data/withResolvedSeriesList.js
@@ -0,0 +1,83 @@
+import {input, templateCompositeFrom} from '#composite';
+import find from '#find';
+import {stitchArrays} from '#sugar';
+import {isSeriesList} from '#validators';
+
+import {
+  fillMissingListItems,
+  withFlattenedList,
+  withUnflattenedList,
+  withPropertiesFromList,
+} from '#composite/data';
+
+import withResolvedReferenceList from './withResolvedReferenceList.js';
+
+export default templateCompositeFrom({
+  annotation: `withResolvedSeriesList`,
+
+  inputs: {
+    list: input({validate: isSeriesList}),
+  },
+
+  outputs: ['#resolvedSeriesList'],
+
+  steps: () => [
+    withPropertiesFromList({
+      list: input('list'),
+      prefix: input.value('#serieses'),
+      properties: input.value([
+        'name',
+        'description',
+        'albums',
+      ]),
+    }),
+
+    fillMissingListItems({
+      list: '#serieses.albums',
+      fill: input.value([]),
+    }),
+
+    withFlattenedList({
+      list: '#serieses.albums',
+    }),
+
+    withResolvedReferenceList({
+      list: '#flattenedList',
+      data: 'albumData',
+      find: input.value(find.album),
+      notFoundMode: input.value('null'),
+    }),
+
+    withUnflattenedList({
+      list: '#resolvedReferenceList',
+    }).outputs({
+      '#unflattenedList': '#serieses.albums',
+    }),
+
+    fillMissingListItems({
+      list: '#serieses.description',
+      fill: input.value(null),
+    }),
+
+    {
+      dependencies: [
+        '#serieses.name',
+        '#serieses.description',
+        '#serieses.albums',
+      ],
+
+      compute: (continuation, {
+        ['#serieses.name']: name,
+        ['#serieses.description']: description,
+        ['#serieses.albums']: albums,
+      }) => continuation({
+        ['#resolvedSeriesList']:
+          stitchArrays({
+            name,
+            description,
+            albums,
+          }),
+      }),
+    },
+  ],
+});
diff --git a/src/data/composite/wiki-properties/index.js b/src/data/composite/wiki-properties/index.js
index adfe4a9b..32916771 100644
--- a/src/data/composite/wiki-properties/index.js
+++ b/src/data/composite/wiki-properties/index.js
@@ -22,6 +22,7 @@ export {default as referenceList} from './referenceList.js';
 export {default as reverseContributionList} from './reverseContributionList.js';
 export {default as reverseReferenceList} from './reverseReferenceList.js';
 export {default as reverseSingleReferenceList} from './reverseSingleReferenceList.js';
+export {default as seriesList} from './seriesList.js';
 export {default as simpleDate} from './simpleDate.js';
 export {default as simpleString} from './simpleString.js';
 export {default as singleReference} from './singleReference.js';
diff --git a/src/data/composite/wiki-properties/seriesList.js b/src/data/composite/wiki-properties/seriesList.js
new file mode 100644
index 00000000..aadd56c8
--- /dev/null
+++ b/src/data/composite/wiki-properties/seriesList.js
@@ -0,0 +1,23 @@
+import {input, templateCompositeFrom} from '#composite';
+import {isSeriesList} from '#validators';
+
+import {exposeDependency} from '#composite/control-flow';
+import {withResolvedSeriesList} from '#composite/wiki-data';
+
+export default templateCompositeFrom({
+  annotation: `seriesList`,
+
+  compose: false,
+
+  steps: () => [
+    withResolvedSeriesList({
+      list: input.updateValue({
+        validate: isSeriesList,
+      }),
+    }),
+
+    exposeDependency({
+      dependency: '#resolvedSeriesList',
+    }),
+  ],
+});
diff --git a/src/data/things/group.js b/src/data/things/group.js
index 0dbbbb7f..bd8e2fbf 100644
--- a/src/data/things/group.js
+++ b/src/data/things/group.js
@@ -3,6 +3,7 @@ export const GROUP_DATA_FILE = 'groups.yaml';
 import {input} from '#composite';
 import find from '#find';
 import Thing from '#thing';
+import {parseSerieses} from '#yaml';
 
 import {
   color,
@@ -10,6 +11,7 @@ import {
   directory,
   name,
   referenceList,
+  seriesList,
   urls,
   wikiData,
 } from '#composite/wiki-properties';
@@ -33,6 +35,8 @@ export class Group extends Thing {
       data: 'albumData',
     }),
 
+    serieses: seriesList(),
+
     // Update only
 
     albumData: wikiData({
@@ -106,6 +110,11 @@ export class Group extends Thing {
 
       'Featured Albums': {property: 'featuredAlbums'},
 
+      'Series': {
+        property: 'serieses',
+        transform: parseSerieses,
+      },
+
       'Review Points': {ignore: true},
     },
   };
diff --git a/src/data/validators.js b/src/data/validators.js
index 31c7025a..dfb20ff0 100644
--- a/src/data/validators.js
+++ b/src/data/validators.js
@@ -713,6 +713,14 @@ export const isTrackSection = validateProperties({
 
 export const isTrackSectionList = validateArrayItems(isTrackSection);
 
+export const isSeries = validateProperties({
+  name: isName,
+  description: optional(isContentString),
+  albums: optional(validateReferenceList('album')),
+});
+
+export const isSeriesList = validateArrayItems(isSeries);
+
 export function isDimensions(dimensions) {
   isArray(dimensions);
 
diff --git a/src/data/yaml.js b/src/data/yaml.js
index be59080e..f5394752 100644
--- a/src/data/yaml.js
+++ b/src/data/yaml.js
@@ -465,6 +465,18 @@ export function parseAdditionalNames(entries) {
   });
 }
 
+export function parseSerieses(entries) {
+  return parseArrayEntries(entries, item => {
+    if (typeof item !== 'object') return item;
+
+    return {
+      name: item['Name'],
+      description: item['Description'] ?? null,
+      albums: item['Albums'] ?? null,
+    };
+  });
+}
+
 export function parseDimensions(string) {
   // It's technically possible to pass an array like [30, 40] through here.
   // That's not really an issue because if it isn't of the appropriate shape,