From 6320f76f3bc2678f7cee8d372e706b6c449673ba Mon Sep 17 00:00:00 2001 From: srgooglo Date: Thu, 29 Sep 2022 12:31:14 +0200 Subject: [PATCH] added `Playlist Creator` --- .../Creator/creators/playlist/index.jsx | 285 +++++++++++++++++- .../Creator/creators/playlist/index.less | 120 +++++++- 2 files changed, 402 insertions(+), 3 deletions(-) diff --git a/packages/app/src/components/Creator/creators/playlist/index.jsx b/packages/app/src/components/Creator/creators/playlist/index.jsx index 9ccd2535..836998aa 100644 --- a/packages/app/src/components/Creator/creators/playlist/index.jsx +++ b/packages/app/src/components/Creator/creators/playlist/index.jsx @@ -1,12 +1,293 @@ import React from "react" import * as antd from "antd" -import { Icons, createIconRender } from "components/Icons" +import { Icons } from "components/Icons" import "./index.less" +const UploadHint = (props) => { + return
+ +

Upload your tracks

+

Drag and drop your tracks here or click this box to start uploading files.

+
+} + +// TODO: Handle `cntr+v` to paste data from the clipboard to the post additions +// TODO: Send file deletion request to the server when user removes file from the list +// TODO: Make cover preview style more beautiful (E.G. Use the entire div as background) +// TODO: Make files list item can be dragged to change their order +// TODO: Make files can be modified (E.G. Change cover, change title, change artist, etc.) + export default (props) => { + const api = app.api.withEndpoints("main") + + const [playlistName, setPlaylistName] = React.useState(null) + const [playlistDescription, setPlaylistDescription] = React.useState(null) + const [playlistArtist, setPlaylistArtist] = React.useState(null) + const [coverURL, setCoverURL] = React.useState(null) + const [fileList, setFileList] = React.useState([]) + + const [pending, setPending] = React.useState([]) + const [loading, setLoading] = React.useState(false) + + const handleTitleOnChange = (event) => { + const value = event.target.value + + if (value === "") { + return setPlaylistName(null) + } + + return setPlaylistName(event.target.value) + } + + const handleDescriptionOnChange = (event) => { + const value = event.target.value + + if (value === "") { + return setPlaylistDescription(null) + } + + return setPlaylistDescription(event.target.value) + } + + const handleArtistOnChange = (event) => { + const value = event.target.value + + if (value === "") { + return setPlaylistArtist(null) + } + + return setPlaylistArtist(event.target.value) + } + + const handleUploaderOnChange = (change) => { + switch (change.file.status) { + case "uploading": { + setPending([...pending, change.file.uid]) + break + } + case "done": { + const recivedFiles = [] + + // remove pending file + setPending(pending.filter(uid => uid !== change.file.uid)) + + // push to file list + if (Array.isArray(change.file.response)) { + recivedFiles.push(...change.file.response) + } else { + recivedFiles.push(change.file.response) + } + + // add uid to files + recivedFiles.forEach((file) => { + file.uid = change.file.uid + }) + + setFileList([...fileList, ...recivedFiles]) + + break + } + case "removed": { + // remove from file list + setFileList(fileList.filter(file => file.uid !== change.file.uid)) + } + + default: { + break + } + } + } + + const handleCoverUploaderOnChange = (change) => { + switch (change.file.status) { + case "uploading": { + setPending([...pending, change.file.uid]) + break + } + case "done": { + // remove pending file + setPending(pending.filter(uid => uid !== change.file.uid)) + + setCoverURL(change.file.response[0].url) + + break + } + case "removed": { + setCoverURL(null) + } + + default: { + break + } + } + } + + const handleUpload = async (req) => { + // get file data + const file = req.file + + // append to form data + const formData = new FormData() + formData.append("files", file) + + // send request + const request = await api.post.upload(formData, undefined).catch((error) => { + console.error(error) + antd.message.error(error) + req.onError(error) + + return false + }) + + if (request) { + return req.onSuccess(request) + } + } + + const checkCanSubmit = () => { + const nameValid = playlistName !== null && playlistName.length !== 0 + const filesListValid = fileList.length !== 0 + const isPending = pending.length !== 0 + + return nameValid && filesListValid && !isPending + } + + const handleSubmit = async () => { + setLoading(true) + + let RequestData = { + type: "playlist", + message: playlistDescription, + data: { + title: playlistName, + cover: coverURL, + artist: playlistArtist, + playlist: fileList.map((file) => { + return { + title: file.name, + cover: file.cover ?? coverURL, + artist: file.artist ?? "Unknown", + src: file.url, + } + }) + } + } + + const response = api.post.post(RequestData).catch(error => { + console.error(error) + antd.message.error(error) + + return false + }) + + setLoading(false) + + if (response) { + if (typeof props.close === "function") { + props.close() + } + } + } + return
- +
+
+ + +
+
+ + +
+
+ + +
+
+ + { + coverURL &&
+ cover + { + setCoverURL(null) + }} + icon={} + shape="round" + > + Remove Cover + +
+ } + { + !coverURL && + }>Upload cover + + } +
+ +
+ + {fileList.length === 0 ? : }> + Upload files + } + +
+ +
+ } + loading={loading} + onClick={handleSubmit} + > + Publish + +
+ +
+

+ Uploading files that are not permitted by our app.setLocation("/terms")}>Terms of Service may result in your account being suspended. +

+
+
} \ No newline at end of file diff --git a/packages/app/src/components/Creator/creators/playlist/index.less b/packages/app/src/components/Creator/creators/playlist/index.less index d061c844..240d0574 100644 --- a/packages/app/src/components/Creator/creators/playlist/index.less +++ b/packages/app/src/components/Creator/creators/playlist/index.less @@ -1,3 +1,121 @@ .playlistCreator { - + display: flex; + flex-direction: column; + + align-items: center; + justify-content: center; + + width: 100%; + + .inputField { + display: inline-flex; + flex-direction: row; + + align-self: start; + align-items: center; + justify-content: flex-start; + + width: 100%; + + margin-bottom: 20px; + + font-size: 2rem; + + .inputText { + width: 100%; + } + + .coverUploader { + width: 100px; + } + + .coverPreview { + height: 5vh; + + img { + height: 100%; + border-radius: 10px; + margin-right: 10px; + } + + svg { + margin: 0!important; + } + } + } + + .files { + display: flex; + flex-direction: column; + + align-items: center; + justify-content: center; + + border: 1px solid var(--border-color); + border-radius: 8px; + + width: 100%; + height: 100%; + + padding: 10px; + margin-bottom: 20px; + + .uploader, + .ant-upload { + display: flex; + flex-direction: column; + + align-items: center; + justify-content: center; + + width: 100%; + } + + .ant-upload-list, + .ant-upload-list-picture-container { + width: 100%; + } + + .ant-upload-list-item-thumbnail { + display: inline-flex; + flex-direction: row; + align-items: center; + justify-content: center; + } + + .ant-upload-list-item { + display: inline-flex; + flex-direction: row; + + align-items: center; + justify-content: space-between; + + width: 100%; + } + } + + .uploadHint { + display: flex; + flex-direction: column; + + align-self: center; + align-items: center; + justify-content: center; + + width: 100%; + height: 100%; + + svg { + font-size: 3rem; + } + + h3 { + font-size: 1.5rem; + } + } + + .footer { + position: relative; + padding: 10px; + } } \ No newline at end of file