diff --git a/PCUT/Http.Core/Constants/HttpConstants.cs b/PCUT/Http.Core/Constants/HttpConstants.cs
index 015904e..ec84a14 100644
--- a/PCUT/Http.Core/Constants/HttpConstants.cs
+++ b/PCUT/Http.Core/Constants/HttpConstants.cs
@@ -42,6 +42,9 @@
public const string MetadataById = "api/metadata/{0}";
public const string Log = "api/logs";
+
+ public const string Banner = "api/banners";
+ public const string BannerById = "api/banners/{0}";
}
}
}
diff --git a/PCUT/PCUT.Entities/Banner.cs b/PCUT/PCUT.Entities/Banner.cs
index 1a8afb1..d9552a7 100644
--- a/PCUT/PCUT.Entities/Banner.cs
+++ b/PCUT/PCUT.Entities/Banner.cs
@@ -1,4 +1,5 @@
-using System;
+using Newtonsoft.Json;
+using System;
using System.Collections.Generic;
using System.Text;
@@ -6,8 +7,14 @@ namespace PCUT.Entities
{
public class Banner
{
+
+ [JsonProperty("_id")]
public string Id { get; set; }
+
+ [JsonProperty("name")]
public string Name { get; set; }
+
+ [JsonProperty("content")]
public string Content { get; set; }
}
}
diff --git a/PCUT/PCUT.Entities/UpsertBanner.cs b/PCUT/PCUT.Entities/UpsertBanner.cs
new file mode 100644
index 0000000..4d1e4af
--- /dev/null
+++ b/PCUT/PCUT.Entities/UpsertBanner.cs
@@ -0,0 +1,13 @@
+using Newtonsoft.Json;
+
+namespace PCUT.Entities
+{
+ public class UpsertBanner
+ {
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("content")]
+ public string Content { get; set; }
+ }
+}
diff --git a/PCUT/PCUT/PCUT.csproj b/PCUT/PCUT/PCUT.csproj
index b42d793..8b50670 100644
--- a/PCUT/PCUT/PCUT.csproj
+++ b/PCUT/PCUT/PCUT.csproj
@@ -186,6 +186,9 @@
AppOutdatedDialog.xaml
+
+ BannerUpsertDialog.xaml
+
BannerViewPage.xaml
@@ -256,6 +259,7 @@
UserListPage.xaml
+
@@ -367,6 +371,10 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
diff --git a/PCUT/PCUT/Pages/BannerManagement/BannerUpsertDialog.xaml b/PCUT/PCUT/Pages/BannerManagement/BannerUpsertDialog.xaml
new file mode 100644
index 0000000..eeebe32
--- /dev/null
+++ b/PCUT/PCUT/Pages/BannerManagement/BannerUpsertDialog.xaml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PCUT/PCUT/Pages/BannerManagement/BannerUpsertDialog.xaml.cs b/PCUT/PCUT/Pages/BannerManagement/BannerUpsertDialog.xaml.cs
new file mode 100644
index 0000000..0fdd69e
--- /dev/null
+++ b/PCUT/PCUT/Pages/BannerManagement/BannerUpsertDialog.xaml.cs
@@ -0,0 +1,38 @@
+using PCUT.Entities;
+using PCUT.ViewModels;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices.WindowsRuntime;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Navigation;
+
+// The Content Dialog item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
+
+namespace PCUT.Pages.BannerManagement
+{
+ public sealed partial class BannerUpsertDialog : ContentDialog
+ {
+ private readonly BannerUpsertViewModel _context;
+ public BannerUpsertDialog(string bannerId = null)
+ {
+ this.InitializeComponent();
+ Title = bannerId is null ? "ADD BANNER" : "EDIT BANNER";
+ _context = this.DataContext as BannerUpsertViewModel;
+ _context.Initialize(bannerId);
+ }
+
+ private async void ContentDialog_Opened(ContentDialog sender, ContentDialogOpenedEventArgs args)
+ {
+ await _context.LoadAsync();
+ }
+ }
+}
diff --git a/PCUT/PCUT/ViewModels/BannerUpsertViewModel.cs b/PCUT/PCUT/ViewModels/BannerUpsertViewModel.cs
new file mode 100644
index 0000000..fbdc407
--- /dev/null
+++ b/PCUT/PCUT/ViewModels/BannerUpsertViewModel.cs
@@ -0,0 +1,124 @@
+using Http.Core.Exceptions;
+using Http.Core;
+using Http.Core.Extensions;
+using PCUT.Entities.ApiResponse;
+using PCUT.Entities;
+using PCUT.Helpers;
+using PCUT.Models;
+using System;
+using System.Threading.Tasks;
+using System.Windows.Input;
+using static Http.Core.Constants.HttpConstants;
+using System.Net.Http;
+using Windows.UI.Popups;
+
+namespace PCUT.ViewModels
+{
+ public class BannerUpsertViewModel : NotificationBase
+ {
+ private string _name;
+ public string Name
+ {
+ get => _name;
+ set { SetProperty(ref _name, value); }
+ }
+
+ private string _content;
+ public string Content
+ {
+ get => _content;
+ set { SetProperty(ref _content, value);}
+ }
+
+ private string _bannerId;
+
+ public ICommand Command { get; }
+
+ public BannerUpsertViewModel()
+ {
+ Command = new RelayCommand(async () => await UpsertBannerAsync());
+ }
+
+ public void Initialize(string bannerId)
+ {
+ _bannerId = bannerId;
+ }
+
+ public async Task LoadAsync()
+ {
+ if (_bannerId is null)
+ return;
+
+ using (var client = HttpClientFactory.CreateClient(ClientNames.ApiClient))
+ {
+ try
+ {
+ var response = await client.GetAsync(Api.BannerById.FormatRoute(_bannerId));
+ if (response.IsSuccessStatusCode)
+ {
+ var bannerData = await response.DeserializeObjectAsync>();
+ Name = bannerData.Data.Name;
+ Content = bannerData.Data.Content;
+ }
+ }
+ catch (Exception ex) when (!(ex is AppOutdatedException)) { }
+ }
+ }
+
+ public async Task UpsertBannerAsync()
+ {
+ using (var client = HttpClientFactory.CreateClient(ClientNames.ApiClient))
+ {
+ string message;
+ if (_bannerId is null)
+ message = await AddAsync(client);
+ else
+ message = await EditAsync(client);
+
+ await new MessageDialog(message).ShowAsync();
+ }
+ }
+
+ private async Task AddAsync(HttpClient client)
+ {
+ var banner = new UpsertBanner
+ {
+ Name = this.Name,
+ Content = this.Content
+ };
+ try
+ {
+ var response = await client.PostAsJsonAsync(Api.Banner, banner);
+ if (response.IsSuccessStatusCode)
+ return "Banner added successfully!";
+ else
+ return "Failed to add the banner!";
+ }
+ catch (Exception ex) when (!(ex is AppOutdatedException))
+ {
+ return $"error: {ex.Message}";
+ }
+ }
+
+ private async Task EditAsync(HttpClient client)
+ {
+ var banner = new UpsertBanner
+ {
+ Name = this.Name,
+ Content = this.Content
+ };
+ try
+ {
+ var response = await client.PutAsJsonAsync(Api.BannerById.FormatRoute(_bannerId), banner);
+ if (response.IsSuccessStatusCode)
+ return "Banner edited successfully!";
+ else
+ return "Failed to edit the banner!";
+ }
+ catch (Exception ex) when (!(ex is AppOutdatedException))
+ {
+ return $"error: {ex.Message}";
+ }
+ }
+ }
+}
diff --git a/PCUT/PCUT/ViewModels/BannerViewModel.cs b/PCUT/PCUT/ViewModels/BannerViewModel.cs
index b833bbc..582e098 100644
--- a/PCUT/PCUT/ViewModels/BannerViewModel.cs
+++ b/PCUT/PCUT/ViewModels/BannerViewModel.cs
@@ -5,13 +5,88 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Http.Core;
+using Http.Core.Extensions;
+using static Http.Core.Constants.HttpConstants;
+using Http.Core.Exceptions;
+using PCUT.Entities.ApiResponse;
+using Windows.ApplicationModel.Core;
namespace PCUT.ViewModels
{
public class BannerViewModel : NotificationBase
{
public PaginationViewModel Pagination { get; } = new PaginationViewModel(withSearch: true);
- public SelectableCollection FilteredBanners { get; }
+ public SelectableCollection FilteredBanners { get; } = new SelectableCollection();
+
+ public BannerViewModel()
+ {
+ Pagination.TextSearched += async (sender, args) => await SearchBannerAsync(args.Text);
+ Pagination.PageChanged += OnPageChanged;
+ }
+
+ public async Task Reload()
+ {
+ await LoadBannerAsync(Pagination.Page, Pagination.PageSize, Pagination.SearchText);
+ }
+
+ private async void OnPageChanged(object sender, PageChangedEventArgs args)
+ {
+ await LoadBannerAsync(args.Page, args.PageSize, Pagination.SearchText);
+ }
+
+ private async Task SearchBannerAsync(string searchText)
+ {
+ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
+ {
+ await LoadBannerAsync(Pagination.Page, Pagination.PageSize, searchText);
+ });
+ }
+
+ private async Task LoadBannerAsync(int page, int pageSize, string searchText)
+ {
+ var url = CreateFilterUrl(page, pageSize, searchText);
+ using (var httpClient = HttpClientFactory.CreateClient(ClientNames.ApiClient))
+ {
+ try
+ {
+ var response = await httpClient.GetAsync(url);
+ if (response.IsSuccessStatusCode)
+ {
+ var apiResponse = await response.DeserializeObjectAsync>>();
+ var data = apiResponse.Data;
+ Pagination.Page = apiResponse.Pagination.Page;
+ Pagination.TotalPage = apiResponse.Pagination.TotalPages;
+ Pagination.TotalRecords = apiResponse.Pagination.TotalRecords;
+
+ int displayId = (apiResponse.Pagination.Page - 1) * pageSize + 1;
+ var banners = data.Select(banner =>
+ {
+ banner.DisplayId = displayId.ToString();
+ displayId++;
+ return banner;
+ });
+ FilteredBanners.Load(banners);
+ }
+ }
+ catch (Exception ex) when (!(ex is AppOutdatedException))
+ {
+ }
+ }
+ }
+
+ private string CreateFilterUrl(int page, int pageSize, string searchText)
+ {
+ var builder = PathBuilder.FromRouteTemplate(Api.Banner)
+ .AddQuery("page", page.ToString())
+ .AddQuery("pageSize", pageSize.ToString());
+ if (!string.IsNullOrEmpty(searchText))
+ {
+ var filter = new StringBuilder().AppendFilter("name", "cn", searchText).BuildFilter().ToString();
+ builder.AddQuery("filter", filter);
+ }
+ return builder.Build();
+ }
public class BannerModel : Banner
{