Skip to content
Open
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
88 changes: 84 additions & 4 deletions src/components/BMDashboard/Issues/openIssueCharts.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState, useRef } from 'react';
import { useEffect, useState, useRef, useMemo } from 'react';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
import { useDispatch, useSelector } from 'react-redux';
Expand Down Expand Up @@ -92,7 +92,7 @@ const createSelectStyles = (isDark, textColor) => ({

function IssueCharts() {
const dispatch = useDispatch();
const darkMode = useSelector(state => state.theme.darkMode);
const darkMode = useSelector(state => state.theme?.darkMode);
const { issues, loading, error, selectedProjects } = useSelector(state => state.bmissuechart);
const projects = useSelector(state => state.bmProjects);

Expand Down Expand Up @@ -125,6 +125,86 @@ function IssueCharts() {
padding: '20px',
};

// Normalize issues for chart
// Number issues per project to avoid conflicts when multiple projects are selected
// Prefix with project name when multiple projects are selected to distinguish them
const normalizedIssues = useMemo(() => {
if (!issues || issues.length === 0) return [];

// Check if multiple projects are selected
const uniqueProjectIds = new Set((issues || []).map(item => item.projectId).filter(Boolean));
Copy link
Copy Markdown

@naznin07 naznin07 Mar 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useMemo normalization system added.

PR # 4653

const multipleProjects = uniqueProjectIds.size > 1;

// Group issues by projectId
const issuesByProject = new Map();
(issues || []).forEach(item => {
const projectId = item.projectId || 'unknown';
if (!issuesByProject.has(projectId)) {
issuesByProject.set(projectId, []);
}
issuesByProject.get(projectId).push(item);
});

// Create per-project numbering maps
const projectNumberMaps = new Map();

issuesByProject.forEach((projectIssues, projectId) => {
const issueIdToNumber = new Map();
let counter = 1;

// Sort issues by issueId within each project for consistent ordering
const sortedById = [...projectIssues].sort((a, b) => {
const idA = a.issueId || '';
const idB = b.issueId || '';
return idA.localeCompare(idB);
});

// Assign numbers to issues without names within this project
sortedById.forEach(item => {
if (!item.issueName && item.issueId && !issueIdToNumber.has(item.issueId)) {
issueIdToNumber.set(item.issueId, counter++);
}
});

projectNumberMaps.set(projectId, issueIdToNumber);
});

// Map back to original order (sorted by duration) but use per-project numbers
return (issues || []).map(item => {
const projectId = item.projectId || 'unknown';
const projectNumberMap = projectNumberMaps.get(projectId);

// Generate the base issue name
let baseIssueName = item.issueName;
let isGeneratedName = false;

if (!baseIssueName) {
// If no name, generate Issue #X based on project numbering
if (item.issueId && projectNumberMap && projectNumberMap.has(item.issueId)) {
baseIssueName = `Issue #${projectNumberMap.get(item.issueId)}`;
isGeneratedName = true;
} else {
baseIssueName = 'Untitled Issue';
isGeneratedName = true;
}
}

// Only prefix with project name if:
// 1. Multiple projects are selected AND
// 2. The issue name was generated (Issue #X), not a real name
// This keeps the display clean for named issues while distinguishing unnamed issues
const finalIssueName =
multipleProjects && isGeneratedName && item.projectName
? `${item.projectName} - ${baseIssueName}`
: baseIssueName;

return {
issueName: finalIssueName,
durationOpen: item.durationOpen ?? 0,
};
});
}, [issues]);

useEffect(() => {
dispatch(fetchBMProjects());
}, [dispatch]);
Expand Down Expand Up @@ -185,7 +265,7 @@ function IssueCharts() {
chartContent = <div style={errorMessageStyle}>Error: {error}</div>;
} else if (loading) {
chartContent = <div style={loadingMessageStyle}>Loading chart data...</div>;
} else if (!issues || issues.length === 0) {
} else if (!normalizedIssues || normalizedIssues.length === 0) {
chartContent = (
<div className={noDataMessageClass}>
<div className={noDataContentClass}>
Expand All @@ -198,7 +278,7 @@ function IssueCharts() {
} else {
chartContent = (
<ResponsiveContainer width="100%" height={400}>
<BarChart data={issues} layout="vertical" margin={margin}>
<BarChart data={normalizedIssues} layout="vertical" margin={margin}>
<CartesianGrid stroke={gridColor} />
<XAxis
type="number"
Expand Down
100 changes: 70 additions & 30 deletions src/components/CommunityPortal/Calendar/CommunityCalendar.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,13 @@
border: 2px solid #ddd;
border-radius: 8px;
overflow: hidden;
background-color: #fff;
background-color: #fff !important;
color: #000 !important;
}

.reactCalendarDarkMode {
background-color: #1b2a41;
color: #ffffff;
background-color: #1B2A41 !important;
color: #FFFFFF !important;
border: 1px solid #444;
}

Expand Down Expand Up @@ -135,40 +136,90 @@

.reactCalendar :global(.react-calendar__month-view__weekdays__weekday) abbr {
text-decoration: none !important;
color: #000 !important;
}

.reactCalendar :global(.react-calendar__month-view__weekdays__weekday) {
color: #000 !important;
}

.reactCalendarDarkMode :global(.react-calendar__month-view__weekdays__weekday) {
color: #FFFFFF !important;
}

.reactCalendarDarkMode :global(.react-calendar__month-view__weekdays__weekday) abbr {
color: #FFFFFF !important;
}

.reactCalendar :global(.react-calendar__month-view__days__day) {
height: 80px;
border: 1px solid #000000;
vertical-align: top;
padding: 2px;
color: #000 !important;
}

.reactCalendarDarkMode :global(.react-calendar__month-view__days__day) {
color: #FFFFFF !important;
border: 1px solid #666 !important;
}

.reactCalendar :global(.react-calendar__navigation) {
background-color: #f9f9f9;
background-color: #f9f9f9 !important;
border-bottom: 1px solid #ddd;
margin-bottom: 0px !important;
color: #000 !important;
}

.reactCalendarDarkMode :global(.react-calendar__navigation) {
background-color: #1B2A41 !important;
color: #FFFFFF !important;
border-bottom: 1px solid #444;
}

.reactCalendar :global(.react-calendar__navigation button) {
color: #000 !important;
}

.reactCalendarDarkMode :global(.react-calendar__navigation button) {
color: #FFFFFF !important;
}

.reactCalendar :global(.react-calendar__navigation button:hover),
.reactCalendar :global(.react-calendar__navigation button:enabled:hover) {
background-color: #e6e6e6 !important;
}

.reactCalendarDarkMode :global(.react-calendar__navigation button:hover),
.reactCalendarDarkMode :global(.react-calendar__navigation button:enabled:hover) {
background-color: #3A506B !important;
}

.reactCalendar :global(.react-calendar__tile) {
display: block;
height: 90px;
background: #fff;
background: #fff !important;
border: 1px solid #dee2e6 !important;
box-sizing: border-box;
transition: background 0.3s, border-color 0.3s ease;
overflow: hidden;
padding: 4px;
color: #1a202c;
color: #000 !important;
}
.reactCalendarDarkMode :global(.react-calendar__tile) {
background: transparent;
color: #ffffff;
background: transparent !important;
color: #FFFFFF !important;
border: 1px solid #444 !important;
}

.reactCalendar :global(.react-calendar__tile):hover {
background-color: #f5f5f5;
border-color: #999;
background-color: #f5f5f5 !important;
border-color: #999 !important;
}

.reactCalendarDarkMode :global(.react-calendar__tile):hover {
background-color: #3A506B !important;
border-color: #666 !important;
}

/* Prevent hover from overriding selected date styling - light mode */
Expand Down Expand Up @@ -201,11 +252,6 @@
filter: brightness(1.8) contrast(1.5) !important;
}

.reactCalendarDarkMode :global(.react-calendar__tile):hover {
background-color: #2d3748;
border-color: #4a5568;
}

.reactCalendar :global(.react-calendar__tile) .tileEvents {
font-size: 0.9rem;
color: #555;
Expand Down Expand Up @@ -329,9 +375,16 @@
background-color: #718096;
}

.react-calendar__tile--active,
.react-calendar__tile--now {
.reactCalendar :global(.react-calendar__tile--active),
.reactCalendar :global(.react-calendar__tile--now) {
background-color: transparent !important;
color: #000 !important;
}

.reactCalendarDarkMode :global(.react-calendar__tile--active),
.reactCalendarDarkMode :global(.react-calendar__tile--now) {
background-color: transparent !important;
color: #FFFFFF !important;
}

/* Ensure today's date is visible in light mode */
Expand Down Expand Up @@ -934,19 +987,6 @@
color: #fff;
}

.reactCalendarDarkMode :global(.react-calendar__navigation) {
background-color: #2d3748;
border-bottom-color: #4a5568;
}

.reactCalendarDarkMode :global(.react-calendar__month-view__weekdays__weekday) {
color: #e2e8f0;
}

.reactCalendarDarkMode :global(.react-calendar__month-view__weekdays__weekday) abbr {
color: #e2e8f0;
}

.selectedDate {
box-shadow: inset 0 0 0 2px #3182ce;
border-radius: 8px;
Expand Down
Loading