Skip to content

Commit 4ff505d

Browse files
committed
search add
1 parent edb2b8b commit 4ff505d

File tree

4 files changed

+110
-25
lines changed

4 files changed

+110
-25
lines changed

src/dataneo.TutorialLibs.Domain/Tutorials/Specifications/TutorialSearchSpecification.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ namespace dataneo.TutorialLibs.Domain.Tutorials.Specifications
88
{
99
public class TutorialSearchSpecification : Specification<Tutorial>
1010
{
11+
public TutorialSearchSpecification()
12+
{
13+
Query.AsNoTracking();
14+
}
15+
1116
public TutorialSearchSpecification FilterByCategories(IEnumerable<Category> categories, bool filterWithNoCategory = true)
1217
{
1318
Guard.Against.Null(categories, nameof(categories));
@@ -39,8 +44,9 @@ public TutorialSearchSpecification TutorialTitleSearch(string title)
3944
{
4045
if (string.IsNullOrWhiteSpace(title))
4146
return this;
47+
var titleLowered = title.ToLower();
4248

43-
Query.Where(w => w.Name.Contains(title));
49+
Query.Where(w => w.Name.ToLower().Contains(titleLowered));
4450

4551
return this;
4652
}

src/dataneo.TutorialsLib.WPF/Resources/Global.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
22
<SolidColorBrush x:Key="foreGround">#B2B1B0</SolidColorBrush>
33
<SolidColorBrush x:Key="backGround">#1A1A17</SolidColorBrush>
4+
<SolidColorBrush x:Key="drawingLines">#1E1A1A</SolidColorBrush>
45
<SolidColorBrush x:Key="btnNavColot" Color="#464646" />
56
<Style x:Key="button" TargetType="{x:Type Button}">
67
<Setter Property="Background" Value="#353535" />

src/dataneo.TutorialsLib.WPF/UI/TutorialList/TutorialListPage.xaml

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -205,15 +205,23 @@
205205
<StackPanel
206206
Grid.Row="1"
207207
Grid.Column="0"
208-
Margin="4,2"
208+
Margin="4,2,0,4"
209209
Orientation="Horizontal">
210210
<TextBox
211211
x:Name="tbSearch"
212212
Width="240"
213213
FontSize="16"
214-
Style="{StaticResource textBoxGlobalStyle}" />
214+
Style="{StaticResource textBoxGlobalStyle}"
215+
Text="{Binding Path=SearchTitle, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
216+
<Behaviors:Interaction.Triggers>
217+
<Behaviors:EventTrigger EventName="KeyDown">
218+
<Behaviors:InvokeCommandAction Command="{Binding SearchPrevCommand}" PassEventArgsToCommand="True" />
219+
</Behaviors:EventTrigger>
220+
</Behaviors:Interaction.Triggers>
221+
</TextBox>
215222
<Button
216223
Margin="2,0"
224+
Command="{Binding Path=SearchCommand, Mode=OneTime}"
217225
Cursor="Hand"
218226
Style="{StaticResource button}">
219227
<StackPanel Orientation="Horizontal">
@@ -222,14 +230,14 @@
222230
Canvas.Left="9"
223231
Canvas.Top="5.8"
224232
Data="M 4,7 L 10,15"
225-
Stroke="#1E1A1A"
233+
Stroke="{StaticResource drawingLines}"
226234
StrokeThickness="2" />
227235
<Ellipse
228236
Canvas.Left="2"
229237
Canvas.Top="2"
230238
Width="14"
231239
Height="14"
232-
Stroke="#1E1A1A"
240+
Stroke="{StaticResource drawingLines}"
233241
StrokeThickness="2" />
234242
</Canvas>
235243
<TextBlock
@@ -241,6 +249,7 @@
241249
</StackPanel>
242250
</Button>
243251
<Button
252+
Command="{Binding Path=PrevPageCommand, Mode=OneTime}"
244253
Cursor="Hand"
245254
Style="{StaticResource button}"
246255
ToolTip="{x:Static lang:UI.PREV_PAGE}">
@@ -249,7 +258,7 @@
249258
Canvas.Left="18"
250259
Canvas.Top="4"
251260
Data="M 0,0 L -12,8 L 0 16"
252-
Stroke="#1E1A1A"
261+
Stroke="{StaticResource drawingLines}"
253262
StrokeThickness="2" />
254263
</Canvas>
255264
</Button>
@@ -260,15 +269,21 @@
260269
VerticalContentAlignment="Center"
261270
FontSize="15"
262271
Style="{StaticResource textBoxGlobalStyle}"
263-
Text="1">
272+
Text="{Binding Path=Page, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
264273
<Behaviors:Interaction.Behaviors>
265274
<local:TextBoxInputRegExBehaviour
266275
EmptyValue="1"
267276
MaxLength="2"
268277
RegularExpression="^\d+$" />
269278
</Behaviors:Interaction.Behaviors>
279+
<Behaviors:Interaction.Triggers>
280+
<Behaviors:EventTrigger EventName="KeyDown">
281+
<Behaviors:InvokeCommandAction Command="{Binding PageNoEnterCommand}" PassEventArgsToCommand="True" />
282+
</Behaviors:EventTrigger>
283+
</Behaviors:Interaction.Triggers>
270284
</TextBox>
271285
<Button
286+
Command="{Binding Path=NextPageCommand, Mode=OneTime}"
272287
Cursor="Hand"
273288
Style="{StaticResource button}"
274289
ToolTip="{x:Static lang:UI.NEXT_PAGE}">
@@ -277,13 +292,13 @@
277292
Canvas.Left="6"
278293
Canvas.Top="4"
279294
Data="M 0,0 L 12,8 L 0 16"
280-
Stroke="#1E1A1A"
295+
Stroke="{StaticResource drawingLines}"
281296
StrokeThickness="2" />
282297
</Canvas>
283298
</Button>
284299
<TextBlock Margin="4,0" VerticalAlignment="Center">
285300
<Run Text="/" />
286-
<Run Text="12" />
301+
<Run Text="{Binding Path=TotalPage, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
287302
</TextBlock>
288303
</StackPanel>
289304
<ListView
@@ -493,14 +508,14 @@
493508
Canvas.Left="9"
494509
Canvas.Top="5.8"
495510
Data="M 0,0 L 0,12 L 8, 6 L 0, 0"
496-
Stroke="#1E1A1A"
511+
Stroke="{StaticResource drawingLines}"
497512
StrokeThickness="2" />
498513
<Ellipse
499514
Canvas.Left="0"
500515
Canvas.Top="0"
501516
Width="24"
502517
Height="24"
503-
Stroke="#1E1A1A"
518+
Stroke="{StaticResource drawingLines}"
504519
StrokeThickness="2" />
505520
</Canvas>
506521
<TextBlock

src/dataneo.TutorialsLib.WPF/UI/TutorialList/TutorialListPageViewModel.cs

Lines changed: 77 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using Prism.Services.Dialogs;
1313
using System;
1414
using System.Collections.Generic;
15+
using System.Collections.ObjectModel;
1516
using System.Linq;
1617
using System.Threading.Tasks;
1718
using System.Windows.Input;
@@ -20,18 +21,18 @@ namespace dataneo.TutorialLibs.WPF.UI.TutorialList
2021
{
2122
internal sealed class TutorialListPageViewModel : BaseViewModel
2223
{
23-
private const short TutorialOnPage = 40;
24+
private const short TutorialOnPage = 20;
2425

2526
private readonly IDialogService _dialogService;
2627
private readonly ITutorialRespositoryAsync _tutorialRespositoryAsync;
2728
private readonly ICategoryRespositoryAsync _categoryRespositoryAsync;
2829
private readonly IAddTutorial _addTutorial;
2930
private readonly ISettingManager _settingManager;
3031

31-
public readonly CategoryManager CategoriesManager;
32+
public CategoryManager CategoriesManager { get; }
3233

33-
private IEnumerable<TutorialHeaderDto> tutorials;
34-
public IEnumerable<TutorialHeaderDto> Tutorials
34+
private ObservableCollection<TutorialHeaderDto> tutorials = new ObservableCollection<TutorialHeaderDto>();
35+
public ObservableCollection<TutorialHeaderDto> Tutorials
3536
{
3637
get { return tutorials; }
3738
set { tutorials = value; RaisePropertyChanged(); }
@@ -62,6 +63,13 @@ public IEnumerable<CategoryMenuItem> TutorialCategories
6263
set { _tutorialCategories = value; RaisePropertyChanged(); }
6364
}
6465

66+
private string searchTitle;
67+
public string SearchTitle
68+
{
69+
get { return searchTitle; }
70+
set { searchTitle = value; RaisePropertyChanged(); }
71+
}
72+
6573
private short page;
6674
public short Page
6775
{
@@ -111,6 +119,11 @@ public short TotalPage
111119
public ICommand DeleteTutorialCommand { get; }
112120
public ICommand ShowTutorialCategoriesCommand { get; }
113121
public ICommand TutorialCategoriesChangedCommand { get; }
122+
public ICommand NextPageCommand { get; }
123+
public ICommand PrevPageCommand { get; }
124+
public ICommand SearchCommand { get; }
125+
public ICommand SearchPrevCommand { get; }
126+
public ICommand PageNoEnterCommand { get; }
114127

115128
public TutorialListPageViewModel(IRegionManager regionManager,
116129
IDialogService dialogService,
@@ -137,6 +150,11 @@ public TutorialListPageViewModel(IRegionManager regionManager,
137150
this.SetTutorialAsUnWatchedCommand = new Command(SetTutorialAsUnWatchedCommandImpl);
138151
this.ShowTutorialCategoriesCommand = new Command(ShowTutorialCategoriesCommandImpl);
139152
this.TutorialCategoriesChangedCommand = new Command(TutorialCategoriesChangedCommandImpl);
153+
this.NextPageCommand = new Command(NextPageCommandImplAsync);
154+
this.PrevPageCommand = new Command(PrevPageCommandImplAsync);
155+
this.SearchCommand = new Command(SearchCommandImplAsync);
156+
this.SearchPrevCommand = new Command<KeyEventArgs>(SearchPrevCommandImplAsync);
157+
this.PageNoEnterCommand = new Command<KeyEventArgs>(PageNoEnterCommandImplAsync);
140158
}
141159

142160
public async override void OnNavigatedTo(NavigationContext navigationContext)
@@ -190,6 +208,40 @@ private void ShowTutorialCategoriesCommandImpl()
190208
this.TutorialCategories = GetCategoryMenuItem(this.SelectedTutorial, this.CategoriesManager.Categories);
191209
}
192210

211+
private async void PrevPageCommandImplAsync()
212+
{
213+
await Result.Try(() => LoadTutorialsDtoAsync(this.Page - 1))
214+
.OnFailure(error => ShowError(error));
215+
}
216+
217+
private async void NextPageCommandImplAsync()
218+
{
219+
await Result.Try(() => LoadTutorialsDtoAsync(this.Page + 1))
220+
.OnFailure(error => ShowError(error));
221+
}
222+
223+
private async void SearchCommandImplAsync()
224+
{
225+
await Result.Try(LoadTutorialsDtoAsync)
226+
.OnFailure(error => ShowError(error));
227+
}
228+
229+
private async void SearchPrevCommandImplAsync(KeyEventArgs obj)
230+
{
231+
if (obj.Key != Key.Enter)
232+
return;
233+
await Result.Try(LoadTutorialsDtoAsync)
234+
.OnFailure(error => ShowError(error));
235+
}
236+
237+
private async void PageNoEnterCommandImplAsync(KeyEventArgs obj)
238+
{
239+
if (obj.Key != Key.Enter)
240+
return;
241+
await Result.Try(() => LoadTutorialsDtoAsync(this.Page))
242+
.OnFailure(error => ShowError(error));
243+
}
244+
193245
private IReadOnlyList<CategoryMenuItem> GetCategoryMenuItem(TutorialHeaderDto tutorialHeaderDto,
194246
IEnumerable<CategoryMenuItem> categoryMenuItems)
195247
{
@@ -231,8 +283,11 @@ private async void TutorialCategoriesChangedCommandImpl()
231283
private void UpdateTutorialDtoCategories(IReadOnlyList<Category> newTutorialCategories, TutorialHeaderDto tutorialHeaderDto)
232284
{
233285
var newTutorialDto = tutorialHeaderDto with { Categories = newTutorialCategories };
234-
this.Tutorials = this.Tutorials.Select(s => s == tutorialHeaderDto ? newTutorialDto : s)
286+
var newTutorials = this.Tutorials.Select(s => s == tutorialHeaderDto ? newTutorialDto : s)
235287
.ToArray();
288+
289+
this.Tutorials.Clear();
290+
this.Tutorials.AddRange(newTutorials);
236291
}
237292

238293
private async Task UpdateTutorialCategoriesAsync(IReadOnlyList<Category> newTutorialCategories, TutorialHeaderDto tutorialHeaderDto)
@@ -245,33 +300,41 @@ private async Task UpdateTutorialCategoriesAsync(IReadOnlyList<Category> newTuto
245300
private async Task LoadCategoriesAndTutorialsonSelectionChangeAsync()
246301
{
247302
await this.CategoriesManager.LoadCategoriesAsync();
248-
await LoadTutorialsDtoAsync();
303+
await LoadTutorialsDtoAsync(this.Page);
249304
}
250305

251-
private async Task LoadTutorialsDtoAsync()
306+
private Task LoadTutorialsDtoAsync()
307+
=> LoadTutorialsDtoAsync(Maybe<int>.None);
308+
309+
private async Task LoadTutorialsDtoAsync(Maybe<int> page)
252310
{
253-
var specificationCount = GetSpecificationAccToFilterSelect();
254-
var totalRecords = await this._tutorialRespositoryAsync.CountAsync(specificationCount);
255-
this.TotalPage = (short)Math.Ceiling(totalRecords / (double)TutorialOnPage);
256-
this.Page = 1;
311+
if (page.HasNoValue)
312+
{
313+
var specificationCount = GetSpecificationAccToFilterSelect();
314+
var totalRecords = await this._tutorialRespositoryAsync.CountAsync(specificationCount);
315+
this.TotalPage = (short)Math.Ceiling(totalRecords / (double)TutorialOnPage);
316+
}
317+
318+
this.Page = (short)page.GetValueOrDefault(1);
257319
var specification = GetSpecificationAccToFilterSelect(this.Page);
258-
this.Tutorials = await this._tutorialRespositoryAsync.GetAllTutorialHeadersDtoAsync(specification);
320+
this.Tutorials.Clear();
321+
this.Tutorials.AddRange(await this._tutorialRespositoryAsync.GetAllTutorialHeadersDtoAsync(specification));
259322
}
260323

261324
private ISpecification<Tutorial> GetSpecificationAccToFilterSelect(short? page = null)
262325
{
263326
var specBuilder = new SpecificationBuilder();
264327
specBuilder
265328
.FilterByCategories(this.CategoriesManager.GetFilteredCategories(),
266-
this.CategoriesManager.IsFilterByNoCategory());
329+
this.CategoriesManager.IsFilterByNoCategory())
330+
.TutorialTitleSearch(this.SearchTitle);
267331

268332
if (page.HasValue)
269333
{
270334
specBuilder.Page(page.Value, TutorialOnPage)
271335
.OrderBy(this.SelectedTutorialsOrderType);
272336
}
273337

274-
275338
return specBuilder.GetSpecification();
276339
}
277340

0 commit comments

Comments
 (0)