From 8a620196b51c0ac58bf47d316e6fc9c5b4f0bba2 Mon Sep 17 00:00:00 2001 From: "kwan.nguyen" Date: Thu, 9 Jan 2025 09:02:40 +0700 Subject: [PATCH] update get and upsert banner --- PCUT/Http.Core/Constants/HttpConstants.cs | 3 + PCUT/PCUT.Entities/Banner.cs | 9 +- PCUT/PCUT.Entities/UpsertBanner.cs | 13 ++ PCUT/PCUT/PCUT.csproj | 8 ++ .../BannerManagement/BannerUpsertDialog.xaml | 43 ++++++ .../BannerUpsertDialog.xaml.cs | 38 ++++++ PCUT/PCUT/ViewModels/BannerUpsertViewModel.cs | 124 ++++++++++++++++++ PCUT/PCUT/ViewModels/BannerViewModel.cs | 77 ++++++++++- 8 files changed, 313 insertions(+), 2 deletions(-) create mode 100644 PCUT/PCUT.Entities/UpsertBanner.cs create mode 100644 PCUT/PCUT/Pages/BannerManagement/BannerUpsertDialog.xaml create mode 100644 PCUT/PCUT/Pages/BannerManagement/BannerUpsertDialog.xaml.cs create mode 100644 PCUT/PCUT/ViewModels/BannerUpsertViewModel.cs 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 {