@@ -16,6 +16,7 @@ import ErrorBoundary from "@/components/errorBoundary.tsx";
1616import '../GraphvizContainer.css' ;
1717import { Context } from "@/Context.tsx" ;
1818import { Button } from './ui/button' ;
19+ import { Download } from 'lucide-react' ;
1920
2021// History item interface
2122interface HistoryItem {
@@ -38,6 +39,7 @@ interface GraphvizParentProps {
3839 onMaxEdgeCountChange : ( count : number ) => void ;
3940 onMaxMinEdgeCountChange : ( count : number ) => void ;
4041 errorMode : boolean ;
42+ uniqueStudentMode : boolean ;
4143}
4244
4345const GraphvizParent : React . FC < GraphvizParentProps > = ( {
@@ -47,7 +49,8 @@ const GraphvizParent: React.FC<GraphvizParentProps> = ({
4749 minVisits,
4850 onMaxEdgeCountChange,
4951 onMaxMinEdgeCountChange,
50- errorMode
52+ errorMode,
53+ uniqueStudentMode
5154} ) => {
5255 const [ dotString , setDotString ] = useState < string | null > ( null ) ;
5356 const [ filteredDotString , setFilteredDotString ] = useState < string | null > ( null ) ;
@@ -110,7 +113,15 @@ const GraphvizParent: React.FC<GraphvizParentProps> = ({
110113 // Calculate and update the maximum minimum-edge count
111114 const sequenceToUse = selectedSequence || topSequences [ 0 ] ?. sequence ;
112115 if ( sequenceToUse ) {
113- const maxMinEdgeCount = calculateMaxMinEdgeCount ( newEdgeCounts , sequenceToUse ) ;
116+ console . log ( "GraphvizParent: Calculating maxMinEdgeCount for MAIN graph" ) ;
117+ console . log ( "GraphvizParent: Sequence length:" , sequenceToUse . length ) ;
118+ console . log ( "GraphvizParent: Total edge count keys:" , Object . keys ( newEdgeCounts ) . length ) ;
119+ console . log ( "GraphvizParent: Unique student mode:" , uniqueStudentMode ) ;
120+
121+ // Use edgeCounts (unique students) or totalVisits based on mode
122+ const countsToUse = uniqueStudentMode ? newEdgeCounts : totalVisits ;
123+ const maxMinEdgeCount = calculateMaxMinEdgeCount ( countsToUse , sequenceToUse ) ;
124+ console . log ( "GraphvizParent: Setting maxMinEdgeCount to:" , maxMinEdgeCount ) ;
114125 onMaxMinEdgeCountChange ( maxMinEdgeCount ) ;
115126 }
116127
@@ -121,7 +132,13 @@ const GraphvizParent: React.FC<GraphvizParentProps> = ({
121132 }
122133 }
123134
124- const normalizedThicknesses = normalizeThicknesses ( newEdgeCounts , maxEdgeCount , 10 ) ;
135+ // Use appropriate data for thickness normalization based on mode
136+ const countsForThickness = uniqueStudentMode ? newEdgeCounts : totalVisits ;
137+ const maxCountForThickness = uniqueStudentMode ? maxEdgeCount : Math . max ( ...Object . values ( totalVisits ) , 1 ) ;
138+ const normalizedThicknesses = normalizeThicknesses ( countsForThickness , maxCountForThickness , 10 ) ;
139+
140+ console . log ( "GraphvizParent: Using counts for thickness:" , uniqueStudentMode ? "unique students" : "total visits" ) ;
141+ console . log ( "GraphvizParent: Max count for thickness:" , maxCountForThickness ) ;
125142
126143 const dotString = generateDotString (
127144 normalizedThicknesses ,
@@ -136,7 +153,8 @@ const GraphvizParent: React.FC<GraphvizParentProps> = ({
136153 totalVisits ,
137154 repeatVisits ,
138155 errorMode ,
139- mainGraphData . firstAttemptOutcomes
156+ mainGraphData . firstAttemptOutcomes ,
157+ uniqueStudentMode
140158 ) ;
141159
142160 setDotString ( dotString ) ;
@@ -155,11 +173,12 @@ const GraphvizParent: React.FC<GraphvizParentProps> = ({
155173 totalVisits ,
156174 repeatVisits ,
157175 errorMode ,
158- mainGraphData . firstAttemptOutcomes
176+ mainGraphData . firstAttemptOutcomes ,
177+ uniqueStudentMode
159178 )
160179 ) ;
161180 }
162- } , [ mainGraphData , minVisits , selectedSequence , setTop5Sequences , top5Sequences , onMaxEdgeCountChange , onMaxMinEdgeCountChange , errorMode ] ) ;
181+ } , [ mainGraphData , minVisits , selectedSequence , setTop5Sequences , top5Sequences , onMaxEdgeCountChange , onMaxMinEdgeCountChange , errorMode , uniqueStudentMode ] ) ;
163182
164183 // Memoized filtered graph data
165184 const filteredGraphData = useMemo ( ( ) => {
@@ -202,11 +221,20 @@ const GraphvizParent: React.FC<GraphvizParentProps> = ({
202221 // Calculate max min edge count for filtered data
203222 const sequenceToUse = selectedSequence || top5Sequences ?. [ 0 ] ?. sequence ;
204223 if ( sequenceToUse ) {
205- const filteredMinEdgeCount = calculateMaxMinEdgeCount ( filteredEdgeCounts , sequenceToUse ) ;
224+ console . log ( "GraphvizParent: Calculating maxMinEdgeCount for FILTERED graph" ) ;
225+ console . log ( "GraphvizParent: Filter:" , filter ) ;
226+ console . log ( "GraphvizParent: Filtered edge count keys:" , Object . keys ( filteredEdgeCounts ) . length ) ;
227+ console . log ( "GraphvizParent: Filtered unique student mode:" , uniqueStudentMode ) ;
228+ const filteredCountsToUse = uniqueStudentMode ? filteredEdgeCounts : filteredTotalVisits ;
229+ const filteredMinEdgeCount = calculateMaxMinEdgeCount ( filteredCountsToUse , sequenceToUse ) ;
230+ console . log ( "GraphvizParent: Setting filtered maxMinEdgeCount to:" , filteredMinEdgeCount ) ;
206231 onMaxMinEdgeCountChange ( filteredMinEdgeCount ) ;
207232 }
208233
209- const normalizedThicknesses = normalizeThicknesses ( filteredEdgeCounts , filteredMaxEdgeCount , 10 ) ;
234+ // Use appropriate data for filtered thickness normalization based on mode
235+ const filteredCountsForThickness = uniqueStudentMode ? filteredEdgeCounts : filteredTotalVisits ;
236+ const filteredMaxCountForThickness = uniqueStudentMode ? filteredMaxEdgeCount : Math . max ( ...Object . values ( filteredTotalVisits ) , 1 ) ;
237+ const normalizedThicknesses = normalizeThicknesses ( filteredCountsForThickness , filteredMaxCountForThickness , 10 ) ;
210238
211239 const filteredDotString = generateDotString (
212240 normalizedThicknesses ,
@@ -221,7 +249,8 @@ const GraphvizParent: React.FC<GraphvizParentProps> = ({
221249 filteredTotalVisits ,
222250 filteredRepeatVisits ,
223251 errorMode ,
224- filteredGraphData . firstAttemptOutcomes
252+ filteredGraphData . firstAttemptOutcomes ,
253+ uniqueStudentMode
225254 ) ;
226255
227256 setFilteredDotString ( filteredDotString ) ;
@@ -231,12 +260,13 @@ const GraphvizParent: React.FC<GraphvizParentProps> = ({
231260 if ( mainGraphData ) {
232261 const sequenceToUse = selectedSequence || top5Sequences ?. [ 0 ] ?. sequence ;
233262 if ( sequenceToUse ) {
234- const maxMinEdgeCount = calculateMaxMinEdgeCount ( mainGraphData . edgeCounts , sequenceToUse ) ;
263+ const resetCountsToUse = uniqueStudentMode ? mainGraphData . edgeCounts : mainGraphData . totalVisits ;
264+ const maxMinEdgeCount = calculateMaxMinEdgeCount ( resetCountsToUse , sequenceToUse ) ;
235265 onMaxMinEdgeCountChange ( maxMinEdgeCount ) ;
236266 }
237267 }
238268 }
239- } , [ filteredGraphData , minVisits , selectedSequence , top5Sequences , errorMode , mainGraphData , onMaxMinEdgeCountChange ] ) ;
269+ } , [ filteredGraphData , minVisits , selectedSequence , top5Sequences , errorMode , mainGraphData , onMaxMinEdgeCountChange , uniqueStudentMode ] ) ;
240270
241271 // Cleanup all event listeners when component unmounts
242272 useEffect ( ( ) => {
@@ -1210,7 +1240,7 @@ const GraphvizParent: React.FC<GraphvizParentProps> = ({
12101240 { filter && filter !== 'ALL' && filteredDotString && (
12111241 < div
12121242 className = { `graph-item flex flex-col items-center ${ topDotString && dotString && filteredDotString ? 'w-[400px]' : 'w-[500px]' } border-2 border-gray-700 rounded-lg p-4 bg-gray-100 flex-shrink-0` } >
1213- < h2 className = "text-lg font-semibold text-center mb-4 " > Filtered Graph: { titleCase ( filter ) } </ h2 >
1243+ < h2 className = "text-lg font-semibold text-center mb-2 " > Filtered Graph: { titleCase ( filter ) } </ h2 >
12141244 < div ref = { graphRefFiltered }
12151245 className = "w-full h-[575px] border-2 border-gray-700 rounded-lg p-4 bg-white flex items-center justify-center" > </ div >
12161246 < ExportButton onClick = { ( ) => exportGraphAsPNG ( graphRefFiltered , 'filtered_graph' ) } />
@@ -1301,12 +1331,14 @@ interface ExportButtonProps {
13011331 label ?: string ;
13021332}
13031333
1304- function ExportButton ( { onClick, label = "Export Image " } : ExportButtonProps ) {
1334+ function ExportButton ( { onClick, label = "Export as PNG " } : ExportButtonProps ) {
13051335 return (
13061336 < Button
1307- variant = { 'secondary ' }
1337+ variant = { 'outline ' }
13081338 onClick = { onClick }
1339+ className = "flex items-center gap-2 hover:bg-blue-50 hover:border-blue-300 transition-all duration-200 shadow-sm"
13091340 >
1341+ < Download className = "h-4 w-4" />
13101342 { label }
13111343 </ Button >
13121344 ) ;
0 commit comments