diff options
Diffstat (limited to 'src/data/things/homepage-layout.js')
-rw-r--r-- | src/data/things/homepage-layout.js | 201 |
1 files changed, 155 insertions, 46 deletions
diff --git a/src/data/things/homepage-layout.js b/src/data/things/homepage-layout.js index 5948ff4..00d6aef 100644 --- a/src/data/things/homepage-layout.js +++ b/src/data/things/homepage-layout.js @@ -1,19 +1,37 @@ -import Thing from './thing.js'; - -import find from '../../util/find.js'; +export const HOMEPAGE_LAYOUT_DATA_FILE = 'homepage.yaml'; + +import {input} from '#composite'; +import find from '#find'; +import Thing from '#thing'; + +import { + anyOf, + is, + isCountingNumber, + isString, + isStringNonEmpty, + validateArrayItems, + validateInstanceOf, + validateReference, +} from '#validators'; + +import {exposeDependency} from '#composite/control-flow'; +import {withResolvedReference} from '#composite/wiki-data'; +import {color, contentString, name, referenceList, wikiData} + from '#composite/wiki-properties'; export class HomepageLayout extends Thing { - static [Thing.getPropertyDescriptors] = ({ - HomepageLayoutRow, + static [Thing.friendlyName] = `Homepage Layout`; - validators: { - validateArrayItems, - validateInstanceOf, - }, - }) => ({ + static [Thing.getPropertyDescriptors] = ({HomepageLayoutRow}) => ({ // Update & expose - sidebarContent: Thing.common.simpleString(), + sidebarContent: contentString(), + + navbarLinks: { + flags: {update: true, expose: true}, + update: {validate: validateArrayItems(isStringNonEmpty)}, + }, rows: { flags: {update: true, expose: true}, @@ -22,17 +40,25 @@ export class HomepageLayout extends Thing { validate: validateArrayItems(validateInstanceOf(HomepageLayoutRow)), }, }, - }) + }); + + static [Thing.yamlDocumentSpec] = { + fields: { + 'Homepage': {ignore: true}, + + 'Sidebar Content': {property: 'sidebarContent'}, + 'Navbar Links': {property: 'navbarLinks'}, + }, + }; } export class HomepageLayoutRow extends Thing { - static [Thing.getPropertyDescriptors] = ({ - Album, - Group, - }) => ({ + static [Thing.friendlyName] = `Homepage Row`; + + static [Thing.getPropertyDescriptors] = ({Album, Group}) => ({ // Update & expose - name: Thing.common.name('Unnamed Homepage Row'), + name: name('Unnamed Homepage Row'), type: { flags: {update: true, expose: true}, @@ -44,29 +70,36 @@ export class HomepageLayoutRow extends Thing { }, }, - color: Thing.common.color(), + color: color(), // Update only - // These aren't necessarily used by every HomepageLayoutRow subclass, but - // for convenience of providing this data, every row accepts all wiki data - // arrays depended upon by any subclass's behavior. - albumData: Thing.common.wikiData(Album), - groupData: Thing.common.wikiData(Group), + // These wiki data arrays aren't necessarily used by every subclass, but + // to the convenience of providing these, the superclass accepts all wiki + // data arrays depended upon by any subclass. + + albumData: wikiData({ + class: input.value(Album), + }), + + groupData: wikiData({ + class: input.value(Group), + }), }); + + static [Thing.yamlDocumentSpec] = { + fields: { + 'Row': {property: 'name'}, + 'Color': {property: 'color'}, + 'Type': {property: 'type'}, + }, + }; } export class HomepageLayoutAlbumsRow extends HomepageLayoutRow { - static [Thing.getPropertyDescriptors] = (opts, { - Album, - Group, - - validators: { - isCountingNumber, - isString, - validateArrayItems, - }, - } = opts) => ({ + static [Thing.friendlyName] = `Homepage Albums Row`; + + static [Thing.getPropertyDescriptors] = (opts, {Album, Group} = opts) => ({ ...HomepageLayoutRow[Thing.getPropertyDescriptors](opts), // Update & expose @@ -84,8 +117,52 @@ export class HomepageLayoutAlbumsRow extends HomepageLayoutRow { }, }, - sourceGroupByRef: Thing.common.singleReference(Group), - sourceAlbumsByRef: Thing.common.referenceList(Album), + displayStyle: { + flags: {update: true, expose: true}, + + update: { + validate: is('grid', 'carousel'), + }, + + expose: { + transform: (displayStyle) => + displayStyle ?? 'grid', + }, + }, + + sourceGroup: [ + { + flags: {expose: true, update: true, compose: true}, + + update: { + validate: + anyOf( + is('new-releases', 'new-additions'), + validateReference(Group[Thing.referenceType])), + }, + + expose: { + transform: (value, continuation) => + (value === 'new-releases' || value === 'new-additions' + ? value + : continuation(value)), + }, + }, + + withResolvedReference({ + ref: input.updateValue(), + data: 'groupData', + find: input.value(find.group), + }), + + exposeDependency({dependency: '#resolvedReference'}), + ], + + sourceAlbums: referenceList({ + class: input.value(Album), + find: input.value(find.album), + data: 'albumData', + }), countAlbumsFromGroup: { flags: {update: true, expose: true}, @@ -96,19 +173,51 @@ export class HomepageLayoutAlbumsRow extends HomepageLayoutRow { flags: {update: true, expose: true}, update: {validate: validateArrayItems(isString)}, }, + }); + + static [Thing.yamlDocumentSpec] = Thing.extendDocumentSpec(HomepageLayoutRow, { + fields: { + 'Display Style': {property: 'displayStyle'}, + 'Group': {property: 'sourceGroup'}, + 'Count': {property: 'countAlbumsFromGroup'}, + 'Albums': {property: 'sourceAlbums'}, + 'Actions': {property: 'actionLinks'}, + }, + }); - // Expose only + static [Thing.getYamlLoadingSpec] = ({ + documentModes: {headerAndEntries}, // Kludge, see below + thingConstructors: { + HomepageLayout, + HomepageLayoutAlbumsRow, + }, + }) => ({ + title: `Process homepage layout file`, + + // Kludge: This benefits from the same headerAndEntries style messaging as + // albums and tracks (for example), but that document mode is designed to + // support multiple files, and only one is actually getting processed here. + files: [HOMEPAGE_LAYOUT_DATA_FILE], + + documentMode: headerAndEntries, + headerDocumentThing: HomepageLayout, + entryDocumentThing: document => { + switch (document['Type']) { + case 'albums': + return HomepageLayoutAlbumsRow; + default: + throw new TypeError(`No processDocument function for row type ${document['Type']}!`); + } + }, - sourceGroup: Thing.common.dynamicThingFromSingleReference( - 'sourceGroupByRef', - 'groupData', - find.group - ), + save(results) { + if (!results[0]) { + return; + } - sourceAlbums: Thing.common.dynamicThingsFromReferenceList( - 'sourceAlbumsByRef', - 'albumData', - find.album - ), + const {header: homepageLayout, entries: rows} = results[0]; + Object.assign(homepageLayout, {rows}); + return {homepageLayout}; + }, }); } |