Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 53 additions & 16 deletions ui/src/components/custom/search/matrixExplorer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ interface CarverMatrix {
hosts: string[];
participants: string[];
roleBased: boolean;
createdAt: string;
}

const MatrixExplorer: React.FC = () => {
Expand Down Expand Up @@ -86,15 +87,16 @@ const MatrixExplorer: React.FC = () => {
const filteredMatrices = matrices.filter((matrix) => {
// Text search filter
const term = searchTerm.toLowerCase();
const matchesSearch = matrix.name.toLowerCase().includes(term) ||
const matchesSearch =
matrix.name.toLowerCase().includes(term) ||
matrix.description.toLowerCase().includes(term);

// Role-based matrix filter
if (roleBasedFilter !== 'all') {
if (roleBasedFilter === 'enabled' && !matrix.roleBased) {
if (roleBasedFilter !== "all") {
if (roleBasedFilter === "enabled" && !matrix.roleBased) {
return false;
}
if (roleBasedFilter === 'disabled' && matrix.roleBased) {
if (roleBasedFilter === "disabled" && matrix.roleBased) {
return false;
}
}
Expand All @@ -111,7 +113,7 @@ const MatrixExplorer: React.FC = () => {

// Role-based filtering
if (!userEmail) {
console.log('No user email available');
console.log("No user email available");
return false;
}

Expand All @@ -125,19 +127,33 @@ const MatrixExplorer: React.FC = () => {
matchesRole = isBoth;
} else {
if (roleFilters.host) {
matchesRole = isHost;
matchesRole = isHost; // Show all matrices where user is a host, including those where they are both
}
if (roleFilters.participant) {
matchesRole = matchesRole || isParticipant;
matchesRole = matchesRole || isParticipant; // Show all matrices where user is a participant, including those where they are both
}
if (!roleFilters.host && !roleFilters.participant) {
matchesRole = true;
matchesRole = true; // No role filters selected
}
}

return matchesSearch && matchesRole;
});

// Sort matrices by timestamp (newest first)
const sortedMatrices = [...filteredMatrices].sort((a, b) => {
return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
});

// Helper functions to check if user is host or participant
const isHost = (matrix: CarverMatrix): boolean => {
return userEmail ? matrix.hosts?.includes(userEmail) || false : false;
};

const isParticipant = (matrix: CarverMatrix): boolean => {
return userEmail ? matrix.participants?.includes(userEmail) || false : false;
};

const handleMatrixSelect = (matrixId: number) => {
window.location.href = `/EditMatrix?matrixId=${matrixId}`;
};
Expand Down Expand Up @@ -381,16 +397,37 @@ const MatrixExplorer: React.FC = () => {
gap: 1.5,
boxSizing: 'border-box',
pr: 0.5,
'&::-webkit-scrollbar': {
width: '6px',
},
'&::-webkit-scrollbar-track': {
background: 'rgba(255, 255, 255, 0.05)',
borderRadius: '3px',
},
'&::-webkit-scrollbar-thumb': {
background: 'rgba(255, 255, 255, 0.2)',
borderRadius: '3px',
'&:hover': {
background: 'rgba(255, 255, 255, 0.3)',
},
},
}}
>
{filteredMatrices.map((matrix) => (
<MiniMatrixCard
key={matrix.matrixId}
title={matrix.name}
onSelectMatrix={() => handleMatrixSelect(matrix.matrixId)}
titleColor="#ffffff"
/>
))}
{sortedMatrices.length > 0 ? (
sortedMatrices.map((matrix) => (
<MiniMatrixCard
key={matrix.matrixId}
title={matrix.name}
onSelectMatrix={() => handleMatrixSelect(matrix.matrixId)}
isHost={isHost(matrix)}
isParticipant={isParticipant(matrix)}
/>
))
) : (
<Typography variant="body2" color="text.secondary" align="center">
No matrices found
</Typography>
)}
</Box>
</Box>
);
Expand Down
49 changes: 33 additions & 16 deletions ui/src/components/custom/search/miniMatrixCard.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import React from "react";
import { Typography, Paper } from "@mui/material";
import { Typography, Paper, Box } from "@mui/material";
import AdminPanelSettingsIcon from '@mui/icons-material/AdminPanelSettings';
import PersonIcon from '@mui/icons-material/Person';

interface MiniMatrixCardProps {
title: string;
onSelectMatrix: () => void;
titleColor?: string;
isHost?: boolean;
isParticipant?: boolean;
}

const MiniMatrixCard: React.FC<MiniMatrixCardProps> = ({
title,
onSelectMatrix,
titleColor = "#ffffff",
isHost = false,
isParticipant = false,
}) => {
return (
<Paper
Expand All @@ -37,19 +41,32 @@ const MiniMatrixCard: React.FC<MiniMatrixCardProps> = ({
}}
onClick={onSelectMatrix}
>
<Typography
variant="subtitle2"
fontWeight="bold"
color={titleColor}
sx={{
fontSize: "0.9rem",
fontFamily: "'Roboto Condensed', sans-serif",
textTransform: "uppercase",
letterSpacing: "0.5px",
}}
>
{title || ""}
</Typography>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
{isHost && (
<AdminPanelSettingsIcon sx={{ color: '#4D9FFF', fontSize: 20 }} />
)}
{!isHost && isParticipant && (
<PersonIcon sx={{ color: '#00E676', fontSize: 20 }} />
)}
<Typography
variant="subtitle2"
fontWeight="bold"
sx={{
fontSize: "0.9rem",
fontFamily: "'Roboto Condensed', sans-serif",
textTransform: "uppercase",
letterSpacing: "0.5px",
overflow: "hidden",
textOverflow: "ellipsis",
display: "-webkit-box",
WebkitLineClamp: 2,
WebkitBoxOrient: "vertical",
color: "#ffffff",
}}
>
{title || ""}
</Typography>
</Box>
</Paper>
);
};
Expand Down
38 changes: 32 additions & 6 deletions ui/src/components/navigation/Redirect.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useContext, useEffect, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import { GlobalContext } from "../../context/GlobalContext";
import { useUnsavedChanges } from "../../context/UnsavedChangesContext";
import {
ADMIN_ROUTES,
blueTheme,
Expand Down Expand Up @@ -39,6 +40,7 @@ export const Redirect: React.FC<RedirectProps> = ({ children }) => {
const location = useLocation();
const [height, setHeight] = useState<number>(window.innerHeight);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const { hasUnsavedChanges, showUnsavedChangesDialog } = useUnsavedChanges();

// Map routes to display names for breadcrumbs
const routeNames = {
Expand All @@ -65,7 +67,11 @@ export const Redirect: React.FC<RedirectProps> = ({ children }) => {

const handleProfile = () => {
handleProfileMenuClose();
navigate(ROUTES.profile);
if (hasUnsavedChanges) {
showUnsavedChangesDialog(() => navigate(ROUTES.profile));
} else {
navigate(ROUTES.profile);
}
};

const handleLogout = () => {
Expand Down Expand Up @@ -134,7 +140,7 @@ export const Redirect: React.FC<RedirectProps> = ({ children }) => {
const getBreadcrumbs = () => {
const pathnames = location.pathname.split('/').filter((x) => x);
let currentPath = '';
let breadcrumbPaths: string[] = [];
const breadcrumbPaths: string[] = [];

// Build the breadcrumb paths array
pathnames.forEach((value) => {
Expand All @@ -150,14 +156,22 @@ export const Redirect: React.FC<RedirectProps> = ({ children }) => {
breadcrumbPaths.push(currentPath);
});

const handleNavigation = (path: string) => {
if (hasUnsavedChanges) {
showUnsavedChangesDialog(() => navigate(path));
} else {
navigate(path);
}
};

return (
<Breadcrumbs
separator={<NavigateNextIcon sx={{ color: 'rgba(255, 255, 255, 0.7)', fontSize: '1.2rem' }} />}
sx={{ ml: 2 }}
>
<Link
component="button"
onClick={() => navigate(ROUTES.landing)}
onClick={() => handleNavigation(ROUTES.landing)}
sx={{
color: '#ffffff',
textDecoration: 'none',
Expand Down Expand Up @@ -189,7 +203,7 @@ export const Redirect: React.FC<RedirectProps> = ({ children }) => {
<Link
key={path}
component="button"
onClick={() => navigate(path)}
onClick={() => handleNavigation(path)}
sx={{
color: '#ffffff',
textDecoration: 'none',
Expand Down Expand Up @@ -234,7 +248,13 @@ export const Redirect: React.FC<RedirectProps> = ({ children }) => {
flex: 1,
}}
>
<IconButton onClick={() => navigate(ROUTES.landing)}>
<IconButton onClick={() => {
if (hasUnsavedChanges) {
showUnsavedChangesDialog(() => navigate(ROUTES.landing));
} else {
navigate(ROUTES.landing);
}
}}>
<img src="/AIDIV-logo.svg" />
</IconButton>
{getBreadcrumbs()}
Expand All @@ -252,7 +272,13 @@ export const Redirect: React.FC<RedirectProps> = ({ children }) => {
<>
<Typography variant="h6">Dashboard</Typography>
<Stack>
<IconButton onClick={() => navigate(ROUTES.admin)}>
<IconButton onClick={() => {
if (hasUnsavedChanges) {
showUnsavedChangesDialog(() => navigate(ROUTES.admin));
} else {
navigate(ROUTES.admin);
}
}}>
<SpaceDashboardOutlined
sx={{ color: "#FFF" }}
></SpaceDashboardOutlined>
Expand Down
Loading
Loading