forked from tangled.org/core
Monorepo for Tangled — https://tangled.org

appview: pull: add "relation-chain" style attachment to pulls interface

Changed files
+184 -61
appview
db
pages
templates
state
+22
appview/db/pulls.go
···
return nil
+
// all pulls above this pull (including self) in this stack
+
func (stack Stack) Above(pull *Pull) Stack {
+
position := stack.Position(pull)
+
+
if position < 0 {
+
return nil
+
}
+
+
return stack[:position+1]
+
}
+
+
// all pulls below this pull (excluding self) in this stack
+
func (stack Stack) StrictlyAbove(pull *Pull) Stack {
+
above := stack.Above(pull)
+
+
if len(above) > 0 {
+
return above[:len(above)-1]
+
}
+
+
return nil
+
}
+
// the combined format-patches of all the newest submissions in this stack
func (stack Stack) CombinedPatch() string {
// go in reverse order because the bottom of the stack is the last element in the slice
+2
appview/pages/pages.go
···
Active string
DidHandleMap map[string]string
Pull *db.Pull
+
Stack db.Stack
MergeCheck types.MergeCheckResponse
ResubmitCheck ResubmitResult
}
···
DidHandleMap map[string]string
RepoInfo repoinfo.RepoInfo
Pull *db.Pull
+
Stack db.Stack
Diff *types.NiceDiff
Round int
Submission *db.PullSubmission
+94 -57
appview/pages/templates/repo/pulls/fragments/pullHeader.html
···
{{ define "repo/pulls/fragments/pullHeader" }}
-
<header class="pb-4">
-
<h1 class="text-2xl dark:text-white">
-
{{ .Pull.Title }}
-
<span class="text-gray-500 dark:text-gray-400">#{{ .Pull.PullId }}</span>
-
</h1>
-
</header>
+
<header class="flex items-center gap-2 pb-2">
+
{{ block "pullState" .Pull }} {{ end }}
+
<h1 class="text-2xl dark:text-white">
+
<span class="text-gray-500 dark:text-gray-400">#{{ .Pull.PullId }}</span>
+
{{ .Pull.Title }}
+
</h1>
+
</header>
-
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
-
{{ $icon := "ban" }}
+
<section class="">
+
<div class="flex items-center gap-2">
+
<span class="text-gray-500 dark:text-gray-400 text-sm">
+
opened by
+
{{ $owner := index $.DidHandleMap .Pull.OwnerDid }}
+
<a href="/{{ $owner }}" class="no-underline hover:underline">{{ $owner }}</a>
+
<span class="select-none before:content-['\00B7']"></span>
+
<time>{{ .Pull.Created | timeFmt }}</time>
+
<span class="select-none before:content-['\00B7']"></span>
+
<span>
+
targeting
+
<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">
+
<a href="/{{ .RepoInfo.FullName }}/tree/{{ .Pull.TargetBranch }}" class="no-underline hover:underline">{{ .Pull.TargetBranch }}</a>
+
</span>
+
</span>
+
{{ if not .Pull.IsPatchBased }}
+
from
+
<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">
+
{{ if .Pull.IsForkBased }}
+
{{ if .Pull.PullSource.Repo }}
+
<a href="/{{ $owner }}/{{ .Pull.PullSource.Repo.Name }}" class="no-underline hover:underline">{{ $owner }}/{{ .Pull.PullSource.Repo.Name }}</a>:
+
{{- else -}}
+
<span class="italic">[deleted fork]</span>
+
{{- end -}}
+
{{- end -}}
+
{{- .Pull.PullSource.Branch -}}
+
</span>
+
{{ end }}
+
</span>
+
</div>
-
{{ if .Pull.State.IsOpen }}
-
{{ $bgColor = "bg-green-600 dark:bg-green-700" }}
-
{{ $icon = "git-pull-request" }}
-
{{ else if .Pull.State.IsMerged }}
-
{{ $bgColor = "bg-purple-600 dark:bg-purple-700" }}
-
{{ $icon = "git-merge" }}
+
{{ if .Pull.Body }}
+
<article id="body" class="mt-2 prose dark:prose-invert">
+
{{ .Pull.Body | markdown }}
+
</article>
+
{{ end }}
+
</section>
+
+
{{ end }}
+
+
{{ define "singlePullHeader" }}
+
{{ end }}
+
+
{{ define "stackedPullHeader" }}
+
<div class="border border-gray-200 dark:border-gray-700 rounded-sm">
+
{{ block "stackedPullHeaderAbove" . }} {{ end }}
+
<div class="p-2">
+
{{ block "singlePullHeader" . }} {{ end }}
+
</div>
+
{{ block "stackedPullHeaderBelow" . }} {{ end }}
+
</div>
+
{{ end }}
+
+
{{ define "stackedPullHeaderAbove" }}
+
{{ if .Pull.IsStacked }}
+
{{ $above := .Stack.StrictlyAbove .Pull }}
+
<div class="flex flex-col">
+
{{ range $pull := $above }}
+
<div class="border-b border-gray-200 dark:border-gray-700 p-2">
+
{{ block "summarizedHeader" (list $pull $) }} {{ end }}
+
</div>
+
{{ end }}
+
</div>
+
{{ end }}
{{ end }}
-
<section class="mt-2">
-
<div class="flex items-center gap-2">
-
<div
-
id="state"
-
class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }}"
-
>
-
{{ i $icon "w-4 h-4 mr-1.5 text-white" }}
-
<span class="text-white">{{ .Pull.State.String }}</span>
+
{{ define "stackedPullHeaderBelow" }}
+
{{ if .Pull.IsStacked }}
+
{{ $below := .Stack.StrictlyBelow .Pull }}
+
<div class="flex flex-col">
+
{{ range $pull := $below }}
+
<div class="border-t border-gray-200 dark:border-gray-700 p-2">
+
{{ block "summarizedHeader" (list $pull $) }} {{ end }}
</div>
-
<span class="text-gray-500 dark:text-gray-400 text-sm">
-
opened by
-
{{ $owner := index $.DidHandleMap .Pull.OwnerDid }}
-
<a href="/{{ $owner }}" class="no-underline hover:underline"
-
>{{ $owner }}</a
-
>
-
<span class="select-none before:content-['\00B7']"></span>
-
<time>{{ .Pull.Created | timeFmt }}</time>
-
<span class="select-none before:content-['\00B7']"></span>
-
<span>
-
targeting
-
<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">
-
<a href="/{{ .RepoInfo.FullName }}/tree/{{ .Pull.TargetBranch }}" class="no-underline hover:underline">{{ .Pull.TargetBranch }}</a>
-
</span>
-
</span>
-
{{ if not .Pull.IsPatchBased }}
-
from
-
<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">
-
{{ if .Pull.IsForkBased }}
-
{{ if .Pull.PullSource.Repo }}
-
<a href="/{{ $owner }}/{{ .Pull.PullSource.Repo.Name }}" class="no-underline hover:underline">{{ $owner }}/{{ .Pull.PullSource.Repo.Name }}</a>:
-
{{- else -}}
-
<span class="italic">[deleted fork]</span>
-
{{- end -}}
-
{{- end -}}
-
{{- .Pull.PullSource.Branch -}}
-
</span>
-
{{ end }}
-
</span>
+
{{ end }}
</div>
+
{{ end }}
+
{{ end }}
-
{{ if .Pull.Body }}
-
<article id="body" class="mt-8 prose dark:prose-invert">
-
{{ .Pull.Body | markdown }}
-
</article>
-
{{ end }}
-
</section>
+
{{ define "pullState" }}
+
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
+
{{ $icon := "ban" }}
+
{{ if .State.IsOpen }}
+
{{ $bgColor = "bg-green-600 dark:bg-green-700" }}
+
{{ $icon = "git-pull-request" }}
+
{{ else if .State.IsMerged }}
+
{{ $bgColor = "bg-purple-600 dark:bg-purple-700" }}
+
{{ $icon = "git-merge" }}
+
{{ end }}
+
<div id="state" class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }}" >
+
{{ i $icon "w-4 h-4 mr-1.5 text-white" }}
+
<span class="text-white ">{{ .State.String }}</span>
+
</div>
{{ end }}
+47
appview/pages/templates/repo/pulls/fragments/pullStack.html
···
+
{{ define "repo/pulls/fragments/pullStack" }}
+
<div class="grid grid-cols-1 rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700">
+
{{ range $pull := .Stack }}
+
{{ $isCurrent := false }}
+
{{ with $.Pull }}
+
{{ $isCurrent = eq $pull.PullId $.Pull.PullId }}
+
{{ end }}
+
<div class="flex gap-2 items-center p-2">
+
{{ block "summarizedHeader" (list $pull $) }} {{ end }}
+
{{ if $isCurrent }}
+
{{ i "arrow-left" "w-4 h-4" }}
+
{{ end }}
+
</div>
+
{{ end }}
+
</div>
+
{{ end }}
+
+
{{ define "summarizedHeader" }}
+
{{ $pull := index . 0 }}
+
{{ $root := index . 1 }}
+
<a href="/{{ $root.RepoInfo.FullName }}/pulls/{{ $pull.PullId }}" class="no-underline hover:no-underline">
+
<div class="flex text-sm items-center gap-2">
+
{{ block "summarizedPullState" $pull }} {{ end }}
+
<span class="dark:text-white">
+
<span class="text-gray-500 dark:text-gray-400">#{{ $pull.PullId }}</span>
+
{{ $pull.Title }}
+
</span>
+
</div>
+
</a>
+
{{ end }}
+
+
{{ define "summarizedPullState" }}
+
{{ $fgColor := "text-gray-600 dark:text-gray-300" }}
+
{{ $icon := "ban" }}
+
+
{{ if .State.IsOpen }}
+
{{ $fgColor = "text-green-600 dark:text-green-500" }}
+
{{ $icon = "git-pull-request" }}
+
{{ else if .State.IsMerged }}
+
{{ $fgColor = "text-purple-600 dark:text-purple-500" }}
+
{{ $icon = "git-merge" }}
+
{{ end }}
+
+
{{ $style := printf "w-4 h-4 %s" $fgColor }}
+
+
{{ i $icon $style }}
+
{{ end }}
+8 -1
appview/pages/templates/repo/pulls/pull.html
···
{{ define "repoContent" }}
-
{{ template "repo/pulls/fragments/pullHeader" . }}
+
{{ template "repo/pulls/fragments/pullHeader" . }}
+
+
{{ if .Pull.IsStacked }}
+
<div class="mt-8">
+
<p class="text-sm font-bold p-2 dark:text-white">STACK</p>
+
{{ template "repo/pulls/fragments/pullStack" . }}
+
</div>
+
{{ end }}
{{ end }}
{{ define "repoAfter" }}
+11 -3
appview/state/pull.go
···
RepoInfo: f.RepoInfo(s, user),
DidHandleMap: didHandleMap,
Pull: pull,
+
Stack: stack,
MergeCheck: mergeCheckResponse,
ResubmitCheck: resubmitResult,
})
···
return
}
+
stack, _ := r.Context().Value("stack").(db.Stack)
+
roundId := chi.URLParam(r, "round")
roundIdInt, err := strconv.Atoi(roundId)
if err != nil || roundIdInt >= len(pull.Submissions) {
···
DidHandleMap: didHandleMap,
RepoInfo: f.RepoInfo(s, user),
Pull: pull,
+
Stack: stack,
Round: roundIdInt,
Submission: pull.Submissions[roundIdInt],
Diff: &diff,
···
if op, ok := origById[np.ChangeId]; ok {
// pull exists in both stacks
// TODO: can we avoid reparse?
-
origFiles, _, _ := gitdiff.Parse(strings.NewReader(op.LatestPatch()))
-
newFiles, _, _ := gitdiff.Parse(strings.NewReader(np.LatestPatch()))
+
origFiles, origHeaderStr, _ := gitdiff.Parse(strings.NewReader(op.LatestPatch()))
+
newFiles, newHeaderStr, _ := gitdiff.Parse(strings.NewReader(np.LatestPatch()))
+
+
origHeader, _ := gitdiff.ParsePatchHeader(origHeaderStr)
+
newHeader, _ := gitdiff.ParsePatchHeader(newHeaderStr)
patchutil.SortPatch(newFiles)
patchutil.SortPatch(origFiles)
-
if patchutil.Equal(newFiles, origFiles) {
+
// text content of patch may be identical, but a jj rebase might have forwarded it
+
if patchutil.Equal(newFiles, origFiles) && origHeader.SHA == newHeader.SHA {
unchanged[op.ChangeId] = struct{}{}
} else {
updated[op.ChangeId] = struct{}{}