diff --git a/src/frontend/src/components/skeletonCardComponent/index.tsx b/src/frontend/src/components/skeletonCardComponent/index.tsx
new file mode 100644
index 000000000..a9857e4f4
--- /dev/null
+++ b/src/frontend/src/components/skeletonCardComponent/index.tsx
@@ -0,0 +1,16 @@
+import { Skeleton } from "../ui/skeleton";
+
+export const SkeletonCardComponent = (): JSX.Element => {
+ return (
+
+ );
+};
diff --git a/src/frontend/src/components/ui/skeleton.tsx b/src/frontend/src/components/ui/skeleton.tsx
new file mode 100644
index 000000000..6556585a4
--- /dev/null
+++ b/src/frontend/src/components/ui/skeleton.tsx
@@ -0,0 +1,15 @@
+import { cn } from "../../utils/utils"
+
+function Skeleton({
+ className,
+ ...props
+}: React.HTMLAttributes) {
+ return (
+
+ )
+}
+
+export { Skeleton }
diff --git a/src/frontend/src/contexts/tabsContext.tsx b/src/frontend/src/contexts/tabsContext.tsx
index ac0d676e0..97ad50329 100644
--- a/src/frontend/src/contexts/tabsContext.tsx
+++ b/src/frontend/src/contexts/tabsContext.tsx
@@ -39,6 +39,7 @@ const TabsContextInitialValue: TabsContextType = {
save: () => {},
tabId: "",
setTabId: (index: string) => {},
+ isLoading: true,
flows: [],
removeFlow: (id: string) => {},
addFlow: async (flowData?: any) => "",
@@ -72,10 +73,12 @@ export const TabsContext = createContext(
export function TabsProvider({ children }: { children: ReactNode }) {
const { setErrorData, setNoticeData, setSuccessData } =
useContext(alertContext);
- const { getAuthentication } = useContext(AuthContext);
+ const { getAuthentication, isAuthenticated } = useContext(AuthContext);
const [tabId, setTabId] = useState("");
+ const [isLoading, setIsLoading] = useState(true);
+
const [flows, setFlows] = useState>([]);
const [id, setId] = useState(uid());
const { templates, reactFlowInstance } = useContext(typesContext);
@@ -86,6 +89,12 @@ export function TabsProvider({ children }: { children: ReactNode }) {
const [tabsState, setTabsState] = useState({});
const [getTweak, setTweak] = useState([]);
+ useEffect(() => {
+ if (!isAuthenticated) {
+ hardReset();
+ }
+ }, [isAuthenticated]);
+
const newNodeId = useRef(uid());
function incrementNodeId() {
newNodeId.current = uid();
@@ -116,11 +125,13 @@ export function TabsProvider({ children }: { children: ReactNode }) {
}
function refreshFlows() {
+ setIsLoading(true);
getTabsDataFromDB().then((DbData) => {
if (DbData && Object.keys(templates).length > 0) {
try {
processDBData(DbData);
updateStateWithDbData(DbData);
+ setIsLoading(false);
} catch (e) {}
}
});
@@ -229,6 +240,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
setTabId("");
setFlows([]);
+ setIsLoading(true);
setId(uid());
}
@@ -641,6 +653,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
paste,
getTweak,
setTweak,
+ isLoading,
}}
>
{children}
diff --git a/src/frontend/src/pages/MainPage/index.tsx b/src/frontend/src/pages/MainPage/index.tsx
index 67412401a..442a43e2f 100644
--- a/src/frontend/src/pages/MainPage/index.tsx
+++ b/src/frontend/src/pages/MainPage/index.tsx
@@ -3,12 +3,20 @@ import { Link, useNavigate } from "react-router-dom";
import { CardComponent } from "../../components/cardComponent";
import IconComponent from "../../components/genericIconComponent";
import Header from "../../components/headerComponent";
+import { SkeletonCardComponent } from "../../components/skeletonCardComponent";
import { Button } from "../../components/ui/button";
import { USER_PROJECTS_HEADER } from "../../constants/constants";
import { TabsContext } from "../../contexts/tabsContext";
export default function HomePage(): JSX.Element {
- const { flows, setTabId, downloadFlows, uploadFlows, addFlow, removeFlow } =
- useContext(TabsContext);
+ const {
+ flows,
+ setTabId,
+ downloadFlows,
+ uploadFlows,
+ addFlow,
+ removeFlow,
+ isLoading,
+ } = useContext(TabsContext);
// Set a null id
useEffect(() => {
@@ -16,6 +24,10 @@ export default function HomePage(): JSX.Element {
}, []);
const navigate = useNavigate();
+ useEffect(() => {
+ console.log(isLoading);
+ }, [isLoading]);
+
// Personal flows display
return (
<>
@@ -62,31 +74,40 @@ export default function HomePage(): JSX.Element {
Manage your personal projects. Download or upload your collection.
- {flows.map((flow, idx) => (
-
-
-
- }
- onDelete={() => {
- removeFlow(flow.id);
- }}
- />
- ))}
+ {isLoading && flows.length == 0 ? (
+ <>
+
+
+
+
+ >
+ ) : (
+ flows.map((flow, idx) => (
+
+
+
+ }
+ onDelete={() => {
+ removeFlow(flow.id);
+ }}
+ />
+ ))
+ )}
>
diff --git a/src/frontend/src/style/applies.css b/src/frontend/src/style/applies.css
index 4f6f9b3a5..685d81b05 100644
--- a/src/frontend/src/style/applies.css
+++ b/src/frontend/src/style/applies.css
@@ -126,6 +126,18 @@
@apply form-input block w-full truncate rounded-md border-border bg-background px-3 text-left shadow-sm placeholder:text-muted-foreground focus:border-ring focus:placeholder-transparent focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 sm:text-sm;
}
+ .skeleton-card {
+ @apply bg-background h-48 p-4 border rounded-lg flex flex-col gap-6;
+ }
+
+ .skeleton-card-wrapper {
+ @apply flex items-center space-x-4;
+ }
+
+ .skeleton-card-text {
+ @apply flex flex-col gap-3;
+ }
+
/* The same as primary-input but no-truncate */
.textarea-primary {
@apply form-input block w-full rounded-md border-border bg-background px-3 text-left shadow-sm placeholder:text-muted-foreground focus:border-ring focus:placeholder-transparent focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 sm:text-sm;
diff --git a/src/frontend/src/types/tabs/index.ts b/src/frontend/src/types/tabs/index.ts
index a87cdb35e..036f82717 100644
--- a/src/frontend/src/types/tabs/index.ts
+++ b/src/frontend/src/types/tabs/index.ts
@@ -5,6 +5,7 @@ export type TabsContextType = {
saveFlow: (flow: FlowType) => Promise;
save: () => void;
tabId: string;
+ isLoading: boolean;
setTabId: (index: string) => void;
flows: Array;
removeFlow: (id: string) => void;