diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..0a4d4fc --- /dev/null +++ b/.prettierrc @@ -0,0 +1,10 @@ +{ + "printWidth": 80, + "singleQuote": false, + "trailingComma": "es5", + "bracketSpacing": true, + "jsxBracketSameLine": false, + "arrowParens": "avoid", + "tabWidth": 2, + "semi": true +} diff --git a/src/components/EditPlaylist/EditPlaylist.tsx b/src/components/EditPlaylist/EditPlaylist.tsx index c049418..d224dc2 100644 --- a/src/components/EditPlaylist/EditPlaylist.tsx +++ b/src/components/EditPlaylist/EditPlaylist.tsx @@ -43,11 +43,15 @@ import { setEditPlaylist, } from "../../state/features/videoSlice"; import ImageUploader from "../common/ImageUploader"; -import { QTUBE_PLAYLIST_BASE, QTUBE_VIDEO_BASE, categories, subCategories } from "../../constants"; +import { categories, subCategories } from "../../constants/Categories.ts"; import { Playlists } from "../Playlists/Playlists"; import { PlaylistListEdit } from "../PlaylistListEdit/PlaylistListEdit"; import { TextEditor } from "../common/TextEditor/TextEditor"; import { extractTextFromHTML } from "../common/TextEditor/utils"; +import { + QTUBE_PLAYLIST_BASE, + QTUBE_VIDEO_BASE, +} from "../../constants/Identifiers.ts"; const uid = new ShortUniqueId(); const shortuid = new ShortUniqueId({ length: 5 }); @@ -87,17 +91,17 @@ export const EditPlaylist = () => { const [selectedSubCategoryVideos, setSelectedSubCategoryVideos] = useState(null); - const isNew = useMemo(()=> { - return editVideoProperties?.mode === 'new' - }, [editVideoProperties]) + const isNew = useMemo(() => { + return editVideoProperties?.mode === "new"; + }, [editVideoProperties]); - useEffect(()=> { - if(isNew){ + useEffect(() => { + if (isNew) { setPlaylistData({ - videos: [] - }) + videos: [], + }); } - }, [isNew]) + }, [isNew]); // useEffect(() => { // if (editVideoProperties) { @@ -145,7 +149,7 @@ export const EditPlaylist = () => { // } // }, [editVideoProperties]); - const checkforPlaylist = React.useCallback(async (videoList) => { + const checkforPlaylist = React.useCallback(async videoList => { try { const combinedData: any = {}; const videos = []; @@ -174,21 +178,19 @@ export const EditPlaylist = () => { useEffect(() => { if (editVideoProperties) { setTitle(editVideoProperties?.title || ""); - - if(editVideoProperties?.htmlDescription){ - setDescription(editVideoProperties?.htmlDescription); - } else if(editVideoProperties?.description) { - const paragraph = `

${editVideoProperties?.description}

` + if (editVideoProperties?.htmlDescription) { + setDescription(editVideoProperties?.htmlDescription); + } else if (editVideoProperties?.description) { + const paragraph = `

${editVideoProperties?.description}

`; setDescription(paragraph); - } setCoverImage(editVideoProperties?.image || ""); setVideos(editVideoProperties?.videos || []); if (editVideoProperties?.category) { const selectedOption = categories.find( - (option) => option.id === +editVideoProperties.category + option => option.id === +editVideoProperties.category ); setSelectedCategoryVideos(selectedOption || null); } @@ -200,7 +202,7 @@ export const EditPlaylist = () => { ) { const selectedOption = subCategories[ +editVideoProperties?.category - ]?.find((option) => option.id === +editVideoProperties.subcategory); + ]?.find(option => option.id === +editVideoProperties.subcategory); setSelectedSubCategoryVideos(selectedOption || null); } @@ -211,24 +213,22 @@ export const EditPlaylist = () => { }, [editVideoProperties]); const onClose = () => { - setTitle("") - setDescription("") - setVideos([]) - setPlaylistData(null) - setSelectedCategoryVideos(null) - setSelectedSubCategoryVideos(null) - setCoverImage("") + setTitle(""); + setDescription(""); + setVideos([]); + setPlaylistData(null); + setSelectedCategoryVideos(null); + setSelectedSubCategoryVideos(null); + setCoverImage(""); dispatch(setEditPlaylist(null)); - }; async function publishQDNResource() { try { - - if(!title) throw new Error('Please enter a title') - if(!description) throw new Error('Please enter a description') - if(!coverImage) throw new Error('Please select cover image') - if(!selectedCategoryVideos) throw new Error('Please select a category') + if (!title) throw new Error("Please enter a title"); + if (!description) throw new Error("Please enter a description"); + if (!coverImage) throw new Error("Please select cover image"); + if (!selectedCategoryVideos) throw new Error("Please select a category"); if (!editVideoProperties) return; if (!userAddress) throw new Error("Unable to locate user address"); @@ -258,7 +258,7 @@ export const EditPlaylist = () => { const category = selectedCategoryVideos.id; const subcategory = selectedSubCategoryVideos?.id || ""; - const videoStructured = playlistData.videos.map((item) => { + const videoStructured = playlistData.videos.map(item => { const descriptionVid = item?.metadata?.description; if (!descriptionVid) throw new Error("cannot find video code"); @@ -286,13 +286,12 @@ export const EditPlaylist = () => { }); const id = uid(); - let commentsId = editVideoProperties?.id - - if(isNew){ - commentsId = `${QTUBE_PLAYLIST_BASE}_cm_${id}` - } - const stringDescription = extractTextFromHTML(description) + let commentsId = editVideoProperties?.id; + if (isNew) { + commentsId = `${QTUBE_PLAYLIST_BASE}_cm_${id}`; + } + const stringDescription = extractTextFromHTML(description); const playlistObject: any = { title, @@ -303,10 +302,13 @@ export const EditPlaylist = () => { videos: videoStructured, commentsId: commentsId, category, - subcategory + subcategory, }; - const codes = videoStructured.map((item) => `c:${item.code};`).slice(0,10).join(""); + const codes = videoStructured + .map(item => `c:${item.code};`) + .slice(0, 10) + .join(""); let metadescription = `**category:${category};subcategory:${subcategory};${codes}**` + stringDescription.slice(0, 120); @@ -314,15 +316,18 @@ export const EditPlaylist = () => { const crowdfundObjectToBase64 = await objectToBase64(playlistObject); // Description is obtained from raw data - let identifier = editVideoProperties?.id + let identifier = editVideoProperties?.id; const sanitizeTitle = title .replace(/[^a-zA-Z0-9\s-]/g, "") .replace(/\s+/g, "-") .replace(/-+/g, "-") .trim() .toLowerCase(); - if(isNew){ - identifier = `${QTUBE_PLAYLIST_BASE}${sanitizeTitle.slice(0, 30)}_${id}`; + if (isNew) { + identifier = `${QTUBE_PLAYLIST_BASE}${sanitizeTitle.slice( + 0, + 30 + )}_${id}`; } const requestBodyJson: any = { action: "PUBLISH_QDN_RESOURCE", @@ -336,21 +341,17 @@ export const EditPlaylist = () => { }; await qortalRequest(requestBodyJson); - if(isNew){ + if (isNew) { const objectToStore = { title: title.slice(0, 50), description: metadescription, id: identifier, service: "PLAYLIST", user: username, - ...playlistObject - } - dispatch( - updateVideo(objectToStore) - ); - dispatch( - updateInHashMap(objectToStore) - ); + ...playlistObject, + }; + dispatch(updateVideo(objectToStore)); + dispatch(updateInHashMap(objectToStore)); } else { dispatch( updateVideo({ @@ -365,7 +366,7 @@ export const EditPlaylist = () => { }) ); } - + dispatch( setNotification({ msg: "Playlist published", @@ -399,13 +400,11 @@ export const EditPlaylist = () => { } } - - const handleOptionCategoryChangeVideos = ( event: SelectChangeEvent ) => { const optionId = event.target.value; - const selectedOption = categories.find((option) => option.id === +optionId); + const selectedOption = categories.find(option => option.id === +optionId); setSelectedCategoryVideos(selectedOption || null); }; const handleOptionSubCategoryChangeVideos = ( @@ -414,19 +413,18 @@ export const EditPlaylist = () => { ) => { const optionId = event.target.value; const selectedOption = subcategories.find( - (option) => option.id === +optionId + option => option.id === +optionId ); setSelectedSubCategoryVideos(selectedOption || null); }; - - const removeVideo = (index) => { + const removeVideo = index => { const copyData = structuredClone(playlistData); copyData.videos.splice(index, 1); setPlaylistData(copyData); }; - const addVideo = (data) => { + const addVideo = data => { const copyData = structuredClone(playlistData); copyData.videos = [...copyData.videos, { ...data }]; setPlaylistData(copyData); @@ -449,10 +447,8 @@ export const EditPlaylist = () => { > {isNew ? ( Create new playlist - ) : ( - Update Playlist properties - + Update Playlist properties )} <> @@ -471,7 +467,7 @@ export const EditPlaylist = () => { value={selectedCategoryVideos?.id || ""} onChange={handleOptionCategoryChangeVideos} > - {categories.map((option) => ( + {categories.map(option => ( {option.name} @@ -486,20 +482,18 @@ export const EditPlaylist = () => { labelId="Sub-Category" input={} value={selectedSubCategoryVideos?.id || ""} - onChange={(e) => + onChange={e => handleOptionSubCategoryChangeVideos( e, subCategories[selectedCategoryVideos?.id] ) } > - {subCategories[selectedCategoryVideos.id].map( - (option) => ( - - {option.name} - - ) - )} + {subCategories[selectedCategoryVideos.id].map(option => ( + + {option.name} + + ))} )} @@ -533,9 +527,12 @@ export const EditPlaylist = () => { label="Title of playlist" variant="filled" value={title} - onChange={(e) => { + onChange={e => { const value = e.target.value; - const formattedValue = value.replace(/[^a-zA-Z0-9\s-_!?]/g, ""); + const formattedValue = value.replace( + /[^a-zA-Z0-9\s-_!?]/g, + "" + ); setTitle(formattedValue); }} inputProps={{ maxLength: 180 }} @@ -552,12 +549,19 @@ export const EditPlaylist = () => { maxRows={3} required /> */} - Description of playlist - { - setDescription(value) - }} /> + + Description of playlist + + { + setDescription(value); + }} + /> { useState(null); const [selectedSubCategoryVideos, setSelectedSubCategoryVideos] = useState(null); - const [imageExtracts, setImageExtracts] = useState([]) - + const [imageExtracts, setImageExtracts] = useState([]); const { getRootProps, getInputProps } = useDropzone({ accept: { @@ -111,7 +112,7 @@ export const EditVideo = () => { let errorString = null; rejectedFiles.forEach(({ file, errors }) => { - errors.forEach((error) => { + errors.forEach(error => { if (error.code === "file-too-large") { errorString = "File must be under 400mb"; } @@ -178,19 +179,17 @@ export const EditVideo = () => { useEffect(() => { if (editVideoProperties) { setTitle(editVideoProperties?.title || ""); - if(editVideoProperties?.htmlDescription){ + if (editVideoProperties?.htmlDescription) { setDescription(editVideoProperties?.htmlDescription); - - } else if(editVideoProperties?.fullDescription) { - const paragraph = `

${editVideoProperties?.fullDescription}

` + } else if (editVideoProperties?.fullDescription) { + const paragraph = `

${editVideoProperties?.fullDescription}

`; setDescription(paragraph); - } setCoverImage(editVideoProperties?.videoImage || ""); if (editVideoProperties?.category) { const selectedOption = categories.find( - (option) => option.id === +editVideoProperties.category + option => option.id === +editVideoProperties.category ); setSelectedCategoryVideos(selectedOption || null); } @@ -202,7 +201,7 @@ export const EditVideo = () => { ) { const selectedOption = subCategories[ +editVideoProperties?.category - ]?.find((option) => option.id === +editVideoProperties.subcategory); + ]?.find(option => option.id === +editVideoProperties.subcategory); setSelectedSubCategoryVideos(selectedOption || null); } } @@ -213,7 +212,7 @@ export const EditVideo = () => { setVideoPropertiesToSetToRedux(null); setFile(null); setTitle(""); - setImageExtracts([]) + setImageExtracts([]); setDescription(""); setCoverImage(""); }; @@ -253,7 +252,7 @@ export const EditVideo = () => { const category = selectedCategoryVideos.id; const subcategory = selectedSubCategoryVideos?.id || ""; - const fullDescription = extractTextFromHTML(description) + const fullDescription = extractTextFromHTML(description); let fileExtension = "mp4"; const fileExtensionSplit = file?.name?.split("."); if (fileExtensionSplit?.length > 1) { @@ -285,15 +284,13 @@ export const EditVideo = () => { subcategory, code: editVideoProperties.code, videoType: file?.type || "video/mp4", - filename: `${alphanumericString.trim()}.${fileExtension}` + filename: `${alphanumericString.trim()}.${fileExtension}`, }; let metadescription = `**category:${category};subcategory:${subcategory};code:${editVideoProperties.code}**` + description.slice(0, 150); - - const crowdfundObjectToBase64 = await objectToBase64(videoObject); // Description is obtained from raw data const requestBodyJson: any = { @@ -319,7 +316,7 @@ export const EditVideo = () => { description: metadescription, identifier: editVideoProperties.videoReference?.identifier, tag1: QTUBE_VIDEO_BASE, - filename: `${alphanumericString.trim()}.${fileExtension}` + filename: `${alphanumericString.trim()}.${fileExtension}`, }; listOfPublishes.push(requestBodyVideo); @@ -356,13 +353,11 @@ export const EditVideo = () => { } } - - const handleOptionCategoryChangeVideos = ( event: SelectChangeEvent ) => { const optionId = event.target.value; - const selectedOption = categories.find((option) => option.id === +optionId); + const selectedOption = categories.find(option => option.id === +optionId); setSelectedCategoryVideos(selectedOption || null); }; const handleOptionSubCategoryChangeVideos = ( @@ -371,48 +366,45 @@ export const EditVideo = () => { ) => { const optionId = event.target.value; const selectedOption = subcategories.find( - (option) => option.id === +optionId + option => option.id === +optionId ); setSelectedSubCategoryVideos(selectedOption || null); }; - const onFramesExtracted = async (imgs)=> { + const onFramesExtracted = async imgs => { try { - let imagesExtracts = [] - - for (const img of imgs){ + let imagesExtracts = []; + + for (const img of imgs) { try { - let compressedFile - const image = img - await new Promise((resolve) => { + let compressedFile; + const image = img; + await new Promise(resolve => { new Compressor(image, { - quality: .8, + quality: 0.8, maxWidth: 750, - mimeType: 'image/webp', + mimeType: "image/webp", success(result) { - const file = new File([result], 'name', { - type: 'image/webp' - }) - compressedFile = file - resolve() + const file = new File([result], "name", { + type: "image/webp", + }); + compressedFile = file; + resolve(); }, - error(err) {} - }) - }) - if (!compressedFile) continue - const base64Img = await toBase64(compressedFile) - imagesExtracts.push(base64Img) - + error(err) {}, + }); + }); + if (!compressedFile) continue; + const base64Img = await toBase64(compressedFile); + imagesExtracts.push(base64Img); } catch (error) { - console.error(error) + console.error(error); } } - setImageExtracts(imagesExtracts) - } catch (error) { - - } - } + setImageExtracts(imagesExtracts); + } catch (error) {} + }; return ( <> @@ -467,7 +459,7 @@ export const EditVideo = () => { value={selectedCategoryVideos?.id || ""} onChange={handleOptionCategoryChangeVideos} > - {categories.map((option) => ( + {categories.map(option => ( {option.name} @@ -482,26 +474,27 @@ export const EditVideo = () => { labelId="Sub-Category" input={} value={selectedSubCategoryVideos?.id || ""} - onChange={(e) => + onChange={e => handleOptionSubCategoryChangeVideos( e, subCategories[selectedCategoryVideos?.id] ) } > - {subCategories[selectedCategoryVideos.id].map( - (option) => ( - - {option.name} - - ) - )} + {subCategories[selectedCategoryVideos.id].map(option => ( + + {option.name} + + ))} )} {file && ( - onFramesExtracted(imgs)}/> + onFramesExtracted(imgs)} + /> )} {!coverImage ? ( @@ -532,23 +525,27 @@ export const EditVideo = () => { label="Title of video" variant="filled" value={title} - onChange={(e) => { + onChange={e => { const value = e.target.value; - const formattedValue = value.replace( - /[^a-zA-Z0-9\s-_!?]/g, - "" - ); + const formattedValue = value.replace(titleFormatter, ""); setTitle(formattedValue); }} inputProps={{ maxLength: 180 }} required /> - Description of video - { - setDescription(value) - }} /> + + Description of video + + { + setDescription(value); + }} + /> {/* { disabled={file && imageExtracts.length === 0} > {file && imageExtracts.length === 0 && ( - - )} + + )} Publish diff --git a/src/components/PlaylistListEdit/PlaylistListEdit.tsx b/src/components/PlaylistListEdit/PlaylistListEdit.tsx index ffae637..90fba1c 100644 --- a/src/components/PlaylistListEdit/PlaylistListEdit.tsx +++ b/src/components/PlaylistListEdit/PlaylistListEdit.tsx @@ -3,208 +3,208 @@ import { CardContentContainerComment } from "../common/Comments/Comments-styles" import { CrowdfundSubTitle, CrowdfundSubTitleRow, -} from "../UploadVideo/Upload-styles"; +} from "../PublishVideo/PublishVideo-styles.tsx"; import { Box, Button, Input, Typography, useTheme } from "@mui/material"; import { useNavigate } from "react-router-dom"; import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline"; import { removeVideo } from "../../state/features/videoSlice"; -import AddIcon from '@mui/icons-material/Add'; -import { QTUBE_VIDEO_BASE } from "../../constants"; +import AddIcon from "@mui/icons-material/Add"; import { useSelector } from "react-redux"; import { RootState } from "../../state/store"; +import { QTUBE_VIDEO_BASE } from "../../constants/Identifiers.ts"; export const PlaylistListEdit = ({ playlistData, removeVideo, addVideo }) => { const theme = useTheme(); const navigate = useNavigate(); const username = useSelector((state: RootState) => state.auth?.user?.name); - const [searchResults, setSearchResults] = useState([]) -const [filterSearch, setFilterSearch] = useState("") - const search = async()=> { - - const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&mode=ALL&identifier=${QTUBE_VIDEO_BASE}&title=${filterSearch}&limit=20&includemetadata=true&reverse=true&name=${username}&exactmatchnames=true&offset=0` + const [searchResults, setSearchResults] = useState([]); + const [filterSearch, setFilterSearch] = useState(""); + const search = async () => { + const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&mode=ALL&identifier=${QTUBE_VIDEO_BASE}&title=${filterSearch}&limit=20&includemetadata=true&reverse=true&name=${username}&exactmatchnames=true&offset=0`; const response = await fetch(url, { - method: 'GET', + method: "GET", headers: { - 'Content-Type': 'application/json' - } - }) - const responseDataSearchVid = await response.json() - setSearchResults(responseDataSearchVid) - } + "Content-Type": "application/json", + }, + }); + const responseDataSearchVid = await response.json(); + setSearchResults(responseDataSearchVid); + }; return ( - - - - Playlist - - - {playlistData?.videos?.map((vid, index) => { - return ( - - - {index + 1} - - + Playlist + + + {playlistData?.videos?.map((vid, index) => { + return ( + - {vid?.metadata?.title} - - { - removeVideo(index); - }} - sx={{ - cursor: "pointer", - }} - /> - - ); - })} - - - - - - Add videos to playlist - - + {index + 1} + + + {vid?.metadata?.title} + + { + removeVideo(index); + }} + sx={{ + cursor: "pointer", + }} + /> + + ); + })} + + + - - { - setFilterSearch(e.target.value); - }} - value={filterSearch} - placeholder="Search by title" + + Add videos to playlist + + + - - - - {searchResults?.map((vid, index) => { - return ( - { + setFilterSearch(e.target.value); + }} + value={filterSearch} + placeholder="Search by title" sx={{ - display: "flex", - gap: "10px", - width: "100%", - alignItems: "center", - padding: "10px", - borderRadius: "5px", - userSelect: "none", + borderBottom: "1px solid white", + "&&:before": { + borderBottom: "none", + }, + "&&:after": { + borderBottom: "none", + }, + "&&:hover:before": { + borderBottom: "none", + }, + "&&.Mui-focused:before": { + borderBottom: "none", + }, + "&&.Mui-focused": { + outline: "none", + }, + fontSize: "18px", }} + /> +