diff --git a/NGitLab.Mock/Clients/IssueClient.cs b/NGitLab.Mock/Clients/IssueClient.cs index 987b7e4c..39060718 100644 --- a/NGitLab.Mock/Clients/IssueClient.cs +++ b/NGitLab.Mock/Clients/IssueClient.cs @@ -451,4 +451,14 @@ private IEnumerable FilterByQuery(IEnumerable issues, IssueQuery q return issues; } + + public IEnumerable GetParticipants(ProjectId projectId, int issueIid) + { + throw new NotImplementedException(); + } + + public Models.Issue Unsubscribe(ProjectId projectId, int issueIid) + { + throw new NotImplementedException(); + } } diff --git a/NGitLab.Tests/IssueTests.cs b/NGitLab.Tests/IssueTests.cs index 054a125b..862d23de 100644 --- a/NGitLab.Tests/IssueTests.cs +++ b/NGitLab.Tests/IssueTests.cs @@ -311,4 +311,18 @@ public async Task Test_get_linked_issue() // for now, no API to link issues so not links exist but API should not throw Assert.That(issues, Has.Count.EqualTo(1), $"Expected 1. Got {issues.Count}"); } + + [Test] + [NGitLabRetry] + public async Task Test_getparticipants_issue() + { + using var context = await GitLabTestContext.CreateAsync(); + var project = context.CreateProject(); + var issuesClient = context.Client.Issues; + var issue1 = issuesClient.Create(new IssueCreate { ProjectId = project.Id, Title = "title1", Confidential = true }); + + var participant = issuesClient.GetParticipants(project.Id, issue1.IssueId); + + Assert.That(participant.Count, Is.EqualTo(1)); + } } diff --git a/NGitLab/IIssueClient.cs b/NGitLab/IIssueClient.cs index 92628207..b842b796 100644 --- a/NGitLab/IIssueClient.cs +++ b/NGitLab/IIssueClient.cs @@ -180,4 +180,20 @@ public interface IIssueClient /// /// Task CloneAsync(int projectId, int issueIid, IssueClone issueClone, CancellationToken cancellationToken = default); + + /// + /// Get Participants + /// + /// The project id + /// The id of the issue in the project's scope. + /// The participants of the issue. + IEnumerable GetParticipants(ProjectId projectId, int issueIid); + + /// + /// Unsubscribe to the issue + /// + /// The project id + /// The id of the issue in the project's scope. + /// The issue that corresponds to the project id and issue id + Issue Unsubscribe(ProjectId projectId, int issueIid); } diff --git a/NGitLab/Impl/IssueClient.cs b/NGitLab/Impl/IssueClient.cs index 6e6d731e..f67b1fe9 100644 --- a/NGitLab/Impl/IssueClient.cs +++ b/NGitLab/Impl/IssueClient.cs @@ -23,6 +23,8 @@ public class IssueClient : IIssueClient private const string ClosedByUrl = "/projects/{0}/issues/{1}/closed_by"; private const string TimeStatsUrl = "/projects/{0}/issues/{1}/time_stats"; private const string CloneIssueUrl = "/projects/{0}/issues/{1}/clone"; + private const string ParticipantsUrl = "/projects/{0}/issues/{1}/participants"; + private const string UnsubscribeUrl = "/projects/{0}/issues/{1}/unsubscribe"; private readonly API _api; @@ -192,6 +194,16 @@ public Task CloneAsync(int projectId, int issueIid, IssueClone issueClone return _api.Post().With(issueClone).ToAsync(string.Format(CultureInfo.InvariantCulture, CloneIssueUrl, projectId, issueIid), cancellationToken); } + public IEnumerable GetParticipants(ProjectId projectId, int issueIid) + { + return _api.Get().GetAll(string.Format(CultureInfo.InvariantCulture, ParticipantsUrl, projectId.ValueAsUriParameter(), issueIid)); + } + + public Issue Unsubscribe(ProjectId projectId, int issueIid) + { + return _api.Post().To(string.Format(CultureInfo.InvariantCulture, UnsubscribeUrl, projectId.ValueAsUriParameter(), issueIid)); + } + private GitLabCollectionResponse Get(string url, IssueQuery query) { url = AddIssueQueryParameters(url, query); diff --git a/NGitLab/Models/Participant.cs b/NGitLab/Models/Participant.cs new file mode 100644 index 00000000..2fd27034 --- /dev/null +++ b/NGitLab/Models/Participant.cs @@ -0,0 +1,24 @@ +using System.Text.Json.Serialization; + +namespace NGitLab.Models; + +public class Participant +{ + [JsonPropertyName("id")] + public int Id { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("username")] + public string Username { get; set; } + + [JsonPropertyName("state")] + public string State { get; set; } + + [JsonPropertyName("avatar_url")] + public string AvatarURL { get; set; } + + [JsonPropertyName("web_url")] + public string WebUrl { get; set; } +} diff --git a/NGitLab/PublicAPI.Unshipped.txt b/NGitLab/PublicAPI.Unshipped.txt index 7506c8ec..57403c20 100644 --- a/NGitLab/PublicAPI.Unshipped.txt +++ b/NGitLab/PublicAPI.Unshipped.txt @@ -347,6 +347,7 @@ NGitLab.IIssueClient.GetAsync(int projectId, NGitLab.Models.IssueQuery query) -> NGitLab.IIssueClient.GetAsync(NGitLab.Models.IssueQuery query) -> NGitLab.GitLabCollectionResponse NGitLab.IIssueClient.GetById(int issueId) -> NGitLab.Models.Issue NGitLab.IIssueClient.GetByIdAsync(int issueId, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task +NGitLab.IIssueClient.GetParticipants(NGitLab.Models.ProjectId projectId, int issueIid) -> System.Collections.Generic.IEnumerable NGitLab.IIssueClient.LinkedToAsync(int projectId, int issueId) -> NGitLab.GitLabCollectionResponse NGitLab.IIssueClient.Owned.get -> System.Collections.Generic.IEnumerable NGitLab.IIssueClient.RelatedTo(int projectId, int issueIid) -> System.Collections.Generic.IEnumerable @@ -358,6 +359,7 @@ NGitLab.IIssueClient.ResourceMilestoneEventsAsync(int projectId, int issueIid) - NGitLab.IIssueClient.ResourceStateEvents(int projectId, int issueIid) -> System.Collections.Generic.IEnumerable NGitLab.IIssueClient.ResourceStateEventsAsync(int projectId, int issueIid) -> NGitLab.GitLabCollectionResponse NGitLab.IIssueClient.TimeStatsAsync(int projectId, int issueIid, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task +NGitLab.IIssueClient.Unsubscribe(NGitLab.Models.ProjectId projectId, int issueIid) -> NGitLab.Models.Issue NGitLab.IJobClient NGitLab.IJobClient.Get(int jobId) -> NGitLab.Models.Job NGitLab.IJobClient.GetAsync(int jobId, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task @@ -640,6 +642,7 @@ NGitLab.Impl.IssueClient.GetAsync(int projectId, NGitLab.Models.IssueQuery query NGitLab.Impl.IssueClient.GetAsync(NGitLab.Models.IssueQuery query) -> NGitLab.GitLabCollectionResponse NGitLab.Impl.IssueClient.GetById(int issueId) -> NGitLab.Models.Issue NGitLab.Impl.IssueClient.GetByIdAsync(int issueId, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task +NGitLab.Impl.IssueClient.GetParticipants(NGitLab.Models.ProjectId projectId, int issueIid) -> System.Collections.Generic.IEnumerable NGitLab.Impl.IssueClient.IssueClient(NGitLab.Impl.API api) -> void NGitLab.Impl.IssueClient.LinkedToAsync(int projectId, int issueId) -> NGitLab.GitLabCollectionResponse NGitLab.Impl.IssueClient.Owned.get -> System.Collections.Generic.IEnumerable @@ -652,6 +655,7 @@ NGitLab.Impl.IssueClient.ResourceMilestoneEventsAsync(int projectId, int issueIi NGitLab.Impl.IssueClient.ResourceStateEvents(int projectId, int issueIid) -> System.Collections.Generic.IEnumerable NGitLab.Impl.IssueClient.ResourceStateEventsAsync(int projectId, int issueIid) -> NGitLab.GitLabCollectionResponse NGitLab.Impl.IssueClient.TimeStatsAsync(int projectId, int issueIid, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task +NGitLab.Impl.IssueClient.Unsubscribe(NGitLab.Models.ProjectId projectId, int issueIid) -> NGitLab.Models.Issue NGitLab.Impl.JobClient NGitLab.Impl.JobClient.Get(int jobId) -> NGitLab.Models.Job NGitLab.Impl.JobClient.GetAsync(int jobId, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task @@ -2750,6 +2754,20 @@ NGitLab.Models.PageQuery NGitLab.Models.PageQuery.PageQuery(int page = 1, int perPage = 20, TQueryType query = default(TQueryType)) -> void NGitLab.Models.PageQuery.Query.get -> TQueryType NGitLab.Models.PageQuery.Query.set -> void +NGitLab.Models.Participant +NGitLab.Models.Participant.Participant() -> void +NGitLab.Models.Participant.Id.get -> int +NGitLab.Models.Participant.Id.set -> void +NGitLab.Models.Participant.AvatarURL.get -> string +NGitLab.Models.Participant.AvatarURL.set -> void +NGitLab.Models.Participant.Name.get -> string +NGitLab.Models.Participant.Name.set -> void +NGitLab.Models.Participant.State.get -> string +NGitLab.Models.Participant.State.set -> void +NGitLab.Models.Participant.Username.get -> string +NGitLab.Models.Participant.Username.set -> void +NGitLab.Models.Participant.WebUrl.get -> string +NGitLab.Models.Participant.WebUrl.set -> void NGitLab.Models.PersonInfo NGitLab.Models.PersonInfo.Email -> string NGitLab.Models.PersonInfo.Name -> string