Added a client (From generator) and a basic login page to test it.

This commit is contained in:
Dennis Brentjes 2023-04-30 20:51:42 +02:00
parent b2aba31264
commit 22f05c00c1
23 changed files with 415 additions and 175 deletions

View File

@ -27,10 +27,8 @@
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.1.0" />
<PackageReference Include="Uno.Extensions.Configuration" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Http" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Http.Refit" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Logging.WinUI" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Serialization.Http" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Serialization.Refit" Version="2.3.6" />
<PackageReference Include="Uno.Material.WinUI" Version="2.5.3" />
<PackageReference Include="Uno.Toolkit.WinUI.Material" Version="2.5.5" />
<PackageReference Include="Uno.Toolkit.WinUI" Version="2.5.5" />

View File

@ -14,10 +14,8 @@
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.1.0" />
<PackageReference Include="Uno.Extensions.Configuration" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Http" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Http.Refit" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Logging.WinUI" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Serialization.Http" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Serialization.Refit" Version="2.3.6" />
<PackageReference Include="Uno.Material.WinUI" Version="2.5.3" />
<PackageReference Include="Uno.Toolkit.WinUI.Material" Version="2.5.5" />
<PackageReference Include="Uno.Toolkit.WinUI" Version="2.5.5" />

View File

@ -64,11 +64,9 @@
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.1.0" />
<PackageReference Include="Uno.Extensions.Configuration" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Http" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Http.Refit" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Logging.WebAssembly.Console" Version="1.4.0" />
<PackageReference Include="Uno.Extensions.Logging.WinUI" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Serialization.Http" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Serialization.Refit" Version="2.3.6" />
<PackageReference Include="Uno.Material.WinUI" Version="2.5.3" />
<PackageReference Include="Uno.Toolkit.WinUI.Material" Version="2.5.5" />
<PackageReference Include="Uno.Toolkit.WinUI" Version="2.5.5" />

View File

@ -30,10 +30,8 @@
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.1.0" />
<PackageReference Include="Uno.Extensions.Configuration" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Http" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Http.Refit" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Logging.WinUI" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Serialization.Http" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Serialization.Refit" Version="2.3.6" />
<PackageReference Include="Uno.Material.WinUI" Version="2.5.3" />
<PackageReference Include="Uno.Toolkit.WinUI.Material" Version="2.5.5" />
<PackageReference Include="Uno.Toolkit.WinUI" Version="2.5.5" />

View File

@ -1,5 +1,6 @@
using FrontendPlatformUno.Views;
using FrontendPlatformUno.ViewModels;
using FrontendPlatformUno.Services.Api;
namespace FrontendPlatformUno
{
@ -34,23 +35,11 @@ namespace FrontendPlatformUno
)
// Enable localization (see appsettings.json for supported languages)
.UseLocalization()
// Register Json serializers (ISerializer and ISerializer)
.UseSerialization((context, services) => services
.AddContentSerializer(context)
.AddJsonTypeInfo(WeatherForecastContext.Default.IImmutableListWeatherForecast))
.UseHttp((context, services) => services
// Register HttpClient
#if DEBUG
// DelegatingHandler will be automatically injected into Refit Client
.AddTransient<DelegatingHandler, DebugHttpHandler>()
#endif
.AddSingleton<IWeatherCache, WeatherCache>()
.AddRefitClient<IApiClient>(context))
.ConfigureServices((context, services) =>
{
// TODO: Register your services
//services.AddSingleton<IMyService, MyService>();
//services.AddSingleton<NavBarViewModel>();
services.AddSingleton<IDefaultApi>(_ => new DefaultApi("http://localhost:8080"));
})
.UseNavigation(RegisterRoutes)
);
@ -68,8 +57,6 @@ namespace FrontendPlatformUno
{
views.Register(
new ViewMap(ViewModel: typeof(ShellViewModel)),
//new ViewMap<MainPage, MainViewModel>(),
//new DataViewMap<SecondPage, SecondViewModel, Entity>(),
new ViewMap<GamenightsPage, GamenightsViewModel>(),
new ViewMap<LoginPage, LoginViewModel>()
);

View File

@ -8,6 +8,7 @@
ColorOverrideSource="ms-appx:///FrontendPlatformUno/Styles/ColorPaletteOverride.xaml"
FontOverrideSource="ms-appx:///FrontendPlatformUno/Styles/MaterialFontsOverride.xaml" />
<ResourceDictionary Source="ms-appx:///FrontendPlatformUno/Styles/GamenightStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
<!-- Add resources here -->

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows')) or '$(EnableWindowsTargeting)' == 'true'">$(TargetFrameworks);net7.0-windows10.0.19041</TargetFrameworks>
<TargetFrameworks>$(TargetFrameworks);net7.0;net7.0-ios;net7.0-android;net7.0-maccatalyst</TargetFrameworks>
@ -8,16 +8,18 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JsonSubTypes" Version="2.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Polly" Version="7.2.3" />
<PackageReference Include="RestSharp" Version="108.0.2" />
<PackageReference Include="Uno.Dsp.Tasks" Version="1.0.1" />
<PackageReference Include="Uno.WinUI" Version="4.8.24" />
<PackageReference Include="Uno.Resizetizer" Version="1.0.2" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.1.0" />
<PackageReference Include="Uno.Extensions.Configuration" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Http" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Http.Refit" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Logging.WinUI" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Serialization.Http" Version="2.3.6" />
<PackageReference Include="Uno.Extensions.Serialization.Refit" Version="2.3.6" />
<PackageReference Include="Uno.Material.WinUI" Version="2.5.3" />
<PackageReference Include="Uno.Toolkit.WinUI.Material" Version="2.5.5" />
<PackageReference Include="Uno.Toolkit.WinUI" Version="2.5.5" />
@ -77,8 +79,10 @@
<ItemGroup>
<None Remove="Styles\ColorPaletteOverride.zip" />
<None Remove="Styles\GamenightStyles.xaml" />
<None Remove="Views\GamenightsPage.xaml" />
<None Remove="Views\LoginPage.xaml" />
<None Remove="Views\NavBarUserControl.xaml" />
</ItemGroup>
<ItemGroup>
@ -86,7 +90,24 @@
</ItemGroup>
<ItemGroup>
<UpToDateCheckInput Remove="Styles\GamenightStyles.xaml" />
<UpToDateCheckInput Remove="Views\GamenightsPage.xaml" />
<UpToDateCheckInput Remove="Views\LoginPage.xaml" />
<UpToDateCheckInput Remove="Views\NavBarUserControl.xaml" />
</ItemGroup>
<ItemGroup>
<Compile Update="Services\Gamenight.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Gamenight.yaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Update="Services\Gamenight.yaml">
<Generator>OpenApiCodeGenerator</Generator>
<LastGenOutput>Gamenight.cs</LastGenOutput>
</None>
</ItemGroup>
</Project>

View File

@ -2,11 +2,17 @@
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
<ItemGroup>
<Page Update="Styles\GamenightStyles.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Views\GamenightsPage.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Views\LoginPage.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Views\NavBarUserControl.xaml">
<SubType>Designer</SubType>
</Page>
</ItemGroup>
</Project>

View File

@ -2,8 +2,6 @@
global using FrontendPlatformUno.DataContracts;
global using FrontendPlatformUno.DataContracts.Serialization;
global using FrontendPlatformUno.Infrastructure;
global using FrontendPlatformUno.Services.Caching;
global using FrontendPlatformUno.Services.Endpoints;
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Hosting;
global using Microsoft.Extensions.Localization;
@ -13,7 +11,6 @@ global using Microsoft.UI.Xaml;
global using Microsoft.UI.Xaml.Controls;
global using Microsoft.UI.Xaml.Media;
global using Microsoft.UI.Xaml.Navigation;
global using Refit;
global using System;
global using System.Collections.Generic;
global using System.Collections.Immutable;

View File

@ -0,0 +1 @@
Gamenight.cs

View File

@ -1,10 +0,0 @@
using FrontendPlatformUno.DataContracts;
using System.Collections.Immutable;
namespace FrontendPlatformUno.Services.Caching
{
public interface IWeatherCache
{
ValueTask<IImmutableList<WeatherForecast>> GetForecast(CancellationToken token);
}
}

View File

@ -1,80 +0,0 @@
using Uno.Extensions.Serialization;
using Windows.Networking.Connectivity;
using Windows.Storage;
namespace FrontendPlatformUno.Services.Caching
{
public sealed class WeatherCache : IWeatherCache
{
private readonly IApiClient _api;
private readonly ISerializer _serializer;
private readonly ILogger _logger;
public WeatherCache(IApiClient api, ISerializer serializer, ILogger<WeatherCache> logger)
{
_api = api;
_serializer = serializer;
_logger = logger;
}
private bool IsConnected => NetworkInformation.GetInternetConnectionProfile().GetNetworkConnectivityLevel() == NetworkConnectivityLevel.InternetAccess;
public async ValueTask<IImmutableList<WeatherForecast>> GetForecast(CancellationToken token)
{
var weatherText = await GetCachedWeather();
if (!string.IsNullOrWhiteSpace(weatherText))
{
return _serializer.FromString<ImmutableArray<WeatherForecast>>(weatherText);
}
if (!IsConnected)
{
_logger.LogWarning("App is offline and cannot connect to the API.");
throw new Exception("No internet connection");
}
var response = await _api.GetWeather(token);
if (response.IsSuccessStatusCode && response.Content is not null)
{
var weather = response.Content;
await Save(weather, token);
return weather;
}
else if (response.Error is not null)
{
_logger.LogError(response.Error, "An error occurred while retrieving the latest Forecast.");
throw response.Error;
}
else
{
return ImmutableArray<WeatherForecast>.Empty;
}
}
private async ValueTask<StorageFile> GetFile(CreationCollisionOption option) =>
await ApplicationData.Current.TemporaryFolder.CreateFileAsync("weather.json", option);
private async ValueTask<string?> GetCachedWeather()
{
var file = await GetFile(CreationCollisionOption.OpenIfExists);
var properties = await file.GetBasicPropertiesAsync();
// Reuse latest cache file if offline
// or if the file is less than 5 minutes old
if (IsConnected || DateTimeOffset.Now.AddMinutes(-5) > properties.DateModified)
{
return null;
}
return await File.ReadAllTextAsync(file.Path);
}
private async ValueTask Save(IImmutableList<WeatherForecast> weather, CancellationToken token)
{
var weatherText = _serializer.ToString(weather);
var file = await GetFile(CreationCollisionOption.ReplaceExisting);
await File.WriteAllTextAsync(file.Path, weatherText);
}
}
}

View File

@ -1,12 +0,0 @@
using FrontendPlatformUno.DataContracts;
using System.Collections.Immutable;
namespace FrontendPlatformUno.Services.Endpoints
{
[Headers("Content-Type: application/json")]
public interface IApiClient
{
[Get("/api/weatherforecast")]
Task<ApiResponse<IImmutableList<WeatherForecast>>> GetWeather(CancellationToken cancellationToken = default);
}
}

View File

@ -0,0 +1,249 @@
openapi: 3.0.0
x-stoplight:
id: w776sltk0h1bo
info:
title: Gamenight
version: '1.0'
contact:
name: Dennis Brentjes
email: dennis@brentj.es
url: 'https://brentj.es'
description: Api specifaction for a Gamenight server
license:
name: MIT
servers:
- url: 'http://localhost:8080'
description: Gamenight
paths:
/token:
get:
summary: ''
operationId: get-token
responses:
'200':
$ref: '#/components/responses/TokenResponse'
'401':
$ref: '#/components/responses/FailureResponse'
requestBody:
$ref: '#/components/requestBodies/Login'
description: Submit your credentials to get a JWT-token to use with the rest of the api.
/user:
post:
summary: ''
operationId: post-register
requestBody:
$ref: '#/components/requestBodies/Register'
responses:
'200':
description: ''
'422':
$ref: '#/components/responses/FailureResponse'
description: 'Create a new user given a registration token and user information, username and email must be unique, and password and password_repeat must match.'
parameters: []
/gamenights:
get:
summary: Your GET endpoint
responses:
'200':
$ref: '#/components/responses/GamenightsResponse'
'400':
$ref: '#/components/responses/FailureResponse'
'401':
$ref: '#/components/responses/FailureResponse'
operationId: get-gamenights
security:
- JWT-Auth: []
description: Retrieve the list of gamenights on this gamenight server. Requires authorization.
/gamenight:
post:
summary: ''
operationId: post-gamenight
responses:
'200':
description: OK
'401':
$ref: '#/components/responses/FailureResponse'
'422':
$ref: '#/components/responses/FailureResponse'
security:
- JWT-Auth: []
requestBody:
$ref: '#/components/requestBodies/AddGamenight'
description: 'Add a gamenight by providing a name and a date, only available when providing an JWT token.'
get:
summary: ''
operationId: get-gamenight
responses:
'200':
$ref: '#/components/responses/GamenightResponse'
'401':
$ref: '#/components/responses/FailureResponse'
'422':
$ref: '#/components/responses/FailureResponse'
requestBody:
$ref: '#/components/requestBodies/GetGamenight'
security:
- JWT-Auth: []
components:
schemas:
Gamenight:
title: Gamenight
x-stoplight:
id: 0nmru75ph5wh3
type: object
properties:
id:
type: string
x-stoplight:
id: 3bd6bux9juutk
name:
type: string
x-stoplight:
id: hp3ulebe5l5k2
datetime:
type: string
x-stoplight:
id: qrae8k13mit85
owner_id:
type: string
x-stoplight:
id: q8g2pnzqx4byh
required:
- id
- name
- datetime
- owner_id
requestBodies:
Login:
content:
application/json:
schema:
type: object
properties:
username:
type: string
x-stoplight:
id: hvemn3s02e6h2
password:
type: string
x-stoplight:
id: yx02fdolrp9rj
required:
- username
- password
Register:
content:
application/json:
schema:
type: object
properties:
username:
type: string
x-stoplight:
id: el8e6kdc6xgmw
email:
type: string
x-stoplight:
id: ipexmxasalhym
password:
type: string
x-stoplight:
id: 5fztmf9jhd7dt
password_repeat:
type: string
x-stoplight:
id: xw1skr0mjujuq
registration_token:
type: string
x-stoplight:
id: kvq6rzg1fcn7s
required:
- username
- email
- password
- password_repeat
- registration_token
AddGamenight:
content:
application/json:
schema:
type: object
properties:
name:
type: string
x-stoplight:
id: ak4fkyj5haj8k
datetime:
type: string
x-stoplight:
id: 3dylqwf2yuyku
GetGamenight:
content:
application/json:
schema:
type: object
properties:
id:
type: string
x-stoplight:
id: qykfde4zkqfgx
responses:
TokenResponse:
description: Example response
content:
application/json:
schema:
type: object
properties:
jwt_token:
type: string
x-stoplight:
id: qyp2q6rqsk1ql
required:
- jwt_token
FailureResponse:
description: Example response
content:
application/json:
schema:
type: object
properties:
message:
type: string
x-stoplight:
id: g1la0pt0erd0b
application/xml:
schema:
type: object
properties:
message:
type: string
x-stoplight:
id: ir85ew0w88sv7
required:
- message
GamenightsResponse:
description: Example response
content:
application/json:
schema:
type: object
properties:
gamenights:
x-stoplight:
id: t1i2zjid122y2
type: array
items:
$ref: '#/components/schemas/Gamenight'
GamenightResponse:
description: Example response
content:
application/json:
schema:
$ref: '#/components/schemas/Gamenight'
securitySchemes:
JWT-Auth:
type: http
scheme: bearer
bearerFormat: JWT
description: ''

View File

@ -0,0 +1,13 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="TextBox" BasedOn="{StaticResource FilledTextBoxStyle}">
<Setter Property="Margin" Value="5,10"/>
</Style>
<Style TargetType="PasswordBox" BasedOn="{StaticResource FilledPasswordBoxStyle}">
<Setter Property="Margin" Value="5,10"/>
</Style>
</ResourceDictionary>

View File

@ -1,5 +1,8 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using FrontendPlatformUno.Services.Api;
using FrontendPlatformUno.Services.Client;
using FrontendPlatformUno.Services.Model;
using FrontendPlatformUno.Views;
using System;
using System.Collections.Generic;
@ -16,16 +19,41 @@ namespace FrontendPlatformUno.ViewModels
public string? Title { get; }
public ICommand GoToLogin { get; }
public LoginViewModel(INavigator navigator, IStringLocalizer stringLocalizer)
public string? Username { get; set; }
public string? Password { get; set; }
public ICommand LoginCommand { get; internal set; }
private IDefaultApi GamenightApi { get; }
public LoginViewModel(INavigator navigator, IStringLocalizer stringLocalizer, IDefaultApi gamenightApi)
{
Navigator = navigator;
GamenightApi = gamenightApi;
Title = $"{stringLocalizer["ApplicationName"]} - Login";
GoToLogin = new AsyncRelayCommand(GoToLoginView);
LoginCommand = new AsyncRelayCommand(Login);
}
private async Task GoToLoginView()
{
await Navigator.NavigateViewModelAsync<LoginViewModel>(this);
}
private async Task Login()
{
var req = new GetTokenRequest(Username, Password);
GetToken200Response tokenResponse;
try
{
tokenResponse = await GamenightApi.GetTokenAsync(req);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
return;
}
((Configuration)GamenightApi.Configuration).AccessToken = tokenResponse.JwtToken;
}
}
}

View File

@ -17,18 +17,7 @@
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<utu:NavigationBar Content="{Binding Title}">
<utu:NavigationBar.MainCommand>
<AppBarButton>
<AppBarButton.Icon>
<BitmapIcon UriSource="ms-appx:///FrontendPlatformUno/Assets/Icons/back.png" />
</AppBarButton.Icon>
</AppBarButton>
</utu:NavigationBar.MainCommand>
<utu:NavigationBar.PrimaryCommands>
<AppBarButton Label="Login" Tag="Login" Icon="OtherUser" not_skia:AutomationProperties.AutomationId="LoginPageButton" Command="{Binding GoToLogin}"/>
</utu:NavigationBar.PrimaryCommands>
</utu:NavigationBar>
<local:NavBarUserControl/>
</Grid>
</Grid>
</Page>

View File

@ -17,18 +17,21 @@
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<utu:NavigationBar Content="{Binding Title}">
<utu:NavigationBar.MainCommand>
<AppBarButton>
<AppBarButton.Icon>
<BitmapIcon UriSource="ms-appx:///FrontendPlatformUno/Assets/Icons/back.png" />
</AppBarButton.Icon>
</AppBarButton>
</utu:NavigationBar.MainCommand>
<utu:NavigationBar.PrimaryCommands>
<AppBarButton Label="Login" Tag="Login" Icon="OtherUser" not_skia:AutomationProperties.AutomationId="LoginPageButton" Command="{Binding GoToLogin}"/>
</utu:NavigationBar.PrimaryCommands>
</utu:NavigationBar>
<local:NavBarUserControl/>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition MinWidth="600" Width="8*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="1" Orientation="Vertical" HorizontalAlignment="Stretch" VerticalAlignment="Center">
<TextBox HorizontalAlignment="Stretch" Text="{Binding Username, Mode=TwoWay}" Header="Username" PlaceholderText="Username" KeyUp="OnButton"/>
<PasswordBox HorizontalAlignment="Stretch" Password="{Binding Password, Mode=TwoWay}" Header="Password" PlaceholderText="Password" KeyUp="OnButton"/>
<Button Content="Login" Command="{Binding LoginCommand}"/>
</StackPanel>
</Grid>
</Grid>
</Grid>
</Page>

View File

@ -11,8 +11,10 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Uno;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Core;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
@ -27,5 +29,14 @@ namespace FrontendPlatformUno.Views
{
this.InitializeComponent();
}
void OnButton(object sender, KeyRoutedEventArgs e)
{
if(e.Key == Windows.System.VirtualKey.Enter)
{
((LoginViewModel)DataContext).LoginCommand?.Execute(null);
e.Handled = true;
}
}
}
}

View File

@ -0,0 +1,27 @@
<UserControl
x:Class="FrontendPlatformUno.Views.NavBarUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:FrontendPlatformUno.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:uen="using:Uno.Extensions.Navigation.UI"
xmlns:utu="using:Uno.Toolkit.UI"
xmlns:not_skia="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
d:DesignHeight="300"
d:DesignWidth="400">
<utu:NavigationBar Content="{Binding Title}">
<utu:NavigationBar.MainCommand>
<AppBarButton>
<AppBarButton.Icon>
<BitmapIcon UriSource="ms-appx:///FrontendPlatformUno/Assets/Icons/back.png" />
</AppBarButton.Icon>
</AppBarButton>
</utu:NavigationBar.MainCommand>
<utu:NavigationBar.PrimaryCommands>
<AppBarButton Label="Login" Tag="Login" Icon="OtherUser" not_skia:AutomationProperties.AutomationId="LoginPageButton" Command="{Binding GoToLogin}"/>
</utu:NavigationBar.PrimaryCommands>
</utu:NavigationBar>
</UserControl>

View File

@ -0,0 +1,27 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
namespace FrontendPlatformUno.Views
{
public sealed partial class NavBarUserControl : UserControl
{
public NavBarUserControl()
{
this.InitializeComponent();
}
}
}

View File

@ -20,15 +20,6 @@ impl LoginResponse {
jwt_token: Some(token)
}
}
pub fn failure(message: String) -> Self {
Self {
login_result: false,
message: Some(message),
user_id: None,
jwt_token: None
}
}
}
#[derive(Serialize, Deserialize)]

View File

@ -34,23 +34,22 @@ impl Into<schema::user::Register> for Register {
pub async fn login(pool: web::Data<DbPool>, login_data: web::Json<Login>) -> Result<impl Responder, ApiError> {
let data = login_data.into_inner();
let response = if let Some(user) = web::block(move || {
if let Ok(Some(user)) = web::block(move || {
let mut conn = pool.get_conn();
schema::login(&mut conn, data.into())
})
.await??
.await?
{
let token = get_token(&user)?;
LoginResponse::success(user.id, token)
let response = LoginResponse::success(user.id, token);
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&response)?)
)
}
else {
LoginResponse::failure("User doesn't exist or password doesn't match".to_string())
};
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&response)?)
)
Err(ApiError{status: 401, message: "User doesn't exist or password doesn't match".to_string()})
}
}
#[post("/user")]