From 7a21c665d888b0db4c47c72049f7649bf1dabcde Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Sat, 9 Sep 2023 08:47:38 -0300 Subject: data: withPropertiesFrom{Object,List} --- src/data/things/album.js | 19 +++++++----- src/data/things/composite.js | 72 ++++++++++++++++++++++++++++++++++++++++++++ src/data/things/thing.js | 17 ++++++----- 3 files changed, 94 insertions(+), 14 deletions(-) diff --git a/src/data/things/album.js b/src/data/things/album.js index 288caa04..e11d0909 100644 --- a/src/data/things/album.js +++ b/src/data/things/album.js @@ -10,7 +10,7 @@ import { exposeUpdateValueOrContinue, fillMissingListItems, withFlattenedArray, - withPropertyFromList, + withPropertiesFromList, withUnflattenedArray, withUpdateValueAsDependency, } from '#composite'; @@ -86,17 +86,22 @@ export class Album extends Thing { withUpdateValueAsDependency({into: '#sections'}), - withPropertyFromList({list: '#sections', property: 'tracks', into: '#sections.trackRefs'}), - withPropertyFromList({list: '#sections', property: 'dateOriginallyReleased'}), - withPropertyFromList({list: '#sections', property: 'isDefaultTrackSection'}), - withPropertyFromList({list: '#sections', property: 'color'}), + withPropertiesFromList({ + list: '#sections', + properties: [ + 'tracks', + 'dateOriginallyReleased', + 'isDefaultTrackSection', + 'color', + ], + }), - fillMissingListItems({list: '#sections.trackRefs', value: []}), + fillMissingListItems({list: '#sections.tracks', value: []}), fillMissingListItems({list: '#sections.isDefaultTrackSection', value: false}), fillMissingListItems({list: '#sections.color', dependency: 'color'}), withFlattenedArray({ - from: '#sections.trackRefs', + from: '#sections.tracks', into: '#trackRefs', intoIndices: '#sections.startIndex', }), diff --git a/src/data/things/composite.js b/src/data/things/composite.js index b37b8e31..e3225563 100644 --- a/src/data/things/composite.js +++ b/src/data/things/composite.js @@ -1119,6 +1119,39 @@ export function withPropertyFromObject({ }; } +// Gets the listed properties from some object, providing each property's value +// as a dependency prefixed with the same name as the object (by default). +// If the object itself is null, all provided dependencies will be null; +// if it's missing only select properties, those will be provided as null. +export function withPropertiesFromObject({ + object, + properties, + prefix = + (object.startsWith('#') + ? object + : `#${object}`), +}) { + return { + annotation: `withPropertiesFromObject`, + flags: {expose: true, compose: true}, + + expose: { + mapDependencies: {object}, + options: {prefix, properties}, + + compute: ({object, '#options': {prefix, properties}}, continuation) => + continuation( + Object.fromEntries( + properties.map(property => [ + `${prefix}.${property}`, + (object === null || object === undefined + ? null + : object[property] ?? null), + ]))), + }, + }; +} + // Gets a property from each of a list of objects (in a dependency) and // provides the results. This doesn't alter any list indices, so positions // which were null in the original list are kept null here. Objects which don't @@ -1159,6 +1192,45 @@ export function withPropertyFromList({ }; } +// Gets the listed properties from each of a list of objects, providing lists +// of property values each into a dependency prefixed with the same name as the +// list (by default). Like withPropertyFromList, this doesn't alter indices. +export function withPropertiesFromList({ + list, + properties, + prefix = + (list.startsWith('#') + ? list + : `#${list}`), +}) { + return { + annotation: `withPropertiesFromList`, + flags: {expose: true, compose: true}, + + expose: { + mapDependencies: {list}, + options: {prefix, properties}, + + compute({list, '#options': {prefix, properties}}, continuation) { + const lists = + Object.fromEntries( + properties.map(property => [`${prefix}.${property}`, []])); + + for (const item of list) { + for (const property of properties) { + lists[`${prefix}.${property}`].push( + (item === null || item === undefined + ? null + : item[property] ?? null)); + } + } + + return continuation(lists); + } + } + } +} + // Replaces items of a list, which are null or undefined, with some fallback // value, either a constant (set {value}) or from a dependency ({dependency}). // By default, this replaces the passed dependency. diff --git a/src/data/things/thing.js b/src/data/things/thing.js index a87e6ed6..52f0b773 100644 --- a/src/data/things/thing.js +++ b/src/data/things/thing.js @@ -15,7 +15,7 @@ import { exposeDependency, exposeDependencyOrContinue, raiseWithoutDependency, - withPropertyFromList, + withPropertiesFromList, withUpdateValueAsDependency, } from '#composite'; @@ -409,21 +409,24 @@ export function withResolvedContribs({ raise: {into: []}, }), - withPropertyFromList({list: from, property: 'who', into: '#artistRefs'}), - withPropertyFromList({list: from, property: 'what', into: '#what'}), + withPropertiesFromList({ + list: from, + properties: ['who', 'what'], + prefix: '#contribs', + }), withResolvedReferenceList({ - list: '#artistRefs', + list: '#contribs.who', data: 'artistData', - into: '#who', + into: '#contribs.who', find: find.artist, notFoundMode: 'null', }), { - dependencies: ['#who', '#what'], + dependencies: ['#contribs.who', '#contribs.what'], mapContinuation: {into}, - compute({'#who': who, '#what': what}, continuation) { + compute({'#contribs.who': who, '#contribs.what': what}, continuation) { filterMultipleArrays(who, what, (who, _what) => who); return continuation({ into: stitchArrays({who, what}), -- cgit 1.3.0-6-gf8a5