Skip to content

Commit

Permalink
fix: Resolve issues highlighted in PR review
Browse files Browse the repository at this point in the history
  • Loading branch information
Loxeris committed May 7, 2024
1 parent e180b96 commit c3e5571
Show file tree
Hide file tree
Showing 12 changed files with 134 additions and 85 deletions.
22 changes: 0 additions & 22 deletions src/app/(dashboard)/jobmonitor/error.tsx

This file was deleted.

7 changes: 0 additions & 7 deletions src/app/(dashboard)/jobmonitor/layout.tsx

This file was deleted.

5 changes: 0 additions & 5 deletions src/app/(dashboard)/jobmonitor/page.tsx

This file was deleted.

14 changes: 9 additions & 5 deletions src/app/(dashboard)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@ export default function Page() {
const appId = searchParams.get("appId");
const [sections] = React.useContext(ApplicationsContext);

const appType = sections
.find((section) => section.items.some((item) => item.id === appId))
?.items.find((item) => item.id === appId)?.type;
const appType = React.useMemo(() => {
const section = sections.find((section) =>
section.items.some((item) => item.id === appId),
);
return section?.items.find((item) => item.id === appId)?.type;
}, [sections, appId]);

const Component = applicationList.find((app) => app.name === appType)
?.component;
const Component = React.useMemo(() => {
return applicationList.find((app) => app.name === appType)?.component;
}, [appType]);

return Component ? <Component /> : <UserDashboard />;
}
3 changes: 2 additions & 1 deletion src/components/applications/ApplicationList.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Dashboard, FolderCopy, Monitor } from "@mui/icons-material";
import JobMonitor from "./JobMonitor";
import UserDashboard from "./UserDashboard";
import ApplicationConfig from "@/types/ApplicationConfig";

export const applicationList = [
export const applicationList: ApplicationConfig[] = [
{ name: "Dashboard", component: UserDashboard, icon: Dashboard },
{
name: "Job Monitor",
Expand Down
30 changes: 20 additions & 10 deletions src/components/ui/ApplicationDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import {
Button,
Grid,
Icon,
IconButton,
} from "@mui/material";
import { Close } from "@mui/icons-material";
import { applicationList } from "../applications/ApplicationList";

/**
Expand Down Expand Up @@ -55,10 +57,26 @@ export default function AppDialog({
fullWidth
maxWidth="sm"
>
<DialogTitle id="application-dialog-label">New Application</DialogTitle>
<DialogTitle id="application-dialog-label">
Available applications
</DialogTitle>
<IconButton
aria-label="close"
onClick={() => setAppDialogOpen(false)}
sx={{
position: "absolute",
right: 8,
top: 8,
color: (theme) => theme.palette.grey[500],
}}
>
<Close />
</IconButton>
<DialogContent>
<DialogContentText sx={{ mb: 2 }}>
Choose the type of application you would like to create.
Click on any application to open it in a new instance in the drawer.
Multiple instances of the same application can be opened
simultaneously.
</DialogContentText>
<Grid container spacing={2}>
{applicationList.map((app) => (
Expand All @@ -78,14 +96,6 @@ export default function AppDialog({
))}
</Grid>
</DialogContent>
<DialogActions>
<Button
sx={{ color: "warning.main" }}
onClick={() => setAppDialogOpen(false)}
>
Cancel
</Button>
</DialogActions>
</Dialog>
);
}
35 changes: 28 additions & 7 deletions src/components/ui/DashboardDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import DrawerItemGroup from "./DrawerItemGroup";
import { DiracLogo } from "./DiracLogo";
import AppDialog from "./ApplicationDialog";
import { ApplicationsContext } from "@/contexts/ApplicationsProvider";
import { useMUITheme } from "@/hooks/theme";

interface DashboardDrawerProps {
variant: "permanent" | "temporary";
Expand All @@ -52,8 +53,7 @@ export default function DashboardDrawer(props: DashboardDrawerProps) {
window !== undefined ? () => window.document.body : undefined;
// Check if the drawer is in "temporary" mode.
const isTemporary = props.variant === "temporary";

// Wether the modal for Application Creation is open
// Whether the modal for Application Creation is open
const [appDialogOpen, setAppDialogOpen] = useState(false);

const [contextMenu, setContextMenu] = React.useState<{
Expand All @@ -73,7 +73,10 @@ export default function DashboardDrawer(props: DashboardDrawerProps) {
// Each section has an associated icon and path.
const [userSections, setSections] = useContext(ApplicationsContext);

const theme = useMUITheme();

useEffect(() => {
// Handle changes to sections when drag and drop occurs.
return monitorForElements({
onDrop({ source, location }) {
const target = location.current.dropTargets[0];
Expand All @@ -84,6 +87,7 @@ export default function DashboardDrawer(props: DashboardDrawerProps) {
const targetData = target.data;

if (location.current.dropTargets.length == 2) {
// If the target is an item
const groupTitle = targetData.title;
const closestEdgeOfTarget = extractClosestEdge(targetData);
const targetIndex = targetData.index as number;
Expand All @@ -105,6 +109,7 @@ export default function DashboardDrawer(props: DashboardDrawerProps) {
destinationIndex,
);
} else {
// If the target is a group
const groupTitle = targetData.title;
const sourceGroup = userSections.find(
(group) => group.title == sourceData.title,
Expand Down Expand Up @@ -140,13 +145,13 @@ export default function DashboardDrawer(props: DashboardDrawerProps) {
destinationIndex &&
sourceIndex < destinationIndex
) {
destinationIndex -= 1;
destinationIndex -= 1; // Corrects the index within the same group if needed
}
if (
sourceGroup.title === destinationGroup.title &&
(destinationIndex == null || sourceIndex === destinationIndex)
) {
return;
return; // Nothing to do
}

if (sourceGroup.title === destinationGroup.title) {
Expand Down Expand Up @@ -361,7 +366,14 @@ export default function DashboardDrawer(props: DashboardDrawerProps) {
style={{ display: "flex", flexDirection: "column", height: "100%" }}
>
{/* Display the logo in the toolbar section of the drawer. */}
<Toolbar>
<Toolbar
sx={{
position: "sticky",
top: "0",
zIndex: 1,
backgroundColor: theme.palette.background.default,
}}
>
<DiracLogo />
</Toolbar>
{/* Map over user sections and render them as list items in the drawer. */}
Expand All @@ -380,8 +392,17 @@ export default function DashboardDrawer(props: DashboardDrawerProps) {
</ListItem>
))}
</List>
{/* Render a link to documentation, positioned at the bottom of the drawer. */}
<List sx={{ mt: "auto" }}>

{/* Render a link to documentation and a button to add applications, positioned at the bottom of the drawer. */}
<List
sx={{
mt: "auto",
position: "sticky",
bottom: "0",
zIndex: 1,
backgroundColor: theme.palette.background.default,
}}
>
<ListItem key={"Add application"}>
<ListItemButton onClick={() => setAppDialogOpen(true)}>
<ListItemIcon>
Expand Down
26 changes: 24 additions & 2 deletions src/components/ui/DrawerItem.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { useEffect, useState } from "react";
import { createRoot } from "react-dom/client";
import Link from "next/link";
import {
ListItemButton,
ListItemIcon,
Expand All @@ -25,6 +24,14 @@ import { ThemeProvider } from "@/contexts/ThemeProvider";
import { useMUITheme } from "@/hooks/theme";
import { useSearchParamsUtils } from "@/hooks/searchParamsUtils";

/**
* Represents a drawer item component.
*
* @param item - The item object containing the title, id, and icon.
* @param index - The index of the item.
* @param groupTitle - The title of the group.
* @returns The rendered JSX for the drawer item.
*/
export default function DrawerItem({
item: { title, id, icon },
index,
Expand All @@ -34,11 +41,13 @@ export default function DrawerItem({
index: number;
groupTitle: string;
}) {
// Ref to use for the draggable element
const dragRef = React.useRef(null);
// Ref to use for the handle of the draggable element, must be a child of the draggable element
const handleRef = React.useRef(null);
const theme = useMUITheme();
const { setParam } = useSearchParamsUtils();

// Represents the closest edge to the mouse cursor
const [closestEdge, setClosestEdge]: any = useState<Edge | null>(null);

useEffect(() => {
Expand All @@ -47,10 +56,13 @@ export default function DrawerItem({
const handleItem = handleRef.current;

return combine(
// makes the item draggable
draggable({
element: element,
dragHandle: handleItem,
// Sets the initial data for the drag and drop interaction
getInitialData: () => ({ index, title: groupTitle }),
// Sets a lightweight version of the real item as a preview
onGenerateDragPreview: ({ nativeSetDragImage, source, location }) => {
setCustomNativeDragPreview({
nativeSetDragImage,
Expand All @@ -71,6 +83,7 @@ export default function DrawerItem({
);
return () => root.unmount();
},
// Seemless transition between the preview and the real element
getOffset: ({ container }) => {
const elementPos = source.element.getBoundingClientRect();
const x = location.current.input.pageX - elementPos.x;
Expand All @@ -80,6 +93,7 @@ export default function DrawerItem({
});
},
}),
// Makes the item a target for dragged elements. Attach the closest edge data and highlight the destination when hovering over the item
dropTargetForElements({
element: element,
getData: ({ input, element }) => {
Expand Down Expand Up @@ -150,6 +164,14 @@ export default function DrawerItem({
);
}

/**
* Lightweight preview of an item in the drawer.
*
* @param {Object} props - The component props.
* @param {string} props.title - The title of the item.
* @param {React.ComponentType} props.icon - The icon component for the item.
* @returns {JSX.Element} The rendered item preview.
*/
function ItemPreview({
title,
icon,
Expand Down
16 changes: 13 additions & 3 deletions src/components/ui/DrawerItemGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ import { UserSection } from "@/types/UserSection";
/**
* Represents a group of items in a drawer.
*
* @param group - The group object containing the title, expanded state, and items.
* @param setSections - The function to update the sections state.
* @returns The JSX element representing the drawer item group.
* @component
* @param {Object} props - The component props.
* @param {Object} props.group - The group object containing the title, expanded state, and items.
* @param {string} props.group.title - The title of the group.
* @param {boolean} props.group.extended - The expanded state of the group.
* @param {Array} props.group.items - The array of items in the group.
* @param {Function} props.setSections - The function to set the sections state.
* @param {Function} props.handleContextMenu - The function to handle the context menu.
* @returns {JSX.Element} The rendered DrawerItemGroup component.
*/
export default function DrawerItemGroup({
group: { title, extended: expanded, items },
Expand All @@ -32,13 +38,16 @@ export default function DrawerItemGroup({
id: string | null,
) => (event: React.MouseEvent<HTMLElement>) => void;
}) {
// Ref to use for the drag and drop target
const dropRef = React.useRef(null);
// State to track whether the user is hovering over the item during a drag operation
const [hovered, setHovered] = React.useState(false);

useEffect(() => {
if (!dropRef.current) return;
const dropItem = dropRef.current;

// Makes the element a valid drop target, sets up the data transfer and manage the hovered state
return dropTargetForElements({
element: dropItem,
getData: () => ({ title }),
Expand All @@ -52,6 +61,7 @@ export default function DrawerItemGroup({
});
});

// Handles expansion of the accordion group
const handleChange = (title: string) => (event: any, isExpanded: any) => {
// Set the extended state of the accordion group.
setSections((sections) =>
Expand Down
13 changes: 9 additions & 4 deletions src/hooks/theme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ export const useMUITheme = () => {
},
});

const scrollbarBackground = theme === "dark" ? "#333" : "#f1f1f1";
const scrollbarThumbBackground = theme === "dark" ? "#888" : "#ccc";
const scrollbarThumbHoverBackground = theme === "dark" ? "#555" : "#999";
const scrollbarColor = `${scrollbarThumbBackground} ${scrollbarBackground}`;

muiTheme.components = {
MuiCssBaseline: {
styleOverrides: `
Expand All @@ -44,18 +49,18 @@ export const useMUITheme = () => {
border-radius: 5px;
}
::-webkit-scrollbar-track {
background: ${theme === "dark" ? "#333" : "#f1f1f1"};
background: ${scrollbarBackground};
}
::-webkit-scrollbar-thumb {
background: ${theme === "dark" ? "#888" : "#ccc"};
background: ${scrollbarThumbBackground};
border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover {
background: ${theme === "dark" ? "#555" : "#999"};
background: ${scrollbarThumbHoverBackground};
}
@supports not selector(::-webkit-scrollbar) {
html {
scrollbar-color: ${theme === "dark" ? "#888 #333" : "#ccc #f1f1f1"};
scrollbar-color: ${scrollbarColor};
}
}
`,
Expand Down
8 changes: 8 additions & 0 deletions src/types/ApplicationConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { SvgIconComponent } from "@mui/icons-material";
import { ElementType } from "react";

export default interface ApplicationConfig {
name: string;
component: ElementType;
icon: SvgIconComponent;
}
Loading

0 comments on commit c3e5571

Please sign in to comment.