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,1399 @@
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/end/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 endStyle = `
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
+ /* ── Cwd input ── */
30
+ .cwd-section {
31
+ margin-bottom: 20px;
32
+ animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) both;
33
+ }
34
+ .cwd-row {
35
+ display: flex;
36
+ gap: 8px;
37
+ align-items: stretch;
38
+ }
39
+ .cwd-input {
40
+ flex: 1;
41
+ padding: 10px 14px;
42
+ font-size: 13px;
43
+ font-family: var(--mono);
44
+ color: var(--text-1);
45
+ background: var(--bg-input);
46
+ border: 1px solid var(--border);
47
+ border-radius: 8px;
48
+ outline: none;
49
+ transition: border-color 0.15s;
50
+ }
51
+ .cwd-input::placeholder { color: var(--text-3); }
52
+ .cwd-input:focus { border-color: var(--neon); }
53
+ .cwd-btn {
54
+ padding: 10px 16px;
55
+ font-size: 13px;
56
+ font-family: var(--sans);
57
+ font-weight: 500;
58
+ color: var(--bg-void);
59
+ background: var(--neon);
60
+ border: none;
61
+ border-radius: 8px;
62
+ cursor: pointer;
63
+ transition: background 0.15s;
64
+ }
65
+ .cwd-btn:hover { background: var(--neon-hover); }
66
+ .cwd-btn:disabled { opacity: 0.5; cursor: not-allowed; }
67
+ .cwd-error {
68
+ font-size: 12px;
69
+ color: var(--error);
70
+ margin-top: 6px;
71
+ }
72
+ .cwd-display {
73
+ display: flex;
74
+ align-items: center;
75
+ gap: 12px;
76
+ padding: 12px 16px;
77
+ background: var(--bg-card);
78
+ border: 1px solid var(--border);
79
+ border-radius: 8px;
80
+ font-family: var(--mono);
81
+ font-size: 13px;
82
+ color: var(--text-1);
83
+ }
84
+ .cwd-display-label {
85
+ font-size: 11px;
86
+ color: var(--text-3);
87
+ text-transform: uppercase;
88
+ letter-spacing: 0.05em;
89
+ }
90
+
91
+ /* ── Pipeline ── */
92
+ .pipeline {
93
+ display: flex;
94
+ align-items: center;
95
+ gap: 0;
96
+ margin-bottom: 28px;
97
+ animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) 0.08s both;
98
+ }
99
+ .pipeline-step {
100
+ display: flex;
101
+ align-items: center;
102
+ gap: 6px;
103
+ font-size: 11px;
104
+ font-family: var(--mono);
105
+ color: var(--text-3);
106
+ font-weight: 400;
107
+ white-space: nowrap;
108
+ }
109
+ .pipeline-step.active {
110
+ color: var(--neon);
111
+ font-weight: 500;
112
+ }
113
+ .pipeline-step.done {
114
+ color: var(--cyan);
115
+ }
116
+ .pipeline-node {
117
+ width: 8px; height: 8px;
118
+ border-radius: 50%;
119
+ background: var(--text-3);
120
+ transition: background 0.3s, box-shadow 0.3s;
121
+ }
122
+ .pipeline-step.active .pipeline-node {
123
+ background: var(--neon);
124
+ box-shadow: 0 0 8px var(--neon-glow);
125
+ animation: neon-pulse 2s ease infinite;
126
+ }
127
+ .pipeline-step.done .pipeline-node {
128
+ background: var(--cyan);
129
+ box-shadow: 0 0 4px var(--cyan-glow);
130
+ }
131
+ .pipeline-line {
132
+ width: 32px;
133
+ height: 1px;
134
+ background: var(--border);
135
+ margin: 0 4px;
136
+ transition: background 0.3s;
137
+ }
138
+ .pipeline-line.done { background: var(--cyan); }
139
+
140
+ /* ── Select ── */
141
+ .sel {
142
+ position: relative;
143
+ margin-bottom: 16px;
144
+ animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) 0.12s both;
145
+ z-index: 1;
146
+ }
147
+ .sel-trigger {
148
+ width: 100%;
149
+ display: flex;
150
+ align-items: center;
151
+ gap: 8px;
152
+ padding: 12px 14px;
153
+ font-size: 13px;
154
+ font-family: var(--sans);
155
+ color: var(--text-1);
156
+ background: var(--bg-input);
157
+ border: 1px solid var(--border);
158
+ border-radius: 8px;
159
+ cursor: pointer;
160
+ outline: none;
161
+ transition: border-color 0.2s, box-shadow 0.2s;
162
+ text-align: left;
163
+ }
164
+ .sel-trigger:hover { border-color: var(--border-active); }
165
+ .sel-trigger:focus,
166
+ .sel-trigger.open {
167
+ border-color: var(--neon);
168
+ box-shadow: 0 0 0 2px var(--neon-soft), 0 0 8px var(--neon-glow);
169
+ }
170
+ .sel-trigger-label {
171
+ font-size: 11px;
172
+ color: var(--text-3);
173
+ flex-shrink: 0;
174
+ }
175
+ .sel-trigger-value {
176
+ flex: 1;
177
+ font-family: var(--mono);
178
+ font-size: 13px;
179
+ font-weight: 500;
180
+ color: var(--text-1);
181
+ }
182
+ .sel-trigger-value.empty {
183
+ color: var(--text-3);
184
+ font-weight: 300;
185
+ }
186
+ .sel-trigger-arrow {
187
+ color: var(--text-3);
188
+ font-size: 10px;
189
+ transition: transform 0.2s;
190
+ }
191
+ .sel-trigger.open .sel-trigger-arrow {
192
+ transform: rotate(180deg);
193
+ }
194
+ .sel-dropdown {
195
+ position: absolute;
196
+ top: calc(100% + 6px);
197
+ left: 0; right: 0;
198
+ max-height: 280px;
199
+ overflow-y: auto;
200
+ background: var(--bg-card);
201
+ border: 1px solid rgba(0,255,136,0.08);
202
+ border-radius: 8px;
203
+ box-shadow: 0 8px 32px rgba(0,0,0,0.6), 0 0 12px rgba(0,255,136,0.03);
204
+ z-index: 1000;
205
+ animation: dropdown-in 0.12s ease both;
206
+ }
207
+ .sel-dropdown::-webkit-scrollbar { width: 6px; }
208
+ .sel-dropdown::-webkit-scrollbar-track { background: transparent; }
209
+ .sel-dropdown::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
210
+ .sel-search {
211
+ padding: 8px;
212
+ border-bottom: 1px solid var(--border);
213
+ position: sticky;
214
+ top: 0;
215
+ background: var(--bg-card);
216
+ z-index: 1;
217
+ }
218
+ .sel-search-input {
219
+ width: 100%;
220
+ padding: 6px 10px;
221
+ font-size: 12px;
222
+ font-family: var(--mono);
223
+ color: var(--text-1);
224
+ background: var(--bg-void);
225
+ border: 1px solid var(--border);
226
+ border-radius: 4px;
227
+ outline: none;
228
+ transition: border-color 0.15s;
229
+ }
230
+ .sel-search-input::placeholder { color: var(--text-3); }
231
+ .sel-search-input:focus { border-color: var(--neon); }
232
+ .sel-item {
233
+ padding: 10px 14px;
234
+ font-size: 13px;
235
+ cursor: pointer;
236
+ transition: background 0.1s;
237
+ border-left: 3px solid transparent;
238
+ }
239
+ .sel-item:first-child { border-radius: 7px 7px 0 0; }
240
+ .sel-item:last-child { border-radius: 0 0 7px 7px; }
241
+ .sel-item:hover,
242
+ .sel-item.highlighted { background: var(--bg-hover); }
243
+ .sel-item.active {
244
+ background: var(--neon-soft);
245
+ border-left-color: var(--neon);
246
+ font-weight: 500;
247
+ }
248
+ .sel-item-name { font-weight: 500; color: var(--text-1); }
249
+ .sel-empty { padding: 12px; text-align: center; color: var(--text-3); font-size: 12px; }
250
+
251
+ /* ── Spinner ── */
252
+ .spinner {
253
+ display: inline-block;
254
+ width: 14px; height: 14px;
255
+ border: 2px solid var(--border);
256
+ border-top-color: var(--neon);
257
+ border-radius: 50%;
258
+ animation: spin 0.6s linear infinite;
259
+ }
260
+ @keyframes spin { to { transform: rotate(360deg); } }
261
+ .loading-row {
262
+ display: flex;
263
+ align-items: center;
264
+ gap: 8px;
265
+ padding: 10px 14px;
266
+ color: var(--text-3);
267
+ font-size: 13px;
268
+ margin-bottom: 16px;
269
+ animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) both;
270
+ }
271
+
272
+ /* ── Info card ── */
273
+ .info-card {
274
+ display: flex;
275
+ align-items: center;
276
+ gap: 12px;
277
+ padding: 14px 20px;
278
+ background: var(--bg-card);
279
+ border: 1px solid var(--border);
280
+ border-radius: 8px;
281
+ margin-bottom: 16px;
282
+ animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) both;
283
+ }
284
+ .info-label {
285
+ font-size: 11px;
286
+ color: var(--text-3);
287
+ text-transform: uppercase;
288
+ letter-spacing: 0.05em;
289
+ font-family: var(--mono);
290
+ }
291
+ .info-value {
292
+ font-size: 15px;
293
+ font-weight: 600;
294
+ font-family: var(--mono);
295
+ color: var(--cyan);
296
+ letter-spacing: -0.01em;
297
+ }
298
+ .info-value.neon { color: var(--neon); }
299
+
300
+ /* ── Action button ── */
301
+ .action-btn {
302
+ width: 100%;
303
+ min-height: 44px;
304
+ padding: 10px 20px;
305
+ font-size: 13px;
306
+ font-family: var(--sans);
307
+ font-weight: 500;
308
+ color: var(--bg-void);
309
+ background: var(--neon);
310
+ border: none;
311
+ border-radius: 8px;
312
+ cursor: pointer;
313
+ transition: background 0.15s, box-shadow 0.2s;
314
+ margin-bottom: 16px;
315
+ position: relative;
316
+ z-index: 1;
317
+ }
318
+ .action-btn:hover { background: var(--neon-hover); box-shadow: 0 0 12px var(--neon-glow), 0 2px 12px rgba(0,255,136,0.2); }
319
+ .action-btn:disabled { opacity: 0.5; cursor: not-allowed; }
320
+ .action-btn.secondary {
321
+ color: var(--text-3);
322
+ background: transparent;
323
+ border: 1px solid var(--border);
324
+ }
325
+ .action-btn.secondary:hover { border-color: var(--text-2); color: var(--text-2); }
326
+ .action-btn.rerun {
327
+ color: var(--text-2);
328
+ background: var(--bg-card);
329
+ border: 1px solid var(--border);
330
+ margin-top: 24px;
331
+ }
332
+ .action-btn.rerun:hover { border-color: var(--neon); color: var(--neon); }
333
+
334
+ /* ── Result card ── */
335
+ .result-card {
336
+ padding: 12px 16px;
337
+ background: var(--bg-card);
338
+ border: 1px solid rgba(0,212,255,0.08);
339
+ border-radius: 8px;
340
+ margin-bottom: 16px;
341
+ animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) both;
342
+ }
343
+ .result-success {
344
+ border-color: rgba(0,255,136,0.12);
345
+ }
346
+ .result-error {
347
+ border-color: rgba(255,68,68,0.12);
348
+ }
349
+ .result-label {
350
+ font-size: 11px;
351
+ color: var(--text-3);
352
+ margin-bottom: 4px;
353
+ }
354
+ .result-key {
355
+ font-family: var(--mono);
356
+ font-size: 14px;
357
+ font-weight: 600;
358
+ color: var(--neon);
359
+ text-decoration: none;
360
+ border-bottom: 1px dashed rgba(0,255,136,0.3);
361
+ transition: border-color 0.2s;
362
+ }
363
+ .result-key:hover { border-bottom-color: var(--neon); }
364
+ .result-text {
365
+ font-family: var(--mono);
366
+ font-size: 14px;
367
+ font-weight: 600;
368
+ }
369
+ .result-text.success { color: var(--neon); }
370
+ .result-text.error { color: var(--error); }
371
+ .result-badge {
372
+ display: inline-block;
373
+ font-size: 10px;
374
+ padding: 2px 8px;
375
+ border-radius: 4px;
376
+ margin-left: 8px;
377
+ font-weight: 500;
378
+ background: var(--neon-soft);
379
+ color: var(--neon);
380
+ }
381
+ .mr-url-row {
382
+ display: flex;
383
+ align-items: center;
384
+ gap: 8px;
385
+ margin-top: 8px;
386
+ }
387
+ .mr-url-input {
388
+ flex: 1;
389
+ padding: 8px 12px;
390
+ font-size: 12px;
391
+ font-family: var(--mono);
392
+ color: var(--text-1);
393
+ background: var(--bg-void);
394
+ border: 1px solid var(--border);
395
+ border-radius: 6px;
396
+ outline: none;
397
+ }
398
+ .copy-btn {
399
+ padding: 8px 12px;
400
+ font-size: 11px;
401
+ font-family: var(--sans);
402
+ font-weight: 500;
403
+ color: var(--bg-void);
404
+ background: var(--cyan);
405
+ border: none;
406
+ border-radius: 6px;
407
+ cursor: pointer;
408
+ transition: background 0.15s;
409
+ }
410
+ .copy-btn:hover { background: #33e0ff; }
411
+ .copy-btn.copied { background: var(--neon); }
412
+
413
+ /* ── Ticket list ── */
414
+ .ticket-list {
415
+ display: flex;
416
+ flex-direction: column;
417
+ gap: 8px;
418
+ margin-bottom: 16px;
419
+ }
420
+ .ticket-item {
421
+ display: flex;
422
+ align-items: center;
423
+ justify-content: space-between;
424
+ padding: 12px 16px;
425
+ background: var(--bg-card);
426
+ border: 1px solid var(--border);
427
+ border-radius: 8px;
428
+ animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) both;
429
+ transition: border-color 0.15s;
430
+ }
431
+ .ticket-item:hover { border-color: var(--border-active); }
432
+ .ticket-key {
433
+ font-family: var(--mono);
434
+ font-size: 14px;
435
+ font-weight: 600;
436
+ color: var(--neon);
437
+ text-decoration: none;
438
+ border-bottom: 1px dashed rgba(0,255,136,0.3);
439
+ }
440
+ .ticket-key:hover { border-bottom-color: var(--neon); }
441
+ .ticket-status {
442
+ font-size: 12px;
443
+ color: var(--text-3);
444
+ }
445
+ .ticket-status.success { color: var(--neon); }
446
+ .ticket-status.error { color: var(--error); }
447
+ .ticket-transitions {
448
+ display: flex;
449
+ gap: 6px;
450
+ margin-top: 8px;
451
+ }
452
+ .trans-btn {
453
+ padding: 6px 12px;
454
+ font-size: 12px;
455
+ font-family: var(--sans);
456
+ font-weight: 400;
457
+ color: var(--text-2);
458
+ background: var(--bg-input);
459
+ border: 1px solid var(--border);
460
+ border-radius: 6px;
461
+ cursor: pointer;
462
+ transition: border-color 0.15s, color 0.15s;
463
+ }
464
+ .trans-btn:hover { border-color: var(--neon); color: var(--neon); }
465
+ .trans-btn:disabled { opacity: 0.5; cursor: not-allowed; }
466
+ .trans-btn.primary {
467
+ border-color: var(--neon);
468
+ color: var(--neon);
469
+ background: var(--neon-soft);
470
+ }
471
+
472
+ /* ── Warning ── */
473
+ .warning-card {
474
+ padding: 12px 16px;
475
+ background: rgba(255,184,0,0.04);
476
+ border: 1px solid rgba(255,184,0,0.12);
477
+ border-radius: 8px;
478
+ margin-bottom: 16px;
479
+ color: var(--warning);
480
+ font-size: 13px;
481
+ animation: slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1) both;
482
+ }
483
+
484
+ .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; }
485
+ `;
486
+ const initial = {
487
+ cwd: "",
488
+ cwdInput: "",
489
+ cwdError: "",
490
+ currentBranch: "",
491
+ localBranches: [],
492
+ detectedSource: "",
493
+ loading: false,
494
+ error: "",
495
+ branchOpen: false,
496
+ branchSearch: "",
497
+ branchIndex: -1,
498
+ targetBranch: "",
499
+ rebaseStatus: "idle",
500
+ rebaseError: "",
501
+ pushStatus: "idle",
502
+ pushError: "",
503
+ ticketKeys: [],
504
+ ticketsLoading: false,
505
+ ticketsError: "",
506
+ mrStatus: "idle",
507
+ mrUrl: "",
508
+ mrError: "",
509
+ copied: false,
510
+ jiraStatus: {},
511
+ jiraTransitions: {},
512
+ jiraErrors: {},
513
+ jiraResults: {}
514
+ };
515
+ const reducer = (state, action) => {
516
+ switch (action.type) {
517
+ case "SET_CWD_INPUT": return {
518
+ ...state,
519
+ cwdInput: action.value,
520
+ cwdError: ""
521
+ };
522
+ case "SET_CWD": return {
523
+ ...state,
524
+ cwd: action.cwd,
525
+ cwdError: ""
526
+ };
527
+ case "CWD_ERROR": return {
528
+ ...state,
529
+ cwdError: action.error
530
+ };
531
+ case "LOADED": return {
532
+ ...state,
533
+ ...action.data,
534
+ loading: false,
535
+ targetBranch: action.data.detectedSource || ""
536
+ };
537
+ case "LOAD_ERROR": return {
538
+ ...state,
539
+ loading: false,
540
+ error: action.error
541
+ };
542
+ case "SET_BRANCH_OPEN": return {
543
+ ...state,
544
+ branchOpen: action.open,
545
+ ...action.open ? {} : {
546
+ branchSearch: "",
547
+ branchIndex: -1
548
+ }
549
+ };
550
+ case "SET_BRANCH_SEARCH": return {
551
+ ...state,
552
+ branchSearch: action.search,
553
+ branchIndex: -1
554
+ };
555
+ case "SET_BRANCH_INDEX": return {
556
+ ...state,
557
+ branchIndex: action.index
558
+ };
559
+ case "SELECT_TARGET_BRANCH": return {
560
+ ...state,
561
+ targetBranch: action.branch,
562
+ branchOpen: false,
563
+ branchSearch: "",
564
+ branchIndex: -1
565
+ };
566
+ case "REBASE_RUNNING": return {
567
+ ...state,
568
+ rebaseStatus: "running",
569
+ rebaseError: ""
570
+ };
571
+ case "REBASE_SUCCESS": return {
572
+ ...state,
573
+ rebaseStatus: "success"
574
+ };
575
+ case "REBASE_CONFLICT": return {
576
+ ...state,
577
+ rebaseStatus: "conflict"
578
+ };
579
+ case "REBASE_ERROR": return {
580
+ ...state,
581
+ rebaseStatus: "error",
582
+ rebaseError: action.error
583
+ };
584
+ case "PUSH_RUNNING": return {
585
+ ...state,
586
+ pushStatus: "running",
587
+ pushError: ""
588
+ };
589
+ case "PUSH_SUCCESS": return {
590
+ ...state,
591
+ pushStatus: "success"
592
+ };
593
+ case "PUSH_ERROR": return {
594
+ ...state,
595
+ pushStatus: "error",
596
+ pushError: action.error
597
+ };
598
+ case "TICKETS_LOADING": return {
599
+ ...state,
600
+ ticketsLoading: true,
601
+ ticketsError: ""
602
+ };
603
+ case "TICKETS_LOADED": return {
604
+ ...state,
605
+ ticketsLoading: false,
606
+ ticketKeys: action.keys
607
+ };
608
+ case "TICKETS_ERROR": return {
609
+ ...state,
610
+ ticketsLoading: false,
611
+ ticketsError: action.error
612
+ };
613
+ case "MR_RUNNING": return {
614
+ ...state,
615
+ mrStatus: "running",
616
+ mrError: ""
617
+ };
618
+ case "MR_SUCCESS": return {
619
+ ...state,
620
+ mrStatus: "success",
621
+ mrUrl: action.url
622
+ };
623
+ case "MR_ERROR": return {
624
+ ...state,
625
+ mrStatus: "error",
626
+ mrError: action.error
627
+ };
628
+ case "MR_SKIPPED": return {
629
+ ...state,
630
+ mrStatus: "skipped"
631
+ };
632
+ case "COPIED": return {
633
+ ...state,
634
+ copied: true
635
+ };
636
+ case "JIRA_LOADING": return {
637
+ ...state,
638
+ jiraStatus: {
639
+ ...state.jiraStatus,
640
+ [action.key]: "loading"
641
+ }
642
+ };
643
+ case "JIRA_TRANSITIONS_LOADED": return {
644
+ ...state,
645
+ jiraStatus: {
646
+ ...state.jiraStatus,
647
+ [action.key]: "idle"
648
+ },
649
+ jiraTransitions: {
650
+ ...state.jiraTransitions,
651
+ [action.key]: action.transitions
652
+ }
653
+ };
654
+ case "JIRA_TRANSITION_SUCCESS": return {
655
+ ...state,
656
+ jiraStatus: {
657
+ ...state.jiraStatus,
658
+ [action.key]: "success"
659
+ },
660
+ jiraResults: {
661
+ ...state.jiraResults,
662
+ [action.key]: action.name
663
+ }
664
+ };
665
+ case "JIRA_TRANSITION_ERROR": return {
666
+ ...state,
667
+ jiraStatus: {
668
+ ...state.jiraStatus,
669
+ [action.key]: "error"
670
+ },
671
+ jiraErrors: {
672
+ ...state.jiraErrors,
673
+ [action.key]: action.error
674
+ }
675
+ };
676
+ case "RESET": return {
677
+ ...initial,
678
+ cwd: state.cwd,
679
+ cwdInput: state.cwd
680
+ };
681
+ }
682
+ return state;
683
+ };
684
+ const selKeyDown = (e, open, len, idx, onSelect, onClose) => {
685
+ if (!open || len === 0) return void 0;
686
+ switch (e.key) {
687
+ case "ArrowDown":
688
+ e.preventDefault();
689
+ return Math.min(idx + 1, len - 1);
690
+ case "ArrowUp":
691
+ e.preventDefault();
692
+ return Math.max(idx - 1, -1);
693
+ case "Enter":
694
+ e.preventDefault();
695
+ if (idx >= 0) onSelect(idx);
696
+ return;
697
+ case "Escape":
698
+ onClose();
699
+ return;
700
+ }
701
+ };
702
+ const pipelineStepClass = (done, active) => done ? "pipeline-step done" : active ? "pipeline-step active" : "pipeline-step";
703
+ const pipelineLineClass = (done) => done ? "pipeline-line done" : "pipeline-line";
704
+ const cwdParam = (cwd) => cwd ? `&cwd=${encodeURIComponent(cwd)}` : "";
705
+ const cwdBody = (cwd) => cwd ? { cwd } : {};
706
+ const EndClient = () => {
707
+ const [s, d] = useReducer(reducer, initial);
708
+ const branchSearchRef = useRef(null);
709
+ useEffect(() => {
710
+ const cwdFromQuery = new URLSearchParams(window.location.search).get("cwd");
711
+ if (cwdFromQuery) {
712
+ d({
713
+ type: "SET_CWD",
714
+ cwd: cwdFromQuery
715
+ });
716
+ d({
717
+ type: "SET_CWD_INPUT",
718
+ value: cwdFromQuery
719
+ });
720
+ }
721
+ }, []);
722
+ useEffect(() => {
723
+ if (!s.cwd) return;
724
+ d({
725
+ type: "LOAD_ERROR",
726
+ error: ""
727
+ });
728
+ fetch(`/end/api/git/status?cwd=${encodeURIComponent(s.cwd)}`).then((r) => r.json()).then((data) => {
729
+ if (data.error) d({
730
+ type: "LOAD_ERROR",
731
+ error: data.error
732
+ });
733
+ else d({
734
+ type: "LOADED",
735
+ data
736
+ });
737
+ }).catch((e) => d({
738
+ type: "LOAD_ERROR",
739
+ error: e instanceof Error ? e.message : String(e)
740
+ }));
741
+ }, [s.cwd]);
742
+ useEffect(() => {
743
+ if (!s.branchOpen) return;
744
+ const handler = (e) => {
745
+ if (!e.target.closest(".sel")) d({
746
+ type: "SET_BRANCH_OPEN",
747
+ open: false
748
+ });
749
+ };
750
+ document.addEventListener("click", handler);
751
+ return () => document.removeEventListener("click", handler);
752
+ }, [s.branchOpen]);
753
+ useEffect(() => {
754
+ if (s.branchOpen) setTimeout(() => branchSearchRef.current?.focus(), 50);
755
+ }, [s.branchOpen]);
756
+ const setCwd = async () => {
757
+ const path = s.cwdInput.trim();
758
+ if (!path) return;
759
+ try {
760
+ const data = await (await fetch("/end/api/set-cwd", {
761
+ method: "POST",
762
+ headers: { "Content-Type": "application/json" },
763
+ body: JSON.stringify({ cwd: path })
764
+ })).json();
765
+ if (data.error) d({
766
+ type: "CWD_ERROR",
767
+ error: data.error
768
+ });
769
+ else d({
770
+ type: "SET_CWD",
771
+ cwd: path
772
+ });
773
+ } catch (e) {
774
+ d({
775
+ type: "CWD_ERROR",
776
+ error: e instanceof Error ? e.message : String(e)
777
+ });
778
+ }
779
+ };
780
+ const doRebase = async () => {
781
+ d({ type: "REBASE_RUNNING" });
782
+ try {
783
+ const data = await (await fetch("/end/api/rebase", {
784
+ method: "POST",
785
+ headers: { "Content-Type": "application/json" },
786
+ body: JSON.stringify({
787
+ targetBranch: s.targetBranch,
788
+ ...cwdBody(s.cwd)
789
+ })
790
+ })).json();
791
+ if (data.error) d({
792
+ type: "REBASE_ERROR",
793
+ error: data.error
794
+ });
795
+ else if (data.conflict) d({ type: "REBASE_CONFLICT" });
796
+ else d({ type: "REBASE_SUCCESS" });
797
+ } catch (e) {
798
+ d({
799
+ type: "REBASE_ERROR",
800
+ error: e instanceof Error ? e.message : String(e)
801
+ });
802
+ }
803
+ };
804
+ const doPush = async () => {
805
+ d({ type: "PUSH_RUNNING" });
806
+ try {
807
+ const data = await (await fetch("/end/api/push", {
808
+ method: "POST",
809
+ headers: { "Content-Type": "application/json" },
810
+ body: JSON.stringify({
811
+ branch: s.currentBranch,
812
+ ...cwdBody(s.cwd)
813
+ })
814
+ })).json();
815
+ if (data.error) d({
816
+ type: "PUSH_ERROR",
817
+ error: data.error
818
+ });
819
+ else {
820
+ d({ type: "PUSH_SUCCESS" });
821
+ d({ type: "TICKETS_LOADING" });
822
+ const ticketData = await (await fetch(`/end/api/commits?base=${encodeURIComponent(s.targetBranch)}${cwdParam(s.cwd)}`)).json();
823
+ if (ticketData.error) d({
824
+ type: "TICKETS_ERROR",
825
+ error: ticketData.error
826
+ });
827
+ else {
828
+ d({
829
+ type: "TICKETS_LOADED",
830
+ keys: ticketData.ticketKeys || []
831
+ });
832
+ for (const key of ticketData.ticketKeys || []) {
833
+ d({
834
+ type: "JIRA_LOADING",
835
+ key
836
+ });
837
+ try {
838
+ const transData = await (await fetch(`/end/api/jira/transitions?key=${encodeURIComponent(key)}`)).json();
839
+ if (transData.transitions) d({
840
+ type: "JIRA_TRANSITIONS_LOADED",
841
+ key,
842
+ transitions: transData.transitions
843
+ });
844
+ } catch {
845
+ d({
846
+ type: "JIRA_TRANSITION_ERROR",
847
+ key,
848
+ error: "Failed"
849
+ });
850
+ }
851
+ }
852
+ }
853
+ }
854
+ } catch (e) {
855
+ d({
856
+ type: "PUSH_ERROR",
857
+ error: e instanceof Error ? e.message : String(e)
858
+ });
859
+ }
860
+ };
861
+ const doCreateMR = async () => {
862
+ d({ type: "MR_RUNNING" });
863
+ try {
864
+ const data = await (await fetch("/end/api/create-mr", {
865
+ method: "POST",
866
+ headers: { "Content-Type": "application/json" },
867
+ body: JSON.stringify({
868
+ currentBranch: s.currentBranch,
869
+ targetBranch: s.targetBranch,
870
+ ticketKeys: s.ticketKeys,
871
+ ...cwdBody(s.cwd)
872
+ })
873
+ })).json();
874
+ if (data.error) d({
875
+ type: "MR_ERROR",
876
+ error: data.error
877
+ });
878
+ else {
879
+ d({
880
+ type: "MR_SUCCESS",
881
+ url: data.mrUrl
882
+ });
883
+ if (data.mrUrl) for (const key of s.ticketKeys) try {
884
+ await fetch("/end/api/jira/comment", {
885
+ method: "POST",
886
+ headers: { "Content-Type": "application/json" },
887
+ body: JSON.stringify({
888
+ key,
889
+ body: `提交问题 ${key} [代码|${data.mrUrl}]`
890
+ })
891
+ });
892
+ } catch {}
893
+ }
894
+ } catch (e) {
895
+ d({
896
+ type: "MR_ERROR",
897
+ error: e instanceof Error ? e.message : String(e)
898
+ });
899
+ }
900
+ };
901
+ const doTransition = async (key, transitionId) => {
902
+ d({
903
+ type: "JIRA_LOADING",
904
+ key
905
+ });
906
+ try {
907
+ const data = await (await fetch("/end/api/jira/transition", {
908
+ method: "POST",
909
+ headers: { "Content-Type": "application/json" },
910
+ body: JSON.stringify({
911
+ key,
912
+ transitionId
913
+ })
914
+ })).json();
915
+ if (data.error) d({
916
+ type: "JIRA_TRANSITION_ERROR",
917
+ key,
918
+ error: data.error
919
+ });
920
+ else {
921
+ const trans = s.jiraTransitions[key]?.find((tr) => tr.id === transitionId);
922
+ d({
923
+ type: "JIRA_TRANSITION_SUCCESS",
924
+ key,
925
+ name: trans?.name ?? "Done"
926
+ });
927
+ }
928
+ } catch (e) {
929
+ d({
930
+ type: "JIRA_TRANSITION_ERROR",
931
+ key,
932
+ error: e instanceof Error ? e.message : String(e)
933
+ });
934
+ }
935
+ };
936
+ const copyMrUrl = async () => {
937
+ try {
938
+ await navigator.clipboard.writeText(s.mrUrl);
939
+ d({ type: "COPIED" });
940
+ setTimeout(() => d({ type: "COPIED" }), 2e3);
941
+ } catch {}
942
+ };
943
+ const step1Done = !!s.targetBranch;
944
+ const step1Active = !s.loading && !s.error && !step1Done;
945
+ const step2Done = s.rebaseStatus === "success";
946
+ const step2Active = step1Done && s.rebaseStatus === "idle";
947
+ const step3Done = s.pushStatus === "success";
948
+ const step3Active = step2Done && s.pushStatus === "idle";
949
+ const step4Done = !s.ticketsLoading && s.ticketKeys.length > 0;
950
+ const step4Active = step3Done && s.ticketsLoading;
951
+ const step5Done = s.mrStatus === "success" || s.mrStatus === "skipped";
952
+ const step5Active = step4Done && s.mrStatus === "idle";
953
+ const step6Done = s.ticketKeys.length > 0 && s.ticketKeys.every((k) => s.jiraStatus[k] === "success");
954
+ const step6Active = step5Done && !step6Done && s.ticketKeys.length > 0;
955
+ const allDone = s.cwd && step2Done && step3Done && step5Done;
956
+ const fb = filterByRelevance(s.localBranches.map((b) => ({ name: b })), s.branchSearch);
957
+ if (!s.cwd) return /* @__PURE__ */ jsxDEV("div", { children: [
958
+ /* @__PURE__ */ jsxDEV("style", { children: endStyle }),
959
+ /* @__PURE__ */ jsxDEV("div", {
960
+ class: "page-header",
961
+ children: [/* @__PURE__ */ jsxDEV("h2", { children: t("web.endTitle") }), /* @__PURE__ */ jsxDEV("p", { children: t("web.endDesc") })]
962
+ }),
963
+ /* @__PURE__ */ jsxDEV("div", {
964
+ class: "cwd-section",
965
+ children: [/* @__PURE__ */ jsxDEV("div", {
966
+ class: "cwd-row",
967
+ children: [/* @__PURE__ */ jsxDEV("input", {
968
+ class: "cwd-input",
969
+ type: "text",
970
+ placeholder: t("end.enterPath"),
971
+ value: s.cwdInput,
972
+ onChange: (e) => d({
973
+ type: "SET_CWD_INPUT",
974
+ value: e.target.value
975
+ }),
976
+ onKeyDown: (e) => {
977
+ if (e.key === "Enter") setCwd();
978
+ }
979
+ }), /* @__PURE__ */ jsxDEV("button", {
980
+ class: "cwd-btn",
981
+ type: "button",
982
+ disabled: !s.cwdInput.trim(),
983
+ onClick: setCwd,
984
+ children: t("end.setPath")
985
+ })]
986
+ }), s.cwdError && /* @__PURE__ */ jsxDEV("div", {
987
+ class: "cwd-error",
988
+ children: s.cwdError
989
+ })]
990
+ })
991
+ ] });
992
+ if (s.loading) return /* @__PURE__ */ jsxDEV("div", { children: [
993
+ /* @__PURE__ */ jsxDEV("style", { children: endStyle }),
994
+ /* @__PURE__ */ jsxDEV("div", {
995
+ class: "cwd-display",
996
+ children: [/* @__PURE__ */ jsxDEV("span", {
997
+ class: "cwd-display-label",
998
+ children: t("end.projectPath")
999
+ }), /* @__PURE__ */ jsxDEV("span", { children: s.cwd })]
1000
+ }),
1001
+ /* @__PURE__ */ jsxDEV("div", {
1002
+ class: "loading-row",
1003
+ children: [/* @__PURE__ */ jsxDEV("span", { class: "spinner" }), t("web.loading")]
1004
+ })
1005
+ ] });
1006
+ if (s.error) return /* @__PURE__ */ jsxDEV("div", { children: [
1007
+ /* @__PURE__ */ jsxDEV("style", { children: endStyle }),
1008
+ /* @__PURE__ */ jsxDEV("div", {
1009
+ class: "cwd-display",
1010
+ children: [/* @__PURE__ */ jsxDEV("span", {
1011
+ class: "cwd-display-label",
1012
+ children: t("end.projectPath")
1013
+ }), /* @__PURE__ */ jsxDEV("span", { children: s.cwd })]
1014
+ }),
1015
+ /* @__PURE__ */ jsxDEV("div", {
1016
+ class: "result-card result-error",
1017
+ children: /* @__PURE__ */ jsxDEV("div", {
1018
+ class: "result-text error",
1019
+ children: s.error
1020
+ })
1021
+ }),
1022
+ /* @__PURE__ */ jsxDEV("button", {
1023
+ class: "action-btn rerun",
1024
+ type: "button",
1025
+ onClick: () => d({ type: "RESET" }),
1026
+ children: t("end.rerun")
1027
+ })
1028
+ ] });
1029
+ return /* @__PURE__ */ jsxDEV("div", { children: [
1030
+ /* @__PURE__ */ jsxDEV("style", { children: endStyle }),
1031
+ /* @__PURE__ */ jsxDEV("div", {
1032
+ class: "page-header",
1033
+ children: [/* @__PURE__ */ jsxDEV("h2", { children: t("web.endTitle") }), /* @__PURE__ */ jsxDEV("p", { children: t("web.endDesc") })]
1034
+ }),
1035
+ /* @__PURE__ */ jsxDEV("div", {
1036
+ class: "cwd-display",
1037
+ children: [/* @__PURE__ */ jsxDEV("span", {
1038
+ class: "cwd-display-label",
1039
+ children: t("end.projectPath")
1040
+ }), /* @__PURE__ */ jsxDEV("span", { children: s.cwd })]
1041
+ }),
1042
+ /* @__PURE__ */ jsxDEV("div", {
1043
+ class: "pipeline",
1044
+ children: [
1045
+ /* @__PURE__ */ jsxDEV("div", {
1046
+ class: pipelineStepClass(step1Done, step1Active),
1047
+ children: [/* @__PURE__ */ jsxDEV("span", { class: "pipeline-node" }), t("end.stepBranch")]
1048
+ }),
1049
+ /* @__PURE__ */ jsxDEV("div", { class: pipelineLineClass(step1Done) }),
1050
+ /* @__PURE__ */ jsxDEV("div", {
1051
+ class: pipelineStepClass(step2Done, step2Active),
1052
+ children: [/* @__PURE__ */ jsxDEV("span", { class: "pipeline-node" }), t("end.stepRebase")]
1053
+ }),
1054
+ /* @__PURE__ */ jsxDEV("div", { class: pipelineLineClass(step2Done) }),
1055
+ /* @__PURE__ */ jsxDEV("div", {
1056
+ class: pipelineStepClass(step3Done, step3Active),
1057
+ children: [/* @__PURE__ */ jsxDEV("span", { class: "pipeline-node" }), t("end.stepPush")]
1058
+ }),
1059
+ /* @__PURE__ */ jsxDEV("div", { class: pipelineLineClass(step3Done) }),
1060
+ /* @__PURE__ */ jsxDEV("div", {
1061
+ class: pipelineStepClass(step4Done, step4Active),
1062
+ children: [/* @__PURE__ */ jsxDEV("span", { class: "pipeline-node" }), t("end.stepTickets")]
1063
+ }),
1064
+ /* @__PURE__ */ jsxDEV("div", { class: pipelineLineClass(step4Done) }),
1065
+ /* @__PURE__ */ jsxDEV("div", {
1066
+ class: pipelineStepClass(step5Done, step5Active),
1067
+ children: [/* @__PURE__ */ jsxDEV("span", { class: "pipeline-node" }), t("end.stepMR")]
1068
+ }),
1069
+ /* @__PURE__ */ jsxDEV("div", { class: pipelineLineClass(step5Done) }),
1070
+ /* @__PURE__ */ jsxDEV("div", {
1071
+ class: pipelineStepClass(step6Done, step6Active),
1072
+ children: [/* @__PURE__ */ jsxDEV("span", { class: "pipeline-node" }), t("end.stepJira")]
1073
+ })
1074
+ ]
1075
+ }),
1076
+ /* @__PURE__ */ jsxDEV("div", {
1077
+ class: "info-card",
1078
+ children: [/* @__PURE__ */ jsxDEV("span", {
1079
+ class: "info-label",
1080
+ children: t("end.currentBranch")
1081
+ }), /* @__PURE__ */ jsxDEV("span", {
1082
+ class: "info-value neon",
1083
+ children: s.currentBranch
1084
+ })]
1085
+ }),
1086
+ /* @__PURE__ */ jsxDEV("div", {
1087
+ class: "sel",
1088
+ style: `z-index:${s.branchOpen ? 100 : 1}`,
1089
+ children: [/* @__PURE__ */ jsxDEV("button", {
1090
+ class: `sel-trigger${s.branchOpen ? " open" : ""}`,
1091
+ type: "button",
1092
+ role: "combobox",
1093
+ "aria-expanded": s.branchOpen,
1094
+ "aria-haspopup": "listbox",
1095
+ onClick: () => d({
1096
+ type: "SET_BRANCH_OPEN",
1097
+ open: !s.branchOpen
1098
+ }),
1099
+ children: [
1100
+ /* @__PURE__ */ jsxDEV("span", {
1101
+ class: "sel-trigger-label",
1102
+ children: t("end.targetBranch")
1103
+ }),
1104
+ /* @__PURE__ */ jsxDEV("span", {
1105
+ class: `sel-trigger-value${s.targetBranch ? "" : " empty"}`,
1106
+ children: s.targetBranch ? s.detectedSource && s.targetBranch === s.detectedSource ? `${s.targetBranch} (${t("end.detectedSource")})` : s.targetBranch : t("end.selectBranch")
1107
+ }),
1108
+ /* @__PURE__ */ jsxDEV("span", {
1109
+ class: "sel-trigger-arrow",
1110
+ children: "▼"
1111
+ })
1112
+ ]
1113
+ }), s.branchOpen && /* @__PURE__ */ jsxDEV("div", {
1114
+ class: "sel-dropdown",
1115
+ role: "listbox",
1116
+ "aria-label": t("end.selectBranch"),
1117
+ children: [/* @__PURE__ */ jsxDEV("div", {
1118
+ class: "sel-search",
1119
+ children: /* @__PURE__ */ jsxDEV("input", {
1120
+ ref: branchSearchRef,
1121
+ class: "sel-search-input",
1122
+ type: "text",
1123
+ placeholder: t("end.selectBranch"),
1124
+ value: s.branchSearch,
1125
+ onChange: (e) => d({
1126
+ type: "SET_BRANCH_SEARCH",
1127
+ search: e.target.value
1128
+ }),
1129
+ onKeyDown: (e) => {
1130
+ const n = selKeyDown(e, s.branchOpen, fb.length, s.branchIndex, (i) => {
1131
+ const b = fb[i];
1132
+ if (b) d({
1133
+ type: "SELECT_TARGET_BRANCH",
1134
+ branch: b.name
1135
+ });
1136
+ }, () => d({
1137
+ type: "SET_BRANCH_OPEN",
1138
+ open: false
1139
+ }));
1140
+ if (n !== void 0) d({
1141
+ type: "SET_BRANCH_INDEX",
1142
+ index: n
1143
+ });
1144
+ }
1145
+ })
1146
+ }), fb.length > 0 ? fb.map((b, i) => /* @__PURE__ */ jsxDEV("div", {
1147
+ class: `sel-item${b.name === s.targetBranch ? " active" : ""}${i === s.branchIndex ? " highlighted" : ""}`,
1148
+ onMouseEnter: () => d({
1149
+ type: "SET_BRANCH_INDEX",
1150
+ index: i
1151
+ }),
1152
+ onClick: () => d({
1153
+ type: "SELECT_TARGET_BRANCH",
1154
+ branch: b.name
1155
+ }),
1156
+ children: /* @__PURE__ */ jsxDEV("span", {
1157
+ class: "sel-item-name",
1158
+ children: b.name
1159
+ })
1160
+ })) : /* @__PURE__ */ jsxDEV("div", {
1161
+ class: "sel-empty",
1162
+ children: t("end.selectBranch")
1163
+ })]
1164
+ })]
1165
+ }),
1166
+ s.rebaseStatus === "idle" && s.targetBranch && /* @__PURE__ */ jsxDEV("button", {
1167
+ class: "action-btn",
1168
+ type: "button",
1169
+ onClick: doRebase,
1170
+ children: [
1171
+ t("end.rebaseBtn"),
1172
+ " → ",
1173
+ s.targetBranch
1174
+ ]
1175
+ }),
1176
+ s.rebaseStatus === "running" && /* @__PURE__ */ jsxDEV("div", {
1177
+ class: "loading-row",
1178
+ children: [
1179
+ /* @__PURE__ */ jsxDEV("span", { class: "spinner" }),
1180
+ t("end.rebasing"),
1181
+ " ",
1182
+ s.targetBranch,
1183
+ "..."
1184
+ ]
1185
+ }),
1186
+ s.rebaseStatus === "success" && /* @__PURE__ */ jsxDEV("div", {
1187
+ class: "result-card result-success",
1188
+ children: /* @__PURE__ */ jsxDEV("div", {
1189
+ class: "result-text success",
1190
+ children: [
1191
+ t("end.rebaseResult"),
1192
+ ": ",
1193
+ s.targetBranch
1194
+ ]
1195
+ })
1196
+ }),
1197
+ s.rebaseStatus === "conflict" && /* @__PURE__ */ jsxDEV("div", {
1198
+ class: "warning-card",
1199
+ children: t("end.conflictWarning")
1200
+ }),
1201
+ s.rebaseStatus === "error" && /* @__PURE__ */ jsxDEV("div", {
1202
+ class: "result-card result-error",
1203
+ children: /* @__PURE__ */ jsxDEV("div", {
1204
+ class: "result-text error",
1205
+ children: s.rebaseError
1206
+ })
1207
+ }),
1208
+ s.rebaseStatus === "success" && s.pushStatus === "idle" && /* @__PURE__ */ jsxDEV("button", {
1209
+ class: "action-btn",
1210
+ type: "button",
1211
+ onClick: doPush,
1212
+ children: [
1213
+ t("end.pushBtn"),
1214
+ " ",
1215
+ s.currentBranch
1216
+ ]
1217
+ }),
1218
+ s.pushStatus === "running" && /* @__PURE__ */ jsxDEV("div", {
1219
+ class: "loading-row",
1220
+ children: [
1221
+ /* @__PURE__ */ jsxDEV("span", { class: "spinner" }),
1222
+ t("end.pushing"),
1223
+ "..."
1224
+ ]
1225
+ }),
1226
+ s.pushStatus === "success" && /* @__PURE__ */ jsxDEV("div", {
1227
+ class: "result-card result-success",
1228
+ children: /* @__PURE__ */ jsxDEV("div", {
1229
+ class: "result-text success",
1230
+ children: [
1231
+ t("end.pushResult"),
1232
+ ": ",
1233
+ s.currentBranch
1234
+ ]
1235
+ })
1236
+ }),
1237
+ s.pushStatus === "error" && /* @__PURE__ */ jsxDEV("div", {
1238
+ class: "result-card result-error",
1239
+ children: /* @__PURE__ */ jsxDEV("div", {
1240
+ class: "result-text error",
1241
+ children: s.pushError
1242
+ })
1243
+ }),
1244
+ s.ticketsLoading && /* @__PURE__ */ jsxDEV("div", {
1245
+ class: "loading-row",
1246
+ children: [/* @__PURE__ */ jsxDEV("span", { class: "spinner" }), t("end.analyzingCommits")]
1247
+ }),
1248
+ s.pushStatus === "success" && !s.ticketsLoading && /* @__PURE__ */ jsxDEV("div", {
1249
+ class: "result-card",
1250
+ children: [/* @__PURE__ */ jsxDEV("div", {
1251
+ class: "result-label",
1252
+ children: t("end.ticketKeys")
1253
+ }), s.ticketKeys.length > 0 ? s.ticketKeys.map((key) => /* @__PURE__ */ jsxDEV("span", {
1254
+ class: "result-badge",
1255
+ style: "margin-right:6px",
1256
+ children: key
1257
+ })) : t("end.noTickets")]
1258
+ }),
1259
+ s.ticketsError && /* @__PURE__ */ jsxDEV("div", {
1260
+ class: "result-card result-error",
1261
+ children: /* @__PURE__ */ jsxDEV("div", {
1262
+ class: "result-text error",
1263
+ children: s.ticketsError
1264
+ })
1265
+ }),
1266
+ s.pushStatus === "success" && !s.ticketsLoading && s.mrStatus === "idle" && /* @__PURE__ */ jsxDEV("div", {
1267
+ style: "display:flex;gap:8px",
1268
+ children: [/* @__PURE__ */ jsxDEV("button", {
1269
+ class: "action-btn",
1270
+ type: "button",
1271
+ onClick: doCreateMR,
1272
+ children: t("end.createMrBtn")
1273
+ }), /* @__PURE__ */ jsxDEV("button", {
1274
+ class: "action-btn secondary",
1275
+ type: "button",
1276
+ onClick: () => d({ type: "MR_SKIPPED" }),
1277
+ children: t("end.skipMr")
1278
+ })]
1279
+ }),
1280
+ s.mrStatus === "running" && /* @__PURE__ */ jsxDEV("div", {
1281
+ class: "loading-row",
1282
+ children: [/* @__PURE__ */ jsxDEV("span", { class: "spinner" }), t("end.creatingMR")]
1283
+ }),
1284
+ s.mrStatus === "success" && s.mrUrl && /* @__PURE__ */ jsxDEV("div", {
1285
+ class: "result-card result-success",
1286
+ children: [/* @__PURE__ */ jsxDEV("div", {
1287
+ class: "result-text success",
1288
+ children: t("end.mrCreated")
1289
+ }), /* @__PURE__ */ jsxDEV("div", {
1290
+ class: "mr-url-row",
1291
+ children: [
1292
+ /* @__PURE__ */ jsxDEV("input", {
1293
+ class: "mr-url-input",
1294
+ type: "text",
1295
+ readOnly: true,
1296
+ value: s.mrUrl
1297
+ }),
1298
+ /* @__PURE__ */ jsxDEV("a", {
1299
+ class: "result-key",
1300
+ href: s.mrUrl,
1301
+ target: "_blank",
1302
+ rel: "noreferrer",
1303
+ style: "font-size:12px;padding:8px 12px;border-radius:6px",
1304
+ children: t("end.mrUrl")
1305
+ }),
1306
+ /* @__PURE__ */ jsxDEV("button", {
1307
+ class: `copy-btn${s.copied ? " copied" : ""}`,
1308
+ type: "button",
1309
+ onClick: copyMrUrl,
1310
+ children: s.copied ? t("end.copied") : t("end.copy")
1311
+ })
1312
+ ]
1313
+ })]
1314
+ }),
1315
+ s.mrStatus === "error" && /* @__PURE__ */ jsxDEV("div", {
1316
+ class: "result-card result-error",
1317
+ children: /* @__PURE__ */ jsxDEV("div", {
1318
+ class: "result-text error",
1319
+ children: s.mrError
1320
+ })
1321
+ }),
1322
+ s.mrStatus === "skipped" && /* @__PURE__ */ jsxDEV("div", {
1323
+ class: "result-card",
1324
+ children: /* @__PURE__ */ jsxDEV("div", {
1325
+ class: "result-label",
1326
+ children: [
1327
+ t("end.manualMR"),
1328
+ " ",
1329
+ s.targetBranch
1330
+ ]
1331
+ })
1332
+ }),
1333
+ (s.mrStatus === "success" || s.mrStatus === "skipped") && s.ticketKeys.length > 0 && /* @__PURE__ */ jsxDEV("div", {
1334
+ class: "ticket-list",
1335
+ children: s.ticketKeys.map((key) => /* @__PURE__ */ jsxDEV("div", {
1336
+ class: "ticket-item",
1337
+ children: [/* @__PURE__ */ jsxDEV("div", {
1338
+ style: "flex:1",
1339
+ children: [
1340
+ /* @__PURE__ */ jsxDEV("a", {
1341
+ class: "ticket-key",
1342
+ href: `#/browse/${key}`,
1343
+ target: "_blank",
1344
+ rel: "noreferrer",
1345
+ children: key
1346
+ }),
1347
+ s.jiraResults[key] && /* @__PURE__ */ jsxDEV("span", {
1348
+ class: "ticket-status success",
1349
+ style: "margin-left:8px",
1350
+ children: ["→ ", s.jiraResults[key]]
1351
+ }),
1352
+ s.jiraErrors[key] && /* @__PURE__ */ jsxDEV("span", {
1353
+ class: "ticket-status error",
1354
+ style: "margin-left:8px",
1355
+ children: t("end.transitionFailed")
1356
+ })
1357
+ ]
1358
+ }), s.jiraStatus[key] === "success" ? /* @__PURE__ */ jsxDEV("span", {
1359
+ class: "result-badge",
1360
+ children: t("end.transitionSuccess")
1361
+ }) : s.jiraStatus[key] === "loading" ? /* @__PURE__ */ jsxDEV("span", { class: "spinner" }) : s.jiraTransitions[key]?.length > 0 && /* @__PURE__ */ jsxDEV("div", {
1362
+ class: "ticket-transitions",
1363
+ children: [s.jiraTransitions[key].filter((tr) => tr.name === "完成" || tr.name === "Done" || tr.name.toLowerCase().includes("done")).slice(0, 1).map((tr) => /* @__PURE__ */ jsxDEV("button", {
1364
+ class: "trans-btn primary",
1365
+ type: "button",
1366
+ onClick: () => doTransition(key, tr.id),
1367
+ disabled: s.jiraStatus[key] === "loading",
1368
+ children: tr.name
1369
+ })), s.jiraTransitions[key].filter((tr) => tr.name !== "完成" && tr.name !== "Done" && !tr.name.toLowerCase().includes("done")).slice(0, 3).map((tr) => /* @__PURE__ */ jsxDEV("button", {
1370
+ class: "trans-btn",
1371
+ type: "button",
1372
+ onClick: () => doTransition(key, tr.id),
1373
+ disabled: s.jiraStatus[key] === "loading",
1374
+ children: tr.name
1375
+ }))]
1376
+ })]
1377
+ }))
1378
+ }),
1379
+ allDone && /* @__PURE__ */ jsxDEV("div", {
1380
+ class: "result-card result-success",
1381
+ children: /* @__PURE__ */ jsxDEV("div", {
1382
+ class: "result-text success",
1383
+ children: t("end.done")
1384
+ })
1385
+ }),
1386
+ allDone && /* @__PURE__ */ jsxDEV("button", {
1387
+ class: "action-btn rerun",
1388
+ type: "button",
1389
+ onClick: () => d({ type: "RESET" }),
1390
+ children: t("end.rerun")
1391
+ })
1392
+ ] });
1393
+ };
1394
+ const mount = async (el) => {
1395
+ await initPromise;
1396
+ render(/* @__PURE__ */ jsxDEV(EndClient, {}), el);
1397
+ };
1398
+ //#endregion
1399
+ export { mount };