Skip to content

Commit

Permalink
Add textbox to filter WorkPackage directly via OpenProject API
Browse files Browse the repository at this point in the history
  • Loading branch information
GeorgDangl committed May 14, 2019
1 parent 621f459 commit eefd4d7
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 9 deletions.
22 changes: 20 additions & 2 deletions Bcfier/OpenProjectApi/OpenProjectClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,31 @@ public Task<ResponseWrapper<List<Project>>> GetAllProjectsAsync()

public Task<ResponseWrapper<List<WorkPackage>>> GetBcfWorkPackagesForProjectAsync(int projectId,
int pageSize,
int pageNumber)
int pageNumber,
string userTextQuery = null)
{
var client = HttpClientFactory.GetHttpClient(_openProjectAccessToken);
var url = $"{_apiBaseUrl}/projects/{projectId}/work_packages";
var query = $"?pageSize={pageSize}&offset={pageNumber}";
url += query;
var bcfTopicFilter = "&filters=[{\"status\":{\"operator\":\"*\",\"values\":[]}},{\"type\":{\"operator\":\"=\",\"values\":[\"7\"]}}]&sortBy=[[\"createdAt\",\"desc\"]]";

var textFilter = string.Empty;
if (!string.IsNullOrWhiteSpace(userTextQuery))
{
var jsonFilter = Newtonsoft.Json.JsonConvert.SerializeObject(new
{
values = new[] { userTextQuery },
@operator = "**"
});

textFilter = ",{\"search\":" + jsonFilter + "}";
}

var bcfTopicFilter = "&filters=[" +
"{\"status\":{\"operator\":\"*\",\"values\":[]}}," +
"{\"type\":{\"operator\":\"=\",\"values\":[\"7\"]}}" +
textFilter +
"]&sortBy=[[\"createdAt\",\"desc\"]]";
url += bcfTopicFilter;
return client.GetJsonAsync<List<WorkPackage>>(url);
}
Expand Down
56 changes: 50 additions & 6 deletions Bcfier/ViewModels/OpenProjectSyncViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Input;

namespace Bcfier.ViewModels
Expand All @@ -22,6 +24,8 @@ public class OpenProjectSyncViewModel : INotifyPropertyChanged
private List<Project> _projects;
private Project _selectedProject;
private WorkPackage _selectedWorkPackage;
private string _issueFilter;
private readonly Timer _filterRefreshTimer = new Timer(500);

public OpenProjectSyncViewModel(string openProjectApiBaseUrl,
string openProjectAccessToken,
Expand All @@ -34,13 +38,34 @@ public OpenProjectSyncViewModel(string openProjectApiBaseUrl,
SelectWorkPackageCommand = new RelayCommand(DownloadWorkPackageAsBcf);
OpenAllWorkPackagesInProjectCommand = new RelayCommand(DownloadAllWorkPackagesAsBcf);
LoadProjects();
this.PropertyChanged += (s, e) =>

var shouldRequeryDueToTextFilterChange = false;
_filterRefreshTimer.Elapsed += (s, e) =>
{
if (shouldRequeryDueToTextFilterChange)
{
Application.Current.Dispatcher.Invoke(() =>
{
WorkPackages.Clear();
});

LoadWorkPackages();
shouldRequeryDueToTextFilterChange = false;
}
};
_filterRefreshTimer.Start();

PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(SelectedProject))
{
WorkPackages.Clear();
LoadWorkPackages();
}
else if (e.PropertyName == nameof(IssueFilter))
{
shouldRequeryDueToTextFilterChange = true;
}
};
}

Expand Down Expand Up @@ -100,6 +125,19 @@ public WorkPackage SelectedWorkPackage
}
}

public string IssueFilter
{
get => _issueFilter;
set
{
if (_issueFilter != value)
{
_issueFilter = value;
NotifyPropertyChanged(nameof(IssueFilter));
}
}
}

public ObservableCollection<WorkPackage> WorkPackages { get; } = new ObservableCollection<WorkPackage>();

public ICommand SelectWorkPackageCommand { get; }
Expand Down Expand Up @@ -144,7 +182,7 @@ private async Task DownloadAllWorkPackagesAsBcfAsync()

// The '.bcf' file extension indicates that this is a BCF XML v2.1, the format that's currently exported by Open Project.
// This is relevant later down since we're using the original methods to load a BCF XML file via a temp file
var tempPath = Path.Combine(Path.GetTempPath(), "BCFier", Guid.NewGuid().ToString(), (SelectedProject?.Name?? string.Empty) + ".bcf");
var tempPath = Path.Combine(Path.GetTempPath(), "BCFier", Guid.NewGuid().ToString(), (SelectedProject?.Name ?? string.Empty) + ".bcf");
if (!Directory.Exists(Path.GetDirectoryName(tempPath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(tempPath));
Expand Down Expand Up @@ -182,23 +220,29 @@ private async Task LoadWorkPackages()
}

var currentPage = 1;
var pageSize = 200;
var pageSize = 500;
var canLoadMore = true;
var userTextQuery = IssueFilter;
while (canLoadMore)
{
canLoadMore = false;
var workPackagesResult = await _openProjectClient.GetBcfWorkPackagesForProjectAsync(selectedProject.Id,
pageSize,
currentPage++);
currentPage++,
userTextQuery);
if (workPackagesResult.IsSuccess)
{
if (selectedProject == SelectedProject)
if (selectedProject == SelectedProject && userTextQuery == IssueFilter)
{
// This guards against stale work packages, e.g. a request for work packages
// that finishes after the user has changed the selected project
// Guards also against changed IssueFilters
foreach (var newWorkPackage in workPackagesResult.Result)
{
WorkPackages.Add(newWorkPackage);
Application.Current.Dispatcher.Invoke(() =>
{
WorkPackages.Add(newWorkPackage);
});
}
NotifyPropertyChanged(nameof(WorkPackages));
if (workPackagesResult.Result.Count >= pageSize)
Expand Down
11 changes: 10 additions & 1 deletion Bcfier/Windows/OpenProjectSync.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:src="clr-namespace:Bcfier.Data.ValueConverters"
xmlns:themes="clr-namespace:Bcfier.Themes"
mc:Ignorable="d"
Title="Sync with OpenProject"
Width="550"
Expand Down Expand Up @@ -49,9 +50,17 @@
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<themes:TextPlaceholder
Height="25"
Margin="5"
HorizontalAlignment="Stretch"
Placeholder="Filter Issues"
Text="{Binding IssueFilter, UpdateSourceTrigger=PropertyChanged}"/>
<ListBox ItemsSource="{Binding WorkPackages}"
SelectedItem="{Binding SelectedWorkPackage}">
SelectedItem="{Binding SelectedWorkPackage}"
Grid.Row="1">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
Expand Down

0 comments on commit eefd4d7

Please sign in to comment.