Skip to content

Commit

Permalink
Fix #228 and implement ICloneable for all EntityViewModel
Browse files Browse the repository at this point in the history
  • Loading branch information
TheAxelander committed Mar 14, 2024
1 parent 0bb68e5 commit 67bbd09
Show file tree
Hide file tree
Showing 16 changed files with 310 additions and 180 deletions.
37 changes: 18 additions & 19 deletions OpenBudgeteer.Blazor/Pages/Rules.razor
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
@page "/rules"

@using System
@using System.Drawing
@using OpenBudgeteer.Core.Common.Extensions
@using OpenBudgeteer.Core.ViewModels.EntityViewModels
Expand Down Expand Up @@ -47,26 +46,26 @@
<tr>
<td style="width: 120px">
<select class="form-select form-select-sm"
@bind:get="mappingRule.ComparisionField.ToString()"
@bind:set="(value) => { mappingRule.ComparisionField = (MappingRuleViewModel.MappingComparisionField)Convert.ToInt32(value); }">
@for (int i = 1; i <= 4; i++)
@bind:get="mappingRule.ComparisonField.ToString()"
@bind:set="(value) => { ComparisionField_SelectionChanged(value, mappingRule); }">
@foreach (var comparisionField in Enum.GetValues<MappingRuleComparisonField>())
{
<option value="@i">@(((MappingRuleViewModel.MappingComparisionField)i).GetStringValue())</option>
<option value="@comparisionField">@comparisionField.GetStringValue()</option>
}
</select>
</td>
<td style="width: 160px">
<select class="form-select form-select-sm"
@bind:get="mappingRule.ComparisionType.ToString()"
@bind:set="(value) => { mappingRule.ComparisionType = (MappingRuleViewModel.MappingComparisionType)Convert.ToInt32(value); }">
@for (int i = 1; i <= 4; i++)
@bind:get="mappingRule.ComparisonType.ToString()"
@bind:set="(value) => { ComparisionType_SelectionChanged(value, mappingRule); }">
@foreach (var comparisionType in Enum.GetValues<MappingRuleComparisonType>())
{
<option value="@i">@(((MappingRuleViewModel.MappingComparisionType)i).GetStringValue())</option>
<option value="@comparisionType">@comparisionType.GetStringValue()</option>
}
</select>
</td>
<td>
<input class="form-control form-control-sm" type="text" @bind="mappingRule.ComparisionValue" />
<input class="form-control form-control-sm" type="text" @bind="mappingRule.ComparisonValue" />
</td>
<td class="col-buttons" style="width: 1px">
<button class="btn btn-sm btn-primary bi bi-plus-lg" @onclick="@(() => _dataContext.NewRuleSet.AddEmptyMappingRule())"></button>
Expand Down Expand Up @@ -117,26 +116,26 @@
<tr>
<td style="width: 120px">
<select class="form-select form-select-sm"
@bind:get="((int)mappingRule.ComparisionField).ToString()"
@bind:set="(value) => { mappingRule.ComparisionField = (MappingRuleViewModel.MappingComparisionField)Convert.ToInt32(value); }">
@for (int i = 1; i <= 4; i++)
@bind:get="mappingRule.ComparisonField.ToString()"
@bind:set="(value) => { ComparisionField_SelectionChanged(value, mappingRule); }">
@foreach (var comparisionField in Enum.GetValues<MappingRuleComparisonField>())
{
<option value="@i">@(((MappingRuleViewModel.MappingComparisionField)i).GetStringValue())</option>
<option value="@comparisionField">@comparisionField.GetStringValue()</option>
}
</select>
</td>
<td style="width: 160px">
<select class="form-select form-select-sm"
@bind:get="((int)mappingRule.ComparisionType).ToString()"
@bind:set="(value) => { mappingRule.ComparisionType = (MappingRuleViewModel.MappingComparisionType)Convert.ToInt32(value); }">
@for (int i = 1; i <= 4; i++)
@bind:get="mappingRule.ComparisonType.ToString()"
@bind:set="(value) => { ComparisionType_SelectionChanged(value, mappingRule); }">
@foreach (var comparisionType in Enum.GetValues<MappingRuleComparisonType>())
{
<option value="@i">@(((MappingRuleViewModel.MappingComparisionType)i).GetStringValue())</option>
<option value="@comparisionType">@comparisionType.GetStringValue()</option>
}
</select>
</td>
<td>
<input class="form-control form-control-sm" type="text" @bind="mappingRule.ComparisionValue" />
<input class="form-control form-control-sm" type="text" @bind="mappingRule.ComparisonValue" />
</td>
<td class="col-buttons" style="width: 1px">
<button class="btn btn-sm btn-primary bi bi-plus-lg" @onclick="@(() => ruleSet.AddEmptyMappingRule())"></button>
Expand Down
18 changes: 18 additions & 0 deletions OpenBudgeteer.Blazor/Pages/Rules.razor.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using OpenBudgeteer.Core.Common;
using OpenBudgeteer.Core.Common.Extensions;
using OpenBudgeteer.Core.Data.Contracts.Services;
using OpenBudgeteer.Core.ViewModels.EntityViewModels;
using OpenBudgeteer.Core.ViewModels.Helper;
Expand Down Expand Up @@ -82,6 +84,22 @@ private void UpdateSelectedBucket(BucketViewModel selectedBucket)
_ruleSetViewModelToBeUpdated!.UpdateSelectedBucket(selectedBucket);
_isBucketSelectDialogVisible = false;
}

private void ComparisionField_SelectionChanged(string? value, MappingRuleViewModel mappingRule)
{
if (string.IsNullOrEmpty(value)) return;
mappingRule.ComparisonField = Enum.TryParse(typeof(MappingRuleComparisonField), value, out var result)
? (MappingRuleComparisonField)result
: MappingRuleComparisonField.Account;
}

private void ComparisionType_SelectionChanged(string? value, MappingRuleViewModel mappingRule)
{
if (string.IsNullOrEmpty(value)) return;
mappingRule.ComparisonType = Enum.TryParse(typeof(MappingRuleComparisonType), value, out var result)
? (MappingRuleComparisonType)result
: MappingRuleComparisonType.Equal;
}

private void HandleShowDeleteRuleSetDialog(RuleSetViewModel ruleSet)
{
Expand Down
4 changes: 2 additions & 2 deletions OpenBudgeteer.Blazor/Shared/EditBucketDialog.razor
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<div class="col-12 col-sm-6 mb-2">
<label class="form-label">Bucket Group:</label>
<select class="form-select form-select-sm"
@bind:get="DataContext.BucketGroupId.ToString()"
@bind:get="DataContext.SelectedBucketGroup.Id.ToString()"
@bind:set="BucketGroup_SelectionChanged">
@foreach (var bucketGroup in DataContext.AvailableBucketGroups!)
{
Expand Down Expand Up @@ -177,6 +177,6 @@
void BucketGroup_SelectionChanged(string? value)
{
if (string.IsNullOrEmpty(value)) return;
DataContext.BucketGroupId = Guid.Parse(value);
DataContext.SelectedBucketGroup = DataContext.AvailableBucketGroups.First(i => i.Id == Guid.Parse(value));
}
}
13 changes: 13 additions & 0 deletions OpenBudgeteer.Core/Common/Extensions/MappingRuleComparisonField.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace OpenBudgeteer.Core.Common.Extensions;

public enum MappingRuleComparisonField
{
[StringValue("Account")]
Account = 1,
[StringValue("Payee")]
Payee = 2,
[StringValue("Memo")]
Memo = 3,
[StringValue("Amount")]
Amount = 4
}
13 changes: 13 additions & 0 deletions OpenBudgeteer.Core/Common/Extensions/MappingRuleComparisonType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace OpenBudgeteer.Core.Common.Extensions;

public enum MappingRuleComparisonType
{
[StringValue("Equal")]
Equal = 1,
[StringValue("Not equal")]
NotEqual = 2,
[StringValue("Contains")]
Contains = 3,
[StringValue("Does not contain")]
DoesNotContain = 4
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ protected AccountViewModel(AccountViewModel viewModel) : base(viewModel.ServiceM
AccountId = viewModel.AccountId;
_name = viewModel.Name;
_isActive = viewModel.IsActive;
_balance = viewModel.Balance;
_in = viewModel.In;
_out = viewModel.Out;
}

/// <summary>
Expand All @@ -121,14 +124,13 @@ public static AccountViewModel CreateFromAccount(IServiceManager serviceManager,
}

/// <summary>
/// Initialize a copy of the passed ViewModel
/// Return a deep copy of the ViewModel
/// </summary>
/// <param name="accountViewModel">Current ViewModel instance</param>
public static AccountViewModel CreateAsCopy(AccountViewModel accountViewModel)
public override object Clone()
{
return new AccountViewModel(accountViewModel);
return new AccountViewModel(this);
}

#endregion

#region Modification Handler
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@

namespace OpenBudgeteer.Core.ViewModels.EntityViewModels;

public abstract class BaseEntityViewModel<TEntity> : ViewModelBase where TEntity : IEntity
public abstract class BaseEntityViewModel<TEntity> : ViewModelBase, ICloneable where TEntity : IEntity
{
protected BaseEntityViewModel(IServiceManager serviceManager) : base(serviceManager)
{
}

internal abstract TEntity ConvertToDto();
public abstract object Clone();
}
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,14 @@ public static BucketGroupViewModel CreateEmpty(IServiceManager serviceManager)
return new BucketGroupViewModel(serviceManager, null, DateTime.Now);
}

/// <summary>
/// Return a deep copy of the ViewModel
/// </summary>
public override object Clone()
{
return new BucketGroupViewModel(this);
}

#endregion

#region Modification Handler
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,21 +74,6 @@ public BucketType BucketTypeParameter
}
}

public string BucketTypeOutput
{
get
{
return BucketTypeParameter switch
{
BucketType.StandardBucket => CamelCaseConverter.ConvertToSpaces(nameof(BucketType.StandardBucket)),
BucketType.MonthlyExpense => CamelCaseConverter.ConvertToSpaces(nameof(BucketType.MonthlyExpense)),
BucketType.ExpenseEveryXMonths => CamelCaseConverter.ConvertToSpaces(nameof(BucketType.ExpenseEveryXMonths)),
BucketType.SaveXUntilYDate => CamelCaseConverter.ConvertToSpaces(nameof(BucketType.SaveXUntilYDate)),
_ => throw new ArgumentOutOfRangeException()
};
}
}

private int _bucketTypeIntParameter;
/// <summary>
/// Integer based parameter of the Bucket type
Expand Down Expand Up @@ -227,7 +212,15 @@ public static BucketVersionViewModel CreateEmpty(IServiceManager serviceManager)
{
return new BucketVersionViewModel(serviceManager, null);
}


/// <summary>
/// Return a deep copy of the ViewModel
/// </summary>
public override object Clone()
{
return new BucketVersionViewModel(this);
}

#endregion

#region Modification Handler
Expand Down
88 changes: 76 additions & 12 deletions OpenBudgeteer.Core/ViewModels/EntityViewModels/BucketViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ public BucketVersionViewModel BucketVersion
set => Set(ref _bucketVersion, value);
}

private Guid _bucketGroupId;
private BucketGroup _selectedBucketGroup;
/// <summary>
/// Database Id of which <see cref="BucketGroup"/> this Bucket is assigned to
/// <see cref="BucketGroup"/> to which this Bucket is assigned to
/// </summary>
public Guid BucketGroupId
{
get => _bucketGroupId;
set => Set(ref _bucketGroupId, value);
public BucketGroup SelectedBucketGroup
{
get => _selectedBucketGroup;
set => Set(ref _selectedBucketGroup, value);
}

private string _colorCode;
Expand Down Expand Up @@ -245,7 +245,7 @@ protected BucketViewModel(IServiceManager serviceManager, Bucket? bucket, DateTi
{
BucketId = bucket.Id;
_name = bucket.Name ?? string.Empty;
_bucketGroupId = bucket.BucketGroupId;
_selectedBucketGroup = new BucketGroup() { Id = bucket.BucketGroupId };
_colorCode = bucket.ColorCode ?? string.Empty;
_textColorCode = bucket.TextColorCode ?? string.Empty;
_validFrom = bucket.ValidFrom;
Expand Down Expand Up @@ -293,6 +293,47 @@ protected BucketViewModel(
}
}

/// <summary>
/// Initialize a copy of the passed ViewModel
/// </summary>
/// <param name="viewModel">Current ViewModel instance</param>
protected BucketViewModel(BucketViewModel viewModel) : base(viewModel.ServiceManager)
{
BucketId = viewModel.BucketId;
_name = viewModel.Name;
_bucketVersion = (BucketVersionViewModel)viewModel.BucketVersion.Clone();
_selectedBucketGroup = viewModel.SelectedBucketGroup;
_colorCode = viewModel.ColorCode;
_textColorCode = viewModel.TextColorCode;
_validFrom = viewModel.ValidFrom;
_isInactive = viewModel.IsInactive;
_isInactiveFrom = viewModel.IsInactiveFrom;

_balance = viewModel.Balance;
_inOut = viewModel.InOut;
_want = Want;
_in = viewModel.In;
_activity = viewModel.Activity;
_details = viewModel.Details;
_progress = viewModel.Progress;
_isProgressBarVisible = viewModel.IsProgressbarVisible;
_isHovered = viewModel.IsHovered;

AvailableColors = new ObservableCollection<Color>();
foreach (var availableColor in viewModel.AvailableColors)

Check warning on line 323 in OpenBudgeteer.Core/ViewModels/EntityViewModels/BucketViewModel.cs

View workflow job for this annotation

GitHub Actions / Run Test Cases

Dereference of a possibly null reference.

Check warning on line 323 in OpenBudgeteer.Core/ViewModels/EntityViewModels/BucketViewModel.cs

View workflow job for this annotation

GitHub Actions / Run Test Cases

Dereference of a possibly null reference.
{
AvailableColors.Add(availableColor);
}

AvailableBucketGroups = new ObservableCollection<BucketGroup>();
foreach (var item in viewModel.AvailableBucketGroups)

Check warning on line 329 in OpenBudgeteer.Core/ViewModels/EntityViewModels/BucketViewModel.cs

View workflow job for this annotation

GitHub Actions / Run Test Cases

Dereference of a possibly null reference.

Check warning on line 329 in OpenBudgeteer.Core/ViewModels/EntityViewModels/BucketViewModel.cs

View workflow job for this annotation

GitHub Actions / Run Test Cases

Dereference of a possibly null reference.
{
AvailableBucketGroups.Add(item);
}

_currentYearMonth = viewModel._currentYearMonth;
}

/// <summary>
/// Initialize ViewModel based on an existing <see cref="Bucket"/> object and a specific YearMonth
/// </summary>
Expand Down Expand Up @@ -325,9 +366,24 @@ public static BucketViewModel CreateEmpty(
var availableBucketGroups = serviceManager.BucketGroupService.GetAll().ToList();
return new BucketViewModel(serviceManager, availableBucketGroups, null, yearMonth)
{
_bucketGroupId = bucketGroupId
SelectedBucketGroup = availableBucketGroups.First(i => i.Id == bucketGroupId)
};
}

/// <summary>
/// Initialize ViewModel for displaying the <see cref="Bucket"/>. Not to be used for any modification purposes
/// </summary>
/// <param name="serviceManager">Reference to API based services</param>
/// <param name="bucket">Bucket instance</param>
/// <param name="yearMonth">Current month, required for calculating various values</param>
/// <returns>New ViewModel instance</returns>
public static BucketViewModel CreateForListing(
IServiceManager serviceManager,
Bucket bucket,
DateTime yearMonth)
{
return new BucketViewModel(serviceManager, bucket, yearMonth);
}

/// <summary>
/// Initialize ViewModel for displaying the <see cref="Bucket"/>. Not to be used for any modification purposes
Expand All @@ -341,9 +397,17 @@ public static async Task<BucketViewModel> CreateForListingAsync(
Bucket bucket,
DateTime yearMonth)
{
return await Task.Run(() => new BucketViewModel(serviceManager, bucket, yearMonth));
return await Task.Run(() => CreateForListing(serviceManager, bucket, yearMonth));
}


/// <summary>
/// Return a deep copy of the ViewModel
/// </summary>
public override object Clone()
{
return new BucketViewModel(this);
}

#endregion

#region Modification Handler
Expand Down Expand Up @@ -486,7 +550,7 @@ internal override Bucket ConvertToDto()
{
Id = BucketId,
Name = Name,
BucketGroupId = BucketGroupId,
BucketGroupId = SelectedBucketGroup.Id,
ColorCode = ColorCode,
TextColorCode = TextColorCode,
ValidFrom = ValidFrom,
Expand Down Expand Up @@ -544,7 +608,7 @@ public ViewModelOperationResult CreateOrUpdateBucket()
: ConvertToDto());
}
CalculateValues();
return new ViewModelOperationResult(true);
return new ViewModelOperationResult(true, true);
}
catch (Exception e)
{
Expand Down
Loading

0 comments on commit 67bbd09

Please sign in to comment.