From 6a74354abac7f265a4a28017a646dc245d155d79 Mon Sep 17 00:00:00 2001 From: Schlauer-Hax Date: Fri, 29 Mar 2024 19:36:40 +0100 Subject: [PATCH] add artistdb & songdb Co-authored-by: Skidder Co-authored-by: lucsoft --- pages/_legacy/helper.ts | 10 ++++----- pages/_legacy/music/changeDrop.ts | 4 ++-- pages/_legacy/music/data.ts | 4 ++-- pages/_legacy/music/table.ts | 4 ++-- pages/music/state.ts | 4 ++-- spec/music.ts | 35 ++++++++++++++++++------------- 6 files changed, 34 insertions(+), 27 deletions(-) diff --git a/pages/_legacy/helper.ts b/pages/_legacy/helper.ts index 1bbe0c7..1527892 100644 --- a/pages/_legacy/helper.ts +++ b/pages/_legacy/helper.ts @@ -2,7 +2,7 @@ import { API, fileCache, Permission, stupidErrorAlert, Table2 } from "shared/mod import { asState, Box, Button, Cache, CenterV, Component, Custom, DropDownInput, Horizontal, IconButton, Image, Label, MIcon, SheetDialog, SheetsStack, Spacer, StateHandler, Style, SupportedThemes, TextInput, Vertical } from "webgen/mod.ts"; import { templateArtwork } from "../../assets/imports.ts"; import { loginRequired } from "../../components/pages.ts"; -import { Artist, ArtistTypes, Drop } from "../../spec/music.ts"; +import { ArtistRef, ArtistTypes, Drop } from "../../spec/music.ts"; export const allowedAudioFormats = ["audio/flac", "audio/wav", "audio/mp3"]; export const allowedImageFormats = ["image/png", "image/jpeg"]; @@ -185,7 +185,7 @@ export function saveBlob(blob: Blob, fileName: string) { } const ARTIST_ARRAY = ["PRIMARY", "FEATURING", "PRODUCER", "SONGWRITER"]; -export const EditArtistsDialog = (state: StateHandler<{ artists: Artist[] }>) => { +export const EditArtistsDialog = (state: StateHandler<{ artists: ArtistRef[] }>) => { const dialog = SheetDialog( sheetStack, "Manage your Artists", @@ -193,11 +193,11 @@ export const EditArtistsDialog = (state: StateHandler<{ artists: Artist[] }>) => new Table2(state.$artists) .addClass("artist-table") .setColumnTemplate("10rem auto min-content") - .addColumn("Type", (artist: Artist) => + .addColumn("Type", (artist: ArtistRef) => DropDownInput("Type", ARTIST_ARRAY) .setValue(artist[2]) .onChange((data) => artist[2] = data)) - .addColumn("Name", (artist: Artist) => + .addColumn("Name", (artist: ArtistRef) => TextInput("text", "Name", "blur") .setValue(artist[0]) .onChange((data) => artist[0] = data ?? "")) @@ -205,7 +205,7 @@ export const EditArtistsDialog = (state: StateHandler<{ artists: Artist[] }>) => Horizontal( Spacer(), Button("Add Artist") - .onClick(() => state.artists = asState([...state.artists, ["", "", ArtistTypes.Primary]] as Artist[])), + .onClick(() => state.artists = asState([...state.artists, ["", "", ArtistTypes.Primary]] as ArtistRef[])), ).setPadding("0 0 3rem 0"), Horizontal( Spacer(), diff --git a/pages/_legacy/music/changeDrop.ts b/pages/_legacy/music/changeDrop.ts index a3684cd..c8bc1f6 100644 --- a/pages/_legacy/music/changeDrop.ts +++ b/pages/_legacy/music/changeDrop.ts @@ -5,7 +5,7 @@ import { zod } from "webgen/zod.ts"; import { templateArtwork } from "../../../assets/imports.ts"; import genres from "../../../data/genres.json" with { type: "json" }; import language from "../../../data/language.json" with { type: "json" }; -import { artist, DATE_PATTERN, Drop, song, userString } from "../../../spec/music.ts"; +import { artistref, DATE_PATTERN, Drop, song, userString } from "../../../spec/music.ts"; import { allowedImageFormats, EditArtistsDialog, getSecondary } from "../helper.ts"; import { uploadArtwork } from "./data.ts"; @@ -20,7 +20,7 @@ export function ChangeDrop(drop: Drop) { asState(drop), zod.object({ title: userString, - artists: artist.array().refine((x) => x.some(([, , type]) => type == "PRIMARY"), { message: "At least one primary artist is required" }), + artists: artistref.array().refine((x) => x.some(({type}) => type == "PRIMARY"), { message: "At least one primary artist is required" }), release: zod.string().regex(DATE_PATTERN, { message: "Not a date" }), language: zod.string(), primaryGenre: zod.string(), diff --git a/pages/_legacy/music/data.ts b/pages/_legacy/music/data.ts index 4ad6362..70604f1 100644 --- a/pages/_legacy/music/data.ts +++ b/pages/_legacy/music/data.ts @@ -1,9 +1,9 @@ import { API, StreamingUploadHandler } from "shared/mod.ts"; import { delay } from "std/async/delay.ts"; import { AdvancedImage, asState, Reference, StateHandler } from "webgen/mod.ts"; -import { Artist, Song } from "../../../spec/music.ts"; +import { ArtistRef, Song } from "../../../spec/music.ts"; -export function uploadSongToDrop(state: StateHandler<{ songs: Song[]; artists: Artist[]; language: string | undefined; primaryGenre: string | undefined; secondaryGenre: string | undefined; _id: string }>, uploadingSongs: Reference, file: File) { +export function uploadSongToDrop(state: StateHandler<{ songs: Song[]; artists: ArtistRef[]; language: string | undefined; primaryGenre: string | undefined; secondaryGenre: string | undefined; _id: string }>, uploadingSongs: Reference, file: File) { const uploadId = crypto.randomUUID(); uploadingSongs.addItem(uploadId); diff --git a/pages/_legacy/music/table.ts b/pages/_legacy/music/table.ts index a620ce9..d359aeb 100644 --- a/pages/_legacy/music/table.ts +++ b/pages/_legacy/music/table.ts @@ -2,7 +2,7 @@ import { Progress, Table2 } from "shared/mod.ts"; import { Box, ButtonStyle, Checkbox, Color, DropDownInput, IconButton, Image, InlineTextInput, Label, MIcon, StateHandler } from "webgen/mod.ts"; import genres from "../../../data/genres.json" with { type: "json" }; import language from "../../../data/language.json" with { type: "json" }; -import { Artist, Song } from "../../../spec/music.ts"; +import { ArtistRef, Song } from "../../../spec/music.ts"; import { EditArtistsDialog, getSecondary, getYearList, ProfilePicture } from "../helper.ts"; import "./table.css"; @@ -12,7 +12,7 @@ export function ManageSongs(state: StateHandler<{ songs: Song[]; primaryGenre: s .addColumn("Title", (song) => song.progress !== undefined ? Progress(song.progress) : InlineTextInput("text", "blur").addClass("low-level").sync(song, "title")) .addColumn("Artists", (song) => song.$artists.map((artists) => - Box(...artists.map(([name, url, _type]: Artist) => ProfilePicture(url ? Image(url, "A profile picture") : Label(""), name)), IconButton(MIcon("add"), "add")) + Box(...artists.map(([name, url, _type]: ArtistRef) => ProfilePicture(url ? Image(url, "A profile picture") : Label(""), name)), IconButton(MIcon("add"), "add")) .addClass("artists-list") .onClick(() => EditArtistsDialog(song).open()) ).asRefComponent()) diff --git a/pages/music/state.ts b/pages/music/state.ts index a45774a..0ba3e79 100644 --- a/pages/music/state.ts +++ b/pages/music/state.ts @@ -1,6 +1,6 @@ import { AdvancedImage, asState } from "webgen/mod.ts"; import { zod } from "webgen/zod.ts"; -import { Artist, Drop, Payout, Song } from "../../spec/music.ts"; +import { ArtistRef, Drop, Payout, Song } from "../../spec/music.ts"; export const state = asState({ published: "loading", @@ -16,7 +16,7 @@ export const creationState = asState({ title: undefined, release: undefined, language: undefined, - artists: [], + artists: [], primaryGenre: undefined, secondaryGenre: undefined, compositionCopyright: undefined, diff --git a/spec/music.ts b/spec/music.ts index 42ab0e5..5b9e7a3 100644 --- a/spec/music.ts +++ b/spec/music.ts @@ -43,17 +43,25 @@ export enum ReviewResponse { DeclineMaliciousActivity = "DECLINE_MALICIOUS_ACTIVITY", } -export const artist = zod.tuple([ - userString, - zod.string(), - zod.nativeEnum(ArtistTypes), -]); +export const artist = zod.object({ + _id: zod.string(), + name: userString, + users: zod.string().array(), + avatar: zod.string().optional(), +}); + +export const artistref = zod.object({ + _id: zod.string(), + type: zod.nativeEnum(ArtistTypes), +}); export const song = zod.object({ - id: zod.string(), + _id: zod.string(), + user: zod.string(), isrc: zod.string().optional(), title: userString, - artists: artist.array().refine((x) => x.some(([, , type]) => type == "PRIMARY"), { message: "At least one primary artist is required" }), + artists: artistref.array().refine((x) => x.some(({ type }) => type == "PRIMARY"), { message: "At least one primary artist is required" }), + primaryGenre: zod.string(), secondaryGenre: zod.string(), year: zod.number(), country: zod.string(), @@ -62,9 +70,7 @@ export const song = zod.object({ explicit: zod.boolean(), instrumental: zod.boolean(), file: zod.string({ required_error: "a Song is missing its file." }), - progress: zod.number().optional().transform((x) => undefined), -}) - .refine(({ instrumental, explicit }) => !(instrumental && explicit), "Can't have an explicit instrumental song"); +}); export const pureDrop = zod.object({ upc: zod.string().trim().max(0).nullable().or( @@ -78,7 +84,7 @@ export const pureDrop = zod.object({ }), ), title: userString, - artists: artist.array().refine((x) => x.some(([, , type]) => type == "PRIMARY"), { message: "At least one primary artist is required" }), + artists: artistref.array().refine((x) => x.some(({ type }) => type == "PRIMARY"), { message: "At least one primary artist is required" }), release: zod.string().regex(DATE_PATTERN, { message: "Not a date" }), language: zod.string(), primaryGenre: zod.string(), @@ -86,7 +92,7 @@ export const pureDrop = zod.object({ compositionCopyright: userString, soundRecordingCopyright: userString, artwork: zod.string(), - songs: song.array().min(1), + songs: zod.string().array().min(1), comments: userString.optional(), }); @@ -110,7 +116,7 @@ const pageOne = zod.object({ const pageTwo = zod.object({ title: userString, - artists: artist.array().refine((x) => x.some(([, , type]) => type == "PRIMARY"), { message: "At least one primary artist is required" }), + artists: artistref.array().refine((x) => x.some(({ type }) => type == "PRIMARY"), { message: "At least one primary artist is required" }), release: zod.string().regex(DATE_PATTERN, { message: "Not a date" }), language: zod.string(), primaryGenre: zod.string(), @@ -128,7 +134,7 @@ const pageFour = zod.object({ }); const pageFive = zod.object({ - songs: song.array().min(1, { message: "At least one song is required" }), + songs: song.array().min(1, { message: "At least one song is required" }).refine((songs) => songs.every(({ instrumental, explicit }) => !(instrumental && explicit)), "Can't have an explicit instrumental song"), uploadingSongs: zod.array(zod.string()).max(0, { message: "Some uploads are still in progress" }), }); @@ -613,6 +619,7 @@ export type RequestPayoutResponse = zod.infer; export type SidecarResponse = zod.infer; export type Addon = zod.infer; export type SidecarRequest = zod.infer; +export type ArtistRef = zod.infer; export type Artist = zod.infer; export type BugReport = zod.infer; export type Drop = zod.infer;