Skip to content

Commit

Permalink
Merge pull request #14 from surgeforward/SupportAssociatedRepositories
Browse files Browse the repository at this point in the history
Support associated repositories
  • Loading branch information
jeremysawesome authored Jun 15, 2016
2 parents 82c0dce + 919115b commit 820abab
Show file tree
Hide file tree
Showing 33 changed files with 536 additions and 67 deletions.
5 changes: 5 additions & 0 deletions src/Nagger.Data/Fake/FakeRemoteTaskRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ public IEnumerable<Task> GetTasksByProjectId(string projectId, string lastTaskId
throw new NotImplementedException();
}

public void InitializeForProject(Project project)
{
throw new NotImplementedException();
}

static Task GetTask(string id, string name, Task parent = null)
{
return new Task
Expand Down
16 changes: 14 additions & 2 deletions src/Nagger.Data/JIRA/BaseJiraRepository.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace Nagger.Data.JIRA
{
using Extensions;
using Interfaces;
using Models;

Expand All @@ -9,6 +10,7 @@ public class BaseJiraRepository
const string UsernameKey = "JiraUsername";
const string PasswordKey = "JiraPassword";
const string ApiBaseUrlKey = "JiraApi";
const string ModifiedFormat = "{0}_{1}";
readonly BaseRepository _baseRepository;

User _user;
Expand All @@ -23,7 +25,8 @@ public string ApiBaseUrl
{
get
{
_apiBaseUrl = _apiBaseUrl ?? _baseRepository.GetApiBaseUrl(ApiName, ApiBaseUrlKey);
var apiKey = GetSettingKey(ApiBaseUrlKey);
_apiBaseUrl = _apiBaseUrl ?? _baseRepository.GetApiBaseUrl(ApiName, apiKey);
return _apiBaseUrl;
}
}
Expand All @@ -32,11 +35,20 @@ public User JiraUser
{
get
{
_user = _user ?? _baseRepository.GetUser(ApiName, UsernameKey, PasswordKey);
var uKey = GetSettingKey(UsernameKey);
var pKey = GetSettingKey(PasswordKey);
_user = _user ?? _baseRepository.GetUser(ApiName, uKey, pKey);
return _user;
}
}

public string GetSettingKey(string key)
{
return !KeyModifier.IsNullOrWhitespace() ? ModifiedFormat.FormatWith(KeyModifier, key) : key;
}

public string KeyModifier { get; set; }

public bool UserExists => JiraUser != null;
}
}
18 changes: 13 additions & 5 deletions src/Nagger.Data/JIRA/JiraTaskRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,21 @@

public class JiraTaskRepository : IRemoteTaskRepository
{
readonly JiraApi _api;
JiraApi _api;
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
readonly BaseJiraRepository _baseJiraRepository;

JiraApi Api => _api ?? (_api = new JiraApi(_baseJiraRepository.JiraUser, _baseJiraRepository.ApiBaseUrl));


public JiraTaskRepository(BaseJiraRepository baseJiraRepository)
{
_baseJiraRepository = baseJiraRepository;
}

public void InitializeForProject(Project project)
{
_baseJiraRepository.KeyModifier = project.Id;
_api = new JiraApi(_baseJiraRepository.JiraUser, _baseJiraRepository.ApiBaseUrl);
}

Expand Down Expand Up @@ -71,7 +79,7 @@ public IEnumerable<Task> GetTasks(string lastTaskId = null)
});
}

var apiResult = _api.Execute<TaskResult>(request);
var apiResult = Api.Execute<TaskResult>(request);

return apiResult?.issues?.Select(x => new Task
{
Expand Down Expand Up @@ -102,7 +110,7 @@ public Task GetTaskByName(string name)
}
};

var apiResult = _api.Execute<TaskResult>(request);
var apiResult = Api.Execute<TaskResult>(request);

if (apiResult?.issues == null || !apiResult.issues.Any()) return null;

Expand Down Expand Up @@ -148,7 +156,7 @@ public IEnumerable<Task> GetTasks(Project project)
}
};

var apiResult = _api.Execute<TaskResult>(request);
var apiResult = Api.Execute<TaskResult>(request);

return apiResult?.issues?.Select(x => new Task
{
Expand Down Expand Up @@ -203,7 +211,7 @@ public IEnumerable<Task> GetTasksByProjectId(string projectId, string lastTaskId
}
};

var apiResult = _api.Execute<TaskResult>(request);
var apiResult = Api.Execute<TaskResult>(request);
if (apiResult?.issues == null) yield break;

foreach (var issue in apiResult.issues)
Expand Down
69 changes: 59 additions & 10 deletions src/Nagger.Data/JIRA/JiraTimeRepository.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,75 @@
namespace Nagger.Data.JIRA
{
using System;
using API;
using DTO;
using Extensions;
using Interfaces;
using Models;
using RestSharp;
using Project = Models.Project;

public class JiraTimeRepository : IRemoteTimeRepository
public class JiraTimeRepository : IRemoteTimeRepository, IInitializable
{
readonly JiraApi _api;

JiraApi _api;
readonly BaseJiraRepository _baseJiraRepository;
readonly ISettingsService _settingsService;
readonly IInputService _inputService;
const string AdjustEstimateKey = "AdjustJiraEstimate";
JiraApi Api => _api ?? (_api = new JiraApi(_baseJiraRepository.JiraUser, _baseJiraRepository.ApiBaseUrl));

public JiraTimeRepository(BaseJiraRepository baseJiraRepository)
public JiraTimeRepository(BaseJiraRepository baseJiraRepository, ISettingsService settingsService, IInputService inputService)
{
_api = new JiraApi(baseJiraRepository.JiraUser, baseJiraRepository.ApiBaseUrl);
_baseJiraRepository = baseJiraRepository;
_settingsService = settingsService;
_inputService = inputService;
}

// needs to post to: /rest/api/2/issue/{issueIdOrKey}/worklog
public bool RecordTime(TimeEntry timeEntry)
{
// Jira requires a task
if (!timeEntry.HasTask) return false;

return RecordTime(timeEntry, timeEntry.Task);
}

public bool RecordAssociatedTime(TimeEntry timeEntry)
{
if (!timeEntry.HasAssociatedTask) return false;
try
{
return RecordTime(timeEntry, timeEntry.AssociatedTask);
}
catch (ApplicationException)
{
return false;
}
}

public void InitializeForProject(Project project)
{
_baseJiraRepository.KeyModifier = project.Id;
_api = new JiraApi(_baseJiraRepository.JiraUser, _baseJiraRepository.ApiBaseUrl);
AdjustJiraEstimate();
}

public void Initialize()
{
AdjustJiraEstimate();
}

bool AdjustJiraEstimate(Project project = null)
{
var settingKey = _baseJiraRepository.GetSettingKey(AdjustEstimateKey);
if (!_settingsService.GetSetting<string>(settingKey).IsNullOrWhitespace()) return _settingsService.GetSetting<bool>(settingKey);

var projectString = (project != null) ? " for {0} ".FormatWith(project.Name) : "";
var adjustJiraEstimate = _inputService.AskForBoolean("Would you like JIRA to automatically adjust estimates {0}when you log your time?".FormatWith(projectString));
_settingsService.SaveSetting(settingKey, adjustJiraEstimate.ToString());
return adjustJiraEstimate;
}

// needs to post to: /rest/api/2/issue/{issueIdOrKey}/worklog
bool RecordTime(TimeEntry timeEntry, Task task)
{
// jira requires a special format - like ISO 8601 but not quite
const string jiraTimeFormat = "yyyy-MM-ddTHH:mm:ss.fffK";

Expand All @@ -36,16 +83,18 @@ public bool RecordTime(TimeEntry timeEntry)
timeSpent = timeEntry.MinutesSpent +"m"
};

var adjustEstimate = !AdjustJiraEstimate() ? "?adjustEstimate=leave": "";

var post = new RestRequest()
{
Resource = "issue/"+timeEntry.Task.Id+"/worklog?adjustEstimate=leave",
Resource = "issue/{0}/worklog{1}".FormatWith(task.Id, adjustEstimate),
Method = Method.POST,
RequestFormat = DataFormat.Json
};

post.AddBody(worklog);

var result = _api.Execute<Worklog>(post);
var result = Api.Execute<Worklog>(post);
return result != null;
}
}
Expand Down
68 changes: 63 additions & 5 deletions src/Nagger.Data/Local/LocalProjectRepository.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
namespace Nagger.Data.Local
{
using System;
using System.Collections.Generic;
using System.Linq;
using Extensions;
using Interfaces;
using Models;

Expand All @@ -12,7 +15,7 @@ public Project GetProjectById(string id)
using (var cmd = cnn.CreateCommand())
{
cmd.CommandText = @"SELECT * FROM Projects
WHERE Id = @id";
WHERE Projects.Id = @id";

cmd.Prepare();
cmd.Parameters.AddWithValue("@id", id);
Expand All @@ -28,6 +31,8 @@ public Project GetProjectById(string id)
Key = reader.Get<string>("Key")
};

project.AssociatedRemoteRepository = GetAssociatedRemoteRepository(project.Id);

return project;
}
}
Expand All @@ -52,9 +57,11 @@ public Project GetProjectByKey(string key)
{
Id = reader.Get<string>("Id"),
Name = reader.Get<string>("Name"),
Key = reader.Get<string>("Key")
Key = reader.Get<string>("Key"),
};

project.AssociatedRemoteRepository = GetAssociatedRemoteRepository(project.Id);

return project;
}
}
Expand All @@ -77,9 +84,11 @@ public IEnumerable<Project> GetProjects()
{
Id = reader.Get<string>("Id"),
Name = reader.Get<string>("Name"),
Key = reader.Get<string>("Key")
Key = reader.Get<string>("Key"),
};

project.AssociatedRemoteRepository = GetAssociatedRemoteRepository(project.Id);

projects.Add(project);
}
}
Expand All @@ -93,8 +102,7 @@ public void StoreProject(Project project)
using (var cnn = GetConnection())
using (var cmd = cnn.CreateCommand())
{
cmd.CommandText = @"INSERT OR IGNORE INTO Projects (Id, Name, Key)
VALUES (@Id, @Name, @Key)";
cmd.CommandText = @"INSERT OR IGNORE INTO Projects (Id, Name, Key) VALUES (@Id, @Name, @Key)";

cmd.Prepare();
cmd.Parameters.AddWithValue("@Id", project.Id);
Expand All @@ -103,6 +111,24 @@ public void StoreProject(Project project)

cmd.ExecuteNonQuery();
}

StoreAssociatedRepository(project.Id, project.AssociatedRemoteRepository.ToString());

}

void StoreAssociatedRepository(string projectId, string remoteRepository)
{
using (var cnn = GetConnection())
using (var cmd = cnn.CreateCommand())
{
cmd.CommandText = @"INSERT OR REPLACE INTO AssociatedRemoteRepositories (ProjectId, RemoteRepository) VALUES (@ProjectId, @RemoteRepository)";

cmd.Prepare();
cmd.Parameters.AddWithValue("@ProjectId", projectId);
cmd.Parameters.AddWithValue("@RemoteRepository", remoteRepository);

cmd.ExecuteNonQuery();
}
}

public Project GetProjectByName(string name)
Expand All @@ -126,10 +152,42 @@ public Project GetProjectByName(string name)
Name = reader.Get<string>("Name"),
Key = reader.Get<string>("Key")
};
project.AssociatedRemoteRepository = GetAssociatedRemoteRepository(project.Id);

return project;
}
}
}

SupportedRemoteRepository? GetAssociatedRemoteRepository(string projectId)
{
var repositories = GetAssociatedRemoteRepositories(projectId).ToList();
if (!repositories.Any()) return null;
return repositories.First();
}

IEnumerable<SupportedRemoteRepository> GetAssociatedRemoteRepositories(string projectId)
{
using (var cnn = GetConnection())
using (var cmd = cnn.CreateCommand())
{
cmd.CommandText = @"SELECT RemoteRepository FROM AssociatedRemoteRepositories
WHERE ProjectId = @ProjectId";

cmd.Prepare();
cmd.Parameters.AddWithValue("@ProjectId", projectId);

using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var repositoryString = reader.Get<string>("RemoteRepository");
if (repositoryString.IsNullOrWhitespace()) continue;
SupportedRemoteRepository remoteRepository;
if (Enum.TryParse(repositoryString, out remoteRepository)) yield return remoteRepository;
}
}
}
}
}
}
Loading

0 comments on commit 820abab

Please sign in to comment.