From 4e7af4bc9318c1190dec3a86121ecb4f6281faf3 Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Wed, 3 Apr 2024 15:51:17 +0200 Subject: [PATCH 1/8] Update PointOfSale App --- .../PointOfSale.API/PointOfSale.API.csproj | 22 +++ .../src/PointOfSale.API/Program.cs | 38 ++++ .../Properties/launchSettings.json | 39 +++++ .../appsettings.Development.json | 9 + .../src/PointOfSale.API/appsettings.json | 18 ++ .../src/PointOfSale.API/azuredeploy.json | 164 ++++++++++++++++++ .../src/PointOfSale/Common/CursorBehavior.cs | 43 +++++ .../src/PointOfSale/Data/Constants.cs | 23 +++ .../src/PointOfSale/Data/UserAccount.cs | 17 ++ .../PointOfSale/Messages/AddToOrderMessage.cs | 10 ++ .../Messages/DragProductMessage.cs | 12 ++ .../Pages/Handheld/MobileLoginPage.xaml | 29 ++++ .../Pages/Handheld/MobileLoginPage.xaml.cs | 16 ++ .../Pages/Handheld/MobileLoginViewModel.cs | 21 +++ .../PointOfSale/Pages/Handheld/ScanPage.xaml | 56 ++++++ .../Pages/Handheld/ScanPage.xaml.cs | 52 ++++++ .../Platforms/MacCatalyst/CursorBehavior.cs | 38 ++++ .../Platforms/iOS/Entitlements.plist | 10 ++ .../src/PointOfSale/Resources/Images/beth.png | Bin 0 -> 73851 bytes .../PointOfSale/Resources/Images/david.png | Bin 0 -> 71209 bytes .../PointOfSale/Resources/Images/hunter.png | Bin 0 -> 59448 bytes .../PointOfSale/Resources/Images/juice.png | Bin 0 -> 15401 bytes .../PointOfSale/Resources/Images/maddy.png | Bin 0 -> 73824 bytes .../PointOfSale/Resources/Images/rachel.png | Bin 0 -> 45129 bytes .../PointOfSale/Resources/Images/sweeky.png | Bin 0 -> 89097 bytes .../PointOfSale/src/PointOfSale/_usings.cs | 7 + 26 files changed, 624 insertions(+) create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale.API/PointOfSale.API.csproj create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale.API/Program.cs create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale.API/Properties/launchSettings.json create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale.API/appsettings.Development.json create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale.API/appsettings.json create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale.API/azuredeploy.json create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale/Common/CursorBehavior.cs create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale/Data/Constants.cs create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale/Data/UserAccount.cs create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale/Messages/AddToOrderMessage.cs create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale/Messages/DragProductMessage.cs create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale/Pages/Handheld/MobileLoginPage.xaml create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale/Pages/Handheld/MobileLoginPage.xaml.cs create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale/Pages/Handheld/MobileLoginViewModel.cs create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale/Pages/Handheld/ScanPage.xaml create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale/Pages/Handheld/ScanPage.xaml.cs create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale/Platforms/MacCatalyst/CursorBehavior.cs create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale/Platforms/iOS/Entitlements.plist create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale/Resources/Images/beth.png create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale/Resources/Images/david.png create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale/Resources/Images/hunter.png create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale/Resources/Images/juice.png create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale/Resources/Images/maddy.png create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale/Resources/Images/rachel.png create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale/Resources/Images/sweeky.png create mode 100644 8.0/Apps/PointOfSale/src/PointOfSale/_usings.cs diff --git a/8.0/Apps/PointOfSale/src/PointOfSale.API/PointOfSale.API.csproj b/8.0/Apps/PointOfSale/src/PointOfSale.API/PointOfSale.API.csproj new file mode 100644 index 000000000..3b45ec565 --- /dev/null +++ b/8.0/Apps/PointOfSale/src/PointOfSale.API/PointOfSale.API.csproj @@ -0,0 +1,22 @@ + + + + net7.0 + enable + enable + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + diff --git a/8.0/Apps/PointOfSale/src/PointOfSale.API/Program.cs b/8.0/Apps/PointOfSale/src/PointOfSale.API/Program.cs new file mode 100644 index 000000000..7adbb0919 --- /dev/null +++ b/8.0/Apps/PointOfSale/src/PointOfSale.API/Program.cs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. +// Licensed under the MIT License. + +using System; +using Microsoft.AspNetCore.Datasync; +using Microsoft.EntityFrameworkCore; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.Identity.Web; +//using TodoAppService.NET6.Db; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddMicrosoftIdentityWebApi(builder.Configuration); +builder.Services.AddAuthorization(); +//var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); + +//if (connectionString == null) +//{ +// throw new ApplicationException("DefaultConnection is not set"); +//} + +//builder.Services.AddDbContext(options => options.UseSqlServer(connectionString)); +//builder.Services.AddDatasyncControllers(); + +var app = builder.Build(); + +// Initialize the database +//using (var scope = app.Services.CreateScope()) +//{ +// var context = scope.ServiceProvider.GetRequiredService(); +// await context.InitializeDatabaseAsync().ConfigureAwait(false); +//} + +// Configure and run the web service. +app.UseAuthentication(); +app.UseAuthorization(); +//app.MapControllers(); +app.Run(); \ No newline at end of file diff --git a/8.0/Apps/PointOfSale/src/PointOfSale.API/Properties/launchSettings.json b/8.0/Apps/PointOfSale/src/PointOfSale.API/Properties/launchSettings.json new file mode 100644 index 000000000..21bc37ad6 --- /dev/null +++ b/8.0/Apps/PointOfSale/src/PointOfSale.API/Properties/launchSettings.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:64228", + "sslPort": 44388 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5128", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7111;http://localhost:5128", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/8.0/Apps/PointOfSale/src/PointOfSale.API/appsettings.Development.json b/8.0/Apps/PointOfSale/src/PointOfSale.API/appsettings.Development.json new file mode 100644 index 000000000..ce16a2e30 --- /dev/null +++ b/8.0/Apps/PointOfSale/src/PointOfSale.API/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} + diff --git a/8.0/Apps/PointOfSale/src/PointOfSale.API/appsettings.json b/8.0/Apps/PointOfSale/src/PointOfSale.API/appsettings.json new file mode 100644 index 000000000..915211bfd --- /dev/null +++ b/8.0/Apps/PointOfSale/src/PointOfSale.API/appsettings.json @@ -0,0 +1,18 @@ +{ + "AzureAD": { + "Instance": "https://login.microsoftonline.com", + "ClientId": "4c5a1b86-86f9-431a-a99d-999024e16848", + "TenantId": "common" + }, + "ConnectionStrings": { + "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=TodoApp;Trusted_Connection=True" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} + diff --git a/8.0/Apps/PointOfSale/src/PointOfSale.API/azuredeploy.json b/8.0/Apps/PointOfSale/src/PointOfSale.API/azuredeploy.json new file mode 100644 index 000000000..18d562868 --- /dev/null +++ b/8.0/Apps/PointOfSale/src/PointOfSale.API/azuredeploy.json @@ -0,0 +1,164 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "skuName": { + "type": "string", + "defaultValue": "F1", + "allowedValues": [ + "F1", + "D1", + "B1", + "B2", + "B3", + "S1", + "S2", + "S3", + "P1", + "P2", + "P3", + "P4" + ], + "metadata": { + "description": "Describes plan's pricing tier and instance size. Check details at https://azure.microsoft.com/en-us/pricing/details/app-service/" + } + }, + "skuCapacity": { + "type": "int", + "defaultValue": 1, + "maxValue": 3, + "minValue": 1, + "metadata": { + "description": "Describes plan's instance count" + } + }, + "sqlAdministratorLogin": { + "type": "string", + "defaultValue": "appadmin", + "metadata": { + "description": "The admin user of the SQL Server" + } + }, + "sqlPassword": { + "type": "secureString", + "metadata": { + "description": "The password of the admin user of the SQL Server" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Location for all resources." + } + } + }, + "variables": { + "hostingPlanName": "[format('{0}hosting', uniqueString(resourceGroup().id))]", + "websiteName": "[format('{0}-service', uniqueString(resourceGroup().id))]", + "sqlserverName": "[format('{0}-dbserver', uniqueString(resourceGroup().id))]", + "databaseName": "quickstart" + }, + "resources": [ + { + "type": "Microsoft.Sql/servers", + "apiVersion": "2021-02-01-preview", + "name": "[variables('sqlserverName')]", + "location": "[parameters('location')]", + "properties": { + "administratorLogin": "[parameters('sqlAdministratorLogin')]", + "administratorLoginPassword": "[parameters('sqlPassword')]", + "version": "12.0" + } + }, + { + "type": "Microsoft.Sql/servers/databases", + "apiVersion": "2021-02-01-preview", + "name": "[format('{0}/{1}', variables('sqlserverName'), variables('databaseName'))]", + "location": "[parameters('location')]", + "sku": { + "name": "Basic" + }, + "properties": { + "collation": "SQL_Latin1_General_CP1_CI_AS", + "maxSizeBytes": 1073741824 + }, + "dependsOn": [ + "[resourceId('Microsoft.Sql/servers', variables('sqlserverName'))]" + ] + }, + { + "type": "Microsoft.Sql/servers/firewallRules", + "apiVersion": "2021-02-01-preview", + "name": "[format('{0}/{1}', variables('sqlserverName'), 'AllowAllWindowsAzureIps')]", + "properties": { + "endIpAddress": "0.0.0.0", + "startIpAddress": "0.0.0.0" + }, + "dependsOn": [ + "[resourceId('Microsoft.Sql/servers', variables('sqlserverName'))]" + ] + }, + { + "type": "Microsoft.Web/serverfarms", + "apiVersion": "2021-03-01", + "name": "[variables('hostingPlanName')]", + "location": "[parameters('location')]", + "tags": { + "displayName": "HostingPlan" + }, + "sku": { + "name": "[parameters('skuName')]", + "capacity": "[parameters('skuCapacity')]" + }, + "properties": { + "numberOfWorkers": 1 + } + }, + { + "type": "Microsoft.Web/sites", + "apiVersion": "2021-03-01", + "name": "[variables('websiteName')]", + "location": "[parameters('location')]", + "tags": { + "[format('hidden-related:{0}', resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName')))]": "empty", + "displayName": "Website" + }, + "properties": { + "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]" + ] + }, + { + "type": "Microsoft.Web/sites/config", + "apiVersion": "2021-03-01", + "name": "[format('{0}/{1}', variables('websiteName'), 'connectionstrings')]", + "properties": { + "DefaultConnection": { + "value": "[format('Data Source=tcp:{0},1433;Initial Catalog={1};User Id={2}@{3};Password={4};', reference(resourceId('Microsoft.Sql/servers', variables('sqlserverName'))).fullyQualifiedDomainName, variables('databaseName'), parameters('sqlAdministratorLogin'), reference(resourceId('Microsoft.Sql/servers', variables('sqlserverName'))).fullyQualifiedDomainName, parameters('sqlPassword'))]", + "type": "SQLAzure" + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Sql/servers', variables('sqlserverName'))]", + "[resourceId('Microsoft.Web/sites', variables('websiteName'))]" + ] + } + ], + "outputs": { + "backendUrl": { + "type": "string", + "value": "[concat('https://', variables('websiteName'), '.azurewebsites.net')]" + }, + "sqlUsername": { + "type": "string", + "value": "[parameters('sqlAdministratorLogin')]" + }, + "sqlPassword": { + "type": "string", + "value": "[parameters('sqlPassword')]" + } + } +} \ No newline at end of file diff --git a/8.0/Apps/PointOfSale/src/PointOfSale/Common/CursorBehavior.cs b/8.0/Apps/PointOfSale/src/PointOfSale/Common/CursorBehavior.cs new file mode 100644 index 000000000..b2b8d13c3 --- /dev/null +++ b/8.0/Apps/PointOfSale/src/PointOfSale/Common/CursorBehavior.cs @@ -0,0 +1,43 @@ +using System; +using CommunityToolkit.Maui.Behaviors; + +namespace PointOfSale.Common.Behaviors; + +public partial class CursorBehavior : PlatformBehavior +{ + public static readonly BindableProperty AttachBehaviorProperty = + BindableProperty.CreateAttached("AttachBehavior", typeof(bool), typeof(CursorBehavior), false, propertyChanged: OnAttachBehaviorChanged); + + public static bool GetAttachBehavior(BindableObject view) + { + return (bool)view.GetValue(AttachBehaviorProperty); + } + + public static void SetAttachBehavior(BindableObject view, bool value) + { + view.SetValue(AttachBehaviorProperty, value); + } + + static void OnAttachBehaviorChanged(BindableObject view, object oldValue, object newValue) + { + var btn = view as Button; + if (btn == null) + { + return; + } + + bool attachBehavior = (bool)newValue; + if (attachBehavior) + { + btn.Behaviors.Add(new CursorBehavior()); + } + else + { + var toRemove = btn.Behaviors.FirstOrDefault(b => b is CursorBehavior); + if (toRemove != null) + { + btn.Behaviors.Remove(toRemove); + } + } + } +} \ No newline at end of file diff --git a/8.0/Apps/PointOfSale/src/PointOfSale/Data/Constants.cs b/8.0/Apps/PointOfSale/src/PointOfSale/Data/Constants.cs new file mode 100644 index 000000000..274d76957 --- /dev/null +++ b/8.0/Apps/PointOfSale/src/PointOfSale/Data/Constants.cs @@ -0,0 +1,23 @@ +using System; +namespace PointOfSale.Data; + +public static class Constants +{ + /// + /// The base URI for the Datasync service. + /// + public static string ServiceUri = "https://yojjaontbpmia-service.azurewebsites.net"; + + /// + /// The application (client) ID for the native app within Azure Active Directory + /// + public static string ApplicationId = "e8b7e84c-1cb6-4619-bee9-ace98d4211e5"; + + /// + /// The list of scopes to request + /// + public static string[] Scopes = new[] + { + "access_as_user" + }; +} \ No newline at end of file diff --git a/8.0/Apps/PointOfSale/src/PointOfSale/Data/UserAccount.cs b/8.0/Apps/PointOfSale/src/PointOfSale/Data/UserAccount.cs new file mode 100644 index 000000000..f8982e550 --- /dev/null +++ b/8.0/Apps/PointOfSale/src/PointOfSale/Data/UserAccount.cs @@ -0,0 +1,17 @@ +using System; +namespace PointOfSale.Data +{ + public class UserAccount + { + public string DisplayName { get; set; } + + public string ID { get; set; } + + public string UserPrincipalName { get; set; } + + public UserAccount() + { + } + } +} + diff --git a/8.0/Apps/PointOfSale/src/PointOfSale/Messages/AddToOrderMessage.cs b/8.0/Apps/PointOfSale/src/PointOfSale/Messages/AddToOrderMessage.cs new file mode 100644 index 000000000..7561eb9d7 --- /dev/null +++ b/8.0/Apps/PointOfSale/src/PointOfSale/Messages/AddToOrderMessage.cs @@ -0,0 +1,10 @@ +using CommunityToolkit.Mvvm.Messaging.Messages; + +namespace PointOfSale; + +public class AddToOrderMessage : ValueChangedMessage +{ + public AddToOrderMessage(Item product) : base(product) + { + } +} diff --git a/8.0/Apps/PointOfSale/src/PointOfSale/Messages/DragProductMessage.cs b/8.0/Apps/PointOfSale/src/PointOfSale/Messages/DragProductMessage.cs new file mode 100644 index 000000000..e89464fff --- /dev/null +++ b/8.0/Apps/PointOfSale/src/PointOfSale/Messages/DragProductMessage.cs @@ -0,0 +1,12 @@ +using System; +using CommunityToolkit.Mvvm.Messaging.Messages; + +namespace PointOfSale.Messages; + +public class DragProductMessage : ValueChangedMessage +{ + public DragProductMessage(bool value) : base(value) + { + } +} + diff --git a/8.0/Apps/PointOfSale/src/PointOfSale/Pages/Handheld/MobileLoginPage.xaml b/8.0/Apps/PointOfSale/src/PointOfSale/Pages/Handheld/MobileLoginPage.xaml new file mode 100644 index 000000000..514d2ed42 --- /dev/null +++ b/8.0/Apps/PointOfSale/src/PointOfSale/Pages/Handheld/MobileLoginPage.xaml @@ -0,0 +1,29 @@ + + + + + + + + + + + +