Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public AzureDevopsTrackerContext(DbContextOptions options) : base(options)
public DbSet<TimeByState> TimeByStates { get; set; }
public DbSet<ChangeLogItem> ChangeLogItems { get; set; }
public DbSet<ChangeLog> ChangeLogs { get; set; }
public DbSet<WorkItemCustomField> CustomFields { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
Expand Down
2 changes: 1 addition & 1 deletion AzureDevopsTracker/Data/Mapping/ChangeLogMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ public void Configure(EntityTypeBuilder<ChangeLog> builder)
.HasColumnType("varchar(max)");
}
}
}
}
14 changes: 14 additions & 0 deletions AzureDevopsTracker/Data/Mapping/WorkItemCustomFieldMapping.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using AzureDevopsTracker.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace AzureDevopsTracker.Data.Mapping
{
public class WorkItemCustomFieldMapping : IEntityTypeConfiguration<WorkItemCustomField>
{
public void Configure(EntityTypeBuilder<WorkItemCustomField> builder)
{
builder.HasKey(k => new { k.WorkItemId, k.Key });
}
}
}
25 changes: 5 additions & 20 deletions AzureDevopsTracker/Entities/WorkItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ public class WorkItem : Entity

public ChangeLogItem ChangeLogItem { get; private set; }

private readonly List<WorkItemChange> _workItemsChanges = new List<WorkItemChange>();
private readonly List<WorkItemChange> _workItemsChanges = new();
public IReadOnlyCollection<WorkItemChange> WorkItemsChanges => _workItemsChanges;

private readonly List<TimeByState> _timeByState = new List<TimeByState>();
private readonly List<TimeByState> _timeByState = new();
public IReadOnlyCollection<TimeByState> TimeByStates => _timeByState;

private readonly List<WorkItemCustomField> _workItemCustomFields = new List<WorkItemCustomField>();
private readonly List<WorkItemCustomField> _workItemCustomFields = new();
public IReadOnlyCollection<WorkItemCustomField> CustomFields => _workItemCustomFields;
public string CurrentStatus => _workItemsChanges?.OrderBy(x => x.CreatedAt)?.LastOrDefault()?.NewState;
public string LastStatus => _workItemsChanges?.OrderBy(x => x.CreatedAt)?.ToList()?.Skip(1)?.LastOrDefault()?.OldState;
Expand Down Expand Up @@ -117,9 +117,6 @@ public void AddCustomField(WorkItemCustomField customField)
if (customField is null)
throw new ArgumentException("CustomField is null");

if (customField.WorkItemId.IsNullOrEmpty())
customField.LinkWorkItem(Id);

_workItemCustomFields.Add(customField);
}

Expand All @@ -137,20 +134,8 @@ public void UpdateCustomFields(IEnumerable<WorkItemCustomField> newCustomFields)
if (newCustomFields is not null && !newCustomFields.Any())
return;

var customFieldsToAdd = newCustomFields.Where(x => !_workItemCustomFields.Select(x => x.Key).Contains(x.Key));
AddCustomFields(customFieldsToAdd);

var customFieldsToUpdate = newCustomFields.Where(x => _workItemCustomFields.Select(x => x.Key).Contains(x.Key));
foreach (var newCustomField in customFieldsToUpdate)
{
var customField = _workItemCustomFields.FirstOrDefault(x => x.Key == newCustomField.Key);
if (customField is null) continue;

if (customField.WorkItemId.IsNullOrEmpty())
customField.LinkWorkItem(Id);

customField.Update(customField.Value);
}
_workItemCustomFields.Clear();
AddCustomFields(newCustomFields);
}

public void ClearTimesByState()
Expand Down
8 changes: 0 additions & 8 deletions AzureDevopsTracker/Entities/WorkItemCustomField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,6 @@ public WorkItemCustomField(string workItemId, string key, string value)
Value = value;
}

public void LinkWorkItem(string workItemId)
{
if (workItemId.IsNullOrEmpty())
throw new ArgumentException("WorkItemId is required");

WorkItemId = workItemId;
}

public void Update(string value)
{
Value = value;
Expand Down
3 changes: 0 additions & 3 deletions AzureDevopsTracker/Interfaces/IAzureDevopsTrackerService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,5 @@ public interface IAzureDevopsTrackerService
Task Delete(DeleteWorkItemDTO deleteDto);
Task Restore(RestoreWorkItemDTO restoreDto);
Task<WorkItemDTO> GetByWorkItemId(string workItemId);

Task Create(string jsonText, bool addWorkItemChange = true);
Task Update(string jsonText);
}
}
92 changes: 39 additions & 53 deletions AzureDevopsTracker/Services/AzureDevopsTrackerService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
using AzureDevopsTracker.Helpers;
using AzureDevopsTracker.Interfaces;
using AzureDevopsTracker.Interfaces.Internals;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using System;
using System.Linq;
Expand All @@ -20,15 +22,18 @@ public class AzureDevopsTrackerService : IAzureDevopsTrackerService
public readonly IWorkItemRepository _workItemRepository;
public readonly IWorkItemAdapter _workItemAdapter;
public readonly IChangeLogItemRepository _changeLogItemRepository;
private readonly IServiceScopeFactory _serviceScopeFactory;

public AzureDevopsTrackerService(
IWorkItemAdapter workItemAdapter,
IWorkItemRepository workItemRepository,
IChangeLogItemRepository changeLogItemRepository)
IChangeLogItemRepository changeLogItemRepository,
IServiceScopeFactory serviceScopeFactory)
{
_workItemAdapter = workItemAdapter;
_workItemRepository = workItemRepository;
_changeLogItemRepository = changeLogItemRepository;
_serviceScopeFactory = serviceScopeFactory;
}

public async Task Create(CreateWorkItemDTO create, bool addWorkItemChange = true)
Expand All @@ -55,6 +60,8 @@ public async Task Create(CreateWorkItemDTO create, bool addWorkItemChange = true

CheckWorkItemAvailableToChangeLog(workItem, create.Resource.Fields);

ManipulateCustomFields(workItem);

await _workItemRepository.Add(workItem);
await _workItemRepository.SaveChangesAsync();
}
Expand Down Expand Up @@ -101,6 +108,8 @@ public async Task Update(UpdatedWorkItemDTO update)

CheckWorkItemAvailableToChangeLog(workItem, update.Resource.Revision.Fields);

ManipulateCustomFields(workItem);

_workItemRepository.Update(workItem);
await _workItemRepository.SaveChangesAsync();
}
Expand Down Expand Up @@ -131,6 +140,8 @@ public async Task Delete(DeleteWorkItemDTO delete)
delete.Resource.Fields.Activity,
delete.Resource.Fields.Lancado);

ManipulateCustomFields(workItem);

_workItemRepository.Update(workItem);
await _workItemRepository.SaveChangesAsync();
}
Expand Down Expand Up @@ -161,6 +172,8 @@ public async Task Restore(RestoreWorkItemDTO restore)
restore.Resource.Fields.Activity,
restore.Resource.Fields.Lancado);

ManipulateCustomFields(workItem);

_workItemRepository.Update(workItem);
await _workItemRepository.SaveChangesAsync();
}
Expand All @@ -175,6 +188,31 @@ public async Task<WorkItemDTO> GetByWorkItemId(string workItemId)
}

#region Support Methods
public void ManipulateCustomFields(WorkItem workItem)
{
try
{
var json = GetRequestBody();
if (json.IsNullOrEmpty())
return;

var customFields = ReadJsonHelper.ReadJson(workItem.Id, json);
if (customFields is null || !customFields.Any())
return;

workItem.UpdateCustomFields(customFields);
}
catch
{ }
}

public string GetRequestBody()
{
using var scope = _serviceScopeFactory.CreateScope();
var httpContext = scope.ServiceProvider.GetService<IHttpContextAccessor>();
return httpContext?.HttpContext?.Request?.Body?.ToString();
}

public WorkItemChange ToWorkItemChange(
string workItemId, string changedBy,
string iterationPath, DateTime newDate, string newState,
Expand Down Expand Up @@ -274,58 +312,6 @@ public void RemoveChangeLogItem(WorkItem workItem)
workItem.RemoveChangeLogItem();
}
}

/*
* Still missing:
* - Migration
*/
public async Task Create(string jsonText, bool addWorkItemChange = true)
{
try
{
var workItemDTO = JsonConvert.DeserializeObject<CreateWorkItemDTO>(jsonText);
await Create(workItemDTO);

var workItem = await _workItemRepository.GetByWorkItemId(workItemDTO.Resource.Id);
if (workItem is null)
return;

var customFields = ReadJsonHelper.ReadJson(workItem.Id, jsonText);
if (customFields is null || !customFields.Any())
return;

workItem.AddCustomFields(customFields);

_workItemRepository.Update(workItem);
await _workItemRepository.SaveChangesAsync();
}
catch
{ }
}

public async Task Update(string jsonText)
{
try
{
var workItemDTO = JsonConvert.DeserializeObject<UpdatedWorkItemDTO>(jsonText);
await Update(workItemDTO);

var workItem = await _workItemRepository.GetByWorkItemId(workItemDTO.Resource.WorkItemId);
if (workItem is null)
return;

var customFields = ReadJsonHelper.ReadJson(workItem.Id, jsonText);
if (customFields is null || !customFields.Any())
return;

workItem.UpdateCustomFields(customFields);

_workItemRepository.Update(workItem);
await _workItemRepository.SaveChangesAsync();
}
catch
{ }
}
#endregion
}
}