@@ -15,6 +15,30 @@ const SLA_INPUT_FIELD_ID = 'jira-helper-sla-input';
1515
1616const log10 = x => Math . log ( x ) / Math . log ( 10 ) ;
1717
18+ const getBasicSlaRect = ( chartElement , slaPathElementIdentifier , strokeColor ) => {
19+ const rectId = `${ slaPathElementIdentifier } -rect` ;
20+ if ( document . getElementById ( rectId ) ) {
21+ return document . getElementById ( rectId ) ;
22+ }
23+
24+ const namespace = chartElement . namespaceURI ;
25+
26+ const slaRect = document . createElementNS ( namespace , 'rect' ) ;
27+ slaRect . id = rectId ;
28+ slaRect . setAttributeNS ( null , 'fill' , strokeColor || SLA_COLOR ) ;
29+ slaRect . setAttributeNS ( null , 'stroke' , strokeColor || SLA_COLOR ) ;
30+ slaRect . setAttributeNS ( null , 'fill-opacity' , '0.15' ) ;
31+ slaRect . setAttributeNS ( null , 'stroke-width' , '1' ) ;
32+ slaRect . setAttributeNS ( null , 'x' , '0' ) ;
33+ slaRect . setAttributeNS ( null , 'y' , '0' ) ;
34+ slaRect . setAttributeNS ( null , 'width' , '0' ) ;
35+ slaRect . setAttributeNS ( null , 'height' , '0' ) ;
36+
37+ chartElement . querySelector ( '.layer.mean' ) . appendChild ( slaRect ) ;
38+
39+ return slaRect ;
40+ } ;
41+
1842const getBasicSlaPath = ( chartElement , slaPathElementIdentifier , strokeColor ) => {
1943 if ( document . getElementById ( slaPathElementIdentifier ) ) {
2044 return document . getElementById ( slaPathElementIdentifier ) ;
@@ -58,11 +82,10 @@ const getSlaLabel = (chartElement, slaPathElementIdentifier, fillColor) => {
5882 return slaLabelText ;
5983} ;
6084
61- const renderSlaPercentageLabel = ( chartElement , value , slaPosition , slaPathElementIdentifier , fillColor ) => {
62- const singleIssuesUnderSlaCount = [ ...chartElement . querySelectorAll ( 'g.layer.issues circle.issue' ) ] . filter (
63- issue => issue . attributes . cy . value >= slaPosition
64- ) . length ;
65- const issuesInClustersUnderSlaCount = [ ...chartElement . querySelectorAll ( 'g.layer.issue-clusters circle.cluster' ) ]
85+ const calculateSlaPercentile = ( { slaPosition, issues, issuesCluster } ) => {
86+ const singleIssuesUnderSlaCount = issues . filter ( issue => issue . attributes . cy . value >= slaPosition ) . length ;
87+
88+ const issuesInClustersUnderSlaCount = issuesCluster
6689 . filter ( issue => issue . attributes . cy . value >= slaPosition )
6790 . map ( cluster =>
6891 Math . round (
@@ -76,30 +99,95 @@ const renderSlaPercentageLabel = (chartElement, value, slaPosition, slaPathEleme
7699 )
77100 )
78101 . reduce ( ( a , b ) => a + b , 0 ) ;
102+
79103 const totalIssuesCount = document . querySelector ( '.js-chart-snapshot-issue-count' ) . innerText . replace ( ',' , '' ) ;
104+
80105 const percentUnderSla = Math . round (
81106 ( ( singleIssuesUnderSlaCount + issuesInClustersUnderSlaCount ) / totalIssuesCount ) * 100
82107 ) ;
83108
84- const slaLabel = getSlaLabel ( chartElement , slaPathElementIdentifier , fillColor ) ;
109+ return percentUnderSla ;
110+ } ;
111+
112+ const renderSlaPercentageLabel = ( { chartElement, value, slaPercentile, slaPosition, pathId, strokeColor } ) => {
113+ const slaLabel = getSlaLabel ( chartElement , pathId , strokeColor ) ;
85114
86115 slaLabel . firstChild . innerHTML = `${ value } d` ;
87- slaLabel . lastChild . innerHTML = `${ percentUnderSla } %` ;
116+ slaLabel . lastChild . innerHTML = `${ slaPercentile } %` ;
88117 slaLabel . setAttributeNS ( null , 'y' , slaPosition + 12 ) ;
89118} ;
90119
120+ const findRangeForSlaRectPosition = ( { slaPercentile, ticsVals, issues, issuesCluster } ) => {
121+ const maxDay = ticsVals [ ticsVals . length - 1 ] . value ;
122+ const slaPosition = [ 0 , 0 ] ;
123+ const step = maxDay < 50 ? 0.5 : 1 ;
124+ let pIn = 0 ;
125+ let day = ticsVals [ 0 ] . value ;
126+
127+ let soughtPercentile = 0 ;
128+ let valPosition = 0 ;
129+
130+ while ( pIn < 2 && day <= maxDay ) {
131+ valPosition = getChartLinePosition ( ticsVals , day ) ;
132+ soughtPercentile = calculateSlaPercentile ( { slaPosition : valPosition , issues, issuesCluster } ) ;
133+
134+ day += step ; // for case if user set fractional number to input
135+ if ( soughtPercentile === slaPercentile ) {
136+ slaPosition [ pIn ] = valPosition ;
137+
138+ if ( pIn === 0 ) {
139+ pIn += 1 ;
140+ slaPosition [ pIn ] = valPosition ; // if one step on the one Percentile
141+ // eslint-disable-next-line no-continue
142+ continue ;
143+ }
144+ }
145+
146+ if ( pIn === 1 && soughtPercentile !== slaPercentile ) {
147+ // exit from top board
148+ pIn += 1 ;
149+ break ;
150+ }
151+ }
152+
153+ slaPosition [ 0 ] = Number . isNaN ( slaPosition [ 0 ] ) ? 0 : slaPosition [ 0 ] ;
154+ slaPosition [ 1 ] = Number . isNaN ( slaPosition [ 1 ] ) ? 0 : slaPosition [ 1 ] ;
155+
156+ return slaPosition ;
157+ } ;
158+
91159const renderSlaLine = ( sla , chartElement , changingSlaValue = sla ) => {
92160 const ticsVals = getChartTics ( chartElement ) ;
93161
162+ const issues = [ ...chartElement . querySelectorAll ( 'g.layer.issues circle.issue' ) ] ;
163+ const issuesCluster = [ ...chartElement . querySelectorAll ( 'g.layer.issue-clusters circle.cluster' ) ] ;
164+
94165 const meanLine = chartElement . querySelector ( '.control-chart-mean' ) ;
95166 const [ , rightPoint ] = meanLine . getAttribute ( 'd' ) . split ( 'L' ) ;
96167 const [ lineLength ] = rightPoint . split ( ',' ) ;
97168
98169 const renderSvgLine = ( { value, pathId, strokeColor } ) => {
99- const slaPath = getBasicSlaPath ( chartElement , pathId , strokeColor ) ;
100170 const slaPosition = getChartLinePosition ( ticsVals , value ) ;
171+ if ( Number . isNaN ( slaPosition ) ) return ;
172+
173+ const slaPercentile = calculateSlaPercentile ( { slaPosition, issues, issuesCluster } ) ;
174+ const [ minSlaPosition , maxSlaPosition ] = findRangeForSlaRectPosition ( {
175+ slaPercentile,
176+ ticsVals,
177+ issues,
178+ issuesCluster,
179+ } ) ;
180+
181+ const slaPath = getBasicSlaPath ( chartElement , pathId , strokeColor ) ;
101182 slaPath . setAttributeNS ( null , 'd' , `M0,${ slaPosition } L${ lineLength } ,${ slaPosition } ` ) ;
102- renderSlaPercentageLabel ( chartElement , value , slaPosition , pathId , strokeColor ) ;
183+
184+ const slaRect = getBasicSlaRect ( chartElement , pathId , strokeColor ) ;
185+ const slaRectHeight = minSlaPosition - maxSlaPosition ;
186+ slaRect . setAttributeNS ( null , 'y' , maxSlaPosition ) ;
187+ slaRect . setAttributeNS ( null , 'width' , lineLength ) ;
188+ slaRect . setAttributeNS ( null , 'height' , slaRectHeight ) ;
189+
190+ renderSlaPercentageLabel ( { chartElement, value, slaPercentile, slaPosition, pathId, strokeColor } ) ;
103191 } ;
104192
105193 renderSvgLine ( {
0 commit comments