Skip to content

Commit effe369

Browse files
completed validation rules (#397)
1 parent 317c8e8 commit effe369

File tree

4 files changed

+111
-11
lines changed

4 files changed

+111
-11
lines changed

Panzerfaust/Service/ProjectService.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ namespace Panzerfaust.Service
1010
{
1111
internal class ProjectService : IProjectService
1212
{
13-
private const string _cachePath = "./Cache";
14-
private const string _fileExtension = ".pzf";
13+
private readonly string _cachePath = Path.Combine(".", "Cache");
14+
private readonly string _fileExtension = ".pzf";
1515

1616
private void EnsureCacheDirectoryIsPresent()
1717
{
@@ -27,7 +27,7 @@ private void EnsureCacheDirectoryIsPresent()
2727

2828
Project p = new() { Name = name, Fullpath = path, CreationDate = creationTime, UpdateDate = updateTime };
2929

30-
using var fs = File.OpenWrite($"{_cachePath}/{p.GetHash()}{_fileExtension}");
30+
using var fs = File.OpenWrite(Path.Combine(_cachePath, $"{p.GetHash()}{_fileExtension}"));
3131
await JsonSerializer.SerializeAsync(fs, p).ConfigureAwait(false);
3232
return p;
3333
}
@@ -57,7 +57,7 @@ public async Task SaveAsync(Project p)
5757
{
5858
EnsureCacheDirectoryIsPresent();
5959

60-
using var fs = File.OpenWrite($"{_cachePath}/{p.GetHash()}{_fileExtension}");
60+
using var fs = File.OpenWrite(Path.Combine(_cachePath, $"{p.GetHash()}{_fileExtension}"));
6161
await JsonSerializer.SerializeAsync(fs, p).ConfigureAwait(false);
6262
}
6363

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
using ReactiveUI;
2+
using System;
3+
using System.Collections;
4+
using System.Collections.Generic;
5+
using System.ComponentModel;
6+
using System.Linq;
7+
using System.Text;
8+
using System.Text.RegularExpressions;
9+
using System.Threading.Tasks;
10+
using System.Xml.Linq;
11+
12+
namespace Panzerfaust.ViewModels
13+
{
14+
internal partial class ProjectWindowViewModel : INotifyDataErrorInfo
15+
{
16+
private Dictionary<string, List<string>> _errors = new();
17+
18+
public bool HasErrors => _errors.Count > 0;
19+
20+
public event EventHandler<DataErrorsChangedEventArgs>? ErrorsChanged;
21+
22+
public IEnumerable GetErrors(string? propertyName)
23+
{
24+
if ((propertyName != null) && _errors.ContainsKey(propertyName))
25+
{
26+
return _errors[propertyName];
27+
}
28+
return new List<string>();
29+
}
30+
31+
private void ValidateProjectName(string? name)
32+
{
33+
if (_errors.ContainsKey(nameof(ProjectName)))
34+
{
35+
_errors[nameof(ProjectName)].Clear();
36+
}
37+
38+
if (string.IsNullOrEmpty(name))
39+
{
40+
_errors[nameof(ProjectName)] = new() { "Name can't be empty" };
41+
}
42+
else if (string.IsNullOrWhiteSpace(name))
43+
{
44+
_errors[nameof(ProjectName)] = new() { "Name can't contain only whitespaces" };
45+
}
46+
else if (Regex.IsMatch(name, @"[\s\W]+"))
47+
{
48+
_errors[nameof(ProjectName)] = new() { "Name can't contain special characters or whitespace." };
49+
}
50+
51+
this.RaisePropertyChanged(nameof(HasErrors));
52+
}
53+
54+
private void ValidateProjectLocation(string? location)
55+
{
56+
if (_errors.ContainsKey(nameof(ProjectLocation)))
57+
{
58+
_errors[nameof(ProjectLocation)].Clear();
59+
}
60+
61+
if (string.IsNullOrEmpty(location))
62+
{
63+
_errors[nameof(ProjectLocation)] = new() { "Location can't be empty" };
64+
}
65+
else if (string.IsNullOrWhiteSpace(location))
66+
{
67+
_errors[nameof(ProjectLocation)] = new() { "Location can't contain only whitespaces" };
68+
}
69+
70+
if (!Directory.Exists(location))
71+
{
72+
_errors[nameof(ProjectLocation)] = new() { "This location isn't valid" };
73+
}
74+
75+
this.RaisePropertyChanged(nameof(HasErrors));
76+
}
77+
}
78+
}

Panzerfaust/ViewModels/ProjectWindowViewModel.cs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using ReactiveUI;
44
using System;
55
using System.Collections.Generic;
6+
using System.ComponentModel;
67
using System.Linq;
78
using System.Reactive;
89
using System.Reactive.Linq;
@@ -13,17 +14,35 @@
1314

1415
namespace Panzerfaust.ViewModels
1516
{
16-
internal class ProjectWindowViewModel : ViewModelBase
17+
internal partial class ProjectWindowViewModel : ViewModelBase
1718
{
1819
private bool _isBusy = false;
1920
private string? _projectName = string.Empty;
20-
private string? _projectLocation = string.Empty;
21+
private string? _projectLocation = Directory.GetCurrentDirectory();
2122
private string? _progressReportText = string.Empty;
2223
private string _progressReportTextColor = "White";
2324

2425
public bool IsBusy { get => _isBusy; set => this.RaiseAndSetIfChanged(ref _isBusy, value); }
25-
public string? ProjectName { get => _projectName; set => this.RaiseAndSetIfChanged(ref _projectName, value); }
26-
public string? ProjectLocation { get => _projectLocation; set => this.RaiseAndSetIfChanged(ref _projectLocation, value); }
26+
public string? ProjectName
27+
{
28+
get => _projectName;
29+
set
30+
{
31+
ValidateProjectName(value);
32+
this.RaiseAndSetIfChanged(ref _projectName, value);
33+
}
34+
}
35+
36+
public string? ProjectLocation
37+
{
38+
get => _projectLocation;
39+
set
40+
{
41+
ValidateProjectLocation(value);
42+
this.RaiseAndSetIfChanged(ref _projectLocation, value);
43+
}
44+
}
45+
2746
public string? ProgressReportText { get => _progressReportText; set => this.RaiseAndSetIfChanged(ref _progressReportText, value); }
2847
public string ProgressReportTextColor { get => _progressReportTextColor; set => this.RaiseAndSetIfChanged(ref _progressReportTextColor, value); }
2948

@@ -36,7 +55,7 @@ public ProjectWindowViewModel()
3655
DirectoryDialogCommand = ReactiveCommand.CreateFromTask(OnDirectoryDialogCommandHandler);
3756
CancelCommand = ReactiveCommand.Create(OnCancelCommandHandler);
3857
FinishCommand = ReactiveCommand.CreateFromTask(OnFinishCommandHandler,
39-
this.WhenAnyValue(x => x.ProjectName, x => x.ProjectLocation, (name, location) => !(string.IsNullOrEmpty(name) || string.IsNullOrEmpty(location))));
58+
this.WhenAnyValue(x => x.ProjectName, x => x.ProjectLocation, x => x.HasErrors, (name, location, hasErrors) => !(string.IsNullOrEmpty(name) || string.IsNullOrEmpty(location) || hasErrors)));
4059
}
4160

4261
private async Task OnDirectoryDialogCommandHandler()

Panzerfaust/Views/CreateProjectView.axaml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@
1313
<Button Content="Cancel" Command="{Binding CancelCommand}"/>
1414
<Button Content="Finish" Background="Green" Command="{Binding FinishCommand}" IsEnabled="{Binding FinishCommand.CanExecute}"/>
1515
</StackPanel>
16-
<ProgressBar DockPanel.Dock="Bottom" HorizontalAlignment="Stretch" VerticalAlignment="Center" Margin="0, 0, 0, 20" IsIndeterminate="{Binding IsBusy}" Foreground="{Binding ProgressReportTextColor}" />
16+
<ProgressBar DockPanel.Dock="Bottom"
17+
HorizontalAlignment="Stretch" VerticalAlignment="Center"
18+
Margin="0, 0, 0, 20" IsIndeterminate="{Binding IsBusy}"
19+
Foreground="{Binding ProgressReportTextColor}" />
1720
<TextBlock Text="{Binding ProgressReportText}" DockPanel.Dock="Bottom" HorizontalAlignment="Stretch" FontWeight="Light" VerticalAlignment="Center" Margin="0, 0, 0, 8" Foreground=""/>
1821
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Stretch" Spacing="15">
1922
<TextBlock Text="Project name" />
20-
<TextBox Watermark="Enter a project name" CornerRadius="5" HorizontalAlignment="Stretch" Text="{Binding ProjectName, Mode=TwoWay}"/>
23+
<TextBox Watermark="Enter a project name" CornerRadius="5" HorizontalAlignment="Stretch" Text="{Binding ProjectName, Mode=TwoWay}" />
2124
<TextBlock Text="Location" />
2225
<Grid HorizontalAlignment="Stretch">
2326
<TextBox Watermark="" CornerRadius="5" HorizontalAlignment="Stretch" Text="{Binding ProjectLocation, Mode=TwoWay}"/>

0 commit comments

Comments
 (0)