1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
import find from '#find';
import {isName, validateArrayItems} from '#validators';
import Thing from './thing.js';
export class Artist extends Thing {
static [Thing.referenceType] = 'artist';
static [Thing.getPropertyDescriptors] = ({Album, Flash, Track}) => ({
// Update & expose
name: Thing.common.name('Unnamed Artist'),
directory: Thing.common.directory(),
urls: Thing.common.urls(),
contextNotes: Thing.common.simpleString(),
hasAvatar: Thing.common.flag(false),
avatarFileExtension: Thing.common.fileExtension('jpg'),
aliasNames: {
flags: {update: true, expose: true},
update: {validate: validateArrayItems(isName)},
expose: {transform: (names) => names ?? []},
},
isAlias: Thing.common.flag(),
aliasedArtistRef: Thing.common.singleReference(Artist),
// Update only
albumData: Thing.common.wikiData(Album),
artistData: Thing.common.wikiData(Artist),
flashData: Thing.common.wikiData(Flash),
trackData: Thing.common.wikiData(Track),
// Expose only
aliasedArtist: {
flags: {expose: true},
expose: {
dependencies: ['artistData', 'aliasedArtistRef'],
compute: ({artistData, aliasedArtistRef}) =>
aliasedArtistRef && artistData
? find.artist(aliasedArtistRef, artistData, {mode: 'quiet'})
: null,
},
},
tracksAsArtist:
Artist.filterByContrib('trackData', 'artistContribs'),
tracksAsContributor:
Artist.filterByContrib('trackData', 'contributorContribs'),
tracksAsCoverArtist:
Artist.filterByContrib('trackData', 'coverArtistContribs'),
tracksAsAny: {
flags: {expose: true},
expose: {
dependencies: ['this', 'trackData'],
compute: ({this: artist, trackData}) =>
trackData?.filter((track) =>
[
...track.artistContribs ?? [],
...track.contributorContribs ?? [],
...track.coverArtistContribs ?? [],
].some(({who}) => who === artist)) ?? [],
},
},
tracksAsCommentator: {
flags: {expose: true},
expose: {
dependencies: ['this', 'trackData'],
compute: ({this: artist, trackData}) =>
trackData?.filter(({commentatorArtists}) =>
commentatorArtists.includes(artist)) ?? [],
},
},
albumsAsAlbumArtist:
Artist.filterByContrib('albumData', 'artistContribs'),
albumsAsCoverArtist:
Artist.filterByContrib('albumData', 'coverArtistContribs'),
albumsAsWallpaperArtist:
Artist.filterByContrib('albumData', 'wallpaperArtistContribs'),
albumsAsBannerArtist:
Artist.filterByContrib('albumData', 'bannerArtistContribs'),
albumsAsCommentator: {
flags: {expose: true},
expose: {
dependencies: [this, 'albumData'],
compute: ({this: artist, albumData}) =>
albumData?.filter(({commentatorArtists}) =>
commentatorArtists.includes(artist)) ?? [],
},
},
flashesAsContributor:
Artist.filterByContrib('flashData', 'contributorContribs'),
});
static [Thing.getSerializeDescriptors] = ({
serialize: S,
}) => ({
name: S.id,
directory: S.id,
urls: S.id,
contextNotes: S.id,
hasAvatar: S.id,
avatarFileExtension: S.id,
aliasNames: S.id,
tracksAsArtist: S.toRefs,
tracksAsContributor: S.toRefs,
tracksAsCoverArtist: S.toRefs,
tracksAsCommentator: S.toRefs,
albumsAsAlbumArtist: S.toRefs,
albumsAsCoverArtist: S.toRefs,
albumsAsWallpaperArtist: S.toRefs,
albumsAsBannerArtist: S.toRefs,
albumsAsCommentator: S.toRefs,
flashesAsContributor: S.toRefs,
});
static filterByContrib = (thingDataProperty, contribsProperty) => ({
flags: {expose: true},
expose: {
dependencies: ['this', thingDataProperty],
compute: ({
this: artist,
[thingDataProperty]: thingData,
}) =>
thingData?.filter(thing =>
thing[contribsProperty]
?.some(contrib => contrib.who === artist)) ?? [],
},
});
}
|