1
- import React from 'react' ;
2
-
3
1
import { useApplicationRepositoryStore } from 'explorviz-frontend/src/stores/repos/application-repository' ;
4
2
import { useEvolutionDataRepositoryStore } from 'explorviz-frontend/src/stores/repos/evolution-data-repository' ;
5
- import { useCommitTreeStateStore } from 'explorviz-frontend/src/stores/commit-tree-state' ;
6
3
import {
7
4
ApplicationMetricsCode ,
8
5
ClassMetricCode ,
@@ -11,6 +8,7 @@ import PopupData from 'explorviz-frontend/src/components/visualization/rendering
11
8
import { Class } from 'explorviz-frontend/src/utils/landscape-schemes/structure-data' ;
12
9
import { calculateFqn } from 'explorviz-frontend/src/utils/landscape-structure-helpers' ;
13
10
import HelpTooltip from 'explorviz-frontend/src/components/help-tooltip.tsx' ;
11
+ import { useCommitTreeStateStore } from 'explorviz-frontend/src/stores/commit-tree-state' ;
14
12
15
13
interface ClazzPopupCodeProps {
16
14
popupData : PopupData ;
@@ -22,12 +20,11 @@ export default function ClazzPopupCode({ popupData }: ClazzPopupCodeProps) {
22
20
useEvolutionDataRepositoryStore (
23
21
( state ) => state . _appNameToCommitIdToApplicationMetricsCodeMap
24
22
) ;
23
+
25
24
const getSelectedCommits = useCommitTreeStateStore (
26
25
( state ) => state . getSelectedCommits
27
26
) ;
28
27
29
- const fileName = ( popupData . entity as Class ) . name ;
30
-
31
28
const appName : string | undefined = ( ( ) => {
32
29
const { applicationId : appId } = popupData ;
33
30
@@ -60,162 +57,104 @@ export default function ClazzPopupCode({ popupData }: ClazzPopupCodeProps) {
60
57
return selectedCommitToApplicationMetricsCodeMap ;
61
58
} ) ( ) ;
62
59
63
- const getNumOfCurrentSelectedCommits = ( ( ) => {
64
- if ( ! appName ) {
65
- return [ ] ;
66
- }
67
-
68
- const selectedCommits = getSelectedCommits ( ) . get ( appName ) ?? [ ] ;
69
-
70
- return selectedCommits . length ;
71
- } ) ( ) ;
72
-
73
- const classnameToCommitAndClassMetricsArray = ( ( ) => {
74
- const classnameToCommitAndClassMetricsArray : Map <
75
- string ,
76
- { commitId : string ; classMetric : ClassMetricCode } [ ]
77
- > = new Map ( ) ;
60
+ const commitIdToClassMetrics = ( ( ) => {
61
+ const commitIdToClassMetric : Map < string , ClassMetricCode > = new Map ( ) ;
78
62
79
- const commitIdToClassMetricsMap : Map <
80
- string ,
81
- Map < string , ClassMetricCode >
82
- > = new Map ( ) ;
83
-
84
- const fqnForClass = calculateFqn ( popupData . entity as Class , '/' ) ;
63
+ const fqnForClass = calculateFqn ( popupData . entity as Class , '.' ) ;
85
64
86
65
for ( const [ commitId , appMetricsCode ] of commitToAppMetricsCodeMap ) {
87
- const indexOfFileName = appMetricsCode . files . findIndex ( ( file ) =>
88
- file . includes ( fqnForClass )
89
- ) ;
90
-
91
- if ( indexOfFileName === - 1 ) {
92
- //return commitIdToClassMetricsMap;
66
+ const classMetric = appMetricsCode . classMetrics [ fqnForClass ] ;
67
+ if ( ! classMetric ) {
93
68
continue ;
94
69
}
95
-
96
- const classMetric = appMetricsCode . classMetrics [ indexOfFileName ] ;
97
-
98
- for ( const [ classFqn , metricsData ] of Object . entries ( classMetric ) ) {
99
- const fqnDelimited = classFqn . split ( '.' ) ;
100
- const simpleClassName = fqnDelimited [ fqnDelimited . length - 1 ] ;
101
-
102
- if ( classnameToCommitAndClassMetricsArray . has ( simpleClassName ) ) {
103
- classnameToCommitAndClassMetricsArray
104
- . get ( simpleClassName )
105
- ?. push ( { commitId, classMetric : metricsData } ) ;
106
- } else {
107
- classnameToCommitAndClassMetricsArray . set ( simpleClassName , [
108
- { commitId, classMetric : metricsData } ,
109
- ] ) ;
110
- }
111
-
112
- commitIdToClassMetricsMap . set (
113
- commitId ,
114
- new Map ( [ [ simpleClassName , metricsData ] ] )
115
- ) ;
116
- }
70
+ commitIdToClassMetric . set ( commitId , classMetric ) ;
117
71
}
118
72
119
- return classnameToCommitAndClassMetricsArray ;
73
+ return commitIdToClassMetric ;
120
74
} ) ( ) ;
121
75
122
- const keyValuePairs = Array . from (
123
- classnameToCommitAndClassMetricsArray . entries ( )
76
+ const keyValuePairs = Array . from ( commitIdToClassMetrics . entries ( ) ) ;
77
+
78
+ // Extract all unique metric keys to use as row headers
79
+ const allMetricKeys = Array . from (
80
+ new Set (
81
+ keyValuePairs . flatMap ( ( [ , classMetric ] ) => Object . keys ( classMetric ) )
82
+ )
124
83
) ;
125
84
85
+ if ( keyValuePairs . length === 0 ) {
86
+ return (
87
+ < div className = "card mb-4" >
88
+ < div className = "card-body" >
89
+ < p > No class metrics found for this entity across commits.</ p >
90
+ </ div >
91
+ </ div >
92
+ ) ;
93
+ }
94
+
95
+ const isFirstCommitId = ( commitId : string ) => {
96
+ if ( ! appName ) {
97
+ return false ;
98
+ }
99
+ const firstCommit = getSelectedCommits ( ) . get ( appName ) ;
100
+ if ( ! firstCommit || firstCommit . length === 0 ) {
101
+ return false ;
102
+ }
103
+ return firstCommit [ 0 ] . commitId === commitId ;
104
+ } ;
105
+
106
+ const getMetricDiff = ( metricKey : string ) => {
107
+ if ( keyValuePairs . length < 2 ) {
108
+ return '' ;
109
+ }
110
+ const firstValue = keyValuePairs [ 0 ] [ 1 ] [ metricKey as keyof ClassMetricCode ] ;
111
+ const secondValue = keyValuePairs [ 1 ] [ 1 ] [ metricKey as keyof ClassMetricCode ] ;
112
+ if ( firstValue === undefined || secondValue === undefined ) {
113
+ return '' ;
114
+ }
115
+ const diff = Number . parseInt ( secondValue ) - Number . parseInt ( firstValue ) ;
116
+ return diff !== 0 ? ` (${ diff > 0 ? '+' : '' } ${ diff } )` : '' ;
117
+ } ;
118
+
126
119
return (
127
- < >
128
- { keyValuePairs . map ( ( [ classname , commitAndClassMetricsArray ] ) => {
129
- return (
130
- < div className = "card mb-4" key = { classname } >
131
- < div className = "card-header" >
132
- < strong > Class Name:</ strong >
133
- { classname }
134
- </ div >
135
- < div className = "card-body" >
136
- < table className = "table table-sm" >
137
- < thead >
138
- < tr >
139
- < th > Commit:</ th >
140
- { commitAndClassMetricsArray . map (
141
- ( commitAndClassMetricsObject , index ) => {
142
- return (
143
- < th className = "text-left" key = { index } >
144
- { shortCommitIdentifierForTable ( index ) }
145
- < HelpTooltip
146
- title = { commitAndClassMetricsObject . commitId }
147
- />
148
- </ th >
149
- ) ;
150
- }
151
- ) }
152
- </ tr >
153
- </ thead >
154
- < tbody >
155
- < tr >
156
- < th > LOC:</ th >
157
- { commitAndClassMetricsArray . map (
158
- ( commitAndClassMetricsObject ) => {
159
- return (
160
- < th className = "text-left" key = { commitAndClassMetricsObject . commitId } >
161
- { commitAndClassMetricsObject . classMetric . loc }
162
- </ th >
163
- ) ;
164
- }
165
- ) }
166
- </ tr >
167
- < tr >
168
- < th > LCOM4:</ th >
169
- { commitAndClassMetricsArray . map (
170
- ( commitAndClassMetricsObject ) => {
171
- return (
172
- < th className = "text-left" key = { commitAndClassMetricsObject . commitId } >
173
- { commitAndClassMetricsObject . classMetric . LCOM4 }
174
- </ th >
175
- ) ;
176
- }
177
- ) }
178
- </ tr >
179
- < tr >
180
- < th > Cyclomatic complexity:</ th >
181
- { commitAndClassMetricsArray . map (
182
- ( commitAndClassMetricsObject ) => {
183
- return (
184
- < th className = "text-left" key = { commitAndClassMetricsObject . commitId } >
185
- {
186
- commitAndClassMetricsObject . classMetric
187
- . cyclomatic_complexity
188
- }
189
- </ th >
190
- ) ;
191
- }
192
- ) }
193
- </ tr >
194
- < tr >
195
- < th > Cyclomatic complexity (weighted):</ th >
196
- { commitAndClassMetricsArray . map (
197
- ( commitAndClassMetricsObject ) => {
198
- return (
199
- < th className = "text-left" key = { commitAndClassMetricsObject . commitId } >
200
- {
201
- commitAndClassMetricsObject . classMetric
202
- . cyclomatic_complexity_weighted
203
- }
204
- </ th >
205
- ) ;
206
- }
207
- ) }
208
- </ tr >
209
- </ tbody >
210
- </ table >
211
- </ div >
212
- </ div >
213
- ) ;
214
- } ) }
215
- </ >
120
+ < div className = "card mb-4" >
121
+ < div className = "card-body" >
122
+ < table className = "table table-sm" >
123
+ < thead >
124
+ < tr >
125
+ { /* First header cell for the metric names */ }
126
+ < th > Metric</ th >
127
+ { /* Headers for each commit */ }
128
+ { keyValuePairs . map ( ( [ commitId , _ ] ) => (
129
+ < th className = "text-left" key = { commitId + '-tooltip' } >
130
+ { 'C-' + ( isFirstCommitId ( commitId ) ? '1' : '2' ) }
131
+ < HelpTooltip title = { commitId } />
132
+ </ th >
133
+ ) ) }
134
+ </ tr >
135
+ </ thead >
136
+ < tbody >
137
+ { /* Rows for each metric */ }
138
+ { allMetricKeys . map ( ( metricKey ) => (
139
+ < tr key = { metricKey } >
140
+ < th > { metricKey } :</ th >
141
+ { /* Data cells for each commit's metric value */ }
142
+ { keyValuePairs . map ( ( [ commitId , classMetric ] , index ) => (
143
+ < td key = { commitId + '-' + metricKey } className = "text-left" >
144
+ { /* Check if the metric exists for this commit, otherwise display N/A*/ }
145
+ { classMetric [ metricKey as keyof ClassMetricCode ] !==
146
+ undefined
147
+ ? String (
148
+ classMetric [ metricKey as keyof ClassMetricCode ]
149
+ ) + ( index == 1 ? getMetricDiff ( metricKey ) : '' )
150
+ : 'N/A' }
151
+ </ td >
152
+ ) ) }
153
+ </ tr >
154
+ ) ) }
155
+ </ tbody >
156
+ </ table >
157
+ </ div >
158
+ </ div >
216
159
) ;
217
160
}
218
-
219
- function shortCommitIdentifierForTable ( tableIndex : number ) {
220
- return `C-${ tableIndex + 1 } ` ;
221
- }
0 commit comments