╭ changed ─────────────╮ │src/ui/Repo/Issues.zig│ ╰──────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────╮ │← previous│ ╰──────────╯ ╭────────────────────────────────────────────────────────────────────────────────╮ │216 const rooted = empty.selected_id.len != 0; │ │217 - const tagged = empty.tag.len != 0; │ │218 - // an explicitly named issue or tag that doesn't exist is a bad url │ │217 + const labeled = empty.label.len != 0; │ │218 + // an explicitly named issue or label that doesn't exist is a bad url │ │219 // (NotFound -> 404); the bare route falls through to an empty listing.│ │220 - const strict = rooted or tagged; │ │220 + const strict = rooted or labeled; │ │221 │ │222 // a repo with no consumed events has no moment yet. │ │223 const gpa = arena.child_allocator; │ ╰────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │233 return empty; │ │234 }; │ │235 │ │236 - // the sorted sets to window, per status: the tag's sets when filtered, │ │236 + // the sorted sets to window, per status: the label's sets when filtered,│ │237 // else the top-level per-status sets. a missing set is an empty window. │ │238 var open_set: ?DB.SortedSet(.read_only) = null; │ │239 var closed_set: ?DB.SortedSet(.read_only) = null; │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │240 - if (tagged) { │ │241 - const tag_to_issues_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, evt.Issue.tag_status_to_id_set_key)) orelse return error.NotFound; │ │242 - const tag_to_issues = try DB.SortedMap(.read_only).init(tag_to_issues_cursor); │ │243 - const decoded = std.Uri.percentDecodeInPlace(try aa.dupe(u8, empty.tag)); │ │244 - open_set = try thread.tagStatusSet(Self, DB, tag_to_issues, decoded, .open); │ │245 - closed_set = try thread.tagStatusSet(Self, DB, tag_to_issues, decoded, .closed); │ │246 - // a tag no issue carries is a bad url │ │240 + if (labeled) { │ │241 + const label_to_issues_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, evt.Issue.label_status_to_id_set_key)) orelse return error.NotFound;│ │242 + const label_to_issues = try DB.SortedMap(.read_only).init(label_to_issues_cursor); │ │243 + const decoded = std.Uri.percentDecodeInPlace(try aa.dupe(u8, empty.label)); │ │244 + open_set = try thread.labelStatusSet(Self, DB, label_to_issues, decoded, .open); │ │245 + closed_set = try thread.labelStatusSet(Self, DB, label_to_issues, decoded, .closed); │ │246 + // a label no issue carries is a bad url │ │247 if (open_set == null and closed_set == null) return error.NotFound; │ │248 } else if (try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, evt.Issue.status_to_id_set_key))) |status_to_issues_cursor| { │ │249 const status_to_issues = try DB.SortedMap(.read_only).init(status_to_issues_cursor); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────╮ │286 if (!try set.contains(order_key)) return error.NotFound; │ │287 conflicts_root = order_key; │ │288 } else { │ │289 - // the named issue must be in its windowed set (a tag url can name │ │290 - // an issue that doesn't carry the tag). │ │289 + // the named issue must be in its windowed set (a label url can name│ │290 + // an issue that doesn't carry the label). │ │291 const set = (switch (issue_event.event.status) { │ │292 .open => open_set, │ │293 .closed => closed_set, │ ╰─────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │333 else │ │334 try Comment.init(repo_opts.hash, arena, admin_moment, haxy_moment, empty.selected_id, empty.comment_id, comments_start);│ │335 │ │336 - const tags = try thread.loadTags(Self, repo_opts.hash, arena, haxy_moment); │ │336 + const labels = try thread.loadLabels(Self, repo_opts.hash, arena, haxy_moment); │ │337 │ │338 return .{ │ │339 .identity = empty.identity, │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────╮ │340 - .tag = empty.tag, │ │340 + .label = empty.label, │ │341 .search = empty.search, │ │342 .selected_id = empty.selected_id,│ │343 .comment_id = empty.comment_id, │ ╰──────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────╮ │350 .theirs_picks = empty.theirs_picks, │ │351 .view = resolved_view, │ │352 .description_page = empty.description_page,│ │353 - .tags = tags, │ │353 + .labels = labels, │ │354 }; │ │355 } │ │356 │ ╰────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────╮ │362 │ │363 const open_tab_label = "open"; │ │364 const closed_tab_label = "closed";│ │365 -const tags_tab_label = "tags"; │ │365 +const labels_tab_label = "labels";│ │366 const edit_tab_label = "edit"; │ │367 const reply_tab_label = "reply"; │ │368 const remove_tab_label = "remove";│ ╰───────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │381 // a list tab per status, labeled with its listing's issue count │ │382 const status_labels = [_][]const u8{ open_tab_label, closed_tab_label }; │ │383 for ([_]evt.Issue.Status{ .open, .closed }, status_labels, 0..) |status, status_label, index| { │ │384 - const route = try thread.searchRoute(ui.RoutablePage.repoIssuesRoute(data.identity, status, data.tag, ""), data.search); │ │384 + const route = try thread.searchRoute(ui.RoutablePage.repoIssuesRoute(data.identity, status, data.label, ""), data.search);│ │385 const link = try ui.inPageTabLink(session, route, page_selected and selected_index == index); │ │386 var label_buf: [64]u8 = undefined; │ │387 const label = try thread.countLabel(&label_buf, status_label, data.window(status).*); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │388 try header.addTab(allocator, label, link, index); │ │389 } │ │390 │ │391 - // tags tab, labeled with the active tag filter │ │391 + // labels tab, showing the active label filter │ │392 { │ │393 - const tags_route = try thread.searchRoute(ui.RoutablePage.repoThreadTagsRoute(.issue, data.identity, data.tag), data.search); │ │394 - const tags_link = try ui.inPageTabLink(session, tags_route, page_selected and selected_index == View.viewIndex(.tags)); │ │395 - const label = if (data.tag.len == 0) tags_tab_label else blk: { │ │396 - const decoded = std.Uri.percentDecodeInPlace(try aa.dupe(u8, data.tag)); │ │397 - break :blk try std.fmt.allocPrint(aa, tags_tab_label ++ " ({s})", .{decoded}); │ │393 + const labels_route = try thread.searchRoute(ui.RoutablePage.repoThreadLabelsRoute(.issue, data.identity, data.label), data.search);│ │394 + const labels_link = try ui.inPageTabLink(session, labels_route, page_selected and selected_index == View.viewIndex(.labels)); │ │395 + const label = if (data.label.len == 0) labels_tab_label else blk: { │ │396 + const decoded = std.Uri.percentDecodeInPlace(try aa.dupe(u8, data.label)); │ │397 + break :blk try std.fmt.allocPrint(aa, labels_tab_label ++ " ({s})", .{decoded}); │ │398 }; │ │399 - try header.addTab(allocator, label, tags_link, View.viewIndex(.tags)); │ │399 + try header.addTab(allocator, label, labels_link, View.viewIndex(.labels)); │ │400 } │ │401 │ │402 // new-issue tab; an edit or resolve url shows its tab in this place │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯