Skip to content

Commit

Permalink
feat(ux): 🚸 implement continue-like autofill for tgl edit (#56)
Browse files Browse the repository at this point in the history
starting to implement the design ideology of #28
  • Loading branch information
JamesNZL committed Jun 23, 2023
1 parent 6a742d7 commit 74f58a2
Showing 1 changed file with 140 additions and 1 deletion.
141 changes: 140 additions & 1 deletion src/TogglTrack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1247,7 +1247,8 @@ internal async ValueTask<List<Result>> RequestEditEntry(CancellationToken token,
}

var timeEntries = (await this._GetTimeEntries())?.ConvertAll(timeEntry => timeEntry.ToTimeEntry(me));
if (timeEntries is null)
var maxTimeEntries = (await this._GetMaxReportTimeEntries())?.ToSummaryReport(me);
if (timeEntries is null || maxTimeEntries is null)
{
return new List<Result>
{
Expand Down Expand Up @@ -1496,6 +1497,74 @@ internal async ValueTask<List<Result>> RequestEditEntry(CancellationToken token,
},
});

if (!string.IsNullOrEmpty(description))
{
var pastEntries = maxTimeEntries.Groups.Values.SelectMany(pastProject =>
{
if (pastProject.SubGroups is null)
{
return Enumerable.Empty<Result>();
}
return pastProject.SubGroups.Values.Select(pastTimeEntry => new Result
{
Title = pastTimeEntry.GetTitle(),
SubTitle = $"{pastProject.Project?.WithClientName ?? "No Project"} | {timeEntry.HumanisedElapsed} ({timeEntry.DetailedElapsed})",
IcoPath = this._colourIconProvider.GetColourIcon(pastProject.Project?.Colour, "edit.png"),
AutoCompleteText = $"{query.ActionKeyword} {pastTimeEntry.GetTitle(escapePotentialFlags: true)}",
Score = (int)(pastTimeEntry.LatestId ?? 0),
Action = c =>
{
Task.Run(async delegate
{
try
{
this._context.API.LogInfo("TogglTrack", $"past time entry {pastProject.Project?.Id}, {pastTimeEntry.Id}, {timeEntry.Duration}, {timeEntry.Start}, {this._state.SelectedIds.Project}, {timeEntry.WorkspaceId}, {description}, {pastTimeEntry.GetTitle()}");
var editedTimeEntry = (await this._client.EditTimeEntry(
workspaceId: timeEntry.WorkspaceId,
projectId: pastProject.Project?.Id,
id: timeEntry.Id,
description: pastTimeEntry.GetRawTitle(),
duration: timeEntry.Duration,
tags: timeEntry.Tags,
billable: timeEntry.Billable
))?.ToTimeEntry(me);
if (editedTimeEntry?.Id is null)
{
throw new Exception("An API error was encountered.");
}
this.ShowSuccessMessage($"Edited {editedTimeEntry.GetRawDescription()}", $"{pastProject.Project?.WithClientName ?? "No Project"} | {timeEntry.DetailedElapsed}", "edit.png");
// Update cached running time entry state
this.RefreshCache();
}
catch (Exception exception)
{
this._context.API.LogException("TogglTrack", "Failed to edit time entry", exception);
this.ShowErrorMessage("Failed to edit time entry.", exception.Message);
}
finally
{
this._state.SelectedIds.TimeEntry = -1;
this._state.SelectedIds.Project = -1;
this._state.EditProject = TogglTrack.EditProjectState.NoProjectChange;
}
});
return true;
},
});
}).ToList();

results.AddRange(pastEntries.FindAll(result =>
{
return this._context.API.FuzzySearch(description, result.Title).Score > 0;
}));
}

if (this._settings.ShowUsageTips)
{
if (!hasTimeSpanFlag)
Expand Down Expand Up @@ -1686,6 +1755,76 @@ internal async ValueTask<List<Result>> RequestEditEntry(CancellationToken token,
return true;
},
});

if (!string.IsNullOrEmpty(sanitisedDescription))
{
var pastEntries = maxTimeEntries.Groups.Values.SelectMany(pastProject =>
{
if (pastProject.SubGroups is null)
{
return Enumerable.Empty<Result>();
}
return pastProject.SubGroups.Values.Select(pastTimeEntry => new Result
{
Title = pastTimeEntry.GetTitle(),
SubTitle = $"{pastProject.Project?.WithClientName ?? "No Project"} | {newElapsed.Humanize(minUnit: Humanizer.Localisation.TimeUnit.Second, maxUnit: Humanizer.Localisation.TimeUnit.Hour)} ({(int)newElapsed.TotalHours}:{newElapsed.ToString(@"mm\:ss")})",
IcoPath = this._colourIconProvider.GetColourIcon(pastProject.Project?.Colour, "edit.png"),
AutoCompleteText = $"{query.ActionKeyword} {pastTimeEntry.GetTitle(escapePotentialFlags: true)}",
Score = (int)(pastTimeEntry.LatestId ?? 0),
Action = c =>
{
Task.Run(async delegate
{
try
{
this._context.API.LogInfo("TogglTrack", $"past time entry {pastProject.Project?.Id}, {pastTimeEntry.Id}, {timeEntry.Duration}, {timeEntry.Start}, {this._state.SelectedIds.Project}, {timeEntry.WorkspaceId}, {sanitisedDescription}, {pastTimeEntry.GetTitle()}");
var editedTimeEntry = (await this._client.EditTimeEntry(
workspaceId: timeEntry.WorkspaceId,
projectId: pastProject.Project?.Id,
id: timeEntry.Id,
description: pastTimeEntry.GetRawTitle(),
start: startTime,
stop: stopTime,
duration: timeEntry.Duration,
tags: timeEntry.Tags,
billable: timeEntry.Billable
))?.ToTimeEntry(me);
if (editedTimeEntry?.Id is null)
{
throw new Exception("An API error was encountered.");
}
this.ShowSuccessMessage($"Edited {editedTimeEntry.GetRawDescription()}", $"{pastProject.Project?.WithClientName ?? "No Project"} | {(int)newElapsed.TotalHours}:{newElapsed.ToString(@"mm\:ss")}", "edit.png");
// Update cached running time entry state
this.RefreshCache();
}
catch (Exception exception)
{
this._context.API.LogException("TogglTrack", "Failed to edit time entry", exception);
this.ShowErrorMessage("Failed to edit time entry.", exception.Message);
}
finally
{
this._state.SelectedIds.TimeEntry = -1;
this._state.SelectedIds.Project = -1;
this._state.EditProject = TogglTrack.EditProjectState.NoProjectChange;
}
});
return true;
},
});
}).ToList();

results.AddRange(pastEntries.FindAll(result =>
{
return this._context.API.FuzzySearch(sanitisedDescription, result.Title).Score > 0;
}));
}
}
catch (ArgumentException exception)
{
Expand Down

0 comments on commit 74f58a2

Please sign in to comment.