Skip to content

Commit

Permalink
feat: changed front end and added information modals, changed styling…
Browse files Browse the repository at this point in the history
…, and fixed some errors in rsust server.rs [2024-12-12]
  • Loading branch information
CHRISCARLON committed Dec 12, 2024
1 parent 719a944 commit 0a860b8
Show file tree
Hide file tree
Showing 10 changed files with 219 additions and 61 deletions.
2 changes: 1 addition & 1 deletion gridwalk-backend/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export function MapClient({ apiUrl }: MapClientProps) {
const [uploadError, setUploadError] = useState<string | null>(null);
const [uploadSuccess, setUploadSuccess] = useState(false);

// Map Initialization
// Map Initialisation
const { mapContainer, mapError } = useMapInit({
...INITIAL_MAP_CONFIG,
styleUrl: currentStyle,
Expand Down Expand Up @@ -88,7 +88,13 @@ export function MapClient({ apiUrl }: MapClientProps) {
workspace_id: response.data!.workspace_id,
},
]);

setUploadSuccess(true);
setIsUploading(false);

setTimeout(() => {
setUploadSuccess(false);
}, 1000);
}
},
(error) => {
Expand Down Expand Up @@ -136,6 +142,8 @@ export function MapClient({ apiUrl }: MapClientProps) {
const handleModalClose = useCallback(() => {
setIsModalOpen(false);
setSelectedItem(null);
setUploadSuccess(false);
setUploadError(null);
}, []);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const BaseLayerNav: React.FC<BaseLayerNavProps> = ({
${
selectedBaseItem?.id === item.id
? getSelectedStyle(item.id)
: "text-white hover:bg-gray-700"
: "text-white hover:bg-blue-400"
}
`}
title={item.title}
Expand All @@ -69,7 +69,7 @@ const BaseLayerNav: React.FC<BaseLayerNavProps> = ({
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":
Expand Down
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -29,21 +27,27 @@ const MapModal: React.FC<ModalProps> = ({
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",
Expand All @@ -52,18 +56,6 @@ const MapModal: React.FC<ModalProps> = ({
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<HTMLInputElement>) => {
Expand All @@ -75,16 +67,10 @@ const MapModal: React.FC<ModalProps> = ({

const getIconComponent = (iconName: string) => {
switch (iconName) {
case "map":
return <Map className="w-5 h-5" />;
case "layers":
return <Layers className="w-5 h-5" />;
case "file":
return <File className="w-5 h-5" />;
case "settings":
return <Settings className="w-5 h-5" />;
case "info":
return <Info className="w-5 h-5" />;
default:
return null;
}
Expand All @@ -101,7 +87,10 @@ const MapModal: React.FC<ModalProps> = ({

{/* Upload Section */}
<div className="mb-6">
<label className="flex flex-col items-center px-4 py-6 bg-white rounded-lg shadow-lg border-2 border-dashed border-gray-300 hover:border-blue-400 cursor-pointer transition-colors">
<label
key={uploadKey}
className="flex flex-col items-center px-4 py-6 bg-white rounded-lg shadow-lg border-2 border-dashed border-gray-300 hover:border-blue-400 cursor-pointer transition-colors"
>
<Upload className="w-8 h-8 text-gray-400 mb-2" />
<span className="text-sm text-gray-500">
Click to upload a file
Expand All @@ -116,11 +105,17 @@ const MapModal: React.FC<ModalProps> = ({
</label>
</div>

{/* Status Messages */}
{isUploading && (
<div className="flex items-center justify-center space-x-2 text-blue-500 mb-4">
<LoadingDots />
<span className="ml-2">Uploading file</span>
<span className="ml-2">Uploading file ({uploadProgress}%)</span>
</div>
)}

{uploadSuccess && !isUploading && (
<div className="mb-4 p-3 bg-green-50 text-green-700 rounded-md flex items-center">
<CheckCircle2 className="w-5 h-5 text-green-500 mr-2" />
<span>File uploaded successfully!</span>
</div>
)}

Expand Down Expand Up @@ -177,7 +172,7 @@ const MapModal: React.FC<ModalProps> = ({
<div className="mt-auto mb-6">
<button
onClick={() => router.push("/workspace")}
className="w-10 h-8 flex items-center justify-center text-white bg-blue-700 hover:text-white hover:bg-blue-800 group relative"
className="w-10 h-8 flex items-center justify-center text-white bg-blue-400 hover:text-white hover:bg-blue-500 group relative"
aria-label="Back to workspace"
>
<ArrowLeft className="w-5 h-5" />
Expand Down
23 changes: 21 additions & 2 deletions gridwalk-ui/src/app/workspace/[workspaceId]/workspaceProjects.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"use client";
import React, { useState } from "react";
import { Plus, UserPlus, Users, ChevronDown, Trash2 } from "lucide-react";
import { Plus, UserPlus, Users, ChevronDown, Trash2, HelpCircle } from "lucide-react";
import { CreateProjectModal, DeleteProjectModal } from "./projectModal";
import { HelpSupportModal } from "../supportModal";
import { AddWorkspaceMemberModal } from "./addMemberModal";
import { ViewWorkspaceMemberModal } from "./viewMembersModal";
import { useWorkspaces } from "../workspaceContext";
Expand Down Expand Up @@ -31,6 +32,7 @@ export default function WorkspaceProjectsClient({
const { workspaces } = useWorkspaces();
const [isProjectDialogOpen, setIsProjectDialogOpen] = useState(false);
const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
const [isHelpSupportModalOpen, setIsHelpSupportModalOpen] = useState(false);
const [isMemberDialogOpen, setIsMemberDialogOpen] = useState(false);
const [isViewMemberDialogOpen, setIsViewMemberDialogOpen] = useState(false);
const [isActionsOpen, setIsActionsOpen] = useState(true);
Expand Down Expand Up @@ -164,7 +166,7 @@ export default function WorkspaceProjectsClient({
No projects found. Create your first project!
</div>
) : (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-2 gap-4 max-w-[800px]">
{initialProjects.map((project) => (
<div
key={project.id}
Expand All @@ -185,6 +187,18 @@ export default function WorkspaceProjectsClient({
)}
</div>

{/* Help Button */}
<div className="fixed bottom-0 right-0 p-6">
<button
onClick={() => setIsHelpSupportModalOpen(true)}
className="bg-white rounded-full shadow-lg hover:shadow-xl transition-all duration-200 group p-4"
aria-label="Help and Support"
>
<HelpCircle className="w-6 h-6 text-blue-500 group-hover:text-blue-600" />
</button>
</div>

{/* Modals */}
<CreateProjectModal
isOpen={isProjectDialogOpen}
onClose={() => setIsProjectDialogOpen(false)}
Expand Down Expand Up @@ -212,6 +226,11 @@ export default function WorkspaceProjectsClient({
onClose={() => setIsViewMemberDialogOpen(false)}
workspaceId={workspaceId}
/>

<HelpSupportModal
isOpen={isHelpSupportModalOpen}
onClose={() => setIsHelpSupportModalOpen(false)}
/>
</div>
</div>
);
Expand Down
42 changes: 30 additions & 12 deletions gridwalk-ui/src/app/workspace/page.tsx
Original file line number Diff line number Diff line change
@@ -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);
Expand All @@ -19,15 +21,15 @@ export default function WorkspacePage() {
<div className="space-y-3">
<div className="flex items-center gap-3">
<h1 className="text-3xl sm:text-4xl font-bold bg-gradient-to-r from-gray-900 to-gray-600 bg-clip-text text-transparent">
Workspaces
GridWalk Workspaces
</h1>
</div>
<p className="text-gray-600 text-lg">
Manage and organise your projects across different workspaces.
</p>
</div>
<Button
className="w-full sm:w-auto bg-background text-gray-300 hover:bg-blue-600 hover:text-white"
className="w-full sm:w-auto bg-background text-white hover:bg-blue-600 hover:text-white"
size="lg"
onClick={() => setIsModalOpen(true)}
>
Expand All @@ -36,12 +38,6 @@ export default function WorkspacePage() {
</Button>
</div>

<CreateWorkspaceModal
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
onCreate={handleCreateWorkspace}
/>

<div className="mt-8 flex flex-col items-center justify-center min-h-[400px] bg-white rounded-2xl shadow-sm border border-gray-100 p-8">
<div className="flex flex-col items-center text-center max-w-md">
<div className="bg-gray-50 p-4 rounded-full mb-6">
Expand All @@ -58,6 +54,28 @@ export default function WorkspacePage() {
</div>
</div>
</div>

{/* Help Button - Fixed to bottom right */}
<div className="fixed bottom-0 right-0 p-6">
<button
onClick={() => setIsHelpSupportModalOpen(true)}
className="bg-white rounded-full shadow-lg hover:shadow-xl transition-all duration-200 group p-4"
aria-label="Help and Support"
>
<HelpCircle className="w-6 h-6 text-blue-500 group-hover:text-blue-600" />
</button>
</div>

{/* Modals */}
<CreateWorkspaceModal
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
onCreate={handleCreateWorkspace}
/>
<HelpSupportModal
isOpen={isHelpSupportModalOpen}
onClose={() => setIsHelpSupportModalOpen(false)}
/>
</div>
);
}
}
23 changes: 13 additions & 10 deletions gridwalk-ui/src/app/workspace/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,19 @@ const WorkspaceAccordion = ({ workspaces }: { workspaces: Workspaces }) => {
return (
<div className="space-y-2">
<div className="px-4 py-2">
<div className="flex justify-between items-center mb-2">
<h2 className="text-xl font-semibold">Workspaces</h2>
<Button
variant="ghost"
size="sm"
onClick={() => setIsCreateModalOpen(true)}
className="hover:bg-blue-500 hover:text-white"
>
<Plus className="h-4 w-4" />
</Button>
<div className="flex flex-col gap-3">
<h2 className="text-gray-600 font-semibold italic">GridWalk</h2>
<div className="flex justify-between items-center mb-4">
<h2 className="text-xl font-semibold">Workspaces</h2>
<Button
variant="ghost"
size="sm"
onClick={() => setIsCreateModalOpen(true)}
className="hover:bg-blue-500 hover:text-white"
>
<Plus className="h-4 w-4" />
</Button>
</div>
</div>
<button
onClick={() => setIsOpen(!isOpen)}
Expand Down
Loading

0 comments on commit 0a860b8

Please sign in to comment.