Skip to content

Commit

Permalink
Merge pull request #159 from Kibnet/feat/Duration-filter
Browse files Browse the repository at this point in the history
Feat/duration filter
  • Loading branch information
Kibnet authored Jul 11, 2024
2 parents 5249686 + c68eeb7 commit b85d0e7
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 16 deletions.
51 changes: 51 additions & 0 deletions src/Unlimotion.ViewModel/DurationFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using System;
using System.Collections.ObjectModel;
using DynamicData.Binding;
using PropertyChanged;

namespace Unlimotion.ViewModel;

[AddINotifyPropertyChangedInterface]
public class DurationFilter
{
public string Title { get; set; }
public bool ShowTasks { get; set; }
public Func<TaskItemViewModel, bool> Predicate { get; set; }

public static ReadOnlyObservableCollection<DurationFilter> GetDefinitions()
{
return new ReadOnlyObservableCollection<DurationFilter>(new ObservableCollectionExtended<DurationFilter>
{
new()
{
Title = "No duration",
Predicate = e => e.PlannedDuration == null
},
new()
{
Title = "<=5m",
Predicate = e => e.PlannedDuration <= TimeSpan.FromMinutes(5)
},
new()
{
Title = "5m< & <=30m",
Predicate = e => TimeSpan.FromMinutes(5) < e.PlannedDuration && e.PlannedDuration <= TimeSpan.FromMinutes(30)
},
new()
{
Title = "30m< & <=2h",
Predicate = e => TimeSpan.FromMinutes(30) < e.PlannedDuration && e.PlannedDuration <= TimeSpan.FromHours(2)
},
new()
{
Title = "2h< & <=1d",
Predicate = e => TimeSpan.FromHours(2) < e.PlannedDuration && e.PlannedDuration <= TimeSpan.FromDays(1)
},
new()
{
Title = "1d<",
Predicate = e => TimeSpan.FromDays(1) < e.PlannedDuration
}
});
}
}
16 changes: 16 additions & 0 deletions src/Unlimotion.ViewModel/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,20 @@ bool Predicate(TaskItemViewModel task)
return (Func<TaskItemViewModel, bool>)Predicate;
});

var durationFilter = DurationFilters.ToObservableChangeSet()
.AutoRefreshOnObservable(filter => filter.WhenAnyValue(e => e.ShowTasks))
.ToCollection()
.Select(filter =>
{
bool Predicate(TaskItemViewModel task)
{
return (filter.All(e => e.ShowTasks == false) ||
filter.Where(e => e.ShowTasks).Any(item => item.Predicate(task)));
}
return (Func<TaskItemViewModel, bool>)Predicate;
});

this.WhenAnyValue(m => m.ArchivedDateFilter.CurrentOption, m => m.ArchivedDateFilter.IsCustom)
.Subscribe(filter =>
Expand Down Expand Up @@ -443,6 +457,7 @@ bool Predicate(TaskItemViewModel task)
m => m.PlannedDuration,
m => m.PlannedEndDateTime))
.Filter(unlockedTimeFilter)
.Filter(durationFilter)
.Filter(emojiFilter)
.Filter(wantedFilter)
.Transform(item =>
Expand Down Expand Up @@ -947,6 +962,7 @@ public TaskWrapperViewModel FindTaskWrapperViewModel(TaskItemViewModel taskItemV
public EmojiFilter AllEmojiFilter { get; } = new() { Emoji = "", Title = "All", ShowTasks = false, SortText = "\u0000" };

public ReadOnlyObservableCollection<UnlockedTimeFilter> UnlockedTimeFilters { get; set; } = UnlockedTimeFilter.GetDefinitions();
public ReadOnlyObservableCollection<DurationFilter> DurationFilters { get; set; } = DurationFilter.GetDefinitions();
public bool DetailsAreOpen { get; set; }

public DateFilter CompletedDateFilter { get; set; } = new();
Expand Down
47 changes: 47 additions & 0 deletions src/Unlimotion.ViewModel/SetDurationCommands.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System;
using System.Windows.Input;
using PropertyChanged;
using ReactiveUI;

namespace Unlimotion.ViewModel;

[AddINotifyPropertyChangedInterface]
public class SetDurationCommands
{
TaskItemViewModel taskItemViewModel;

public SetDurationCommands(TaskItemViewModel item)
{
taskItemViewModel = item;
var hasDuration = taskItemViewModel.WhenAny(m => m.PlannedDuration, (time) => time.Value != null);
var any = taskItemViewModel.WhenAny(m => m.PlannedDuration, (time) => true);

OneMinCommand = ReactiveCommand.Create(() => taskItemViewModel.PlannedDuration = TimeSpan.FromMinutes(1), any);
FiveMinutesCommand = ReactiveCommand.Create(() => taskItemViewModel.PlannedDuration = TimeSpan.FromMinutes(5), any);
TenMinutesCommand = ReactiveCommand.Create(() => taskItemViewModel.PlannedDuration = TimeSpan.FromMinutes(10), any);
TwentyMinutesCommand = ReactiveCommand.Create(() => taskItemViewModel.PlannedDuration = TimeSpan.FromMinutes(20), any);
FortyMinutesCommand = ReactiveCommand.Create(() => taskItemViewModel.PlannedDuration = TimeSpan.FromMinutes(40), any);
OneHourCommand = ReactiveCommand.Create(() => taskItemViewModel.PlannedDuration = TimeSpan.FromHours(1), any);
TwoHoursCommand = ReactiveCommand.Create(() => taskItemViewModel.PlannedDuration = TimeSpan.FromHours(2), any);
FourHoursCommand = ReactiveCommand.Create(() => taskItemViewModel.PlannedDuration = TimeSpan.FromHours(4), any);
OneDayCommand = ReactiveCommand.Create(() => taskItemViewModel.PlannedDuration = TimeSpan.FromDays(1), any);
TwoDaysCommand = ReactiveCommand.Create(() => taskItemViewModel.PlannedDuration = TimeSpan.FromDays(2), any);
FourDaysCommand = ReactiveCommand.Create(() => taskItemViewModel.PlannedDuration = TimeSpan.FromDays(4), any);
EightDaysCommand = ReactiveCommand.Create(() => taskItemViewModel.PlannedDuration = TimeSpan.FromDays(8), any);
NoneCommand = ReactiveCommand.Create(() => taskItemViewModel.PlannedDuration = null, hasDuration);
}

public ICommand OneMinCommand { get; set; }
public ICommand FiveMinutesCommand { get; set; }
public ICommand TenMinutesCommand { get; set; }
public ICommand TwentyMinutesCommand { get; set; }
public ICommand FortyMinutesCommand { get; set; }
public ICommand OneHourCommand { get; set; }
public ICommand TwoHoursCommand { get; set; }
public ICommand FourHoursCommand { get; set; }
public ICommand OneDayCommand { get; set; }
public ICommand TwoDaysCommand { get; set; }
public ICommand FourDaysCommand { get; set; }
public ICommand EightDaysCommand { get; set; }
public ICommand NoneCommand { get; set; }
}
4 changes: 3 additions & 1 deletion src/Unlimotion.ViewModel/TaskItemViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ private bool GetCanBeCompleted() => (ContainsTasks.All(m => m.IsCompleted != fal
private ReadOnlyObservableCollection<TaskItemViewModel> _blockedByTasks;
private TimeSpan? plannedPeriod;
private DateCommands commands = null;
public SetDurationCommands SetDurationCommands { get; set; }

private void Init(ITaskRepository taskRepository)
{
SetDurationCommands = new SetDurationCommands(this);
SaveItemCommand = ReactiveCommand.CreateFromTask(async () =>
{
var model = Model;
Expand Down Expand Up @@ -722,7 +724,7 @@ public IEnumerable<TaskItemViewModel> GetAllParents()
/// Команды для быстрого выбора дат, ленивая загрузка
/// </summary>
public DateCommands Commands => commands ??= new DateCommands(this);

private void ShowModalAndChangeChildrenStatuses(INotificationManagerWrapper notificationManager, string taskName,
List<TaskItemViewModel> childrenTasks, ArchiveMethodType methodType)
{
Expand Down
54 changes: 39 additions & 15 deletions src/Unlimotion/Views/MainControl.axaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModel="clr-namespace:Unlimotion.ViewModel;assembly=Unlimotion.ViewModel"
xmlns:unlimotion="clr-namespace:Unlimotion"
xmlns:views="clr-namespace:Unlimotion.Views"
xmlns:converters="clr-namespace:Unlimotion.Converters"
xmlns:behavior="clr-namespace:Unlimotion.Behavior"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:DataType="viewModel:MainWindowViewModel"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModel="clr-namespace:Unlimotion.ViewModel;assembly=Unlimotion.ViewModel"
xmlns:unlimotion="clr-namespace:Unlimotion"
xmlns:views="clr-namespace:Unlimotion.Views"
xmlns:converters="clr-namespace:Unlimotion.Converters"
xmlns:behavior="clr-namespace:Unlimotion.Behavior"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:DataType="viewModel:MainWindowViewModel"
Name="mainControl"
x:Class="Unlimotion.Views.MainControl">
x:Class="Unlimotion.Views.MainControl">

<Design.DataContext>
<viewModel:MainWindowViewModel/>
Expand All @@ -31,10 +31,10 @@
<Grid Background="Transparent">
<ContentControl Content="{Binding TaskItem}"/>
<Button Background="#00000000"
Content=""
BorderThickness="0"
HorizontalAlignment="Right"
Command="{Binding RemoveCommand}"/>
Content=""
BorderThickness="0"
HorizontalAlignment="Right"
Command="{Binding RemoveCommand}"/>
</Grid>
</DataTemplate>
<DataTemplate DataType="viewModel:EmojiFilter">
Expand All @@ -46,6 +46,9 @@
<DataTemplate DataType="viewModel:UnlockedTimeFilter">
<CheckBox Content="{Binding Title}" IsChecked="{Binding ShowTasks}" VerticalAlignment="Center"/>
</DataTemplate>
<DataTemplate DataType="viewModel:DurationFilter">
<CheckBox Content="{Binding Title}" IsChecked="{Binding ShowTasks}" VerticalAlignment="Center"/>
</DataTemplate>
</UserControl.DataTemplates>

<UserControl.KeyBindings>
Expand Down Expand Up @@ -155,6 +158,7 @@
<CheckBox Content="Only Wanted" IsChecked="{Binding ShowWanted}" IsThreeState="True" Margin="0,0,10,0"/>
<ComboBox ItemsSource="{Binding SortDefinitions}" SelectedItem="{Binding CurrentSortDefinitionForUnlocked}" Margin="0,0,10,0"/>
<ComboBox ItemsSource="{Binding UnlockedTimeFilters}" Margin="0,0,10,0" />
<ComboBox ItemsSource="{Binding DurationFilters}" Margin="0,0,10,0" />
</WrapPanel>
<TreeView Grid.Row="1" AutoScrollToSelectedItem="True"
ItemsSource="{Binding UnlockedItems}"
Expand Down Expand Up @@ -363,6 +367,26 @@
<behavior:LostFocusUpdateBindingBehavior Text="{Binding PlannedDuration, Converter={StaticResource TimeSpanStringConverter}}"/>
</Interaction.Behaviors>
</TextBox>

<DropDownButton Content="Set Duration" Grid.Column="1" Grid.Row="1">
<DropDownButton.Flyout>
<MenuFlyout>
<MenuItem Header="1 minute" Command="{Binding SetDurationCommands.OneMinCommand}" />
<MenuItem Header="5 minute" Command="{Binding SetDurationCommands.FiveMinutesCommand}" />
<MenuItem Header="10 minute" Command="{Binding SetDurationCommands.TenMinutesCommand}" />
<MenuItem Header="20 minute" Command="{Binding SetDurationCommands.TwentyMinutesCommand}" />
<MenuItem Header="40 minute" Command="{Binding SetDurationCommands.FortyMinutesCommand}" />
<MenuItem Header="1 hour" Command="{Binding SetDurationCommands.OneHourCommand}" />
<MenuItem Header="2 hour" Command="{Binding SetDurationCommands.TwoHoursCommand}" />
<MenuItem Header="4 hour" Command="{Binding SetDurationCommands.FourHoursCommand}" />
<MenuItem Header="1 day" Command="{Binding SetDurationCommands.OneDayCommand}" />
<MenuItem Header="2 day" Command="{Binding SetDurationCommands.TwoDaysCommand}" />
<MenuItem Header="4 day" Command="{Binding SetDurationCommands.FourDaysCommand}" />
<MenuItem Header="8 day" Command="{Binding SetDurationCommands.EightDaysCommand}" />
<MenuItem Header="None" Command="{Binding SetDurationCommands.NoneCommand}" />
</MenuFlyout>
</DropDownButton.Flyout>
</DropDownButton>
<CalendarDatePicker Grid.Column="2" SelectedDate="{Binding PlannedEndDateTime}"
IsTodayHighlighted="True"
Watermark="Planned End"
Expand Down

0 comments on commit b85d0e7

Please sign in to comment.