First Commit
Q-Support is forked from Q-Share and has the following changes from it: Changed Q-Share Categories and Identifiers to Q-Support Categories and Identifiers. Theme updated with main colors being the same as Qortal logo. Added Support Icon StatsData component only displays if published posts Full Publish form shown before choosing file User doesn't input Issue State Category in Publish Form because it is always open by default Publishing File is Optional in publish form User can add multiple images in PublishFile.tsx
854
package-lock.json
generated
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "qtube",
|
"name": "qsupport",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.0",
|
"version": "1.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@ -43,6 +43,6 @@
|
|||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"eslint-plugin-react-refresh": "^0.3.4",
|
"eslint-plugin-react-refresh": "^0.3.4",
|
||||||
"typescript": "^5.0.2",
|
"typescript": "^5.0.2",
|
||||||
"vite": "^4.3.2"
|
"vite": "6.0.0-alpha.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Routes, Route } from "react-router-dom";
|
import { Route, Routes } from "react-router-dom";
|
||||||
import { ThemeProvider } from "@mui/material/styles";
|
import { ThemeProvider } from "@mui/material/styles";
|
||||||
import { CssBaseline } from "@mui/material";
|
import { CssBaseline } from "@mui/material";
|
||||||
import { lightTheme, darkTheme } from "./styles/theme";
|
import { darkTheme, lightTheme } from "./styles/theme";
|
||||||
import { store } from "./state/store";
|
import { store } from "./state/store";
|
||||||
import { Provider } from "react-redux";
|
import { Provider } from "react-redux";
|
||||||
import GlobalWrapper from "./wrappers/GlobalWrapper";
|
import GlobalWrapper from "./wrappers/GlobalWrapper";
|
||||||
import Notification from "./components/common/Notification/Notification";
|
import Notification from "./components/common/Notification/Notification";
|
||||||
import { Home } from "./pages/Home/Home";
|
import { Home } from "./pages/Home/Home";
|
||||||
import { FileContent } from "./pages/FileContent/FileContent.tsx";
|
import { IssueContent } from "./pages/IssueContent/IssueContent.tsx";
|
||||||
import DownloadWrapper from "./wrappers/DownloadWrapper";
|
import DownloadWrapper from "./wrappers/DownloadWrapper";
|
||||||
import { IndividualProfile } from "./pages/IndividualProfile/IndividualProfile";
|
import { IndividualProfile } from "./pages/IndividualProfile/IndividualProfile";
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ function App() {
|
|||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<Home />} />
|
<Route path="/" element={<Home />} />
|
||||||
<Route path="/share/:name/:id" element={<FileContent />} />
|
<Route path="/share/:name/:id" element={<IssueContent />} />
|
||||||
<Route path="/channel/:name" element={<IndividualProfile />} />
|
<Route path="/channel/:name" element={<IndividualProfile />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</GlobalWrapper>
|
</GlobalWrapper>
|
||||||
|
BIN
src/assets/icons/ClosedIcon.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/icons/CompleteIcon.png
Normal file
After Width: | Height: | Size: 132 KiB |
BIN
src/assets/icons/InProgressIcon.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
BIN
src/assets/icons/OpenIcon.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
src/assets/img/Q-SupportIcon.webp
Normal file
After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 13 KiB |
@ -21,7 +21,7 @@ import {
|
|||||||
updateFile,
|
updateFile,
|
||||||
updateInHashMap,
|
updateInHashMap,
|
||||||
} from "../../state/features/fileSlice.ts";
|
} from "../../state/features/fileSlice.ts";
|
||||||
import { QSHARE_FILE_BASE } from "../../constants/Identifiers.ts";
|
import { QSUPPORT_FILE_BASE } from "../../constants/Identifiers.ts";
|
||||||
import { MultiplePublish } from "../common/MultiplePublish/MultiplePublishAll";
|
import { MultiplePublish } from "../common/MultiplePublish/MultiplePublishAll";
|
||||||
import { TextEditor } from "../common/TextEditor/TextEditor";
|
import { TextEditor } from "../common/TextEditor/TextEditor";
|
||||||
import { extractTextFromHTML } from "../common/TextEditor/utils";
|
import { extractTextFromHTML } from "../common/TextEditor/utils";
|
||||||
@ -32,6 +32,10 @@ import {
|
|||||||
CategoryListRef,
|
CategoryListRef,
|
||||||
getCategoriesFromObject,
|
getCategoriesFromObject,
|
||||||
} from "../common/CategoryList/CategoryList.tsx";
|
} from "../common/CategoryList/CategoryList.tsx";
|
||||||
|
import {
|
||||||
|
ImagePublisher,
|
||||||
|
ImagePublisherRef,
|
||||||
|
} from "../common/ImagePublisher/ImagePublisher.tsx";
|
||||||
|
|
||||||
const uid = new ShortUniqueId();
|
const uid = new ShortUniqueId();
|
||||||
const shortuid = new ShortUniqueId({ length: 5 });
|
const shortuid = new ShortUniqueId({ length: 5 });
|
||||||
@ -53,7 +57,7 @@ interface VideoFile {
|
|||||||
identifier?: string;
|
identifier?: string;
|
||||||
filename?: string;
|
filename?: string;
|
||||||
}
|
}
|
||||||
export const EditFile = () => {
|
export const EditIssue = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const username = useSelector((state: RootState) => state.auth?.user?.name);
|
const username = useSelector((state: RootState) => state.auth?.user?.name);
|
||||||
@ -75,6 +79,7 @@ export const EditFile = () => {
|
|||||||
const [files, setFiles] = useState<VideoFile[]>([]);
|
const [files, setFiles] = useState<VideoFile[]>([]);
|
||||||
const [editCategories, setEditCategories] = useState<string[]>([]);
|
const [editCategories, setEditCategories] = useState<string[]>([]);
|
||||||
const categoryListRef = useRef<CategoryListRef>(null);
|
const categoryListRef = useRef<CategoryListRef>(null);
|
||||||
|
const imagePublisherRef = useRef<ImagePublisherRef>(null);
|
||||||
|
|
||||||
const { getRootProps, getInputProps } = useDropzone({
|
const { getRootProps, getInputProps } = useDropzone({
|
||||||
maxFiles: 10,
|
maxFiles: 10,
|
||||||
@ -121,7 +126,10 @@ export const EditFile = () => {
|
|||||||
const paragraph = `<p>${editFileProperties?.fullDescription}</p>`;
|
const paragraph = `<p>${editFileProperties?.fullDescription}</p>`;
|
||||||
setDescription(paragraph);
|
setDescription(paragraph);
|
||||||
}
|
}
|
||||||
setEditCategories(getCategoriesFromObject(editFileProperties));
|
|
||||||
|
const categoriesFromEditFile =
|
||||||
|
getCategoriesFromObject(editFileProperties);
|
||||||
|
setEditCategories(categoriesFromEditFile);
|
||||||
}
|
}
|
||||||
}, [editFileProperties]);
|
}, [editFileProperties]);
|
||||||
const onClose = () => {
|
const onClose = () => {
|
||||||
@ -141,7 +149,6 @@ export const EditFile = () => {
|
|||||||
if (!categoryList[0]) throw new Error("Please select a category");
|
if (!categoryList[0]) throw new Error("Please select a category");
|
||||||
if (!editFileProperties) return;
|
if (!editFileProperties) return;
|
||||||
if (!userAddress) throw new Error("Unable to locate user address");
|
if (!userAddress) throw new Error("Unable to locate user address");
|
||||||
if (files.length === 0) throw new Error("Add at least one file");
|
|
||||||
|
|
||||||
let errorMsg = "";
|
let errorMsg = "";
|
||||||
let name = "";
|
let name = "";
|
||||||
@ -186,7 +193,7 @@ export const EditFile = () => {
|
|||||||
const file = publish.file;
|
const file = publish.file;
|
||||||
const id = uid();
|
const id = uid();
|
||||||
|
|
||||||
const identifier = `${QSHARE_FILE_BASE}${sanitizeTitle.slice(0, 30)}_${id}`;
|
const identifier = `${QSUPPORT_FILE_BASE}${sanitizeTitle.slice(0, 30)}_${id}`;
|
||||||
|
|
||||||
let fileExtension = "";
|
let fileExtension = "";
|
||||||
const fileExtensionSplit = file?.name?.split(".");
|
const fileExtensionSplit = file?.name?.split(".");
|
||||||
@ -227,7 +234,7 @@ export const EditFile = () => {
|
|||||||
description: metadescription,
|
description: metadescription,
|
||||||
identifier,
|
identifier,
|
||||||
filename,
|
filename,
|
||||||
tag1: QSHARE_FILE_BASE,
|
tag1: QSUPPORT_FILE_BASE,
|
||||||
};
|
};
|
||||||
listOfPublishes.push(requestBodyVideo);
|
listOfPublishes.push(requestBodyVideo);
|
||||||
fileReferences.push({
|
fileReferences.push({
|
||||||
@ -248,24 +255,25 @@ export const EditFile = () => {
|
|||||||
commentsId: editFileProperties.commentsId,
|
commentsId: editFileProperties.commentsId,
|
||||||
...categoryListRef.current?.categoriesToObject(),
|
...categoryListRef.current?.categoriesToObject(),
|
||||||
files: fileReferences,
|
files: fileReferences,
|
||||||
|
images: imagePublisherRef?.current?.getImageArray(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let metadescription =
|
let metadescription =
|
||||||
`**${categoryListRef.current?.getCategoriesFetchString()}**` +
|
`**${categoryListRef.current?.getCategoriesFetchString()}**` +
|
||||||
fullDescription.slice(0, 150);
|
fullDescription.slice(0, 150);
|
||||||
|
|
||||||
const crowdfundObjectToBase64 = await objectToBase64(fileObject);
|
const fileObjectToBase64 = await objectToBase64(fileObject);
|
||||||
// Description is obtained from raw data
|
// Description is obtained from raw data
|
||||||
|
|
||||||
const requestBodyJson: any = {
|
const requestBodyJson: any = {
|
||||||
action: "PUBLISH_QDN_RESOURCE",
|
action: "PUBLISH_QDN_RESOURCE",
|
||||||
name: name,
|
name: name,
|
||||||
service: "DOCUMENT",
|
service: "DOCUMENT",
|
||||||
data64: crowdfundObjectToBase64,
|
data64: fileObjectToBase64,
|
||||||
title: title.slice(0, 50),
|
title: title.slice(0, 50),
|
||||||
description: metadescription,
|
description: metadescription,
|
||||||
identifier: editFileProperties.id,
|
identifier: editFileProperties.id,
|
||||||
tag1: QSHARE_FILE_BASE,
|
tag1: QSUPPORT_FILE_BASE,
|
||||||
filename: `video_metadata.json`,
|
filename: `video_metadata.json`,
|
||||||
};
|
};
|
||||||
listOfPublishes.push(requestBodyJson);
|
listOfPublishes.push(requestBodyJson);
|
||||||
@ -336,7 +344,7 @@ export const EditFile = () => {
|
|||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<NewCrowdfundTitle>Update share</NewCrowdfundTitle>
|
<NewCrowdfundTitle>Update Issue</NewCrowdfundTitle>
|
||||||
</Box>
|
</Box>
|
||||||
<>
|
<>
|
||||||
<Box
|
<Box
|
||||||
@ -390,56 +398,52 @@ export const EditFile = () => {
|
|||||||
alignItems: "flex-start",
|
alignItems: "flex-start",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{files?.length > 0 && (
|
<Box
|
||||||
<>
|
sx={{
|
||||||
<Box
|
display: "flex",
|
||||||
sx={{
|
flexDirection: "column",
|
||||||
display: "flex",
|
gap: "20px",
|
||||||
flexDirection: "column",
|
width: "100%",
|
||||||
gap: "20px",
|
}}
|
||||||
width: "100%",
|
>
|
||||||
}}
|
<CategoryList
|
||||||
>
|
categoryData={allCategoryData}
|
||||||
<CategoryList
|
initialCategories={editCategories}
|
||||||
categoryData={allCategoryData}
|
columns={3}
|
||||||
initialCategories={editCategories}
|
ref={categoryListRef}
|
||||||
columns={3}
|
/>
|
||||||
ref={categoryListRef}
|
</Box>
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Box>
|
</Box>
|
||||||
{files?.length > 0 && (
|
<ImagePublisher
|
||||||
<>
|
ref={imagePublisherRef}
|
||||||
<CustomInputField
|
initialImages={editFileProperties?.images}
|
||||||
name="title"
|
/>
|
||||||
label="Title of share"
|
<CustomInputField
|
||||||
variant="filled"
|
name="title"
|
||||||
value={title}
|
label="Title of Issue"
|
||||||
onChange={e => {
|
variant="filled"
|
||||||
const value = e.target.value;
|
value={title}
|
||||||
const formattedValue = value.replace(titleFormatter, "");
|
onChange={e => {
|
||||||
setTitle(formattedValue);
|
const value = e.target.value;
|
||||||
}}
|
const formattedValue = value.replace(titleFormatter, "");
|
||||||
inputProps={{ maxLength: 180 }}
|
setTitle(formattedValue);
|
||||||
required
|
}}
|
||||||
/>
|
inputProps={{ maxLength: 180 }}
|
||||||
<Typography
|
required
|
||||||
sx={{
|
/>
|
||||||
fontSize: "18px",
|
<Typography
|
||||||
}}
|
sx={{
|
||||||
>
|
fontSize: "18px",
|
||||||
Description of share
|
}}
|
||||||
</Typography>
|
>
|
||||||
<TextEditor
|
Description of Issue
|
||||||
inlineContent={description}
|
</Typography>
|
||||||
setInlineContent={value => {
|
<TextEditor
|
||||||
setDescription(value);
|
inlineContent={description}
|
||||||
}}
|
setInlineContent={value => {
|
||||||
/>
|
setDescription(value);
|
||||||
</>
|
}}
|
||||||
)}
|
/>
|
||||||
</>
|
</>
|
||||||
|
|
||||||
<CrowdfundActionButtonRow>
|
<CrowdfundActionButtonRow>
|
@ -6,11 +6,9 @@ import {
|
|||||||
CrowdfundActionButton,
|
CrowdfundActionButton,
|
||||||
CrowdfundActionButtonRow,
|
CrowdfundActionButtonRow,
|
||||||
CustomInputField,
|
CustomInputField,
|
||||||
CustomSelect,
|
|
||||||
LogoPreviewRow,
|
LogoPreviewRow,
|
||||||
ModalBody,
|
ModalBody,
|
||||||
NewCrowdfundTitle,
|
NewCrowdfundTitle,
|
||||||
StyledButton,
|
|
||||||
TimesIcon,
|
TimesIcon,
|
||||||
} from "./Upload-styles.tsx";
|
} from "./Upload-styles.tsx";
|
||||||
import {
|
import {
|
||||||
@ -27,27 +25,20 @@ import {
|
|||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import ShortUniqueId from "short-unique-id";
|
import ShortUniqueId from "short-unique-id";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import AddBoxIcon from "@mui/icons-material/AddBox";
|
|
||||||
import { useDropzone } from "react-dropzone";
|
|
||||||
|
|
||||||
import { setNotification } from "../../state/features/notificationsSlice";
|
import { setNotification } from "../../state/features/notificationsSlice";
|
||||||
import { objectToBase64, uint8ArrayToBase64 } from "../../utils/toBase64";
|
import { objectToBase64 } from "../../utils/toBase64";
|
||||||
import { RootState } from "../../state/store";
|
import { RootState } from "../../state/store";
|
||||||
import {
|
import {
|
||||||
upsertFilesBeginning,
|
setEditPlaylist,
|
||||||
addToHashMap,
|
|
||||||
upsertFiles,
|
|
||||||
setEditFile,
|
|
||||||
updateFile,
|
updateFile,
|
||||||
updateInHashMap,
|
updateInHashMap,
|
||||||
setEditPlaylist,
|
|
||||||
} from "../../state/features/fileSlice.ts";
|
} from "../../state/features/fileSlice.ts";
|
||||||
import ImageUploader from "../common/ImageUploader";
|
import ImageUploader from "../common/ImagePublisher/ImageUploader.tsx";
|
||||||
import {
|
import {
|
||||||
QSHARE_PLAYLIST_BASE,
|
QSUPPORT_FILE_BASE,
|
||||||
QSHARE_FILE_BASE,
|
QSUPPORT_PLAYLIST_BASE,
|
||||||
} from "../../constants/Identifiers.ts";
|
} from "../../constants/Identifiers.ts";
|
||||||
import { Playlists } from "../Playlists/Playlists";
|
|
||||||
import { PlaylistListEdit } from "../PlaylistListEdit/PlaylistListEdit";
|
import { PlaylistListEdit } from "../PlaylistListEdit/PlaylistListEdit";
|
||||||
import { TextEditor } from "../common/TextEditor/TextEditor";
|
import { TextEditor } from "../common/TextEditor/TextEditor";
|
||||||
import { extractTextFromHTML } from "../common/TextEditor/utils";
|
import { extractTextFromHTML } from "../common/TextEditor/utils";
|
||||||
@ -87,7 +78,7 @@ export const EditPlaylist = () => {
|
|||||||
const [playlistData, setPlaylistData] = useState<any>(null);
|
const [playlistData, setPlaylistData] = useState<any>(null);
|
||||||
const [title, setTitle] = useState<string>("");
|
const [title, setTitle] = useState<string>("");
|
||||||
const [description, setDescription] = useState<string>("");
|
const [description, setDescription] = useState<string>("");
|
||||||
const [coverImage, setCoverImage] = useState<string>("");
|
const [coverImage, setCoverImage] = useState<string[]>([]);
|
||||||
const [videos, setVideos] = useState([]);
|
const [videos, setVideos] = useState([]);
|
||||||
const [selectedCategoryVideos, setSelectedCategoryVideos] =
|
const [selectedCategoryVideos, setSelectedCategoryVideos] =
|
||||||
useState<any>(null);
|
useState<any>(null);
|
||||||
@ -222,7 +213,7 @@ export const EditPlaylist = () => {
|
|||||||
setPlaylistData(null);
|
setPlaylistData(null);
|
||||||
setSelectedCategoryVideos(null);
|
setSelectedCategoryVideos(null);
|
||||||
setSelectedSubCategoryVideos(null);
|
setSelectedSubCategoryVideos(null);
|
||||||
setCoverImage("");
|
setCoverImage([]);
|
||||||
dispatch(setEditPlaylist(null));
|
dispatch(setEditPlaylist(null));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -292,7 +283,7 @@ export const EditPlaylist = () => {
|
|||||||
let commentsId = editVideoProperties?.id;
|
let commentsId = editVideoProperties?.id;
|
||||||
|
|
||||||
if (isNew) {
|
if (isNew) {
|
||||||
commentsId = `${QSHARE_PLAYLIST_BASE}_cm_${id}`;
|
commentsId = `${QSUPPORT_PLAYLIST_BASE}_cm_${id}`;
|
||||||
}
|
}
|
||||||
const stringDescription = extractTextFromHTML(description);
|
const stringDescription = extractTextFromHTML(description);
|
||||||
|
|
||||||
@ -324,7 +315,7 @@ export const EditPlaylist = () => {
|
|||||||
.trim()
|
.trim()
|
||||||
.toLowerCase();
|
.toLowerCase();
|
||||||
if (isNew) {
|
if (isNew) {
|
||||||
identifier = `${QSHARE_PLAYLIST_BASE}${sanitizeTitle.slice(0, 30)}_${id}`;
|
identifier = `${QSUPPORT_PLAYLIST_BASE}${sanitizeTitle.slice(0, 30)}_${id}`;
|
||||||
}
|
}
|
||||||
const requestBodyJson: any = {
|
const requestBodyJson: any = {
|
||||||
action: "PUBLISH_QDN_RESOURCE",
|
action: "PUBLISH_QDN_RESOURCE",
|
||||||
@ -334,7 +325,7 @@ export const EditPlaylist = () => {
|
|||||||
title: title.slice(0, 50),
|
title: title.slice(0, 50),
|
||||||
description: metadescription,
|
description: metadescription,
|
||||||
identifier: identifier,
|
identifier: identifier,
|
||||||
tag1: QSHARE_FILE_BASE,
|
tag1: QSUPPORT_FILE_BASE,
|
||||||
};
|
};
|
||||||
|
|
||||||
await qortalRequest(requestBodyJson);
|
await qortalRequest(requestBodyJson);
|
||||||
@ -519,7 +510,7 @@ export const EditPlaylist = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{!coverImage ? (
|
{!coverImage ? (
|
||||||
<ImageUploader onPick={(img: string) => setCoverImage(img)}>
|
<ImageUploader onPick={(img: string[]) => setCoverImage(img)}>
|
||||||
<AddCoverImageButton variant="contained">
|
<AddCoverImageButton variant="contained">
|
||||||
Add Cover Image
|
Add Cover Image
|
||||||
<AddLogoIcon
|
<AddLogoIcon
|
||||||
@ -532,10 +523,15 @@ export const EditPlaylist = () => {
|
|||||||
</ImageUploader>
|
</ImageUploader>
|
||||||
) : (
|
) : (
|
||||||
<LogoPreviewRow>
|
<LogoPreviewRow>
|
||||||
<CoverImagePreview src={coverImage} alt="logo" />
|
{coverImage.map(
|
||||||
|
image =>
|
||||||
|
image && (
|
||||||
|
<CoverImagePreview src={image} alt="logo" key={image} />
|
||||||
|
)
|
||||||
|
)}
|
||||||
<TimesIcon
|
<TimesIcon
|
||||||
color={theme.palette.text.primary}
|
color={theme.palette.text.primary}
|
||||||
onClickFunc={() => setCoverImage("")}
|
onClickFunc={() => setCoverImage([])}
|
||||||
height={"32"}
|
height={"32"}
|
||||||
width={"32"}
|
width={"32"}
|
||||||
></TimesIcon>
|
></TimesIcon>
|
||||||
|
@ -3,15 +3,15 @@ import { CardContentContainerComment } from "../common/Comments/Comments-styles"
|
|||||||
import {
|
import {
|
||||||
CrowdfundSubTitle,
|
CrowdfundSubTitle,
|
||||||
CrowdfundSubTitleRow,
|
CrowdfundSubTitleRow,
|
||||||
} from "../PublishFile/Upload-styles.tsx";
|
} from "../PublishIssue/Upload-styles.tsx";
|
||||||
import { Box, Button, Input, Typography, useTheme } from "@mui/material";
|
import { Box, Button, Input, Typography, useTheme } from "@mui/material";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline";
|
import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline";
|
||||||
import { removeFile } from "../../state/features/fileSlice.ts";
|
|
||||||
import AddIcon from "@mui/icons-material/Add";
|
import AddIcon from "@mui/icons-material/Add";
|
||||||
import { QSHARE_FILE_BASE } from "../../constants/Identifiers.ts";
|
import { QSUPPORT_FILE_BASE } from "../../constants/Identifiers.ts";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { RootState } from "../../state/store";
|
import { RootState } from "../../state/store";
|
||||||
|
|
||||||
export const PlaylistListEdit = ({ playlistData, removeVideo, addVideo }) => {
|
export const PlaylistListEdit = ({ playlistData, removeVideo, addVideo }) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -20,7 +20,7 @@ export const PlaylistListEdit = ({ playlistData, removeVideo, addVideo }) => {
|
|||||||
const [searchResults, setSearchResults] = useState([]);
|
const [searchResults, setSearchResults] = useState([]);
|
||||||
const [filterSearch, setFilterSearch] = useState("");
|
const [filterSearch, setFilterSearch] = useState("");
|
||||||
const search = async () => {
|
const search = async () => {
|
||||||
const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&mode=ALL&identifier=${QSHARE_FILE_BASE}&title=${filterSearch}&limit=20&includemetadata=true&reverse=true&name=${username}&exactmatchnames=true&offset=0`;
|
const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&mode=ALL&identifier=${QSUPPORT_FILE_BASE}&title=${filterSearch}&limit=20&includemetadata=true&reverse=true&name=${username}&exactmatchnames=true&offset=0`;
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
|
@ -1,66 +1,79 @@
|
|||||||
import React from 'react'
|
import React from "react";
|
||||||
import { CardContentContainerComment } from '../common/Comments/Comments-styles'
|
import { CardContentContainerComment } from "../common/Comments/Comments-styles";
|
||||||
import { CrowdfundSubTitle, CrowdfundSubTitleRow } from '../PublishFile/Upload-styles.tsx'
|
import {
|
||||||
import { Box, Typography, useTheme } from '@mui/material'
|
CrowdfundSubTitle,
|
||||||
import { useNavigate } from 'react-router-dom'
|
CrowdfundSubTitleRow,
|
||||||
|
} from "../PublishIssue/Upload-styles.tsx";
|
||||||
export const Playlists = ({playlistData, currentVideoIdentifier}) => {
|
import { Box, Typography, useTheme } from "@mui/material";
|
||||||
const theme = useTheme();
|
import { useNavigate } from "react-router-dom";
|
||||||
const navigate = useNavigate()
|
|
||||||
|
|
||||||
|
export const Playlists = ({ playlistData, currentVideoIdentifier }) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{
|
<Box
|
||||||
display: 'flex',
|
sx={{
|
||||||
flexDirection: 'column',
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
maxWidth: '400px',
|
|
||||||
width: '100%'
|
maxWidth: "400px",
|
||||||
}}>
|
width: "100%",
|
||||||
<CrowdfundSubTitleRow >
|
}}
|
||||||
|
>
|
||||||
|
<CrowdfundSubTitleRow>
|
||||||
<CrowdfundSubTitle>Playlist</CrowdfundSubTitle>
|
<CrowdfundSubTitle>Playlist</CrowdfundSubTitle>
|
||||||
</CrowdfundSubTitleRow>
|
</CrowdfundSubTitleRow>
|
||||||
<CardContentContainerComment sx={{
|
<CardContentContainerComment
|
||||||
marginTop: '25px',
|
sx={{
|
||||||
height: '450px',
|
marginTop: "25px",
|
||||||
overflow: 'auto'
|
height: "450px",
|
||||||
}}>
|
overflow: "auto",
|
||||||
{playlistData?.videos?.map((vid, index)=> {
|
}}
|
||||||
const isCurrentVidPlayling = vid?.identifier === currentVideoIdentifier;
|
>
|
||||||
|
{playlistData?.videos?.map((vid, index) => {
|
||||||
|
const isCurrentVidPlayling =
|
||||||
|
vid?.identifier === currentVideoIdentifier;
|
||||||
return (
|
|
||||||
<Box key={vid?.identifier} sx={{
|
|
||||||
display: 'flex',
|
|
||||||
gap: '10px',
|
|
||||||
width: '100%',
|
|
||||||
background: isCurrentVidPlayling && theme.palette.primary.main,
|
|
||||||
alignItems: 'center',
|
|
||||||
padding: '10px',
|
|
||||||
borderRadius: '5px',
|
|
||||||
cursor: isCurrentVidPlayling ? 'default' : 'pointer',
|
|
||||||
userSelect: 'none'
|
|
||||||
}}
|
|
||||||
onClick={()=> {
|
|
||||||
if(isCurrentVidPlayling) return
|
|
||||||
|
|
||||||
navigate(`/video/${vid.name}/${vid.identifier}`)
|
return (
|
||||||
|
<Box
|
||||||
|
key={vid?.identifier}
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
gap: "10px",
|
||||||
|
width: "100%",
|
||||||
|
background: isCurrentVidPlayling && theme.palette.primary.main,
|
||||||
|
alignItems: "center",
|
||||||
|
padding: "10px",
|
||||||
|
borderRadius: "5px",
|
||||||
|
cursor: isCurrentVidPlayling ? "default" : "pointer",
|
||||||
|
userSelect: "none",
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
if (isCurrentVidPlayling) return;
|
||||||
|
|
||||||
|
navigate(`/video/${vid.name}/${vid.identifier}`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
fontSize: "14px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography sx={{
|
{index + 1}
|
||||||
fontSize: '14px'
|
</Typography>
|
||||||
}}>{index + 1}</Typography>
|
<Typography
|
||||||
<Typography sx={{
|
sx={{
|
||||||
fontSize: '18px',
|
fontSize: "18px",
|
||||||
wordBreak: 'break-word'
|
wordBreak: "break-word",
|
||||||
}}>{vid?.metadata?.title}</Typography>
|
}}
|
||||||
|
>
|
||||||
</Box>
|
{vid?.metadata?.title}
|
||||||
)
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
})}
|
})}
|
||||||
</CardContentContainerComment>
|
</CardContentContainerComment>
|
||||||
</Box>
|
</Box>
|
||||||
|
);
|
||||||
)
|
};
|
||||||
}
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import {
|
import {
|
||||||
CrowdfundActionButton,
|
ActionButton,
|
||||||
CrowdfundActionButtonRow,
|
ActionButtonRow,
|
||||||
CustomInputField,
|
CustomInputField,
|
||||||
ModalBody,
|
ModalBody,
|
||||||
NewCrowdfundTitle,
|
NewCrowdfundTitle,
|
||||||
@ -17,16 +17,22 @@ import { useDropzone } from "react-dropzone";
|
|||||||
import { setNotification } from "../../state/features/notificationsSlice";
|
import { setNotification } from "../../state/features/notificationsSlice";
|
||||||
import { objectToBase64 } from "../../utils/toBase64";
|
import { objectToBase64 } from "../../utils/toBase64";
|
||||||
import { RootState } from "../../state/store";
|
import { RootState } from "../../state/store";
|
||||||
import { QSHARE_FILE_BASE } from "../../constants/Identifiers.ts";
|
import { QSUPPORT_FILE_BASE } from "../../constants/Identifiers.ts";
|
||||||
import { MultiplePublish } from "../common/MultiplePublish/MultiplePublishAll";
|
import { MultiplePublish } from "../common/MultiplePublish/MultiplePublishAll";
|
||||||
import { TextEditor } from "../common/TextEditor/TextEditor";
|
import { TextEditor } from "../common/TextEditor/TextEditor";
|
||||||
import { extractTextFromHTML } from "../common/TextEditor/utils";
|
import { extractTextFromHTML } from "../common/TextEditor/utils";
|
||||||
import { allCategoryData } from "../../constants/Categories/1stCategories.ts";
|
import { allCategoryData } from "../../constants/Categories/1stCategories.ts";
|
||||||
import { titleFormatter } from "../../constants/Misc.ts";
|
import { titleFormatter } from "../../constants/Misc.ts";
|
||||||
import {
|
import {
|
||||||
|
appendCategoryToList,
|
||||||
CategoryList,
|
CategoryList,
|
||||||
CategoryListRef,
|
CategoryListRef,
|
||||||
} from "../common/CategoryList/CategoryList.tsx";
|
} from "../common/CategoryList/CategoryList.tsx";
|
||||||
|
import { SupportState } from "../../constants/Categories/2ndCategories.ts";
|
||||||
|
import {
|
||||||
|
ImagePublisher,
|
||||||
|
ImagePublisherRef,
|
||||||
|
} from "../common/ImagePublisher/ImagePublisher.tsx";
|
||||||
|
|
||||||
const uid = new ShortUniqueId();
|
const uid = new ShortUniqueId();
|
||||||
const shortuid = new ShortUniqueId({ length: 5 });
|
const shortuid = new ShortUniqueId({ length: 5 });
|
||||||
@ -46,7 +52,7 @@ interface VideoFile {
|
|||||||
description: string;
|
description: string;
|
||||||
coverImage?: string;
|
coverImage?: string;
|
||||||
}
|
}
|
||||||
export const PublishFile = ({ editId, editContent }: NewCrowdfundProps) => {
|
export const PublishIssue = ({ editId, editContent }: NewCrowdfundProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [isOpenMultiplePublish, setIsOpenMultiplePublish] = useState(false);
|
const [isOpenMultiplePublish, setIsOpenMultiplePublish] = useState(false);
|
||||||
@ -73,7 +79,7 @@ export const PublishFile = ({ editId, editContent }: NewCrowdfundProps) => {
|
|||||||
const [playlistSetting, setPlaylistSetting] = useState<null | string>(null);
|
const [playlistSetting, setPlaylistSetting] = useState<null | string>(null);
|
||||||
const [publishes, setPublishes] = useState<any>(null);
|
const [publishes, setPublishes] = useState<any>(null);
|
||||||
const categoryListRef = useRef<CategoryListRef>(null);
|
const categoryListRef = useRef<CategoryListRef>(null);
|
||||||
|
const imagePublisherRef = useRef<ImagePublisherRef>(null);
|
||||||
const { getRootProps, getInputProps } = useDropzone({
|
const { getRootProps, getInputProps } = useDropzone({
|
||||||
maxFiles: 10,
|
maxFiles: 10,
|
||||||
maxSize: 419430400, // 400 MB in bytes
|
maxSize: 419430400, // 400 MB in bytes
|
||||||
@ -127,7 +133,6 @@ export const PublishFile = ({ editId, editContent }: NewCrowdfundProps) => {
|
|||||||
if (!description) throw new Error("Please enter a description");
|
if (!description) throw new Error("Please enter a description");
|
||||||
if (!categoryListRef.current?.getSelectedCategories()[0])
|
if (!categoryListRef.current?.getSelectedCategories()[0])
|
||||||
throw new Error("Please select a category");
|
throw new Error("Please select a category");
|
||||||
if (files.length === 0) throw new Error("Add at least one file");
|
|
||||||
let errorMsg = "";
|
let errorMsg = "";
|
||||||
let name = "";
|
let name = "";
|
||||||
if (username) {
|
if (username) {
|
||||||
@ -169,7 +174,7 @@ export const PublishFile = ({ editId, editContent }: NewCrowdfundProps) => {
|
|||||||
const file = publish.file;
|
const file = publish.file;
|
||||||
const id = uid();
|
const id = uid();
|
||||||
|
|
||||||
const identifier = `${QSHARE_FILE_BASE}${sanitizeTitle.slice(0, 30)}_${id}`;
|
const identifier = `${QSUPPORT_FILE_BASE}${sanitizeTitle.slice(0, 30)}_${id}`;
|
||||||
|
|
||||||
let fileExtension = "";
|
let fileExtension = "";
|
||||||
const fileExtensionSplit = file?.name?.split(".");
|
const fileExtensionSplit = file?.name?.split(".");
|
||||||
@ -197,9 +202,12 @@ export const PublishFile = ({ editId, editContent }: NewCrowdfundProps) => {
|
|||||||
filename = alphanumericString;
|
filename = alphanumericString;
|
||||||
}
|
}
|
||||||
|
|
||||||
let metadescription =
|
const categoryList = appendCategoryToList(
|
||||||
`**${categoryListRef.current?.getCategoriesFetchString()}**` +
|
categoryListRef.current?.getSelectedCategories(),
|
||||||
fullDescription.slice(0, 150);
|
"101"
|
||||||
|
);
|
||||||
|
const categoryString = `**${categoryListRef.current?.getCategoriesFetchString(categoryList)}**`;
|
||||||
|
let metadescription = categoryString + fullDescription.slice(0, 150);
|
||||||
|
|
||||||
const requestBodyVideo: any = {
|
const requestBodyVideo: any = {
|
||||||
action: "PUBLISH_QDN_RESOURCE",
|
action: "PUBLISH_QDN_RESOURCE",
|
||||||
@ -210,7 +218,7 @@ export const PublishFile = ({ editId, editContent }: NewCrowdfundProps) => {
|
|||||||
description: metadescription,
|
description: metadescription,
|
||||||
identifier,
|
identifier,
|
||||||
filename,
|
filename,
|
||||||
tag1: QSHARE_FILE_BASE,
|
tag1: QSUPPORT_FILE_BASE,
|
||||||
};
|
};
|
||||||
listOfPublishes.push(requestBodyVideo);
|
listOfPublishes.push(requestBodyVideo);
|
||||||
fileReferences.push({
|
fileReferences.push({
|
||||||
@ -224,32 +232,38 @@ export const PublishFile = ({ editId, editContent }: NewCrowdfundProps) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const idMeta = uid();
|
const idMeta = uid();
|
||||||
const identifier = `${QSHARE_FILE_BASE}${sanitizeTitle.slice(0, 30)}_${idMeta}`;
|
const identifier = `${QSUPPORT_FILE_BASE}${sanitizeTitle.slice(0, 30)}_${idMeta}`;
|
||||||
|
|
||||||
|
const categoryList = appendCategoryToList(
|
||||||
|
categoryListRef.current?.getSelectedCategories(),
|
||||||
|
"101"
|
||||||
|
);
|
||||||
|
|
||||||
const fileObject: any = {
|
const fileObject: any = {
|
||||||
title,
|
title,
|
||||||
version: 1,
|
version: 1,
|
||||||
fullDescription,
|
fullDescription,
|
||||||
htmlDescription: description,
|
htmlDescription: description,
|
||||||
commentsId: `${QSHARE_FILE_BASE}_cm_${idMeta}`,
|
commentsId: `${QSUPPORT_FILE_BASE}_cm_${idMeta}`,
|
||||||
...categoryListRef.current?.categoriesToObject(),
|
...categoryListRef.current?.categoriesToObject(categoryList),
|
||||||
files: fileReferences,
|
files: fileReferences,
|
||||||
|
images: imagePublisherRef?.current?.getImageArray(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let metadescription =
|
const categoryString = `**${categoryListRef.current?.getCategoriesFetchString(categoryList)}**`;
|
||||||
`**${categoryListRef.current?.getCategoriesFetchString()}**` +
|
let metadescription = categoryString + fullDescription.slice(0, 150);
|
||||||
fullDescription.slice(0, 150);
|
|
||||||
|
|
||||||
const crowdfundObjectToBase64 = await objectToBase64(fileObject);
|
const fileObjectToBase64 = await objectToBase64(fileObject);
|
||||||
// Description is obtained from raw data
|
// Description is obtained from raw data
|
||||||
const requestBodyJson: any = {
|
const requestBodyJson: any = {
|
||||||
action: "PUBLISH_QDN_RESOURCE",
|
action: "PUBLISH_QDN_RESOURCE",
|
||||||
name: name,
|
name: name,
|
||||||
service: "DOCUMENT",
|
service: "DOCUMENT",
|
||||||
data64: crowdfundObjectToBase64,
|
data64: fileObjectToBase64,
|
||||||
title: title.slice(0, 50),
|
title: title.slice(0, 50),
|
||||||
description: metadescription,
|
description: metadescription,
|
||||||
identifier: identifier + "_metadata",
|
identifier: identifier + "_metadata",
|
||||||
tag1: QSHARE_FILE_BASE,
|
tag1: QSUPPORT_FILE_BASE,
|
||||||
filename: `video_metadata.json`,
|
filename: `video_metadata.json`,
|
||||||
};
|
};
|
||||||
listOfPublishes.push(requestBodyJson);
|
listOfPublishes.push(requestBodyJson);
|
||||||
@ -264,17 +278,17 @@ export const PublishFile = ({ editId, editContent }: NewCrowdfundProps) => {
|
|||||||
let notificationObj: any = null;
|
let notificationObj: any = null;
|
||||||
if (typeof error === "string") {
|
if (typeof error === "string") {
|
||||||
notificationObj = {
|
notificationObj = {
|
||||||
msg: error || "Failed to publish share",
|
msg: error || "Failed to publish issue",
|
||||||
alertType: "error",
|
alertType: "error",
|
||||||
};
|
};
|
||||||
} else if (typeof error?.error === "string") {
|
} else if (typeof error?.error === "string") {
|
||||||
notificationObj = {
|
notificationObj = {
|
||||||
msg: error?.error || "Failed to publish share",
|
msg: error?.error || "Failed to publish issue",
|
||||||
alertType: "error",
|
alertType: "error",
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
notificationObj = {
|
notificationObj = {
|
||||||
msg: error?.message || "Failed to publish share",
|
msg: error?.message || "Failed to publish issue",
|
||||||
alertType: "error",
|
alertType: "error",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -295,7 +309,7 @@ export const PublishFile = ({ editId, editContent }: NewCrowdfundProps) => {
|
|||||||
setIsOpen(true);
|
setIsOpen(true);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
share
|
Open an Issue
|
||||||
</StyledButton>
|
</StyledButton>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
@ -314,7 +328,7 @@ export const PublishFile = ({ editId, editContent }: NewCrowdfundProps) => {
|
|||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<NewCrowdfundTitle>Share</NewCrowdfundTitle>
|
<NewCrowdfundTitle>Issue</NewCrowdfundTitle>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{step === "videos" && (
|
{step === "videos" && (
|
||||||
@ -331,7 +345,7 @@ export const PublishFile = ({ editId, editContent }: NewCrowdfundProps) => {
|
|||||||
>
|
>
|
||||||
<input {...getInputProps()} />
|
<input {...getInputProps()} />
|
||||||
<Typography>
|
<Typography>
|
||||||
Drag and drop files here or click to select files
|
Publish files related to issue (Optional)
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
{files.map((file, index) => {
|
{files.map((file, index) => {
|
||||||
@ -362,53 +376,53 @@ export const PublishFile = ({ editId, editContent }: NewCrowdfundProps) => {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
||||||
{files?.length > 0 && (
|
<>
|
||||||
<>
|
<Box
|
||||||
<Box
|
sx={{
|
||||||
sx={{
|
display: "flex",
|
||||||
display: "flex",
|
gap: "20px",
|
||||||
gap: "20px",
|
alignItems: "flex-start",
|
||||||
alignItems: "flex-start",
|
}}
|
||||||
}}
|
>
|
||||||
>
|
<CategoryList
|
||||||
<CategoryList
|
categoryData={allCategoryData}
|
||||||
categoryData={allCategoryData}
|
ref={categoryListRef}
|
||||||
ref={categoryListRef}
|
columns={3}
|
||||||
columns={3}
|
excludeCategories={SupportState}
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
<CustomInputField
|
|
||||||
name="title"
|
|
||||||
label="Title of share"
|
|
||||||
variant="filled"
|
|
||||||
value={title}
|
|
||||||
onChange={e => {
|
|
||||||
const value = e.target.value;
|
|
||||||
const formattedValue = value.replace(titleFormatter, "");
|
|
||||||
setTitle(formattedValue);
|
|
||||||
}}
|
|
||||||
inputProps={{ maxLength: 180 }}
|
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
<Typography
|
</Box>
|
||||||
sx={{
|
<ImagePublisher ref={imagePublisherRef} />
|
||||||
fontSize: "18px",
|
<CustomInputField
|
||||||
}}
|
name="title"
|
||||||
>
|
label="Title of Issue"
|
||||||
Description of share
|
variant="filled"
|
||||||
</Typography>
|
value={title}
|
||||||
<TextEditor
|
onChange={e => {
|
||||||
inlineContent={description}
|
const value = e.target.value;
|
||||||
setInlineContent={value => {
|
const formattedValue = value.replace(titleFormatter, "");
|
||||||
setDescription(value);
|
setTitle(formattedValue);
|
||||||
}}
|
}}
|
||||||
/>
|
inputProps={{ maxLength: 180 }}
|
||||||
</>
|
required
|
||||||
)}
|
/>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
fontSize: "18px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Description of Issue
|
||||||
|
</Typography>
|
||||||
|
<TextEditor
|
||||||
|
inlineContent={description}
|
||||||
|
setInlineContent={value => {
|
||||||
|
setDescription(value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<CrowdfundActionButtonRow>
|
<ActionButtonRow>
|
||||||
<CrowdfundActionButton
|
<ActionButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onClose();
|
onClose();
|
||||||
}}
|
}}
|
||||||
@ -416,7 +430,7 @@ export const PublishFile = ({ editId, editContent }: NewCrowdfundProps) => {
|
|||||||
color="error"
|
color="error"
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</CrowdfundActionButton>
|
</ActionButton>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@ -424,16 +438,16 @@ export const PublishFile = ({ editId, editContent }: NewCrowdfundProps) => {
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CrowdfundActionButton
|
<ActionButton
|
||||||
variant="contained"
|
variant="contained"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
publishQDNResource();
|
publishQDNResource();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Publish
|
Publish
|
||||||
</CrowdfundActionButton>
|
</ActionButton>
|
||||||
</Box>
|
</Box>
|
||||||
</CrowdfundActionButtonRow>
|
</ActionButtonRow>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
@ -466,7 +480,7 @@ export const PublishFile = ({ editId, editContent }: NewCrowdfundProps) => {
|
|||||||
categoryListRef.current?.clearCategories();
|
categoryListRef.current?.clearCategories();
|
||||||
dispatch(
|
dispatch(
|
||||||
setNotification({
|
setNotification({
|
||||||
msg: "Files published",
|
msg: "Issue published",
|
||||||
alertType: "success",
|
alertType: "success",
|
||||||
})
|
})
|
||||||
);
|
);
|
@ -7,9 +7,9 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
Grid,
|
Grid,
|
||||||
Rating,
|
Rating,
|
||||||
|
Select,
|
||||||
TextField,
|
TextField,
|
||||||
Typography,
|
Typography,
|
||||||
Select
|
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import AddPhotoAlternateIcon from "@mui/icons-material/AddPhotoAlternate";
|
import AddPhotoAlternateIcon from "@mui/icons-material/AddPhotoAlternate";
|
||||||
import { TimesSVG } from "../../assets/svgs/TimesSVG";
|
import { TimesSVG } from "../../assets/svgs/TimesSVG";
|
||||||
@ -67,9 +67,9 @@ export const ModalBody = styled(Box)(({ theme }) => ({
|
|||||||
overflowY: "auto",
|
overflowY: "auto",
|
||||||
maxHeight: "95vh",
|
maxHeight: "95vh",
|
||||||
boxShadow:
|
boxShadow:
|
||||||
theme.palette.mode === "dark"
|
theme.palette.mode === "dark"
|
||||||
? "0px 4px 5px 0px hsla(0,0%,0%,0.14), 0px 1px 10px 0px hsla(0,0%,0%,0.12), 0px 2px 4px -1px hsla(0,0%,0%,0.2)"
|
? "0px 4px 5px 0px hsla(0,0%,0%,0.14), 0px 1px 10px 0px hsla(0,0%,0%,0.12), 0px 2px 4px -1px hsla(0,0%,0%,0.2)"
|
||||||
: "rgba(99, 99, 99, 0.2) 0px 2px 8px 0px",
|
: "rgba(99, 99, 99, 0.2) 0px 2px 8px 0px",
|
||||||
"&::-webkit-scrollbar-track": {
|
"&::-webkit-scrollbar-track": {
|
||||||
backgroundColor: theme.palette.background.paper,
|
backgroundColor: theme.palette.background.paper,
|
||||||
},
|
},
|
||||||
@ -159,8 +159,6 @@ export const CustomInputField = styled(TextField)(({ theme }) => ({
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const CrowdfundTitle = styled(Typography)(({ theme }) => ({
|
export const CrowdfundTitle = styled(Typography)(({ theme }) => ({
|
||||||
fontFamily: "Copse",
|
fontFamily: "Copse",
|
||||||
letterSpacing: "1px",
|
letterSpacing: "1px",
|
||||||
@ -203,11 +201,11 @@ export const CrowdfundDescription = styled(Typography)(({ theme }) => ({
|
|||||||
|
|
||||||
export const Spacer = ({ height }: any) => {
|
export const Spacer = ({ height }: any) => {
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
height: height,
|
height: height,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -314,14 +312,14 @@ export const AddCrowdFundButton = styled(Button)(({ theme }) => ({
|
|||||||
gap: "8px",
|
gap: "8px",
|
||||||
color: "#ffffff",
|
color: "#ffffff",
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
theme.palette.mode === "dark" ? theme.palette.primary.main : "#2a9a86",
|
theme.palette.mode === "dark" ? theme.palette.primary.main : "#2a9a86",
|
||||||
border: "none",
|
border: "none",
|
||||||
borderRadius: "5px",
|
borderRadius: "5px",
|
||||||
transition: "all 0.3s ease-in-out",
|
transition: "all 0.3s ease-in-out",
|
||||||
"&:hover": {
|
"&:hover": {
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
theme.palette.mode === "dark" ? theme.palette.primary.dark : "#217e6d",
|
theme.palette.mode === "dark" ? theme.palette.primary.dark : "#217e6d",
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -333,14 +331,14 @@ export const EditCrowdFundButton = styled(Button)(({ theme }) => ({
|
|||||||
gap: "8px",
|
gap: "8px",
|
||||||
color: "#ffffff",
|
color: "#ffffff",
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
theme.palette.mode === "dark" ? theme.palette.primary.main : "#2a9a86",
|
theme.palette.mode === "dark" ? theme.palette.primary.main : "#2a9a86",
|
||||||
border: "none",
|
border: "none",
|
||||||
borderRadius: "5px",
|
borderRadius: "5px",
|
||||||
transition: "all 0.3s ease-in-out",
|
transition: "all 0.3s ease-in-out",
|
||||||
"&:hover": {
|
"&:hover": {
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
theme.palette.mode === "dark" ? theme.palette.primary.dark : "#217e6d",
|
theme.palette.mode === "dark" ? theme.palette.primary.dark : "#217e6d",
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -466,14 +464,14 @@ export const CoverImage = styled("img")({
|
|||||||
objectPosition: "center",
|
objectPosition: "center",
|
||||||
});
|
});
|
||||||
|
|
||||||
export const CrowdfundActionButtonRow = styled(Box)({
|
export const ActionButtonRow = styled(Box)({
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
});
|
});
|
||||||
|
|
||||||
export const CrowdfundActionButton = styled(Button)(({ theme }) => ({
|
export const ActionButton = styled(Button)(({ theme }) => ({
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
fontFamily: "Montserrat",
|
fontFamily: "Montserrat",
|
||||||
@ -540,8 +538,8 @@ export const NoReviewsFont = styled(Typography)(({ theme }) => ({
|
|||||||
export const StyledButton = styled(Button)(({ theme }) => ({
|
export const StyledButton = styled(Button)(({ theme }) => ({
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
color: theme.palette.text.primary,
|
color: theme.palette.text.primary,
|
||||||
fontFamily: "Cairo"
|
fontFamily: "Cairo",
|
||||||
}))
|
}));
|
||||||
|
|
||||||
export const CustomSelect = styled(Select)(({ theme }) => ({
|
export const CustomSelect = styled(Select)(({ theme }) => ({
|
||||||
fontFamily: "Mulish",
|
fontFamily: "Mulish",
|
||||||
@ -550,38 +548,38 @@ export const CustomSelect = styled(Select)(({ theme }) => ({
|
|||||||
fontWeight: 400,
|
fontWeight: 400,
|
||||||
color: theme.palette.text.primary,
|
color: theme.palette.text.primary,
|
||||||
backgroundColor: theme.palette.background.default,
|
backgroundColor: theme.palette.background.default,
|
||||||
'& .MuiSelect-select': {
|
"& .MuiSelect-select": {
|
||||||
padding: '12px',
|
padding: "12px",
|
||||||
fontFamily: "Mulish",
|
fontFamily: "Mulish",
|
||||||
fontSize: "19px",
|
fontSize: "19px",
|
||||||
letterSpacing: "0px",
|
letterSpacing: "0px",
|
||||||
fontWeight: 400,
|
fontWeight: 400,
|
||||||
borderRadius: theme.shape.borderRadius, // Match border radius
|
borderRadius: theme.shape.borderRadius, // Match border radius
|
||||||
},
|
},
|
||||||
'&:before': {
|
"&:before": {
|
||||||
// Underline style
|
// Underline style
|
||||||
borderBottomColor: theme.palette.mode === "light" ? "#B2BAC2" : "#c9cccf",
|
borderBottomColor: theme.palette.mode === "light" ? "#B2BAC2" : "#c9cccf",
|
||||||
},
|
},
|
||||||
'&:after': {
|
"&:after": {
|
||||||
// Underline style when focused
|
// Underline style when focused
|
||||||
borderBottomColor: theme.palette.secondary.main,
|
borderBottomColor: theme.palette.secondary.main,
|
||||||
},
|
},
|
||||||
'& .MuiOutlinedInput-root': {
|
"& .MuiOutlinedInput-root": {
|
||||||
'& fieldset': {
|
"& fieldset": {
|
||||||
borderColor: "#E0E3E7",
|
borderColor: "#E0E3E7",
|
||||||
},
|
},
|
||||||
'&:hover fieldset': {
|
"&:hover fieldset": {
|
||||||
borderColor: "#B2BAC2",
|
borderColor: "#B2BAC2",
|
||||||
},
|
},
|
||||||
'&.Mui-focused fieldset': {
|
"&.Mui-focused fieldset": {
|
||||||
borderColor: "#6F7E8C",
|
borderColor: "#6F7E8C",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'& .MuiInputBase-root': {
|
"& .MuiInputBase-root": {
|
||||||
fontFamily: "Mulish",
|
fontFamily: "Mulish",
|
||||||
fontSize: "19px",
|
fontSize: "19px",
|
||||||
letterSpacing: "0px",
|
letterSpacing: "0px",
|
||||||
fontWeight: 400,
|
fontWeight: 400,
|
||||||
color: theme.palette.text.primary,
|
color: theme.palette.text.primary,
|
||||||
},
|
},
|
||||||
}));
|
}));
|
@ -25,13 +25,13 @@ export const StatsData = () => {
|
|||||||
getFilesCount,
|
getFilesCount,
|
||||||
} = useFetchFiles();
|
} = useFetchFiles();
|
||||||
|
|
||||||
const totalVideosPublished = useSelector(
|
const totalIssuesPublished = useSelector(
|
||||||
(state: RootState) => state.global.totalFilesPublished
|
(state: RootState) => state.global.totalFilesPublished
|
||||||
);
|
);
|
||||||
const totalNamesPublished = useSelector(
|
const totalNamesPublished = useSelector(
|
||||||
(state: RootState) => state.global.totalNamesPublished
|
(state: RootState) => state.global.totalNamesPublished
|
||||||
);
|
);
|
||||||
const videosPerNamePublished = useSelector(
|
const issuesPerNamePublished = useSelector(
|
||||||
(state: RootState) => state.global.filesPerNamePublished
|
(state: RootState) => state.global.filesPerNamePublished
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -40,22 +40,28 @@ export const StatsData = () => {
|
|||||||
}, [getFilesCount]);
|
}, [getFilesCount]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StatsCol>
|
totalIssuesPublished > 0 && (
|
||||||
<div>
|
<StatsCol>
|
||||||
Shares:{" "}
|
<div>
|
||||||
<span style={{ fontWeight: "bold" }}>{totalVideosPublished}</span>
|
Issues Published:{" "}
|
||||||
</div>
|
<span style={{ fontWeight: "bold" }}>
|
||||||
<div>
|
{totalIssuesPublished || ""}
|
||||||
Publishers:{" "}
|
</span>
|
||||||
<span style={{ fontWeight: "bold" }}>{totalNamesPublished}</span>
|
</div>
|
||||||
</div>
|
<div>
|
||||||
<div>
|
Publishers:{" "}
|
||||||
Average:{" "}
|
<span style={{ fontWeight: "bold" }}>
|
||||||
<span style={{ fontWeight: "bold" }}>
|
{totalNamesPublished || ""}
|
||||||
{videosPerNamePublished > 0 &&
|
</span>
|
||||||
Number(videosPerNamePublished).toFixed(0)}
|
</div>
|
||||||
</span>
|
<div>
|
||||||
</div>
|
Average:{" "}
|
||||||
</StatsCol>
|
<span style={{ fontWeight: "bold" }}>
|
||||||
|
{issuesPerNamePublished > 0 &&
|
||||||
|
Number(issuesPerNamePublished).toFixed(0)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</StatsCol>
|
||||||
|
)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -10,9 +10,10 @@ import {
|
|||||||
Theme,
|
Theme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
|
||||||
import React, { forwardRef, useImperativeHandle, useState } from "react";
|
import React, { useEffect, useImperativeHandle, useState } from "react";
|
||||||
import { CategoryContainer } from "./CategoryList-styles.tsx";
|
import { CategoryContainer } from "./CategoryList-styles.tsx";
|
||||||
import { allCategoryData } from "../../../constants/Categories/1stCategories.ts";
|
import { allCategoryData } from "../../../constants/Categories/1stCategories.ts";
|
||||||
|
import { log } from "../../../constants/Misc.ts";
|
||||||
|
|
||||||
export interface Category {
|
export interface Category {
|
||||||
id: number;
|
id: number;
|
||||||
@ -29,19 +30,22 @@ export interface CategoryData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ListDirection = "column" | "row";
|
type ListDirection = "column" | "row";
|
||||||
|
|
||||||
interface CategoryListProps {
|
interface CategoryListProps {
|
||||||
sx?: SxProps<Theme>;
|
sx?: SxProps<Theme>;
|
||||||
categoryData: CategoryData;
|
categoryData: CategoryData;
|
||||||
initialCategories?: string[];
|
initialCategories?: string[];
|
||||||
columns?: number;
|
columns?: number;
|
||||||
|
afterChange?: (categories: string[]) => void;
|
||||||
|
excludeCategories?: Category[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CategoryListRef = {
|
export type CategoryListRef = {
|
||||||
getSelectedCategories: () => string[];
|
getSelectedCategories: () => string[];
|
||||||
setSelectedCategories: (arr: string[]) => void;
|
setSelectedCategories: (arr: string[]) => void;
|
||||||
clearCategories: () => void;
|
clearCategories: () => void;
|
||||||
getCategoriesFetchString: () => string;
|
getCategoriesFetchString: (categories?: string[]) => string;
|
||||||
categoriesToObject: () => object;
|
categoriesToObject: (categories?: string[]) => object;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CategoryList = React.forwardRef<
|
export const CategoryList = React.forwardRef<
|
||||||
@ -49,7 +53,14 @@ export const CategoryList = React.forwardRef<
|
|||||||
CategoryListProps
|
CategoryListProps
|
||||||
>(
|
>(
|
||||||
(
|
(
|
||||||
{ sx, categoryData, initialCategories, columns = 1 }: CategoryListProps,
|
{
|
||||||
|
sx,
|
||||||
|
categoryData,
|
||||||
|
initialCategories,
|
||||||
|
columns = 1,
|
||||||
|
afterChange,
|
||||||
|
excludeCategories,
|
||||||
|
}: CategoryListProps,
|
||||||
ref
|
ref
|
||||||
) => {
|
) => {
|
||||||
const categoriesLength = categoryData.subCategories.length + 1;
|
const categoriesLength = categoryData.subCategories.length + 1;
|
||||||
@ -60,20 +71,27 @@ export const CategoryList = React.forwardRef<
|
|||||||
const [selectedCategories, setSelectedCategories] = useState<string[]>(
|
const [selectedCategories, setSelectedCategories] = useState<string[]>(
|
||||||
initialCategories || emptyCategories
|
initialCategories || emptyCategories
|
||||||
);
|
);
|
||||||
|
useEffect(() => {
|
||||||
|
if (initialCategories) setSelectedCategories(initialCategories);
|
||||||
|
}, [initialCategories]);
|
||||||
|
|
||||||
const categoriesToObject = () => {
|
const updateCategories = (categories: string[]) => {
|
||||||
|
setSelectedCategories(categories);
|
||||||
|
if (afterChange) afterChange(categories);
|
||||||
|
};
|
||||||
|
const categoriesToObject = (categories: string[]) => {
|
||||||
let categoriesObject = {};
|
let categoriesObject = {};
|
||||||
selectedCategories.map((category, index) => {
|
categories.map((category, index) => {
|
||||||
if (index === 0) categoriesObject["category"] = category;
|
if (index === 0) categoriesObject["category"] = category;
|
||||||
else if (index === 1) categoriesObject["subcategory"] = category;
|
else if (index === 1) categoriesObject["subcategory"] = category;
|
||||||
else categoriesObject[`subcategory${index}`] = category;
|
else categoriesObject[`subcategory${index}`] = category;
|
||||||
});
|
});
|
||||||
console.log("categoriesObject is: ", categoriesObject);
|
if (log) console.log("categoriesObject is: ", categoriesObject);
|
||||||
return categoriesObject;
|
return categoriesObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
const clearCategories = () => {
|
const clearCategories = () => {
|
||||||
setSelectedCategories(emptyCategories);
|
updateCategories(emptyCategories);
|
||||||
};
|
};
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
@ -81,26 +99,31 @@ export const CategoryList = React.forwardRef<
|
|||||||
return selectedCategories;
|
return selectedCategories;
|
||||||
},
|
},
|
||||||
setSelectedCategories: categories => {
|
setSelectedCategories: categories => {
|
||||||
console.log("setSelectedCategories: ", categories);
|
if (log) console.log("setSelectedCategories: ", categories);
|
||||||
//categories.map((category, index) => selectCategory(category, index));
|
updateCategories(categories);
|
||||||
setSelectedCategories(categories);
|
|
||||||
},
|
},
|
||||||
clearCategories,
|
clearCategories,
|
||||||
getCategoriesFetchString: () =>
|
getCategoriesFetchString: (categories?: string[]) =>
|
||||||
getCategoriesFetchString(selectedCategories),
|
getCategoriesFetchString(categories || selectedCategories),
|
||||||
categoriesToObject,
|
categoriesToObject: (categories?: string[]) =>
|
||||||
|
categoriesToObject(categories || selectedCategories),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const selectCategory = (optionId: string, index: number) => {
|
const selectCategory = (optionId: string, index: number) => {
|
||||||
const isMainCategory = index === 0;
|
const isMainCategory = index === 0;
|
||||||
const subCategoryIndex = index - 1;
|
const subCategoryIndex = index - 1;
|
||||||
|
let selectedOption: Category | undefined;
|
||||||
|
if (isMainCategory)
|
||||||
|
selectedOption = categoryData.category.find(
|
||||||
|
option => option.id === +optionId
|
||||||
|
);
|
||||||
|
else {
|
||||||
|
const subCategoryLevel = categoryData.subCategories[subCategoryIndex];
|
||||||
|
const parentCategory = selectedCategories[subCategoryIndex];
|
||||||
|
const subCategory = subCategoryLevel[parentCategory];
|
||||||
|
|
||||||
const selectedOption = isMainCategory
|
selectedOption = subCategory.find(option => option.id === +optionId);
|
||||||
? categoryData.category.find(option => option.id === +optionId)
|
}
|
||||||
: categoryData.subCategories[subCategoryIndex][
|
|
||||||
selectedCategories[subCategoryIndex]
|
|
||||||
].find(option => option.id === +optionId);
|
|
||||||
|
|
||||||
const newSelectedCategories: string[] = selectedCategories.map(
|
const newSelectedCategories: string[] = selectedCategories.map(
|
||||||
(category, categoryIndex) => {
|
(category, categoryIndex) => {
|
||||||
if (index > categoryIndex) return category;
|
if (index > categoryIndex) return category;
|
||||||
@ -108,7 +131,7 @@ export const CategoryList = React.forwardRef<
|
|||||||
else return "";
|
else return "";
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
setSelectedCategories(newSelectedCategories);
|
updateCategories(newSelectedCategories);
|
||||||
};
|
};
|
||||||
|
|
||||||
const selectCategoryEvent = (event: SelectChangeEvent, index: number) => {
|
const selectCategoryEvent = (event: SelectChangeEvent, index: number) => {
|
||||||
@ -136,15 +159,16 @@ export const CategoryList = React.forwardRef<
|
|||||||
|
|
||||||
const fillMenu = (category: Categories, index: number) => {
|
const fillMenu = (category: Categories, index: number) => {
|
||||||
const subCategoryIndex = selectedCategories[index];
|
const subCategoryIndex = selectedCategories[index];
|
||||||
console.log("selected categories: ", selectedCategories);
|
if (log) console.log("selected categories: ", selectedCategories);
|
||||||
console.log("index is: ", index);
|
if (log) console.log("index is: ", index);
|
||||||
console.log("subCategoryIndex is: ", subCategoryIndex);
|
if (log) console.log("subCategoryIndex is: ", subCategoryIndex);
|
||||||
console.log("category is: ", category);
|
if (log) console.log("category is: ", category);
|
||||||
console.log(
|
if (log)
|
||||||
"subCategoryIndex within category: ",
|
console.log(
|
||||||
selectedCategories[subCategoryIndex]
|
"subCategoryIndex within category: ",
|
||||||
);
|
selectedCategories[subCategoryIndex]
|
||||||
console.log("categoryData: ", categoryData);
|
);
|
||||||
|
if (log) console.log("categoryData: ", categoryData);
|
||||||
|
|
||||||
const menuToFill = category[subCategoryIndex];
|
const menuToFill = category[subCategoryIndex];
|
||||||
if (menuToFill)
|
if (menuToFill)
|
||||||
@ -158,6 +182,7 @@ export const CategoryList = React.forwardRef<
|
|||||||
const hasSubCategory = (category: Categories, index: number) => {
|
const hasSubCategory = (category: Categories, index: number) => {
|
||||||
const subCategoryIndex = selectedCategories[index];
|
const subCategoryIndex = selectedCategories[index];
|
||||||
const subCategory = category[subCategoryIndex];
|
const subCategory = category[subCategoryIndex];
|
||||||
|
if (excludeCategories && subCategory === excludeCategories) return false;
|
||||||
return subCategory && subCategoryIndex;
|
return subCategory && subCategoryIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -265,10 +290,21 @@ export const getCategoriesFetchString = (categories: string[]) => {
|
|||||||
else fetchString += `;sub${index}:${category}`;
|
else fetchString += `;sub${index}:${category}`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
console.log("categoriesAsDescription: ", fetchString);
|
if (log) console.log("categoriesAsDescription: ", fetchString);
|
||||||
return fetchString;
|
return fetchString;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const appendCategoryToList = (
|
||||||
|
categories: string[],
|
||||||
|
appendedCategoryID: string
|
||||||
|
) => {
|
||||||
|
const filteredCategories = categories.filter(
|
||||||
|
categoryString => categoryString.length > 0
|
||||||
|
);
|
||||||
|
filteredCategories.push(appendedCategoryID);
|
||||||
|
return filteredCategories;
|
||||||
|
};
|
||||||
|
|
||||||
export const getCategoriesFromObject = (editFileProperties: any) => {
|
export const getCategoriesFromObject = (editFileProperties: any) => {
|
||||||
const categoryList: string[] = [];
|
const categoryList: string[] = [];
|
||||||
const categoryCount = allCategoryData.subCategories.length + 1;
|
const categoryCount = allCategoryData.subCategories.length + 1;
|
||||||
|
@ -11,7 +11,7 @@ import {
|
|||||||
CommentInputContainer,
|
CommentInputContainer,
|
||||||
SubmitCommentButton,
|
SubmitCommentButton,
|
||||||
} from "./Comments-styles";
|
} from "./Comments-styles";
|
||||||
import { QSHARE_COMMENT_BASE } from "../../../constants/Identifiers.ts";
|
import { QSUPPORT_COMMENT_BASE } from "../../../constants/Identifiers.ts";
|
||||||
const uid = new ShortUniqueId();
|
const uid = new ShortUniqueId();
|
||||||
|
|
||||||
const notification = localforage.createInstance({
|
const notification = localforage.createInstance({
|
||||||
@ -201,13 +201,13 @@ export const CommentEditor = ({
|
|||||||
try {
|
try {
|
||||||
const id = uid();
|
const id = uid();
|
||||||
|
|
||||||
let identifier = `${QSHARE_COMMENT_BASE}${postId.slice(-12)}_base_${id}`;
|
let identifier = `${QSUPPORT_COMMENT_BASE}${postId.slice(-12)}_base_${id}`;
|
||||||
let idForNotification = identifier;
|
let idForNotification = identifier;
|
||||||
|
|
||||||
if (isReply && commentId) {
|
if (isReply && commentId) {
|
||||||
const removeBaseCommentId = commentId;
|
const removeBaseCommentId = commentId;
|
||||||
removeBaseCommentId.replace("_base_", "");
|
removeBaseCommentId.replace("_base_", "");
|
||||||
identifier = `${QSHARE_COMMENT_BASE}${postId.slice(
|
identifier = `${QSUPPORT_COMMENT_BASE}${postId.slice(
|
||||||
-12
|
-12
|
||||||
)}_reply_${removeBaseCommentId.slice(-6)}_${id}`;
|
)}_reply_${removeBaseCommentId.slice(-6)}_${id}`;
|
||||||
idForNotification = commentId;
|
idForNotification = commentId;
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
import { CommentEditor } from "./CommentEditor";
|
import { CommentEditor } from "./CommentEditor";
|
||||||
import { Comment } from "./Comment";
|
import { Comment } from "./Comment";
|
||||||
import { Box, Button, CircularProgress, useTheme } from "@mui/material";
|
import { CircularProgress } from "@mui/material";
|
||||||
import { styled } from "@mui/system";
|
import { styled } from "@mui/system";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { RootState } from "../../../state/store";
|
import { RootState } from "../../../state/store";
|
||||||
import { useNavigate, useLocation } from "react-router-dom";
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
CommentContainer,
|
CommentContainer,
|
||||||
CommentEditorContainer,
|
CommentEditorContainer,
|
||||||
@ -14,8 +14,11 @@ import {
|
|||||||
LoadMoreCommentsButtonRow,
|
LoadMoreCommentsButtonRow,
|
||||||
NoCommentsRow,
|
NoCommentsRow,
|
||||||
} from "./Comments-styles";
|
} from "./Comments-styles";
|
||||||
import { QSHARE_COMMENT_BASE } from "../../../constants/Identifiers.ts";
|
import { QSUPPORT_COMMENT_BASE } from "../../../constants/Identifiers.ts";
|
||||||
import { CrowdfundSubTitle, CrowdfundSubTitleRow } from "../../PublishFile/Upload-styles.tsx";
|
import {
|
||||||
|
CrowdfundSubTitle,
|
||||||
|
CrowdfundSubTitleRow,
|
||||||
|
} from "../../PublishIssue/Upload-styles.tsx";
|
||||||
|
|
||||||
interface CommentSectionProps {
|
interface CommentSectionProps {
|
||||||
postId: string;
|
postId: string;
|
||||||
@ -105,7 +108,7 @@ export const CommentSection = ({ postId, postName }: CommentSectionProps) => {
|
|||||||
const offset = 0;
|
const offset = 0;
|
||||||
|
|
||||||
const removeBaseCommentId = commentId.replace("_base_", "");
|
const removeBaseCommentId = commentId.replace("_base_", "");
|
||||||
const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_COMMENT&query=${QSHARE_COMMENT_BASE}${postId.slice(
|
const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_COMMENT&query=${QSUPPORT_COMMENT_BASE}${postId.slice(
|
||||||
-12
|
-12
|
||||||
)}_reply_${removeBaseCommentId.slice(
|
)}_reply_${removeBaseCommentId.slice(
|
||||||
-6
|
-6
|
||||||
@ -150,7 +153,7 @@ export const CommentSection = ({ postId, postName }: CommentSectionProps) => {
|
|||||||
if (isNewMessages && numberOfComments) {
|
if (isNewMessages && numberOfComments) {
|
||||||
offset = numberOfComments;
|
offset = numberOfComments;
|
||||||
}
|
}
|
||||||
const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_COMMENT&query=${QSHARE_COMMENT_BASE}${postId.slice(
|
const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_COMMENT&query=${QSUPPORT_COMMENT_BASE}${postId.slice(
|
||||||
-12
|
-12
|
||||||
)}_base_&limit=20&includemetadata=false&offset=${offset}&reverse=false&excludeblocked=true`;
|
)}_base_&limit=20&includemetadata=false&offset=${offset}&reverse=false&excludeblocked=true`;
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
@ -218,11 +221,10 @@ export const CommentSection = ({ postId, postName }: CommentSectionProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
||||||
<Panel>
|
<Panel>
|
||||||
<CrowdfundSubTitleRow >
|
<CrowdfundSubTitleRow>
|
||||||
<CrowdfundSubTitle>Comments</CrowdfundSubTitle>
|
<CrowdfundSubTitle>Comments</CrowdfundSubTitle>
|
||||||
</CrowdfundSubTitleRow>
|
</CrowdfundSubTitleRow>
|
||||||
<CommentsContainer>
|
<CommentsContainer>
|
||||||
{loadingComments ? (
|
{loadingComments ? (
|
||||||
<NoCommentsRow>
|
<NoCommentsRow>
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
import { Box, Button } from "@mui/material";
|
||||||
|
import { styled } from "@mui/system";
|
||||||
|
import AddPhotoAlternateIcon from "@mui/icons-material/AddPhotoAlternate";
|
||||||
|
import { TimesSVG } from "./TimesSVG.tsx";
|
||||||
|
|
||||||
|
export const AddCoverImageButton = styled(Button)(({ theme }) => ({
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
fontFamily: "Montserrat",
|
||||||
|
fontSize: "16px",
|
||||||
|
fontWeight: 400,
|
||||||
|
letterSpacing: "0.2px",
|
||||||
|
color: "white",
|
||||||
|
gap: "5px",
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const AddLogoIcon = styled(AddPhotoAlternateIcon)(({ theme }) => ({
|
||||||
|
color: "#fff",
|
||||||
|
height: "25px",
|
||||||
|
width: "auto",
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const LogoPreviewRow = styled(Box)(({ theme }) => ({
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "10px",
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const CoverImagePreview = styled("img")(({ theme }) => ({
|
||||||
|
width: "100px",
|
||||||
|
height: "100px",
|
||||||
|
objectFit: "contain",
|
||||||
|
userSelect: "none",
|
||||||
|
borderRadius: "3px",
|
||||||
|
marginBottom: "10px",
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const TimesIcon = styled(TimesSVG)(({ theme }) => ({
|
||||||
|
backgroundColor: theme.palette.background.paper,
|
||||||
|
borderRadius: "50%",
|
||||||
|
padding: "5px",
|
||||||
|
transition: "all 0.2s ease-in-out",
|
||||||
|
"&:hover": {
|
||||||
|
cursor: "pointer",
|
||||||
|
scale: "1.1",
|
||||||
|
},
|
||||||
|
}));
|
62
src/components/common/ImagePublisher/ImagePublisher.tsx
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import ImageUploader from "./ImageUploader.tsx";
|
||||||
|
import React, { useImperativeHandle, useState } from "react";
|
||||||
|
import {
|
||||||
|
AddCoverImageButton,
|
||||||
|
AddLogoIcon,
|
||||||
|
CoverImagePreview,
|
||||||
|
LogoPreviewRow,
|
||||||
|
TimesIcon,
|
||||||
|
} from "./ImagePublisher-styles.tsx";
|
||||||
|
import { useTheme } from "@mui/material";
|
||||||
|
|
||||||
|
export type ImagePublisherRef = {
|
||||||
|
getImageArray: () => string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
interface ImagePublisherProps {
|
||||||
|
initialImages?: string[];
|
||||||
|
}
|
||||||
|
export const ImagePublisher = React.forwardRef<
|
||||||
|
ImagePublisherRef,
|
||||||
|
ImagePublisherProps
|
||||||
|
>(({ initialImages }: ImagePublisherProps, ref) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const [imageArray, setImageArray] = useState<string[]>(initialImages || []);
|
||||||
|
|
||||||
|
useImperativeHandle(ref, () => ({
|
||||||
|
getImageArray: () => {
|
||||||
|
return imageArray;
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{imageArray.length === 0 ? (
|
||||||
|
<ImageUploader onPick={(img: string[]) => setImageArray(img)}>
|
||||||
|
<AddCoverImageButton variant="contained">
|
||||||
|
Add Images
|
||||||
|
<AddLogoIcon
|
||||||
|
sx={{
|
||||||
|
height: "25px",
|
||||||
|
width: "auto",
|
||||||
|
}}
|
||||||
|
></AddLogoIcon>
|
||||||
|
</AddCoverImageButton>
|
||||||
|
</ImageUploader>
|
||||||
|
) : (
|
||||||
|
<LogoPreviewRow>
|
||||||
|
{imageArray.map(
|
||||||
|
image =>
|
||||||
|
image && <CoverImagePreview src={image} alt="logo" key={image} />
|
||||||
|
)}
|
||||||
|
<TimesIcon
|
||||||
|
color={theme.palette.text.primary}
|
||||||
|
onClickFunc={() => setImageArray([])}
|
||||||
|
height={"32"}
|
||||||
|
width={"32"}
|
||||||
|
></TimesIcon>
|
||||||
|
</LogoPreviewRow>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
});
|
109
src/components/common/ImagePublisher/ImageUploader.tsx
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
import React, { useCallback } from "react";
|
||||||
|
import { Box } from "@mui/material";
|
||||||
|
import {
|
||||||
|
DropzoneInputProps,
|
||||||
|
DropzoneRootProps,
|
||||||
|
useDropzone,
|
||||||
|
} from "react-dropzone";
|
||||||
|
import Compressor from "compressorjs";
|
||||||
|
import { setNotification } from "../../../state/features/notificationsSlice.ts";
|
||||||
|
import { useDispatch } from "react-redux";
|
||||||
|
|
||||||
|
const toBase64 = (file: File): Promise<string | ArrayBuffer | null> =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
reader.onload = () => resolve(reader.result);
|
||||||
|
reader.onerror = error => {
|
||||||
|
reject(error);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
interface ImageUploaderProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
onPick: (base64Img: string[]) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ImageUploader: React.FC<ImageUploaderProps> = ({
|
||||||
|
children,
|
||||||
|
onPick,
|
||||||
|
}) => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const imageLimit = 3;
|
||||||
|
|
||||||
|
const compressImages = async (images: File[]) => {
|
||||||
|
const promises = images.map(image => {
|
||||||
|
return new Promise<File | Blob>(resolve => {
|
||||||
|
new Compressor(image, {
|
||||||
|
quality: 0.6,
|
||||||
|
maxWidth: 1200,
|
||||||
|
mimeType: "image/webp",
|
||||||
|
success(result) {
|
||||||
|
const file = new File([result], "name", {
|
||||||
|
type: "image/webp",
|
||||||
|
});
|
||||||
|
resolve(result);
|
||||||
|
},
|
||||||
|
error(err) {},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return await Promise.all(promises);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDrop = useCallback(
|
||||||
|
async (acceptedFiles: File[]) => {
|
||||||
|
if (acceptedFiles.length > imageLimit) {
|
||||||
|
const notificationObj = {
|
||||||
|
msg: `Only ${imageLimit} images can be published`,
|
||||||
|
alertType: "error",
|
||||||
|
};
|
||||||
|
dispatch(setNotification(notificationObj));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const compressedImages = await compressImages(acceptedFiles);
|
||||||
|
if (!compressedImages) return;
|
||||||
|
|
||||||
|
const base64Iamges = await Promise.all(
|
||||||
|
compressedImages.map(image => toBase64(image as File))
|
||||||
|
);
|
||||||
|
|
||||||
|
onPick(base64Iamges as string[]);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[onPick]
|
||||||
|
);
|
||||||
|
|
||||||
|
const {
|
||||||
|
getRootProps,
|
||||||
|
getInputProps,
|
||||||
|
isDragActive,
|
||||||
|
}: {
|
||||||
|
getRootProps: () => DropzoneRootProps;
|
||||||
|
getInputProps: () => DropzoneInputProps;
|
||||||
|
isDragActive: boolean;
|
||||||
|
} = useDropzone({
|
||||||
|
onDrop,
|
||||||
|
accept: {
|
||||||
|
"image/*": [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
{...getRootProps()}
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<input {...getInputProps()} />
|
||||||
|
{children}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ImageUploader;
|
28
src/components/common/ImagePublisher/TimesSVG.tsx
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
export interface IconTypes {
|
||||||
|
color?: string;
|
||||||
|
height: string;
|
||||||
|
width: string;
|
||||||
|
className?: string;
|
||||||
|
onClickFunc?: (e?: any) => void;
|
||||||
|
}
|
||||||
|
export const TimesSVG: React.FC<IconTypes> = ({
|
||||||
|
color,
|
||||||
|
height,
|
||||||
|
width,
|
||||||
|
className,
|
||||||
|
onClickFunc,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
onClick={onClickFunc}
|
||||||
|
className={className}
|
||||||
|
fill={color}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
height={height}
|
||||||
|
viewBox="0 -960 960 960"
|
||||||
|
width={width}
|
||||||
|
>
|
||||||
|
<path d="m249-207-42-42 231-231-231-231 42-42 231 231 231-231 42 42-231 231 231 231-42 42-231-231-231 231Z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
@ -1,89 +0,0 @@
|
|||||||
import React, { useCallback } from 'react'
|
|
||||||
import { Box, Button, TextField, Typography, Modal } from '@mui/material'
|
|
||||||
import {
|
|
||||||
useDropzone,
|
|
||||||
DropzoneRootProps,
|
|
||||||
DropzoneInputProps
|
|
||||||
} from 'react-dropzone'
|
|
||||||
import Compressor from 'compressorjs'
|
|
||||||
|
|
||||||
const toBase64 = (file: File): Promise<string | ArrayBuffer | null> =>
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
const reader = new FileReader()
|
|
||||||
reader.readAsDataURL(file)
|
|
||||||
reader.onload = () => resolve(reader.result)
|
|
||||||
reader.onerror = (error) => {
|
|
||||||
reject(error)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
interface ImageUploaderProps {
|
|
||||||
children: React.ReactNode
|
|
||||||
onPick: (base64Img: string) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
const ImageUploader: React.FC<ImageUploaderProps> = ({ children, onPick }) => {
|
|
||||||
const onDrop = useCallback(
|
|
||||||
async (acceptedFiles: File[]) => {
|
|
||||||
if (acceptedFiles.length > 1) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let compressedFile: File | undefined
|
|
||||||
|
|
||||||
try {
|
|
||||||
const image = acceptedFiles[0]
|
|
||||||
await new Promise<void>((resolve) => {
|
|
||||||
new Compressor(image, {
|
|
||||||
quality: 0.6,
|
|
||||||
maxWidth: 1200,
|
|
||||||
mimeType: 'image/webp',
|
|
||||||
success(result) {
|
|
||||||
const file = new File([result], 'name', {
|
|
||||||
type: 'image/webp'
|
|
||||||
})
|
|
||||||
compressedFile = file
|
|
||||||
resolve()
|
|
||||||
},
|
|
||||||
error(err) {}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
if (!compressedFile) return
|
|
||||||
const base64Img = await toBase64(compressedFile)
|
|
||||||
|
|
||||||
onPick(base64Img as string)
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[onPick]
|
|
||||||
)
|
|
||||||
|
|
||||||
const {
|
|
||||||
getRootProps,
|
|
||||||
getInputProps,
|
|
||||||
isDragActive
|
|
||||||
}: {
|
|
||||||
getRootProps: () => DropzoneRootProps
|
|
||||||
getInputProps: () => DropzoneInputProps
|
|
||||||
isDragActive: boolean
|
|
||||||
} = useDropzone({
|
|
||||||
onDrop,
|
|
||||||
accept: {
|
|
||||||
'image/*': []
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box
|
|
||||||
{...getRootProps()}
|
|
||||||
sx={{
|
|
||||||
display: 'flex'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<input {...getInputProps()} />
|
|
||||||
{children}
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ImageUploader
|
|
@ -14,26 +14,22 @@ export const CustomAppBar = styled(AppBar)(({ theme }) => ({
|
|||||||
borderBottom: `1px solid ${theme.palette.primary.light}`,
|
borderBottom: `1px solid ${theme.palette.primary.light}`,
|
||||||
backgroundColor: theme.palette.background.default,
|
backgroundColor: theme.palette.background.default,
|
||||||
[theme.breakpoints.only("xs")]: {
|
[theme.breakpoints.only("xs")]: {
|
||||||
gap: "15px"
|
gap: "15px",
|
||||||
},
|
},
|
||||||
height: '55px'
|
height: "100px",
|
||||||
}));
|
}));
|
||||||
export const LogoContainer = styled("div")({
|
export const LogoContainer = styled("div")({
|
||||||
cursor: 'pointer',
|
cursor: "pointer",
|
||||||
height: '100%',
|
height: "100%",
|
||||||
display: 'flex',
|
display: "flex",
|
||||||
alignItems: 'center'
|
alignItems: "center",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const CustomTitle = styled(Typography)({
|
export const CustomTitle = styled(Typography)({
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
color: "#000000"
|
color: "#000000",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
export const AuthenticateButton = styled(Button)(({ theme }) => ({
|
export const AuthenticateButton = styled(Button)(({ theme }) => ({
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
@ -50,8 +46,8 @@ export const AuthenticateButton = styled(Button)(({ theme }) => ({
|
|||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
boxShadow: "rgba(0, 0, 0, 0.15) 1.95px 1.95px 2.6px;",
|
boxShadow: "rgba(0, 0, 0, 0.15) 1.95px 1.95px 2.6px;",
|
||||||
backgroundColor: theme.palette.secondary.dark,
|
backgroundColor: theme.palette.secondary.dark,
|
||||||
filter: "brightness(1.1)"
|
filter: "brightness(1.1)",
|
||||||
}
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const AvatarContainer = styled(Box)({
|
export const AvatarContainer = styled(Box)({
|
||||||
@ -61,9 +57,9 @@ export const AvatarContainer = styled(Box)({
|
|||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
"& #expand-icon": {
|
"& #expand-icon": {
|
||||||
transition: "all 0.3s ease-in-out",
|
transition: "all 0.3s ease-in-out",
|
||||||
filter: "brightness(0.7)"
|
filter: "brightness(0.7)",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const DropdownContainer = styled(Box)(({ theme }) => ({
|
export const DropdownContainer = styled(Box)(({ theme }) => ({
|
||||||
@ -76,22 +72,22 @@ export const DropdownContainer = styled(Box)(({ theme }) => ({
|
|||||||
"&:hover": {
|
"&:hover": {
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
filter:
|
filter:
|
||||||
theme.palette.mode === "light" ? "brightness(0.95)" : "brightness(1.1)"
|
theme.palette.mode === "light" ? "brightness(0.95)" : "brightness(1.1)",
|
||||||
}
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const DropdownText = styled(Typography)(({ theme }) => ({
|
export const DropdownText = styled(Typography)(({ theme }) => ({
|
||||||
fontFamily: "Raleway",
|
fontFamily: "Raleway",
|
||||||
fontSize: "16px",
|
fontSize: "16px",
|
||||||
color: theme.palette.text.primary,
|
color: theme.palette.text.primary,
|
||||||
userSelect: "none"
|
userSelect: "none",
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const NavbarName = styled(Typography)(({ theme }) => ({
|
export const NavbarName = styled(Typography)(({ theme }) => ({
|
||||||
fontFamily: "Raleway",
|
fontFamily: "Raleway",
|
||||||
fontSize: "18px",
|
fontSize: "18px",
|
||||||
color: theme.palette.text.primary,
|
color: theme.palette.text.primary,
|
||||||
margin: "0 10px"
|
margin: "0 10px",
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const ThemeSelectRow = styled(Box)({
|
export const ThemeSelectRow = styled(Box)({
|
||||||
@ -99,7 +95,7 @@ export const ThemeSelectRow = styled(Box)({
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
gap: "5px",
|
gap: "5px",
|
||||||
flexBasis: 0,
|
flexBasis: 0,
|
||||||
height: '100%'
|
height: "100%",
|
||||||
});
|
});
|
||||||
|
|
||||||
export const LightModeIcon = styled(LightModeSVG)(({ theme }) => ({
|
export const LightModeIcon = styled(LightModeSVG)(({ theme }) => ({
|
||||||
@ -109,8 +105,8 @@ export const LightModeIcon = styled(LightModeSVG)(({ theme }) => ({
|
|||||||
filter:
|
filter:
|
||||||
theme.palette.mode === "dark"
|
theme.palette.mode === "dark"
|
||||||
? "drop-shadow(0px 4px 6px rgba(255, 255, 255, 0.6))"
|
? "drop-shadow(0px 4px 6px rgba(255, 255, 255, 0.6))"
|
||||||
: "drop-shadow(0px 4px 6px rgba(99, 88, 88, 0.1))"
|
: "drop-shadow(0px 4px 6px rgba(99, 88, 88, 0.1))",
|
||||||
}
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const DarkModeIcon = styled(DarkModeSVG)(({ theme }) => ({
|
export const DarkModeIcon = styled(DarkModeSVG)(({ theme }) => ({
|
||||||
@ -120,6 +116,6 @@ export const DarkModeIcon = styled(DarkModeSVG)(({ theme }) => ({
|
|||||||
filter:
|
filter:
|
||||||
theme.palette.mode === "dark"
|
theme.palette.mode === "dark"
|
||||||
? "drop-shadow(0px 4px 6px rgba(255, 255, 255, 0.6))"
|
? "drop-shadow(0px 4px 6px rgba(255, 255, 255, 0.6))"
|
||||||
: "drop-shadow(0px 4px 6px rgba(99, 88, 88, 0.1))"
|
: "drop-shadow(0px 4px 6px rgba(99, 88, 88, 0.1))",
|
||||||
}
|
},
|
||||||
}));
|
}));
|
||||||
|
@ -1,27 +1,15 @@
|
|||||||
import React, { useState, useRef } from "react";
|
import React, { useRef, useState } from "react";
|
||||||
import {
|
import { Box, Input, Popover, Typography, useTheme } from "@mui/material";
|
||||||
Box,
|
|
||||||
Button,
|
|
||||||
Input,
|
|
||||||
Popover,
|
|
||||||
Typography,
|
|
||||||
useTheme,
|
|
||||||
} from "@mui/material";
|
|
||||||
import ExitToAppIcon from "@mui/icons-material/ExitToApp";
|
|
||||||
import { BlockedNamesModal } from "../../common/BlockedNamesModal/BlockedNamesModal";
|
import { BlockedNamesModal } from "../../common/BlockedNamesModal/BlockedNamesModal";
|
||||||
import AddBoxIcon from "@mui/icons-material/AddBox";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AvatarContainer,
|
AvatarContainer,
|
||||||
CustomAppBar,
|
CustomAppBar,
|
||||||
DropdownContainer,
|
DropdownContainer,
|
||||||
DropdownText,
|
DropdownText,
|
||||||
AuthenticateButton,
|
|
||||||
NavbarName,
|
|
||||||
LightModeIcon,
|
|
||||||
DarkModeIcon,
|
|
||||||
ThemeSelectRow,
|
|
||||||
LogoContainer,
|
LogoContainer,
|
||||||
|
NavbarName,
|
||||||
|
ThemeSelectRow,
|
||||||
} from "./Navbar-styles";
|
} from "./Navbar-styles";
|
||||||
import { AccountCircleSVG } from "../../../assets/svgs/AccountCircleSVG";
|
import { AccountCircleSVG } from "../../../assets/svgs/AccountCircleSVG";
|
||||||
import BackspaceIcon from "@mui/icons-material/Backspace";
|
import BackspaceIcon from "@mui/icons-material/Backspace";
|
||||||
@ -32,18 +20,17 @@ import { useNavigate } from "react-router-dom";
|
|||||||
import SearchIcon from "@mui/icons-material/Search";
|
import SearchIcon from "@mui/icons-material/Search";
|
||||||
|
|
||||||
import { DownloadTaskManager } from "../../common/DownloadTaskManager";
|
import { DownloadTaskManager } from "../../common/DownloadTaskManager";
|
||||||
import QShareLogo from "../../../assets/img/q-share-icon.webp";
|
import QSupportLogo from "../../../assets/img/Q-SupportIcon.webp";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import {
|
import {
|
||||||
addFilteredFiles,
|
addFilteredFiles,
|
||||||
setEditPlaylist,
|
|
||||||
setFilterValue,
|
setFilterValue,
|
||||||
setIsFiltering,
|
setIsFiltering,
|
||||||
} from "../../../state/features/fileSlice.ts";
|
} from "../../../state/features/fileSlice.ts";
|
||||||
import { RootState } from "../../../state/store";
|
import { RootState } from "../../../state/store";
|
||||||
import { useWindowSize } from "../../../hooks/useWindowSize";
|
import { useWindowSize } from "../../../hooks/useWindowSize";
|
||||||
import { PublishFile } from "../../PublishFile/PublishFile.tsx";
|
import { PublishIssue } from "../../PublishIssue/PublishIssue.tsx";
|
||||||
import { StyledButton } from "../../PublishFile/Upload-styles.tsx";
|
|
||||||
interface Props {
|
interface Props {
|
||||||
isAuthenticated: boolean;
|
isAuthenticated: boolean;
|
||||||
userName: string | null;
|
userName: string | null;
|
||||||
@ -125,21 +112,21 @@ const NavBar: React.FC<Props> = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src={QShareLogo}
|
src={QSupportLogo}
|
||||||
style={{
|
style={{
|
||||||
width: "auto",
|
width: "auto",
|
||||||
height: "55px",
|
height: "100px",
|
||||||
padding: "2px",
|
padding: "2px",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</LogoContainer>
|
</LogoContainer>
|
||||||
<Typography
|
<Typography
|
||||||
sx={{
|
sx={{
|
||||||
fontSize: "16px",
|
fontSize: "30px",
|
||||||
whiteSpace: "nowrap",
|
whiteSpace: "nowrap",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Sharing is caring
|
Welcome to Q-Support
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</ThemeSelectRow>
|
</ThemeSelectRow>
|
||||||
@ -150,135 +137,6 @@ const NavBar: React.FC<Props> = ({
|
|||||||
gap: "10px",
|
gap: "10px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* {windowSize.width <= 600 ? (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: 1
|
|
||||||
}}
|
|
||||||
className="myClassOver600"
|
|
||||||
|
|
||||||
|
|
||||||
>
|
|
||||||
<Box onClick={openNotificationPopover}>
|
|
||||||
<SearchIcon
|
|
||||||
sx={{
|
|
||||||
cursor: 'pointer',
|
|
||||||
display: 'flex'
|
|
||||||
}}
|
|
||||||
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
{filterValue && (
|
|
||||||
<BackspaceIcon
|
|
||||||
sx={{
|
|
||||||
cursor: 'pointer'
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
dispatch(setIsFiltering(false))
|
|
||||||
dispatch(setFilterValue(''))
|
|
||||||
dispatch(addFilteredVideos([]))
|
|
||||||
searchValRef.current = ''
|
|
||||||
if (!inputRef.current) return
|
|
||||||
inputRef.current.value = ''
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
</Box>
|
|
||||||
): (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: 1
|
|
||||||
}}
|
|
||||||
className="myClassUnder600"
|
|
||||||
>
|
|
||||||
<Input
|
|
||||||
id="standard-adornment-name"
|
|
||||||
inputRef={inputRef}
|
|
||||||
onChange={(e) => {
|
|
||||||
searchValRef.current = e.target.value
|
|
||||||
}}
|
|
||||||
onKeyDown={(event) => {
|
|
||||||
if (event.key === 'Enter' || event.keyCode === 13) {
|
|
||||||
if (!searchValRef.current) {
|
|
||||||
dispatch(setIsFiltering(false))
|
|
||||||
dispatch(setFilterValue(''))
|
|
||||||
dispatch(addFilteredVideos([]))
|
|
||||||
searchValRef.current = ''
|
|
||||||
if (!inputRef.current) return
|
|
||||||
inputRef.current.value = ''
|
|
||||||
return
|
|
||||||
}
|
|
||||||
navigate('/')
|
|
||||||
dispatch(setIsFiltering(true))
|
|
||||||
dispatch(addFilteredVideos([]))
|
|
||||||
dispatch(setFilterValue(searchValRef.current))
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
placeholder="Search"
|
|
||||||
sx={{
|
|
||||||
'&&:before': {
|
|
||||||
borderBottom: 'none'
|
|
||||||
},
|
|
||||||
'&&:after': {
|
|
||||||
borderBottom: 'none'
|
|
||||||
},
|
|
||||||
'&&:hover:before': {
|
|
||||||
borderBottom: 'none'
|
|
||||||
},
|
|
||||||
'&&.Mui-focused:before': {
|
|
||||||
borderBottom: 'none'
|
|
||||||
},
|
|
||||||
'&&.Mui-focused': {
|
|
||||||
outline: 'none'
|
|
||||||
},
|
|
||||||
fontSize: '18px'
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<SearchIcon
|
|
||||||
sx={{
|
|
||||||
cursor: 'pointer'
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
if (!searchValRef.current) {
|
|
||||||
dispatch(setIsFiltering(false))
|
|
||||||
dispatch(setFilterValue(''))
|
|
||||||
dispatch(addFilteredVideos([]))
|
|
||||||
searchValRef.current = ''
|
|
||||||
if (!inputRef.current) return
|
|
||||||
inputRef.current.value = ''
|
|
||||||
return
|
|
||||||
}
|
|
||||||
navigate('/')
|
|
||||||
dispatch(setIsFiltering(true))
|
|
||||||
dispatch(addFilteredVideos([]))
|
|
||||||
dispatch(setFilterValue(searchValRef.current))
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{filterValue && (
|
|
||||||
<BackspaceIcon
|
|
||||||
sx={{
|
|
||||||
cursor: 'pointer'
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
dispatch(setIsFiltering(false))
|
|
||||||
dispatch(setFilterValue(''))
|
|
||||||
dispatch(addFilteredVideos([]))
|
|
||||||
searchValRef.current = ''
|
|
||||||
if (!inputRef.current) return
|
|
||||||
inputRef.current.value = ''
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
</Box>
|
|
||||||
)} */}
|
|
||||||
|
|
||||||
<Popover
|
<Popover
|
||||||
id={idNotification}
|
id={idNotification}
|
||||||
open={openPopover}
|
open={openPopover}
|
||||||
@ -411,7 +269,7 @@ const NavBar: React.FC<Props> = ({
|
|||||||
<AvatarContainer>
|
<AvatarContainer>
|
||||||
{isAuthenticated && userName && (
|
{isAuthenticated && userName && (
|
||||||
<>
|
<>
|
||||||
<PublishFile />
|
<PublishIssue />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</AvatarContainer>
|
</AvatarContainer>
|
||||||
|
@ -7,15 +7,6 @@ import softwareIcon from "../../assets/icons/software.webp";
|
|||||||
import unknownIcon from "../../assets/icons/unknown.webp";
|
import unknownIcon from "../../assets/icons/unknown.webp";
|
||||||
import videoIcon from "../../assets/icons/video.webp";
|
import videoIcon from "../../assets/icons/video.webp";
|
||||||
|
|
||||||
import {
|
|
||||||
audioSubCategories,
|
|
||||||
bookSubCategories,
|
|
||||||
documentSubCategories,
|
|
||||||
imageSubCategories,
|
|
||||||
softwareSubCategories,
|
|
||||||
videoSubCategories,
|
|
||||||
} from "./2ndCategories.ts";
|
|
||||||
import { musicSubCategories } from "./3rdCategories.ts";
|
|
||||||
import {
|
import {
|
||||||
Categories,
|
Categories,
|
||||||
Category,
|
Category,
|
||||||
@ -25,30 +16,30 @@ import {
|
|||||||
getAllCategoriesWithIcons,
|
getAllCategoriesWithIcons,
|
||||||
sortCategory,
|
sortCategory,
|
||||||
} from "./CategoryFunctions.ts";
|
} from "./CategoryFunctions.ts";
|
||||||
|
import { QappCategories, SupportState } from "./2ndCategories.ts";
|
||||||
|
|
||||||
export const firstCategories: Category[] = [
|
export const firstCategories: Category[] = [
|
||||||
{ id: 1, name: "Software", icon: softwareIcon },
|
{ id: 1, name: "Core" },
|
||||||
{ id: 2, name: "Gaming", icon: gamingIcon },
|
{ id: 2, name: "UI" },
|
||||||
{ id: 3, name: "Audio", icon: audioIcon },
|
{ id: 3, name: "Q-Apps" },
|
||||||
{ id: 4, name: "Video", icon: videoIcon },
|
{ id: 4, name: "Website" },
|
||||||
{ id: 5, name: "Image", icon: imageIcon },
|
{ id: 5, name: "Marketing" },
|
||||||
{ id: 6, name: "Document", icon: documentIcon },
|
{ id: 99, name: "Other" },
|
||||||
{ id: 7, name: "Book", icon: bookIcon },
|
];
|
||||||
{ id: 99, name: "Other", icon: unknownIcon },
|
|
||||||
].sort(sortCategory);
|
|
||||||
export const secondCategories: Categories = {
|
export const secondCategories: Categories = {
|
||||||
1: softwareSubCategories.sort(sortCategory),
|
1: SupportState,
|
||||||
3: audioSubCategories.sort(sortCategory),
|
2: SupportState,
|
||||||
4: videoSubCategories.sort(sortCategory),
|
3: QappCategories,
|
||||||
5: imageSubCategories.sort(sortCategory),
|
4: SupportState,
|
||||||
6: documentSubCategories.sort(sortCategory),
|
5: SupportState,
|
||||||
7: bookSubCategories.sort(sortCategory),
|
99: SupportState,
|
||||||
};
|
|
||||||
|
|
||||||
export const thirdCategories: Categories = {
|
|
||||||
301: musicSubCategories,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export let thirdCategories: Categories = {};
|
||||||
|
QappCategories.map(
|
||||||
|
supportStateCategory =>
|
||||||
|
(thirdCategories[supportStateCategory.id] = SupportState)
|
||||||
|
);
|
||||||
export const allCategoryData: CategoryData = {
|
export const allCategoryData: CategoryData = {
|
||||||
category: firstCategories,
|
category: firstCategories,
|
||||||
subCategories: [secondCategories, thirdCategories],
|
subCategories: [secondCategories, thirdCategories],
|
||||||
|
@ -1,88 +1,23 @@
|
|||||||
export const softwareSubCategories = [
|
import OpenIcon from "../../assets/icons/OpenIcon.png";
|
||||||
{ id: 101, name: "OS" },
|
import ClosedIcon from "../../assets/icons/ClosedIcon.png";
|
||||||
{ id: 102, name: "Application" },
|
import InProgressIcon from "../../assets/icons/InProgressIcon.png";
|
||||||
{ id: 103, name: "Source Code" },
|
import CompleteIcon from "../../assets/icons/CompleteIcon.png";
|
||||||
{ id: 104, name: "Plugin" },
|
|
||||||
{ id: 199, name: "Other" },
|
export const SupportState = [
|
||||||
|
{ id: 101, name: "Open", icon: OpenIcon },
|
||||||
|
{ id: 102, name: "Closed", icon: ClosedIcon },
|
||||||
|
{ id: 103, name: "In Progress", icon: InProgressIcon },
|
||||||
|
{ id: 104, name: "Complete", icon: CompleteIcon },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const audioSubCategories = [
|
export const QappCategories = [
|
||||||
{ id: 301, name: "Music" },
|
{ id: 301, name: "Q-Blog" },
|
||||||
{ id: 302, name: "Podcast" },
|
{ id: 302, name: "Q-Mail" },
|
||||||
{ id: 303, name: "Audiobook" },
|
{ id: 303, name: "Q-Shop" },
|
||||||
{ id: 304, name: "Sound Effect" },
|
{ id: 304, name: "Q-Fund" },
|
||||||
{ id: 305, name: "Lecture or Speech" },
|
{ id: 305, name: "Ear-Bump" },
|
||||||
{ id: 306, name: "Radio Show" },
|
{ id: 306, name: "Q-Tube" },
|
||||||
{ id: 307, name: "Ambient Sound" },
|
{ id: 307, name: "Q-Share" },
|
||||||
{ id: 308, name: "Language Learning Material" },
|
{ id: 308, name: "Q-Support" },
|
||||||
{ id: 309, name: "Comedy & Satire" },
|
|
||||||
{ id: 310, name: "Documentary" },
|
|
||||||
{ id: 311, name: "Guided Meditation & Yoga" },
|
|
||||||
{ id: 312, name: "Live Performance" },
|
|
||||||
{ id: 313, name: "Nature Sound" },
|
|
||||||
{ id: 314, name: "Soundtrack" },
|
|
||||||
{ id: 315, name: "Interview" },
|
|
||||||
{ id: 399, name: "Other" },
|
{ id: 399, name: "Other" },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const videoSubCategories = [
|
|
||||||
{ id: 404, name: "Education" },
|
|
||||||
{ id: 405, name: "Lifestyle" },
|
|
||||||
{ id: 406, name: "Gaming" },
|
|
||||||
{ id: 407, name: "Technology" },
|
|
||||||
{ id: 408, name: "Sports" },
|
|
||||||
{ id: 409, name: "News & Politics" },
|
|
||||||
{ id: 410, name: "Cooking & Food" },
|
|
||||||
{ id: 411, name: "Animation" },
|
|
||||||
{ id: 412, name: "Science" },
|
|
||||||
{ id: 413, name: "Health & Wellness" },
|
|
||||||
{ id: 414, name: "DIY & Crafts" },
|
|
||||||
{ id: 415, name: "Kids & Family" },
|
|
||||||
{ id: 416, name: "Comedy" },
|
|
||||||
{ id: 417, name: "Travel & Adventure" },
|
|
||||||
{ id: 418, name: "Art & Design" },
|
|
||||||
{ id: 419, name: "Nature & Environment" },
|
|
||||||
{ id: 420, name: "Business & Finance" },
|
|
||||||
{ id: 421, name: "Personal Development" },
|
|
||||||
{ id: 423, name: "History" },
|
|
||||||
{ id: 499, name: "Other" },
|
|
||||||
];
|
|
||||||
|
|
||||||
export const imageSubCategories = [
|
|
||||||
{ id: 501, name: "Nature" },
|
|
||||||
{ id: 502, name: "Urban & Cityscapes" },
|
|
||||||
{ id: 503, name: "People & Portraits" },
|
|
||||||
{ id: 504, name: "Art & Abstract" },
|
|
||||||
{ id: 505, name: "Travel & Adventure" },
|
|
||||||
{ id: 506, name: "Animals & Wildlife" },
|
|
||||||
{ id: 507, name: "Sports & Action" },
|
|
||||||
{ id: 508, name: "Food & Cuisine" },
|
|
||||||
{ id: 509, name: "Fashion & Beauty" },
|
|
||||||
{ id: 510, name: "Technology & Science" },
|
|
||||||
{ id: 511, name: "Historical & Cultural" },
|
|
||||||
{ id: 512, name: "Aerial & Drone" },
|
|
||||||
{ id: 513, name: "Black & White" },
|
|
||||||
{ id: 514, name: "Events & Celebrations" },
|
|
||||||
{ id: 515, name: "Business & Corporate" },
|
|
||||||
{ id: 516, name: "Health & Wellness" },
|
|
||||||
{ id: 517, name: "Transportation & Vehicles" },
|
|
||||||
{ id: 518, name: "Still Life & Objects" },
|
|
||||||
{ id: 519, name: "Architecture & Buildings" },
|
|
||||||
{ id: 520, name: "Landscapes & Seascapes" },
|
|
||||||
{ id: 599, name: "Other" },
|
|
||||||
];
|
|
||||||
|
|
||||||
export const documentSubCategories = [
|
|
||||||
{ id: 601, name: "PDF" },
|
|
||||||
{ id: 602, name: "Word Document" },
|
|
||||||
{ id: 603, name: "Spreadsheet" },
|
|
||||||
{ id: 604, name: "Powerpoint" },
|
|
||||||
{ id: 699, name: "Other" },
|
|
||||||
];
|
|
||||||
|
|
||||||
export const bookSubCategories = [
|
|
||||||
{ id: 701, name: "Audiobook" },
|
|
||||||
{ id: 702, name: "Comic" },
|
|
||||||
{ id: 703, name: "Magazine" },
|
|
||||||
{ id: 799, name: "Other" },
|
|
||||||
];
|
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
export const musicSubCategories = [
|
|
||||||
{ id: 30101, name: "Rock" },
|
|
||||||
{ id: 30102, name: "Pop" },
|
|
||||||
{ id: 30103, name: "Classical" },
|
|
||||||
{ id: 30104, name: "Jazz" },
|
|
||||||
{ id: 30105, name: "Electronic" },
|
|
||||||
{ id: 30106, name: "Country" },
|
|
||||||
{ id: 30107, name: "Hip Hop/Rap" },
|
|
||||||
{ id: 30108, name: "Blues" },
|
|
||||||
{ id: 30109, name: "R&B/Soul" },
|
|
||||||
{ id: 30110, name: "Reggae" },
|
|
||||||
{ id: 30111, name: "Folk" },
|
|
||||||
{ id: 30112, name: "Metal" },
|
|
||||||
{ id: 30113, name: "World Music" },
|
|
||||||
{ id: 30114, name: "Latin" },
|
|
||||||
{ id: 30115, name: "Indie" },
|
|
||||||
{ id: 30116, name: "Punk" },
|
|
||||||
{ id: 30117, name: "Soundtracks" },
|
|
||||||
{ id: 30118, name: "Children's Music" },
|
|
||||||
{ id: 30119, name: "New Age" },
|
|
||||||
{ id: 30120, name: "Classical Crossover" },
|
|
||||||
{ id: 30199, name: "Other" },
|
|
||||||
];
|
|
@ -1,13 +1,13 @@
|
|||||||
const useTestIdentifiers = false;
|
const useTestIdentifiers = false;
|
||||||
|
|
||||||
export const QSHARE_FILE_BASE = useTestIdentifiers
|
export const QSUPPORT_FILE_BASE = useTestIdentifiers
|
||||||
? "MYTEST_share_vid_"
|
? "MYTEST_support_issue_"
|
||||||
: "qshare_file_";
|
: "q_support_issue_";
|
||||||
|
|
||||||
export const QSHARE_PLAYLIST_BASE = useTestIdentifiers
|
export const QSUPPORT_PLAYLIST_BASE = useTestIdentifiers
|
||||||
? "MYTEST_share_playlist_"
|
? "MYTEST_support_playlist_"
|
||||||
: "qshare_playlist_";
|
: "q_support_playlist_";
|
||||||
|
|
||||||
export const QSHARE_COMMENT_BASE = useTestIdentifiers
|
export const QSUPPORT_COMMENT_BASE = useTestIdentifiers
|
||||||
? "qcomment_v1_MYTEST_"
|
? "qcomment_v1_MYTEST_support_"
|
||||||
: "qcomment_v1_qshare_";
|
: "qcomment_v1_q_support_";
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
export const minPriceSuperlike = 10;
|
export const minPriceSuperlike = 10;
|
||||||
export const titleFormatter = /[^a-zA-Z0-9\s-_!?()&'",.;:|—~@#$%^*+=<>]/g;
|
export const titleFormatter = /[^a-zA-Z0-9\s-_!?()&'",.;:|—~@#$%^*+=<>]/g;
|
||||||
export const titleFormatterOnSave = /[^a-zA-Z0-9\s-_!()&',.;—~@#$%^+=]/g;
|
export const titleFormatterOnSave = /[^a-zA-Z0-9\s-_!()&',.;—~@#$%^+=]/g;
|
||||||
|
|
||||||
|
export const log = false;
|
||||||
|
@ -19,8 +19,8 @@ import {
|
|||||||
import { RootState } from "../state/store";
|
import { RootState } from "../state/store";
|
||||||
import { fetchAndEvaluateVideos } from "../utils/fetchVideos";
|
import { fetchAndEvaluateVideos } from "../utils/fetchVideos";
|
||||||
import {
|
import {
|
||||||
QSHARE_PLAYLIST_BASE,
|
QSUPPORT_PLAYLIST_BASE,
|
||||||
QSHARE_FILE_BASE,
|
QSUPPORT_FILE_BASE,
|
||||||
} from "../constants/Identifiers.ts";
|
} from "../constants/Identifiers.ts";
|
||||||
import { RequestQueue } from "../utils/queue";
|
import { RequestQueue } from "../utils/queue";
|
||||||
import { queue } from "../wrappers/GlobalWrapper";
|
import { queue } from "../wrappers/GlobalWrapper";
|
||||||
@ -114,7 +114,7 @@ export const useFetchFiles = () => {
|
|||||||
try {
|
try {
|
||||||
dispatch(setIsLoadingGlobal(true));
|
dispatch(setIsLoadingGlobal(true));
|
||||||
|
|
||||||
const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QSHARE_FILE_BASE}&limit=20&includemetadata=false&reverse=true&excludeblocked=true&exactmatchnames=true`;
|
const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QSUPPORT_FILE_BASE}&limit=20&includemetadata=false&reverse=true&excludeblocked=true&exactmatchnames=true`;
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
@ -218,10 +218,10 @@ export const useFetchFiles = () => {
|
|||||||
}
|
}
|
||||||
if (type === "playlists") {
|
if (type === "playlists") {
|
||||||
defaultUrl = defaultUrl + `&service=PLAYLIST`;
|
defaultUrl = defaultUrl + `&service=PLAYLIST`;
|
||||||
defaultUrl = defaultUrl + `&identifier=${QSHARE_PLAYLIST_BASE}`;
|
defaultUrl = defaultUrl + `&identifier=${QSUPPORT_PLAYLIST_BASE}`;
|
||||||
} else {
|
} else {
|
||||||
defaultUrl = defaultUrl + `&service=DOCUMENT`;
|
defaultUrl = defaultUrl + `&service=DOCUMENT`;
|
||||||
defaultUrl = defaultUrl + `&identifier=${QSHARE_FILE_BASE}`;
|
defaultUrl = defaultUrl + `&identifier=${QSUPPORT_FILE_BASE}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QTUBE_VIDEO_BASE}&limit=${videoLimit}&includemetadata=false&reverse=true&excludeblocked=true&exactmatchnames=true&offset=${offset}`
|
// const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QTUBE_VIDEO_BASE}&limit=${videoLimit}&includemetadata=false&reverse=true&excludeblocked=true&exactmatchnames=true&offset=${offset}`
|
||||||
@ -289,7 +289,7 @@ export const useFetchFiles = () => {
|
|||||||
const offset = filteredVideos.length;
|
const offset = filteredVideos.length;
|
||||||
const replaceSpacesWithUnderscore = filterValue.replace(/ /g, "_");
|
const replaceSpacesWithUnderscore = filterValue.replace(/ /g, "_");
|
||||||
|
|
||||||
const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${replaceSpacesWithUnderscore}&identifier=${QSHARE_FILE_BASE}&limit=10&includemetadata=false&reverse=true&excludeblocked=true&exactmatchnames=true&offset=${offset}`;
|
const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${replaceSpacesWithUnderscore}&identifier=${QSUPPORT_FILE_BASE}&limit=10&includemetadata=false&reverse=true&excludeblocked=true&exactmatchnames=true&offset=${offset}`;
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
@ -345,7 +345,7 @@ export const useFetchFiles = () => {
|
|||||||
|
|
||||||
const checkNewFiles = React.useCallback(async () => {
|
const checkNewFiles = React.useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QSHARE_FILE_BASE}&limit=20&includemetadata=false&reverse=true&excludeblocked=true&exactmatchnames=true`;
|
const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QSUPPORT_FILE_BASE}&limit=20&includemetadata=false&reverse=true&excludeblocked=true&exactmatchnames=true`;
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
@ -382,7 +382,7 @@ export const useFetchFiles = () => {
|
|||||||
|
|
||||||
const getFilesCount = React.useCallback(async () => {
|
const getFilesCount = React.useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
let url = `/arbitrary/resources/search?mode=ALL&includemetadata=false&limit=0&service=DOCUMENT&identifier=${QSHARE_FILE_BASE}`;
|
let url = `/arbitrary/resources/search?mode=ALL&includemetadata=false&limit=0&service=DOCUMENT&identifier=${QSUPPORT_FILE_BASE}`;
|
||||||
|
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
@ -2,12 +2,12 @@ import { Avatar, Box, Skeleton, Tooltip } from "@mui/material";
|
|||||||
import {
|
import {
|
||||||
BlockIconContainer,
|
BlockIconContainer,
|
||||||
BottomParent,
|
BottomParent,
|
||||||
|
FileContainer,
|
||||||
IconsBox,
|
IconsBox,
|
||||||
NameContainer,
|
NameContainer,
|
||||||
VideoCard,
|
VideoCard,
|
||||||
VideoCardName,
|
VideoCardName,
|
||||||
VideoCardTitle,
|
VideoCardTitle,
|
||||||
FileContainer,
|
|
||||||
VideoUploadDate,
|
VideoUploadDate,
|
||||||
} from "./FileList-styles.tsx";
|
} from "./FileList-styles.tsx";
|
||||||
import EditIcon from "@mui/icons-material/Edit";
|
import EditIcon from "@mui/icons-material/Edit";
|
||||||
@ -18,7 +18,7 @@ import {
|
|||||||
} from "../../state/features/fileSlice.ts";
|
} from "../../state/features/fileSlice.ts";
|
||||||
import BlockIcon from "@mui/icons-material/Block";
|
import BlockIcon from "@mui/icons-material/Block";
|
||||||
import AttachFileIcon from "@mui/icons-material/AttachFile";
|
import AttachFileIcon from "@mui/icons-material/AttachFile";
|
||||||
import { formatBytes } from "../FileContent/FileContent.tsx";
|
import { formatBytes } from "../IssueContent/IssueContent.tsx";
|
||||||
import { formatDate } from "../../utils/time.ts";
|
import { formatDate } from "../../utils/time.ts";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
@ -88,7 +88,7 @@ export const FileList = ({ files }: FileListProps) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{fileObj?.user === username && (
|
{fileObj?.user === username && (
|
||||||
<Tooltip title="Edit video properties" placement="top">
|
<Tooltip title="Edit Issue Properties" placement="top">
|
||||||
<BlockIconContainer>
|
<BlockIconContainer>
|
||||||
<EditIcon
|
<EditIcon
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -19,8 +19,8 @@ import {
|
|||||||
import { formatDate } from "../../utils/time";
|
import { formatDate } from "../../utils/time";
|
||||||
import { Video } from "../../state/features/fileSlice.ts";
|
import { Video } from "../../state/features/fileSlice.ts";
|
||||||
import { queue } from "../../wrappers/GlobalWrapper";
|
import { queue } from "../../wrappers/GlobalWrapper";
|
||||||
import { QSHARE_FILE_BASE } from "../../constants/Identifiers.ts";
|
import { QSUPPORT_FILE_BASE } from "../../constants/Identifiers.ts";
|
||||||
import { formatBytes } from "../FileContent/FileContent.tsx";
|
import { formatBytes } from "../IssueContent/IssueContent.tsx";
|
||||||
import { getIconsFromObject } from "../../constants/Categories/CategoryFunctions.ts";
|
import { getIconsFromObject } from "../../constants/Categories/CategoryFunctions.ts";
|
||||||
|
|
||||||
interface VideoListProps {
|
interface VideoListProps {
|
||||||
@ -46,7 +46,7 @@ export const FileListComponentLevel = ({ mode }: VideoListProps) => {
|
|||||||
const getVideos = React.useCallback(async () => {
|
const getVideos = React.useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
const offset = videos.length;
|
const offset = videos.length;
|
||||||
const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QSHARE_FILE_BASE}_&limit=50&includemetadata=false&reverse=true&excludeblocked=true&name=${paramName}&exactmatchnames=true&offset=${offset}`;
|
const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QSUPPORT_FILE_BASE}_&limit=50&includemetadata=false&reverse=true&excludeblocked=true&name=${paramName}&exactmatchnames=true&offset=${offset}`;
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
|
@ -275,6 +275,8 @@ export const Home = ({ mode }: HomeProps) => {
|
|||||||
}}
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
marginTop: "20px",
|
marginTop: "20px",
|
||||||
|
fontWeight: 1000,
|
||||||
|
color: "white",
|
||||||
}}
|
}}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
>
|
>
|
||||||
@ -286,6 +288,8 @@ export const Home = ({ mode }: HomeProps) => {
|
|||||||
}}
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
marginTop: "20px",
|
marginTop: "20px",
|
||||||
|
fontWeight: 1000,
|
||||||
|
color: "white",
|
||||||
}}
|
}}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
>
|
>
|
||||||
|
@ -5,11 +5,10 @@ import {
|
|||||||
AuthorTextComment,
|
AuthorTextComment,
|
||||||
StyledCardColComment,
|
StyledCardColComment,
|
||||||
StyledCardHeaderComment,
|
StyledCardHeaderComment,
|
||||||
} from "../FileContent/FileContent-styles.tsx";
|
} from "../IssueContent/IssueContent-styles.tsx";
|
||||||
import { Avatar, Box, useTheme } from "@mui/material";
|
import { Avatar, Box, useTheme } from "@mui/material";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { setUserAvatarHash } from "../../state/features/globalSlice";
|
|
||||||
import { RootState } from "../../state/store";
|
import { RootState } from "../../state/store";
|
||||||
|
|
||||||
export const IndividualProfile = () => {
|
export const IndividualProfile = () => {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { styled } from "@mui/system";
|
import { styled } from "@mui/system";
|
||||||
import { Box, Grid, Typography, Checkbox } from "@mui/material";
|
import { Box, Typography } from "@mui/material";
|
||||||
|
|
||||||
export const FilePlayerContainer = styled(Box)(({ theme }) => ({
|
export const FilePlayerContainer = styled(Box)(({ theme }) => ({
|
||||||
maxWidth: "95%",
|
maxWidth: "95%",
|
||||||
@ -25,6 +25,10 @@ export const FileDescription = styled(Typography)(({ theme }) => ({
|
|||||||
wordBreak: "break-word",
|
wordBreak: "break-word",
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
export const ImageContainer = styled(Box)(({ theme }) => ({
|
||||||
|
display: "flex",
|
||||||
|
}));
|
||||||
|
|
||||||
export const Spacer = ({ height }: any) => {
|
export const Spacer = ({ height }: any) => {
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
@ -14,29 +14,22 @@ import {
|
|||||||
FileDescription,
|
FileDescription,
|
||||||
FilePlayerContainer,
|
FilePlayerContainer,
|
||||||
FileTitle,
|
FileTitle,
|
||||||
|
ImageContainer,
|
||||||
Spacer,
|
Spacer,
|
||||||
StyledCardColComment,
|
StyledCardColComment,
|
||||||
StyledCardHeaderComment,
|
StyledCardHeaderComment,
|
||||||
} from "./FileContent-styles.tsx";
|
} from "./IssueContent-styles.tsx";
|
||||||
import { formatDate } from "../../utils/time";
|
import { formatDate } from "../../utils/time";
|
||||||
import { CommentSection } from "../../components/common/Comments/CommentSection";
|
import { CommentSection } from "../../components/common/Comments/CommentSection";
|
||||||
import { QSHARE_FILE_BASE } from "../../constants/Identifiers.ts";
|
import { QSUPPORT_FILE_BASE } from "../../constants/Identifiers.ts";
|
||||||
import { DisplayHtml } from "../../components/common/TextEditor/DisplayHtml";
|
import { DisplayHtml } from "../../components/common/TextEditor/DisplayHtml";
|
||||||
import FileElement from "../../components/common/FileElement";
|
import FileElement from "../../components/common/FileElement";
|
||||||
import {
|
import { allCategoryData } from "../../constants/Categories/1stCategories.ts";
|
||||||
allCategoryData,
|
|
||||||
iconCategories,
|
|
||||||
} from "../../constants/Categories/1stCategories.ts";
|
|
||||||
import {
|
import {
|
||||||
Category,
|
Category,
|
||||||
getCategoriesFromObject,
|
getCategoriesFromObject,
|
||||||
} from "../../components/common/CategoryList/CategoryList.tsx";
|
} from "../../components/common/CategoryList/CategoryList.tsx";
|
||||||
import {
|
import { getIconsFromObject } from "../../constants/Categories/CategoryFunctions.ts";
|
||||||
findAllCategoryData,
|
|
||||||
findCategoryData,
|
|
||||||
getCategoriesWithIcons,
|
|
||||||
getIconsFromObject,
|
|
||||||
} from "../../constants/Categories/CategoryFunctions.ts";
|
|
||||||
|
|
||||||
export function formatBytes(bytes, decimals = 2) {
|
export function formatBytes(bytes, decimals = 2) {
|
||||||
if (bytes === 0) return "0 Bytes";
|
if (bytes === 0) return "0 Bytes";
|
||||||
@ -50,7 +43,7 @@ export function formatBytes(bytes, decimals = 2) {
|
|||||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FileContent = () => {
|
export const IssueContent = () => {
|
||||||
const { name, id } = useParams();
|
const { name, id } = useParams();
|
||||||
const [isExpandedDescription, setIsExpandedDescription] =
|
const [isExpandedDescription, setIsExpandedDescription] =
|
||||||
useState<boolean>(false);
|
useState<boolean>(false);
|
||||||
@ -106,7 +99,7 @@ export const FileContent = () => {
|
|||||||
if (!name || !id) return;
|
if (!name || !id) return;
|
||||||
dispatch(setIsLoadingGlobal(true));
|
dispatch(setIsLoadingGlobal(true));
|
||||||
|
|
||||||
const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QSHARE_FILE_BASE}&limit=1&includemetadata=true&reverse=true&excludeblocked=true&name=${name}&exactmatchnames=true&offset=0&identifier=${id}`;
|
const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QSUPPORT_FILE_BASE}&limit=1&includemetadata=true&reverse=true&excludeblocked=true&name=${name}&exactmatchnames=true&offset=0&identifier=${id}`;
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
@ -272,8 +265,6 @@ export const FileContent = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fileData) {
|
if (fileData) {
|
||||||
//const icon = getIconsFromObject(fileData)[0]?.icon || null;
|
|
||||||
|
|
||||||
const icon = getIconsFromObject(fileData);
|
const icon = getIconsFromObject(fileData);
|
||||||
setIcon(icon);
|
setIcon(icon);
|
||||||
}
|
}
|
||||||
@ -415,6 +406,19 @@ export const FileContent = () => {
|
|||||||
{categoriesDisplay}
|
{categoriesDisplay}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
<ImageContainer>
|
||||||
|
{fileData?.images &&
|
||||||
|
fileData.images.map(image => {
|
||||||
|
return (
|
||||||
|
<img
|
||||||
|
src={image}
|
||||||
|
width={`${1280 / fileData.images.length}px`}
|
||||||
|
height={"480px"}
|
||||||
|
style={{ marginRight: "10px", marginBottom: "10px" }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ImageContainer>
|
||||||
<Spacer height="15px" />
|
<Spacer height="15px" />
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
@ -11,38 +11,38 @@ const commonThemeOptions = {
|
|||||||
"Oxygen",
|
"Oxygen",
|
||||||
"Catamaran",
|
"Catamaran",
|
||||||
"Cairo",
|
"Cairo",
|
||||||
"Arial"
|
"Arial",
|
||||||
].join(","),
|
].join(","),
|
||||||
h1: {
|
h1: {
|
||||||
fontSize: "2rem",
|
fontSize: "2rem",
|
||||||
fontWeight: 600
|
fontWeight: 600,
|
||||||
},
|
},
|
||||||
h2: {
|
h2: {
|
||||||
fontSize: "1.75rem",
|
fontSize: "1.75rem",
|
||||||
fontWeight: 500
|
fontWeight: 500,
|
||||||
},
|
},
|
||||||
h3: {
|
h3: {
|
||||||
fontSize: "1.5rem",
|
fontSize: "1.5rem",
|
||||||
fontWeight: 500
|
fontWeight: 500,
|
||||||
},
|
},
|
||||||
h4: {
|
h4: {
|
||||||
fontSize: "1.25rem",
|
fontSize: "1.25rem",
|
||||||
fontWeight: 500
|
fontWeight: 500,
|
||||||
},
|
},
|
||||||
h5: {
|
h5: {
|
||||||
fontSize: "1rem",
|
fontSize: "1rem",
|
||||||
fontWeight: 500
|
fontWeight: 500,
|
||||||
},
|
},
|
||||||
h6: {
|
h6: {
|
||||||
fontSize: "0.875rem",
|
fontSize: "0.875rem",
|
||||||
fontWeight: 500
|
fontWeight: 500,
|
||||||
},
|
},
|
||||||
body1: {
|
body1: {
|
||||||
fontSize: "23px",
|
fontSize: "23px",
|
||||||
fontFamily: "Raleway",
|
fontFamily: "Raleway",
|
||||||
fontWeight: 400,
|
fontWeight: 400,
|
||||||
lineHeight: 1.5,
|
lineHeight: 1.5,
|
||||||
letterSpacing: "0.5px"
|
letterSpacing: "0.5px",
|
||||||
},
|
},
|
||||||
|
|
||||||
body2: {
|
body2: {
|
||||||
@ -50,12 +50,12 @@ const commonThemeOptions = {
|
|||||||
fontFamily: "Raleway, Arial",
|
fontFamily: "Raleway, Arial",
|
||||||
fontWeight: 400,
|
fontWeight: 400,
|
||||||
lineHeight: 1.4,
|
lineHeight: 1.4,
|
||||||
letterSpacing: "0.2px"
|
letterSpacing: "0.2px",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
shape: {
|
shape: {
|
||||||
borderRadius: 4
|
borderRadius: 4,
|
||||||
},
|
},
|
||||||
breakpoints: {
|
breakpoints: {
|
||||||
values: {
|
values: {
|
||||||
@ -63,8 +63,8 @@ const commonThemeOptions = {
|
|||||||
sm: 600,
|
sm: 600,
|
||||||
md: 900,
|
md: 900,
|
||||||
lg: 1200,
|
lg: 1200,
|
||||||
xl: 1536
|
xl: 1536,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
MuiButton: {
|
MuiButton: {
|
||||||
@ -73,16 +73,16 @@ const commonThemeOptions = {
|
|||||||
backgroundColor: "inherit",
|
backgroundColor: "inherit",
|
||||||
transition: "filter 0.3s ease-in-out",
|
transition: "filter 0.3s ease-in-out",
|
||||||
"&:hover": {
|
"&:hover": {
|
||||||
filter: "brightness(1.1)"
|
filter: "brightness(1.1)",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
defaultProps: {
|
defaultProps: {
|
||||||
disableElevation: true,
|
disableElevation: true,
|
||||||
disableRipple: true
|
disableRipple: true,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const lightTheme = createTheme({
|
const lightTheme = createTheme({
|
||||||
@ -92,20 +92,20 @@ const lightTheme = createTheme({
|
|||||||
primary: {
|
primary: {
|
||||||
main: "#ffffff",
|
main: "#ffffff",
|
||||||
dark: "#F5F5F5",
|
dark: "#F5F5F5",
|
||||||
light: "#FCFCFC"
|
light: "#FCFCFC",
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
main: "#417Ed4",
|
main: "#417Ed4",
|
||||||
dark: "#3e74c1"
|
dark: "#3e74c1",
|
||||||
},
|
},
|
||||||
background: {
|
background: {
|
||||||
default: "#fcfcfc",
|
default: "#fcfcfc",
|
||||||
paper: "#F5F5F5"
|
paper: "#F5F5F5",
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
primary: "#000000",
|
primary: "#000000",
|
||||||
secondary: "#525252"
|
secondary: "#525252",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
MuiCard: {
|
MuiCard: {
|
||||||
@ -118,19 +118,19 @@ const lightTheme = createTheme({
|
|||||||
"&:hover": {
|
"&:hover": {
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
boxShadow:
|
boxShadow:
|
||||||
"rgba(0, 0, 0, 0.1) 0px 4px 6px -1px, rgba(0, 0, 0, 0.06) 0px 2px 4px -1px;"
|
"rgba(0, 0, 0, 0.1) 0px 4px 6px -1px, rgba(0, 0, 0, 0.06) 0px 2px 4px -1px;",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
MuiIcon: {
|
MuiIcon: {
|
||||||
defaultProps: {
|
defaultProps: {
|
||||||
style: {
|
style: {
|
||||||
color: "#000000"
|
color: "#000000",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const darkTheme = createTheme({
|
const darkTheme = createTheme({
|
||||||
@ -138,23 +138,23 @@ const darkTheme = createTheme({
|
|||||||
palette: {
|
palette: {
|
||||||
mode: "dark",
|
mode: "dark",
|
||||||
primary: {
|
primary: {
|
||||||
main: "#FF1493", // Neon pink
|
main: "#01a9e9", //
|
||||||
dark: "#C6127A", // Darker shade of neon pink
|
dark: "#008fcd", //
|
||||||
light: "#FF5EC4" // Lighter shade of neon pink
|
light: "#44c4ff", //
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
main: "#007FFF", // Electric blue
|
main: "#007FFF", // Electric blue
|
||||||
dark: "#0059B2", // Darker shade of electric blue
|
dark: "#0059B2", // Darker shade of electric blue
|
||||||
light: "#3399FF" // Lighter shade of electric blue
|
light: "#3399FF", // Lighter shade of electric blue
|
||||||
},
|
},
|
||||||
background: {
|
background: {
|
||||||
default: "#1C1C1C", // Deep space black
|
default: "#1C1C1C", // Deep space black
|
||||||
paper: "#342F41" // Dark cyberpunk-style purple
|
paper: "#342F41", // Dark cyberpunk-style purple
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
primary: "#ffffff",
|
primary: "#ffffff",
|
||||||
secondary: "#b3b3b3"
|
secondary: "#b3b3b3",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
MuiCard: {
|
MuiCard: {
|
||||||
@ -165,20 +165,20 @@ const darkTheme = createTheme({
|
|||||||
transition: "all 0.3s ease-in-out",
|
transition: "all 0.3s ease-in-out",
|
||||||
"&:hover": {
|
"&:hover": {
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
boxShadow: "0px 3px 4px 0px hsla(0,0%,0%,0.14), 0px 3px 3px -2px hsla(0,0%,0%,0.12), 0px 1px 8px 0px hsla(0,0%,0%,0.2);"
|
boxShadow:
|
||||||
}
|
"0px 3px 4px 0px hsla(0,0%,0%,0.14), 0px 3px 3px -2px hsla(0,0%,0%,0.12), 0px 1px 8px 0px hsla(0,0%,0%,0.2);",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
MuiIcon: {
|
MuiIcon: {
|
||||||
defaultProps: {
|
defaultProps: {
|
||||||
style: {
|
style: {
|
||||||
color: "#ffffff"
|
color: "#ffffff",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
export { lightTheme, darkTheme };
|
export { lightTheme, darkTheme };
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import React, {
|
import React, {
|
||||||
useEffect,
|
|
||||||
useState,
|
|
||||||
useCallback,
|
useCallback,
|
||||||
useRef,
|
useEffect,
|
||||||
useMemo,
|
useMemo,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ import { setUserAvatarHash } from "../state/features/globalSlice";
|
|||||||
import { VideoPlayerGlobal } from "../components/common/VideoPlayerGlobal";
|
import { VideoPlayerGlobal } from "../components/common/VideoPlayerGlobal";
|
||||||
import { Rnd } from "react-rnd";
|
import { Rnd } from "react-rnd";
|
||||||
import { RequestQueue } from "../utils/queue";
|
import { RequestQueue } from "../utils/queue";
|
||||||
import { EditFile } from "../components/EditFile/EditFile.tsx";
|
import { EditIssue } from "../components/EditIssue/EditIssue.tsx";
|
||||||
import { EditPlaylist } from "../components/EditPlaylist/EditPlaylist";
|
import { EditPlaylist } from "../components/EditPlaylist/EditPlaylist";
|
||||||
import ConsentModal from "../components/common/ConsentModal";
|
import ConsentModal from "../components/common/ConsentModal";
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
|
|||||||
userAvatar={userAvatar}
|
userAvatar={userAvatar}
|
||||||
authenticate={askForAccountInformation}
|
authenticate={askForAccountInformation}
|
||||||
/>
|
/>
|
||||||
<EditFile />
|
<EditIssue />
|
||||||
<EditPlaylist />
|
<EditPlaylist />
|
||||||
<Rnd
|
<Rnd
|
||||||
onDragStart={onDragStart}
|
onDragStart={onDragStart}
|
||||||
|