Skip to content

Commit ba612be

Browse files
committed
Fix client name and tags handling
1 parent 8761aa9 commit ba612be

File tree

2 files changed

+47
-22
lines changed

2 files changed

+47
-22
lines changed

Clockify.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
<ItemGroup>
3838
<PackageReference Include="ClockifyClient" Version="1.2.2" />
3939
<PackageReference Include="CommandLineParser" Version="2.9.1" />
40+
<PackageReference Include="FastCloner" Version="3.4.4" />
4041
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="4.14.0">
4142
<PrivateAssets>all</PrivateAssets>
4243
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

Clockify/ClockifyService.cs

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,15 @@ public async Task<TimeEntryWithRatesDtoV1> GetRunningTimerAsync()
8585
logger.LogError($"Fetching running timer failed, no project in workspace matching {_settings.ProjectName}");
8686
return null;
8787
}
88+
89+
var entry = timeEntries?.FirstOrDefault(t => t.ProjectId == _project.Id);
90+
logger.LogInfo($"{string.Join(',', entry?.TagIds?.ToString())}");
8891

8992
return timeEntries?.FirstOrDefault(t => t.ProjectId == _project.Id
9093
&& (string.IsNullOrEmpty(_settings.TimerName) || t.Description == _settings.TimerName)
9194
&& (string.IsNullOrEmpty(_settings.TaskName) || string.IsNullOrEmpty(_task?.Id) || t.TaskId == _task.Id)
92-
&& ((t.TagIds is null && _tags is null) || t.TagIds is not null && _tags is not null && t.TagIds.OrderBy(s => s, StringComparer.InvariantCulture)
93-
.SequenceEqual(_tags.OrderBy(s => s, StringComparer.InvariantCulture)))
95+
&& ((t.TagIds is null && _tags is null) || (t.TagIds is not null && _tags is not null && t.TagIds.OrderBy(s => s, StringComparer.InvariantCulture)
96+
.SequenceEqual(_tags.OrderBy(s => s, StringComparer.InvariantCulture))))
9497
&& t.Billable == _settings.Billable);
9598
}
9699
catch (Exception exception) when (exception is ApiException or HttpRequestException)
@@ -108,6 +111,9 @@ public async Task UpdateSettingsAsync(PluginSettings settings)
108111

109112
var cacheInvalidationRequired = SettingsValidator.HasChanged(_settings, settings);
110113

114+
logger.LogInfo($"{settings.ApiKey}/{settings.WorkspaceName}/{settings.TaskName}/{settings.Billable}/{settings.ProjectName}/{settings.ClientName}/{settings.Tags}");
115+
logger.LogInfo($"{_settings.ApiKey}/{_settings.WorkspaceName}/{_settings.TaskName}/{_settings.Billable}/{_settings.ProjectName}/{_settings.ClientName}/{_settings.Tags}");
116+
111117
// Do we need to recreate the client?
112118
if (!IsValid || _settings.ApiKey != settings.ApiKey || _settings.ServerUrl != settings.ServerUrl)
113119
{
@@ -135,7 +141,7 @@ public async Task UpdateSettingsAsync(PluginSettings settings)
135141
cacheInvalidationRequired = true;
136142
}
137143

138-
_settings = settings;
144+
_settings = FastCloner.FastCloner.DeepClone(settings);
139145

140146
if (cacheInvalidationRequired)
141147
{
@@ -176,6 +182,12 @@ private async Task<CreateTimeEntryRequest> CreateTimeEntryRequestAsync()
176182

177183
private async Task ReloadCacheAsync()
178184
{
185+
if (_clockifyClient is null)
186+
{
187+
logger.LogWarn("The Clockify client was not initialized properly");
188+
return;
189+
}
190+
179191
_workspace = null;
180192
_project = null;
181193
_tags = [];
@@ -185,17 +197,25 @@ private async Task ReloadCacheAsync()
185197
try
186198
{
187199
var workspaces = await _clockifyClient.V1.Workspaces.GetAsync();
188-
_workspace = workspaces?.SingleOrDefault(w => w.Name == _settings.WorkspaceName);
200+
var workspace = workspaces?.SingleOrDefault(w => w.Name == _settings.WorkspaceName);
189201

190-
if (_workspace != null)
202+
if (workspace is not null)
191203
{
192-
_project = await FindMatchingProjectAsync(_workspace.Id, _settings.ProjectName);
204+
_workspace = FastCloner.FastCloner.DeepClone(workspace);
205+
206+
_client = await FindMatchingClientAsync(_workspace.Id, _settings.ClientName);
207+
var task = FindMatchingProjectAsync(_workspace.Id, _settings.ProjectName, _client?.Id);
208+
if (task == null)
209+
{
210+
throw new Exception("Returned Task was null");
211+
}
212+
213+
_project = await task;
193214
_tags = await FindMatchingTagsAsync(_workspace.Id, _settings.Tags);
194215

195-
if (_project != null)
216+
if (_project is not null)
196217
{
197218
_task = await FindMatchingTaskAsync(_workspace.Id, _project.Id, _settings.TaskName);
198-
_client = await FindMatchingClientAsync(_workspace.Id, _settings.ClientName);
199219
}
200220
}
201221

@@ -216,7 +236,7 @@ private async Task<TimeEntryWithRatesDtoV1> StopRunningTimerAsync()
216236
}
217237

218238
var runningTimer = await GetRunningTimerAsync();
219-
if (runningTimer == null)
239+
if (runningTimer is null)
220240
{
221241
// No running timer
222242
return null;
@@ -246,13 +266,15 @@ private async Task<TimeEntryWithRatesDtoV1> StopRunningTimerAsync()
246266
return runningTimer;
247267
}
248268

249-
private async Task<ProjectDtoV1> FindMatchingProjectAsync(string workspaceId, string projectName)
269+
private async Task<ProjectDtoV1> FindMatchingProjectAsync(string workspaceId, string projectName, string clientId = null)
250270
{
251-
if (string.IsNullOrEmpty(projectName))
271+
if (string.IsNullOrEmpty(workspaceId) || string.IsNullOrEmpty(projectName))
252272
{
253273
return null;
254274
}
255275

276+
logger.LogInfo($"Finding matching project... {_clockifyClient}");
277+
256278
try
257279
{
258280
var projects = await _clockifyClient.V1.Workspaces[workspaceId].Projects
@@ -262,9 +284,9 @@ private async Task<ProjectDtoV1> FindMatchingProjectAsync(string workspaceId, st
262284
q.QueryParameters.StrictNameSearch = true;
263285
q.QueryParameters.PageSize = MaxPageSize;
264286

265-
if (_client is not null)
287+
if (clientId is not null)
266288
{
267-
q.QueryParameters.Clients = [_client.Id];
289+
q.QueryParameters.Clients = [clientId];
268290
}
269291
});
270292

@@ -281,9 +303,9 @@ private async Task<ProjectDtoV1> FindMatchingProjectAsync(string workspaceId, st
281303
}
282304

283305
logger.LogInfo("Finding matching project successful");
284-
return projects.Single();
306+
return FastCloner.FastCloner.DeepClone(projects.Single());
285307
}
286-
catch (Exception exception) when (exception is ApiException or HttpRequestException)
308+
catch (Exception exception) when (exception is ApiException or HttpRequestException or NullReferenceException)
287309
{
288310
logger.LogWarn($"Finding matching project failed, unable to retrieve project {projectName}: {exception.Message}");
289311
return null;
@@ -292,7 +314,7 @@ private async Task<ProjectDtoV1> FindMatchingProjectAsync(string workspaceId, st
292314

293315
private async Task<ClientWithCurrencyDtoV1> FindMatchingClientAsync(string workspaceId, string clientName)
294316
{
295-
if (string.IsNullOrEmpty(clientName))
317+
if (string.IsNullOrEmpty(workspaceId) || string.IsNullOrEmpty(clientName))
296318
{
297319
return null;
298320
}
@@ -306,7 +328,8 @@ private async Task<ClientWithCurrencyDtoV1> FindMatchingClientAsync(string works
306328
q.QueryParameters.PageSize = MaxPageSize;
307329
});
308330

309-
return clientResponse?.FirstOrDefault();
331+
var client = clientResponse?.FirstOrDefault();
332+
return client != null ? FastCloner.FastCloner.DeepClone(client) : null;
310333
}
311334
catch (Exception exception) when (exception is ApiException or HttpRequestException)
312335
{
@@ -317,7 +340,7 @@ private async Task<ClientWithCurrencyDtoV1> FindMatchingClientAsync(string works
317340

318341
private async Task<TaskDtoV1> FindMatchingTaskAsync(string workspaceId, string projectId, string taskName)
319342
{
320-
if (string.IsNullOrEmpty(taskName))
343+
if (string.IsNullOrEmpty(workspaceId) || string.IsNullOrEmpty(projectId) || string.IsNullOrEmpty(taskName))
321344
{
322345
return null;
323346
}
@@ -332,7 +355,8 @@ private async Task<TaskDtoV1> FindMatchingTaskAsync(string workspaceId, string p
332355
q.QueryParameters.PageSize = MaxPageSize;
333356
});
334357

335-
return taskResponse?.FirstOrDefault();
358+
var task = taskResponse?.FirstOrDefault();
359+
return FastCloner.FastCloner.DeepClone(task);
336360
}
337361
catch (Exception exception) when (exception is ApiException or HttpRequestException)
338362
{
@@ -343,7 +367,7 @@ private async Task<TaskDtoV1> FindMatchingTaskAsync(string workspaceId, string p
343367

344368
private async Task<string> FindOrCreateTaskAsync(string workspaceId, string projectId, string taskName)
345369
{
346-
if (string.IsNullOrEmpty(taskName))
370+
if (string.IsNullOrEmpty(workspaceId) || string.IsNullOrEmpty(projectId) || string.IsNullOrEmpty(taskName))
347371
{
348372
return null;
349373
}
@@ -374,7 +398,7 @@ private async Task<string> FindOrCreateTaskAsync(string workspaceId, string proj
374398

375399
private async Task<List<string>> FindMatchingTagsAsync(string workspaceId, string tags)
376400
{
377-
if (string.IsNullOrEmpty(tags))
401+
if (string.IsNullOrEmpty(workspaceId) || string.IsNullOrEmpty(tags))
378402
{
379403
return [];
380404
}
@@ -395,7 +419,7 @@ private async Task<List<string>> FindMatchingTagsAsync(string workspaceId, strin
395419
var tagsOnWorkspace = await _clockifyClient.V1.Workspaces[workspaceId].Tags
396420
.GetAsync(q => q.QueryParameters.PageSize = MaxPageSize);
397421

398-
return tagsOnWorkspace == null ? [] : tagsOnWorkspace.Where(t => tagList.Contains(t.Name)).Select(t => t.Id).ToList();
422+
return tagsOnWorkspace is null ? [] : tagsOnWorkspace.Where(t => tagList.Contains(t.Name)).Select(t => t.Id).ToList();
399423
}
400424
catch (Exception exception) when (exception is ApiException or HttpRequestException)
401425
{

0 commit comments

Comments
 (0)