Skip to content

Commit

Permalink
feat: add screen preloader logic
Browse files Browse the repository at this point in the history
  • Loading branch information
MXerFix committed Aug 29, 2024
1 parent e9acff9 commit 41bbbbc
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 157 deletions.
104 changes: 4 additions & 100 deletions frontend/src/UI/Preloader/preloader.css
Original file line number Diff line number Diff line change
@@ -1,113 +1,17 @@
#preloader-wrapper {
background-color: hsl(var(--background));
position: absolute;
top: 0;
left: 0;
z-index: 99;
width: 100%;
height: 100%;
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}

/* #preloader {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
scale: 0.5;
}
#loader {
display: block;
position: relative;
left: 50%;
top: 50%;
width: 150px;
height: 150px;
margin: -75px 0 0 -75px;
border-radius: 50%;
border: 6px solid transparent;
border-top-color: #70db97;
-webkit-animation: spin 2s cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
animation: spin 2s cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
}
#loader:before {
content: "";
position: absolute;
top: 5px;
left: 5px;
right: 5px;
bottom: 5px;
border-radius: 50%;
border: 6px solid transparent;
border-top-color: #2036ff;
-webkit-animation: spin 3s cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
animation: spin 3s cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
}
#loader:after {
content: "";
position: absolute;
top: 15px;
left: 15px;
right: 15px;
bottom: 15px;
border-radius: 50%;
border: 6px solid transparent;
border-top-color: #077ac9;
-webkit-animation: spin 1.5s cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
animation: spin 1.5s cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
}
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes spin {
0% {
-webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-webkit-keyframes spin-reverse {
0% {
-webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(-360deg);
-ms-transform: rotate(-360deg);
transform: rotate(-360deg);
}
}
@keyframes spin-reverse {
0% {
-webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(-360deg);
-ms-transform: rotate(-360deg);
transform: rotate(-360deg);
}
} */

.loader {
position: relative;
width: 120px;
Expand Down
128 changes: 75 additions & 53 deletions frontend/src/contexts/flowContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { get_flows, save_flows } from "../api/flows"
import { FLOW_COLORS } from "../consts"
import { FlowType } from "../types/FlowTypes"
import { NodeType } from "../types/NodeTypes"
import { MetaContext } from "./metaContext"
import { notificationsContext } from "./notificationsContext"
// import { v4 } from "uuid"

Expand Down Expand Up @@ -88,21 +89,29 @@ export const FlowProvider = ({ children }: { children: React.ReactNode }) => {
const { flowId } = useParams()
const [flows, setFlows] = useState<FlowType[]>([])
const { notification: n } = useContext(notificationsContext)
const { screenLoading } = useContext(MetaContext)

useEffect(() => {
setTab(flowId || "")
}, [flowId])

const getFlows = async () => {
const { data } = await get_flows()
if (data.flows) {
if (data.flows.some((flow) => flow.name === "Global")) {
setFlows(data.flows)
screenLoading.addScreenLoading()
try {
const { data } = await get_flows()
if (data.flows) {
if (data.flows.some((flow) => flow.name === "Global")) {
setFlows(data.flows)
} else {
setFlows([globalFlow, ...data.flows])
}
} else {
setFlows([globalFlow, ...data.flows])
setFlows([globalFlow])
}
} else {
setFlows([globalFlow])
} catch (error) {
console.error(error)
} finally {
screenLoading.removeScreenLoading()
}
}

Expand Down Expand Up @@ -145,54 +154,67 @@ export const FlowProvider = ({ children }: { children: React.ReactNode }) => {
[flows]
)

const deleteNode = useCallback((id: string) => {
const flow = flows.find((flow) => flow.data.nodes.some((node) => node.id === id))
if (!flow) return -1
const deleted_node: NodeType = flow.data.nodes.find((node) => node.id === id) as NodeType
if (deleted_node?.data.flags?.includes("start"))
return n.add({ title: "Warning!", message: "Can't delete start node", type: "warning" })
if (deleted_node?.id?.includes("LOCAL")) return n.add({ title: "Warning!", message: "Can't delete local node", type: "warning" })
if (deleted_node?.id?.includes("GLOBAL")) return n.add({ title: "Warning!", message: "Can't delete global node", type: "warning" })
if (deleted_node?.data.flags?.includes("fallback")) {
console.log(
flow.data.nodes
.find((node) => node.id !== id && !node.data.id.includes("LOCAL"))
?.data.flags.push("fallback")
const deleteNode = useCallback(
(id: string) => {
const flow = flows.find((flow) => flow.data.nodes.some((node) => node.id === id))
if (!flow) return -1
const deleted_node: NodeType = flow.data.nodes.find((node) => node.id === id) as NodeType
if (deleted_node?.data.flags?.includes("start"))
return n.add({ title: "Warning!", message: "Can't delete start node", type: "warning" })
if (deleted_node?.id?.includes("LOCAL"))
return n.add({ title: "Warning!", message: "Can't delete local node", type: "warning" })
if (deleted_node?.id?.includes("GLOBAL"))
return n.add({ title: "Warning!", message: "Can't delete global node", type: "warning" })
if (deleted_node?.data.flags?.includes("fallback")) {
console.log(
flow.data.nodes
.find((node) => node.id !== id && !node.data.id.includes("LOCAL"))
?.data.flags.push("fallback")
)
// any_node.data.flags?.push("fallback")
}
const newNodes = flow.data.nodes.filter((node) => node.id !== id)
const newEdges = flow.data.edges.filter(
(edge: Edge) => edge.source !== id && edge.target !== id
)
// any_node.data.flags?.push("fallback")
}
const newNodes = flow.data.nodes.filter((node) => node.id !== id)
const newEdges = flow.data.edges.filter(
(edge: Edge) => edge.source !== id && edge.target !== id
)
const newFlows = flows.map((flow) =>
flow.name === flowId
? { ...flow, data: { ...flow.data, nodes: newNodes, edges: newEdges } }
: flow
)
saveFlows(newFlows)
setFlows(newFlows)
}, [flowId, flows, n])

const deleteEdge = useCallback((id: string) => {
const flow = flows.find((flow) => flow.data.edges.some((edge) => edge.id === id))
if (!flow) return -1
const newEdges = flow.data.edges.filter((edge) => edge.id !== id)
saveFlows(
flows.map((flow) =>
flow.name === flowId ? { ...flow, data: { ...flow.data, edges: newEdges } } : flow
const newFlows = flows.map((flow) =>
flow.name === flowId
? { ...flow, data: { ...flow.data, nodes: newNodes, edges: newEdges } }
: flow
)
saveFlows(newFlows)
setFlows(newFlows)
},
[flowId, flows, n]
)

const deleteEdge = useCallback(
(id: string) => {
const flow = flows.find((flow) => flow.data.edges.some((edge) => edge.id === id))
if (!flow) return -1
const newEdges = flow.data.edges.filter((edge) => edge.id !== id)
saveFlows(
flows.map((flow) =>
flow.name === flowId ? { ...flow, data: { ...flow.data, edges: newEdges } } : flow
)
)
)
setFlows((flows) => flows.map((flow) => ({ ...flow, data: { ...flow.data, edges: newEdges } })))
}, [flowId, flows])

const deleteObject = useCallback((id: string) => {
const flow_node = flows.find((flow) => flow.data.nodes.some((node) => node.id === id))
const flow_edge = flows.find((flow) => flow.data.edges.some((edge) => edge.id === id))
if (!flow_node && !flow_edge) return -1
if (flow_node) deleteNode(id)
if (flow_edge) deleteEdge(id)
}, [deleteEdge, deleteNode, flows])
setFlows((flows) =>
flows.map((flow) => ({ ...flow, data: { ...flow.data, edges: newEdges } }))
)
},
[flowId, flows]
)

const deleteObject = useCallback(
(id: string) => {
const flow_node = flows.find((flow) => flow.data.nodes.some((node) => node.id === id))
const flow_edge = flows.find((flow) => flow.data.edges.some((edge) => edge.id === id))
if (!flow_node && !flow_edge) return -1
if (flow_node) deleteNode(id)
if (flow_edge) deleteEdge(id)
},
[deleteEdge, deleteNode, flows]
)

return (
<flowContext.Provider
Expand Down
48 changes: 45 additions & 3 deletions frontend/src/contexts/metaContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,72 @@ import { get_config_version } from "../api/meta"
type metaContextType = {
version: string
setVersion: React.Dispatch<React.SetStateAction<string>>
setScreenLoading: React.Dispatch<React.SetStateAction<number>>
screenLoading: {
addScreenLoading: () => void
removeScreenLoading: () => void
value: number
}
}

export const MetaContext = createContext<metaContextType>({
version: "",
setVersion: () => {},
screenLoading: {
addScreenLoading: () => {},
removeScreenLoading: () => {},
value: 0,
},
setScreenLoading: () => {},
})

interface MetaProviderProps {
children: React.ReactNode
}

const MetaProvider = ({ children }: MetaProviderProps) => {
const [screenLoading, setScreenLoading] = useState<number>(0)
const [version, setVersion] = useState<string>("")

const addScreenLoading = () => {
setScreenLoading((prev) => prev + 1)
}

const removeScreenLoading = () => {
setScreenLoading((prev) => prev - 1)
}

const getVersion = async () => {
const version_data = await get_config_version()
setVersion(version_data)
addScreenLoading()
try {
const version_data = await get_config_version()
setVersion(version_data)
} catch (error) {
console.error(error)
} finally {
removeScreenLoading()
}
}

useEffect(() => {
getVersion()
}, [])

return <MetaContext.Provider value={{ version, setVersion }}>{children}</MetaContext.Provider>
return (
<MetaContext.Provider
value={{
version,
setVersion,
screenLoading: {
addScreenLoading,
removeScreenLoading,
value: screenLoading,
},
setScreenLoading,
}}>
{children}
</MetaContext.Provider>
)
}

export default MetaProvider
8 changes: 7 additions & 1 deletion frontend/src/pages/Flow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ import LinkNode from "../components/nodes/LinkNode"
import SideBar from "../components/sidebar/SideBar"
import { NODES, NODE_NAMES } from "../consts"
import { flowContext } from "../contexts/flowContext"
import { MetaContext } from "../contexts/metaContext"
import { notificationsContext } from "../contexts/notificationsContext"
import { undoRedoContext } from "../contexts/undoRedoContext"
import { workspaceContext } from "../contexts/workspaceContext"
import "../index.css"
import { FlowType } from "../types/FlowTypes"
import { NodeDataType, NodeType, NodesTypes } from "../types/NodeTypes"
import { responseType } from "../types/ResponseTypes"
import { Preloader } from "../UI/Preloader/Preloader"
import Fallback from "./Fallback"
import Logs from "./Logs"
import NodesLayout from "./NodesLayout"
Expand Down Expand Up @@ -65,6 +67,7 @@ export default function Flow() {
mouseOnPane,
managerMode,
} = useContext(workspaceContext)
const { screenLoading } = useContext(MetaContext)
const { takeSnapshot, undo } = useContext(undoRedoContext)

const { flowId } = useParams()
Expand Down Expand Up @@ -357,7 +360,10 @@ export default function Flow() {
exitBeforeEnter: true,
})

if (!flow) return <Fallback />
if (screenLoading.value) return <Preloader />
else if (flows.length && !flow && !screenLoading.value) {
return <Fallback />
}

return (
<div
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,9 @@ export const isNodeDeletionValid = (nodes: NodeType[], id: string) => {
if (!node) return false
return !node.data.flags?.includes("start")
}

export function delay(ms: number) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms);
});
}

0 comments on commit 41bbbbc

Please sign in to comment.