Skip to content

Commit

Permalink
more wizard changes
Browse files Browse the repository at this point in the history
  • Loading branch information
GregTCLTK committed Jan 12, 2024
1 parent 9f1a36c commit 9a4711d
Show file tree
Hide file tree
Showing 7 changed files with 233 additions and 185 deletions.
2 changes: 1 addition & 1 deletion deno.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"imports": {
"webgen/": "https://raw.githubusercontent.com/lucsoft/WebGen/a9f54f9/",
// "webgen/": "../WebGen/",
"std/": "https://deno.land/std@0.211.0/",
"std/": "https://deno.land/std@0.212.0/",
"shared/": "./pages/shared/"
},
"lock": false,
Expand Down
92 changes: 34 additions & 58 deletions pages/_legacy/helper.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// This code Will be ported to webgen

import { API, fileCache, Permission, stupidErrorAlert } from "shared/mod.ts";
import { Box, Button, Cache, Component, Custom, DropDownInput, Horizontal, Image, Label, SheetsStack, Spacer, State, StateHandler, Style, SupportedThemes, Table, TextInput, Vertical } from "webgen/mod.ts";
import { Box, Button, Cache, Component, Custom, DropDownInput, Horizontal, IconButton, Image, Label, MIcon, SheetDialog, SheetsStack, Spacer, State, StateHandler, Style, SupportedThemes, TextInput, Vertical } from "webgen/mod.ts";
import artwork from "../../assets/img/template-artwork.png";
import { loginRequired } from "../../components/pages.ts";
import { Artist, ArtistTypes, Drop } from "../../spec/music.ts";
import { Table2 } from "../hosting/views/table2.ts";
export const allowedAudioFormats = [ "audio/flac", "audio/wav", "audio/mp3" ];
export const allowedImageFormats = [ "image/png", "image/jpeg" ];

Expand Down Expand Up @@ -45,7 +46,7 @@ export function changeThemeColor(): ((data: SupportedThemes, options: Style) =>
return (_data) => { };// document.head.querySelector("meta[name=theme-color]")?.setAttribute("content", data == SupportedThemes.autoLight ? "#e6e6e6" : "#0a0a0a");
}

export function getSecondary(secondary: Record<string, string[]>, primaryGenre?: string): string[] | null {
export function getSecondary(secondary: Record<string, string[]>, primaryGenre?: string) {
return primaryGenre ? secondary[ primaryGenre ] : null;
}

Expand Down Expand Up @@ -213,57 +214,39 @@ export function saveBlob(blob: Blob, fileName: string) {
}

const ARTIST_ARRAY = <ArtistTypes[]>[ "PRIMARY", "FEATURING", "PRODUCER", "SONGWRITER" ];
export function EditArtists(list: Artist[]) {
const form = Page({
list
}, (state) => [
state.$list.map(() =>
Vertical(
Table([
[ "Type", "10rem", (artist, index) =>
DropDownInput("Type", ARTIST_ARRAY)
.setValue(artist[ 2 ])
.onChange(data => update(state, index, 2, data))
],
[ "Name", "auto", (artist, index) =>
TextInput("text", "Name", "blur")
.setValue(artist[ 0 ])
.onChange(data => update(state, index, 0, data!))
]
], state.list)
.setDelete((_, i) => {
state.list = state.list?.filter((_, index) => index != i) as typeof state.list;
}),
Horizontal(
Spacer(),
Button("Add Artist") // TODO: Remove this in the future => switch to ghost rows
.onClick(() => {
state.list = State([ ...state.list, [ "", "", ArtistTypes.Primary ] ] as [ string, string, ArtistTypes ][]);
})
).setPadding("0 0 3rem 0")
export const EditArtistsDialog = (state: StateHandler<{ artists: Artist[]; }>) => {
const dialog = SheetDialog(sheetStack, "Manage your Artists", Vertical(
new Table2(state.$artists)
.setColumnTemplate("10rem auto min-content")
.addColumn("Type", (artist: Artist) =>
DropDownInput("Type", ARTIST_ARRAY)
.setValue(artist[ 2 ])
.onChange(data => artist[ 2 ] = <ArtistTypes>data)
)
.setGap()
.setWidth("clamp(0rem, 100vw, 60vw)")
.setMargin("0 -.6rem 0 0")
).asRefComponent()
]);
return new Promise<Drop[ "artists" ]>((done) => {
const dialog = Dialog(() => Box(...form.getComponents()))
.setTitle("Manage your Artists")
.allowUserClose()
.addClass("light-mode")
.onClose(() => {
dialog.remove();
})
.addButton("Save", () => {
const data = form.getFormData();
done(data.list);
.addColumn("Name", (artist: Artist) =>
TextInput("text", "Name", "blur")
.setValue(artist[ 0 ])
.onChange(data => artist[ 0 ] = data ?? "")
)
//how to handle without index?
.addColumn("", () => IconButton(MIcon("delete"), "Delete").onClick(() => "remove")),
Horizontal(
Spacer(),
Button("Add Artist")
.onClick(() => state.artists = State([ ...state.artists, [ "", "", ArtistTypes.Primary ] ] as Artist[]))
).setPadding("0 0 3rem 0"),
Horizontal(
Spacer(),
Button("Save")
.onClick(() => dialog.close())
)
)
.setGap()
.setWidth("clamp(0rem, 100vw, 60vw)")
.setMargin("0 -.6rem 0 0"));
return dialog;
};

return "remove";
})
.open();
});
}
export function showPreviewImage(x: Drop) {
return x.artwork ? Cache(`image-preview-${x.artwork}`, () => Promise.resolve(),
type => type == "loaded"
Expand All @@ -281,13 +264,6 @@ export async function loadImage(x: Drop) {
return blob;
}

function update(state: StateHandler<{ list: [ name: string, img: string, type: ArtistTypes ][] | undefined; }>, index: number, key: number, value: string) {
if (!state.list)
state.list = [];
state.list[ index ][ key ] = value;
state.list = [ ...state.list ];
}

export function ProfilePicture(component: Component, name: string) {
const ele = component.draw();
ele.style.backgroundColor = stringToColor(name);
Expand Down
8 changes: 3 additions & 5 deletions pages/_legacy/music/changeDrop.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { API, stupidErrorAlert, uploadFilesDialog } from "shared/mod.ts";
import { AdvancedImage, Box, Button, DropAreaInput, DropDownInput, Grid, IconButton, Image, MIcon, Spacer, State, TextInput } from "webgen/mod.ts";
import { AdvancedImage, Box, Button, DropAreaInput, DropDownInput, Grid, IconButton, Image, MIcon, Spacer, TextInput } from "webgen/mod.ts";
import artwork from "../../../assets/img/template-artwork.png";
import genres from "../../../data/genres.json" with { type: "json" };
import language from "../../../data/language.json" with { type: "json" };
import { ArtistTypes, Drop } from "../../../spec/music.ts";
import { EditArtists, allowedImageFormats, getSecondary } from "../helper.ts";
import { EditArtistsDialog, allowedImageFormats, getSecondary } from "../helper.ts";
import { uploadArtwork } from "./data.ts";

export function ChangeDrop(drop: Drop) {
Expand Down Expand Up @@ -59,9 +59,7 @@ export function ChangeDrop(drop: Drop) {
// TODO: Make this a nicer component
Button("Artists")
.onClick(() => {
EditArtists(data.artists ?? [ [ "", "", ArtistTypes.Primary ] ]).then((x) => {
data.artists = State(x);
});
EditArtistsDialog(data.artists ?? [ [ "", "", ArtistTypes.Primary ] ]).open();
}),
],
[ { width: 2, height: 2 }, Spacer() ],
Expand Down
11 changes: 5 additions & 6 deletions pages/_legacy/music/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import { Artist, Song } from "../../../spec/music.ts";
export function uploadSongToDrop(state: StateHandler<{ uploadingSongs: string[]; songs: Song[]; artists: Artist[], language: string | undefined, primaryGenre: string | undefined, secondaryGenre: string | undefined, _id: string; }>, file: File) {
const uploadId = crypto.randomUUID();
state.uploadingSongs.push(uploadId);
if (!state.songs)
state.songs = State([]);

const cleanedUpTitle = file.name
.replaceAll("_", " ")
.replaceAll("-", " ")
Expand All @@ -35,13 +34,13 @@ export function uploadSongToDrop(state: StateHandler<{ uploadingSongs: string[];
state.uploadingSongs = <StateHandler<string[]>>state.uploadingSongs.filter(x => x != uploadId);
if (state.songs)
state.songs[ state.songs.findIndex(x => x.id == uploadId) ].progress = -1;
state.songs = State<Song[]>([ ...state.songs ?? [] ]);
state.songs = State<Song[]>([ ...state.songs ]);
alert("Your Upload has failed. Please try a different file or try again later");
},
uploadDone: () => {
if (state.songs)
state.songs[ state.songs.findIndex(x => x.id == uploadId) ].progress = 100;
state.songs = State<Song[]>([ ...state.songs ?? [] ]);
state.songs = State<Song[]>([ ...state.songs ]);
},
credentials: () => API.getToken(),
backendResponse: (id: string) => {
Expand All @@ -50,13 +49,13 @@ export function uploadSongToDrop(state: StateHandler<{ uploadingSongs: string[];
state.songs[ state.songs.findIndex(x => x.id == uploadId) ].file = id;
}
state.uploadingSongs = <StateHandler<string[]>>state.uploadingSongs.filter(x => x != uploadId);
state.songs = State<Song[]>([ ...state.songs ?? [] ]);
state.songs = State<Song[]>([ ...state.songs ]);
},
// deno-lint-ignore require-await
onUploadTick: async (percentage) => {
if (state.songs)
state.songs[ state.songs.findIndex(x => x.id == uploadId) ].progress = percentage;
state.songs = State<Song[]>([ ...state.songs ?? [] ]);
state.songs = State<Song[]>([ ...state.songs ]);
}
}, file);
}
Expand Down
126 changes: 42 additions & 84 deletions pages/_legacy/music/table.ts
Original file line number Diff line number Diff line change
@@ -1,89 +1,47 @@
import { Progress } from "shared/mod.ts";
import { Box, ButtonStyle, Checkbox, Color, Content, DropDownInput, IconButton, Image, InlineTextInput, Label, MIcon, State, StateHandler, Table } from "webgen/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 { Drop, Song } from "../../../spec/music.ts";
import { EditArtists, ProfilePicture, getSecondary, getYearList } from "../helper.ts";
import { Song } from "../../../spec/music.ts";
import { Table2 } from "../../hosting/views/table2.ts";
import { EditArtistsDialog, ProfilePicture, getSecondary, getYearList } from "../helper.ts";

export function ManageSongs(state: StateHandler<{ songs: Song[]; }>) {
const tableView = Content(
Table([
[ "Title", "auto", ({ progress, title }, index) => progress !== undefined ? Progress(progress) : InlineTextInput("text", "blur").addClass("low-level").setValue(title).onChange(x => update(state, index, "title", x)) ],
[ "Artists", "max-content", ({ artists }, index) =>
Box(
...artists.map(([ name, url, _type ]: string[]) =>
ProfilePicture(url ? Image(url, "A profile picture") : Label(""), name)
),
IconButton(MIcon("add"), "add")
)
.addClass("artists-list")
.onClick(() => {
EditArtists(artists ?? [ [ "", "", "PRIMARY" ] ]).then((x) => {
update(state, index, "artists", x?.map(x => x.map(x => x.trim())));
});
})
],
[ "Year", "max-content", ({ year }, index) =>
DropDownInput("Year", getYearList())
.setValue(year.toString())
.onChange((data) => update(state, index, "year", data ? parseInt(data) : undefined))
.setStyle(ButtonStyle.Inline)
.addClass("low-level")
],
[ "Country", "max-content", (row, index) =>
DropDownInput("Country", Object.keys(language))
.setRender((key) => language[ <keyof typeof language>key ])
.setValue(row.country)
.onChange((data) => update(state, index, "country", data))
.setStyle(ButtonStyle.Inline)
.addClass("low-level")
],
//TODO: Lock these components (greyed out), if only one song, since dependent on drop level values
[ "Primary Genre", "max-content", ({ primaryGenre }, index) =>
DropDownInput("Primary Genre", Object.keys(genres))
.setValue(primaryGenre)
.onChange((data) => {
update(state, index, "primaryGenre", data);
update(state, index, "secondaryGenre", undefined);
})
.setStyle(ButtonStyle.Inline)
.addClass("low-level")
],
[ "Secondary Genre", "max-content", ({ primaryGenre, secondaryGenre }, index) =>
DropDownInput("Secondary Genre", getSecondary(genres, primaryGenre) ?? [])
.setValue(secondaryGenre ? secondaryGenre : undefined)
.onChange((data) => update(state, index, "secondaryGenre", data))
.setStyle(ButtonStyle.Inline)
.addClass("low-level")
],
[ "Instrumental", "max-content", ({ instrumental, explicit }, index) =>
Checkbox(instrumental ?? false)
.setColor(explicit ? Color.Disabled : Color.Grayscaled)
.onClick((_, value) => update(state, index, "instrumental", !value))
.addClass("low-level")
],
[ "Explicit", "max-content", ({ explicit, instrumental }, index) =>
Checkbox(explicit ?? false)
.setColor(instrumental ? Color.Disabled : Color.Grayscaled)
.onClick((_, value) => update(state, index, "explicit", !value))
.addClass("low-level")
]
], state.songs ?? []).setDelete((_, i) => {
state.songs = state.songs?.filter((_, index) => index != i) as typeof state.songs;
}).addClass("inverted-class", "light-mode")
);
// state.$on("songs", () => {
// tableView.viewOptions().update({});
// });
return tableView.addClass("inverted-class");
}

// deno-lint-ignore no-explicit-any
function update(state: StateHandler<{ songs: Drop[ "songs" ]; }>, index: number, key: keyof NonNullable<Drop[ "songs" ]>[ 0 ], value: any) {
if (!state.songs)
state.songs = State([]);
// @ts-ignore errors due to any usage.
state.songs[ index ][ key ] = value;
// @ts-ignore errors due to any usage.
state.songs = State([ ...state.songs ]);
export function ManageSongs(state: StateHandler<{ songs: Song[]; primaryGenre: string; }>) {
return new Table2(state.$songs)
.setColumnTemplate("auto max-content max-content max-content max-content max-content max-content min-content")
.addColumn("Title", (song) => song.progress !== undefined ? Progress(song.progress) :
InlineTextInput("text", "blur").addClass("low-level").sync(song, "title"))
.addColumn("Artists", (song) => Box(
...song.artists.map(([ name, url, _type ]: string[]) =>
ProfilePicture(url ? Image(url, "A profile picture") : Label(""), name)
),
IconButton(MIcon("add"), "add")
)
.addClass("artists-list")
.onClick(() => EditArtistsDialog(song).open()))
.addColumn("Year", (song) => DropDownInput("Year", getYearList())
.setValue(song.year.toString())
.onChange(data => song.year = parseInt(data))
.setStyle(ButtonStyle.Inline)
.addClass("low-level"))
//TODO: create real country.json as soon as searchable dropdown is implemented
.addColumn("Country", (song) => DropDownInput("Country", Object.keys(language))
.setRender(key => language[ <keyof typeof language>key ])
.sync(song, "country")
.setStyle(ButtonStyle.Inline)
.addClass("low-level"))
.addColumn("Secondary Genre", (song) => DropDownInput("Secondary Genre", getSecondary(genres, state.primaryGenre) ?? [])
.sync(song, "secondaryGenre")
.setStyle(ButtonStyle.Inline)
.addClass("low-level"))
.addColumn("Instrumental", (song) => Checkbox(song.instrumental ?? false)
.setColor(song.explicit ? Color.Disabled : Color.Grayscaled)
.onClick((_, value) => song.instrumental = !value)
.addClass("low-level"))
.addColumn("Explicit", (song) => Checkbox(song.explicit ?? false)
.setColor(song.instrumental ? Color.Disabled : Color.Grayscaled)
.onClick((_, value) => song.explicit = !value)
.addClass("low-level"))
.addColumn("", (song) => IconButton(MIcon("delete"), "Delete").onClick(() => state.songs = state.songs.filter((x) => x.id != song.id) as typeof state.songs))
.addClass("inverted-class", "light-mode");
}
Loading

0 comments on commit 9a4711d

Please sign in to comment.