diff options
author | (quasar) nebula <qznebula@protonmail.com> | 2023-01-15 20:37:34 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-15 20:37:34 -0400 |
commit | 62dbb79342927cb1fe19651e33fcc27bc2804f6e (patch) | |
tree | 313c34f694337cae483047d9e06f0a410e44d155 | |
parent | 088a0d4ef42c90d6e81586601ee6cb37340b5bf4 (diff) | |
parent | 8093844a5460683b48219dba238b0e6e864dacd8 (diff) |
Merge pull request #117 from hsmusic/track-sections
Change trackGroups to trackSections, avoid usage of a dedicated "domain-specific" Thing subclass
-rw-r--r-- | src/data/things/album.js | 113 | ||||
-rw-r--r-- | src/data/things/track.js | 6 | ||||
-rw-r--r-- | src/data/things/validators.js | 14 | ||||
-rw-r--r-- | src/data/yaml.js | 69 | ||||
-rw-r--r-- | src/page/album.js | 34 | ||||
-rw-r--r-- | src/strings-default.json | 2 | ||||
-rw-r--r-- | test/things.js | 8 |
7 files changed, 110 insertions, 136 deletions
diff --git a/src/data/things/album.js b/src/data/things/album.js index ade34e3d..0c0c7fb4 100644 --- a/src/data/things/album.js +++ b/src/data/things/album.js @@ -10,13 +10,11 @@ export class Album extends Thing { Artist, Group, Track, - TrackGroup, validators: { isDate, isDimensions, - validateArrayItems, - validateInstanceOf, + isTrackSectionList, }, }) => ({ // Update & expose @@ -56,11 +54,39 @@ export class Album extends Thing { groupsByRef: Thing.common.referenceList(Group), artTagsByRef: Thing.common.referenceList(ArtTag), - trackGroups: { + trackSections: { flags: {update: true, expose: true}, update: { - validate: validateArrayItems(validateInstanceOf(TrackGroup)), + validate: isTrackSectionList, + }, + + expose: { + dependencies: ['color', 'trackData'], + transform(trackSections, { + color: albumColor, + trackData, + }) { + let startIndex = 0; + return trackSections?.map(section => ({ + name: section.name ?? null, + color: section.color ?? albumColor ?? null, + dateOriginallyReleased: section.dateOriginallyReleased ?? null, + isDefaultTrackSection: section.isDefaultTrackSection ?? false, + + startIndex: ( + startIndex += section.tracksByRef.length, + startIndex - section.tracksByRef.length + ), + + tracksByRef: section.tracksByRef ?? [], + tracks: + (trackData && section.tracksByRef + ?.map(ref => find.track(ref, trackData, {mode: 'quiet'})) + .filter(Boolean)) ?? + [], + })); + }, }, }, @@ -114,11 +140,11 @@ export class Album extends Thing { flags: {expose: true}, expose: { - dependencies: ['trackGroups', 'trackData'], - compute: ({trackGroups, trackData}) => - trackGroups && trackData - ? trackGroups - .flatMap((group) => group.tracksByRef ?? []) + dependencies: ['trackSections', 'trackData'], + compute: ({trackSections, trackData}) => + trackSections && trackData + ? trackSections + .flatMap((section) => section.tracksByRef ?? []) .map((ref) => find.track(ref, trackData, {mode: 'quiet'})) .filter(Boolean) : [], @@ -179,72 +205,11 @@ export class Album extends Thing { }); } -export class TrackGroup extends Thing { - static [Thing.getPropertyDescriptors] = ({ - isColor, - Track, - - validators: { - validateInstanceOf, - }, - }) => ({ - // Update & expose - +export class TrackSectionHelper extends Thing { + static [Thing.getPropertyDescriptors] = () => ({ name: Thing.common.name('Unnamed Track Group'), - - color: { - flags: {update: true, expose: true}, - - update: {validate: isColor}, - - expose: { - dependencies: ['album'], - - transform(color, {album}) { - return color ?? album?.color ?? null; - }, - }, - }, - + color: Thing.common.color(), dateOriginallyReleased: Thing.common.simpleDate(), - - tracksByRef: Thing.common.referenceList(Track), - isDefaultTrackGroup: Thing.common.flag(false), - - // Update only - - album: { - flags: {update: true}, - update: {validate: validateInstanceOf(Album)}, - }, - - trackData: Thing.common.wikiData(Track), - - // Expose only - - tracks: { - flags: {expose: true}, - - expose: { - dependencies: ['tracksByRef', 'trackData'], - compute: ({tracksByRef, trackData}) => - tracksByRef && trackData - ? tracksByRef.map((ref) => find.track(ref, trackData)).filter(Boolean) - : [], - }, - }, - - startIndex: { - flags: {expose: true}, - - expose: { - dependencies: ['album'], - compute: ({album, [TrackGroup.instance]: trackGroup}) => - album.trackGroups - .slice(0, album.trackGroups.indexOf(trackGroup)) - .reduce((acc, tg) => acc + tg.tracks.length, 0), - }, - }, }) } diff --git a/src/data/things/track.js b/src/data/things/track.js index a8020956..6b1e958b 100644 --- a/src/data/things/track.js +++ b/src/data/things/track.js @@ -151,9 +151,9 @@ export class Track extends Thing { dependencies: ['albumData'], compute: ({albumData, [Track.instance]: track}) => - Track.findAlbum(track, albumData)?.trackGroups.find((tg) => - tg.tracks.includes(track) - )?.color ?? null, + Track.findAlbum(track, albumData) + ?.trackSections.find(({tracks}) => tracks.includes(track)) + ?.color ?? null, }, }, diff --git a/src/data/things/validators.js b/src/data/things/validators.js index a0d473ba..24db3c79 100644 --- a/src/data/things/validators.js +++ b/src/data/things/validators.js @@ -96,6 +96,10 @@ export function isStringNonEmpty(value) { return true; } +export function optional(validator) { + return value => value === null || value === undefined || validator(value); +} + // Complex types (non-primitives) export function isInstance(value, constructor) { @@ -252,6 +256,16 @@ export const isAdditionalFile = validateProperties({ export const isAdditionalFileList = validateArrayItems(isAdditionalFile); +export const isTrackSection = validateProperties({ + name: optional(isString), + color: optional(isColor), + dateOriginallyReleased: optional(isDate), + isDefaultTrackSection: optional(isBoolean), + tracksByRef: optional(validateReferenceList('track')), +}); + +export const isTrackSectionList = validateArrayItems(isTrackSection); + export function isDimensions(dimensions) { isArray(dimensions); diff --git a/src/data/yaml.js b/src/data/yaml.js index b00d68ee..f269d447 100644 --- a/src/data/yaml.js +++ b/src/data/yaml.js @@ -227,7 +227,7 @@ export const processAlbumDocument = makeProcessDocument(T.Album, { }, }); -export const processTrackGroupDocument = makeProcessDocument(T.TrackGroup, { +export const processTrackSectionDocument = makeProcessDocument(T.TrackSectionHelper, { fieldTransformations: { 'Date Originally Released': (value) => new Date(value), }, @@ -652,7 +652,7 @@ export const dataSteps = [ processHeaderDocument: processAlbumDocument, processEntryDocument(document) { return 'Group' in document - ? processTrackGroupDocument(document) + ? processTrackSectionDocument(document) : processTrackDocument(document); }, @@ -661,39 +661,39 @@ export const dataSteps = [ const trackData = []; for (const {header: album, entries} of results) { - // We can't mutate an array once it's set as a property - // value, so prepare the tracks and track groups that will - // show up in a track list all the way before actually - // applying them. - const trackGroups = []; - let currentTracksByRef = null; - let currentTrackGroup = null; + // We can't mutate an array once it's set as a property value, + // so prepare the track sections that will show up in a track list + // all the way before actually applying them. (It's okay to mutate + // an individual section before applying it, since those are just + // generic objects; they aren't Things in and of themselves.) + const trackSections = []; + + let currentTrackSection = { + name: `Default Track Section`, + isDefaultTrackSection: true, + tracksByRef: [], + }; const albumRef = T.Thing.getReference(album); - const closeCurrentTrackGroup = () => { - if (currentTracksByRef) { - let trackGroup; - - if (currentTrackGroup) { - trackGroup = currentTrackGroup; - } else { - trackGroup = new T.TrackGroup(); - trackGroup.name = `Default Track Group`; - trackGroup.isDefaultTrackGroup = true; - } - - trackGroup.album = album; - trackGroup.tracksByRef = currentTracksByRef; - trackGroups.push(trackGroup); + const closeCurrentTrackSection = () => { + if (!empty(currentTrackSection.tracksByRef)) { + trackSections.push(currentTrackSection); } }; for (const entry of entries) { - if (entry instanceof T.TrackGroup) { - closeCurrentTrackGroup(); - currentTracksByRef = []; - currentTrackGroup = entry; + if (entry instanceof T.TrackSectionHelper) { + closeCurrentTrackSection(); + + currentTrackSection = { + name: entry.name, + color: entry.color, + dateOriginallyReleased: entry.dateOriginallyReleased, + isDefaultTrackSection: false, + tracksByRef: [], + }; + continue; } @@ -701,17 +701,12 @@ export const dataSteps = [ entry.dataSourceAlbumByRef = albumRef; - const trackRef = T.Thing.getReference(entry); - if (currentTracksByRef) { - currentTracksByRef.push(trackRef); - } else { - currentTracksByRef = [trackRef]; - } + currentTrackSection.tracksByRef.push(T.Thing.getReference(entry)); } - closeCurrentTrackGroup(); + closeCurrentTrackSection(); - album.trackGroups = trackGroups; + album.trackSections = trackSections; albumData.push(album); } @@ -1126,8 +1121,6 @@ export function linkWikiDataArrays(wikiData) { assignWikiData([WD.wikiInfo], 'groupData'); assignWikiData(WD.albumData, 'artistData', 'artTagData', 'groupData', 'trackData'); - WD.albumData.forEach((album) => assignWikiData(album.trackGroups, 'trackData')); - assignWikiData(WD.trackData, 'albumData', 'artistData', 'artTagData', 'flashData', 'trackData'); assignWikiData(WD.artistData, 'albumData', 'artistData', 'flashData', 'trackData'); assignWikiData(WD.groupData, 'albumData', 'groupCategoryData'); diff --git a/src/page/album.js b/src/page/album.js index 1fc74520..906c02ea 100644 --- a/src/page/album.js +++ b/src/page/album.js @@ -50,10 +50,10 @@ export function write(album, {wikiData}) { const hasAdditionalFiles = !empty(album.additionalFiles); const albumDuration = getTotalDuration(album.tracks); - const displayTrackGroups = - album.trackGroups && - (album.trackGroups.length > 1 || - !album.trackGroups[0].isDefaultTrackGroup); + const displayTrackSections = + album.trackSections && + (album.trackSections.length > 1 || + !album.trackSections[0].isDefaultTrackSection); const listTag = getAlbumListTag(album); @@ -107,10 +107,10 @@ export function write(album, {wikiData}) { wallpaperArtistContribs: serializeContribs(album.wallpaperArtistContribs), bannerArtistContribs: serializeContribs(album.bannerArtistContribs), groups: serializeGroupsForAlbum(album), - trackGroups: album.trackGroups?.map((trackGroup) => ({ - name: trackGroup.name, - color: trackGroup.color, - tracks: trackGroup.tracks.map((track) => track.directory), + trackSections: album.trackSections?.map((section) => ({ + name: section.name, + color: section.color, + tracks: section.tracks.map((track) => track.directory), })), tracks: album.tracks.map((track) => ({ link: serializeLink(track), @@ -300,10 +300,10 @@ export function write(album, {wikiData}) { ), })), - displayTrackGroups && + displayTrackSections && html.tag('dl', {class: 'album-group-list'}, - album.trackGroups.flatMap(({ + album.trackSections.flatMap(({ name, startIndex, tracks, @@ -322,7 +322,7 @@ export function write(album, {wikiData}) { tracks.map(trackToListItem))), ])), - !displayTrackGroups && + !displayTrackSections && html.tag(listTag, album.tracks.map(trackToListItem)), @@ -515,7 +515,7 @@ export function generateAlbumSidebar(album, currentTrack, { const listTag = getAlbumListTag(album); - const {trackGroups} = album; + const {trackSections} = album; const trackToListItem = (track) => html.tag('li', @@ -524,19 +524,19 @@ export function generateAlbumSidebar(album, currentTrack, { track: link.track(track), })); - const nameOrDefault = (isDefaultTrackGroup, name) => - isDefaultTrackGroup - ? language.$('albumSidebar.trackList.fallbackGroupName') + const nameOrDefault = (isDefaultTrackSection, name) => + isDefaultTrackSection + ? language.$('albumSidebar.trackList.fallbackSectionName') : name; const trackListPart = [ html.tag('h1', link.album(album)), - ...trackGroups.map(({name, color, startIndex, tracks, isDefaultTrackGroup}) => { + ...trackSections.map(({name, color, startIndex, tracks, isDefaultTrackSection}) => { const groupName = html.tag('span', {class: 'group-name'}, nameOrDefault( - isDefaultTrackGroup, + isDefaultTrackSection, name )); return html.tag('details', diff --git a/src/strings-default.json b/src/strings-default.json index f9c1db8b..13ae61af 100644 --- a/src/strings-default.json +++ b/src/strings-default.json @@ -191,7 +191,7 @@ "homepage.title": "{TITLE}", "homepage.news.title": "News", "homepage.news.entry.viewRest": "(View rest of entry!)", - "albumSidebar.trackList.fallbackGroupName": "Track list", + "albumSidebar.trackList.fallbackSectionName": "Track list", "albumSidebar.trackList.group": "{GROUP}", "albumSidebar.trackList.group.withRange": "{GROUP} ({RANGE})", "albumSidebar.trackList.item": "{TRACK}", diff --git a/test/things.js b/test/things.js index f36a4995..0d74b60d 100644 --- a/test/things.js +++ b/test/things.js @@ -9,9 +9,11 @@ import { function stubAlbum(tracks) { const album = new Album(); - const trackGroup = new TrackGroup(); - trackGroup.tracksByRef = tracks.map(t => Thing.getReference(t)); - album.trackGroups = [trackGroup]; + album.trackSections = [ + { + tracksByRef: tracks.map(t => Thing.getReference(t)), + }, + ]; album.trackData = tracks; return album; } |