diff --git a/gridwalk-backend/src/server.rs b/gridwalk-backend/src/server.rs index 4f77d45..9576eda 100644 --- a/gridwalk-backend/src/server.rs +++ b/gridwalk-backend/src/server.rs @@ -33,7 +33,7 @@ pub fn create_app(app_state: AppState) -> Router { .route("/workspace", post(create_workspace)) .route("/workspace/members", post(add_workspace_member)) .route( - "/workspacei/:workspace_id/members", + "/workspace/:workspace_id/members", get(get_workspace_members), ) .route( diff --git a/gridwalk-ui/src/app/project/[workspaceId]/[projectName]/components/hooks/useFileUploader.ts b/gridwalk-ui/src/app/project/[workspaceId]/[projectName]/components/hooks/useFileUploader.ts index 416a65c..5b0ee65 100644 --- a/gridwalk-ui/src/app/project/[workspaceId]/[projectName]/components/hooks/useFileUploader.ts +++ b/gridwalk-ui/src/app/project/[workspaceId]/[projectName]/components/hooks/useFileUploader.ts @@ -43,6 +43,7 @@ export const useFileUploader = () => { try { const baseHeaders = await getUploadHeaders(); const totalChunks = Math.ceil(file.size / CHUNK_SIZE); + let finalResponse = null; for (let currentChunk = 0; currentChunk < totalChunks; currentChunk++) { const start = currentChunk * CHUNK_SIZE; @@ -102,9 +103,18 @@ export const useFileUploader = () => { onProgress?.(progress); if (currentChunk === totalChunks - 1) { - onSuccess?.(data); + finalResponse = data; } } + + if (finalResponse) { + console.log("Upload completed, calling success callback", finalResponse); + onSuccess?.({ + success: true, + data: finalResponse + }); + } + } catch (err) { const errorMessage = err instanceof Error ? err.message : "Unknown error"; diff --git a/gridwalk-ui/src/app/project/[workspaceId]/[projectName]/components/mapClient.tsx b/gridwalk-ui/src/app/project/[workspaceId]/[projectName]/components/mapClient.tsx index 73e1d91..4f30159 100644 --- a/gridwalk-ui/src/app/project/[workspaceId]/[projectName]/components/mapClient.tsx +++ b/gridwalk-ui/src/app/project/[workspaceId]/[projectName]/components/mapClient.tsx @@ -51,7 +51,7 @@ export function MapClient({ apiUrl }: MapClientProps) { const [uploadError, setUploadError] = useState(null); const [uploadSuccess, setUploadSuccess] = useState(false); - // Map Initialization + // Map Initialisation const { mapContainer, mapError } = useMapInit({ ...INITIAL_MAP_CONFIG, styleUrl: currentStyle, @@ -88,7 +88,13 @@ export function MapClient({ apiUrl }: MapClientProps) { workspace_id: response.data!.workspace_id, }, ]); + setUploadSuccess(true); + setIsUploading(false); + + setTimeout(() => { + setUploadSuccess(false); + }, 1000); } }, (error) => { @@ -136,6 +142,8 @@ export function MapClient({ apiUrl }: MapClientProps) { const handleModalClose = useCallback(() => { setIsModalOpen(false); setSelectedItem(null); + setUploadSuccess(false); + setUploadError(null); }, []); return ( diff --git a/gridwalk-ui/src/app/project/[workspaceId]/[projectName]/components/mapInit.ts b/gridwalk-ui/src/app/project/[workspaceId]/[projectName]/components/mapInit.ts index 9068c28..95088f4 100644 --- a/gridwalk-ui/src/app/project/[workspaceId]/[projectName]/components/mapInit.ts +++ b/gridwalk-ui/src/app/project/[workspaceId]/[projectName]/components/mapInit.ts @@ -30,6 +30,7 @@ export interface UseMapInitResult { mapError: string | null; } +// Fetch api tokens in order to load OS maps const getToken = (apiUrl: string): TokenData => { const xhr = new XMLHttpRequest() xhr.open("GET", `${apiUrl}/os-token`, false) diff --git a/gridwalk-ui/src/app/project/[workspaceId]/[projectName]/components/navBars/baseLayerNavigation.tsx b/gridwalk-ui/src/app/project/[workspaceId]/[projectName]/components/navBars/baseLayerNavigation.tsx index 4ecf695..8bdb726 100644 --- a/gridwalk-ui/src/app/project/[workspaceId]/[projectName]/components/navBars/baseLayerNavigation.tsx +++ b/gridwalk-ui/src/app/project/[workspaceId]/[projectName]/components/navBars/baseLayerNavigation.tsx @@ -52,7 +52,7 @@ const BaseLayerNav: React.FC = ({ ${ selectedBaseItem?.id === item.id ? getSelectedStyle(item.id) - : "text-white hover:bg-gray-700" + : "text-white hover:bg-blue-400" } `} title={item.title} @@ -69,7 +69,7 @@ const BaseLayerNav: React.FC = ({ const getSelectedStyle = (id: string) => { switch (id) { case "light": - return "bg-blue-400 text-white"; // Light blue + return "bg-yellow-500 text-white"; // Light yellow case "dark": return "bg-blue-800 text-white"; // Dark blue case "car": diff --git a/gridwalk-ui/src/app/project/[workspaceId]/[projectName]/components/navBars/mainMapNavigation.tsx b/gridwalk-ui/src/app/project/[workspaceId]/[projectName]/components/navBars/mainMapNavigation.tsx index 4053f2f..7133cf0 100644 --- a/gridwalk-ui/src/app/project/[workspaceId]/[projectName]/components/navBars/mainMapNavigation.tsx +++ b/gridwalk-ui/src/app/project/[workspaceId]/[projectName]/components/navBars/mainMapNavigation.tsx @@ -1,14 +1,12 @@ "use client"; import React from "react"; import { - Map, Layers, - Settings, - Info, File, X, Upload, ArrowLeft, + CheckCircle2 } from "lucide-react"; import { ModalProps, MainMapNav } from "./types"; import { useRouter } from "next/navigation"; @@ -29,21 +27,27 @@ const MapModal: React.FC = ({ onLayerUpload, isUploading, error, + uploadSuccess, + uploadProgress }) => { const router = useRouter(); + // Add a key state that changes when upload is successful + const [uploadKey, setUploadKey] = React.useState(0); + + // Reset the key when upload is successful + React.useEffect(() => { + if (uploadSuccess) { + setUploadKey(prev => prev + 1); + } + }, [uploadSuccess]); + const MainMapNavs: MainMapNav[] = [ - { - id: "map", - title: "Map Settings", - icon: "map", - description: "Configure map display options", - }, { id: "layers", title: "Layers", icon: "layers", - description: "Manage map layers", + description: "Visualise map layers", }, { id: "upload", @@ -52,18 +56,6 @@ const MapModal: React.FC = ({ description: "Upload files and add a layer to the map. Currently accepts .geojson, .json, and .gpkg files.", }, - { - id: "settings", - title: "Settings", - icon: "settings", - description: "Application settings", - }, - { - id: "about", - title: "About", - icon: "info", - description: "About this application", - }, ]; const handleFileChange = (event: React.ChangeEvent) => { @@ -75,16 +67,10 @@ const MapModal: React.FC = ({ const getIconComponent = (iconName: string) => { switch (iconName) { - case "map": - return ; case "layers": return ; case "file": return ; - case "settings": - return ; - case "info": - return ; default: return null; } @@ -101,7 +87,10 @@ const MapModal: React.FC = ({ {/* Upload Section */}
-
- {/* Status Messages */} {isUploading && (
- Uploading file + Uploading file ({uploadProgress}%) +
+ )} + + {uploadSuccess && !isUploading && ( +
+ + File uploaded successfully!
)} @@ -177,7 +172,7 @@ const MapModal: React.FC = ({
) : ( -
+
{initialProjects.map((project) => (
+ {/* Help Button */} +
+ +
+ + {/* Modals */} setIsProjectDialogOpen(false)} @@ -212,6 +226,11 @@ export default function WorkspaceProjectsClient({ onClose={() => setIsViewMemberDialogOpen(false)} workspaceId={workspaceId} /> + + setIsHelpSupportModalOpen(false)} + />
); diff --git a/gridwalk-ui/src/app/workspace/page.tsx b/gridwalk-ui/src/app/workspace/page.tsx index a86d6f6..7d6d944 100644 --- a/gridwalk-ui/src/app/workspace/page.tsx +++ b/gridwalk-ui/src/app/workspace/page.tsx @@ -1,12 +1,14 @@ -"use client"; -import { FolderKanban, Plus } from "lucide-react"; +'use client' +import React, { useState } from "react"; +import { FolderKanban, Plus, HelpCircle } from "lucide-react"; import { Button } from "@/components/ui/button"; -import { useState } from "react"; import { CreateWorkspaceModal } from "./modal"; import { createWorkspace } from "./actions"; +import { HelpSupportModal } from "./supportModal"; export default function WorkspacePage() { const [isModalOpen, setIsModalOpen] = useState(false); + const [isHelpSupportModalOpen, setIsHelpSupportModalOpen] = useState(false); const handleCreateWorkspace = async (name: string) => { await createWorkspace(name); @@ -19,7 +21,7 @@ export default function WorkspacePage() {

- Workspaces + GridWalk Workspaces

@@ -27,7 +29,7 @@ export default function WorkspacePage() {

- setIsModalOpen(false)} - onCreate={handleCreateWorkspace} - /> -
@@ -58,6 +54,28 @@ export default function WorkspacePage() {
+ + {/* Help Button - Fixed to bottom right */} +
+ +
+ + {/* Modals */} + setIsModalOpen(false)} + onCreate={handleCreateWorkspace} + /> + setIsHelpSupportModalOpen(false)} + /> ); -} +} \ No newline at end of file diff --git a/gridwalk-ui/src/app/workspace/sidebar.tsx b/gridwalk-ui/src/app/workspace/sidebar.tsx index 8737cf5..a432040 100644 --- a/gridwalk-ui/src/app/workspace/sidebar.tsx +++ b/gridwalk-ui/src/app/workspace/sidebar.tsx @@ -64,16 +64,19 @@ const WorkspaceAccordion = ({ workspaces }: { workspaces: Workspaces }) => { return (
-
-

Workspaces

- +
+

GridWalk

+
+

Workspaces

+ +
+ + +
+ {supportOptions.map((option, index) => ( + + ))} +
+
+ +
+
+ ); +}; + +export { HelpSupportModal }; \ No newline at end of file