-1
appview/pages/pages.go
-1
appview/pages/pages.go
+17
-32
appview/pages/templates/fragments/pullCompareBranches.html
+17
-32
appview/pages/templates/fragments/pullCompareBranches.html
···
1
1
{{ define "fragments/pullCompareBranches" }}
2
-
3
-
<div id="patch-upload">
4
-
<label for="targetBranch" class="dark:text-white">configure branches</label>
5
-
<div class="flex flex-wrap gap-2 items-center">
6
-
<select
7
-
required
8
-
name="targetBranch"
9
-
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
2
+
<div id="patch-upload">
3
+
<label for="targetBranch" class="dark:text-white"
4
+
>select a branch</label
10
5
>
11
-
<option disabled selected>target branch</option>
12
-
{{ range .Branches }}
13
-
<option value="{{ .Reference.Name }}" class="py-1">
14
-
{{ .Reference.Name }}
15
-
</option>
16
-
{{ end }}
17
-
</select>
18
-
19
-
{{ i "move-left" "w-5 h-5" }}
20
-
21
-
<select
22
-
name="sourceBranch"
23
-
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
24
-
>
25
-
<option disabled selected>source branch</option>
26
-
{{ range .Branches }}
27
-
<option value="{{ .Reference.Name }}" class="py-1">
28
-
{{ .Reference.Name }}
29
-
</option>
30
-
{{ end }}
31
-
</select>
32
-
</div>
33
-
34
-
</div>
6
+
<div class="flex flex-wrap gap-2 items-center">
7
+
<select
8
+
name="sourceBranch"
9
+
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
10
+
>
11
+
<option disabled selected>source branch</option>
12
+
{{ range .Branches }}
13
+
<option value="{{ .Reference.Name }}" class="py-1">
14
+
{{ .Reference.Name }}
15
+
</option>
16
+
{{ end }}
17
+
</select>
18
+
</div>
19
+
</div>
35
20
{{ end }}
+32
-25
appview/pages/templates/fragments/pullCompareForks.html
+32
-25
appview/pages/templates/fragments/pullCompareForks.html
···
3
3
<label for="forkSelect" class="dark:text-white"
4
4
>select a fork to compare</label
5
5
>
6
-
<div class="flex flex-wrap gap-2 items-center mb-4">
7
-
<select
8
-
id="forkSelect"
9
-
name="fork"
10
-
required
11
-
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
12
-
hx-get="/{{ $.RepoInfo.FullName }}/pulls/new/fork-branches"
13
-
hx-target="#branch-selection"
14
-
hx-vals='{"fork": this.value}'
15
-
hx-swap="innerHTML"
16
-
onchange="document.getElementById('hiddenForkInput').value = this.value;"
17
-
>
18
-
<option disabled selected>select a fork</option>
19
-
{{ range .Forks }}
20
-
<option value="{{ .Name }}" class="py-1">
21
-
{{ .Name }}
22
-
</option>
23
-
{{ end }}
24
-
</select>
25
-
26
-
<input type="hidden" id="hiddenForkInput" name="fork" value="">
27
-
</div>
6
+
<div class="flex flex-wrap gap-4 items-center mb-4">
7
+
<div class="flex flex-wrap gap-2 items-center">
8
+
<select
9
+
id="forkSelect"
10
+
name="fork"
11
+
required
12
+
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
13
+
hx-get="/{{ $.RepoInfo.FullName }}/pulls/new/fork-branches"
14
+
hx-target="#branch-selection"
15
+
hx-vals='{"fork": this.value}'
16
+
hx-swap="innerHTML"
17
+
onchange="document.getElementById('hiddenForkInput').value = this.value;"
18
+
>
19
+
<option disabled selected>select a fork</option>
20
+
{{ range .Forks }}
21
+
<option value="{{ .Name }}" class="py-1">
22
+
{{ .Name }}
23
+
</option>
24
+
{{ end }}
25
+
</select>
26
+
27
+
<input
28
+
type="hidden"
29
+
id="hiddenForkInput"
30
+
name="fork"
31
+
value=""
32
+
/>
33
+
</div>
28
34
29
-
<div id="branch-selection" class="mt-2">
30
-
<div class="text-sm text-gray-500 dark:text-gray-400">
31
-
Select a fork first to view available branches
35
+
<div id="branch-selection">
36
+
<div class="text-sm text-gray-500 dark:text-gray-400">
37
+
Select a fork first to view available branches
38
+
</div>
32
39
</div>
33
40
</div>
34
41
</div>
-16
appview/pages/templates/fragments/pullCompareForksBranches.html
-16
appview/pages/templates/fragments/pullCompareForksBranches.html
···
1
1
{{ define "fragments/pullCompareForksBranches" }}
2
2
<div class="flex flex-wrap gap-2 items-center">
3
3
<select
4
-
required
5
-
name="targetBranch"
6
-
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
7
-
>
8
-
<option disabled selected>target branch</option>
9
-
{{ range .TargetBranches }}
10
-
<option value="{{ .Reference.Name }}" class="py-1">
11
-
{{ .Reference.Name }}
12
-
</option>
13
-
{{ end }}
14
-
</select>
15
-
16
-
{{ i "move-left" "w-5 h-5" }}
17
-
18
-
19
-
<select
20
4
name="sourceBranch"
21
5
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
22
6
>
+30
-5
appview/pages/templates/repo/pulls/new.html
+30
-5
appview/pages/templates/repo/pulls/new.html
···
36
36
</div>
37
37
38
38
39
-
<label>choose your pull strategy</label>
40
-
<nav class="flex space-x-4">
39
+
<label>configure your pull request</label>
40
+
41
+
<p>First, choose a target branch on {{ .RepoInfo.FullName }}.</p>
42
+
<div class="pb-2">
43
+
<select
44
+
required
45
+
name="targetBranch"
46
+
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
47
+
>
48
+
<option disabled selected>target branch</option>
49
+
{{ range .Branches }}
50
+
<option value="{{ .Reference.Name }}" class="py-1">
51
+
{{ .Reference.Name }}
52
+
</option>
53
+
{{ end }}
54
+
</select>
55
+
</div>
56
+
57
+
<p>Then, choose a pull strategy.</p>
58
+
<nav class="flex space-x-4 items-end">
41
59
<button
42
60
type="button"
43
61
class="px-3 py-2 pb-2 btn"
···
49
67
</button>
50
68
51
69
{{ if .RepoInfo.Roles.IsPushAllowed }}
70
+
<span class="text-sm text-gray-500 dark:text-gray-400 pb-2">
71
+
or
72
+
</span>
52
73
<button
53
74
type="button"
54
75
class="px-3 py-2 pb-2 btn"
···
59
80
compare branches
60
81
</button>
61
82
{{ end }}
83
+
84
+
<span class="text-sm text-gray-500 dark:text-gray-400 pb-2">
85
+
or
86
+
</span>
62
87
<button
63
88
type="button"
64
89
class="px-3 py-2 pb-2 btn"
···
70
95
</button>
71
96
</nav>
72
97
73
-
<section id="patch-strategy">
98
+
<section id="patch-strategy">
74
99
{{ template "fragments/pullPatchUpload" . }}
75
100
</section>
76
101
77
-
<div class="flex justify-start items-center gap-2">
102
+
<div class="flex justify-start items-center gap-2 mt-4">
78
103
<button type="submit" class="btn flex items-center gap-2">
79
104
{{ i "git-pull-request-create" "w-4 h-4" }}
80
105
create pull
81
106
</button>
82
-
</div>
107
+
</div>
83
108
84
109
</div>
85
110
<div id="pull" class="error dark:text-red-300"></div>
+6
-1
appview/pages/templates/repo/pulls/pull.html
+6
-1
appview/pages/templates/repo/pulls/pull.html
···
50
50
{{ if not .Pull.IsSameRepoBranch }}
51
51
<a href="/{{ $owner }}/{{ .PullSourceRepo.Name }}" class="no-underline hover:underline">{{ $owner }}/{{ .PullSourceRepo.Name }}</a>
52
52
{{ end }}
53
+
54
+
{{ $fullRepo := .RepoInfo.FullName }}
55
+
{{ if not .Pull.IsSameRepoBranch }}
56
+
{{ $fullRepo = printf "%s/%s" $owner .PullSourceRepo.Name }}
57
+
{{ end }}
53
58
<span class="text-xs rounded bg-gray-100 dark:bg-gray-700 text-black dark:text-white font-mono px-2 mx-1/2 inline-flex items-center">
54
-
<a href="/{{ $owner }}/{{ .PullSourceRepo.Name }}/tree/{{ .Pull.PullSource.Branch }}" class="no-underline hover:underline">{{ .Pull.PullSource.Branch }}</a>
59
+
<a href="/{{ $fullRepo }}/tree/{{ .Pull.PullSource.Branch }}" class="no-underline hover:underline">{{ .Pull.PullSource.Branch }}</a>
55
60
</span>
56
61
</span>
57
62
{{ end }}
+14
-16
appview/state/pull.go
+14
-16
appview/state/pull.go
···
501
501
return
502
502
}
503
503
504
-
forks, err := db.GetForksByDid(s.db, user.Did)
505
-
if err != nil {
506
-
log.Println("failed to get forks", err)
507
-
return
508
-
}
509
-
510
504
switch r.Method {
511
505
case http.MethodGet:
512
506
us, err := NewUnsignedClient(f.Knot, s.config.Dev)
···
538
532
s.pages.RepoNewPull(w, pages.RepoNewPullParams{
539
533
LoggedInUser: user,
540
534
RepoInfo: f.RepoInfo(s, user),
541
-
Forks: forks,
542
535
Branches: result.Branches,
543
536
})
544
537
case http.MethodPost:
···
549
542
sourceBranch := r.FormValue("sourceBranch")
550
543
patch := r.FormValue("patch")
551
544
545
+
// Validate required fields for all PR types
546
+
if title == "" || body == "" || targetBranch == "" {
547
+
s.pages.Notice(w, "pull", "Title, body and target branch are required.")
548
+
return
549
+
}
550
+
551
+
// Determine PR type based on input parameters
552
552
isPushAllowed := f.RepoInfo(s, user).Roles.IsPushAllowed()
553
553
isBranchBased := isPushAllowed && sourceBranch != "" && fromFork == ""
554
-
isPatchBased := patch != ""
555
554
isForkBased := fromFork != "" && sourceBranch != ""
555
+
isPatchBased := patch != "" && !isBranchBased && !isForkBased
556
556
557
+
// Validate we have at least one valid PR creation method
557
558
if !isBranchBased && !isPatchBased && !isForkBased {
558
559
s.pages.Notice(w, "pull", "Neither source branch nor patch supplied.")
559
560
return
560
561
}
561
562
562
-
if isBranchBased && isPatchBased {
563
+
// Can't mix branch-based and patch-based approaches
564
+
if isBranchBased && patch != "" {
563
565
s.pages.Notice(w, "pull", "Cannot select both patch and source branch.")
564
566
return
565
567
}
566
568
567
-
if title == "" || body == "" || targetBranch == "" {
568
-
s.pages.Notice(w, "pull", "Title, body and target branch are required.")
569
-
return
570
-
}
571
-
569
+
// Handle the PR creation based on the type
572
570
if isBranchBased {
573
571
s.handleBranchBasedPull(w, r, f, user, title, body, targetBranch, sourceBranch)
572
+
} else if isForkBased {
573
+
s.handleForkBasedPull(w, r, f, user, fromFork, title, body, targetBranch, sourceBranch)
574
574
} else if isPatchBased {
575
575
s.handlePatchBasedPull(w, r, f, user, title, body, targetBranch, patch)
576
-
} else if isForkBased {
577
-
s.handleForkBasedPull(w, r, f, user, fromFork, title, body, targetBranch, sourceBranch)
578
576
}
579
577
return
580
578
}