diff --git a/src/App.tsx b/src/App.tsx
index e97b3a5..751e950 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -8,7 +8,9 @@ import { DashboardProvider } from './dashboard/provider/DashboardProvider.tsx';
import { PrinterWidgetProvider } from './printers/providers/PrinterWidgetProvider.tsx';
import { SSEProvider } from './core/sse/SSEProvider.tsx';
import { SettingsProvider } from './core/settings/settingsProvider.tsx';
-import { EventNotifications } from './system/components/event-notifications/EventNotifications.tsx';
+import { DiscoveryNotifications } from './system/components/discovery-notifications/DiscoveryNotifications.tsx';
+import { NewProjectNotification } from './projects/notifications/new-project-notification/NewProjectNotification.tsx';
+import { Notifications } from '@mantine/notifications';
export default function App() {
const [opened, { toggle }] = useDisclosure();
@@ -41,8 +43,10 @@ export default function App() {
-
+
+
+
diff --git a/src/assets/components/AssetCardProps.ts b/src/assets/components/AssetCardProps.ts
deleted file mode 100644
index 9debae9..0000000
--- a/src/assets/components/AssetCardProps.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { Asset } from "../entities/Assets";
-
-export type AssetCardProps = {
- projectUuid: string;
- asset: Asset;
- selected: boolean;
- onSelectChange: (arg0: boolean) => void;
- view3d?: boolean,
- onView3dChange?: (arg0: boolean) => void;
- onDelete: (projectUuid: string, id: string) => void;
- onChange: (projectUuid: string, id: string) => void;
-}
\ No newline at end of file
diff --git a/src/assets/components/asset-card/AssetCard.tsx b/src/assets/components/asset-card/AssetCard.tsx
index 5aa95da..b09d7d7 100644
--- a/src/assets/components/asset-card/AssetCard.tsx
+++ b/src/assets/components/asset-card/AssetCard.tsx
@@ -40,8 +40,8 @@ export function AssetCard({ asset, focused, onFocused, onDelete, onChange, view3
return (
<>
{modal && asset.image_id && asset.image_id != "" && }
@@ -50,7 +50,7 @@ export function AssetCard({ asset, focused, onFocused, onDelete, onChange, view3
{asset?.image_id === "" ? (iconMap.get(asset.extension) ?? ) :
}
@@ -58,7 +58,7 @@ export function AssetCard({ asset, focused, onFocused, onDelete, onChange, view3
{ onFocused() }}>
- {asset.name}
+ {asset.label != "" ? asset.label : asset.name}
@@ -80,7 +80,7 @@ export function AssetCard({ asset, focused, onFocused, onDelete, onChange, view3
projectUuid={asset.project_uuid}
id={asset.id}
openDetails={() => { onFocused() }}
- downloadURL={`${settings.localBackend}/projects/${asset.project_uuid}/assets/${asset.id}?download=true'`}
+ downloadURL={`${settings.localBackend}/projects/${asset.project_uuid}/assets/${asset.id}/file?download=true'`}
onDelete={onDelete}
toggleLoad={toggleLoadingCallback}>
diff --git a/src/assets/components/model/model-detail-pane/ModelDetailPane.tsx b/src/assets/components/model/model-detail-pane/ModelDetailPane.tsx
index 5a5b758..2548ff3 100644
--- a/src/assets/components/model/model-detail-pane/ModelDetailPane.tsx
+++ b/src/assets/components/model/model-detail-pane/ModelDetailPane.tsx
@@ -17,7 +17,7 @@ type ModelProps = {
function Model({ color, model, projectUuid }: ModelProps) {
const { settings } = useContext(SettingsContext);
- const geom = useLoader(STLLoader, `${settings.localBackend}/projects/${projectUuid}/assets/${model.id}`);
+ const geom = useLoader(STLLoader, `${settings.localBackend}/projects/${projectUuid}/assets/${model.id}/file`);
const meshRef = useRef(null!)
const [active, setActive] = useState(false)
diff --git a/src/assets/entities/Assets.ts b/src/assets/entities/Assets.ts
index e67386c..57df517 100644
--- a/src/assets/entities/Assets.ts
+++ b/src/assets/entities/Assets.ts
@@ -2,6 +2,7 @@
export interface Asset {
id: string
name: string
+ label: string
origin: string
project_uuid: string
path: string
diff --git a/src/core/sse/SubscriptionManager.ts b/src/core/sse/SubscriptionManager.ts
index b28e917..0d4f982 100644
--- a/src/core/sse/SubscriptionManager.ts
+++ b/src/core/sse/SubscriptionManager.ts
@@ -48,6 +48,9 @@ export const createSubsManager = (url: string): SubscriptionManager => {
return;
}
if (ev.event) {
+ if (ev.data.name) {
+ state.evSubs.get(`${ev.event}.${ev.data.name}`)?.forEach(sub => sub.callback(ev.data));
+ }
if (ev.data.state) {
state.evSubs.get(ev.event)?.forEach(sub => sub.callback(ev.data.state));
} else if (Array.isArray(ev.data)) {
diff --git a/src/main.tsx b/src/main.tsx
index d220cf7..1f3baeb 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -24,7 +24,6 @@ import '@mantine/core/styles/Checkbox.css';
import '@mantine/dropzone/styles.css';
import '@mantine/notifications/styles.css';
import { createTheme, MantineProvider } from '@mantine/core';
-import { Notifications } from '@mantine/notifications';
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import { routes as dashboardRoutes } from "./dashboard/routes.tsx";
@@ -71,7 +70,6 @@ console.log(router);
ReactDOM.createRoot(document.getElementById('root')!).render(
-
diff --git a/src/projects/components/project-page/ProjectPage.tsx b/src/projects/components/project-page/ProjectPage.tsx
index 42619d3..a6dba2c 100644
--- a/src/projects/components/project-page/ProjectPage.tsx
+++ b/src/projects/components/project-page/ProjectPage.tsx
@@ -5,6 +5,7 @@ import { useContext } from "react";
import { ProjectPageBody } from "./parts/project-page-body/ProjectPageBody.tsx";
import { Header } from "@/core/header/Header.tsx";
import { SettingsContext } from "@/core/settings/settingsContext.ts";
+import { Refresher } from "./parts/refresher/Refresher.tsx";
export function ProjectPage() {
@@ -23,7 +24,7 @@ export function ProjectPage() {
description={project?.description}
tags={project?.tags}
link={project?.external_link}
- imagePath={`${settings.localBackend}/projects/${project?.uuid}/assets/${project?.default_image_id}`}
+ imagePath={`${settings.localBackend}/projects/${project?.uuid}/assets/${project?.default_image_id}/file`}
onTagClick={(t) => navigate(`/projects/list?filter=${JSON.stringify({ tags: [t.value] })}`)}
/>
{error && Error!
}
@@ -31,6 +32,7 @@ export function ProjectPage() {
console.log("onProjectChange")
refetch()
}} />}
+
>
)
}
\ No newline at end of file
diff --git a/src/projects/components/project-page/parts/project-page-body/ProjectPageBody.tsx b/src/projects/components/project-page/parts/project-page-body/ProjectPageBody.tsx
index 194c5a9..3394702 100644
--- a/src/projects/components/project-page/parts/project-page-body/ProjectPageBody.tsx
+++ b/src/projects/components/project-page/parts/project-page-body/ProjectPageBody.tsx
@@ -1,8 +1,8 @@
-import { Alert, Container, Flex, rem, SimpleGrid, Skeleton, Tabs } from "@mantine/core";
+import { Alert, Button, Container, Flex, rem, SimpleGrid, Skeleton, Tabs } from "@mantine/core";
import useAxios from "axios-hooks";
import { Asset, AssetType } from "@/assets/entities/Assets.ts";
import { useListState } from "@mantine/hooks";
-import React, { useContext, useEffect, useState } from "react";
+import { useContext, useEffect, useState } from "react";
import { ModelDetailPane } from "@/assets/components/model/model-detail-pane/ModelDetailPane.tsx";
import { IconSettings, IconFiles } from "@tabler/icons-react";
import { useNavigate, useSearchParams } from "react-router-dom";
@@ -11,6 +11,7 @@ import { EditProject } from "./parts/edit-project/EditProject.tsx";
import { Project } from "../../../../entities/Project.ts";
import { SettingsContext } from "@/core/settings/settingsContext.ts";
import { AssetDetails } from "@/assets/components/asset-details/AssetDetails.tsx";
+import { Refresher } from "./parts/refresher/Refresher.tsx";
import { AssetCard } from "@/assets/components/asset-card/AssetCard.tsx";
const iconStyle = { width: rem(12), height: rem(12) };
@@ -25,15 +26,21 @@ export function ProjectPageBody({ projectUuid, project, onProjectChange }: Proje
const { settings } = useContext(SettingsContext);
const navigate = useNavigate();
const [searchParams] = useSearchParams();
+ const [assets, setAssets] = useState([]);
const [selectedModels, selectedModelsHandlers] = useListState([]);
const [selectedAsset, setSelectedAsset] = useState();
const [typeFilter, setTypeFilter] = useState(searchParams.get('tab'));
const [{ data: assetTypes, loading: tLoading, error: tError }] = useAxios(
`${settings.localBackend}/assettypes`
);
- const [{ data: assets, loading, error }, refetch] = useAxios(
+ const [{ data, loading, error }, refetch] = useAxios(
`${settings.localBackend}/projects/${projectUuid}/assets`
);
+ useEffect(() => {
+ if (data) {
+ setAssets(data);
+ }
+ }, [data]);
useEffect(() => {
if (selectedModels.length == 0) {
@@ -127,6 +134,7 @@ export function ProjectPageBody({ projectUuid, project, onProjectChange }: Proje
}
+
>
);
}
diff --git a/src/projects/components/project-page/parts/project-page-body/parts/refresher/Refresher.tsx b/src/projects/components/project-page/parts/project-page-body/parts/refresher/Refresher.tsx
new file mode 100644
index 0000000..18865e1
--- /dev/null
+++ b/src/projects/components/project-page/parts/project-page-body/parts/refresher/Refresher.tsx
@@ -0,0 +1,45 @@
+import SSEContext from "@/core/sse/SSEContext";
+import { Anchor } from "@mantine/core";
+import { useId } from "@mantine/hooks";
+import { notifications } from "@mantine/notifications";
+import { useContext, useEffect, useState } from "react";
+import { Link } from "react-router-dom";
+
+type RefresherProps = {
+ projectUUID: string;
+}
+
+export function Refresher({ projectUUID }: RefresherProps) {
+ const subscriberId = useId();
+ const { connected, subscribe, unsubscribe } = useContext(SSEContext)
+ const [assetUpdate, setAssetUpdate] = useState({} as any)
+ const [error, setError] = useState(null);
+ useEffect(() => {
+ if (!connected) return;
+ setAssetUpdate({})
+ const subscription = {
+ subscriberId,
+ provider: `system/events`,
+ }
+ subscribe({
+ ...subscription,
+ event: `system.state.asset.event`,
+ callback: setAssetUpdate
+ }).catch(setError);
+ return () => {
+ unsubscribe(subscriberId)
+ }
+ }, [connected])
+
+ useEffect(() => {
+ console.log(assetUpdate)
+ if (!assetUpdate.state) return;
+ if (projectUUID == assetUpdate.state.projectUUID) {
+ notifications.show({
+ title: `Assets have changed`,
+ message: Refresh,
+ })
+ }
+ }, [assetUpdate])
+ return (<>>)
+}
\ No newline at end of file
diff --git a/src/projects/components/project-page/parts/refresher/Refresher.tsx b/src/projects/components/project-page/parts/refresher/Refresher.tsx
new file mode 100644
index 0000000..65d0d2c
--- /dev/null
+++ b/src/projects/components/project-page/parts/refresher/Refresher.tsx
@@ -0,0 +1,40 @@
+import SSEContext from "@/core/sse/SSEContext";
+import { useId } from "@mantine/hooks";
+import { useContext, useEffect, useState } from "react";
+
+type RefresherProps = {
+ projectUUID: string;
+ refresh: () => void;
+}
+
+export function Refresher({ projectUUID, refresh }: RefresherProps) {
+ const subscriberId = useId();
+ const { connected, subscribe, unsubscribe } = useContext(SSEContext)
+ const [projectUpdate, setProjectUpdate] = useState({} as any)
+ const [error, setError] = useState(null);
+ useEffect(() => {
+ if (!connected) return;
+ setProjectUpdate({})
+ const subscription = {
+ subscriberId,
+ provider: `system/events`,
+ }
+ subscribe({
+ ...subscription,
+ event: `system.state.project.event`,
+ callback: setProjectUpdate
+ }).catch(setError);
+ return () => {
+ unsubscribe(subscriberId)
+ }
+ }, [connected])
+
+ useEffect(() => {
+ console.log(projectUpdate)
+ if (!projectUpdate.state) return;
+ if (projectUpdate.state.projectUUID == projectUUID && projectUpdate.state.type == "update") {
+ refresh();
+ }
+ }, [projectUpdate])
+ return (<>>)
+}
\ No newline at end of file
diff --git a/src/projects/components/projects-page/parts/projects-list/parts/project-card/ProjectCard.tsx b/src/projects/components/projects-page/parts/projects-list/parts/project-card/ProjectCard.tsx
index 04a475b..40d3281 100644
--- a/src/projects/components/projects-page/parts/projects-list/parts/project-card/ProjectCard.tsx
+++ b/src/projects/components/projects-page/parts/projects-list/parts/project-card/ProjectCard.tsx
@@ -26,7 +26,7 @@ export function ProjectCard({ project }: ProjectCardProps) {
}
diff --git a/src/system/components/event-notifications/EventNotifications.tsx b/src/projects/notifications/new-project-notification/NewProjectNotification.tsx
similarity index 58%
rename from src/system/components/event-notifications/EventNotifications.tsx
rename to src/projects/notifications/new-project-notification/NewProjectNotification.tsx
index fdd20ec..6a2be9d 100644
--- a/src/system/components/event-notifications/EventNotifications.tsx
+++ b/src/projects/notifications/new-project-notification/NewProjectNotification.tsx
@@ -1,23 +1,25 @@
import SSEContext from "@/core/sse/SSEContext";
+import { Anchor } from "@mantine/core";
import { useId } from "@mantine/hooks";
import { notifications } from "@mantine/notifications";
import { useContext, useEffect, useState } from "react";
+import { Link } from "react-router-dom";
-export function EventNotifications() {
+export function NewProjectNotification() {
const subscriberId = useId();
const { connected, subscribe, unsubscribe } = useContext(SSEContext)
- const [message, setMessage] = useState("")
+ const [message, setMessage] = useState({} as any)
const [error, setError] = useState(null);
useEffect(() => {
if (!connected) return;
- setMessage("")
+ setMessage({})
const subscription = {
subscriberId,
provider: `system/events`,
}
subscribe({
...subscription,
- event: `system.state`,
+ event: `system.state.project.event`,
callback: setMessage
}).catch(setError);
return () => {
@@ -27,10 +29,13 @@ export function EventNotifications() {
useEffect(() => {
console.log(message)
- notifications.show({
- title: message,
- message: message,
- })
+ if (!message.state) return;
+ if (message.state.type == "new") {
+ notifications.show({
+ title: `New project found`,
+ message: <>Go to {message.state.projectName}>,
+ })
+ }
}, [message])
return (<>>)
}
\ No newline at end of file
diff --git a/src/system/components/discovery-notifications/DiscoveryNotifications.tsx b/src/system/components/discovery-notifications/DiscoveryNotifications.tsx
new file mode 100644
index 0000000..cd1400e
--- /dev/null
+++ b/src/system/components/discovery-notifications/DiscoveryNotifications.tsx
@@ -0,0 +1,54 @@
+import SSEContext from "@/core/sse/SSEContext";
+import { rem } from "@mantine/core";
+import { useId } from "@mantine/hooks";
+import { notifications } from "@mantine/notifications";
+import { IconCheck } from "@tabler/icons-react";
+import { useContext, useEffect, useState } from "react";
+
+export function DiscoveryNotifications() {
+ const subscriberId = useId();
+ const { connected, subscribe, unsubscribe } = useContext(SSEContext)
+ const [id, setId] = useState(null);
+ const [message, setMessage] = useState({} as any)
+ const [error, setError] = useState(null);
+ useEffect(() => {
+ if (!connected) return;
+ setMessage("")
+ const subscription = {
+ subscriberId,
+ provider: `system/events`,
+ }
+ subscribe({
+ ...subscription,
+ event: `system.state.discovery.scan`,
+ callback: setMessage
+ }).catch(setError);
+ return () => {
+ unsubscribe(subscriberId)
+ }
+ }, [connected])
+
+ useEffect(() => {
+ console.log(message)
+ if (!message.state) return;
+ if (message.state.state == "started") {
+ setId(notifications.show({
+ loading: true,
+ title: "New Scan started",
+ message: "Let's find new projects!",
+ autoClose: false
+ }))
+ } else if (id) {
+ notifications.update({
+ id,
+ color: 'teal',
+ title: 'Scan finished!',
+ message: '',
+ icon: ,
+ loading: false,
+ autoClose: 2000,
+ });
+ }
+ }, [message])
+ return (<>>)
+}
\ No newline at end of file