integrate log api

This commit is contained in:
kwan.nguyen 2024-10-25 11:49:33 +07:00
parent 535451e59b
commit d4d6cbd94d
10 changed files with 212 additions and 13 deletions

View File

@ -40,6 +40,7 @@
public const string Metadata = "api/metadata"; public const string Metadata = "api/metadata";
public const string MetadataById = "api/metadata/{0}"; public const string MetadataById = "api/metadata/{0}";
public const string Log = "api/logs";
} }
} }
} }

View File

@ -1,7 +1,6 @@
using Http.Core.Constants; using Http.Core.Constants;
using Http.Core.Contexts; using Http.Core.Contexts;
using Http.Core.Extensions; using Http.Core.Extensions;
using Http.Core.Models;
using System; using System;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
@ -31,13 +30,13 @@ namespace Http.Core.Handlers
return false; return false;
var expiredTime = UserContext.Instance.ExpiredTime; var expiredTime = UserContext.Instance.ExpiredTime;
if (expiredTime != null || expiredTime - DateTime.UtcNow < _requiredRefreshTime) if (expiredTime != null && expiredTime - DateTime.UtcNow < _requiredRefreshTime)
{ {
await _refreshSemaphore.WaitAsync(); await _refreshSemaphore.WaitAsync();
bool refreshSuccess; bool refreshSuccess;
{ {
expiredTime = UserContext.Instance.ExpiredTime; expiredTime = UserContext.Instance.ExpiredTime;
if (expiredTime != null || expiredTime - DateTime.UtcNow < _requiredRefreshTime) if (expiredTime != null && expiredTime - DateTime.UtcNow < _requiredRefreshTime)
refreshSuccess = await RefreshTokenAsync(); refreshSuccess = await RefreshTokenAsync();
else else
refreshSuccess = true; // Some other thread already refreshed token refreshSuccess = true; // Some other thread already refreshed token

13
PCUT/PCUT.Entities/Log.cs Normal file
View File

@ -0,0 +1,13 @@
using Newtonsoft.Json;
using System;
namespace PCUT.Entities
{
public class Log
{
[JsonProperty("datetime")]
public DateTime Timestamp { get; set; }
[JsonProperty("content")]
public string Content { get; set; }
}
}

View File

@ -0,0 +1,26 @@
using System;
using Windows.UI.Xaml.Data;
namespace PCUT.Converters
{
internal class LogTimestampConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
switch (value)
{
case DateTime timeValue:
{
return $"[{timeValue.ToString("yyyy-MM-dd HH:mm:ss.fff K")}]";
}
default:
return string.Empty;
}
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
}

View File

@ -137,6 +137,7 @@
<Compile Include="Converters\BooleanInverter.cs" /> <Compile Include="Converters\BooleanInverter.cs" />
<Compile Include="Converters\BooleanToStringConverter.cs" /> <Compile Include="Converters\BooleanToStringConverter.cs" />
<Compile Include="Converters\BooleanToVisibilityConverter.cs" /> <Compile Include="Converters\BooleanToVisibilityConverter.cs" />
<Compile Include="Converters\LogTimestampConverter.cs" />
<Compile Include="Converters\OpacityConverter.cs" /> <Compile Include="Converters\OpacityConverter.cs" />
<Compile Include="Converters\UserRoleToBooleanConverter.cs" /> <Compile Include="Converters\UserRoleToBooleanConverter.cs" />
<Compile Include="Converters\UserStatusConverter.cs" /> <Compile Include="Converters\UserStatusConverter.cs" />
@ -246,6 +247,7 @@
<DependentUpon>UserListPage.xaml</DependentUpon> <DependentUpon>UserListPage.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ViewModels\LogViewModel.cs" />
<Compile Include="ViewModels\UpsertMetadataViewModel.cs" /> <Compile Include="ViewModels\UpsertMetadataViewModel.cs" />
<Compile Include="ViewModels\CategoriesViewModel.cs" /> <Compile Include="ViewModels\CategoriesViewModel.cs" />
<Compile Include="ViewModels\UpsertCategoryViewModel.cs" /> <Compile Include="ViewModels\UpsertCategoryViewModel.cs" />

View File

@ -29,7 +29,7 @@
<NavigationViewItem Icon="Document" Content="Categories" x:Name="Categories" Tag="Categories" Background="{ThemeResource SystemAccentColor}"/> <NavigationViewItem Icon="Document" Content="Categories" x:Name="Categories" Tag="Categories" Background="{ThemeResource SystemAccentColor}"/>
<NavigationViewItem Icon="Folder" Content="Files" x:Name="Files" Tag="Files" Background="{ThemeResource SystemAccentColor}"/> <NavigationViewItem Icon="Folder" Content="Files" x:Name="Files" Tag="Files" Background="{ThemeResource SystemAccentColor}"/>
<NavigationViewItem Icon="People" Content="Users" x:Name="Users" Tag="Users" Background="{ThemeResource SystemAccentColor}"/> <NavigationViewItem Icon="People" Content="Users" x:Name="Users" Tag="Users" Background="{ThemeResource SystemAccentColor}"/>
<NavigationViewItem Icon="Folder" Content="Logs" x:Name="Logs" Tag="Logs" Background="{ThemeResource SystemAccentColor}"/> <NavigationViewItem Icon="Clock" Content="Logs" x:Name="Logs" Tag="Logs" Background="{ThemeResource SystemAccentColor}"/>
</NavigationView.MenuItems> </NavigationView.MenuItems>
<Frame x:Name="ContentFrame"/> <Frame x:Name="ContentFrame"/>

View File

@ -1,5 +1,4 @@
using PCUT.Pages.Logs; using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;

View File

@ -1,14 +1,66 @@
<Page <Page
x:Class="PCUT.Pages.Logs.LogInformationPage" x:Class="PCUT.Pages.LogInformationPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:PCUT.Pages.UserGuide" xmlns:local="using:PCUT.Pages"
xmlns:localCV="using:PCUT.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" xmlns:viewmodels="using:PCUT.ViewModels"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> mc:Ignorable="d">
<Page.Resources>
<localCV:LogTimestampConverter x:Key="timestampConverter"/>
</Page.Resources>
<Page.DataContext>
<viewmodels:LogViewModel/>
</Page.DataContext>
<Page.Background>
<SolidColorBrush Color="White" />
</Page.Background>
<Page.Transitions>
<TransitionCollection>
<EntranceThemeTransition />
</TransitionCollection>
</Page.Transitions>
<Grid> <Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.9*"/>
<RowDefinition Height="0.1*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="1">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
<Button x:Name="btnFirst" Content="First" Click="btnFirst_Click"/>
<Button x:Name="btnPrevious" Content="Previous" Click="btnPrevious_Click"/>
<TextBlock x:Name="txtPageNumber" VerticalAlignment="Center" Margin="10">
<Run Text="{Binding Pagination.Page, Mode=OneWay}" />
<Run Text="/" />
<Run Text="{Binding Pagination.TotalPage, Mode=OneWay}" />
</TextBlock>
<Button x:Name="btnNext" Content="Next" Click="btnNext_Click"/>
<Button x:Name="btnLast" Content="Last" Click="btnLast_Click"/>
<ComboBox
VerticalAlignment="Center"
ItemsSource="{Binding Pagination.AvailablePageSizes}"
SelectedItem="{Binding Pagination.PageSize, Mode=TwoWay}" />
<TextBlock VerticalAlignment="Center" Text="records/page"/>
<TextBlock VerticalAlignment="Center">
<Run Text=" (total" />
<Run Text="{Binding Pagination.TotalRecords, Mode=TwoWay}" />
<Run Text="records)" />
</TextBlock>
</StackPanel>
</Grid>
<ListView Grid.Row="0" ItemsSource="{Binding Logs}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock>
<Run Text="{Binding Timestamp, Converter={StaticResource timestampConverter}}"/>
<Run Text="{Binding Content}"/>
</TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid> </Grid>
</Page> </Page>

View File

@ -1,17 +1,52 @@
using Windows.UI.Xaml.Controls; using PCUT.ViewModels;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
namespace PCUT.Pages.Logs namespace PCUT.Pages
{ {
/// <summary> /// <summary>
/// An empty page that can be used on its own or navigated to within a Frame. /// An empty page that can be used on its own or navigated to within a Frame.
/// </summary> /// </summary>
public sealed partial class LogInformationPage : Page public sealed partial class LogInformationPage : Page
{ {
public LogViewModel ViewModels { get; set; }
public LogInformationPage() public LogInformationPage()
{ {
this.InitializeComponent(); this.InitializeComponent();
ViewModels = DataContext as LogViewModel;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModels.Pagination.Page = 1;
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModels.Pagination.Dispose();
}
private void btnFirst_Click(object sender, RoutedEventArgs e)
{
ViewModels.Pagination.Page = 1;
}
private void btnLast_Click(object sender, RoutedEventArgs e)
{
ViewModels.Pagination.Page = ViewModels.Pagination.TotalPage;
}
private void btnPrevious_Click(object sender, RoutedEventArgs e)
{
ViewModels.Pagination.Page--;
}
private void btnNext_Click(object sender, RoutedEventArgs e)
{
ViewModels.Pagination.Page++;
} }
} }
} }

View File

@ -0,0 +1,72 @@
using Http.Core;
using Http.Core.Extensions;
using PCUT.Entities;
using PCUT.Entities.ApiResponse;
using PCUT.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using static Http.Core.Constants.HttpConstants;
namespace PCUT.ViewModels
{
public class LogViewModel : NotificationBase
{
public PaginationViewModel Pagination { get; } = new PaginationViewModel(withSearch: false);
public ObservableCollection<Log> Logs { get; }
public LogViewModel()
{
Logs = new ObservableCollection<Log>();
Pagination.PageChanged += OnPageChanged;
}
private async void OnPageChanged(object sender, PageChangedEventArgs args)
{
await LoadLogsAsync(args.Page, args.PageSize);
}
public async Task LoadLogsAsync(int page, int pageSize)
{
var url = CreateFilterUrl(page, pageSize);
using (var httpClient = HttpClientFactory.CreateClient(ClientNames.ApiClient))
{
try
{
var response = await httpClient.GetAsync(url);
if (response.IsSuccessStatusCode)
{
var apiResponse = await response.DeserializeObjectAsync<PaginationResponse<IEnumerable<Log>>>();
var data = apiResponse.Data;
Pagination.Page = apiResponse.Pagination.Page;
Pagination.TotalPage = apiResponse.Pagination.TotalPages;
Pagination.TotalRecords = apiResponse.Pagination.TotalRecords;
Logs.Clear();
foreach (var log in data)
Logs.Add(log);
}
}
catch (Exception ex)
{
}
}
}
private string CreateFilterUrl(int page, int pageSize/*, string searchText*/)
{
var builder = PathBuilder.FromRouteTemplate(Api.Log)
.AddQuery("page", page.ToString())
.AddQuery("pageSize", pageSize.ToString());
//if (!string.IsNullOrEmpty(searchText))
//{
// var filter = new StringBuilder().AppendFilter("username", "cn", searchText).BuildFilter().ToString();
// builder.AddQuery("filter", filter);
//}
return builder.Build();
}
}
}