mirror of
https://github.com/20kaushik02/spotify-manager-web.git
synced 2025-12-06 09:54:07 +00:00
loading!
This commit is contained in:
parent
f942be8d3f
commit
47eb312ba1
@ -4,7 +4,6 @@ import { backendDomain } from "./paths";
|
|||||||
export const axiosInstance = axios.create({
|
export const axiosInstance = axios.create({
|
||||||
baseURL: backendDomain,
|
baseURL: backendDomain,
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
timeout: 20000,
|
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
|
|||||||
50
src/components/SimpleLoader/SimpleLoader.module.css
Normal file
50
src/components/SimpleLoader/SimpleLoader.module.css
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
margin-top: var(--mb-2);
|
||||||
|
font-family: var(--primaryFont);
|
||||||
|
font-size: larger;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loader {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
}
|
||||||
|
.loader div {
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
margin: 8px;
|
||||||
|
/* border: 7px solid var(--primary); */
|
||||||
|
border: 7px solid white;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: loader 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
|
||||||
|
border-color: white transparent transparent transparent;
|
||||||
|
}
|
||||||
|
.loader div:nth-child(1) {
|
||||||
|
animation-delay: -0.45s;
|
||||||
|
}
|
||||||
|
.loader div:nth-child(2) {
|
||||||
|
animation-delay: -0.3s;
|
||||||
|
}
|
||||||
|
.loader div:nth-child(3) {
|
||||||
|
animation-delay: -0.15s;
|
||||||
|
}
|
||||||
|
@keyframes loader {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/components/SimpleLoader/index.tsx
Normal file
17
src/components/SimpleLoader/index.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import styles from "./SimpleLoader.module.css";
|
||||||
|
|
||||||
|
const SimpleLoader = ({ text }: { text?: string }) => {
|
||||||
|
return (
|
||||||
|
<div className={`${styles.container}`}>
|
||||||
|
<div className={`${styles.loader}`}>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
<p className={`${styles.text}`}>{text}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SimpleLoader;
|
||||||
@ -5,6 +5,10 @@
|
|||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
filter: brightness(70%);
|
||||||
|
}
|
||||||
|
|
||||||
.operations_wrapper {
|
.operations_wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
background-color: var(--bgNav);
|
background-color: var(--bgNav);
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import {
|
|||||||
Controls,
|
Controls,
|
||||||
MiniMap,
|
MiniMap,
|
||||||
Background,
|
Background,
|
||||||
|
Panel,
|
||||||
addEdge,
|
addEdge,
|
||||||
applyNodeChanges,
|
applyNodeChanges,
|
||||||
applyEdgeChanges,
|
applyEdgeChanges,
|
||||||
@ -53,6 +54,7 @@ import {
|
|||||||
import { RefreshAuthContext } from "../../App";
|
import { RefreshAuthContext } from "../../App";
|
||||||
import Button from "../../components/Button";
|
import Button from "../../components/Button";
|
||||||
import APIWrapper from "../../components/APIWrapper";
|
import APIWrapper from "../../components/APIWrapper";
|
||||||
|
import SimpleLoader from "../../components/SimpleLoader";
|
||||||
|
|
||||||
const initialNodes: Node[] = [];
|
const initialNodes: Node[] = [];
|
||||||
const initialEdges: Edge[] = [];
|
const initialEdges: Edge[] = [];
|
||||||
@ -134,6 +136,7 @@ const Graph = () => {
|
|||||||
const [selectedEdgeID, setSelectedEdgeID] = useState<Edge["id"]>("");
|
const [selectedEdgeID, setSelectedEdgeID] = useState<Edge["id"]>("");
|
||||||
const [interactive, setInteractive] =
|
const [interactive, setInteractive] =
|
||||||
useState<Interactive>(initialInteractive);
|
useState<Interactive>(initialInteractive);
|
||||||
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
const onFlowInit: OnInit = (_instance) => {
|
const onFlowInit: OnInit = (_instance) => {
|
||||||
console.debug("flow loaded");
|
console.debug("flow loaded");
|
||||||
@ -175,6 +178,7 @@ const Graph = () => {
|
|||||||
);
|
);
|
||||||
// call API to create link
|
// call API to create link
|
||||||
const spotifyPlaylistLinkPrefix = "https://open.spotify.com/playlist/";
|
const spotifyPlaylistLinkPrefix = "https://open.spotify.com/playlist/";
|
||||||
|
setLoading(true);
|
||||||
const resp = await APIWrapper({
|
const resp = await APIWrapper({
|
||||||
apiFn: apiCreateLink,
|
apiFn: apiCreateLink,
|
||||||
data: {
|
data: {
|
||||||
@ -183,6 +187,7 @@ const Graph = () => {
|
|||||||
},
|
},
|
||||||
refreshAuth,
|
refreshAuth,
|
||||||
});
|
});
|
||||||
|
setLoading(false);
|
||||||
if (resp?.status === 201) {
|
if (resp?.status === 201) {
|
||||||
showSuccessToastNotification(resp?.data.message);
|
showSuccessToastNotification(resp?.data.message);
|
||||||
setLinkEdges((eds) => addEdge(connection, eds));
|
setLinkEdges((eds) => addEdge(connection, eds));
|
||||||
@ -203,6 +208,7 @@ const Graph = () => {
|
|||||||
`deleted connection: ${edges[0].source} -> ${edges[0].target}`
|
`deleted connection: ${edges[0].source} -> ${edges[0].target}`
|
||||||
);
|
);
|
||||||
// call API to delete link
|
// call API to delete link
|
||||||
|
setLoading(true);
|
||||||
const resp = await APIWrapper({
|
const resp = await APIWrapper({
|
||||||
apiFn: apiDeleteLink,
|
apiFn: apiDeleteLink,
|
||||||
data: {
|
data: {
|
||||||
@ -211,6 +217,7 @@ const Graph = () => {
|
|||||||
},
|
},
|
||||||
refreshAuth,
|
refreshAuth,
|
||||||
});
|
});
|
||||||
|
setLoading(false);
|
||||||
if (resp?.status === 200) {
|
if (resp?.status === 200) {
|
||||||
showSuccessToastNotification(resp?.data.message);
|
showSuccessToastNotification(resp?.data.message);
|
||||||
return { nodes, edges };
|
return { nodes, edges };
|
||||||
@ -228,6 +235,7 @@ const Graph = () => {
|
|||||||
}
|
}
|
||||||
const selectedEdge = linkEdges.filter((ed) => ed.id === selectedEdgeID)[0];
|
const selectedEdge = linkEdges.filter((ed) => ed.id === selectedEdgeID)[0];
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
const resp = await APIWrapper({
|
const resp = await APIWrapper({
|
||||||
apiFn: apiBackfillLink,
|
apiFn: apiBackfillLink,
|
||||||
data: {
|
data: {
|
||||||
@ -236,6 +244,7 @@ const Graph = () => {
|
|||||||
},
|
},
|
||||||
refreshAuth,
|
refreshAuth,
|
||||||
});
|
});
|
||||||
|
setLoading(false);
|
||||||
|
|
||||||
if (resp?.status === 200) {
|
if (resp?.status === 200) {
|
||||||
showSuccessToastNotification(resp?.data.message);
|
showSuccessToastNotification(resp?.data.message);
|
||||||
@ -252,6 +261,7 @@ const Graph = () => {
|
|||||||
}
|
}
|
||||||
const selectedEdge = linkEdges.filter((ed) => ed.id === selectedEdgeID)[0];
|
const selectedEdge = linkEdges.filter((ed) => ed.id === selectedEdgeID)[0];
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
const resp = await APIWrapper({
|
const resp = await APIWrapper({
|
||||||
apiFn: apiPruneLink,
|
apiFn: apiPruneLink,
|
||||||
data: {
|
data: {
|
||||||
@ -260,6 +270,7 @@ const Graph = () => {
|
|||||||
},
|
},
|
||||||
refreshAuth,
|
refreshAuth,
|
||||||
});
|
});
|
||||||
|
setLoading(false);
|
||||||
|
|
||||||
if (resp?.status === 200) {
|
if (resp?.status === 200) {
|
||||||
showSuccessToastNotification(resp?.data.message);
|
showSuccessToastNotification(resp?.data.message);
|
||||||
@ -359,7 +370,9 @@ const Graph = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const fetchGraph = useCallback(async () => {
|
const fetchGraph = useCallback(async () => {
|
||||||
|
setLoading(true);
|
||||||
const resp = await APIWrapper({ apiFn: apiFetchGraph, refreshAuth });
|
const resp = await APIWrapper({ apiFn: apiFetchGraph, refreshAuth });
|
||||||
|
setLoading(false);
|
||||||
console.debug(
|
console.debug(
|
||||||
`graph fetched with ${resp?.data.playlists?.length} nodes and ${resp?.data.links?.length} edges`
|
`graph fetched with ${resp?.data.playlists?.length} nodes and ${resp?.data.links?.length} edges`
|
||||||
);
|
);
|
||||||
@ -399,10 +412,12 @@ const Graph = () => {
|
|||||||
}, [refreshAuth]);
|
}, [refreshAuth]);
|
||||||
|
|
||||||
const updateUserData = async () => {
|
const updateUserData = async () => {
|
||||||
|
setLoading(true);
|
||||||
const resp = await APIWrapper({
|
const resp = await APIWrapper({
|
||||||
apiFn: apiUpdateUserData,
|
apiFn: apiUpdateUserData,
|
||||||
refreshAuth,
|
refreshAuth,
|
||||||
});
|
});
|
||||||
|
setLoading(false);
|
||||||
showInfoToastNotification(resp?.data.message);
|
showInfoToastNotification(resp?.data.message);
|
||||||
if (resp?.data.removedLinks)
|
if (resp?.data.removedLinks)
|
||||||
showWarnToastNotification(
|
showWarnToastNotification(
|
||||||
@ -442,7 +457,7 @@ const Graph = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.graph_wrapper}>
|
<div className={`${styles.graph_wrapper} ${loading && styles.loading}`}>
|
||||||
<ReactFlow
|
<ReactFlow
|
||||||
nodes={playlistNodes}
|
nodes={playlistNodes}
|
||||||
edges={linkEdges}
|
edges={linkEdges}
|
||||||
@ -452,8 +467,8 @@ const Graph = () => {
|
|||||||
proOptions={proOptions}
|
proOptions={proOptions}
|
||||||
colorMode={"light"}
|
colorMode={"light"}
|
||||||
fitView
|
fitView
|
||||||
minZoom={0.1}
|
minZoom={0.05}
|
||||||
maxZoom={10}
|
maxZoom={20}
|
||||||
elevateEdgesOnSelect
|
elevateEdgesOnSelect
|
||||||
defaultEdgeOptions={edgeOptions}
|
defaultEdgeOptions={edgeOptions}
|
||||||
edgesReconnectable={false}
|
edgesReconnectable={false}
|
||||||
@ -475,6 +490,7 @@ const Graph = () => {
|
|||||||
bgColor={"purple"}
|
bgColor={"purple"}
|
||||||
/>
|
/>
|
||||||
<Background variant={BackgroundVariant.Dots} gap={36} size={3} />
|
<Background variant={BackgroundVariant.Dots} gap={36} size={3} />
|
||||||
|
<Panel position="top-right">{loading && <SimpleLoader />}</Panel>
|
||||||
</ReactFlow>
|
</ReactFlow>
|
||||||
<div className={`${styles.operations_wrapper} custom_scrollbar`}>
|
<div className={`${styles.operations_wrapper} custom_scrollbar`}>
|
||||||
<Button onClickMethod={backfillLink}>
|
<Button onClickMethod={backfillLink}>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user