Skip to content

Commit e7f1152

Browse files
authored
Merge pull request #128 from TheAxelander/124_import_page_dialogs
Merge changes for version 1.6.3
2 parents 16e8bb6 + 7890233 commit e7f1152

File tree

5 files changed

+124
-44
lines changed

5 files changed

+124
-44
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
### 1.6.3 (2023-01-27)
2+
3+
* [Add] Several Confirmation Dialogs for Import Profile handling [#124](https://github.com/TheAxelander/OpenBudgeteer/issues/124)
4+
* [Fixed] Proper reset of values after deleting an Import Profile [#125](https://github.com/TheAxelander/OpenBudgeteer/issues/125)
5+
* [Fixed] Overall improved and fixed error handling on Import Page
6+
17
### 1.6.2 (2023-01-11)
28

39
* [Fixed] Due to implemented fix for [#114](https://github.com/TheAxelander/OpenBudgeteer/issues/114) Column mapping on Import Page was not working properly [#121](https://github.com/TheAxelander/OpenBudgeteer/issues/121) [#122](https://github.com/TheAxelander/OpenBudgeteer/issues/122)

OpenBudgeteer.Blazor/Pages/Import.razor

Lines changed: 66 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,20 @@
5050
<div class="mb-3">
5151
@if (_step4Enabled)
5252
{
53-
<button class="btn btn-sm btn-primary header-action-button" @onclick=@(() => HandleResult(_dataContext.CreateProfile()))>Create Profile</button>
53+
<button class="btn btn-sm btn-primary header-action-button" @onclick=@(() => HandleResult(_dataContext.CreateProfile(), "Profile has been created."))>Create Profile</button>
5454
}
55-
@if (_dataContext.SelectedImportProfile != null && _dataContext.SelectedImportProfile.ImportProfileId != 0)
55+
@if (_dataContext.SelectedImportProfile is {ImportProfileId: > 0 })
5656
{
57-
<button class="btn btn-sm btn-primary header-action-button" @onclick=@(() => HandleResult(_dataContext.SaveProfile()))>Save Profile</button>
58-
<button class="btn btn-sm btn-danger header-action-button" @onclick=@(() => HandleResult(_dataContext.DeleteProfile()))>Delete Profile</button>
57+
<button class="btn btn-sm btn-primary header-action-button" @onclick=@(() => HandleResult(_dataContext.SaveProfile(), "Changes for Profile have been saved."))>Save Profile</button>
58+
<button class="btn btn-sm btn-danger header-action-button" @onclick=@(() => _isDeleteConfirmationDialogVisible = true)>Delete Profile</button>
5959
}
6060
</div>
6161
<div class="row mb-3">
6262
<div class="col">
6363
<label class="form-label">Import Profile:</label>
6464
<ObjectSelect
6565
GetSelectedItemIdHandler="@(e => e.ImportProfileId.ToString())"
66-
SetSelectedItemHandler="@(e => _dataContext.AvailableImportProfiles.FirstOrDefault(i => i.ImportProfileId == Convert.ToInt32(e), dummyImportProfile))"
66+
SetSelectedItemHandler="@(e => _dataContext.AvailableImportProfiles.FirstOrDefault(i => i.ImportProfileId == Convert.ToInt32(e), _dummyImportProfile))"
6767
@bind-SelectedItem="@_dataContext.SelectedImportProfile"
6868
AvailableItems="@_dataContext.AvailableImportProfiles"
6969
OnSelectedItemChanged="@ImportProfile_SelectionChanged"
@@ -81,7 +81,7 @@
8181
<label class="form-label">Target Account:</label>
8282
<ObjectSelect
8383
GetSelectedItemIdHandler="@(e => e.AccountId.ToString())"
84-
SetSelectedItemHandler="@(e => _dataContext.AvailableAccounts.FirstOrDefault(i => i.AccountId == Convert.ToInt32(e), dummyAccount))"
84+
SetSelectedItemHandler="@(e => _dataContext.AvailableAccounts.FirstOrDefault(i => i.AccountId == Convert.ToInt32(e), _dummyAccount))"
8585
@bind-SelectedItem="@_dataContext.SelectedAccount"
8686
AvailableItems="@_dataContext.AvailableAccounts"
8787
OnSelectedItemChanged="@TargetAccount_SelectionChanged"
@@ -452,6 +452,21 @@
452452
<div class="modal-backdrop fade show"></div>
453453
}
454454

455+
<InfoDialog
456+
Title="Import"
457+
Message="@_infoDialogMessage"
458+
IsDialogVisible="@_isInfoDialogVisible"
459+
OnCloseClickCallback="@(() => _isInfoDialogVisible = false)"
460+
/>
461+
462+
<DeleteConfirmationDialog
463+
Title="Delete Import Profile"
464+
Message="Do you really want to delete the selected Import Profile?"
465+
IsDialogVisible="@_isDeleteConfirmationDialogVisible"
466+
OnDeleteClickCallback="@DeleteProfile"
467+
OnCancelClickCallback="@(() => _isDeleteConfirmationDialogVisible = false)"
468+
/>
469+
455470
<ErrorMessageDialog
456471
Title="Import"
457472
Message="@_errorModalDialogMessage"
@@ -464,20 +479,22 @@
464479
ElementReference _inputElement;
465480
ElementReference _step1AccordionButtonElement;
466481

467-
readonly int _placeholderItemId = -1;
468-
readonly string _placeholderItemValue = "___PlaceholderItem___";
482+
const int PlaceholderItemId = -1;
483+
const string PlaceholderItemValue = "___PlaceholderItem___";
484+
const string DummyColumn = "---Select Column---";
469485

470-
ImportProfile dummyImportProfile = new ImportProfile()
486+
readonly ImportProfile _dummyImportProfile = new()
471487
{
472-
ImportProfileId = -1,
473-
ProfileName = "---Select Import Profile---"
488+
ImportProfileId = PlaceholderItemId,
489+
ProfileName = "---Select Import Profile---",
490+
AccountId = PlaceholderItemId
474491
};
475-
OpenBudgeteer.Core.Models.Account dummyAccount = new OpenBudgeteer.Core.Models.Account()
492+
493+
readonly OpenBudgeteer.Core.Models.Account _dummyAccount = new()
476494
{
477-
AccountId = -1,
495+
AccountId = PlaceholderItemId,
478496
Name = "---Select Target Account---"
479497
};
480-
string dummyColumn = "---Select Column---";
481498

482499
bool _step2Enabled;
483500
bool _step3Enabled;
@@ -492,6 +509,11 @@
492509
bool _isConfirmationModalDialogVisible;
493510
string _importConfirmationMessage;
494511

512+
bool _isInfoDialogVisible;
513+
string _infoDialogMessage;
514+
515+
bool _isDeleteConfirmationDialogVisible;
516+
495517
bool _isErrorModalDialogVisible;
496518
string _errorModalDialogMessage;
497519

@@ -514,21 +536,21 @@
514536
void LoadData()
515537
{
516538
HandleResult(_dataContext.LoadData());
517-
_dataContext.AvailableImportProfiles.Insert(0, dummyImportProfile);
518-
_dataContext.AvailableAccounts.Insert(0, dummyAccount);
519-
_dataContext.SelectedImportProfile = dummyImportProfile;
520-
_dataContext.IdentifiedColumns.Insert(0, dummyColumn);
521-
_dataContext.SelectedAccount = dummyAccount;
539+
_dataContext.AvailableImportProfiles.Insert(0, _dummyImportProfile);
540+
_dataContext.AvailableAccounts.Insert(0, _dummyAccount);
541+
_dataContext.SelectedImportProfile = _dummyImportProfile;
542+
_dataContext.IdentifiedColumns.Insert(0, DummyColumn);
543+
_dataContext.SelectedAccount = _dummyAccount;
522544
}
523545

524546
async Task ReadFileAsync()
525547
{
526548
_step2Enabled = false;
527549
_step3Enabled = false;
528550
_step4Enabled = false;
529-
_dataContext.SelectedImportProfile = dummyImportProfile;
530-
_dataContext.IdentifiedColumns.Insert(0, dummyColumn);
531-
_dataContext.SelectedAccount = dummyAccount;
551+
_dataContext.SelectedImportProfile = _dummyImportProfile;
552+
_dataContext.IdentifiedColumns.Insert(0, DummyColumn);
553+
_dataContext.SelectedAccount = _dummyAccount;
532554

533555
var file = (await FileReaderService.CreateReference(_inputElement).EnumerateFilesAsync()).FirstOrDefault();
534556
if (file == null) return;
@@ -541,7 +563,7 @@
541563
var result = await _dataContext.LoadProfileAsync();
542564
if (result.IsSuccessful)
543565
{
544-
_step3Enabled = _dataContext.SelectedImportProfile.ImportProfileId != 0;
566+
_step3Enabled = _dataContext.SelectedImportProfile.ImportProfileId > 0;
545567
CheckColumnMapping();
546568
StateHasChanged();
547569
}
@@ -551,6 +573,18 @@
551573
}
552574
}
553575

576+
void DeleteProfile()
577+
{
578+
_isDeleteConfirmationDialogVisible = false;
579+
HandleResult(_dataContext.DeleteProfile());
580+
if (_dataContext.SelectedImportProfile.ImportProfileId < 1)
581+
{
582+
_dataContext.SelectedImportProfile = _dummyImportProfile;
583+
_dataContext.AvailableImportProfiles.Insert(0, _dummyImportProfile);
584+
_dataContext.SelectedAccount = _dummyAccount;
585+
}
586+
}
587+
554588
void LoadHeaders()
555589
{
556590
var result = _dataContext.LoadHeaders();
@@ -568,13 +602,13 @@
568602
{
569603
_step4Enabled = false;
570604
if (string.IsNullOrEmpty(_dataContext.SelectedImportProfile.TransactionDateColumnName) ||
571-
_dataContext.SelectedImportProfile.TransactionDateColumnName == _placeholderItemValue) return;
605+
_dataContext.SelectedImportProfile.TransactionDateColumnName == PlaceholderItemValue) return;
572606
// Make Payee optional
573607
//if (string.IsNullOrEmpty(_dataContext.PayeeColumn) || _dataContext.PayeeColumn == _placeholderItemValue) return;
574608
if (string.IsNullOrEmpty(_dataContext.SelectedImportProfile.MemoColumnName) ||
575-
_dataContext.SelectedImportProfile.MemoColumnName == _placeholderItemValue) return;
609+
_dataContext.SelectedImportProfile.MemoColumnName == PlaceholderItemValue) return;
576610
if (string.IsNullOrEmpty(_dataContext.SelectedImportProfile.AmountColumnName) ||
577-
_dataContext.SelectedImportProfile.AmountColumnName == _placeholderItemValue) return;
611+
_dataContext.SelectedImportProfile.AmountColumnName == PlaceholderItemValue) return;
578612
_step4Enabled = true;
579613
}
580614

@@ -646,12 +680,17 @@
646680
_dataContext.SelectedImportProfile.AdditionalSettingCreditValue = value;
647681
}
648682

649-
void HandleResult(ViewModelOperationResult result)
683+
void HandleResult(ViewModelOperationResult result, string successMessage = "")
650684
{
651685
if (!result.IsSuccessful)
652686
{
653687
_errorModalDialogMessage = result.Message;
654688
_isErrorModalDialogVisible = true;
689+
return;
655690
}
691+
if (string.IsNullOrEmpty(successMessage)) return;
692+
693+
_infoDialogMessage = successMessage;
694+
_isInfoDialogVisible = true;
656695
}
657696
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
@if (IsDialogVisible)
2+
{
3+
<div class="modal fade show" style="display: block;">
4+
<div class="modal-dialog modal-dialog-scrollable">
5+
<div class="modal-content">
6+
<div class="modal-header">
7+
<h4 class="modal-title">@Title</h4>
8+
<button type="button" class="btn-close" data-dismiss="modal" @onclick="OnCloseClickCallback"></button>
9+
</div>
10+
<div class="modal-body">@Message</div>
11+
<div class="modal-footer">
12+
<button type="button" class="btn btn-primary" data-dismiss="modal" @onclick="OnCloseClickCallback">Ok</button>
13+
</div>
14+
</div>
15+
</div>
16+
</div>
17+
<div class="modal-backdrop fade show"></div>
18+
}
19+
20+
@code {
21+
[Parameter]
22+
public string Title { get; set; }
23+
24+
[Parameter]
25+
public string Message { get; set; }
26+
27+
[Parameter]
28+
public bool IsDialogVisible { get; set; }
29+
30+
[Parameter]
31+
public EventCallback<MouseEventArgs> OnCloseClickCallback { get; set; }
32+
}

OpenBudgeteer.Blazor/Shared/NavMenu.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
<div class="col-md-auto">
6262
<div class="navbar-text">
6363
<span>
64-
Version: 1.6.2 (<a href="https://github.com/TheAxelander/OpenBudgeteer/blob/master/CHANGELOG.md" target="_blank">Change Log</a>)
64+
Version: 1.6.3 (<a href="https://github.com/TheAxelander/OpenBudgeteer/blob/master/CHANGELOG.md" target="_blank">Change Log</a>)
6565
</span>
6666
</div>
6767
</div>

OpenBudgeteer.Core/ViewModels/ImportDataViewModel.cs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ public ImportProfile SelectedImportProfile
178178
{
179179
// Load Headers already to prevent hiccups with other SelectedItem properties from Column Mappings
180180
// as they depend on SelectedImportProfile
181-
if (value != null) LoadHeaders(value);
181+
if (value is { HeaderRow: > 0 }) LoadHeaders(value);
182182
Set(ref _selectedImportProfile, value);
183183
}
184184
}
@@ -433,18 +433,12 @@ public ViewModelOperationResult LoadHeaders()
433433
// If possible and necessary make initial selections after loading headers
434434
if (IdentifiedColumns.Count == 0) return result;
435435
var firstSelection = IdentifiedColumns.First();
436-
if (string.IsNullOrEmpty(SelectedImportProfile.TransactionDateColumnName))
437-
SelectedImportProfile.TransactionDateColumnName = firstSelection;
438-
if (string.IsNullOrEmpty(SelectedImportProfile.PayeeColumnName))
439-
SelectedImportProfile.PayeeColumnName = firstSelection;
440-
if (string.IsNullOrEmpty(SelectedImportProfile.MemoColumnName))
441-
SelectedImportProfile.MemoColumnName = firstSelection;
442-
if (string.IsNullOrEmpty(SelectedImportProfile.AmountColumnName))
443-
SelectedImportProfile.AmountColumnName = firstSelection;
444-
if (string.IsNullOrEmpty(SelectedImportProfile.CreditColumnName))
445-
SelectedImportProfile.CreditColumnName = firstSelection;
446-
if (string.IsNullOrEmpty(SelectedImportProfile.CreditColumnIdentifierColumnName))
447-
SelectedImportProfile.CreditColumnIdentifierColumnName = firstSelection;
436+
SelectedImportProfile.TransactionDateColumnName = firstSelection;
437+
SelectedImportProfile.PayeeColumnName = firstSelection;
438+
SelectedImportProfile.MemoColumnName = firstSelection;
439+
SelectedImportProfile.AmountColumnName = firstSelection;
440+
SelectedImportProfile.CreditColumnName = firstSelection;
441+
SelectedImportProfile.CreditColumnIdentifierColumnName = firstSelection;
448442

449443
return result;
450444
}
@@ -458,13 +452,16 @@ public ViewModelOperationResult LoadHeaders(ImportProfile importProfile)
458452
{
459453
try
460454
{
455+
if (importProfile.HeaderRow < 1 || importProfile.HeaderRow > _fileLines.Length)
456+
throw new Exception("Cannot read headers with given header row.");
457+
461458
// Set ComboBox selection for Column Mapping
462459
IdentifiedColumns.Clear();
463460
var headerLine = _fileLines[importProfile.HeaderRow - 1];
464461
var columns = headerLine.Split(importProfile.Delimiter);
465462
foreach (var column in columns)
466463
{
467-
if (column != string.Empty)
464+
if (!string.IsNullOrEmpty(column))
468465
IdentifiedColumns.Add(column.Trim(importProfile.TextQualifier)); // Exclude TextQualifier
469466
}
470467

@@ -502,6 +499,11 @@ public async Task<ViewModelOperationResult> ValidateDataAsync()
502499
{
503500
try
504501
{
502+
// Run pre-checks
503+
if (string.IsNullOrEmpty(SelectedImportProfile.NumberFormat)) throw new Exception("Missing Number Format");
504+
if (string.IsNullOrEmpty(SelectedImportProfile.DateFormat)) throw new Exception("Missing Date Format");
505+
if (SelectedImportProfile.AccountId < 1) throw new Exception("No target account selected");
506+
505507
// Pre-Load Data for verification
506508
// Initialize CsvReader
507509
var options = new Options(SelectedImportProfile.TextQualifier, '\\', SelectedImportProfile.Delimiter);
@@ -707,7 +709,7 @@ public ViewModelOperationResult SaveProfile()
707709
}
708710

709711
/// <summary>
710-
/// Deletes the <see cref="ImportProfile"/> in the database based on <see cref="SelectedImportProfile"/>
712+
/// Deletes the <see cref="ImportProfile"/> from the database based on <see cref="SelectedImportProfile"/>
711713
/// </summary>
712714
/// <returns>Object which contains information and results of this method</returns>
713715
public ViewModelOperationResult DeleteProfile()
@@ -718,7 +720,8 @@ public ViewModelOperationResult DeleteProfile()
718720
{
719721
dbContext.DeleteImportProfile(SelectedImportProfile);
720722
}
721-
ResetLoadedProfileData();
723+
//ResetLoadedProfileData();
724+
SelectedImportProfile = new();
722725
LoadAvailableProfiles();
723726

724727
return new ViewModelOperationResult(true);

0 commit comments

Comments
 (0)