flowpilot 0.0.2

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.
@@ -0,0 +1,1574 @@
1
+ import { a as useRef, i as useReducer, n as instance, r as useEffect, s as render, t as jsxDEV } from "./jsx-dev-runtime-DGBfem3G.js";
2
+ import { t as filterByRelevance } from "./search-cPm8k8mK.js";
3
+ //#region src/commands/release/client.tsx
4
+ const initPromise = typeof window !== "undefined" && window.__I18N_LOCALE__ && window.__I18N_RESOURCES__ ? instance.init({
5
+ lng: window.__I18N_LOCALE__,
6
+ fallbackLng: "zh-CN",
7
+ resources: window.__I18N_RESOURCES__,
8
+ interpolation: { escapeValue: false }
9
+ }) : Promise.resolve();
10
+ const t = instance.t;
11
+ const releaseStyle = `
12
+ .page-header {
13
+ margin-bottom: 28px;
14
+ animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) 0.05s both;
15
+ }
16
+ .page-header h2 {
17
+ font-size: 22px;
18
+ font-weight: 600;
19
+ letter-spacing: -0.02em;
20
+ margin-bottom: 6px;
21
+ }
22
+ .page-header p {
23
+ font-size: 13px;
24
+ color: var(--text-2);
25
+ font-weight: 300;
26
+ line-height: 1.5;
27
+ }
28
+
29
+ /* ── Pipeline ── */
30
+ .pipeline {
31
+ display: flex;
32
+ align-items: center;
33
+ gap: 0;
34
+ margin-bottom: 28px;
35
+ animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) 0.08s both;
36
+ }
37
+ .pipeline-step {
38
+ display: flex;
39
+ align-items: center;
40
+ gap: 6px;
41
+ font-size: 11px;
42
+ font-family: var(--mono);
43
+ color: var(--text-3);
44
+ font-weight: 400;
45
+ white-space: nowrap;
46
+ }
47
+ .pipeline-step.active {
48
+ color: var(--neon);
49
+ font-weight: 500;
50
+ }
51
+ .pipeline-step.done {
52
+ color: var(--cyan);
53
+ }
54
+ .pipeline-node {
55
+ width: 8px; height: 8px;
56
+ border-radius: 50%;
57
+ background: var(--text-3);
58
+ transition: background 0.3s, box-shadow 0.3s;
59
+ }
60
+ .pipeline-step.active .pipeline-node {
61
+ background: var(--neon);
62
+ box-shadow: 0 0 8px var(--neon-glow);
63
+ animation: neon-pulse 2s ease infinite;
64
+ }
65
+ .pipeline-step.done .pipeline-node {
66
+ background: var(--cyan);
67
+ box-shadow: 0 0 4px var(--cyan-glow);
68
+ }
69
+ .pipeline-line {
70
+ width: 32px;
71
+ height: 1px;
72
+ background: var(--border);
73
+ margin: 0 4px;
74
+ transition: background 0.3s;
75
+ }
76
+ .pipeline-line.done { background: var(--cyan); }
77
+
78
+ /* ── Generic select ── */
79
+ .sel {
80
+ position: relative;
81
+ margin-bottom: 16px;
82
+ animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) 0.12s both;
83
+ z-index: 1;
84
+ }
85
+ .sel-trigger {
86
+ width: 100%;
87
+ display: flex;
88
+ align-items: center;
89
+ gap: 8px;
90
+ padding: 12px 14px;
91
+ font-size: 13px;
92
+ font-family: var(--sans);
93
+ color: var(--text-1);
94
+ background: var(--bg-input);
95
+ border: 1px solid var(--border);
96
+ border-radius: 8px;
97
+ cursor: pointer;
98
+ outline: none;
99
+ transition: border-color 0.2s, box-shadow 0.2s;
100
+ text-align: left;
101
+ }
102
+ .sel-trigger:hover { border-color: var(--border-active); }
103
+ .sel-trigger:focus,
104
+ .sel-trigger.open {
105
+ border-color: var(--neon);
106
+ box-shadow: 0 0 0 2px var(--neon-soft), 0 0 8px var(--neon-glow);
107
+ }
108
+ .sel-trigger-label {
109
+ font-size: 11px;
110
+ color: var(--text-3);
111
+ flex-shrink: 0;
112
+ }
113
+ .sel-trigger-value {
114
+ flex: 1;
115
+ font-family: var(--mono);
116
+ font-size: 13px;
117
+ font-weight: 500;
118
+ color: var(--text-1);
119
+ }
120
+ .sel-trigger-value.empty {
121
+ color: var(--text-3);
122
+ font-weight: 300;
123
+ }
124
+ .sel-trigger-arrow {
125
+ color: var(--text-3);
126
+ font-size: 10px;
127
+ transition: transform 0.2s;
128
+ }
129
+ .sel-trigger.open .sel-trigger-arrow {
130
+ transform: rotate(180deg);
131
+ }
132
+ .sel-dropdown {
133
+ position: absolute;
134
+ top: calc(100% + 6px);
135
+ left: 0; right: 0;
136
+ max-height: 280px;
137
+ overflow-y: auto;
138
+ background: var(--bg-card);
139
+ border: 1px solid rgba(0,255,136,0.08);
140
+ border-radius: 8px;
141
+ box-shadow: 0 8px 32px rgba(0,0,0,0.6), 0 0 12px rgba(0,255,136,0.03);
142
+ z-index: 1000;
143
+ animation: dropdown-in 0.12s ease both;
144
+ }
145
+ .sel-dropdown::-webkit-scrollbar { width: 6px; }
146
+ .sel-dropdown::-webkit-scrollbar-track { background: transparent; }
147
+ .sel-dropdown::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
148
+ .sel-search {
149
+ padding: 8px;
150
+ border-bottom: 1px solid var(--border);
151
+ position: sticky;
152
+ top: 0;
153
+ background: var(--bg-card);
154
+ z-index: 1;
155
+ }
156
+ .sel-search-input {
157
+ width: 100%;
158
+ padding: 6px 10px;
159
+ font-size: 12px;
160
+ font-family: var(--mono);
161
+ color: var(--text-1);
162
+ background: var(--bg-void);
163
+ border: 1px solid var(--border);
164
+ border-radius: 4px;
165
+ outline: none;
166
+ transition: border-color 0.15s;
167
+ }
168
+ .sel-search-input::placeholder { color: var(--text-3); }
169
+ .sel-search-input:focus { border-color: var(--neon); }
170
+ .sel-item {
171
+ padding: 10px 14px;
172
+ font-size: 13px;
173
+ cursor: pointer;
174
+ transition: background 0.1s;
175
+ border-left: 3px solid transparent;
176
+ }
177
+ .sel-item:first-child { border-radius: 7px 7px 0 0; }
178
+ .sel-item:last-child { border-radius: 0 0 7px 7px; }
179
+ .sel-item:hover,
180
+ .sel-item.highlighted { background: var(--bg-hover); }
181
+ .sel-item.active {
182
+ background: var(--neon-soft);
183
+ border-left-color: var(--neon);
184
+ font-weight: 500;
185
+ }
186
+ .sel-item-name { font-weight: 500; color: var(--text-1); }
187
+ .sel-item-sub { font-size: 11px; color: var(--text-3); font-family: var(--mono); margin-top: 2px; }
188
+ .sel-empty { padding: 12px; text-align: center; color: var(--text-3); font-size: 12px; }
189
+
190
+ /* ── Spinner ── */
191
+ .spinner {
192
+ display: inline-block;
193
+ width: 14px; height: 14px;
194
+ border: 2px solid var(--border);
195
+ border-top-color: var(--neon);
196
+ border-radius: 50%;
197
+ animation: spin 0.6s linear infinite;
198
+ }
199
+ @keyframes spin { to { transform: rotate(360deg); } }
200
+ .loading-row {
201
+ display: flex;
202
+ align-items: center;
203
+ gap: 8px;
204
+ padding: 10px 14px;
205
+ color: var(--text-3);
206
+ font-size: 13px;
207
+ margin-bottom: 16px;
208
+ animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) both;
209
+ }
210
+
211
+ /* ── Version display ── */
212
+ .version-display {
213
+ display: flex;
214
+ align-items: center;
215
+ gap: 12px;
216
+ padding: 14px 20px;
217
+ background: var(--bg-card);
218
+ border: 1px solid rgba(0,212,255,0.08);
219
+ border-radius: 8px;
220
+ animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) both;
221
+ }
222
+ .version-tag { font-size: 11px; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.05em; font-family: var(--mono); }
223
+ .version-number { font-size: 20px; font-weight: 600; font-family: var(--mono); color: var(--cyan); letter-spacing: -0.01em; }
224
+ .version-error { color: var(--error); font-size: 13px; animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) both; }
225
+
226
+ .empty-hint { text-align: center; padding: 32px 0; color: var(--text-3); font-size: 13px; animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) 0.15s both; }
227
+ .state-error { color: var(--error); font-size: 13px; animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) both; }
228
+
229
+ /* ── Jira ── */
230
+ .jira-section { margin-top: 20px; animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) both; }
231
+ .jira-btn {
232
+ width: 100%;
233
+ min-height: 44px;
234
+ padding: 10px 20px;
235
+ font-size: 13px;
236
+ font-family: var(--sans);
237
+ font-weight: 500;
238
+ color: var(--bg-void);
239
+ background: var(--neon);
240
+ border: none;
241
+ border-radius: 8px;
242
+ cursor: pointer;
243
+ transition: background 0.15s, box-shadow 0.2s;
244
+ margin-top: 16px;
245
+ position: relative;
246
+ z-index: 1;
247
+ }
248
+ .jira-btn:hover { background: var(--neon-hover); box-shadow: 0 0 12px var(--neon-glow), 0 2px 12px rgba(0,255,136,0.2); }
249
+ .jira-btn:disabled { opacity: 0.5; cursor: not-allowed; }
250
+ .jira-result {
251
+ margin-top: 12px;
252
+ padding: 12px 16px;
253
+ background: var(--bg-card);
254
+ border: 1px solid var(--border);
255
+ border-radius: 8px;
256
+ animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) both;
257
+ position: relative;
258
+ z-index: 1;
259
+ }
260
+ .jira-result-key {
261
+ font-family: var(--mono);
262
+ font-size: 14px;
263
+ font-weight: 600;
264
+ color: var(--neon);
265
+ text-decoration: none;
266
+ border-bottom: 1px dashed rgba(0,255,136,0.3);
267
+ transition: border-color 0.2s;
268
+ }
269
+ .jira-result-key:hover { border-bottom-color: var(--neon); }
270
+ .jira-result-label { font-size: 11px; color: var(--text-3); margin-bottom: 4px; }
271
+ .jira-result-badge { display: inline-block; font-size: 10px; padding: 2px 8px; border-radius: 4px; margin-left: 8px; font-weight: 500; }
272
+ .jira-result-badge.created { background: var(--neon-soft); color: var(--neon); }
273
+ .jira-result-badge.exists { background: var(--cyan-soft); color: var(--cyan); }
274
+ .jira-error { margin-top: 12px; color: var(--error); font-size: 13px; animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) both; }
275
+
276
+ /* ── History ── */
277
+ .history-section {
278
+ margin-bottom: 24px;
279
+ animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) 0.06s both;
280
+ }
281
+ .history-title {
282
+ font-size: 16px;
283
+ font-weight: 600;
284
+ margin-bottom: 12px;
285
+ color: var(--text-1);
286
+ }
287
+ .history-list {
288
+ display: flex;
289
+ flex-direction: column;
290
+ gap: 8px;
291
+ }
292
+ .history-item {
293
+ display: flex;
294
+ flex-direction: column;
295
+ padding: 12px 16px;
296
+ background: var(--bg-card);
297
+ border: 1px solid var(--border);
298
+ border-radius: 8px;
299
+ transition: border-color 0.15s, box-shadow 0.15s;
300
+ animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) both;
301
+ }
302
+ .history-item-row {
303
+ display: flex;
304
+ align-items: center;
305
+ justify-content: space-between;
306
+ }
307
+ .history-item:hover {
308
+ border-color: var(--border-active);
309
+ box-shadow: 0 2px 8px rgba(0,0,0,0.3);
310
+ }
311
+ .history-info {
312
+ display: flex;
313
+ align-items: center;
314
+ gap: 12px;
315
+ flex: 1;
316
+ }
317
+ .history-project { font-weight: 500; color: var(--text-1); font-size: 14px; }
318
+ .history-detail { font-size: 12px; color: var(--text-3); font-family: var(--mono); }
319
+ .history-actions { display: flex; align-items: center; gap: 8px; }
320
+ .history-quick-btn {
321
+ padding: 6px 14px;
322
+ font-size: 12px;
323
+ font-family: var(--sans);
324
+ font-weight: 500;
325
+ color: var(--bg-void);
326
+ background: var(--neon);
327
+ border: none;
328
+ border-radius: 6px;
329
+ cursor: pointer;
330
+ transition: background 0.15s;
331
+ }
332
+ .history-quick-btn:hover { background: var(--neon-hover); }
333
+ .history-quick-btn:disabled { opacity: 0.5; cursor: not-allowed; }
334
+ .history-quick-btn.executing {
335
+ background: var(--border);
336
+ color: var(--text-3);
337
+ }
338
+ .history-footer {
339
+ display: flex;
340
+ align-items: center;
341
+ justify-content: space-between;
342
+ margin-top: 16px;
343
+ padding-top: 16px;
344
+ border-top: 1px solid var(--border);
345
+ }
346
+ .history-new-btn {
347
+ padding: 8px 16px;
348
+ font-size: 13px;
349
+ font-family: var(--sans);
350
+ font-weight: 500;
351
+ color: var(--bg-void);
352
+ background: var(--neon);
353
+ border: none;
354
+ border-radius: 8px;
355
+ cursor: pointer;
356
+ transition: background 0.15s, box-shadow 0.2s;
357
+ }
358
+ .history-new-btn:hover { background: var(--neon-hover); box-shadow: 0 0 12px var(--neon-glow); }
359
+ .history-clear-btn {
360
+ padding: 8px 16px;
361
+ font-size: 13px;
362
+ font-family: var(--sans);
363
+ font-weight: 400;
364
+ color: var(--text-3);
365
+ background: transparent;
366
+ border: 1px solid var(--border);
367
+ border-radius: 8px;
368
+ cursor: pointer;
369
+ transition: border-color 0.15s, color 0.15s;
370
+ }
371
+ .history-clear-btn:hover { border-color: var(--error); color: var(--error); }
372
+ .history-result {
373
+ margin-top: 12px;
374
+ padding: 10px 14px;
375
+ background: var(--bg-void);
376
+ border: 1px solid rgba(0,255,136,0.08);
377
+ border-radius: 8px;
378
+ animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) both;
379
+ }
380
+ .history-result-key {
381
+ font-family: var(--mono);
382
+ font-size: 14px;
383
+ font-weight: 600;
384
+ color: var(--neon);
385
+ text-decoration: none;
386
+ }
387
+ .history-result-error {
388
+ color: var(--error);
389
+ font-size: 13px;
390
+ }
391
+
392
+ /* ── Modal ── */
393
+ .modal-overlay {
394
+ position: fixed;
395
+ top: 0; left: 0; right: 0; bottom: 0;
396
+ background: rgba(0,0,0,0.7);
397
+ display: flex;
398
+ align-items: center;
399
+ justify-content: center;
400
+ z-index: 2000;
401
+ animation: fade-in 0.2s ease both;
402
+ }
403
+ .modal-content {
404
+ width: 90%;
405
+ max-width: 560px;
406
+ background: var(--bg-void);
407
+ border: 1px solid var(--border);
408
+ border-radius: 12px;
409
+ padding: 24px;
410
+ animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) both;
411
+ }
412
+ .modal-header {
413
+ display: flex;
414
+ align-items: center;
415
+ justify-content: space-between;
416
+ margin-bottom: 20px;
417
+ }
418
+ .modal-title { font-size: 18px; font-weight: 600; color: var(--text-1); }
419
+ .modal-close {
420
+ width: 32px; height: 32px;
421
+ display: flex;
422
+ align-items: center;
423
+ justify-content: center;
424
+ font-size: 16px;
425
+ color: var(--text-3);
426
+ background: transparent;
427
+ border: 1px solid var(--border);
428
+ border-radius: 6px;
429
+ cursor: pointer;
430
+ transition: border-color 0.15s, color 0.15s;
431
+ }
432
+ .modal-close:hover { border-color: var(--text-2); color: var(--text-2); }
433
+ `;
434
+ const initial = {
435
+ jiraHost: "",
436
+ projects: [],
437
+ projectsLoading: true,
438
+ projectsError: "",
439
+ projectOpen: false,
440
+ projectSearch: "",
441
+ projectIndex: -1,
442
+ selected: null,
443
+ branches: [],
444
+ branchesLoading: false,
445
+ branchOpen: false,
446
+ branchSearch: "",
447
+ branchIndex: -1,
448
+ selectedBranch: "",
449
+ pomInfo: null,
450
+ pomLoading: false,
451
+ pomError: "",
452
+ jiraProjects: [],
453
+ jiraProjectsLoading: false,
454
+ jiraProjectOpen: false,
455
+ jiraProjectSearch: "",
456
+ jiraProjectIndex: -1,
457
+ selectedJiraProject: null,
458
+ jiraStatus: "idle",
459
+ jiraResult: null,
460
+ jiraError: "",
461
+ history: [],
462
+ historyLoading: true,
463
+ quickExecuting: null,
464
+ quickResults: {},
465
+ quickErrors: {},
466
+ showNewModal: false,
467
+ clearConfirm: false
468
+ };
469
+ const reducer = (state, action) => {
470
+ switch (action.type) {
471
+ case "SET_JIRA_HOST": return {
472
+ ...state,
473
+ jiraHost: action.host
474
+ };
475
+ case "PROJECTS_LOADED": return {
476
+ ...state,
477
+ projects: action.projects,
478
+ projectsLoading: false
479
+ };
480
+ case "PROJECTS_ERROR": return {
481
+ ...state,
482
+ projectsError: action.error,
483
+ projectsLoading: false
484
+ };
485
+ case "SET_PROJECT_OPEN": return {
486
+ ...state,
487
+ projectOpen: action.open,
488
+ ...action.open ? {} : {
489
+ projectSearch: "",
490
+ projectIndex: -1
491
+ }
492
+ };
493
+ case "SET_PROJECT_SEARCH": return {
494
+ ...state,
495
+ projectSearch: action.search,
496
+ projectIndex: -1
497
+ };
498
+ case "SET_PROJECT_INDEX": return {
499
+ ...state,
500
+ projectIndex: action.index
501
+ };
502
+ case "SELECT_PROJECT": return {
503
+ ...state,
504
+ selected: action.project,
505
+ projectOpen: false,
506
+ projectSearch: "",
507
+ projectIndex: -1,
508
+ branches: [],
509
+ branchesLoading: false,
510
+ selectedBranch: "",
511
+ branchOpen: false,
512
+ branchSearch: "",
513
+ branchIndex: -1,
514
+ pomInfo: null,
515
+ pomError: "",
516
+ selectedJiraProject: null,
517
+ jiraStatus: "idle",
518
+ jiraResult: null,
519
+ jiraError: ""
520
+ };
521
+ case "CLEAR_PROJECT": return {
522
+ ...state,
523
+ selected: null,
524
+ branches: [],
525
+ selectedBranch: "",
526
+ branchOpen: false,
527
+ branchSearch: "",
528
+ branchIndex: -1,
529
+ pomInfo: null,
530
+ pomError: "",
531
+ pomLoading: false,
532
+ selectedJiraProject: null,
533
+ jiraStatus: "idle",
534
+ jiraResult: null,
535
+ jiraError: ""
536
+ };
537
+ case "BRANCHES_LOADING": return {
538
+ ...state,
539
+ branchesLoading: true,
540
+ branches: [],
541
+ selectedBranch: ""
542
+ };
543
+ case "BRANCHES_LOADED": return {
544
+ ...state,
545
+ branches: action.branches,
546
+ branchesLoading: false
547
+ };
548
+ case "SET_BRANCH_OPEN": return {
549
+ ...state,
550
+ branchOpen: action.open,
551
+ ...action.open ? {} : {
552
+ branchSearch: "",
553
+ branchIndex: -1
554
+ }
555
+ };
556
+ case "SET_BRANCH_SEARCH": return {
557
+ ...state,
558
+ branchSearch: action.search,
559
+ branchIndex: -1
560
+ };
561
+ case "SET_BRANCH_INDEX": return {
562
+ ...state,
563
+ branchIndex: action.index
564
+ };
565
+ case "SELECT_BRANCH": return {
566
+ ...state,
567
+ selectedBranch: action.branch,
568
+ branchOpen: false,
569
+ branchSearch: "",
570
+ branchIndex: -1
571
+ };
572
+ case "POM_LOADING": return {
573
+ ...state,
574
+ pomLoading: true,
575
+ pomError: "",
576
+ pomInfo: null
577
+ };
578
+ case "POM_LOADED": return {
579
+ ...state,
580
+ pomLoading: false,
581
+ pomInfo: action.info
582
+ };
583
+ case "POM_ERROR": return {
584
+ ...state,
585
+ pomLoading: false,
586
+ pomError: action.error
587
+ };
588
+ case "JIRA_PROJECTS_LOADING": return {
589
+ ...state,
590
+ jiraProjectsLoading: true
591
+ };
592
+ case "JIRA_PROJECTS_LOADED": return {
593
+ ...state,
594
+ jiraProjects: action.projects,
595
+ jiraProjectsLoading: false
596
+ };
597
+ case "JIRA_PROJECTS_ERROR": return {
598
+ ...state,
599
+ jiraProjectsLoading: false
600
+ };
601
+ case "SET_JIRA_PROJECT_OPEN": return {
602
+ ...state,
603
+ jiraProjectOpen: action.open,
604
+ ...action.open ? {} : {
605
+ jiraProjectSearch: "",
606
+ jiraProjectIndex: -1
607
+ }
608
+ };
609
+ case "SET_JIRA_PROJECT_SEARCH": return {
610
+ ...state,
611
+ jiraProjectSearch: action.search,
612
+ jiraProjectIndex: -1
613
+ };
614
+ case "SET_JIRA_PROJECT_INDEX": return {
615
+ ...state,
616
+ jiraProjectIndex: action.index
617
+ };
618
+ case "SELECT_JIRA_PROJECT": return {
619
+ ...state,
620
+ selectedJiraProject: action.project,
621
+ jiraProjectOpen: false,
622
+ jiraProjectSearch: "",
623
+ jiraProjectIndex: -1,
624
+ jiraStatus: "idle",
625
+ jiraResult: null,
626
+ jiraError: ""
627
+ };
628
+ case "CLEAR_JIRA_PROJECT": return {
629
+ ...state,
630
+ selectedJiraProject: null,
631
+ jiraProjectOpen: false,
632
+ jiraProjectSearch: "",
633
+ jiraProjectIndex: -1,
634
+ jiraStatus: "idle",
635
+ jiraResult: null,
636
+ jiraError: ""
637
+ };
638
+ case "JIRA_CHECKING": return {
639
+ ...state,
640
+ jiraStatus: "checking",
641
+ jiraResult: null,
642
+ jiraError: ""
643
+ };
644
+ case "JIRA_CREATING": return {
645
+ ...state,
646
+ jiraStatus: "creating"
647
+ };
648
+ case "JIRA_DONE": return {
649
+ ...state,
650
+ jiraStatus: "done",
651
+ jiraResult: action.result
652
+ };
653
+ case "JIRA_ERROR": return {
654
+ ...state,
655
+ jiraStatus: "error",
656
+ jiraError: action.error
657
+ };
658
+ case "JIRA_RESET": return {
659
+ ...state,
660
+ jiraStatus: "idle",
661
+ jiraResult: null,
662
+ jiraError: ""
663
+ };
664
+ case "SET_HISTORY": return {
665
+ ...state,
666
+ history: action.history,
667
+ historyLoading: false
668
+ };
669
+ case "QUICK_EXEC_START": return {
670
+ ...state,
671
+ quickExecuting: action.id
672
+ };
673
+ case "QUICK_EXEC_SUCCESS": return {
674
+ ...state,
675
+ quickExecuting: null,
676
+ quickResults: {
677
+ ...state.quickResults,
678
+ [action.id]: action.result
679
+ }
680
+ };
681
+ case "QUICK_EXEC_FAIL": return {
682
+ ...state,
683
+ quickExecuting: null,
684
+ quickErrors: {
685
+ ...state.quickErrors,
686
+ [action.id]: action.error
687
+ }
688
+ };
689
+ case "SHOW_NEW_MODAL": return {
690
+ ...state,
691
+ showNewModal: true
692
+ };
693
+ case "HIDE_NEW_MODAL": return {
694
+ ...state,
695
+ showNewModal: false
696
+ };
697
+ case "CLEAR_CONFIRM_TOGGLE": return {
698
+ ...state,
699
+ clearConfirm: !state.clearConfirm
700
+ };
701
+ case "CLEAR_HISTORY_DONE": return {
702
+ ...state,
703
+ history: [],
704
+ clearConfirm: false,
705
+ quickResults: {},
706
+ quickErrors: {}
707
+ };
708
+ }
709
+ };
710
+ const cleanVersion = (v) => (v ?? "").split("-")[0];
711
+ const selKeyDown = (e, open, len, idx, onSelect, onClose) => {
712
+ if (!open || len === 0) return void 0;
713
+ switch (e.key) {
714
+ case "ArrowDown":
715
+ e.preventDefault();
716
+ return Math.min(idx + 1, len - 1);
717
+ case "ArrowUp":
718
+ e.preventDefault();
719
+ return Math.max(idx - 1, -1);
720
+ case "Enter":
721
+ e.preventDefault();
722
+ if (idx >= 0) onSelect(idx);
723
+ return;
724
+ case "Escape":
725
+ onClose();
726
+ return;
727
+ }
728
+ };
729
+ const pipelineStepClass = (done, active) => done ? "pipeline-step done" : active ? "pipeline-step active" : "pipeline-step";
730
+ const pipelineLineClass = (done) => done ? "pipeline-line done" : "pipeline-line";
731
+ const HistoryList = ({ s, d }) => {
732
+ const handleQuickExecute = async (id) => {
733
+ d({
734
+ type: "QUICK_EXEC_START",
735
+ id
736
+ });
737
+ try {
738
+ const data = await (await fetch(`/release/api/history/${id}/execute`, { method: "POST" })).json();
739
+ if (data.error) d({
740
+ type: "QUICK_EXEC_FAIL",
741
+ id,
742
+ error: data.error
743
+ });
744
+ else {
745
+ d({
746
+ type: "QUICK_EXEC_SUCCESS",
747
+ id,
748
+ result: data
749
+ });
750
+ d({
751
+ type: "SET_HISTORY",
752
+ history: await (await fetch("/release/api/history")).json()
753
+ });
754
+ }
755
+ } catch (e) {
756
+ d({
757
+ type: "QUICK_EXEC_FAIL",
758
+ id,
759
+ error: e instanceof Error ? e.message : String(e)
760
+ });
761
+ }
762
+ };
763
+ const handleClearHistory = async () => {
764
+ await fetch("/release/api/history", { method: "DELETE" });
765
+ d({ type: "CLEAR_HISTORY_DONE" });
766
+ };
767
+ return /* @__PURE__ */ jsxDEV("div", {
768
+ class: "history-section",
769
+ children: [
770
+ /* @__PURE__ */ jsxDEV("div", {
771
+ class: "history-title",
772
+ children: t("web.historyTitle")
773
+ }),
774
+ s.history.length > 0 ? /* @__PURE__ */ jsxDEV("div", {
775
+ class: "history-list",
776
+ children: s.history.map((entry) => /* @__PURE__ */ jsxDEV("div", {
777
+ class: "history-item",
778
+ children: [
779
+ /* @__PURE__ */ jsxDEV("div", {
780
+ class: "history-item-row",
781
+ children: [/* @__PURE__ */ jsxDEV("div", {
782
+ class: "history-info",
783
+ children: [/* @__PURE__ */ jsxDEV("span", {
784
+ class: "history-project",
785
+ children: entry.projectName
786
+ }), /* @__PURE__ */ jsxDEV("span", {
787
+ class: "history-detail",
788
+ children: [
789
+ entry.branch,
790
+ " / ",
791
+ entry.jiraProjectKey
792
+ ]
793
+ })]
794
+ }), /* @__PURE__ */ jsxDEV("div", {
795
+ class: "history-actions",
796
+ children: /* @__PURE__ */ jsxDEV("button", {
797
+ class: `history-quick-btn${s.quickExecuting === entry.id ? " executing" : ""}`,
798
+ type: "button",
799
+ disabled: s.quickExecuting !== null,
800
+ onClick: () => handleQuickExecute(entry.id),
801
+ children: s.quickExecuting === entry.id ? t("web.executing") : t("web.quickExecute")
802
+ })
803
+ })]
804
+ }),
805
+ s.quickResults[entry.id] && /* @__PURE__ */ jsxDEV("div", {
806
+ class: "history-result",
807
+ children: [
808
+ /* @__PURE__ */ jsxDEV("a", {
809
+ class: "history-result-key",
810
+ href: s.quickResults[entry.id].issueUrl,
811
+ target: "_blank",
812
+ rel: "noreferrer",
813
+ children: s.quickResults[entry.id].issueKey
814
+ }),
815
+ /* @__PURE__ */ jsxDEV("span", {
816
+ style: "font-size:12px;color:var(--text-3);margin-left:8px",
817
+ children: ["v", s.quickResults[entry.id].version]
818
+ }),
819
+ s.quickResults[entry.id].versionCreated && /* @__PURE__ */ jsxDEV("span", {
820
+ style: "font-size:10px;color:var(--neon);margin-left:4px",
821
+ children: t("web.createdBadge")
822
+ })
823
+ ]
824
+ }),
825
+ s.quickErrors[entry.id] && /* @__PURE__ */ jsxDEV("div", {
826
+ class: "history-result-error",
827
+ children: s.quickErrors[entry.id]
828
+ })
829
+ ]
830
+ }))
831
+ }) : /* @__PURE__ */ jsxDEV("div", {
832
+ class: "empty-hint",
833
+ children: t("web.noHistory")
834
+ }),
835
+ /* @__PURE__ */ jsxDEV("div", {
836
+ class: "history-footer",
837
+ children: [/* @__PURE__ */ jsxDEV("button", {
838
+ class: "history-new-btn",
839
+ type: "button",
840
+ onClick: () => d({ type: "SHOW_NEW_MODAL" }),
841
+ children: t("web.createNew")
842
+ }), s.history.length > 0 && (s.clearConfirm ? /* @__PURE__ */ jsxDEV("div", {
843
+ style: "display:flex;align-items:center;gap:8px",
844
+ children: [
845
+ /* @__PURE__ */ jsxDEV("span", {
846
+ style: "font-size:12px;color:var(--text-3)",
847
+ children: t("web.clearConfirm")
848
+ }),
849
+ /* @__PURE__ */ jsxDEV("button", {
850
+ class: "history-clear-btn",
851
+ type: "button",
852
+ style: "border-color:var(--error);color:var(--error)",
853
+ onClick: handleClearHistory,
854
+ children: t("web.clearHistory")
855
+ }),
856
+ /* @__PURE__ */ jsxDEV("button", {
857
+ class: "history-clear-btn",
858
+ type: "button",
859
+ onClick: () => d({ type: "CLEAR_CONFIRM_TOGGLE" }),
860
+ children: t("web.cancel")
861
+ })
862
+ ]
863
+ }) : /* @__PURE__ */ jsxDEV("button", {
864
+ class: "history-clear-btn",
865
+ type: "button",
866
+ onClick: () => d({ type: "CLEAR_CONFIRM_TOGGLE" }),
867
+ children: t("web.clearHistory")
868
+ }))]
869
+ })
870
+ ]
871
+ });
872
+ };
873
+ const ReleaseFlow = ({ s, d }) => {
874
+ const projectSearchRef = useRef(null);
875
+ const branchSearchRef = useRef(null);
876
+ const jiraSearchRef = useRef(null);
877
+ useEffect(() => {
878
+ fetch("/release/api/config").then((r) => r.json()).then((data) => {
879
+ if (data.jiraHost) d({
880
+ type: "SET_JIRA_HOST",
881
+ host: data.jiraHost
882
+ });
883
+ }).catch(() => {});
884
+ }, []);
885
+ useEffect(() => {
886
+ fetch("/release/api/projects").then((r) => r.json()).then((data) => {
887
+ if (data.error) d({
888
+ type: "PROJECTS_ERROR",
889
+ error: data.error
890
+ });
891
+ else d({
892
+ type: "PROJECTS_LOADED",
893
+ projects: data
894
+ });
895
+ }).catch((e) => d({
896
+ type: "PROJECTS_ERROR",
897
+ error: e.message
898
+ }));
899
+ }, []);
900
+ useEffect(() => {
901
+ if (!s.projectOpen && !s.branchOpen && !s.jiraProjectOpen) return;
902
+ const handler = (e) => {
903
+ if (!e.target.closest(".sel")) {
904
+ d({
905
+ type: "SET_PROJECT_OPEN",
906
+ open: false
907
+ });
908
+ d({
909
+ type: "SET_BRANCH_OPEN",
910
+ open: false
911
+ });
912
+ d({
913
+ type: "SET_JIRA_PROJECT_OPEN",
914
+ open: false
915
+ });
916
+ }
917
+ };
918
+ document.addEventListener("click", handler);
919
+ return () => document.removeEventListener("click", handler);
920
+ }, [
921
+ s.projectOpen,
922
+ s.branchOpen,
923
+ s.jiraProjectOpen
924
+ ]);
925
+ useEffect(() => {
926
+ if (s.projectOpen) setTimeout(() => projectSearchRef.current?.focus(), 50);
927
+ if (s.branchOpen) setTimeout(() => branchSearchRef.current?.focus(), 50);
928
+ if (s.jiraProjectOpen) setTimeout(() => jiraSearchRef.current?.focus(), 50);
929
+ }, [
930
+ s.projectOpen,
931
+ s.branchOpen,
932
+ s.jiraProjectOpen
933
+ ]);
934
+ useEffect(() => {
935
+ if (!s.pomInfo?.version || s.jiraProjects.length > 0 || s.jiraProjectsLoading) return;
936
+ d({ type: "JIRA_PROJECTS_LOADING" });
937
+ fetch("/release/api/jira/projects").then((r) => r.json()).then((data) => {
938
+ if (Array.isArray(data)) d({
939
+ type: "JIRA_PROJECTS_LOADED",
940
+ projects: data
941
+ });
942
+ else d({
943
+ type: "JIRA_PROJECTS_ERROR",
944
+ error: data.error ?? "Failed"
945
+ });
946
+ }).catch(() => d({
947
+ type: "JIRA_PROJECTS_ERROR",
948
+ error: "Failed"
949
+ }));
950
+ }, [s.pomInfo?.version]);
951
+ const fetchPom = (projectId, ref) => {
952
+ d({ type: "POM_LOADING" });
953
+ fetch(`/release/api/projects/${projectId}/pom-version?ref=${encodeURIComponent(ref)}`).then((r) => r.json()).then((data) => {
954
+ if (data.error) d({
955
+ type: "POM_ERROR",
956
+ error: data.error
957
+ });
958
+ else d({
959
+ type: "POM_LOADED",
960
+ info: data
961
+ });
962
+ }).catch(() => d({
963
+ type: "POM_ERROR",
964
+ error: "Failed to fetch version"
965
+ }));
966
+ };
967
+ const handleSelectProject = (project) => {
968
+ d({
969
+ type: "SELECT_PROJECT",
970
+ project
971
+ });
972
+ d({ type: "BRANCHES_LOADING" });
973
+ fetch(`/release/api/projects/${project.id}/branches`).then((r) => r.json()).then((data) => {
974
+ d({
975
+ type: "BRANCHES_LOADED",
976
+ branches: "error" in data ? [] : data
977
+ });
978
+ }).catch(() => d({
979
+ type: "BRANCHES_LOADED",
980
+ branches: []
981
+ }));
982
+ };
983
+ const handleSelectBranch = (name) => {
984
+ d({
985
+ type: "SELECT_BRANCH",
986
+ branch: name
987
+ });
988
+ if (s.selected) fetchPom(s.selected.id, name);
989
+ };
990
+ const handleCreateIssue = async () => {
991
+ if (!s.selected || !s.pomInfo?.version || !s.selectedJiraProject) return;
992
+ const artifactId = s.pomInfo.artifactId ?? s.selected.name;
993
+ const projectVersion = cleanVersion(s.pomInfo.version);
994
+ const versionName = `${artifactId}-${projectVersion}`;
995
+ const summary = `${artifactId}-${projectVersion} ${t("web.releaseSuffix") ?? t("release.releaseSuffix")}`;
996
+ d({ type: "JIRA_CHECKING" });
997
+ try {
998
+ const searchData = await (await fetch("/release/api/jira/search", {
999
+ method: "POST",
1000
+ headers: { "Content-Type": "application/json" },
1001
+ body: JSON.stringify({
1002
+ jql: `summary ~ "${summary}" AND project = ${s.selectedJiraProject.key}`,
1003
+ maxResults: 1
1004
+ })
1005
+ })).json();
1006
+ if (searchData.error) {
1007
+ d({
1008
+ type: "JIRA_ERROR",
1009
+ error: searchData.error
1010
+ });
1011
+ return;
1012
+ }
1013
+ if (searchData.total > 0 && searchData.issues?.[0]) {
1014
+ d({
1015
+ type: "JIRA_DONE",
1016
+ result: {
1017
+ key: searchData.issues[0].key,
1018
+ exists: true,
1019
+ versionName
1020
+ }
1021
+ });
1022
+ await fetch("/release/api/history", {
1023
+ method: "POST",
1024
+ headers: { "Content-Type": "application/json" },
1025
+ body: JSON.stringify({
1026
+ id: Date.now().toString(36),
1027
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1028
+ projectId: s.selected.id,
1029
+ projectName: s.selected.name,
1030
+ projectPath: s.selected.pathWithNamespace ?? "",
1031
+ branch: s.selectedBranch,
1032
+ jiraProjectKey: s.selectedJiraProject.key
1033
+ })
1034
+ });
1035
+ return;
1036
+ }
1037
+ d({ type: "JIRA_CREATING" });
1038
+ const verData = await (await fetch("/release/api/jira/ensure-version", {
1039
+ method: "POST",
1040
+ headers: { "Content-Type": "application/json" },
1041
+ body: JSON.stringify({
1042
+ projectKey: s.selectedJiraProject.key,
1043
+ versionName
1044
+ })
1045
+ })).json();
1046
+ if (verData.error) {
1047
+ d({
1048
+ type: "JIRA_ERROR",
1049
+ error: verData.error
1050
+ });
1051
+ return;
1052
+ }
1053
+ const issueData = await (await fetch("/release/api/jira/create-issue", {
1054
+ method: "POST",
1055
+ headers: { "Content-Type": "application/json" },
1056
+ body: JSON.stringify({
1057
+ projectKey: s.selectedJiraProject.key,
1058
+ summary,
1059
+ issuetypeId: "10000",
1060
+ customfield_15800: "无",
1061
+ customfield_13410: [{ id: verData.id }],
1062
+ customfield_13341: [{ name: "licheng.li" }]
1063
+ })
1064
+ })).json();
1065
+ if (issueData.error) {
1066
+ d({
1067
+ type: "JIRA_ERROR",
1068
+ error: issueData.error
1069
+ });
1070
+ return;
1071
+ }
1072
+ d({
1073
+ type: "JIRA_DONE",
1074
+ result: {
1075
+ key: issueData.key,
1076
+ exists: false,
1077
+ versionName: verData.name
1078
+ }
1079
+ });
1080
+ await fetch("/release/api/history", {
1081
+ method: "POST",
1082
+ headers: { "Content-Type": "application/json" },
1083
+ body: JSON.stringify({
1084
+ id: Date.now().toString(36),
1085
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1086
+ projectId: s.selected.id,
1087
+ projectName: s.selected.name,
1088
+ projectPath: s.selected.pathWithNamespace ?? "",
1089
+ branch: s.selectedBranch,
1090
+ jiraProjectKey: s.selectedJiraProject.key
1091
+ })
1092
+ });
1093
+ } catch (e) {
1094
+ d({
1095
+ type: "JIRA_ERROR",
1096
+ error: e instanceof Error ? e.message : String(e)
1097
+ });
1098
+ }
1099
+ };
1100
+ const fp = filterByRelevance(s.projects.map((p) => ({
1101
+ ...p,
1102
+ name: p.name,
1103
+ path: p.pathWithNamespace ?? ""
1104
+ })), s.projectSearch);
1105
+ const fb = filterByRelevance(s.branches.map((b) => ({
1106
+ ...b,
1107
+ name: b.name
1108
+ })), s.branchSearch);
1109
+ const fj = filterByRelevance(s.jiraProjects.map((p) => ({
1110
+ ...p,
1111
+ name: `${p.key} ${p.name ?? ""}`
1112
+ })), s.jiraProjectSearch);
1113
+ const jiraUrl = s.jiraResult && s.jiraHost ? `${s.jiraHost}/browse/${s.jiraResult.key}` : "";
1114
+ const step1Done = !!s.selected;
1115
+ const step1Active = !s.projectsLoading && !step1Done;
1116
+ const step2Done = !!s.selectedBranch;
1117
+ const step2Active = !!s.selected && !step2Done;
1118
+ const step3Done = !!s.pomInfo?.version;
1119
+ const step3Active = !!s.selectedBranch && !step3Done;
1120
+ const step4Done = !!s.selectedJiraProject;
1121
+ const step4Active = !!s.pomInfo?.version && !step4Done;
1122
+ const step5Done = !!s.jiraResult;
1123
+ const step5Active = !!s.selectedJiraProject && !step5Done;
1124
+ if (s.projectsLoading) return /* @__PURE__ */ jsxDEV("div", {
1125
+ class: "loading-row",
1126
+ children: [/* @__PURE__ */ jsxDEV("span", { class: "spinner" }), t("web.loadingProjects")]
1127
+ });
1128
+ if (s.projectsError) return /* @__PURE__ */ jsxDEV("div", {
1129
+ class: "state-error",
1130
+ children: s.projectsError
1131
+ });
1132
+ return /* @__PURE__ */ jsxDEV("div", { children: [
1133
+ /* @__PURE__ */ jsxDEV("div", {
1134
+ class: "pipeline",
1135
+ children: [
1136
+ /* @__PURE__ */ jsxDEV("div", {
1137
+ class: pipelineStepClass(step1Done, step1Active),
1138
+ children: [/* @__PURE__ */ jsxDEV("span", { class: "pipeline-node" }), t("web.projectLabel")]
1139
+ }),
1140
+ /* @__PURE__ */ jsxDEV("div", { class: pipelineLineClass(step1Done) }),
1141
+ /* @__PURE__ */ jsxDEV("div", {
1142
+ class: pipelineStepClass(step2Done, step2Active),
1143
+ children: [/* @__PURE__ */ jsxDEV("span", { class: "pipeline-node" }), t("web.branchLabel")]
1144
+ }),
1145
+ /* @__PURE__ */ jsxDEV("div", { class: pipelineLineClass(step2Done) }),
1146
+ /* @__PURE__ */ jsxDEV("div", {
1147
+ class: pipelineStepClass(step3Done, step3Active),
1148
+ children: [/* @__PURE__ */ jsxDEV("span", { class: "pipeline-node" }), t("web.versionTag")]
1149
+ }),
1150
+ /* @__PURE__ */ jsxDEV("div", { class: pipelineLineClass(step3Done) }),
1151
+ /* @__PURE__ */ jsxDEV("div", {
1152
+ class: pipelineStepClass(step4Done, step4Active),
1153
+ children: [/* @__PURE__ */ jsxDEV("span", { class: "pipeline-node" }), t("web.jiraProjectLabel")]
1154
+ }),
1155
+ /* @__PURE__ */ jsxDEV("div", { class: pipelineLineClass(step4Done) }),
1156
+ /* @__PURE__ */ jsxDEV("div", {
1157
+ class: pipelineStepClass(step5Done, step5Active),
1158
+ children: [/* @__PURE__ */ jsxDEV("span", { class: "pipeline-node" }), t("web.createBtn")]
1159
+ })
1160
+ ]
1161
+ }),
1162
+ /* @__PURE__ */ jsxDEV("div", {
1163
+ class: "sel",
1164
+ "data-sel": "project",
1165
+ style: `z-index:${s.projectOpen ? 100 : 1}`,
1166
+ children: [/* @__PURE__ */ jsxDEV("button", {
1167
+ class: `sel-trigger${s.projectOpen ? " open" : ""}`,
1168
+ type: "button",
1169
+ role: "combobox",
1170
+ "aria-expanded": s.projectOpen,
1171
+ "aria-haspopup": "listbox",
1172
+ onClick: () => {
1173
+ d({
1174
+ type: "SET_BRANCH_OPEN",
1175
+ open: false
1176
+ });
1177
+ d({
1178
+ type: "SET_JIRA_PROJECT_OPEN",
1179
+ open: false
1180
+ });
1181
+ d({
1182
+ type: "SET_PROJECT_OPEN",
1183
+ open: !s.projectOpen
1184
+ });
1185
+ },
1186
+ children: [
1187
+ /* @__PURE__ */ jsxDEV("span", {
1188
+ class: "sel-trigger-label",
1189
+ children: t("web.projectLabel")
1190
+ }),
1191
+ /* @__PURE__ */ jsxDEV("span", {
1192
+ class: `sel-trigger-value${s.selected ? "" : " empty"}`,
1193
+ children: s.selected ? s.selected.name : t("web.selectProject")
1194
+ }),
1195
+ /* @__PURE__ */ jsxDEV("span", {
1196
+ class: "sel-trigger-arrow",
1197
+ children: "▼"
1198
+ })
1199
+ ]
1200
+ }), s.projectOpen && /* @__PURE__ */ jsxDEV("div", {
1201
+ class: "sel-dropdown",
1202
+ role: "listbox",
1203
+ "aria-label": t("web.selectProject"),
1204
+ children: [/* @__PURE__ */ jsxDEV("div", {
1205
+ class: "sel-search",
1206
+ children: /* @__PURE__ */ jsxDEV("input", {
1207
+ ref: projectSearchRef,
1208
+ class: "sel-search-input",
1209
+ type: "text",
1210
+ placeholder: t("web.searchProjects"),
1211
+ value: s.projectSearch,
1212
+ onChange: (e) => d({
1213
+ type: "SET_PROJECT_SEARCH",
1214
+ search: e.target.value
1215
+ }),
1216
+ onKeyDown: (e) => {
1217
+ const n = selKeyDown(e, s.projectOpen, fp.length, s.projectIndex, (i) => {
1218
+ const p = fp[i];
1219
+ if (p) handleSelectProject(p);
1220
+ }, () => d({
1221
+ type: "SET_PROJECT_OPEN",
1222
+ open: false
1223
+ }));
1224
+ if (n !== void 0) d({
1225
+ type: "SET_PROJECT_INDEX",
1226
+ index: n
1227
+ });
1228
+ }
1229
+ })
1230
+ }), fp.length > 0 ? fp.map((p, i) => /* @__PURE__ */ jsxDEV("div", {
1231
+ class: `sel-item${s.selected?.id === p.id ? " active" : ""}${i === s.projectIndex ? " highlighted" : ""}`,
1232
+ onMouseEnter: () => d({
1233
+ type: "SET_PROJECT_INDEX",
1234
+ index: i
1235
+ }),
1236
+ onClick: () => handleSelectProject(p),
1237
+ children: [/* @__PURE__ */ jsxDEV("div", {
1238
+ class: "sel-item-name",
1239
+ children: p.name
1240
+ }), /* @__PURE__ */ jsxDEV("div", {
1241
+ class: "sel-item-sub",
1242
+ children: p.pathWithNamespace
1243
+ })]
1244
+ })) : /* @__PURE__ */ jsxDEV("div", {
1245
+ class: "sel-empty",
1246
+ children: t("web.noProjects")
1247
+ })]
1248
+ })]
1249
+ }),
1250
+ s.selected && (s.branchesLoading ? /* @__PURE__ */ jsxDEV("div", {
1251
+ class: "loading-row",
1252
+ children: [/* @__PURE__ */ jsxDEV("span", { class: "spinner" }), t("web.loadingBranches")]
1253
+ }) : s.branches.length > 0 && /* @__PURE__ */ jsxDEV("div", {
1254
+ class: "sel",
1255
+ "data-sel": "branch",
1256
+ style: `z-index:${s.branchOpen ? 100 : 1}`,
1257
+ children: [/* @__PURE__ */ jsxDEV("button", {
1258
+ class: `sel-trigger${s.branchOpen ? " open" : ""}`,
1259
+ type: "button",
1260
+ role: "combobox",
1261
+ "aria-expanded": s.branchOpen,
1262
+ "aria-haspopup": "listbox",
1263
+ onClick: () => {
1264
+ d({
1265
+ type: "SET_PROJECT_OPEN",
1266
+ open: false
1267
+ });
1268
+ d({
1269
+ type: "SET_JIRA_PROJECT_OPEN",
1270
+ open: false
1271
+ });
1272
+ d({
1273
+ type: "SET_BRANCH_OPEN",
1274
+ open: !s.branchOpen
1275
+ });
1276
+ },
1277
+ children: [
1278
+ /* @__PURE__ */ jsxDEV("span", {
1279
+ class: "sel-trigger-label",
1280
+ children: t("web.branchLabel")
1281
+ }),
1282
+ /* @__PURE__ */ jsxDEV("span", {
1283
+ class: `sel-trigger-value${s.selectedBranch ? "" : " empty"}`,
1284
+ children: s.selectedBranch || t("web.selectBranch")
1285
+ }),
1286
+ /* @__PURE__ */ jsxDEV("span", {
1287
+ class: "sel-trigger-arrow",
1288
+ children: "▼"
1289
+ })
1290
+ ]
1291
+ }), s.branchOpen && /* @__PURE__ */ jsxDEV("div", {
1292
+ class: "sel-dropdown",
1293
+ role: "listbox",
1294
+ "aria-label": t("web.selectBranch"),
1295
+ children: [/* @__PURE__ */ jsxDEV("div", {
1296
+ class: "sel-search",
1297
+ children: /* @__PURE__ */ jsxDEV("input", {
1298
+ ref: branchSearchRef,
1299
+ class: "sel-search-input",
1300
+ type: "text",
1301
+ placeholder: t("web.filterBranches"),
1302
+ value: s.branchSearch,
1303
+ onChange: (e) => d({
1304
+ type: "SET_BRANCH_SEARCH",
1305
+ search: e.target.value
1306
+ }),
1307
+ onKeyDown: (e) => {
1308
+ const n = selKeyDown(e, s.branchOpen, fb.length, s.branchIndex, (i) => {
1309
+ const b = fb[i];
1310
+ if (b) handleSelectBranch(b.name);
1311
+ }, () => d({
1312
+ type: "SET_BRANCH_OPEN",
1313
+ open: false
1314
+ }));
1315
+ if (n !== void 0) d({
1316
+ type: "SET_BRANCH_INDEX",
1317
+ index: n
1318
+ });
1319
+ }
1320
+ })
1321
+ }), fb.length > 0 ? fb.map((b, i) => /* @__PURE__ */ jsxDEV("div", {
1322
+ class: `sel-item${b.name === s.selectedBranch ? " active" : ""}${i === s.branchIndex ? " highlighted" : ""}`,
1323
+ onMouseEnter: () => d({
1324
+ type: "SET_BRANCH_INDEX",
1325
+ index: i
1326
+ }),
1327
+ onClick: () => handleSelectBranch(b.name),
1328
+ children: [/* @__PURE__ */ jsxDEV("span", {
1329
+ class: "sel-item-name",
1330
+ children: b.name
1331
+ }), b.default && /* @__PURE__ */ jsxDEV("span", {
1332
+ style: "font-size:10px;color:var(--neon);margin-left:6px",
1333
+ children: t("web.defaultBranch")
1334
+ })]
1335
+ })) : /* @__PURE__ */ jsxDEV("div", {
1336
+ class: "sel-empty",
1337
+ children: t("web.noBranches")
1338
+ })]
1339
+ })]
1340
+ })),
1341
+ s.selected && s.selectedBranch && !s.branchesLoading && (s.pomLoading ? /* @__PURE__ */ jsxDEV("div", {
1342
+ class: "loading-row",
1343
+ children: [/* @__PURE__ */ jsxDEV("span", { class: "spinner" }), t("web.loadingVersion")]
1344
+ }) : s.pomError ? /* @__PURE__ */ jsxDEV("div", {
1345
+ class: "version-error",
1346
+ role: "alert",
1347
+ children: s.pomError.includes("404") ? t("web.noPom") : s.pomError
1348
+ }) : s.pomInfo && /* @__PURE__ */ jsxDEV("div", {
1349
+ class: "version-display",
1350
+ children: [/* @__PURE__ */ jsxDEV("span", {
1351
+ class: "version-tag",
1352
+ children: t("web.versionTag")
1353
+ }), /* @__PURE__ */ jsxDEV("span", {
1354
+ class: "version-number",
1355
+ children: cleanVersion(s.pomInfo.version)
1356
+ })]
1357
+ })),
1358
+ s.selected && s.pomInfo?.version && !s.pomLoading && /* @__PURE__ */ jsxDEV("div", {
1359
+ class: "jira-section",
1360
+ children: [
1361
+ s.jiraProjectsLoading ? /* @__PURE__ */ jsxDEV("div", {
1362
+ class: "loading-row",
1363
+ children: [/* @__PURE__ */ jsxDEV("span", { class: "spinner" }), t("web.loadingJiraProjects")]
1364
+ }) : /* @__PURE__ */ jsxDEV("div", {
1365
+ class: "sel",
1366
+ "data-sel": "jira",
1367
+ style: `z-index:${s.jiraProjectOpen ? 100 : 1}`,
1368
+ children: [/* @__PURE__ */ jsxDEV("button", {
1369
+ class: `sel-trigger${s.jiraProjectOpen ? " open" : ""}`,
1370
+ type: "button",
1371
+ role: "combobox",
1372
+ "aria-expanded": s.jiraProjectOpen,
1373
+ "aria-haspopup": "listbox",
1374
+ onClick: () => {
1375
+ d({
1376
+ type: "SET_PROJECT_OPEN",
1377
+ open: false
1378
+ });
1379
+ d({
1380
+ type: "SET_BRANCH_OPEN",
1381
+ open: false
1382
+ });
1383
+ d({
1384
+ type: "SET_JIRA_PROJECT_OPEN",
1385
+ open: !s.jiraProjectOpen
1386
+ });
1387
+ },
1388
+ children: [
1389
+ /* @__PURE__ */ jsxDEV("span", {
1390
+ class: "sel-trigger-label",
1391
+ children: t("web.jiraProjectLabel")
1392
+ }),
1393
+ /* @__PURE__ */ jsxDEV("span", {
1394
+ class: `sel-trigger-value${s.selectedJiraProject ? "" : " empty"}`,
1395
+ children: s.selectedJiraProject ? `${s.selectedJiraProject.key} - ${s.selectedJiraProject.name ?? ""}` : t("web.selectJiraProject")
1396
+ }),
1397
+ /* @__PURE__ */ jsxDEV("span", {
1398
+ class: "sel-trigger-arrow",
1399
+ children: "▼"
1400
+ })
1401
+ ]
1402
+ }), s.jiraProjectOpen && /* @__PURE__ */ jsxDEV("div", {
1403
+ class: "sel-dropdown",
1404
+ role: "listbox",
1405
+ "aria-label": t("web.selectJiraProject"),
1406
+ children: [/* @__PURE__ */ jsxDEV("div", {
1407
+ class: "sel-search",
1408
+ children: /* @__PURE__ */ jsxDEV("input", {
1409
+ ref: jiraSearchRef,
1410
+ class: "sel-search-input",
1411
+ type: "text",
1412
+ placeholder: t("web.searchJiraProject"),
1413
+ value: s.jiraProjectSearch,
1414
+ onChange: (e) => d({
1415
+ type: "SET_JIRA_PROJECT_SEARCH",
1416
+ search: e.target.value
1417
+ }),
1418
+ onKeyDown: (e) => {
1419
+ const n = selKeyDown(e, s.jiraProjectOpen, fj.length, s.jiraProjectIndex, (i) => {
1420
+ const p = fj[i];
1421
+ if (p) d({
1422
+ type: "SELECT_JIRA_PROJECT",
1423
+ project: p
1424
+ });
1425
+ }, () => d({
1426
+ type: "SET_JIRA_PROJECT_OPEN",
1427
+ open: false
1428
+ }));
1429
+ if (n !== void 0) d({
1430
+ type: "SET_JIRA_PROJECT_INDEX",
1431
+ index: n
1432
+ });
1433
+ }
1434
+ })
1435
+ }), fj.length > 0 ? fj.map((p, i) => /* @__PURE__ */ jsxDEV("div", {
1436
+ class: `sel-item${s.selectedJiraProject?.key === p.key ? " active" : ""}${i === s.jiraProjectIndex ? " highlighted" : ""}`,
1437
+ onMouseEnter: () => d({
1438
+ type: "SET_JIRA_PROJECT_INDEX",
1439
+ index: i
1440
+ }),
1441
+ onClick: () => d({
1442
+ type: "SELECT_JIRA_PROJECT",
1443
+ project: p
1444
+ }),
1445
+ children: [/* @__PURE__ */ jsxDEV("span", {
1446
+ class: "sel-item-name",
1447
+ children: p.key
1448
+ }), p.name && /* @__PURE__ */ jsxDEV("div", {
1449
+ class: "sel-item-sub",
1450
+ children: p.name
1451
+ })]
1452
+ })) : /* @__PURE__ */ jsxDEV("div", {
1453
+ class: "sel-empty",
1454
+ children: t("web.noJiraProjects")
1455
+ })]
1456
+ })]
1457
+ }),
1458
+ /* @__PURE__ */ jsxDEV("button", {
1459
+ class: "jira-btn",
1460
+ type: "button",
1461
+ disabled: !s.selectedJiraProject || s.jiraStatus === "checking" || s.jiraStatus === "creating",
1462
+ onClick: handleCreateIssue,
1463
+ children: s.jiraStatus === "checking" ? t("web.checkingBtn") : s.jiraStatus === "creating" ? t("web.creatingBtn") : t("web.createBtn")
1464
+ }),
1465
+ (s.jiraStatus === "checking" || s.jiraStatus === "creating") && /* @__PURE__ */ jsxDEV("div", {
1466
+ class: "loading-row",
1467
+ style: "margin-top:12px",
1468
+ children: [/* @__PURE__ */ jsxDEV("span", { class: "spinner" }), s.jiraStatus === "checking" ? t("web.checkingIssues") : t("web.creatingIssue")]
1469
+ }),
1470
+ s.jiraResult && /* @__PURE__ */ jsxDEV("div", {
1471
+ class: "jira-result",
1472
+ children: [
1473
+ /* @__PURE__ */ jsxDEV("div", {
1474
+ class: "jira-result-label",
1475
+ children: s.jiraResult.exists ? t("web.versionExistsResult", { version: s.jiraResult.versionName }) : t("web.versionCreatedResult", { version: s.jiraResult.versionName })
1476
+ }),
1477
+ /* @__PURE__ */ jsxDEV("a", {
1478
+ class: "jira-result-key",
1479
+ href: jiraUrl,
1480
+ target: "_blank",
1481
+ rel: "noreferrer",
1482
+ children: s.jiraResult.key
1483
+ }),
1484
+ /* @__PURE__ */ jsxDEV("span", {
1485
+ class: `jira-result-badge ${s.jiraResult.exists ? "exists" : "created"}`,
1486
+ children: s.jiraResult.exists ? t("web.existsBadge") : t("web.createdBadge")
1487
+ })
1488
+ ]
1489
+ }),
1490
+ s.jiraError && /* @__PURE__ */ jsxDEV("div", {
1491
+ class: "jira-error",
1492
+ role: "alert",
1493
+ children: s.jiraError
1494
+ })
1495
+ ]
1496
+ }),
1497
+ !s.selected && /* @__PURE__ */ jsxDEV("div", {
1498
+ class: "empty-hint",
1499
+ children: t("web.emptyHint")
1500
+ })
1501
+ ] });
1502
+ };
1503
+ const ReleaseClient = () => {
1504
+ const [s, d] = useReducer(reducer, initial);
1505
+ useEffect(() => {
1506
+ fetch("/release/api/history").then((r) => r.json()).then((data) => d({
1507
+ type: "SET_HISTORY",
1508
+ history: Array.isArray(data) ? data : []
1509
+ })).catch(() => d({
1510
+ type: "SET_HISTORY",
1511
+ history: []
1512
+ }));
1513
+ }, []);
1514
+ return /* @__PURE__ */ jsxDEV("div", { children: [
1515
+ /* @__PURE__ */ jsxDEV("style", { children: releaseStyle }),
1516
+ /* @__PURE__ */ jsxDEV("div", {
1517
+ class: "page-header",
1518
+ children: [/* @__PURE__ */ jsxDEV("h2", { children: t("web.releaseTitle") }), /* @__PURE__ */ jsxDEV("p", { children: t("web.releaseDesc") })]
1519
+ }),
1520
+ s.historyLoading ? /* @__PURE__ */ jsxDEV("div", {
1521
+ class: "loading-row",
1522
+ children: [/* @__PURE__ */ jsxDEV("span", { class: "spinner" }), t("web.loading")]
1523
+ }) : s.showNewModal ? /* @__PURE__ */ jsxDEV("div", {
1524
+ class: "modal-overlay",
1525
+ onClick: (e) => {
1526
+ if (e.target.classList.contains("modal-overlay")) fetch("/release/api/history").then((r) => r.json()).then((data) => {
1527
+ d({
1528
+ type: "SET_HISTORY",
1529
+ history: Array.isArray(data) ? data : []
1530
+ });
1531
+ d({ type: "HIDE_NEW_MODAL" });
1532
+ }).catch(() => d({ type: "HIDE_NEW_MODAL" }));
1533
+ },
1534
+ children: /* @__PURE__ */ jsxDEV("div", {
1535
+ class: "modal-content",
1536
+ children: [/* @__PURE__ */ jsxDEV("div", {
1537
+ class: "modal-header",
1538
+ children: [/* @__PURE__ */ jsxDEV("span", {
1539
+ class: "modal-title",
1540
+ children: t("web.newModalTitle")
1541
+ }), /* @__PURE__ */ jsxDEV("button", {
1542
+ class: "modal-close",
1543
+ type: "button",
1544
+ onClick: () => {
1545
+ fetch("/release/api/history").then((r) => r.json()).then((data) => {
1546
+ d({
1547
+ type: "SET_HISTORY",
1548
+ history: Array.isArray(data) ? data : []
1549
+ });
1550
+ d({ type: "HIDE_NEW_MODAL" });
1551
+ }).catch(() => d({ type: "HIDE_NEW_MODAL" }));
1552
+ },
1553
+ children: "✕"
1554
+ })]
1555
+ }), /* @__PURE__ */ jsxDEV(ReleaseFlow, {
1556
+ s,
1557
+ d
1558
+ })]
1559
+ })
1560
+ }) : s.history.length > 0 ? /* @__PURE__ */ jsxDEV(HistoryList, {
1561
+ s,
1562
+ d
1563
+ }) : /* @__PURE__ */ jsxDEV(ReleaseFlow, {
1564
+ s,
1565
+ d
1566
+ })
1567
+ ] });
1568
+ };
1569
+ const mount = async (el) => {
1570
+ await initPromise;
1571
+ render(/* @__PURE__ */ jsxDEV(ReleaseClient, {}), el);
1572
+ };
1573
+ //#endregion
1574
+ export { mount };