@autocode-cli/autocode 0.1.14 → 0.1.17

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 (211) hide show
  1. package/README.md +38 -38
  2. package/dist/cli/commands/comment.d.ts +1 -1
  3. package/dist/cli/commands/comment.js +11 -11
  4. package/dist/cli/commands/comment.js.map +1 -1
  5. package/dist/cli/commands/init.js +1 -1
  6. package/dist/cli/commands/init.js.map +1 -1
  7. package/dist/cli/commands/list.d.ts +1 -1
  8. package/dist/cli/commands/list.d.ts.map +1 -1
  9. package/dist/cli/commands/list.js +65 -22
  10. package/dist/cli/commands/list.js.map +1 -1
  11. package/dist/cli/commands/move.d.ts +1 -1
  12. package/dist/cli/commands/move.js +12 -12
  13. package/dist/cli/commands/move.js.map +1 -1
  14. package/dist/cli/commands/new.d.ts +1 -1
  15. package/dist/cli/commands/new.d.ts.map +1 -1
  16. package/dist/cli/commands/new.js +26 -13
  17. package/dist/cli/commands/new.js.map +1 -1
  18. package/dist/cli/commands/next.d.ts +1 -1
  19. package/dist/cli/commands/next.js +15 -15
  20. package/dist/cli/commands/next.js.map +1 -1
  21. package/dist/cli/commands/parent.d.ts +9 -0
  22. package/dist/cli/commands/parent.d.ts.map +1 -0
  23. package/dist/cli/commands/parent.js +94 -0
  24. package/dist/cli/commands/parent.js.map +1 -0
  25. package/dist/cli/commands/serve.js +8 -8
  26. package/dist/cli/commands/serve.js.map +1 -1
  27. package/dist/cli/commands/show.d.ts +1 -1
  28. package/dist/cli/commands/show.d.ts.map +1 -1
  29. package/dist/cli/commands/show.js +51 -31
  30. package/dist/cli/commands/show.js.map +1 -1
  31. package/dist/cli/commands/stats.js +2 -2
  32. package/dist/cli/commands/stats.js.map +1 -1
  33. package/dist/cli/commands/sync.js +3 -3
  34. package/dist/cli/commands/sync.js.map +1 -1
  35. package/dist/cli/parser.d.ts.map +1 -1
  36. package/dist/cli/parser.js +5 -3
  37. package/dist/cli/parser.js.map +1 -1
  38. package/dist/core/column.js +2 -2
  39. package/dist/core/column.js.map +1 -1
  40. package/dist/core/hierarchy.d.ts +97 -0
  41. package/dist/core/hierarchy.d.ts.map +1 -0
  42. package/dist/core/hierarchy.js +274 -0
  43. package/dist/core/hierarchy.js.map +1 -0
  44. package/dist/core/issue.d.ts +62 -0
  45. package/dist/core/issue.d.ts.map +1 -0
  46. package/dist/core/issue.js +247 -0
  47. package/dist/core/issue.js.map +1 -0
  48. package/dist/core/sync.d.ts +9 -9
  49. package/dist/core/sync.d.ts.map +1 -1
  50. package/dist/core/sync.js +61 -58
  51. package/dist/core/sync.js.map +1 -1
  52. package/dist/core/workflow.d.ts +22 -20
  53. package/dist/core/workflow.d.ts.map +1 -1
  54. package/dist/core/workflow.js +68 -51
  55. package/dist/core/workflow.js.map +1 -1
  56. package/dist/index.d.ts +1 -1
  57. package/dist/index.js +1 -1
  58. package/dist/server/api-autocomplete.test.d.ts +6 -0
  59. package/dist/server/api-autocomplete.test.d.ts.map +1 -0
  60. package/dist/server/api-autocomplete.test.js +249 -0
  61. package/dist/server/api-autocomplete.test.js.map +1 -0
  62. package/dist/server/api.d.ts.map +1 -1
  63. package/dist/server/api.js +216 -106
  64. package/dist/server/api.js.map +1 -1
  65. package/dist/server/dashboard/pages/column-prompt.d.ts +1 -1
  66. package/dist/server/dashboard/pages/column-prompt.d.ts.map +1 -1
  67. package/dist/server/dashboard/pages/column-prompt.js +11 -11
  68. package/dist/server/dashboard/pages/column-prompt.js.map +1 -1
  69. package/dist/server/dashboard/pages/column-terminal.d.ts +1 -1
  70. package/dist/server/dashboard/pages/column-terminal.d.ts.map +1 -1
  71. package/dist/server/dashboard/pages/column-terminal.js +14 -14
  72. package/dist/server/dashboard/pages/column-terminal.js.map +1 -1
  73. package/dist/server/dashboard/pages/index.d.ts +3 -1
  74. package/dist/server/dashboard/pages/index.d.ts.map +1 -1
  75. package/dist/server/dashboard/pages/index.js +3 -1
  76. package/dist/server/dashboard/pages/index.js.map +1 -1
  77. package/dist/server/dashboard/pages/issue-graph.d.ts +9 -0
  78. package/dist/server/dashboard/pages/issue-graph.d.ts.map +1 -0
  79. package/dist/server/dashboard/pages/issue-graph.js +581 -0
  80. package/dist/server/dashboard/pages/issue-graph.js.map +1 -0
  81. package/dist/server/dashboard/pages/issue-view.d.ts +8 -0
  82. package/dist/server/dashboard/pages/issue-view.d.ts.map +1 -0
  83. package/dist/server/dashboard/pages/{ticket-view.js → issue-view.js} +128 -128
  84. package/dist/server/dashboard/pages/issue-view.js.map +1 -0
  85. package/dist/server/dashboard/pages/main-dashboard.js +21 -21
  86. package/dist/server/dashboard/pages/main-dashboard.js.map +1 -1
  87. package/dist/server/dashboard/pages/new-issue.d.ts +8 -0
  88. package/dist/server/dashboard/pages/new-issue.d.ts.map +1 -0
  89. package/dist/server/dashboard/pages/new-issue.js +648 -0
  90. package/dist/server/dashboard/pages/new-issue.js.map +1 -0
  91. package/dist/server/dashboard/pages/new-issue.test.d.ts +6 -0
  92. package/dist/server/dashboard/pages/new-issue.test.d.ts.map +1 -0
  93. package/dist/server/dashboard/pages/new-issue.test.js +349 -0
  94. package/dist/server/dashboard/pages/new-issue.test.js.map +1 -0
  95. package/dist/server/dashboard/pages/pipeline-configurator.js +1 -1
  96. package/dist/server/dashboard/pages/shared.d.ts +2 -2
  97. package/dist/server/dashboard/pages/shared.d.ts.map +1 -1
  98. package/dist/server/dashboard/pages/shared.js +5 -5
  99. package/dist/server/dashboard/pages/shared.js.map +1 -1
  100. package/dist/server/dashboard/pages/stats-page.js +11 -11
  101. package/dist/server/dashboard/scripts/index.js +134 -134
  102. package/dist/server/dashboard/styles/board.d.ts +1 -1
  103. package/dist/server/dashboard/styles/board.js +10 -10
  104. package/dist/server/dashboard.d.ts +1 -1
  105. package/dist/server/dashboard.d.ts.map +1 -1
  106. package/dist/server/dashboard.js +1 -1
  107. package/dist/server/dashboard.js.map +1 -1
  108. package/dist/server/index.d.ts.map +1 -1
  109. package/dist/server/index.js +40 -24
  110. package/dist/server/index.js.map +1 -1
  111. package/dist/server/websocket.d.ts +6 -6
  112. package/dist/server/websocket.d.ts.map +1 -1
  113. package/dist/server/websocket.js +10 -10
  114. package/dist/server/websocket.js.map +1 -1
  115. package/dist/services/claude.d.ts +13 -13
  116. package/dist/services/claude.d.ts.map +1 -1
  117. package/dist/services/claude.js +98 -98
  118. package/dist/services/claude.js.map +1 -1
  119. package/dist/services/issue-io.d.ts +81 -0
  120. package/dist/services/issue-io.d.ts.map +1 -0
  121. package/dist/services/{ticket-io.js → issue-io.js} +54 -53
  122. package/dist/services/issue-io.js.map +1 -0
  123. package/dist/services/stats.d.ts +2 -0
  124. package/dist/services/stats.d.ts.map +1 -1
  125. package/dist/services/stats.js.map +1 -1
  126. package/dist/types/index.d.ts +6 -4
  127. package/dist/types/index.d.ts.map +1 -1
  128. package/dist/utils/fs.d.ts +2 -2
  129. package/dist/utils/fs.d.ts.map +1 -1
  130. package/dist/utils/fs.js +2 -2
  131. package/dist/utils/fs.js.map +1 -1
  132. package/package.json +3 -3
  133. package/templates/catalog.yaml +2 -2
  134. package/templates/prompts/api-endpoints-test.en.md +2 -2
  135. package/templates/prompts/api-endpoints-test.fr.md +2 -2
  136. package/templates/prompts/backlog.en.md +6 -6
  137. package/templates/prompts/backlog.fr.md +1 -1
  138. package/templates/prompts/changelog.en.md +6 -6
  139. package/templates/prompts/changelog.fr.md +3 -3
  140. package/templates/prompts/dashboard-responsive.en.md +1 -1
  141. package/templates/prompts/deploy-prod.en.md +3 -3
  142. package/templates/prompts/deploy-prod.fr.md +3 -3
  143. package/templates/prompts/deploy-staging.en.md +3 -3
  144. package/templates/prompts/deploy-staging.fr.md +3 -3
  145. package/templates/prompts/design.en.md +5 -5
  146. package/templates/prompts/design.fr.md +3 -3
  147. package/templates/prompts/dev.en.md +4 -4
  148. package/templates/prompts/dev.fr.md +3 -3
  149. package/templates/prompts/done.en.md +5 -5
  150. package/templates/prompts/done.fr.md +2 -2
  151. package/templates/prompts/error-handling-review.en.md +1 -1
  152. package/templates/prompts/error-handling-review.fr.md +1 -1
  153. package/templates/prompts/file-watcher-test.en.md +4 -4
  154. package/templates/prompts/file-watcher-test.fr.md +1 -1
  155. package/templates/prompts/git-commit.en.md +5 -5
  156. package/templates/prompts/git-commit.fr.md +3 -3
  157. package/templates/prompts/git-push.en.md +3 -3
  158. package/templates/prompts/git-push.fr.md +3 -3
  159. package/templates/prompts/git-tag.en.md +3 -3
  160. package/templates/prompts/git-tag.fr.md +3 -3
  161. package/templates/prompts/in-progress.en.md +6 -6
  162. package/templates/prompts/in-progress.fr.md +3 -3
  163. package/templates/prompts/qualification.en.md +8 -8
  164. package/templates/prompts/qualification.fr.md +3 -3
  165. package/templates/prompts/retest-cypress.en.md +3 -3
  166. package/templates/prompts/retest-cypress.fr.md +3 -3
  167. package/templates/prompts/retest-playwright.en.md +4 -4
  168. package/templates/prompts/retest-playwright.fr.md +3 -3
  169. package/templates/prompts/retest.en.md +4 -4
  170. package/templates/prompts/retest.fr.md +3 -3
  171. package/templates/prompts/review-best-practices.en.md +3 -3
  172. package/templates/prompts/review-best-practices.fr.md +3 -3
  173. package/templates/prompts/review-code.en.md +4 -4
  174. package/templates/prompts/review-code.fr.md +3 -3
  175. package/templates/prompts/review-consistency.en.md +3 -3
  176. package/templates/prompts/review-consistency.fr.md +3 -3
  177. package/templates/prompts/review-no-duplication.en.md +3 -3
  178. package/templates/prompts/review-no-duplication.fr.md +3 -3
  179. package/templates/prompts/review-security.en.md +4 -4
  180. package/templates/prompts/review-security.fr.md +3 -3
  181. package/templates/prompts/specification.en.md +5 -5
  182. package/templates/prompts/specification.fr.md +3 -3
  183. package/templates/prompts/splitter.en.md +13 -13
  184. package/templates/prompts/splitter.fr.md +3 -3
  185. package/templates/prompts/template-validation.en.md +1 -1
  186. package/templates/prompts/template-validation.fr.md +1 -1
  187. package/templates/prompts/testing-coverage.en.md +1 -1
  188. package/templates/prompts/testing-coverage.fr.md +1 -1
  189. package/templates/prompts/testing-cypress.en.md +4 -4
  190. package/templates/prompts/testing-cypress.fr.md +3 -3
  191. package/templates/prompts/testing-integration.en.md +4 -4
  192. package/templates/prompts/testing-integration.fr.md +3 -3
  193. package/templates/prompts/testing-playwright.en.md +4 -4
  194. package/templates/prompts/testing-playwright.fr.md +3 -3
  195. package/templates/prompts/testing-unit.en.md +4 -4
  196. package/templates/prompts/testing-unit.fr.md +3 -3
  197. package/templates/prompts/update-docs.en.md +3 -3
  198. package/templates/prompts/update-docs.fr.md +3 -3
  199. package/templates/prompts/validate-staging.en.md +3 -3
  200. package/templates/prompts/validate-staging.fr.md +3 -3
  201. package/templates/prompts/websocket-test.en.md +1 -1
  202. package/dist/core/ticket.d.ts +0 -50
  203. package/dist/core/ticket.d.ts.map +0 -1
  204. package/dist/core/ticket.js +0 -224
  205. package/dist/core/ticket.js.map +0 -1
  206. package/dist/server/dashboard/pages/ticket-view.d.ts +0 -8
  207. package/dist/server/dashboard/pages/ticket-view.d.ts.map +0 -1
  208. package/dist/server/dashboard/pages/ticket-view.js.map +0 -1
  209. package/dist/services/ticket-io.d.ts +0 -80
  210. package/dist/services/ticket-io.d.ts.map +0 -1
  211. package/dist/services/ticket-io.js.map +0 -1
@@ -0,0 +1,581 @@
1
+ /**
2
+ * Issue Graph Page - Hierarchical tree visualization of issues
3
+ */
4
+ import { getStyles } from '../styles/index.js';
5
+ const translations = {
6
+ en: {
7
+ title: 'Issue Hierarchy',
8
+ backToDashboard: 'Back to Dashboard',
9
+ noIssues: 'No issues found',
10
+ rootIssues: 'Root issues',
11
+ totalIssues: 'Total issues',
12
+ maxDepth: 'Max depth',
13
+ loading: 'Loading...',
14
+ zoomIn: 'Zoom in',
15
+ zoomOut: 'Zoom out',
16
+ resetZoom: 'Reset',
17
+ children: 'children',
18
+ },
19
+ fr: {
20
+ title: 'Hierarchie des tickets',
21
+ backToDashboard: 'Retour au tableau',
22
+ noIssues: 'Aucun ticket trouve',
23
+ rootIssues: 'Tickets racines',
24
+ totalIssues: 'Total tickets',
25
+ maxDepth: 'Profondeur max',
26
+ loading: 'Chargement...',
27
+ zoomIn: 'Zoom +',
28
+ zoomOut: 'Zoom -',
29
+ resetZoom: 'Reset',
30
+ children: 'enfants',
31
+ },
32
+ };
33
+ /**
34
+ * Generate the issue graph page
35
+ */
36
+ export function generateIssueGraphPage(lang) {
37
+ const t = translations[lang] || translations.en;
38
+ return `<!DOCTYPE html>
39
+ <html lang="${lang}">
40
+ <head>
41
+ <meta charset="UTF-8">
42
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
43
+ <title>${t.title} - AutoCode</title>
44
+ <style>
45
+ ${getStyles()}
46
+ ${getGraphStyles()}
47
+ </style>
48
+ </head>
49
+ <body>
50
+ <header class="graph-header">
51
+ <div class="header-left">
52
+ <a href="/" class="back-link">&larr; ${t.backToDashboard}</a>
53
+ <h1>${t.title}</h1>
54
+ </div>
55
+ <div class="header-stats">
56
+ <span class="stat"><span class="stat-label">${t.rootIssues}:</span> <span id="root-count">-</span></span>
57
+ <span class="stat"><span class="stat-label">${t.totalIssues}:</span> <span id="total-count">-</span></span>
58
+ <span class="stat"><span class="stat-label">${t.maxDepth}:</span> <span id="max-depth">-</span></span>
59
+ </div>
60
+ <div class="zoom-controls">
61
+ <button onclick="zoomIn()" title="${t.zoomIn}">+</button>
62
+ <button onclick="resetZoom()" title="${t.resetZoom}">100%</button>
63
+ <button onclick="zoomOut()" title="${t.zoomOut}">-</button>
64
+ </div>
65
+ </header>
66
+
67
+ <main class="graph-container" id="graph-container">
68
+ <div class="loading" id="loading">${t.loading}</div>
69
+ <div class="graph-wrapper" id="graph-wrapper">
70
+ <svg id="graph-svg" class="graph-svg"></svg>
71
+ </div>
72
+ <div class="no-issues" id="no-issues" style="display: none;">${t.noIssues}</div>
73
+ </main>
74
+
75
+ <div class="legend">
76
+ <div class="legend-item"><span class="legend-color priority-p0"></span> P0</div>
77
+ <div class="legend-item"><span class="legend-color priority-p1"></span> P1</div>
78
+ <div class="legend-item"><span class="legend-color priority-p2"></span> P2</div>
79
+ <div class="legend-item"><span class="legend-color priority-p3"></span> P3</div>
80
+ <div class="legend-separator"></div>
81
+ <div class="legend-item"><span class="legend-color status-backlog"></span> Backlog</div>
82
+ <div class="legend-item"><span class="legend-color status-progress"></span> In Progress</div>
83
+ <div class="legend-item"><span class="legend-color status-done"></span> Done</div>
84
+ </div>
85
+
86
+ <script>
87
+ ${getGraphScript(t)}
88
+ </script>
89
+ </body>
90
+ </html>`;
91
+ }
92
+ /**
93
+ * Graph-specific styles
94
+ */
95
+ function getGraphStyles() {
96
+ return `
97
+ body {
98
+ margin: 0;
99
+ padding: 0;
100
+ overflow: hidden;
101
+ background: var(--bg-primary);
102
+ }
103
+
104
+ .graph-header {
105
+ display: flex;
106
+ align-items: center;
107
+ justify-content: space-between;
108
+ padding: 12px 20px;
109
+ background: var(--bg-secondary);
110
+ border-bottom: 1px solid var(--border-color);
111
+ position: fixed;
112
+ top: 0;
113
+ left: 0;
114
+ right: 0;
115
+ z-index: 100;
116
+ }
117
+
118
+ .header-left {
119
+ display: flex;
120
+ align-items: center;
121
+ gap: 20px;
122
+ }
123
+
124
+ .header-left h1 {
125
+ margin: 0;
126
+ font-size: 1.2rem;
127
+ color: var(--text-primary);
128
+ }
129
+
130
+ .back-link {
131
+ color: var(--text-secondary);
132
+ text-decoration: none;
133
+ font-size: 0.9rem;
134
+ }
135
+
136
+ .back-link:hover {
137
+ color: var(--accent-color);
138
+ }
139
+
140
+ .header-stats {
141
+ display: flex;
142
+ gap: 20px;
143
+ }
144
+
145
+ .stat {
146
+ font-size: 0.85rem;
147
+ color: var(--text-secondary);
148
+ }
149
+
150
+ .stat-label {
151
+ color: var(--text-muted);
152
+ }
153
+
154
+ .zoom-controls {
155
+ display: flex;
156
+ gap: 4px;
157
+ }
158
+
159
+ .zoom-controls button {
160
+ width: 36px;
161
+ height: 36px;
162
+ border: 1px solid var(--border-color);
163
+ background: var(--bg-primary);
164
+ color: var(--text-primary);
165
+ border-radius: 4px;
166
+ cursor: pointer;
167
+ font-size: 1rem;
168
+ }
169
+
170
+ .zoom-controls button:hover {
171
+ background: var(--bg-hover);
172
+ }
173
+
174
+ .graph-container {
175
+ position: fixed;
176
+ top: 60px;
177
+ left: 0;
178
+ right: 0;
179
+ bottom: 40px;
180
+ overflow: auto;
181
+ }
182
+
183
+ .graph-wrapper {
184
+ min-width: 100%;
185
+ min-height: 100%;
186
+ display: flex;
187
+ justify-content: center;
188
+ padding: 40px;
189
+ box-sizing: border-box;
190
+ }
191
+
192
+ .graph-svg {
193
+ display: block;
194
+ }
195
+
196
+ .loading {
197
+ position: absolute;
198
+ top: 50%;
199
+ left: 50%;
200
+ transform: translate(-50%, -50%);
201
+ color: var(--text-muted);
202
+ font-size: 1.1rem;
203
+ }
204
+
205
+ .no-issues {
206
+ position: absolute;
207
+ top: 50%;
208
+ left: 50%;
209
+ transform: translate(-50%, -50%);
210
+ color: var(--text-muted);
211
+ font-size: 1.1rem;
212
+ }
213
+
214
+ .legend {
215
+ position: fixed;
216
+ bottom: 0;
217
+ left: 0;
218
+ right: 0;
219
+ height: 40px;
220
+ background: var(--bg-secondary);
221
+ border-top: 1px solid var(--border-color);
222
+ display: flex;
223
+ align-items: center;
224
+ justify-content: center;
225
+ gap: 20px;
226
+ padding: 0 20px;
227
+ }
228
+
229
+ .legend-item {
230
+ display: flex;
231
+ align-items: center;
232
+ gap: 6px;
233
+ font-size: 0.8rem;
234
+ color: var(--text-secondary);
235
+ }
236
+
237
+ .legend-color {
238
+ width: 12px;
239
+ height: 12px;
240
+ border-radius: 2px;
241
+ }
242
+
243
+ .legend-separator {
244
+ width: 1px;
245
+ height: 20px;
246
+ background: var(--border-color);
247
+ }
248
+
249
+ .priority-p0 { background: #ef4444; }
250
+ .priority-p1 { background: #f97316; }
251
+ .priority-p2 { background: #3b82f6; }
252
+ .priority-p3 { background: #6b7280; }
253
+
254
+ .status-backlog { background: #6b7280; }
255
+ .status-progress { background: #3b82f6; }
256
+ .status-done { background: #22c55e; }
257
+
258
+ /* SVG Node Styles */
259
+ .node {
260
+ cursor: pointer;
261
+ }
262
+
263
+ .node:hover .node-bg {
264
+ filter: brightness(1.1);
265
+ }
266
+
267
+ .node-bg {
268
+ rx: 6;
269
+ ry: 6;
270
+ }
271
+
272
+ .node-key {
273
+ font-size: 11px;
274
+ font-weight: 600;
275
+ fill: white;
276
+ }
277
+
278
+ .node-title {
279
+ font-size: 10px;
280
+ fill: rgba(255, 255, 255, 0.9);
281
+ }
282
+
283
+ .node-status {
284
+ font-size: 9px;
285
+ fill: rgba(255, 255, 255, 0.7);
286
+ }
287
+
288
+ .node-children {
289
+ font-size: 9px;
290
+ fill: rgba(255, 255, 255, 0.6);
291
+ }
292
+
293
+ .link {
294
+ fill: none;
295
+ stroke: var(--border-color);
296
+ stroke-width: 2;
297
+ }
298
+
299
+ .link-arrow {
300
+ fill: var(--border-color);
301
+ }
302
+ `;
303
+ }
304
+ /**
305
+ * Graph client-side script
306
+ */
307
+ function getGraphScript(t) {
308
+ return `
309
+ const NODE_WIDTH = 180;
310
+ const NODE_HEIGHT = 60;
311
+ const NODE_H_GAP = 40;
312
+ const NODE_V_GAP = 80;
313
+ const CHILDREN_LABEL = '${t.children}';
314
+
315
+ let issues = [];
316
+ let zoom = 1;
317
+
318
+ // Priority colors
319
+ const priorityColors = {
320
+ P0: '#ef4444',
321
+ P1: '#f97316',
322
+ P2: '#3b82f6',
323
+ P3: '#6b7280',
324
+ };
325
+
326
+ // Status colors (border)
327
+ function getStatusColor(columnSlug) {
328
+ const slug = columnSlug.toLowerCase();
329
+ if (slug.includes('backlog')) return '#6b7280';
330
+ if (slug.includes('done') || slug === 'done') return '#22c55e';
331
+ return '#3b82f6';
332
+ }
333
+
334
+ async function loadIssues() {
335
+ try {
336
+ const res = await fetch('/api/issues');
337
+ const data = await res.json();
338
+ if (data.success) {
339
+ issues = data.data.issues;
340
+ renderGraph();
341
+ }
342
+ } catch (e) {
343
+ console.error('Failed to load issues:', e);
344
+ } finally {
345
+ document.getElementById('loading').style.display = 'none';
346
+ }
347
+ }
348
+
349
+ function buildTree(issueList) {
350
+ // Group issues by parent_key
351
+ const childrenMap = new Map();
352
+ const issueMap = new Map();
353
+
354
+ issueList.forEach(t => {
355
+ issueMap.set(t.key, t);
356
+ const parentKey = t.parent_key || null;
357
+ if (!childrenMap.has(parentKey)) {
358
+ childrenMap.set(parentKey, []);
359
+ }
360
+ childrenMap.get(parentKey).push(t);
361
+ });
362
+
363
+ // Sort children by priority then key
364
+ const priorityOrder = { P0: 0, P1: 1, P2: 2, P3: 3 };
365
+ childrenMap.forEach((children) => {
366
+ children.sort((a, b) => {
367
+ const pDiff = priorityOrder[a.priority] - priorityOrder[b.priority];
368
+ if (pDiff !== 0) return pDiff;
369
+ return a.key.localeCompare(b.key);
370
+ });
371
+ });
372
+
373
+ // Build tree nodes recursively
374
+ function buildNode(issue, depth = 0) {
375
+ const children = childrenMap.get(issue.key) || [];
376
+ return {
377
+ issue,
378
+ depth,
379
+ children: children.map(c => buildNode(c, depth + 1)),
380
+ };
381
+ }
382
+
383
+ // Get root issues (no parent)
384
+ const roots = childrenMap.get(null) || [];
385
+ return roots.map(r => buildNode(r, 0));
386
+ }
387
+
388
+ function calculatePositions(tree) {
389
+ let maxX = 0;
390
+ let maxY = 0;
391
+ let maxDepth = 0;
392
+
393
+ // First pass: calculate subtree widths
394
+ function calcWidth(node) {
395
+ if (node.children.length === 0) {
396
+ node.width = NODE_WIDTH;
397
+ return NODE_WIDTH;
398
+ }
399
+ let totalWidth = 0;
400
+ node.children.forEach((child, i) => {
401
+ totalWidth += calcWidth(child);
402
+ if (i < node.children.length - 1) {
403
+ totalWidth += NODE_H_GAP;
404
+ }
405
+ });
406
+ node.width = Math.max(NODE_WIDTH, totalWidth);
407
+ return node.width;
408
+ }
409
+
410
+ // Second pass: assign positions
411
+ function assignPos(node, x, y) {
412
+ node.x = x + (node.width - NODE_WIDTH) / 2;
413
+ node.y = y;
414
+ maxX = Math.max(maxX, node.x + NODE_WIDTH);
415
+ maxY = Math.max(maxY, node.y + NODE_HEIGHT);
416
+ maxDepth = Math.max(maxDepth, node.depth);
417
+
418
+ let childX = x;
419
+ node.children.forEach((child) => {
420
+ assignPos(child, childX, y + NODE_HEIGHT + NODE_V_GAP);
421
+ childX += child.width + NODE_H_GAP;
422
+ });
423
+ }
424
+
425
+ // Calculate for each tree
426
+ let currentX = 0;
427
+ tree.forEach((root, i) => {
428
+ calcWidth(root);
429
+ assignPos(root, currentX, 0);
430
+ currentX += root.width + NODE_H_GAP * 2;
431
+ });
432
+
433
+ return { maxX, maxY, maxDepth };
434
+ }
435
+
436
+ function renderGraph() {
437
+ const tree = buildTree(issues);
438
+
439
+ // Update stats
440
+ document.getElementById('root-count').textContent = tree.length;
441
+ document.getElementById('total-count').textContent = issues.length;
442
+
443
+ if (issues.length === 0) {
444
+ document.getElementById('no-issues').style.display = 'block';
445
+ document.getElementById('max-depth').textContent = '0';
446
+ return;
447
+ }
448
+
449
+ const { maxX, maxY, maxDepth } = calculatePositions(tree);
450
+ document.getElementById('max-depth').textContent = maxDepth + 1;
451
+
452
+ const svg = document.getElementById('graph-svg');
453
+ const padding = 40;
454
+ const width = maxX + padding * 2;
455
+ const height = maxY + padding * 2;
456
+
457
+ svg.setAttribute('width', width * zoom);
458
+ svg.setAttribute('height', height * zoom);
459
+ svg.setAttribute('viewBox', '0 0 ' + width + ' ' + height);
460
+
461
+ // Clear and render
462
+ svg.innerHTML = '';
463
+
464
+ // Create defs for arrow markers
465
+ const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
466
+ defs.innerHTML = '<marker id="arrowhead" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto"><polygon points="0 0, 10 3.5, 0 7" class="link-arrow"/></marker>';
467
+ svg.appendChild(defs);
468
+
469
+ // Render links first (so they appear behind nodes)
470
+ function renderLinks(node) {
471
+ node.children.forEach(child => {
472
+ const line = document.createElementNS('http://www.w3.org/2000/svg', 'path');
473
+ const startX = padding + node.x + NODE_WIDTH / 2;
474
+ const startY = padding + node.y + NODE_HEIGHT;
475
+ const endX = padding + child.x + NODE_WIDTH / 2;
476
+ const endY = padding + child.y;
477
+
478
+ // Bezier curve for smoother lines
479
+ const midY = startY + (endY - startY) / 2;
480
+ const d = 'M ' + startX + ' ' + startY + ' C ' + startX + ' ' + midY + ', ' + endX + ' ' + midY + ', ' + endX + ' ' + endY;
481
+
482
+ line.setAttribute('d', d);
483
+ line.setAttribute('class', 'link');
484
+ line.setAttribute('marker-end', 'url(#arrowhead)');
485
+ svg.appendChild(line);
486
+
487
+ renderLinks(child);
488
+ });
489
+ }
490
+
491
+ // Render nodes
492
+ function renderNode(node) {
493
+ const t = node.issue;
494
+ const x = padding + node.x;
495
+ const y = padding + node.y;
496
+
497
+ const g = document.createElementNS('http://www.w3.org/2000/svg', 'g');
498
+ g.setAttribute('class', 'node');
499
+ g.setAttribute('transform', 'translate(' + x + ',' + y + ')');
500
+ g.onclick = () => window.location.href = '/issue/' + t.key;
501
+
502
+ // Background
503
+ const bg = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
504
+ bg.setAttribute('class', 'node-bg');
505
+ bg.setAttribute('width', NODE_WIDTH);
506
+ bg.setAttribute('height', NODE_HEIGHT);
507
+ bg.setAttribute('fill', priorityColors[t.priority] || priorityColors.P2);
508
+ bg.setAttribute('stroke', getStatusColor(t.column_slug));
509
+ bg.setAttribute('stroke-width', '3');
510
+ g.appendChild(bg);
511
+
512
+ // Key
513
+ const key = document.createElementNS('http://www.w3.org/2000/svg', 'text');
514
+ key.setAttribute('class', 'node-key');
515
+ key.setAttribute('x', 8);
516
+ key.setAttribute('y', 18);
517
+ key.textContent = t.key;
518
+ g.appendChild(key);
519
+
520
+ // Title (truncated)
521
+ const title = document.createElementNS('http://www.w3.org/2000/svg', 'text');
522
+ title.setAttribute('class', 'node-title');
523
+ title.setAttribute('x', 8);
524
+ title.setAttribute('y', 34);
525
+ const maxTitleLen = 22;
526
+ title.textContent = t.title.length > maxTitleLen ? t.title.substring(0, maxTitleLen) + '...' : t.title;
527
+ g.appendChild(title);
528
+
529
+ // Status
530
+ const status = document.createElementNS('http://www.w3.org/2000/svg', 'text');
531
+ status.setAttribute('class', 'node-status');
532
+ status.setAttribute('x', 8);
533
+ status.setAttribute('y', 50);
534
+ status.textContent = t.status.substring(0, 18);
535
+ g.appendChild(status);
536
+
537
+ // Children count
538
+ if (node.children.length > 0) {
539
+ const childCount = document.createElementNS('http://www.w3.org/2000/svg', 'text');
540
+ childCount.setAttribute('class', 'node-children');
541
+ childCount.setAttribute('x', NODE_WIDTH - 8);
542
+ childCount.setAttribute('y', 50);
543
+ childCount.setAttribute('text-anchor', 'end');
544
+ childCount.textContent = node.children.length + ' ' + CHILDREN_LABEL;
545
+ g.appendChild(childCount);
546
+ }
547
+
548
+ svg.appendChild(g);
549
+
550
+ node.children.forEach(renderNode);
551
+ }
552
+
553
+ // Render
554
+ tree.forEach(root => {
555
+ renderLinks(root);
556
+ });
557
+ tree.forEach(root => {
558
+ renderNode(root);
559
+ });
560
+ }
561
+
562
+ function zoomIn() {
563
+ zoom = Math.min(zoom * 1.2, 3);
564
+ renderGraph();
565
+ }
566
+
567
+ function zoomOut() {
568
+ zoom = Math.max(zoom / 1.2, 0.3);
569
+ renderGraph();
570
+ }
571
+
572
+ function resetZoom() {
573
+ zoom = 1;
574
+ renderGraph();
575
+ }
576
+
577
+ // Initialize
578
+ loadIssues();
579
+ `;
580
+ }
581
+ //# sourceMappingURL=issue-graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue-graph.js","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/issue-graph.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAG/C,MAAM,YAAY,GAAG;IACnB,EAAE,EAAE;QACF,KAAK,EAAE,iBAAiB;QACxB,eAAe,EAAE,mBAAmB;QACpC,QAAQ,EAAE,iBAAiB;QAC3B,UAAU,EAAE,aAAa;QACzB,WAAW,EAAE,cAAc;QAC3B,QAAQ,EAAE,WAAW;QACrB,OAAO,EAAE,YAAY;QACrB,MAAM,EAAE,SAAS;QACjB,OAAO,EAAE,UAAU;QACnB,SAAS,EAAE,OAAO;QAClB,QAAQ,EAAE,UAAU;KACrB;IACD,EAAE,EAAE;QACF,KAAK,EAAE,wBAAwB;QAC/B,eAAe,EAAE,mBAAmB;QACpC,QAAQ,EAAE,qBAAqB;QAC/B,UAAU,EAAE,iBAAiB;QAC7B,WAAW,EAAE,eAAe;QAC5B,QAAQ,EAAE,gBAAgB;QAC1B,OAAO,EAAE,eAAe;QACxB,MAAM,EAAE,QAAQ;QAChB,OAAO,EAAE,QAAQ;QACjB,SAAS,EAAE,OAAO;QAClB,QAAQ,EAAE,SAAS;KACpB;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAc;IACnD,MAAM,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,EAAE,CAAC;IAEhD,OAAO;cACK,IAAI;;;;WAIP,CAAC,CAAC,KAAK;;MAEZ,SAAS,EAAE;MACX,cAAc,EAAE;;;;;;6CAMuB,CAAC,CAAC,eAAe;YAClD,CAAC,CAAC,KAAK;;;oDAGiC,CAAC,CAAC,UAAU;oDACZ,CAAC,CAAC,WAAW;oDACb,CAAC,CAAC,QAAQ;;;0CAGpB,CAAC,CAAC,MAAM;6CACL,CAAC,CAAC,SAAS;2CACb,CAAC,CAAC,OAAO;;;;;wCAKZ,CAAC,CAAC,OAAO;;;;mEAIkB,CAAC,CAAC,QAAQ;;;;;;;;;;;;;;;MAevE,cAAc,CAAC,CAAC,CAAC;;;QAGf,CAAC;AACT,CAAC;AAED;;GAEG;AACH,SAAS,cAAc;IACrB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8MN,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,CAAyB;IAC/C,OAAO;;;;;8BAKqB,CAAC,CAAC,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0QrC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Issue view page generator
3
+ */
4
+ /**
5
+ * Generate the issue view page
6
+ */
7
+ export declare function generateIssueViewPage(issueKey: string, lang: string): string;
8
+ //# sourceMappingURL=issue-view.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue-view.d.ts","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/issue-view.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CA00C5E"}