+24
appview/db/repos.go
+24
appview/db/repos.go
···
22
22
Created time.Time
23
23
Description string
24
24
Spindle string
25
+
Labels []string
25
26
26
27
// optionally, populate this when querying for reverse mappings
27
28
RepoStats *RepoStats
···
155
156
for _, r := range repoMap {
156
157
args[i] = r.RepoAt()
157
158
i++
159
+
}
160
+
161
+
// Get labels for all repos
162
+
labelsQuery := fmt.Sprintf(
163
+
`select repo_at, label_at from repo_labels where repo_at in (%s)`,
164
+
inClause,
165
+
)
166
+
rows, err = e.Query(labelsQuery, args...)
167
+
if err != nil {
168
+
return nil, fmt.Errorf("failed to execute labels query: %w ", err)
169
+
}
170
+
for rows.Next() {
171
+
var repoat, labelat string
172
+
if err := rows.Scan(&repoat, &labelat); err != nil {
173
+
log.Println("err", "err", err)
174
+
continue
175
+
}
176
+
if r, ok := repoMap[syntax.ATURI(repoat)]; ok {
177
+
r.Labels = append(r.Labels, labelat)
178
+
}
179
+
}
180
+
if err = rows.Err(); err != nil {
181
+
return nil, fmt.Errorf("failed to execute labels query: %w ", err)
158
182
}
159
183
160
184
languageQuery := fmt.Sprintf(
+1
appview/pages/pages.go
+1
appview/pages/pages.go
+28
appview/pages/templates/repo/settings/fragments/labelListing.html
+28
appview/pages/templates/repo/settings/fragments/labelListing.html
···
1
+
{{ define "repo/settings/fragments/labelListing" }}
2
+
{{ $root := index . 0 }}
3
+
{{ $label := index . 1 }}
4
+
<div id="label-{{$label.Id}}" class="flex items-center justify-between p-2 pl-4">
5
+
<div class="flex flex-col gap-1 text-sm min-w-0 max-w-[80%]">
6
+
{{ template "labels/fragments/labelDef" $label }}
7
+
<div class="flex flex-wrap text items-center gap-1 text-gray-500 dark:text-gray-400">
8
+
{{ $label.ValueType.Type }}
9
+
{{ if $label.ValueType.IsEnumType }}
10
+
<span class="before:content-['·'] before:select-none"></span>
11
+
{{ join $label.ValueType.Enum ", " }}
12
+
{{ end }}
13
+
</div>
14
+
</div>
15
+
<button
16
+
class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 gap-2 group"
17
+
title="Delete label"
18
+
hx-delete="/{{ $root.RepoInfo.FullName }}/settings/label"
19
+
hx-swap="none"
20
+
hx-vals='{"label-id": "{{ $label.Id }}"}'
21
+
hx-confirm="Are you sure you want to delete the label `{{ $label.Name }}`?"
22
+
>
23
+
{{ i "trash-2" "w-5 h-5" }}
24
+
<span class="hidden md:inline">delete</span>
25
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
26
+
</button>
27
+
</div>
28
+
{{ end }}
+42
appview/pages/templates/repo/settings/general.html
+42
appview/pages/templates/repo/settings/general.html
···
7
7
</div>
8
8
<div class="col-span-1 md:col-span-3 flex flex-col gap-6 p-2">
9
9
{{ template "branchSettings" . }}
10
+
{{ template "labelSettings" . }}
10
11
{{ template "deleteRepo" . }}
11
12
<div id="operation-error" class="text-red-500 dark:text-red-400"></div>
12
13
</div>
···
42
43
</div>
43
44
{{ end }}
44
45
46
+
{{ define "labelSettings" }}
47
+
<div class="flex flex-col gap-2">
48
+
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 items-center">
49
+
<div class="col-span-1 md:col-span-2">
50
+
<h2 class="text-sm pb-2 uppercase font-bold">Labels</h2>
51
+
<p class="text-gray-500 dark:text-gray-400">
52
+
Manage your issues and pulls by creating labels to categorize them.
53
+
Only repository owners may configure labels.
54
+
</p>
55
+
</div>
56
+
<div class="col-span-1 md:col-span-1 md:justify-self-end">
57
+
<button
58
+
class="btn flex items-center gap-2"
59
+
popovertarget="add-labeldef-modal"
60
+
{{ if not (or .RepoInfo.Roles.IsOwner .RepoInfo.Roles.IsCollaborator) }}disabled{{ end }}
61
+
popovertargetaction="toggle">
62
+
{{ i "plus" "size-4" }}
63
+
add label
64
+
</button>
65
+
<div
66
+
id="add-labeldef-modal"
67
+
popover
68
+
class="bg-white w-full sm:w-96 dark:bg-gray-800 p-6 rounded border border-gray-200 dark:border-gray-700 drop-shadow dark:text-white backdrop:bg-gray-400/50 dark:backdrop:bg-gray-800/50">
69
+
{{ template "repo/settings/fragments/addLabelDefModal" . }}
70
+
</div>
71
+
</div>
72
+
</div>
73
+
<div class="flex flex-col rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700 w-full">
74
+
{{ range .Labels }}
75
+
{{ template "repo/settings/fragments/labelListing" (list $ .) }}
76
+
{{ else }}
77
+
<div class="flex items-center justify-center p-2 text-gray-500">
78
+
no labels added yet
79
+
</div>
80
+
{{ end }}
81
+
</div>
82
+
<div id="label-operation" class="error"></div>
83
+
</div>
84
+
{{ end }}
85
+
45
86
{{ define "deleteRepo" }}
46
87
{{ if .RepoInfo.Roles.RepoDeleteAllowed }}
47
88
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 items-center">
···
68
109
</div>
69
110
{{ end }}
70
111
{{ end }}
112
+
+8
appview/repo/repo.go
+8
appview/repo/repo.go
···
1391
1391
return
1392
1392
}
1393
1393
1394
+
labels, err := db.GetLabelDefinitions(rp.db, db.FilterIn("at_uri", f.Repo.Labels))
1395
+
if err != nil {
1396
+
log.Println("failed to fetch labels", err)
1397
+
rp.pages.Error503(w)
1398
+
return
1399
+
}
1400
+
1394
1401
rp.pages.RepoGeneralSettings(w, pages.RepoGeneralSettingsParams{
1395
1402
LoggedInUser: user,
1396
1403
RepoInfo: f.RepoInfo(user),
1397
1404
Branches: result.Branches,
1405
+
Labels: labels,
1398
1406
Tabs: settingsTabs,
1399
1407
Tab: "general",
1400
1408
})