Feat: Add and Remove Labels from an MR (#159)
This MR adds the ability to add or remove labels to a merge request. These labels are visible in the summary panel and are colored the same way as they would be in the Gitlab UI. This is a MINOR release.
This commit is contained in:
committed by
GitHub
parent
67f09e559a
commit
50e06ceff6
83
lua/gitlab/actions/labels.lua
Normal file
83
lua/gitlab/actions/labels.lua
Normal file
@@ -0,0 +1,83 @@
|
||||
-- This module is responsible for the creation, deletion,
|
||||
-- and assignment and removeal of labels.
|
||||
local u = require("gitlab.utils")
|
||||
local job = require("gitlab.job")
|
||||
local state = require("gitlab.state")
|
||||
local M = {}
|
||||
|
||||
M.add_label = function()
|
||||
M.add_popup("label")
|
||||
end
|
||||
|
||||
M.delete_label = function()
|
||||
M.delete_popup("label")
|
||||
end
|
||||
|
||||
local refresh_label_state = function(labels)
|
||||
local new_labels = ""
|
||||
for _, label in ipairs(labels) do
|
||||
new_labels = new_labels .. "," .. label
|
||||
end
|
||||
state.INFO.labels = new_labels
|
||||
end
|
||||
|
||||
local get_current_labels = function()
|
||||
local label_string = state.INFO.labels
|
||||
local current_labels = {}
|
||||
for value in label_string:gmatch("[^,]+") do
|
||||
table.insert(current_labels, value)
|
||||
end
|
||||
return current_labels
|
||||
end
|
||||
|
||||
local get_all_labels = function()
|
||||
local labels = {}
|
||||
for _, label in ipairs(state.LABELS) do -- How can we use the colors??
|
||||
table.insert(labels, label.Name)
|
||||
end
|
||||
return labels
|
||||
end
|
||||
|
||||
M.add_popup = function(type)
|
||||
local all_labels = get_all_labels()
|
||||
local current_labels = get_current_labels()
|
||||
local unused_labels = u.difference(all_labels, current_labels)
|
||||
vim.ui.select(unused_labels, {
|
||||
prompt = "Choose label to add",
|
||||
}, function(choice)
|
||||
if not choice then
|
||||
return
|
||||
end
|
||||
local label_string = state.INFO.labels
|
||||
local new_labels = {}
|
||||
for value in label_string:gmatch("[^,]+") do
|
||||
table.insert(new_labels, value)
|
||||
end
|
||||
|
||||
table.insert(new_labels, choice)
|
||||
local body = { labels = new_labels }
|
||||
job.run_job("/mr/" .. type, "PUT", body, function(data)
|
||||
u.notify(data.message, vim.log.levels.INFO)
|
||||
refresh_label_state(data.labels)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
M.delete_popup = function(type)
|
||||
local current_labels = get_current_labels()
|
||||
vim.ui.select(current_labels, {
|
||||
prompt = "Choose label to delete",
|
||||
}, function(choice)
|
||||
if not choice then
|
||||
return
|
||||
end
|
||||
local filtered_labels = u.filter(current_labels, choice)
|
||||
local body = { labels = filtered_labels }
|
||||
job.run_job("/mr/" .. type, "PUT", body, function(data)
|
||||
u.notify(data.message, vim.log.levels.INFO)
|
||||
refresh_label_state(data.labels)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
return M
|
||||
@@ -89,6 +89,8 @@ M.summary = function()
|
||||
vim.api.nvim_set_option_value("readonly", false, { buf = info_popup.bufnr })
|
||||
end
|
||||
|
||||
M.color_labels(info_popup.bufnr) -- Color labels in details popup
|
||||
|
||||
state.set_popup_keymaps(
|
||||
description_popup,
|
||||
M.edit_summary,
|
||||
@@ -128,8 +130,9 @@ M.build_info_lines = function()
|
||||
assignees = { title = "Assignees", content = u.make_readable_list(info.assignees, "name") },
|
||||
reviewers = { title = "Reviewers", content = u.make_readable_list(info.reviewers, "name") },
|
||||
branch = { title = "Branch", content = info.source_branch },
|
||||
labels = { title = "Labels", content = u.make_comma_separated_readable(info.labels) },
|
||||
pipeline = {
|
||||
title = "Pipeline Status:",
|
||||
title = "Pipeline Status",
|
||||
content = function()
|
||||
return pipeline.get_pipeline_status()
|
||||
end,
|
||||
@@ -230,8 +233,25 @@ M.create_layout = function(info_lines)
|
||||
}, internal_layout)
|
||||
|
||||
layout:mount()
|
||||
|
||||
return layout, title_popup, description_popup, details_popup
|
||||
end
|
||||
|
||||
M.color_labels = function(bufnr)
|
||||
local label_namespace = vim.api.nvim_create_namespace("Labels")
|
||||
for i, v in ipairs(state.settings.info.fields) do
|
||||
if v == "labels" then
|
||||
local line_content = u.get_line_content(bufnr, i)
|
||||
vim.print(line_content)
|
||||
for j, label in ipairs(state.LABELS) do
|
||||
local start_idx, end_idx = line_content:find(label.Name)
|
||||
if start_idx ~= nil and end_idx ~= nil then
|
||||
vim.cmd("highlight " .. "label" .. j .. " guifg=white")
|
||||
vim.api.nvim_set_hl(0, ("label" .. j), { fg = label.Color })
|
||||
vim.api.nvim_buf_add_highlight(bufnr, label_namespace, ("label" .. j), i - 1, start_idx - 1, end_idx)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
@@ -11,8 +11,10 @@ local comment = require("gitlab.actions.comment")
|
||||
local pipeline = require("gitlab.actions.pipeline")
|
||||
local create_mr = require("gitlab.actions.create_mr")
|
||||
local approvals = require("gitlab.actions.approvals")
|
||||
local labels = require("gitlab.actions.labels")
|
||||
|
||||
local info = state.dependencies.info
|
||||
local labels_dep = state.dependencies.labels
|
||||
local project_members = state.dependencies.project_members
|
||||
local revisions = state.dependencies.revisions
|
||||
|
||||
@@ -28,11 +30,13 @@ return {
|
||||
discussions.initialize_discussions() -- place signs / diagnostics for discussions in reviewer
|
||||
end,
|
||||
-- Global Actions 🌎
|
||||
summary = async.sequence({ u.merge(info, { refresh = true }) }, summary.summary),
|
||||
summary = async.sequence({ u.merge(info, { refresh = true }), labels_dep }, summary.summary),
|
||||
approve = async.sequence({ info }, approvals.approve),
|
||||
revoke = async.sequence({ info }, approvals.revoke),
|
||||
add_reviewer = async.sequence({ info, project_members }, assignees_and_reviewers.add_reviewer),
|
||||
delete_reviewer = async.sequence({ info, project_members }, assignees_and_reviewers.delete_reviewer),
|
||||
add_label = async.sequence({ info, labels_dep }, labels.add_label),
|
||||
delete_label = async.sequence({ info, labels_dep }, labels.delete_label),
|
||||
add_assignee = async.sequence({ info, project_members }, assignees_and_reviewers.add_assignee),
|
||||
delete_assignee = async.sequence({ info, project_members }, assignees_and_reviewers.delete_assignee),
|
||||
create_comment = async.sequence({ info, revisions }, comment.create_comment),
|
||||
|
||||
@@ -90,6 +90,7 @@ M.settings = {
|
||||
"reviewers",
|
||||
"branch",
|
||||
"pipeline",
|
||||
"labels",
|
||||
},
|
||||
},
|
||||
discussion_sign_and_diagnostic = {
|
||||
@@ -293,6 +294,7 @@ end
|
||||
-- adding a reviewer) requires some initial state.
|
||||
M.dependencies = {
|
||||
info = { endpoint = "/mr/info", key = "info", state = "INFO", refresh = false },
|
||||
labels = { endpoint = "/mr/label", key = "labels", state = "LABELS", refresh = false },
|
||||
revisions = { endpoint = "/mr/revisions", key = "Revisions", state = "MR_REVISIONS", refresh = false },
|
||||
project_members = {
|
||||
endpoint = "/project/members",
|
||||
|
||||
@@ -28,6 +28,16 @@ M.get_last_word = function(sentence, divider)
|
||||
return words[#words] or ""
|
||||
end
|
||||
|
||||
M.filter = function(input_table, value_to_remove)
|
||||
local resultTable = {}
|
||||
for _, v in ipairs(input_table) do
|
||||
if v ~= value_to_remove then
|
||||
table.insert(resultTable, v)
|
||||
end
|
||||
end
|
||||
return resultTable
|
||||
end
|
||||
|
||||
---Merges two deeply nested tables together, overriding values from the first with conflicts
|
||||
---@param defaults table The first table
|
||||
---@param overrides table The second table
|
||||
@@ -328,6 +338,22 @@ M.format_date = function(date_string)
|
||||
end
|
||||
end
|
||||
|
||||
M.difference = function(a, b)
|
||||
local set_b = {}
|
||||
for _, val in ipairs(b) do
|
||||
set_b[val] = true
|
||||
end
|
||||
|
||||
local not_included = {}
|
||||
for _, val in ipairs(a) do
|
||||
if not set_b[val] then
|
||||
table.insert(not_included, val)
|
||||
end
|
||||
end
|
||||
|
||||
return not_included
|
||||
end
|
||||
|
||||
M.jump_to_file = function(filename, line_number)
|
||||
if line_number == nil then
|
||||
line_number = 1
|
||||
@@ -637,6 +663,10 @@ M.get_icon = function(filename)
|
||||
end
|
||||
end
|
||||
|
||||
M.make_comma_separated_readable = function(str)
|
||||
return string.gsub(str, ",", ", ")
|
||||
end
|
||||
|
||||
---@param remote? boolean
|
||||
M.get_all_git_branches = function(remote)
|
||||
local branches = {}
|
||||
|
||||
Reference in New Issue
Block a user