jira-pat 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/AGENTS.md +218 -0
  2. package/README.md +64 -0
  3. package/backend/.env.example +1 -0
  4. package/backend/__tests__/getJiraClient.test.js +57 -0
  5. package/backend/__tests__/issues.test.js +565 -0
  6. package/backend/__tests__/jiraService.test.js +1127 -0
  7. package/backend/__tests__/projects.test.js +256 -0
  8. package/backend/coverage/clover.xml +426 -0
  9. package/backend/coverage/coverage-final.json +4 -0
  10. package/backend/coverage/lcov-report/base.css +224 -0
  11. package/backend/coverage/lcov-report/block-navigation.js +87 -0
  12. package/backend/coverage/lcov-report/favicon.png +0 -0
  13. package/backend/coverage/lcov-report/index.html +131 -0
  14. package/backend/coverage/lcov-report/prettify.css +1 -0
  15. package/backend/coverage/lcov-report/prettify.js +2 -0
  16. package/backend/coverage/lcov-report/routes/index.html +131 -0
  17. package/backend/coverage/lcov-report/routes/issues.js.html +823 -0
  18. package/backend/coverage/lcov-report/routes/projects.js.html +190 -0
  19. package/backend/coverage/lcov-report/service/index.html +116 -0
  20. package/backend/coverage/lcov-report/service/jiraService.js.html +1663 -0
  21. package/backend/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  22. package/backend/coverage/lcov-report/sorter.js +210 -0
  23. package/backend/coverage/lcov.info +707 -0
  24. package/backend/index.js +38 -0
  25. package/backend/jest.config.js +11 -0
  26. package/backend/package-lock.json +5636 -0
  27. package/backend/package.json +28 -0
  28. package/backend/routes/issues.js +246 -0
  29. package/backend/routes/projects.js +35 -0
  30. package/backend/service/jiraService.js +526 -0
  31. package/bin/jira.js +92 -0
  32. package/frontend/.env.example +1 -0
  33. package/frontend/coverage/base.css +224 -0
  34. package/frontend/coverage/block-navigation.js +87 -0
  35. package/frontend/coverage/clover.xml +559 -0
  36. package/frontend/coverage/components/CreateIssueModal.jsx.html +592 -0
  37. package/frontend/coverage/components/IssueDetailPanel.jsx.html +1633 -0
  38. package/frontend/coverage/components/IssueDrawer.jsx.html +550 -0
  39. package/frontend/coverage/components/IssueTable.jsx.html +571 -0
  40. package/frontend/coverage/components/SkeletonComponents.jsx.html +223 -0
  41. package/frontend/coverage/components/ToastContainer.jsx.html +142 -0
  42. package/frontend/coverage/components/index.html +191 -0
  43. package/frontend/coverage/coverage-final.json +14 -0
  44. package/frontend/coverage/favicon.png +0 -0
  45. package/frontend/coverage/hooks/index.html +161 -0
  46. package/frontend/coverage/hooks/useFocusTrap.js.html +262 -0
  47. package/frontend/coverage/hooks/useIssueDrawer.js.html +1000 -0
  48. package/frontend/coverage/hooks/useIssuesList.js.html +175 -0
  49. package/frontend/coverage/hooks/useToasts.js.html +142 -0
  50. package/frontend/coverage/index.html +161 -0
  51. package/frontend/coverage/prettify.css +1 -0
  52. package/frontend/coverage/prettify.js +2 -0
  53. package/frontend/coverage/services/api.js.html +547 -0
  54. package/frontend/coverage/services/index.html +116 -0
  55. package/frontend/coverage/sort-arrow-sprite.png +0 -0
  56. package/frontend/coverage/sorter.js +210 -0
  57. package/frontend/coverage/utils/index.html +131 -0
  58. package/frontend/coverage/utils/issueHelpers.jsx.html +334 -0
  59. package/frontend/coverage/utils/sanitize.js.html +166 -0
  60. package/frontend/index.html +13 -0
  61. package/frontend/package-lock.json +3436 -0
  62. package/frontend/package.json +30 -0
  63. package/frontend/src/App.jsx +447 -0
  64. package/frontend/src/__tests__/components/CreateIssueModal.test.jsx +375 -0
  65. package/frontend/src/__tests__/components/IssueDetailPanel.test.jsx +962 -0
  66. package/frontend/src/__tests__/components/IssueDrawer.test.jsx +240 -0
  67. package/frontend/src/__tests__/components/IssueTable.test.jsx +423 -0
  68. package/frontend/src/__tests__/components/ToastContainer.test.jsx +196 -0
  69. package/frontend/src/__tests__/hooks/useFocusTrap.test.js +197 -0
  70. package/frontend/src/__tests__/hooks/useIssueDrawer.test.js +1053 -0
  71. package/frontend/src/__tests__/hooks/useIssuesList.test.js +175 -0
  72. package/frontend/src/__tests__/hooks/useToasts.test.js +110 -0
  73. package/frontend/src/__tests__/services/api.test.js +568 -0
  74. package/frontend/src/__tests__/setup.js +54 -0
  75. package/frontend/src/__tests__/utils/issueHelpers.test.jsx +336 -0
  76. package/frontend/src/__tests__/utils/sanitize.test.js +238 -0
  77. package/frontend/src/components/CreateIssueModal.jsx +169 -0
  78. package/frontend/src/components/ErrorBoundary.jsx +52 -0
  79. package/frontend/src/components/IssueDetailPanel.jsx +517 -0
  80. package/frontend/src/components/IssueDrawer.jsx +155 -0
  81. package/frontend/src/components/IssueTable.jsx +162 -0
  82. package/frontend/src/components/SkeletonComponents.jsx +46 -0
  83. package/frontend/src/components/StandaloneIssuePage.jsx +176 -0
  84. package/frontend/src/components/ToastContainer.jsx +19 -0
  85. package/frontend/src/hooks/useFocusTrap.js +59 -0
  86. package/frontend/src/hooks/useIssueDrawer.js +305 -0
  87. package/frontend/src/hooks/useIssuesList.js +30 -0
  88. package/frontend/src/hooks/useToasts.js +19 -0
  89. package/frontend/src/index.css +2070 -0
  90. package/frontend/src/main.jsx +13 -0
  91. package/frontend/src/services/api.js +154 -0
  92. package/frontend/src/utils/issueHelpers.jsx +84 -0
  93. package/frontend/src/utils/sanitize.js +27 -0
  94. package/frontend/vite.config.js +15 -0
  95. package/package.json +19 -0
@@ -0,0 +1,1000 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for hooks/useIssueDrawer.js</title>
7
+ <meta charset="utf-8" />
8
+ <link rel="stylesheet" href="../prettify.css" />
9
+ <link rel="stylesheet" href="../base.css" />
10
+ <link rel="shortcut icon" type="image/x-icon" href="../favicon.png" />
11
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
12
+ <style type='text/css'>
13
+ .coverage-summary .sorter {
14
+ background-image: url(../sort-arrow-sprite.png);
15
+ }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <div class='wrapper'>
21
+ <div class='pad1'>
22
+ <h1><a href="../index.html">All files</a> / <a href="index.html">hooks</a> useIssueDrawer.js</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">99.49% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>196/197</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">96.36% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>53/55</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">88% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>22/25</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">99.44% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>180/181</span>
50
+ </div>
51
+
52
+
53
+ </div>
54
+ <p class="quiet">
55
+ Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
+ </p>
57
+ <template id="filterTemplate">
58
+ <div class="quiet">
59
+ Filter:
60
+ <input type="search" id="fileSearch">
61
+ </div>
62
+ </template>
63
+ </div>
64
+ <div class='status-line high'></div>
65
+ <pre><table class="coverage">
66
+ <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
+ <a name='L2'></a><a href='#L2'>2</a>
68
+ <a name='L3'></a><a href='#L3'>3</a>
69
+ <a name='L4'></a><a href='#L4'>4</a>
70
+ <a name='L5'></a><a href='#L5'>5</a>
71
+ <a name='L6'></a><a href='#L6'>6</a>
72
+ <a name='L7'></a><a href='#L7'>7</a>
73
+ <a name='L8'></a><a href='#L8'>8</a>
74
+ <a name='L9'></a><a href='#L9'>9</a>
75
+ <a name='L10'></a><a href='#L10'>10</a>
76
+ <a name='L11'></a><a href='#L11'>11</a>
77
+ <a name='L12'></a><a href='#L12'>12</a>
78
+ <a name='L13'></a><a href='#L13'>13</a>
79
+ <a name='L14'></a><a href='#L14'>14</a>
80
+ <a name='L15'></a><a href='#L15'>15</a>
81
+ <a name='L16'></a><a href='#L16'>16</a>
82
+ <a name='L17'></a><a href='#L17'>17</a>
83
+ <a name='L18'></a><a href='#L18'>18</a>
84
+ <a name='L19'></a><a href='#L19'>19</a>
85
+ <a name='L20'></a><a href='#L20'>20</a>
86
+ <a name='L21'></a><a href='#L21'>21</a>
87
+ <a name='L22'></a><a href='#L22'>22</a>
88
+ <a name='L23'></a><a href='#L23'>23</a>
89
+ <a name='L24'></a><a href='#L24'>24</a>
90
+ <a name='L25'></a><a href='#L25'>25</a>
91
+ <a name='L26'></a><a href='#L26'>26</a>
92
+ <a name='L27'></a><a href='#L27'>27</a>
93
+ <a name='L28'></a><a href='#L28'>28</a>
94
+ <a name='L29'></a><a href='#L29'>29</a>
95
+ <a name='L30'></a><a href='#L30'>30</a>
96
+ <a name='L31'></a><a href='#L31'>31</a>
97
+ <a name='L32'></a><a href='#L32'>32</a>
98
+ <a name='L33'></a><a href='#L33'>33</a>
99
+ <a name='L34'></a><a href='#L34'>34</a>
100
+ <a name='L35'></a><a href='#L35'>35</a>
101
+ <a name='L36'></a><a href='#L36'>36</a>
102
+ <a name='L37'></a><a href='#L37'>37</a>
103
+ <a name='L38'></a><a href='#L38'>38</a>
104
+ <a name='L39'></a><a href='#L39'>39</a>
105
+ <a name='L40'></a><a href='#L40'>40</a>
106
+ <a name='L41'></a><a href='#L41'>41</a>
107
+ <a name='L42'></a><a href='#L42'>42</a>
108
+ <a name='L43'></a><a href='#L43'>43</a>
109
+ <a name='L44'></a><a href='#L44'>44</a>
110
+ <a name='L45'></a><a href='#L45'>45</a>
111
+ <a name='L46'></a><a href='#L46'>46</a>
112
+ <a name='L47'></a><a href='#L47'>47</a>
113
+ <a name='L48'></a><a href='#L48'>48</a>
114
+ <a name='L49'></a><a href='#L49'>49</a>
115
+ <a name='L50'></a><a href='#L50'>50</a>
116
+ <a name='L51'></a><a href='#L51'>51</a>
117
+ <a name='L52'></a><a href='#L52'>52</a>
118
+ <a name='L53'></a><a href='#L53'>53</a>
119
+ <a name='L54'></a><a href='#L54'>54</a>
120
+ <a name='L55'></a><a href='#L55'>55</a>
121
+ <a name='L56'></a><a href='#L56'>56</a>
122
+ <a name='L57'></a><a href='#L57'>57</a>
123
+ <a name='L58'></a><a href='#L58'>58</a>
124
+ <a name='L59'></a><a href='#L59'>59</a>
125
+ <a name='L60'></a><a href='#L60'>60</a>
126
+ <a name='L61'></a><a href='#L61'>61</a>
127
+ <a name='L62'></a><a href='#L62'>62</a>
128
+ <a name='L63'></a><a href='#L63'>63</a>
129
+ <a name='L64'></a><a href='#L64'>64</a>
130
+ <a name='L65'></a><a href='#L65'>65</a>
131
+ <a name='L66'></a><a href='#L66'>66</a>
132
+ <a name='L67'></a><a href='#L67'>67</a>
133
+ <a name='L68'></a><a href='#L68'>68</a>
134
+ <a name='L69'></a><a href='#L69'>69</a>
135
+ <a name='L70'></a><a href='#L70'>70</a>
136
+ <a name='L71'></a><a href='#L71'>71</a>
137
+ <a name='L72'></a><a href='#L72'>72</a>
138
+ <a name='L73'></a><a href='#L73'>73</a>
139
+ <a name='L74'></a><a href='#L74'>74</a>
140
+ <a name='L75'></a><a href='#L75'>75</a>
141
+ <a name='L76'></a><a href='#L76'>76</a>
142
+ <a name='L77'></a><a href='#L77'>77</a>
143
+ <a name='L78'></a><a href='#L78'>78</a>
144
+ <a name='L79'></a><a href='#L79'>79</a>
145
+ <a name='L80'></a><a href='#L80'>80</a>
146
+ <a name='L81'></a><a href='#L81'>81</a>
147
+ <a name='L82'></a><a href='#L82'>82</a>
148
+ <a name='L83'></a><a href='#L83'>83</a>
149
+ <a name='L84'></a><a href='#L84'>84</a>
150
+ <a name='L85'></a><a href='#L85'>85</a>
151
+ <a name='L86'></a><a href='#L86'>86</a>
152
+ <a name='L87'></a><a href='#L87'>87</a>
153
+ <a name='L88'></a><a href='#L88'>88</a>
154
+ <a name='L89'></a><a href='#L89'>89</a>
155
+ <a name='L90'></a><a href='#L90'>90</a>
156
+ <a name='L91'></a><a href='#L91'>91</a>
157
+ <a name='L92'></a><a href='#L92'>92</a>
158
+ <a name='L93'></a><a href='#L93'>93</a>
159
+ <a name='L94'></a><a href='#L94'>94</a>
160
+ <a name='L95'></a><a href='#L95'>95</a>
161
+ <a name='L96'></a><a href='#L96'>96</a>
162
+ <a name='L97'></a><a href='#L97'>97</a>
163
+ <a name='L98'></a><a href='#L98'>98</a>
164
+ <a name='L99'></a><a href='#L99'>99</a>
165
+ <a name='L100'></a><a href='#L100'>100</a>
166
+ <a name='L101'></a><a href='#L101'>101</a>
167
+ <a name='L102'></a><a href='#L102'>102</a>
168
+ <a name='L103'></a><a href='#L103'>103</a>
169
+ <a name='L104'></a><a href='#L104'>104</a>
170
+ <a name='L105'></a><a href='#L105'>105</a>
171
+ <a name='L106'></a><a href='#L106'>106</a>
172
+ <a name='L107'></a><a href='#L107'>107</a>
173
+ <a name='L108'></a><a href='#L108'>108</a>
174
+ <a name='L109'></a><a href='#L109'>109</a>
175
+ <a name='L110'></a><a href='#L110'>110</a>
176
+ <a name='L111'></a><a href='#L111'>111</a>
177
+ <a name='L112'></a><a href='#L112'>112</a>
178
+ <a name='L113'></a><a href='#L113'>113</a>
179
+ <a name='L114'></a><a href='#L114'>114</a>
180
+ <a name='L115'></a><a href='#L115'>115</a>
181
+ <a name='L116'></a><a href='#L116'>116</a>
182
+ <a name='L117'></a><a href='#L117'>117</a>
183
+ <a name='L118'></a><a href='#L118'>118</a>
184
+ <a name='L119'></a><a href='#L119'>119</a>
185
+ <a name='L120'></a><a href='#L120'>120</a>
186
+ <a name='L121'></a><a href='#L121'>121</a>
187
+ <a name='L122'></a><a href='#L122'>122</a>
188
+ <a name='L123'></a><a href='#L123'>123</a>
189
+ <a name='L124'></a><a href='#L124'>124</a>
190
+ <a name='L125'></a><a href='#L125'>125</a>
191
+ <a name='L126'></a><a href='#L126'>126</a>
192
+ <a name='L127'></a><a href='#L127'>127</a>
193
+ <a name='L128'></a><a href='#L128'>128</a>
194
+ <a name='L129'></a><a href='#L129'>129</a>
195
+ <a name='L130'></a><a href='#L130'>130</a>
196
+ <a name='L131'></a><a href='#L131'>131</a>
197
+ <a name='L132'></a><a href='#L132'>132</a>
198
+ <a name='L133'></a><a href='#L133'>133</a>
199
+ <a name='L134'></a><a href='#L134'>134</a>
200
+ <a name='L135'></a><a href='#L135'>135</a>
201
+ <a name='L136'></a><a href='#L136'>136</a>
202
+ <a name='L137'></a><a href='#L137'>137</a>
203
+ <a name='L138'></a><a href='#L138'>138</a>
204
+ <a name='L139'></a><a href='#L139'>139</a>
205
+ <a name='L140'></a><a href='#L140'>140</a>
206
+ <a name='L141'></a><a href='#L141'>141</a>
207
+ <a name='L142'></a><a href='#L142'>142</a>
208
+ <a name='L143'></a><a href='#L143'>143</a>
209
+ <a name='L144'></a><a href='#L144'>144</a>
210
+ <a name='L145'></a><a href='#L145'>145</a>
211
+ <a name='L146'></a><a href='#L146'>146</a>
212
+ <a name='L147'></a><a href='#L147'>147</a>
213
+ <a name='L148'></a><a href='#L148'>148</a>
214
+ <a name='L149'></a><a href='#L149'>149</a>
215
+ <a name='L150'></a><a href='#L150'>150</a>
216
+ <a name='L151'></a><a href='#L151'>151</a>
217
+ <a name='L152'></a><a href='#L152'>152</a>
218
+ <a name='L153'></a><a href='#L153'>153</a>
219
+ <a name='L154'></a><a href='#L154'>154</a>
220
+ <a name='L155'></a><a href='#L155'>155</a>
221
+ <a name='L156'></a><a href='#L156'>156</a>
222
+ <a name='L157'></a><a href='#L157'>157</a>
223
+ <a name='L158'></a><a href='#L158'>158</a>
224
+ <a name='L159'></a><a href='#L159'>159</a>
225
+ <a name='L160'></a><a href='#L160'>160</a>
226
+ <a name='L161'></a><a href='#L161'>161</a>
227
+ <a name='L162'></a><a href='#L162'>162</a>
228
+ <a name='L163'></a><a href='#L163'>163</a>
229
+ <a name='L164'></a><a href='#L164'>164</a>
230
+ <a name='L165'></a><a href='#L165'>165</a>
231
+ <a name='L166'></a><a href='#L166'>166</a>
232
+ <a name='L167'></a><a href='#L167'>167</a>
233
+ <a name='L168'></a><a href='#L168'>168</a>
234
+ <a name='L169'></a><a href='#L169'>169</a>
235
+ <a name='L170'></a><a href='#L170'>170</a>
236
+ <a name='L171'></a><a href='#L171'>171</a>
237
+ <a name='L172'></a><a href='#L172'>172</a>
238
+ <a name='L173'></a><a href='#L173'>173</a>
239
+ <a name='L174'></a><a href='#L174'>174</a>
240
+ <a name='L175'></a><a href='#L175'>175</a>
241
+ <a name='L176'></a><a href='#L176'>176</a>
242
+ <a name='L177'></a><a href='#L177'>177</a>
243
+ <a name='L178'></a><a href='#L178'>178</a>
244
+ <a name='L179'></a><a href='#L179'>179</a>
245
+ <a name='L180'></a><a href='#L180'>180</a>
246
+ <a name='L181'></a><a href='#L181'>181</a>
247
+ <a name='L182'></a><a href='#L182'>182</a>
248
+ <a name='L183'></a><a href='#L183'>183</a>
249
+ <a name='L184'></a><a href='#L184'>184</a>
250
+ <a name='L185'></a><a href='#L185'>185</a>
251
+ <a name='L186'></a><a href='#L186'>186</a>
252
+ <a name='L187'></a><a href='#L187'>187</a>
253
+ <a name='L188'></a><a href='#L188'>188</a>
254
+ <a name='L189'></a><a href='#L189'>189</a>
255
+ <a name='L190'></a><a href='#L190'>190</a>
256
+ <a name='L191'></a><a href='#L191'>191</a>
257
+ <a name='L192'></a><a href='#L192'>192</a>
258
+ <a name='L193'></a><a href='#L193'>193</a>
259
+ <a name='L194'></a><a href='#L194'>194</a>
260
+ <a name='L195'></a><a href='#L195'>195</a>
261
+ <a name='L196'></a><a href='#L196'>196</a>
262
+ <a name='L197'></a><a href='#L197'>197</a>
263
+ <a name='L198'></a><a href='#L198'>198</a>
264
+ <a name='L199'></a><a href='#L199'>199</a>
265
+ <a name='L200'></a><a href='#L200'>200</a>
266
+ <a name='L201'></a><a href='#L201'>201</a>
267
+ <a name='L202'></a><a href='#L202'>202</a>
268
+ <a name='L203'></a><a href='#L203'>203</a>
269
+ <a name='L204'></a><a href='#L204'>204</a>
270
+ <a name='L205'></a><a href='#L205'>205</a>
271
+ <a name='L206'></a><a href='#L206'>206</a>
272
+ <a name='L207'></a><a href='#L207'>207</a>
273
+ <a name='L208'></a><a href='#L208'>208</a>
274
+ <a name='L209'></a><a href='#L209'>209</a>
275
+ <a name='L210'></a><a href='#L210'>210</a>
276
+ <a name='L211'></a><a href='#L211'>211</a>
277
+ <a name='L212'></a><a href='#L212'>212</a>
278
+ <a name='L213'></a><a href='#L213'>213</a>
279
+ <a name='L214'></a><a href='#L214'>214</a>
280
+ <a name='L215'></a><a href='#L215'>215</a>
281
+ <a name='L216'></a><a href='#L216'>216</a>
282
+ <a name='L217'></a><a href='#L217'>217</a>
283
+ <a name='L218'></a><a href='#L218'>218</a>
284
+ <a name='L219'></a><a href='#L219'>219</a>
285
+ <a name='L220'></a><a href='#L220'>220</a>
286
+ <a name='L221'></a><a href='#L221'>221</a>
287
+ <a name='L222'></a><a href='#L222'>222</a>
288
+ <a name='L223'></a><a href='#L223'>223</a>
289
+ <a name='L224'></a><a href='#L224'>224</a>
290
+ <a name='L225'></a><a href='#L225'>225</a>
291
+ <a name='L226'></a><a href='#L226'>226</a>
292
+ <a name='L227'></a><a href='#L227'>227</a>
293
+ <a name='L228'></a><a href='#L228'>228</a>
294
+ <a name='L229'></a><a href='#L229'>229</a>
295
+ <a name='L230'></a><a href='#L230'>230</a>
296
+ <a name='L231'></a><a href='#L231'>231</a>
297
+ <a name='L232'></a><a href='#L232'>232</a>
298
+ <a name='L233'></a><a href='#L233'>233</a>
299
+ <a name='L234'></a><a href='#L234'>234</a>
300
+ <a name='L235'></a><a href='#L235'>235</a>
301
+ <a name='L236'></a><a href='#L236'>236</a>
302
+ <a name='L237'></a><a href='#L237'>237</a>
303
+ <a name='L238'></a><a href='#L238'>238</a>
304
+ <a name='L239'></a><a href='#L239'>239</a>
305
+ <a name='L240'></a><a href='#L240'>240</a>
306
+ <a name='L241'></a><a href='#L241'>241</a>
307
+ <a name='L242'></a><a href='#L242'>242</a>
308
+ <a name='L243'></a><a href='#L243'>243</a>
309
+ <a name='L244'></a><a href='#L244'>244</a>
310
+ <a name='L245'></a><a href='#L245'>245</a>
311
+ <a name='L246'></a><a href='#L246'>246</a>
312
+ <a name='L247'></a><a href='#L247'>247</a>
313
+ <a name='L248'></a><a href='#L248'>248</a>
314
+ <a name='L249'></a><a href='#L249'>249</a>
315
+ <a name='L250'></a><a href='#L250'>250</a>
316
+ <a name='L251'></a><a href='#L251'>251</a>
317
+ <a name='L252'></a><a href='#L252'>252</a>
318
+ <a name='L253'></a><a href='#L253'>253</a>
319
+ <a name='L254'></a><a href='#L254'>254</a>
320
+ <a name='L255'></a><a href='#L255'>255</a>
321
+ <a name='L256'></a><a href='#L256'>256</a>
322
+ <a name='L257'></a><a href='#L257'>257</a>
323
+ <a name='L258'></a><a href='#L258'>258</a>
324
+ <a name='L259'></a><a href='#L259'>259</a>
325
+ <a name='L260'></a><a href='#L260'>260</a>
326
+ <a name='L261'></a><a href='#L261'>261</a>
327
+ <a name='L262'></a><a href='#L262'>262</a>
328
+ <a name='L263'></a><a href='#L263'>263</a>
329
+ <a name='L264'></a><a href='#L264'>264</a>
330
+ <a name='L265'></a><a href='#L265'>265</a>
331
+ <a name='L266'></a><a href='#L266'>266</a>
332
+ <a name='L267'></a><a href='#L267'>267</a>
333
+ <a name='L268'></a><a href='#L268'>268</a>
334
+ <a name='L269'></a><a href='#L269'>269</a>
335
+ <a name='L270'></a><a href='#L270'>270</a>
336
+ <a name='L271'></a><a href='#L271'>271</a>
337
+ <a name='L272'></a><a href='#L272'>272</a>
338
+ <a name='L273'></a><a href='#L273'>273</a>
339
+ <a name='L274'></a><a href='#L274'>274</a>
340
+ <a name='L275'></a><a href='#L275'>275</a>
341
+ <a name='L276'></a><a href='#L276'>276</a>
342
+ <a name='L277'></a><a href='#L277'>277</a>
343
+ <a name='L278'></a><a href='#L278'>278</a>
344
+ <a name='L279'></a><a href='#L279'>279</a>
345
+ <a name='L280'></a><a href='#L280'>280</a>
346
+ <a name='L281'></a><a href='#L281'>281</a>
347
+ <a name='L282'></a><a href='#L282'>282</a>
348
+ <a name='L283'></a><a href='#L283'>283</a>
349
+ <a name='L284'></a><a href='#L284'>284</a>
350
+ <a name='L285'></a><a href='#L285'>285</a>
351
+ <a name='L286'></a><a href='#L286'>286</a>
352
+ <a name='L287'></a><a href='#L287'>287</a>
353
+ <a name='L288'></a><a href='#L288'>288</a>
354
+ <a name='L289'></a><a href='#L289'>289</a>
355
+ <a name='L290'></a><a href='#L290'>290</a>
356
+ <a name='L291'></a><a href='#L291'>291</a>
357
+ <a name='L292'></a><a href='#L292'>292</a>
358
+ <a name='L293'></a><a href='#L293'>293</a>
359
+ <a name='L294'></a><a href='#L294'>294</a>
360
+ <a name='L295'></a><a href='#L295'>295</a>
361
+ <a name='L296'></a><a href='#L296'>296</a>
362
+ <a name='L297'></a><a href='#L297'>297</a>
363
+ <a name='L298'></a><a href='#L298'>298</a>
364
+ <a name='L299'></a><a href='#L299'>299</a>
365
+ <a name='L300'></a><a href='#L300'>300</a>
366
+ <a name='L301'></a><a href='#L301'>301</a>
367
+ <a name='L302'></a><a href='#L302'>302</a>
368
+ <a name='L303'></a><a href='#L303'>303</a>
369
+ <a name='L304'></a><a href='#L304'>304</a>
370
+ <a name='L305'></a><a href='#L305'>305</a>
371
+ <a name='L306'></a><a href='#L306'>306</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
372
+ <span class="cline-any cline-neutral">&nbsp;</span>
373
+ <span class="cline-any cline-neutral">&nbsp;</span>
374
+ <span class="cline-any cline-neutral">&nbsp;</span>
375
+ <span class="cline-any cline-neutral">&nbsp;</span>
376
+ <span class="cline-any cline-neutral">&nbsp;</span>
377
+ <span class="cline-any cline-neutral">&nbsp;</span>
378
+ <span class="cline-any cline-neutral">&nbsp;</span>
379
+ <span class="cline-any cline-yes">259x</span>
380
+ <span class="cline-any cline-yes">259x</span>
381
+ <span class="cline-any cline-yes">259x</span>
382
+ <span class="cline-any cline-yes">259x</span>
383
+ <span class="cline-any cline-yes">259x</span>
384
+ <span class="cline-any cline-yes">259x</span>
385
+ <span class="cline-any cline-neutral">&nbsp;</span>
386
+ <span class="cline-any cline-yes">259x</span>
387
+ <span class="cline-any cline-yes">259x</span>
388
+ <span class="cline-any cline-yes">259x</span>
389
+ <span class="cline-any cline-yes">259x</span>
390
+ <span class="cline-any cline-yes">259x</span>
391
+ <span class="cline-any cline-yes">259x</span>
392
+ <span class="cline-any cline-yes">259x</span>
393
+ <span class="cline-any cline-yes">259x</span>
394
+ <span class="cline-any cline-yes">259x</span>
395
+ <span class="cline-any cline-yes">259x</span>
396
+ <span class="cline-any cline-yes">259x</span>
397
+ <span class="cline-any cline-yes">259x</span>
398
+ <span class="cline-any cline-yes">259x</span>
399
+ <span class="cline-any cline-yes">259x</span>
400
+ <span class="cline-any cline-yes">259x</span>
401
+ <span class="cline-any cline-yes">259x</span>
402
+ <span class="cline-any cline-yes">259x</span>
403
+ <span class="cline-any cline-yes">259x</span>
404
+ <span class="cline-any cline-yes">259x</span>
405
+ <span class="cline-any cline-neutral">&nbsp;</span>
406
+ <span class="cline-any cline-yes">259x</span>
407
+ <span class="cline-any cline-yes">60x</span>
408
+ <span class="cline-any cline-neutral">&nbsp;</span>
409
+ <span class="cline-any cline-yes">56x</span>
410
+ <span class="cline-any cline-yes">56x</span>
411
+ <span class="cline-any cline-yes">56x</span>
412
+ <span class="cline-any cline-yes">56x</span>
413
+ <span class="cline-any cline-yes">56x</span>
414
+ <span class="cline-any cline-yes">56x</span>
415
+ <span class="cline-any cline-yes">56x</span>
416
+ <span class="cline-any cline-yes">56x</span>
417
+ <span class="cline-any cline-yes">56x</span>
418
+ <span class="cline-any cline-yes">56x</span>
419
+ <span class="cline-any cline-yes">56x</span>
420
+ <span class="cline-any cline-yes">56x</span>
421
+ <span class="cline-any cline-neutral">&nbsp;</span>
422
+ <span class="cline-any cline-yes">56x</span>
423
+ <span class="cline-any cline-yes">56x</span>
424
+ <span class="cline-any cline-yes">56x</span>
425
+ <span class="cline-any cline-neutral">&nbsp;</span>
426
+ <span class="cline-any cline-neutral">&nbsp;</span>
427
+ <span class="cline-any cline-yes">1x</span>
428
+ <span class="cline-any cline-yes">2x</span>
429
+ <span class="cline-any cline-neutral">&nbsp;</span>
430
+ <span class="cline-any cline-yes">54x</span>
431
+ <span class="cline-any cline-yes">54x</span>
432
+ <span class="cline-any cline-yes">54x</span>
433
+ <span class="cline-any cline-yes">54x</span>
434
+ <span class="cline-any cline-neutral">&nbsp;</span>
435
+ <span class="cline-any cline-yes">54x</span>
436
+ <span class="cline-any cline-yes">52x</span>
437
+ <span class="cline-any cline-yes">52x</span>
438
+ <span class="cline-any cline-neutral">&nbsp;</span>
439
+ <span class="cline-any cline-neutral">&nbsp;</span>
440
+ <span class="cline-any cline-yes">2x</span>
441
+ <span class="cline-any cline-neutral">&nbsp;</span>
442
+ <span class="cline-any cline-yes">56x</span>
443
+ <span class="cline-any cline-neutral">&nbsp;</span>
444
+ <span class="cline-any cline-neutral">&nbsp;</span>
445
+ <span class="cline-any cline-neutral">&nbsp;</span>
446
+ <span class="cline-any cline-yes">56x</span>
447
+ <span class="cline-any cline-neutral">&nbsp;</span>
448
+ <span class="cline-any cline-neutral">&nbsp;</span>
449
+ <span class="cline-any cline-yes">259x</span>
450
+ <span class="cline-any cline-yes">120x</span>
451
+ <span class="cline-any cline-yes">114x</span>
452
+ <span class="cline-any cline-yes">114x</span>
453
+ <span class="cline-any cline-yes">114x</span>
454
+ <span class="cline-any cline-neutral">&nbsp;</span>
455
+ <span class="cline-any cline-yes">6x</span>
456
+ <span class="cline-any cline-yes">2x</span>
457
+ <span class="cline-any cline-yes">2x</span>
458
+ <span class="cline-any cline-yes">1x</span>
459
+ <span class="cline-any cline-yes">2x</span>
460
+ <span class="cline-any cline-yes">2x</span>
461
+ <span class="cline-any cline-yes">2x</span>
462
+ <span class="cline-any cline-neutral">&nbsp;</span>
463
+ <span class="cline-any cline-yes">1x</span>
464
+ <span class="cline-any cline-neutral">&nbsp;</span>
465
+ <span class="cline-any cline-neutral">&nbsp;</span>
466
+ <span class="cline-any cline-yes">6x</span>
467
+ <span class="cline-any cline-neutral">&nbsp;</span>
468
+ <span class="cline-any cline-neutral">&nbsp;</span>
469
+ <span class="cline-any cline-yes">259x</span>
470
+ <span class="cline-any cline-yes">63x</span>
471
+ <span class="cline-any cline-yes">3x</span>
472
+ <span class="cline-any cline-yes">1x</span>
473
+ <span class="cline-any cline-yes">1x</span>
474
+ <span class="cline-any cline-no">&nbsp;</span>
475
+ <span class="cline-any cline-neutral">&nbsp;</span>
476
+ <span class="cline-any cline-yes">1x</span>
477
+ <span class="cline-any cline-neutral">&nbsp;</span>
478
+ <span class="cline-any cline-neutral">&nbsp;</span>
479
+ <span class="cline-any cline-yes">3x</span>
480
+ <span class="cline-any cline-neutral">&nbsp;</span>
481
+ <span class="cline-any cline-neutral">&nbsp;</span>
482
+ <span class="cline-any cline-yes">259x</span>
483
+ <span class="cline-any cline-yes">4x</span>
484
+ <span class="cline-any cline-yes">3x</span>
485
+ <span class="cline-any cline-yes">3x</span>
486
+ <span class="cline-any cline-yes">3x</span>
487
+ <span class="cline-any cline-yes">2x</span>
488
+ <span class="cline-any cline-yes">2x</span>
489
+ <span class="cline-any cline-yes">2x</span>
490
+ <span class="cline-any cline-neutral">&nbsp;</span>
491
+ <span class="cline-any cline-yes">1x</span>
492
+ <span class="cline-any cline-neutral">&nbsp;</span>
493
+ <span class="cline-any cline-yes">3x</span>
494
+ <span class="cline-any cline-neutral">&nbsp;</span>
495
+ <span class="cline-any cline-neutral">&nbsp;</span>
496
+ <span class="cline-any cline-neutral">&nbsp;</span>
497
+ <span class="cline-any cline-yes">259x</span>
498
+ <span class="cline-any cline-yes">5x</span>
499
+ <span class="cline-any cline-neutral">&nbsp;</span>
500
+ <span class="cline-any cline-yes">4x</span>
501
+ <span class="cline-any cline-neutral">&nbsp;</span>
502
+ <span class="cline-any cline-neutral">&nbsp;</span>
503
+ <span class="cline-any cline-neutral">&nbsp;</span>
504
+ <span class="cline-any cline-neutral">&nbsp;</span>
505
+ <span class="cline-any cline-yes">4x</span>
506
+ <span class="cline-any cline-yes">4x</span>
507
+ <span class="cline-any cline-yes">4x</span>
508
+ <span class="cline-any cline-yes">4x</span>
509
+ <span class="cline-any cline-yes">4x</span>
510
+ <span class="cline-any cline-neutral">&nbsp;</span>
511
+ <span class="cline-any cline-yes">4x</span>
512
+ <span class="cline-any cline-yes">4x</span>
513
+ <span class="cline-any cline-yes">3x</span>
514
+ <span class="cline-any cline-yes">3x</span>
515
+ <span class="cline-any cline-yes">5x</span>
516
+ <span class="cline-any cline-neutral">&nbsp;</span>
517
+ <span class="cline-any cline-yes">1x</span>
518
+ <span class="cline-any cline-yes">1x</span>
519
+ <span class="cline-any cline-neutral">&nbsp;</span>
520
+ <span class="cline-any cline-yes">4x</span>
521
+ <span class="cline-any cline-yes">4x</span>
522
+ <span class="cline-any cline-neutral">&nbsp;</span>
523
+ <span class="cline-any cline-neutral">&nbsp;</span>
524
+ <span class="cline-any cline-neutral">&nbsp;</span>
525
+ <span class="cline-any cline-yes">259x</span>
526
+ <span class="cline-any cline-yes">7x</span>
527
+ <span class="cline-any cline-yes">7x</span>
528
+ <span class="cline-any cline-neutral">&nbsp;</span>
529
+ <span class="cline-any cline-yes">6x</span>
530
+ <span class="cline-any cline-yes">1x</span>
531
+ <span class="cline-any cline-yes">1x</span>
532
+ <span class="cline-any cline-neutral">&nbsp;</span>
533
+ <span class="cline-any cline-neutral">&nbsp;</span>
534
+ <span class="cline-any cline-yes">5x</span>
535
+ <span class="cline-any cline-yes">5x</span>
536
+ <span class="cline-any cline-yes">1x</span>
537
+ <span class="cline-any cline-yes">1x</span>
538
+ <span class="cline-any cline-yes">1x</span>
539
+ <span class="cline-any cline-neutral">&nbsp;</span>
540
+ <span class="cline-any cline-neutral">&nbsp;</span>
541
+ <span class="cline-any cline-yes">4x</span>
542
+ <span class="cline-any cline-yes">4x</span>
543
+ <span class="cline-any cline-yes">4x</span>
544
+ <span class="cline-any cline-yes">4x</span>
545
+ <span class="cline-any cline-yes">3x</span>
546
+ <span class="cline-any cline-yes">3x</span>
547
+ <span class="cline-any cline-yes">3x</span>
548
+ <span class="cline-any cline-yes">3x</span>
549
+ <span class="cline-any cline-neutral">&nbsp;</span>
550
+ <span class="cline-any cline-yes">1x</span>
551
+ <span class="cline-any cline-yes">1x</span>
552
+ <span class="cline-any cline-neutral">&nbsp;</span>
553
+ <span class="cline-any cline-yes">4x</span>
554
+ <span class="cline-any cline-yes">4x</span>
555
+ <span class="cline-any cline-neutral">&nbsp;</span>
556
+ <span class="cline-any cline-neutral">&nbsp;</span>
557
+ <span class="cline-any cline-neutral">&nbsp;</span>
558
+ <span class="cline-any cline-yes">259x</span>
559
+ <span class="cline-any cline-yes">5x</span>
560
+ <span class="cline-any cline-yes">4x</span>
561
+ <span class="cline-any cline-yes">4x</span>
562
+ <span class="cline-any cline-yes">4x</span>
563
+ <span class="cline-any cline-yes">5x</span>
564
+ <span class="cline-any cline-yes">3x</span>
565
+ <span class="cline-any cline-yes">3x</span>
566
+ <span class="cline-any cline-yes">3x</span>
567
+ <span class="cline-any cline-neutral">&nbsp;</span>
568
+ <span class="cline-any cline-yes">1x</span>
569
+ <span class="cline-any cline-neutral">&nbsp;</span>
570
+ <span class="cline-any cline-yes">4x</span>
571
+ <span class="cline-any cline-neutral">&nbsp;</span>
572
+ <span class="cline-any cline-neutral">&nbsp;</span>
573
+ <span class="cline-any cline-neutral">&nbsp;</span>
574
+ <span class="cline-any cline-yes">259x</span>
575
+ <span class="cline-any cline-yes">6x</span>
576
+ <span class="cline-any cline-yes">6x</span>
577
+ <span class="cline-any cline-yes">5x</span>
578
+ <span class="cline-any cline-yes">6x</span>
579
+ <span class="cline-any cline-neutral">&nbsp;</span>
580
+ <span class="cline-any cline-yes">4x</span>
581
+ <span class="cline-any cline-yes">4x</span>
582
+ <span class="cline-any cline-yes">4x</span>
583
+ <span class="cline-any cline-yes">4x</span>
584
+ <span class="cline-any cline-yes">3x</span>
585
+ <span class="cline-any cline-yes">3x</span>
586
+ <span class="cline-any cline-yes">3x</span>
587
+ <span class="cline-any cline-yes">3x</span>
588
+ <span class="cline-any cline-yes">3x</span>
589
+ <span class="cline-any cline-neutral">&nbsp;</span>
590
+ <span class="cline-any cline-yes">1x</span>
591
+ <span class="cline-any cline-neutral">&nbsp;</span>
592
+ <span class="cline-any cline-yes">4x</span>
593
+ <span class="cline-any cline-neutral">&nbsp;</span>
594
+ <span class="cline-any cline-neutral">&nbsp;</span>
595
+ <span class="cline-any cline-neutral">&nbsp;</span>
596
+ <span class="cline-any cline-yes">259x</span>
597
+ <span class="cline-any cline-yes">5x</span>
598
+ <span class="cline-any cline-yes">4x</span>
599
+ <span class="cline-any cline-yes">4x</span>
600
+ <span class="cline-any cline-yes">4x</span>
601
+ <span class="cline-any cline-yes">5x</span>
602
+ <span class="cline-any cline-yes">3x</span>
603
+ <span class="cline-any cline-yes">3x</span>
604
+ <span class="cline-any cline-yes">3x</span>
605
+ <span class="cline-any cline-neutral">&nbsp;</span>
606
+ <span class="cline-any cline-yes">1x</span>
607
+ <span class="cline-any cline-neutral">&nbsp;</span>
608
+ <span class="cline-any cline-yes">4x</span>
609
+ <span class="cline-any cline-neutral">&nbsp;</span>
610
+ <span class="cline-any cline-neutral">&nbsp;</span>
611
+ <span class="cline-any cline-neutral">&nbsp;</span>
612
+ <span class="cline-any cline-yes">259x</span>
613
+ <span class="cline-any cline-yes">5x</span>
614
+ <span class="cline-any cline-neutral">&nbsp;</span>
615
+ <span class="cline-any cline-yes">4x</span>
616
+ <span class="cline-any cline-yes">4x</span>
617
+ <span class="cline-any cline-yes">4x</span>
618
+ <span class="cline-any cline-yes">4x</span>
619
+ <span class="cline-any cline-neutral">&nbsp;</span>
620
+ <span class="cline-any cline-yes">4x</span>
621
+ <span class="cline-any cline-yes">4x</span>
622
+ <span class="cline-any cline-yes">3x</span>
623
+ <span class="cline-any cline-yes">3x</span>
624
+ <span class="cline-any cline-yes">3x</span>
625
+ <span class="cline-any cline-yes">5x</span>
626
+ <span class="cline-any cline-neutral">&nbsp;</span>
627
+ <span class="cline-any cline-yes">1x</span>
628
+ <span class="cline-any cline-yes">1x</span>
629
+ <span class="cline-any cline-neutral">&nbsp;</span>
630
+ <span class="cline-any cline-yes">4x</span>
631
+ <span class="cline-any cline-yes">4x</span>
632
+ <span class="cline-any cline-neutral">&nbsp;</span>
633
+ <span class="cline-any cline-neutral">&nbsp;</span>
634
+ <span class="cline-any cline-neutral">&nbsp;</span>
635
+ <span class="cline-any cline-yes">259x</span>
636
+ <span class="cline-any cline-neutral">&nbsp;</span>
637
+ <span class="cline-any cline-neutral">&nbsp;</span>
638
+ <span class="cline-any cline-neutral">&nbsp;</span>
639
+ <span class="cline-any cline-neutral">&nbsp;</span>
640
+ <span class="cline-any cline-neutral">&nbsp;</span>
641
+ <span class="cline-any cline-neutral">&nbsp;</span>
642
+ <span class="cline-any cline-neutral">&nbsp;</span>
643
+ <span class="cline-any cline-neutral">&nbsp;</span>
644
+ <span class="cline-any cline-neutral">&nbsp;</span>
645
+ <span class="cline-any cline-neutral">&nbsp;</span>
646
+ <span class="cline-any cline-neutral">&nbsp;</span>
647
+ <span class="cline-any cline-neutral">&nbsp;</span>
648
+ <span class="cline-any cline-neutral">&nbsp;</span>
649
+ <span class="cline-any cline-neutral">&nbsp;</span>
650
+ <span class="cline-any cline-neutral">&nbsp;</span>
651
+ <span class="cline-any cline-neutral">&nbsp;</span>
652
+ <span class="cline-any cline-neutral">&nbsp;</span>
653
+ <span class="cline-any cline-neutral">&nbsp;</span>
654
+ <span class="cline-any cline-neutral">&nbsp;</span>
655
+ <span class="cline-any cline-neutral">&nbsp;</span>
656
+ <span class="cline-any cline-neutral">&nbsp;</span>
657
+ <span class="cline-any cline-neutral">&nbsp;</span>
658
+ <span class="cline-any cline-neutral">&nbsp;</span>
659
+ <span class="cline-any cline-neutral">&nbsp;</span>
660
+ <span class="cline-any cline-neutral">&nbsp;</span>
661
+ <span class="cline-any cline-neutral">&nbsp;</span>
662
+ <span class="cline-any cline-neutral">&nbsp;</span>
663
+ <span class="cline-any cline-neutral">&nbsp;</span>
664
+ <span class="cline-any cline-neutral">&nbsp;</span>
665
+ <span class="cline-any cline-neutral">&nbsp;</span>
666
+ <span class="cline-any cline-neutral">&nbsp;</span>
667
+ <span class="cline-any cline-neutral">&nbsp;</span>
668
+ <span class="cline-any cline-neutral">&nbsp;</span>
669
+ <span class="cline-any cline-neutral">&nbsp;</span>
670
+ <span class="cline-any cline-neutral">&nbsp;</span>
671
+ <span class="cline-any cline-neutral">&nbsp;</span>
672
+ <span class="cline-any cline-neutral">&nbsp;</span>
673
+ <span class="cline-any cline-neutral">&nbsp;</span>
674
+ <span class="cline-any cline-neutral">&nbsp;</span>
675
+ <span class="cline-any cline-neutral">&nbsp;</span>
676
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { useState, useEffect, useCallback } from 'react';
677
+ import {
678
+ fetchIssueDetail, fetchComments, postComment, fetchTransitions,
679
+ transitionIssue, fetchAssignableUsers, assignIssue,
680
+ uploadAttachment, fetchProjectVersions, updateIssue, searchLabels
681
+ } from '../services/api';
682
+ &nbsp;
683
+ export function useIssueDrawer(issueKey, addToast, refetch) {
684
+ const [issueDetail, setIssueDetail] = useState(null);
685
+ const [comments, setComments] = useState([]);
686
+ const [transitions, setTransitions] = useState([]);
687
+ const [assignableUsers, setAssignableUsers] = useState([]);
688
+ const [drawerLoading, setDrawerLoading] = useState(false);
689
+ const [drawerError, setDrawerError] = useState(null);
690
+ &nbsp;
691
+ const [newCommentText, setNewCommentText] = useState('');
692
+ const [isPostingComment, setIsPostingComment] = useState(false);
693
+ const [targetTransitionId, setTargetTransitionId] = useState('');
694
+ const [isTransitioning, setIsTransitioning] = useState(false);
695
+ const [assigneeSearch, setAssigneeSearch] = useState('');
696
+ const [targetAccountId, setTargetAccountId] = useState('');
697
+ const [isAssigning, setIsAssigning] = useState(false);
698
+ const [projectVersions, setProjectVersions] = useState([]);
699
+ const [newLabelText, setNewLabelText] = useState('');
700
+ const [labelSuggestions, setLabelSuggestions] = useState([]);
701
+ const [showLabelSuggestions, setShowLabelSuggestions] = useState(false);
702
+ const [isUpdatingLabels, setIsUpdatingLabels] = useState(false);
703
+ const [isUpdatingVersions, setIsUpdatingVersions] = useState(false);
704
+ const [isUploading, setIsUploading] = useState(false);
705
+ const [uploadMessage, setUploadMessage] = useState('');
706
+ const [isTransitioningOptimistic, setIsTransitioningOptimistic] = useState(false);
707
+ const [optimisticStatus, setOptimisticStatus] = useState(null);
708
+ const [isAssigningOptimistic, setIsAssigningOptimistic] = useState(false);
709
+ const [optimisticAssignee, setOptimisticAssignee] = useState(null);
710
+ &nbsp;
711
+ useEffect(() =&gt; {
712
+ if (!issueKey) return;
713
+
714
+ setDrawerLoading(true);
715
+ setDrawerError(null);
716
+ setIssueDetail(null);
717
+ setComments([]);
718
+ setTransitions([]);
719
+ setAssignableUsers([]);
720
+ setNewCommentText('');
721
+ setTargetTransitionId('');
722
+ setTargetAccountId('');
723
+ setAssigneeSearch('');
724
+ setUploadMessage('');
725
+ setNewLabelText('');
726
+ &nbsp;
727
+ const loadIssueData = async () =&gt; {
728
+ try {
729
+ const [detailData, commentsData, transitionsData, usersData] = await Promise.all([
730
+ fetchIssueDetail(issueKey),
731
+ fetchComments(issueKey),
732
+ fetchTransitions(issueKey).catch(() =&gt; []),
733
+ fetchAssignableUsers(issueKey).catch(() =&gt; [])
734
+ ]);
735
+ setIssueDetail(detailData);
736
+ setComments(commentsData);
737
+ setTransitions(transitionsData);
738
+ setAssignableUsers(usersData);
739
+ &nbsp;
740
+ if (detailData.fields.project?.key) {
741
+ const versions = await fetchProjectVersions(detailData.fields.project.key).catch(() =&gt; []);
742
+ setProjectVersions(versions);
743
+ }
744
+ } catch (err) {
745
+ setDrawerError(err.message || 'Failed to load issue details');
746
+ } finally {
747
+ setDrawerLoading(false);
748
+ }
749
+ };
750
+ &nbsp;
751
+ loadIssueData();
752
+ }, [issueKey]);
753
+ &nbsp;
754
+ useEffect(() =&gt; {
755
+ if (!newLabelText || newLabelText.length &lt; 1) {
756
+ setLabelSuggestions([]);
757
+ setShowLabelSuggestions(false);
758
+ return;
759
+ }
760
+ const timer = setTimeout(async () =&gt; {
761
+ try {
762
+ const labels = await searchLabels(newLabelText);
763
+ const currentLabels = issueDetail?.fields?.labels || <span class="branch-1 cbranch-no" title="branch not covered" >[];</span>
764
+ const filtered = labels.filter(l =&gt; !currentLabels.includes(l));
765
+ setLabelSuggestions(filtered);
766
+ setShowLabelSuggestions(filtered.length &gt; 0);
767
+ } catch (err) {
768
+ console.error('Label search error:', err);
769
+ }
770
+ }, 300);
771
+ return () =&gt; clearTimeout(timer);
772
+ }, [newLabelText, issueDetail]);
773
+ &nbsp;
774
+ useEffect(() =&gt; {
775
+ if (!issueKey || !assigneeSearch || assigneeSearch.length &lt; 1) return;
776
+ const timer = setTimeout(async () =&gt; {
777
+ try {
778
+ const users = await fetchAssignableUsers(issueKey, assigneeSearch);
779
+ <span class="cstat-no" title="statement not covered" > setAssignableUsers(users);</span>
780
+ } catch (err) {
781
+ console.error('Assignee search error:', err);
782
+ }
783
+ }, 500);
784
+ return () =&gt; clearTimeout(timer);
785
+ }, [assigneeSearch, issueKey]);
786
+ &nbsp;
787
+ const handlePostComment = useCallback(async () =&gt; {
788
+ if (!newCommentText.trim() || !issueKey) return;
789
+ setIsPostingComment(true);
790
+ try {
791
+ const postedComment = await postComment(issueKey, newCommentText);
792
+ setComments(prev =&gt; [...prev, postedComment]);
793
+ setNewCommentText('');
794
+ addToast('Comment posted', 'success');
795
+ } catch (err) {
796
+ addToast(`Error posting comment: ${err.message}`, 'error');
797
+ } finally {
798
+ setIsPostingComment(false);
799
+ }
800
+ }, [newCommentText, issueKey, addToast]);
801
+ &nbsp;
802
+ const handleAssignUser = useCallback(async (accountId, displayName) =&gt; {
803
+ if (!accountId || !issueKey) return;
804
+ &nbsp;
805
+ const optimisticAssigneeObj = {
806
+ displayName,
807
+ accountId,
808
+ avatarUrls: { '48x48': '' },
809
+ };
810
+ setOptimisticAssignee(optimisticAssigneeObj);
811
+ setIsAssigningOptimistic(true);
812
+ setTargetAccountId('');
813
+ setAssigneeSearch('');
814
+ setIsAssigning(true);
815
+ &nbsp;
816
+ try {
817
+ await assignIssue(issueKey, accountId);
818
+ fetchIssueDetail(issueKey).then(setIssueDetail).catch(<span class="fstat-no" title="function not covered" >()</span> =&gt; {});
819
+ refetch?.();
820
+ addToast('Issue assigned successfully', 'success');
821
+ } catch (err) {
822
+ setOptimisticAssignee(null);
823
+ addToast(`Failed to assign: ${err.message}`, 'error');
824
+ } finally {
825
+ setIsAssigningOptimistic(false);
826
+ setIsAssigning(false);
827
+ }
828
+ }, [issueKey, addToast, refetch]);
829
+ &nbsp;
830
+ const handleFileUpload = useCallback(async (e) =&gt; {
831
+ const file = e.target.files?.[0];
832
+ if (!file || !issueKey) return;
833
+ &nbsp;
834
+ if (file.size &gt; 10 * 1024 * 1024) {
835
+ setUploadMessage('Error: File size exceeds 10MB limit');
836
+ return;
837
+ }
838
+ &nbsp;
839
+ const ALLOWED_TYPES = ['image/png', 'image/jpeg', 'image/gif', 'application/pdf', 'text/plain', 'application/zip'];
840
+ if (!ALLOWED_TYPES.includes(file.type)) {
841
+ addToast('File type not allowed', 'error');
842
+ e.target.value = '';
843
+ return;
844
+ }
845
+ &nbsp;
846
+ setIsUploading(true);
847
+ setUploadMessage('');
848
+ try {
849
+ await uploadAttachment(issueKey, file);
850
+ setUploadMessage('File uploaded successfully');
851
+ addToast('File attached successfully', 'success');
852
+ const updatedDetail = await fetchIssueDetail(issueKey);
853
+ setIssueDetail(updatedDetail);
854
+ } catch (err) {
855
+ setUploadMessage(`Error uploading file: ${err.message}`);
856
+ addToast(`Error attaching file: ${err.message}`, 'error');
857
+ } finally {
858
+ setIsUploading(false);
859
+ e.target.value = '';
860
+ }
861
+ }, [issueKey, addToast]);
862
+ &nbsp;
863
+ const handleUpdateVersion = useCallback(async (versionId) =&gt; {
864
+ if (!issueKey) return;
865
+ setIsUpdatingVersions(true);
866
+ try {
867
+ const fixVersions = versionId ? [{ id: versionId }] : [];
868
+ await updateIssue(issueKey, { fixVersions });
869
+ const updatedDetail = await fetchIssueDetail(issueKey);
870
+ setIssueDetail(updatedDetail);
871
+ addToast('Fix version updated', 'success');
872
+ } catch (err) {
873
+ addToast(`Error updating version: ${err.message}`, 'error');
874
+ } finally {
875
+ setIsUpdatingVersions(false);
876
+ }
877
+ }, [issueKey, addToast]);
878
+ &nbsp;
879
+ const handleAddLabel = useCallback(async (labelToAdd) =&gt; {
880
+ const label = (typeof labelToAdd === 'string' ? labelToAdd : newLabelText).trim();
881
+ if (!label || !issueKey) return;
882
+ const currentLabels = issueDetail?.fields?.labels || <span class="branch-1 cbranch-no" title="branch not covered" >[];</span>
883
+ if (currentLabels.includes(label)) return;
884
+ &nbsp;
885
+ setIsUpdatingLabels(true);
886
+ try {
887
+ const updatedLabels = [...currentLabels, label];
888
+ await updateIssue(issueKey, { labels: updatedLabels });
889
+ const updatedDetail = await fetchIssueDetail(issueKey);
890
+ setIssueDetail(updatedDetail);
891
+ setNewLabelText('');
892
+ setShowLabelSuggestions(false);
893
+ addToast('Label added', 'success');
894
+ } catch (err) {
895
+ addToast(`Error adding label: ${err.message}`, 'error');
896
+ } finally {
897
+ setIsUpdatingLabels(false);
898
+ }
899
+ }, [newLabelText, issueKey, issueDetail, addToast]);
900
+ &nbsp;
901
+ const handleRemoveLabel = useCallback(async (labelToRemove) =&gt; {
902
+ if (!issueKey) return;
903
+ setIsUpdatingLabels(true);
904
+ try {
905
+ const updatedLabels = issueDetail?.fields?.labels?.filter(l =&gt; l !== labelToRemove) || [];
906
+ await updateIssue(issueKey, { labels: updatedLabels });
907
+ const updatedDetail = await fetchIssueDetail(issueKey);
908
+ setIssueDetail(updatedDetail);
909
+ addToast('Label removed', 'success');
910
+ } catch (err) {
911
+ addToast(`Error removing label: ${err.message}`, 'error');
912
+ } finally {
913
+ setIsUpdatingLabels(false);
914
+ }
915
+ }, [issueKey, issueDetail, addToast]);
916
+ &nbsp;
917
+ const handleUpdateStatus = useCallback(async (transitionId, transitionName) =&gt; {
918
+ if (!transitionId || !issueKey) return;
919
+ &nbsp;
920
+ setOptimisticStatus(transitionName);
921
+ setIsTransitioningOptimistic(true);
922
+ setTargetTransitionId('');
923
+ setIsTransitioning(true);
924
+ &nbsp;
925
+ try {
926
+ await transitionIssue(issueKey, transitionId);
927
+ fetchIssueDetail(issueKey).then(setIssueDetail).catch(<span class="fstat-no" title="function not covered" >()</span> =&gt; {});
928
+ fetchTransitions(issueKey).then(setTransitions).catch(<span class="fstat-no" title="function not covered" >()</span> =&gt; {});
929
+ refetch?.();
930
+ addToast('Status updated successfully', 'success');
931
+ } catch (err) {
932
+ setOptimisticStatus(null);
933
+ addToast(`Failed to update status: ${err.message}`, 'error');
934
+ } finally {
935
+ setIsTransitioningOptimistic(false);
936
+ setIsTransitioning(false);
937
+ }
938
+ }, [issueKey, addToast, refetch]);
939
+ &nbsp;
940
+ return {
941
+ issueDetail,
942
+ comments,
943
+ transitions,
944
+ assignableUsers,
945
+ drawerLoading,
946
+ drawerError,
947
+ newCommentText,
948
+ setNewCommentText,
949
+ isPostingComment,
950
+ targetTransitionId,
951
+ setTargetTransitionId,
952
+ isTransitioning,
953
+ isTransitioningOptimistic,
954
+ optimisticStatus,
955
+ assigneeSearch,
956
+ setAssigneeSearch,
957
+ targetAccountId,
958
+ setTargetAccountId,
959
+ isAssigning,
960
+ isAssigningOptimistic,
961
+ optimisticAssignee,
962
+ projectVersions,
963
+ isUpdatingVersions,
964
+ newLabelText,
965
+ setNewLabelText,
966
+ labelSuggestions,
967
+ showLabelSuggestions,
968
+ setShowLabelSuggestions,
969
+ isUpdatingLabels,
970
+ isUploading,
971
+ uploadMessage,
972
+ handlePostComment,
973
+ handleAssignUser,
974
+ handleFileUpload,
975
+ handleUpdateVersion,
976
+ handleAddLabel,
977
+ handleRemoveLabel,
978
+ handleUpdateStatus
979
+ };
980
+ }
981
+ &nbsp;</pre></td></tr></table></pre>
982
+
983
+ <div class='push'></div><!-- for sticky footer -->
984
+ </div><!-- /wrapper -->
985
+ <div class='footer quiet pad2 space-top1 center small'>
986
+ Code coverage generated by
987
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
988
+ at 2026-03-22T01:07:31.116Z
989
+ </div>
990
+ <script src="../prettify.js"></script>
991
+ <script>
992
+ window.onload = function () {
993
+ prettyPrint();
994
+ };
995
+ </script>
996
+ <script src="../sorter.js"></script>
997
+ <script src="../block-navigation.js"></script>
998
+ </body>
999
+ </html>
1000
+