Initial Sync.

This commit is contained in:
2023-12-07 15:36:22 +01:00
parent 37431c19a6
commit 3e797c55b8
75 changed files with 5669 additions and 0 deletions
+400
View File
@@ -0,0 +1,400 @@
# ---> VisualStudio
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml
+138
View File
@@ -0,0 +1,138 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.33627.172
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApp", "TestApp\TestApp\TestApp.csproj", "{B86D0E02-053A-411E-9C97-FE520A67BF92}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Platforms", "Platforms", "{396481E0-54D5-4B3F-9BEC-ED3D09CE0518}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApp.Mobile", "TestApp\TestApp.Mobile\TestApp.Mobile.csproj", "{D7F63168-6563-404F-B6FA-F68D01454C5A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApp.Windows", "TestApp\TestApp.Windows\TestApp.Windows.csproj", "{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApp.Skia.Gtk", "TestApp\TestApp.Skia.Gtk\TestApp.Skia.Gtk.csproj", "{F0B4A2C3-3CEB-4498-B704-CB08D2D1AD4E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApp.Data", "TestApp.Data\TestApp.Data.csproj", "{2719E894-38DA-4F8F-B7C7-AE9D784A8B85}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|arm64 = Debug|arm64
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|arm64 = Release|arm64
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B86D0E02-053A-411E-9C97-FE520A67BF92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B86D0E02-053A-411E-9C97-FE520A67BF92}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B86D0E02-053A-411E-9C97-FE520A67BF92}.Debug|arm64.ActiveCfg = Debug|Any CPU
{B86D0E02-053A-411E-9C97-FE520A67BF92}.Debug|arm64.Build.0 = Debug|Any CPU
{B86D0E02-053A-411E-9C97-FE520A67BF92}.Debug|x64.ActiveCfg = Debug|Any CPU
{B86D0E02-053A-411E-9C97-FE520A67BF92}.Debug|x64.Build.0 = Debug|Any CPU
{B86D0E02-053A-411E-9C97-FE520A67BF92}.Debug|x86.ActiveCfg = Debug|Any CPU
{B86D0E02-053A-411E-9C97-FE520A67BF92}.Debug|x86.Build.0 = Debug|Any CPU
{B86D0E02-053A-411E-9C97-FE520A67BF92}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B86D0E02-053A-411E-9C97-FE520A67BF92}.Release|Any CPU.Build.0 = Release|Any CPU
{B86D0E02-053A-411E-9C97-FE520A67BF92}.Release|arm64.ActiveCfg = Release|Any CPU
{B86D0E02-053A-411E-9C97-FE520A67BF92}.Release|arm64.Build.0 = Release|Any CPU
{B86D0E02-053A-411E-9C97-FE520A67BF92}.Release|x64.ActiveCfg = Release|Any CPU
{B86D0E02-053A-411E-9C97-FE520A67BF92}.Release|x64.Build.0 = Release|Any CPU
{B86D0E02-053A-411E-9C97-FE520A67BF92}.Release|x86.ActiveCfg = Release|Any CPU
{B86D0E02-053A-411E-9C97-FE520A67BF92}.Release|x86.Build.0 = Release|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Debug|arm64.ActiveCfg = Debug|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Debug|arm64.Build.0 = Debug|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Debug|arm64.Deploy.0 = Debug|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Debug|x64.ActiveCfg = Debug|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Debug|x64.Build.0 = Debug|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Debug|x64.Deploy.0 = Debug|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Debug|x86.ActiveCfg = Debug|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Debug|x86.Build.0 = Debug|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Debug|x86.Deploy.0 = Debug|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Release|Any CPU.Build.0 = Release|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Release|Any CPU.Deploy.0 = Release|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Release|arm64.ActiveCfg = Release|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Release|arm64.Build.0 = Release|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Release|arm64.Deploy.0 = Release|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Release|x64.ActiveCfg = Release|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Release|x64.Build.0 = Release|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Release|x64.Deploy.0 = Release|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Release|x86.ActiveCfg = Release|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Release|x86.Build.0 = Release|Any CPU
{D7F63168-6563-404F-B6FA-F68D01454C5A}.Release|x86.Deploy.0 = Release|Any CPU
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Debug|Any CPU.ActiveCfg = Debug|x64
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Debug|Any CPU.Build.0 = Debug|x64
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Debug|Any CPU.Deploy.0 = Debug|x64
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Debug|arm64.ActiveCfg = Debug|arm64
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Debug|arm64.Build.0 = Debug|arm64
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Debug|arm64.Deploy.0 = Debug|arm64
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Debug|x64.ActiveCfg = Debug|x64
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Debug|x64.Build.0 = Debug|x64
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Debug|x64.Deploy.0 = Debug|x64
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Debug|x86.ActiveCfg = Debug|x86
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Debug|x86.Build.0 = Debug|x86
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Debug|x86.Deploy.0 = Debug|x86
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Release|Any CPU.ActiveCfg = Release|x64
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Release|Any CPU.Build.0 = Release|x64
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Release|Any CPU.Deploy.0 = Release|x64
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Release|arm64.ActiveCfg = Release|arm64
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Release|arm64.Build.0 = Release|arm64
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Release|arm64.Deploy.0 = Release|arm64
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Release|x64.ActiveCfg = Release|x64
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Release|x64.Build.0 = Release|x64
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Release|x64.Deploy.0 = Release|x64
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Release|x86.ActiveCfg = Release|x86
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Release|x86.Build.0 = Release|x86
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B}.Release|x86.Deploy.0 = Release|x86
{F0B4A2C3-3CEB-4498-B704-CB08D2D1AD4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F0B4A2C3-3CEB-4498-B704-CB08D2D1AD4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F0B4A2C3-3CEB-4498-B704-CB08D2D1AD4E}.Debug|arm64.ActiveCfg = Debug|Any CPU
{F0B4A2C3-3CEB-4498-B704-CB08D2D1AD4E}.Debug|arm64.Build.0 = Debug|Any CPU
{F0B4A2C3-3CEB-4498-B704-CB08D2D1AD4E}.Debug|x64.ActiveCfg = Debug|Any CPU
{F0B4A2C3-3CEB-4498-B704-CB08D2D1AD4E}.Debug|x64.Build.0 = Debug|Any CPU
{F0B4A2C3-3CEB-4498-B704-CB08D2D1AD4E}.Debug|x86.ActiveCfg = Debug|Any CPU
{F0B4A2C3-3CEB-4498-B704-CB08D2D1AD4E}.Debug|x86.Build.0 = Debug|Any CPU
{F0B4A2C3-3CEB-4498-B704-CB08D2D1AD4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F0B4A2C3-3CEB-4498-B704-CB08D2D1AD4E}.Release|Any CPU.Build.0 = Release|Any CPU
{F0B4A2C3-3CEB-4498-B704-CB08D2D1AD4E}.Release|arm64.ActiveCfg = Release|Any CPU
{F0B4A2C3-3CEB-4498-B704-CB08D2D1AD4E}.Release|arm64.Build.0 = Release|Any CPU
{F0B4A2C3-3CEB-4498-B704-CB08D2D1AD4E}.Release|x64.ActiveCfg = Release|Any CPU
{F0B4A2C3-3CEB-4498-B704-CB08D2D1AD4E}.Release|x64.Build.0 = Release|Any CPU
{F0B4A2C3-3CEB-4498-B704-CB08D2D1AD4E}.Release|x86.ActiveCfg = Release|Any CPU
{F0B4A2C3-3CEB-4498-B704-CB08D2D1AD4E}.Release|x86.Build.0 = Release|Any CPU
{2719E894-38DA-4F8F-B7C7-AE9D784A8B85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2719E894-38DA-4F8F-B7C7-AE9D784A8B85}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2719E894-38DA-4F8F-B7C7-AE9D784A8B85}.Debug|arm64.ActiveCfg = Debug|Any CPU
{2719E894-38DA-4F8F-B7C7-AE9D784A8B85}.Debug|arm64.Build.0 = Debug|Any CPU
{2719E894-38DA-4F8F-B7C7-AE9D784A8B85}.Debug|x64.ActiveCfg = Debug|Any CPU
{2719E894-38DA-4F8F-B7C7-AE9D784A8B85}.Debug|x64.Build.0 = Debug|Any CPU
{2719E894-38DA-4F8F-B7C7-AE9D784A8B85}.Debug|x86.ActiveCfg = Debug|Any CPU
{2719E894-38DA-4F8F-B7C7-AE9D784A8B85}.Debug|x86.Build.0 = Debug|Any CPU
{2719E894-38DA-4F8F-B7C7-AE9D784A8B85}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2719E894-38DA-4F8F-B7C7-AE9D784A8B85}.Release|Any CPU.Build.0 = Release|Any CPU
{2719E894-38DA-4F8F-B7C7-AE9D784A8B85}.Release|arm64.ActiveCfg = Release|Any CPU
{2719E894-38DA-4F8F-B7C7-AE9D784A8B85}.Release|arm64.Build.0 = Release|Any CPU
{2719E894-38DA-4F8F-B7C7-AE9D784A8B85}.Release|x64.ActiveCfg = Release|Any CPU
{2719E894-38DA-4F8F-B7C7-AE9D784A8B85}.Release|x64.Build.0 = Release|Any CPU
{2719E894-38DA-4F8F-B7C7-AE9D784A8B85}.Release|x86.ActiveCfg = Release|Any CPU
{2719E894-38DA-4F8F-B7C7-AE9D784A8B85}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{D7F63168-6563-404F-B6FA-F68D01454C5A} = {396481E0-54D5-4B3F-9BEC-ED3D09CE0518}
{3B69A13C-B8A0-4B51-9B78-9088BBFB5A5B} = {396481E0-54D5-4B3F-9BEC-ED3D09CE0518}
{F0B4A2C3-3CEB-4498-B704-CB08D2D1AD4E} = {396481E0-54D5-4B3F-9BEC-ED3D09CE0518}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DBE75C9E-AE63-4318-8302-E69660E41D90}
EndGlobalSection
EndGlobal
+109
View File
@@ -0,0 +1,109 @@
syntax = "proto3";
option csharp_namespace = "DGM.HoC.BookMng.API.RPC";
package HoC;
service rpcBookMng {
rpc GetAllRoomTypes (EmptyReq) returns (GetAllRoomTypesResponse);
rpc GetRoomTypeById (RoomTypeId) returns (rpcRoomType);
rpc AddRoomType (rpcRoomType) returns (rpcRoomType);
rpc RemoveRoomType (RoomTypeId) returns (EmptyResponse);
rpc UpdateRoomType (rpcRoomType) returns (rpcRoomType);
rpc GetAllBookings (EmptyReq) returns (GetAllBookingsResponse);
rpc GetBookingById (BookingId) returns (rpcBooking);
rpc GetBookingDetailsById (BookingId) returns (rpcBookingDetails);
/*
Cuando creas un Booking no es sólo el booking,
también contiene una lista de RoomItems y el customerData.
Igual ocurre con el Remove, pues son dependientes.
*/
rpc AddBooking (rpcBookingDetails) returns (rpcBookingDetails);
rpc RemoveBooking (BookingId) returns (EmptyResponse);
rpc UpdateBooking (rpcBooking) returns (rpcBooking);
rpc GetRoomItemsByBooking (BookingId) returns (rpcRoomItemList);
rpc AddRoomItem (rpcRoomItem) returns (rpcRoomItem);
rpc RemoveRoomItem (RoomItemId) returns (EmptyResponse);
rpc UpdateRoomItem (rpcRoomItem) returns (rpcRoomItem);
// Los datos de clientes no se pueden crear ni eliminar, sólo actualizar.
// Dependen del booking.
rpc GetBookingCustomer (BookingId) returns (rpcBookingCustomer);
rpc UpdateBookingCustomer (rpcBookingCustomer) returns (rpcBookingCustomer);
}
message EmptyReq {}
message EmptyResponse {
string msg = 1;
}
message RoomTypeId {
int32 id = 1;
}
message RoomItemId {
int32 bookingId = 1;
int32 itemId = 2;
}
message BookingId {
int32 bookingId = 1;
}
message GetAllRoomTypesResponse {
repeated rpcRoomType roomTypeList = 1;
}
message GetAllBookingsResponse {
repeated rpcBooking bookingList = 1;
}
message rpcRoomType {
int32 id = 1;
string name = 2;
string description = 3;
int32 guestAmount = 4;
}
message rpcRoomItem {
int32 bookingId = 1;
int32 itemId = 2;
int32 guestAmount = 3;
string dateIn = 4;
string dateOut = 5;
float pricePerNight = 6;
string notes = 7;
int32 typeId = 8;
}
message rpcRoomItemList {
repeated rpcRoomItem roomItemList = 1;
}
message rpcBookingCustomer {
int32 bookingId = 1;
string name = 2;
string phone = 3;
string email = 4;
}
message rpcBooking {
int32 id = 1;
string description = 2;
string status = 3;
string customerId = 4;
}
message rpcBookingDetails {
rpcBooking data = 1;
rpcBookingCustomer bookingCustomer = 2;
repeated rpcRoomItem rooms = 3;
}
+164
View File
@@ -0,0 +1,164 @@
syntax = "proto3";
option csharp_namespace = "DGM.HoC.CRM.API.RPC";
import "google/protobuf/timestamp.proto";
import "google/protobuf/empty.proto";
package HoC;
service rpcCRM {
rpc GetCustomerById (CustomerIdReq) returns (rpcCustomer);
rpc GetAllCustomers (google.protobuf.Empty) returns (CustomerListResponse);
rpc GetCustomersByFilter (rpcCustomerFilter) returns (CustomerListResponse);
rpc AddCustomer (rpcAddCustomerReq) returns (rpcCustomer);
rpc RemoveCustomer (CustomerIdReq) returns (google.protobuf.Empty);
rpc UpdateCustomer (rpcUpdateCustomerReq) returns (rpcCustomer);
rpc GetAllCustomerContactDetails (google.protobuf.Empty) returns (ContactDetailsListResponse);
rpc GetContactDetailsByCustomer (CustomerIdReq) returns (ContactDetailsListResponse);
rpc GetContactDetailsById (ContactIdReq) returns (rpcContact);
rpc AddCustomerContact (rpcAddContactDetailsReq) returns (rpcContact);
rpc RemoveCustomerContact (ContactIdReq) returns (EmptyResponse);
rpc UpdateCustomerContact (rpcUpdateContactDetailsReq) returns (rpcContact);
rpc GetNoteById (NoteIdReq) returns (rpcNote);
rpc GetNoteByCustomer (CustomerIdReq) returns (NoteListResponse);
rpc GetAllNotes (EmptyReq) returns (NoteListResponse);
rpc AddNote (rpcAddNoteReq) returns (rpcNote);
rpc RemoveNote (NoteIdReq) returns (EmptyResponse);
rpc UpdateNote (rpcUpdateNoteReq) returns (rpcNote);
}
message EmptyReq {}
message EmptyResponse {
string msg = 1;
}
// Requests messages
message CustomerIdReq {
string customerId = 1;
}
message ContactIdReq {
int32 contactId = 1;
}
message NoteIdReq {
int32 noteId = 1;
}
message rpcAddCustomerReq {
string nif = 1;
string name = 2;
rpcAddress customerAddress = 3;
}
message rpcUpdateCustomerReq {
string nif = 1;
optional string name = 2;
optional rpcAddress customerAddress = 3;
}
message rpcAddContactDetailsReq {
string customerNIF = 2;
string type = 5;
string value = 6;
string comment = 7;
}
message rpcUpdateContactDetailsReq {
int32 id = 1;
optional string customerNIF = 2;
optional string type = 5;
optional string value = 6;
optional string comment = 7;
}
message rpcAddNoteReq {
string customerNIF = 2;
string data = 5;
string status = 6;
}
message rpcUpdateNoteReq {
int32 id = 1;
optional string customerNIF = 2;
optional string data = 5;
optional string status = 6;
}
// Response messages
message CustomerListResponse {
repeated rpcCustomer customerList = 1;
}
message ContactDetailsListResponse {
repeated rpcContact contactList = 1;
}
message NoteListResponse {
repeated rpcNote noteList = 1;
}
// Entity messages
message rpcCustomer {
string nif = 1;
string name = 2;
rpcAddress customerAddress = 3;
optional google.protobuf.Timestamp createTime = 6;
optional google.protobuf.Timestamp lastUsedTime = 7;
}
message rpcCustomerFilter {
string nif = 1;
string name = 2;
string contactData = 3;
bool strict = 10;
optional int32 pageIndex = 11;
optional int32 pageSize = 12;
}
message rpcAddress {
optional string tipoVia = 1;
optional string nombreVia = 2;
optional string numero = 3;
optional string provincia = 4;
optional string poblacion = 5;
optional string codigoPostal = 6;
optional string pais = 7;
}
message rpcContact {
string customerNIF = 1;
int32 id = 2;
string type = 3;
string value = 4;
string comment = 5;
}
message rpcNote {
string customerNIF = 1;
int32 id = 2;
string data = 3;
string status = 4;
optional google.protobuf.Timestamp createTime = 5;
}
+28
View File
@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<None Remove="Protos\BookMng.proto" />
<None Remove="Protos\CRM.proto" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.23.0" />
<PackageReference Include="Grpc.Net.Client" Version="2.53.0" />
<PackageReference Include="Grpc.Tools" Version="2.54.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<Protobuf Include="Protos\BookMng.proto" GrpcServices="Client" />
<Protobuf Include="Protos\CRM.proto" GrpcServices="Client" />
</ItemGroup>
</Project>
+53
View File
@@ -0,0 +1,53 @@
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"version": "0.2.0",
"configurations": [
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"name": "Debug (Chrome, WebAssembly)",
"type": "chrome",
"request": "launch",
"url": "http://localhost:5000",
"webRoot": "${workspaceFolder}/TestApp.Wasm",
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"timeout": 30000,
"server": {
"runtimeExecutable": "dotnet",
"program": "run",
"outputCapture": "std",
"timeout": 30000,
"cwd": "${workspaceFolder}/TestApp.Wasm"
}
},
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"name": "Skia.GTK (Debug)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build-skia-gtk",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/TestApp.Skia.Gtk/bin/Debug/net7.0/TestApp.Skia.Gtk.dll",
"args": [],
"env": {
"DOTNET_MODIFIABLE_ASSEMBLIES": "debug"
},
"cwd": "${workspaceFolder}/TestApp.Skia.Gtk",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": "Uno Platform Mobile",
"type": "Uno",
"request": "launch",
// any Uno* task will do, this is simply to satisfy vscode requirement when a launch.json is present
"preLaunchTask": "Uno: android | Debug | android-x64"
}
]
}
+7
View File
@@ -0,0 +1,7 @@
{
"explorer.fileNesting.enabled": true,
"explorer.fileNesting.expand": false,
"explorer.fileNesting.patterns": {
"*.xaml": "$(capture).xaml.cs"
}
}
+53
View File
@@ -0,0 +1,53 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build-wasm",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/TestApp.Wasm/TestApp.Wasm.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish-wasm",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/TestApp.Wasm/TestApp.Wasm.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "build-skia-gtk",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/TestApp.Skia.Gtk/TestApp.Skia.Gtk.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish-skia-gtk",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/TestApp.Skia.Gtk/TestApp.Skia.Gtk.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
]
}
+38
View File
@@ -0,0 +1,38 @@
{
"version": "1.0",
"components": [
"Microsoft.VisualStudio.Component.CoreEditor",
"Microsoft.VisualStudio.Workload.CoreEditor",
"Microsoft.NetCore.Component.SDK",
"Microsoft.NetCore.Component.DevelopmentTools",
"Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions",
"Microsoft.NetCore.Component.Web",
"Microsoft.Net.ComponentGroup.DevelopmentPrerequisites",
"Microsoft.VisualStudio.Component.TextTemplating",
"Microsoft.VisualStudio.Component.IISExpress",
"Component.Microsoft.Web.LibraryManager",
"Microsoft.VisualStudio.ComponentGroup.Web",
"Microsoft.VisualStudio.Component.Web",
"Microsoft.VisualStudio.ComponentGroup.Web.Client",
"Microsoft.VisualStudio.Workload.NetWeb",
"Microsoft.VisualStudio.ComponentGroup.Azure.Prerequisites",
"Microsoft.VisualStudio.Workload.Azure",
"Microsoft.VisualStudio.Component.Windows10SDK.19041",
"Microsoft.VisualStudio.Component.ManagedDesktop.Prerequisites",
"Microsoft.VisualStudio.Component.Debugger.JustInTime",
"Microsoft.VisualStudio.ComponentGroup.MSIX.Packaging",
"Microsoft.VisualStudio.Workload.ManagedDesktop",
"Microsoft.Component.NetFX.Native",
"Microsoft.VisualStudio.Component.Graphics",
"Component.OpenJDK",
"Microsoft.VisualStudio.Component.MonoDebugger",
"Microsoft.VisualStudio.Component.Merq",
"Component.Xamarin.RemotedSimulator",
"Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions.TemplateEngine",
"Component.Xamarin",
"Component.Android.SDK32",
"Microsoft.VisualStudio.Workload.NetCrossPlat",
"Microsoft.VisualStudio.Workload.NetCoreTools",
"Microsoft.VisualStudio.ComponentGroup.Maui.All"
]
}
+59
View File
@@ -0,0 +1,59 @@
<Project ToolsVersion="15.0">
<PropertyGroup>
<LangVersion>11</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<DebugType>portable</DebugType>
<DebugSymbols>True</DebugSymbols>
<SynthesizeLinkMetadata>true</SynthesizeLinkMetadata>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<NoWarn>$(NoWarn);Uno0001;CS1998;CA1416;NU1507</NoWarn>
<DefaultLanguage>en</DefaultLanguage>
<IsAndroid>false</IsAndroid>
<IsIOS>false</IsIOS>
<IsMac>false</IsMac>
<IsMacCatalyst>false</IsMacCatalyst>
<IsWinAppSdk>false</IsWinAppSdk>
</PropertyGroup>
<Choose>
<When Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
<PropertyGroup>
<IsAndroid>true</IsAndroid>
<SupportedOSPlatformVersion>21.0</SupportedOSPlatformVersion>
</PropertyGroup>
</When>
<When Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">
<PropertyGroup>
<IsIOS>true</IsIOS>
<SupportedOSPlatformVersion>14.2</SupportedOSPlatformVersion>
<RuntimeIdentifier Condition="'$(RuntimeIdentifier)'==''">iossimulator-x64</RuntimeIdentifier>
</PropertyGroup>
</When>
<When Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'macos'">
<PropertyGroup>
<IsMac>true</IsMac>
<SupportedOSPlatformVersion>10.14</SupportedOSPlatformVersion>
<RuntimeIdentifier Condition="'$(RuntimeIdentifier)'==''">osx-x64</RuntimeIdentifier>
</PropertyGroup>
</When>
<When Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">
<PropertyGroup>
<IsMacCatalyst>true</IsMacCatalyst>
<SupportedOSPlatformVersion>14.0</SupportedOSPlatformVersion>
<RuntimeIdentifier Condition="'$(RuntimeIdentifier)'==''">maccatalyst-x64</RuntimeIdentifier>
</PropertyGroup>
</When>
<When Condition="$(TargetFramework.Contains('windows10'))">
<PropertyGroup>
<IsWinAppSdk>true</IsWinAppSdk>
<SupportedOSPlatformVersion>10.0.18362.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion>10.0.18362.0</TargetPlatformMinVersion>
</PropertyGroup>
</When>
</Choose>
</Project>
+2
View File
@@ -0,0 +1,2 @@
<Project ToolsVersion="15.0">
</Project>
+17
View File
@@ -0,0 +1,17 @@
<local:App x:Class="TestApp.AppHead"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wasm="http://platform.uno/wasm"
xmlns:local="using:TestApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="wasm">
<local:App.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ms-appx:///TestApp/AppResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</local:App.Resources>
</local:App>
+90
View File
@@ -0,0 +1,90 @@
using Microsoft.Extensions.Logging;
using Microsoft.UI.Xaml;
using System;
namespace TestApp
{
public sealed partial class AppHead : App
{
static AppHead() =>
InitializeLogging();
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public AppHead()
{
this.InitializeComponent();
}
/// <summary>
/// Configures global Uno Platform logging
/// </summary>
private static void InitializeLogging()
{
#if DEBUG
// Logging is disabled by default for release builds, as it incurs a significant
// initialization cost from Microsoft.Extensions.Logging setup. If startup performance
// is a concern for your application, keep this disabled. If you're running on the web or
// desktop targets, you can use URL or command line parameters to enable it.
//
// For more performance documentation: https://platform.uno/docs/articles/Uno-UI-Performance.html
var factory = LoggerFactory.Create(builder =>
{
#if __WASM__
builder.AddProvider(new global::Uno.Extensions.Logging.WebAssembly.WebAssemblyConsoleLoggerProvider());
#elif __IOS__ || __MACCATALYST__
builder.AddProvider(new global::Uno.Extensions.Logging.OSLogLoggerProvider());
#elif NETFX_CORE
builder.AddDebug();
#else
builder.AddConsole();
#endif
// Exclude logs below this level
builder.SetMinimumLevel(LogLevel.Information);
// Default filters for Uno Platform namespaces
builder.AddFilter("Uno", LogLevel.Warning);
builder.AddFilter("Windows", LogLevel.Warning);
builder.AddFilter("Microsoft", LogLevel.Warning);
// Generic Xaml events
// builder.AddFilter("Microsoft.UI.Xaml", LogLevel.Debug );
// builder.AddFilter("Microsoft.UI.Xaml.VisualStateGroup", LogLevel.Debug );
// builder.AddFilter("Microsoft.UI.Xaml.StateTriggerBase", LogLevel.Debug );
// builder.AddFilter("Microsoft.UI.Xaml.UIElement", LogLevel.Debug );
// builder.AddFilter("Microsoft.UI.Xaml.FrameworkElement", LogLevel.Trace );
// Layouter specific messages
// builder.AddFilter("Microsoft.UI.Xaml.Controls", LogLevel.Debug );
// builder.AddFilter("Microsoft.UI.Xaml.Controls.Layouter", LogLevel.Debug );
// builder.AddFilter("Microsoft.UI.Xaml.Controls.Panel", LogLevel.Debug );
// builder.AddFilter("Windows.Storage", LogLevel.Debug );
// Binding related messages
// builder.AddFilter("Microsoft.UI.Xaml.Data", LogLevel.Debug );
// builder.AddFilter("Microsoft.UI.Xaml.Data", LogLevel.Debug );
// Binder memory references tracking
// builder.AddFilter("Uno.UI.DataBinding.BinderReferenceHolder", LogLevel.Debug );
// RemoteControl and HotReload related
// builder.AddFilter("Uno.UI.RemoteControl", LogLevel.Information);
// Debug JS interop
// builder.AddFilter("Uno.Foundation.WebAssemblyRuntime", LogLevel.Debug );
});
global::Uno.Extensions.LogExtensionPoint.AmbientLoggerFactory = factory;
#if HAS_UNO
global::Uno.UI.Adapter.Microsoft.Extensions.Logging.LoggingAdapter.Initialize();
#endif
#endif
}
}
}
+137
View File
@@ -0,0 +1,137 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="450"
height="450"
viewBox="0 0 50.369617 49.826836"
version="1.1"
id="svg151"
sodipodi:docname="appconfig.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview153"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="1.250876"
inkscape:cx="218.64677"
inkscape:cy="175.87674"
inkscape:window-width="1920"
inkscape:window-height="1027"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="g149" />
<defs
id="defs105">
<path
id="aj28a0fd1a"
d="M 1.738,0.156 3.927,2.323 2.347,3.919 0.101,1.81 Z" />
<path
id="fdje57jgic"
d="M 2.201,0.066 3.855,1.703 1.69,3.894 0.093,2.311 Z" />
<path
id="6bg72xwlze"
d="M 2.398,0.044 3.994,1.624 1.886,3.869 0.232,2.232 Z" />
<path
id="eaqjnja8wg"
d="M 1.736,0.023 3.981,2.132 2.344,3.786 0.156,1.619 Z" />
</defs>
<g
fill="none"
fill-rule="evenodd"
id="g149"
transform="translate(-2.9304427e-4,-1.6465461e-4)">
<g
id="g147">
<g
id="g145">
<path
fill="#7a67f8"
d="M 34.758,38.865 H 34.746 C 31.892,38.86 29.342,36.882 26.152,33.692 l -6.93,-6.873 2.166,-2.188 6.937,6.88 c 3.075,3.074 4.876,4.272 6.427,4.275 h 0.005 c 1.567,0 3.467,-1.262 6.558,-4.353 l 3.541,-3.587 c 1.784,-1.784 2.57,-3.34 2.408,-4.762 -0.13,-1.156 -0.894,-2.397 -2.401,-3.904 L 44.83,19.146 C 43.202,17.414 41.211,15.483 39.131,14.414 38.745,12.437 37.48,10.881 37.3,10.596 c 3.803,0.559 7.197,3.703 9.758,6.424 2.788,2.794 5.803,7.176 -0.018,12.996 l -3.54,3.588 c -3.251,3.25 -5.844,5.261 -8.742,5.261"
id="path107" />
<path
fill="#f85977"
d="m 25.399,28.608 6.492,-6.562 c 3.076,-3.076 4.274,-4.877 4.276,-6.428 0.004,-1.567 -1.257,-3.469 -4.352,-6.563 L 28.228,5.515 C 24.58,1.867 22.369,2.699 19.561,5.507 L 19.528,5.54 c -1.54,1.448 -3.237,3.182 -4.346,5.01 -1.031,0.073 -2.361,0.424 -3.997,1.518 0.906,-3.397 3.737,-6.422 6.216,-8.755 2.794,-2.789 7.177,-5.804 12.997,0.017 l 3.588,3.54 c 3.255,3.256 5.266,5.851 5.26,8.754 -0.005,2.854 -1.982,5.404 -5.172,8.594 l -6.489,6.559 z"
id="path109" />
<path
fill="#159bff"
d="M 12.522,38.707 C 8.939,37.946 5.746,34.972 3.308,32.382 2.035,31.106 0.321,29.13 0.042,26.663 c -0.274,-2.414 0.8,-4.795 3.283,-7.278 l 3.542,-3.588 c 3.25,-3.25 5.843,-5.261 8.74,-5.261 h 0.013 c 2.854,0.005 5.404,1.983 8.593,5.172 l 7.046,6.976 -2.165,2.19 -7.053,-6.983 c -3.076,-3.076 -4.876,-4.273 -6.427,-4.276 h -0.006 c -1.566,0 -3.466,1.261 -6.557,4.352 L 5.51,21.555 c -1.784,1.784 -2.57,3.34 -2.409,4.762 0.131,1.156 0.894,2.396 2.402,3.904 l 0.033,0.034 c 1.55,1.649 3.43,3.479 5.401,4.573 0.168,1.739 1.2,3.297 1.585,3.88"
id="path111" />
<path
fill="#67e5ad"
d="m 26.32,49.827 c -1.925,0 -4.114,-0.886 -6.557,-3.33 l -3.588,-3.54 C 9.167,35.949 9.151,32.546 16.086,25.61 l 6.802,-6.872 2.193,2.162 -6.812,6.882 c -3.076,3.076 -4.273,4.877 -4.276,6.427 -0.003,1.568 1.258,3.47 4.352,6.563 l 3.588,3.541 c 3.646,3.647 5.858,2.816 8.666,0.008 l 0.034,-0.033 c 1.654,-1.555 3.5,-3.46 4.593,-5.437 1.661,-0.14 2.9,-0.841 3.835,-1.438 -0.8,3.537 -3.738,6.69 -6.302,9.102 -1.62,1.618 -3.777,3.312 -6.439,3.312"
id="path113" />
<g
transform="translate(21.154,18.577)"
id="g120">
<mask
id="8jptpqrneb"
fill="#ffffff">
<use
xlink:href="#aj28a0fd1a"
id="use115" />
</mask>
<path
d="M 0.101,1.81 1.738,0.156 3.927,2.323 2.347,3.919 Z"
mask="url(#8jptpqrneb)"
id="path118" />
</g>
<g
transform="translate(27.404,20.981)"
id="g127">
<mask
id="b2iljpfwbd"
fill="#ffffff">
<use
xlink:href="#fdje57jgic"
id="use122" />
</mask>
<path
d="M 2.201,0.066 3.855,1.703 1.69,3.894 0.093,2.311 Z"
mask="url(#b2iljpfwbd)"
id="path125" />
</g>
<g
transform="translate(18.99,24.587)"
id="g134">
<mask
id="gj70tyfpnf"
fill="#ffffff">
<use
xlink:href="#6bg72xwlze"
id="use129" />
</mask>
<path
d="M 1.886,3.869 0.232,2.232 2.398,0.044 3.994,1.624 Z"
mask="url(#gj70tyfpnf)"
id="path132" />
</g>
<g
transform="translate(25.24,26.99)"
id="g141">
<mask
id="z7vhvduckh"
fill="#ffffff">
<use
xlink:href="#eaqjnja8wg"
id="use136" />
</mask>
<path
d="M 3.981,2.132 2.344,3.786 0.156,1.619 1.736,0.023 Z"
mask="url(#z7vhvduckh)"
id="path139" />
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

+42
View File
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="456"
height="456"
viewBox="0 0 456 456"
version="1.1"
id="svg453"
sodipodi:docname="iconapp.old.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs457" />
<sodipodi:namedview
id="namedview455"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="1.8574561"
inkscape:cx="228.26919"
inkscape:cy="228.26919"
inkscape:window-width="1920"
inkscape:window-height="1027"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg453" />
<rect
x="0"
y="0"
width="456"
height="456"
fill="#FFFFFF"
id="rect451" />
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -0,0 +1,137 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="450"
height="450"
viewBox="0 0 50.369617 49.826836"
version="1.1"
id="svg151"
sodipodi:docname="appconfig.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview153"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="1.250876"
inkscape:cx="218.64677"
inkscape:cy="175.87674"
inkscape:window-width="1920"
inkscape:window-height="1027"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="g149" />
<defs
id="defs105">
<path
id="aj28a0fd1a"
d="M 1.738,0.156 3.927,2.323 2.347,3.919 0.101,1.81 Z" />
<path
id="fdje57jgic"
d="M 2.201,0.066 3.855,1.703 1.69,3.894 0.093,2.311 Z" />
<path
id="6bg72xwlze"
d="M 2.398,0.044 3.994,1.624 1.886,3.869 0.232,2.232 Z" />
<path
id="eaqjnja8wg"
d="M 1.736,0.023 3.981,2.132 2.344,3.786 0.156,1.619 Z" />
</defs>
<g
fill="none"
fill-rule="evenodd"
id="g149"
transform="translate(-2.9304427e-4,-1.6465461e-4)">
<g
id="g147">
<g
id="g145">
<path
fill="#7a67f8"
d="M 34.758,38.865 H 34.746 C 31.892,38.86 29.342,36.882 26.152,33.692 l -6.93,-6.873 2.166,-2.188 6.937,6.88 c 3.075,3.074 4.876,4.272 6.427,4.275 h 0.005 c 1.567,0 3.467,-1.262 6.558,-4.353 l 3.541,-3.587 c 1.784,-1.784 2.57,-3.34 2.408,-4.762 -0.13,-1.156 -0.894,-2.397 -2.401,-3.904 L 44.83,19.146 C 43.202,17.414 41.211,15.483 39.131,14.414 38.745,12.437 37.48,10.881 37.3,10.596 c 3.803,0.559 7.197,3.703 9.758,6.424 2.788,2.794 5.803,7.176 -0.018,12.996 l -3.54,3.588 c -3.251,3.25 -5.844,5.261 -8.742,5.261"
id="path107" />
<path
fill="#f85977"
d="m 25.399,28.608 6.492,-6.562 c 3.076,-3.076 4.274,-4.877 4.276,-6.428 0.004,-1.567 -1.257,-3.469 -4.352,-6.563 L 28.228,5.515 C 24.58,1.867 22.369,2.699 19.561,5.507 L 19.528,5.54 c -1.54,1.448 -3.237,3.182 -4.346,5.01 -1.031,0.073 -2.361,0.424 -3.997,1.518 0.906,-3.397 3.737,-6.422 6.216,-8.755 2.794,-2.789 7.177,-5.804 12.997,0.017 l 3.588,3.54 c 3.255,3.256 5.266,5.851 5.26,8.754 -0.005,2.854 -1.982,5.404 -5.172,8.594 l -6.489,6.559 z"
id="path109" />
<path
fill="#159bff"
d="M 12.522,38.707 C 8.939,37.946 5.746,34.972 3.308,32.382 2.035,31.106 0.321,29.13 0.042,26.663 c -0.274,-2.414 0.8,-4.795 3.283,-7.278 l 3.542,-3.588 c 3.25,-3.25 5.843,-5.261 8.74,-5.261 h 0.013 c 2.854,0.005 5.404,1.983 8.593,5.172 l 7.046,6.976 -2.165,2.19 -7.053,-6.983 c -3.076,-3.076 -4.876,-4.273 -6.427,-4.276 h -0.006 c -1.566,0 -3.466,1.261 -6.557,4.352 L 5.51,21.555 c -1.784,1.784 -2.57,3.34 -2.409,4.762 0.131,1.156 0.894,2.396 2.402,3.904 l 0.033,0.034 c 1.55,1.649 3.43,3.479 5.401,4.573 0.168,1.739 1.2,3.297 1.585,3.88"
id="path111" />
<path
fill="#67e5ad"
d="m 26.32,49.827 c -1.925,0 -4.114,-0.886 -6.557,-3.33 l -3.588,-3.54 C 9.167,35.949 9.151,32.546 16.086,25.61 l 6.802,-6.872 2.193,2.162 -6.812,6.882 c -3.076,3.076 -4.273,4.877 -4.276,6.427 -0.003,1.568 1.258,3.47 4.352,6.563 l 3.588,3.541 c 3.646,3.647 5.858,2.816 8.666,0.008 l 0.034,-0.033 c 1.654,-1.555 3.5,-3.46 4.593,-5.437 1.661,-0.14 2.9,-0.841 3.835,-1.438 -0.8,3.537 -3.738,6.69 -6.302,9.102 -1.62,1.618 -3.777,3.312 -6.439,3.312"
id="path113" />
<g
transform="translate(21.154,18.577)"
id="g120">
<mask
id="8jptpqrneb"
fill="#ffffff">
<use
xlink:href="#aj28a0fd1a"
id="use115" />
</mask>
<path
d="M 0.101,1.81 1.738,0.156 3.927,2.323 2.347,3.919 Z"
mask="url(#8jptpqrneb)"
id="path118" />
</g>
<g
transform="translate(27.404,20.981)"
id="g127">
<mask
id="b2iljpfwbd"
fill="#ffffff">
<use
xlink:href="#fdje57jgic"
id="use122" />
</mask>
<path
d="M 2.201,0.066 3.855,1.703 1.69,3.894 0.093,2.311 Z"
mask="url(#b2iljpfwbd)"
id="path125" />
</g>
<g
transform="translate(18.99,24.587)"
id="g134">
<mask
id="gj70tyfpnf"
fill="#ffffff">
<use
xlink:href="#6bg72xwlze"
id="use129" />
</mask>
<path
d="M 1.886,3.869 0.232,2.232 2.398,0.044 3.994,1.624 Z"
mask="url(#gj70tyfpnf)"
id="path132" />
</g>
<g
transform="translate(25.24,26.99)"
id="g141">
<mask
id="z7vhvduckh"
fill="#ffffff">
<use
xlink:href="#eaqjnja8wg"
id="use136" />
</mask>
<path
d="M 3.981,2.132 2.344,3.786 0.156,1.619 1.736,0.023 Z"
mask="url(#z7vhvduckh)"
id="path139" />
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

+25
View File
@@ -0,0 +1,25 @@
<Project>
<ItemGroup>
</ItemGroup>
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)AppHead.xaml" />
<ApplicationDefinition Include="$(MSBuildThisFileDirectory)AppHead.xaml"
SubType="Designer"
XamlRuntime="WinUI"
Generator="MSBuild:Compile"
Link="AppHead.xaml" />
<Compile Include="$(MSBuildThisFileDirectory)AppHead.xaml.cs"
XamlRuntime="WinUI"
DependentUpon="AppHead.xaml"
Link="AppHead.xaml.cs" />
<UnoIcon Include="$(MSBuildThisFileDirectory)Icons\iconapp.svg"
ForegroundFile="$(MSBuildThisFileDirectory)Icons\appconfig.svg"
ForegroundScale="0.65"
Color="#00000000" />
<UnoSplashScreen
Include="$(MSBuildThisFileDirectory)Splash\splash_screen.svg"
BaseSize="128,128"
Color="#086AD1" />
</ItemGroup>
</Project>
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:allowBackup="true" android:supportsRtl="true"></application>
</manifest>
@@ -0,0 +1,22 @@
To add cross-platform image assets for your Uno Platform app, use the Assets folder
in the shared project instead. Assets in this folder are Android-only assets.
Any raw assets you want to be deployed with your application can be placed in
this directory (and child directories) and given a Build Action of "AndroidAsset".
These files will be deployed with you package and will be accessible using Android's
AssetManager, like this:
public class ReadAsset : Activity
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
InputStream input = Assets.Open ("my_asset.txt");
}
}
Additionally, some Android functions will automatically load asset files:
Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
@@ -0,0 +1,43 @@
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Com.Nostra13.Universalimageloader.Core;
using Microsoft.UI.Xaml.Media;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestApp.Droid
{
[global::Android.App.ApplicationAttribute(
Label = "@string/ApplicationName",
Icon = "@mipmap/iconapp",
LargeHeap = true,
HardwareAccelerated = true,
Theme = "@style/AppTheme"
)]
public class Application : Microsoft.UI.Xaml.NativeApplication
{
public Application(IntPtr javaReference, JniHandleOwnership transfer)
: base(() => new AppHead(), javaReference, transfer)
{
ConfigureUniversalImageLoader();
}
private static void ConfigureUniversalImageLoader()
{
// Create global configuration and initialize ImageLoader with this config
ImageLoaderConfiguration config = new ImageLoaderConfiguration
.Builder(Context)
.Build();
ImageLoader.Instance.Init(config);
ImageSource.DefaultImageLoader = ImageLoader.Instance.LoadImageAsync;
}
}
}
@@ -0,0 +1,17 @@
using Android.App;
using Android.Content.PM;
using Android.OS;
using Android.Views;
using Android.Widget;
namespace TestApp.Droid
{
[Activity(
MainLauncher = true,
ConfigurationChanges = global::Uno.UI.ActivityHelper.AllConfigChanges,
WindowSoftInputMode = SoftInput.AdjustNothing | SoftInput.StateHidden
)]
public class MainActivity : Microsoft.UI.Xaml.ApplicationActivity
{
}
}
@@ -0,0 +1,47 @@
To add cross-platform image assets for your Uno Platform app, use the Assets folder
in the shared project instead. Resources in this folder are Android-only.
Images, layout descriptions, binary blobs and string dictionaries can be included
in your application as resource files. Various Android APIs are designed to
operate on the resource IDs instead of dealing with images, strings or binary blobs
directly.
For example, a sample Android app that contains a user interface layout (main.axml),
an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
would keep its resources in the "Resources" directory of the application:
Resources/
drawable/
icon.png
layout/
main.axml
values/
strings.xml
In order to get the build system to recognize Android resources, set the build action to
"AndroidResource". The native Android APIs do not operate directly with filenames, but
instead operate on resource IDs. When you compile an Android application that uses resources,
the build system will package the resources for distribution and generate a class called "R"
(this is an Android convention) that contains the tokens for each one of the resources
included. For example, for the above Resources layout, this is what the R class would expose:
public class R {
public class drawable {
public const int icon = 0x123;
}
public class layout {
public const int main = 0x456;
}
public class strings {
public const int first_string = 0xabc;
public const int second_string = 0xbcd;
}
}
You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main
to reference the layout/main.axml file, or R.strings.first_string to reference the first
string in the dictionary file values/strings.xml.
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="Hello">Hello World, Click Me!</string>
<string name="ApplicationName">TestApp</string>
</resources>
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light">
<!-- This removes the ActionBar -->
<item name="windowActionBar">false</item>
<item name="android:windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowNoTitle">true</item>
<!-- This property is used for the splash screen -->
<item name="android:windowSplashScreenBackground">#FFFFFF</item>
<item name="android:windowBackground">@drawable/splash_screen</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/splash_screen</item>
<!--<item name="android:windowSplashScreenBehavior">1</item>-->
</style>
<style name="Theme.AppCompat.Translucent">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">@android:style/Animation</item>
</style>
</resources>
@@ -0,0 +1,2 @@
# See this for more details: http://developer.xamarin.com/guides/android/advanced_topics/garbage_collection/
MONO_GC_PARAMS=bridge-implementation=tarjan,nursery-size=32m,soft-heap-limit=256m
@@ -0,0 +1,50 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net7.0-android</TargetFrameworks>
<SingleProject>true</SingleProject>
<OutputType>Exe</OutputType>
<!-- Display name -->
<ApplicationTitle>TestApp</ApplicationTitle>
<!-- App Identifier -->
<ApplicationId>DGM.HoC.TestApp</ApplicationId>
<ApplicationIdGuid>BC40C823-CF9C-4044-B461-E81F461FBAEF</ApplicationIdGuid>
<!-- Versions -->
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
<ApplicationVersion>1</ApplicationVersion>
<AndroidManifest>Android\AndroidManifest.xml</AndroidManifest>
<!-- Debugger workaround https://github.com/dotnet/maui-samples/blob/8aa6b8780b12e97b157514c3bdc54bb4a13001cd/HelloMacCatalyst/HelloMacCatalyst.csproj#L7 -->
<!-- <MtouchExtraArgs Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">$(MtouchExtraArgs) -setenv:MONO_THREADS_SUSPEND=preemptive</MtouchExtraArgs> -->
<!-- Required for C# Hot Reload -->
<UseInterpreter Condition="'$(Configuration)' == 'Debug' and $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) != 'maccatalyst'">True</UseInterpreter>
<IsUnoHead>true</IsUnoHead>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Uno.Resizetizer" Version="1.0.4" />
<PackageReference Include="Uno.WinUI" Version="4.8.33" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.1.0" />
<PackageReference Include="Uno.Toolkit.WinUI" Version="2.5.5" />
<PackageReference Include="Uno.Extensions.Hosting.WinUI" Version="2.3.10" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="7.0.0" />
<PackageReference Include="Uno.Extensions.Logging.OSLog" Version="1.4.0" />
<PackageReference Include="Uno.UI.Adapter.Microsoft.Extensions.Logging" Version="4.8.33" />
<PackageReference Include="Uno.WinUI.RemoteControl" Version="4.8.33" Condition="'$(Configuration)'=='Debug'" />
</ItemGroup>
<Choose>
<When Condition="$(IsAndroid)">
<ItemGroup>
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.8.0" />
<PackageReference Include="Uno.UniversalImageLoader" Version="1.9.36" />
</ItemGroup>
<ItemGroup>
<AndroidEnvironment Include="Android/environment.conf" />
</ItemGroup>
</When>
</Choose>
<ItemGroup>
<ProjectReference Include="..\TestApp\TestApp.csproj" />
</ItemGroup>
<Import Project="..\TestApp.Base\base.props" />
</Project>
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap rescap">
<Identity
Name="C22E9F46-08B4-494A-99E8-99CBC48F9B44"
Publisher="O=TestApp"
Version="1.0.0.0" />
<Properties>
<DisplayName>TestApp</DisplayName>
<PublisherDisplayName>TestApp</PublisherDisplayName>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="TestApp"
Description="TestApp">
<uap:SplashScreen BackgroundColor="#086AD1"/>
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<rescap:Capability Name="runFullTrust" />
</Capabilities>
</Package>
+22
View File
@@ -0,0 +1,22 @@
using GLib;
using System;
using Uno.UI.Runtime.Skia;
namespace TestApp.Skia.Gtk
{
public class Program
{
public static void Main(string[] args)
{
ExceptionManager.UnhandledException += delegate (UnhandledExceptionArgs expArgs)
{
Console.WriteLine("GLIB UNHANDLED EXCEPTION" + expArgs.ExceptionObject.ToString());
expArgs.ExitApplication = true;
};
var host = new GtkHost(() => new AppHead(), args);
host.Run();
}
}
}
@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType Condition="'$(Configuration)'=='Release'">WinExe</OutputType>
<OutputType Condition="'$(Configuration)'=='Debug'">Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Package.appxmanifest" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Uno.Resizetizer" Version="1.0.4" />
<PackageReference Include="Uno.WinUI.Skia.Gtk" Version="4.8.33" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.1.0" />
<PackageReference Include="Uno.Toolkit.WinUI" Version="2.5.5" />
<PackageReference Include="Uno.Extensions.Hosting.WinUI" Version="2.3.10" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="7.0.0" />
<PackageReference Include="SkiaSharp.Views.Uno.WinUI" Version="2.88.3" />
<PackageReference Include="SkiaSharp.Skottie" Version="2.88.3" />
<PackageReference Include="Uno.WinUI.RemoteControl" Version="4.8.33" Condition="'$(Configuration)'=='Debug'" />
<PackageReference Include="Uno.UI.Adapter.Microsoft.Extensions.Logging" Version="4.8.33" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TestApp\TestApp.csproj" />
</ItemGroup>
<Import Project="..\TestApp.Base\base.props" />
</Project>
+77
View File
@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="TestApp.Gtk"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options
If you want to change the Windows User Account Control level replace the
requestedExecutionLevel node with one of the following.
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
Specifying requestedExecutionLevel element will disable file and registry virtualization.
Remove this element if your application requires this virtualization for backwards
compatibility.
-->
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->
<!-- Windows Vista -->
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
<!-- Windows 7 -->
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
<!-- Windows 8 -->
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
<!-- Windows 8.1 -->
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
<!-- Windows 10 -->
<!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->
</application>
</compatibility>
<!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
DPIs. Windows Presentation Foundation (WPF) applications are automatically DPI-aware and do not need
to opt in. Windows Forms applications targeting .NET Framework 4.6 that opt into this setting, should
also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config. -->
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitor</dpiAwareness>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
</application>
<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
<!--
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
-->
</assembly>
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap rescap">
<Identity
Name="C22E9F46-08B4-494A-99E8-99CBC48F9B44"
Publisher="O=TestApp"
Version="1.0.0.0" />
<Properties>
<DisplayName>TestApp</DisplayName>
<PublisherDisplayName>TestApp</PublisherDisplayName>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="TestApp"
Description="TestApp">
<uap:SplashScreen BackgroundColor="#086AD1"/>
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<rescap:Capability Name="runFullTrust" />
</Capabilities>
</Package>
@@ -0,0 +1,10 @@
{
"profiles": {
"TestApp.Windows (Package)": {
"commandName": "MsixPackage"
},
"TestApp.Windows (Unpackaged)": {
"commandName": "Project"
}
}
}
@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Placeholder" xml:space="preserve">
<value>Hello World!</value>
</data>
</root>
@@ -0,0 +1,58 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net7.0-windows10.0.19041.0</TargetFramework>
<TargetPlatformMinVersion>10.0.18362.0</TargetPlatformMinVersion>
<RootNamespace>UnoWinUIQuickStart</RootNamespace>
<Platforms>x86;x64;arm64</Platforms>
<RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
<PublishProfile>win10-$(Platform).pubxml</PublishProfile>
<UseWinUI>true</UseWinUI>
<EnableMsixTooling>true</EnableMsixTooling>
</PropertyGroup>
<PropertyGroup>
<!-- Bundles the WinAppSDK binaries (Uncomment for unpackaged builds) -->
<!-- <WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained> -->
<!-- This bundles the .NET Core libraries (Uncomment for packaged builds) -->
<SelfContained>true</SelfContained>
</PropertyGroup>
<ItemGroup>
<Content Include="Images\**" />
<Manifest Include="$(ApplicationManifest)" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Uno.Resizetizer" Version="1.0.4" />
<PackageReference Include="Uno.WinUI" Version="4.9.45" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.2.230313.1" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.755" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="7.0.0" />
<PackageReference Include="Uno.Toolkit.WinUI" Version="3.0.5" />
<PackageReference Include="Uno.Extensions.Hosting.WinUI" Version="2.3.10" />
<PackageReference Include="Uno.Core.Extensions.Logging.Singleton" Version="4.0.1" />
<PackageReference Include="Uno.UI.Adapter.Microsoft.Extensions.Logging" Version="4.8.33" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
</ItemGroup>
<ItemGroup>
<!--
If you encounter this error message:
error NETSDK1148: A referenced assembly was compiled using a newer version of Microsoft.Windows.SDK.NET.dll.
Please update to a newer .NET SDK in order to reference this assembly.
This means that the two packages below must be aligned with the "build" version number of
the "Microsoft.Windows.SDK.BuildTools" package above, and the "revision" version number
must be the highest found in https://www.nuget.org/packages/Microsoft.Windows.SDK.NET.Ref.
-->
<!-- <FrameworkReference Update="Microsoft.Windows.SDK.NET.Ref" RuntimeFrameworkVersion="10.0.22621.28" />
<FrameworkReference Update="Microsoft.Windows.SDK.NET.Ref" TargetingPackVersion="10.0.22621.28" /> -->
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TestApp\TestApp.csproj" />
</ItemGroup>
<Import Project="..\TestApp.Base\base.props" />
</Project>
+15
View File
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="TestApp.Windows.app"/>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<!-- The combination of below two tags have the following effect:
1) Per-Monitor for >= Windows 10 Anniversary Update
2) System < Windows 10 Anniversary Update
-->
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
</windowsSettings>
</application>
</assembly>
+83
View File
@@ -0,0 +1,83 @@
using DGM.HoC.BookMng.API.RPC;
using DGM.HoC.CRM.API.RPC;
using Grpc.Net.Client;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using TestApp.Business.Config;
using TestApp.Business.DAO;
using TestApp.Business.Mapper;
using Uno.Extensions;
using Uno.Extensions.Configuration;
using Uno.Extensions.Configuration.Internal;
namespace TestApp
{
public class App : Application
{
private static Window? _window;
public static IHost? Host { get; private set; }
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
var builder = this.CreateBuilder(args)
.Configure(host => host
#if DEBUG
// Switch to Development environment when running in DEBUG
.UseEnvironment(Environments.Development)
#endif
.UseConfiguration(configure: configBuilder => (
configBuilder.EmbeddedSource<App>()
.Section<NetworkSettings>()
))
.ConfigureServices((context, services) =>
{
// TODO: Register your services
//services.AddSingleton<IMyService, MyService>();
services.AddScoped(service =>
{
var addr = context.Configuration["NetworkSettings:Url_CRMApi"] ?? "";
var channel = GrpcChannel.ForAddress(addr);
var crmClient = new rpcCRM.rpcCRMClient(channel);
return crmClient;
});
/*services.AddScoped(service =>
{
var channel = GrpcChannel.ForAddress(apiBookingMngConnString);
var bookingMngClient = new rpcBookMng.rpcBookMngClient(channel);
return bookingMngClient;
});*/
services.AddAutoMapper(typeof(apiCRM_MappingProfile));
services.AddSingleton(typeof(apiCRM_Service));
})
);
_window = builder.Window;
Host = builder.Build();
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (_window.Content is not Frame rootFrame)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
// Place the frame in the current Window
_window.Content = rootFrame;
}
if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
rootFrame.Navigate(typeof(MainPage), args.Arguments);
}
// Ensure the current window is active
_window.Activate();
}
}
}
+13
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">
<ResourceDictionary.MergedDictionaries>
<!-- Load WinUI resources -->
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Load Uno.UI.Toolkit resources -->
<ToolkitResources xmlns="using:Uno.Toolkit.UI" />
</ResourceDictionary.MergedDictionaries>
<!-- Add resources here -->
</ResourceDictionary>
+3
View File
@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16 7H3.83L9.42 1.41L8 0L0 8L8 16L9.41 14.59L3.83 9H16V7Z" fill="#1C1B1F"/>
</svg>

After

Width:  |  Height:  |  Size: 188 B

+34
View File
@@ -0,0 +1,34 @@
See documentation about assets here : https://github.com/unoplatform/uno/blob/master/doc/articles/features/working-with-assets.md
# Here is a cheat sheet:
1. Add the image file to the `Assets` directory of a shared project.
2. Set the build action to `Content`.
3. (Recommended) Provide an asset for various scales/dpi
## Examples
```
\Assets\Images\logo.scale-100.png
\Assets\Images\logo.scale-200.png
\Assets\Images\logo.scale-400.png
\Assets\Images\scale-100\logo.png
\Assets\Images\scale-200\logo.png
\Assets\Images\scale-400\logo.png
```
## Table of scales
| Scale | UWP | iOS | Android |
|-------|:-----------:|:--------:|:-------:|
| `100` | scale-100 | @1x | mdpi |
| `125` | scale-125 | N/A | N/A |
| `150` | scale-150 | N/A | hdpi |
| `200` | scale-200 | @2x | xhdpi |
| `300` | scale-300 | @3x | xxhdpi |
| `400` | scale-400 | N/A | xxxhdpi |
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestApp.Business.Config
{
public partial record NetworkSettings
{
public string? Url_CRMApi { get; set; }
public string? Url_BookingApi { get; set; }
}
}
@@ -0,0 +1,499 @@
using AutoMapper;
using DGM.HoC.CRM.API.RPC;
using Grpc.Net.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Threading.Channels;
using System.Threading.Tasks;
using TestApp.Business.Model;
namespace TestApp.Business.DAO
{
public class apiCRM_Service
{
ILogger<apiCRM_Service> _logger;
IMapper _mapper;
rpcCRM.rpcCRMClient? _grpcClient;
public apiCRM_Service(ILogger<apiCRM_Service> logger, IMapper mapper, rpcCRM.rpcCRMClient? grpcClient)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
_grpcClient = grpcClient ?? throw new ArgumentNullException(nameof(grpcClient));
}
#region Customer
public async Task<IEnumerable<CustomerModel>> GetCustomersAsync()
{
try
{
var call = _grpcClient.GetAllCustomersAsync(new Google.Protobuf.WellKnownTypes.Empty());
var rs = await call;
List<CustomerModel> list = new List<CustomerModel>();
foreach(var item in rs.CustomerList)
{
list.Add(_mapper.Map<CustomerModel>(item));
}
return list;
}
catch (Exception e)
{
//TODO: Handle Ex.
_logger.LogError(e, e.Message);
return new List<CustomerModel>();
}
}
public async Task<CustomerModel> GetCustomerByIdAsync(string customerID)
{
try
{
var call = _grpcClient.GetCustomerByIdAsync(new CustomerIdReq() { CustomerId = customerID });
var rs = await call;
return _mapper.Map<CustomerModel>(rs);
}
catch (Exception e)
{
//TODO: Handle Ex.
_logger.LogError(e, e.Message);
return null;
}
}
public async Task<IEnumerable<CustomerModel>> GetCustomersByFilter(CustomerFilterModel filter)
{
try
{
rpcCustomerFilter rpcFilter = _mapper.Map<CustomerFilterModel, rpcCustomerFilter>(filter);
if(filter.PageIndex is null || filter.PageSize is null)
{
rpcFilter.ClearPageIndex();
rpcFilter.ClearPageSize();
}
var call = _grpcClient.GetCustomersByFilterAsync(rpcFilter);
var rs = await call;
List<CustomerModel> list = new List<CustomerModel>();
list.AddRange(rs.CustomerList.Select(c => _mapper.Map<CustomerModel>(c)));
return list;
}
catch (Exception e)
{
//TODO: Handle Ex.
_logger.LogError(e, e.Message);
return new List<CustomerModel>();
}
}
public async Task<bool> AddCustomerAsync(CustomerModel customerToAdd)
{
try
{
rpcAddCustomerReq rpcCust = _mapper.Map<rpcAddCustomerReq>(customerToAdd);
var call = _grpcClient.AddCustomerAsync(rpcCust);
var response = await call.ResponseAsync;
var status = call.GetStatus();
if (status.StatusCode == Grpc.Core.StatusCode.OK)
{
_logger.LogInformation("Customer added with ID: {0}", customerToAdd.NIF);
return true;
}
else
{
_logger.LogInformation("{0}: {1}", status.StatusCode, status.Detail);
return false;
}
}
catch (Exception e)
{
//TODO: Handle Ex.
_logger.LogError(e, e.Message);
return false;
}
}
public async Task<bool> RemoveCustomerAsync(CustomerModel customerToRemove)
{
if(customerToRemove is null)
{
return false;
}
return await RemoveCustomerAsync(customerToRemove.NIF);
}
public async Task<bool> RemoveCustomerAsync(string customerID)
{
try
{
var call = _grpcClient.RemoveCustomerAsync(new CustomerIdReq { CustomerId = customerID });
var response = await call.ResponseAsync;
var status = call.GetStatus();
if (status.StatusCode == Grpc.Core.StatusCode.OK)
{
_logger.LogInformation("Customer with ID: {0} removed", customerID);
return true;
}
else
{
_logger.LogInformation("{0}: {1}", status.StatusCode, status.Detail);
return false;
}
}
catch (Exception e)
{
_logger.LogInformation("{0}: {1}", e.Message, e.StackTrace);
return false;
}
}
public async Task<bool> UpdateCustomerAsync(CustomerModel customerToUpdate)
{
try
{
rpcUpdateCustomerReq rpcCust = _mapper.Map<rpcUpdateCustomerReq>(customerToUpdate);
var call = _grpcClient.UpdateCustomerAsync(rpcCust);
var response = await call.ResponseAsync;
var status = call.GetStatus();
if (status.StatusCode == Grpc.Core.StatusCode.OK)
{
_logger.LogInformation("Customer with ID: {0} Updated", customerToUpdate.NIF);
return true;
}
else
{
_logger.LogInformation("{0}: {1}", status.StatusCode, status.Detail);
return false;
}
}
catch (Exception e)
{
//TODO: Handle Ex.
_logger.LogError(e, e.Message);
return false;
}
}
#endregion
#region Customer Contacts
public async Task<IEnumerable<ContactDetailsModel>> GetContactsByCustomerAsync(string customerID)
{
try
{
var call = _grpcClient.GetContactDetailsByCustomerAsync(new CustomerIdReq() { CustomerId = customerID});
var rs = await call;
List<ContactDetailsModel> list = new List<ContactDetailsModel>();
foreach (var item in rs.ContactList)
{
list.Add(_mapper.Map<ContactDetailsModel>(item));
}
return list;
}
catch (Exception e)
{
//TODO: Handle Ex.
_logger.LogError(e, e.Message);
return new List<ContactDetailsModel>();
}
}
public async Task<bool> AddContactAsync(ContactDetailsModel contactToAdd)
{
try
{
rpcAddContactDetailsReq rpcCont = _mapper.Map<rpcAddContactDetailsReq>(contactToAdd);
var call = _grpcClient.AddCustomerContactAsync(rpcCont);
var response = await call.ResponseAsync;
var status = call.GetStatus();
if (status.StatusCode == Grpc.Core.StatusCode.OK)
{
_logger.LogInformation("Contact added for customer with ID: {0}", contactToAdd.CustomerNIF);
return true;
}
else
{
_logger.LogInformation("{0}: {1}", status.StatusCode, status.Detail);
return false;
}
}
catch (Exception e)
{
//TODO: Handle Ex.
_logger.LogError(e, e.Message);
return false;
}
}
public async Task<bool> RemoveContactAsync(ContactDetailsModel contactToRemove)
{
if(contactToRemove is null)
{
return false;
}
return await RemoveContactAsync(contactToRemove.Id);
}
public async Task<bool> RemoveContactAsync(int contactId)
{
try
{
var call = _grpcClient.RemoveCustomerContactAsync(new ContactIdReq { ContactId = contactId });
var response = await call.ResponseAsync;
var status = call.GetStatus();
if (status.StatusCode == Grpc.Core.StatusCode.OK)
{
_logger.LogInformation("Contact with ID: {0} removed", contactId);
return true;
}
else
{
_logger.LogInformation("{0}: {1}", status.StatusCode, status.Detail);
return false;
}
}
catch (Exception e)
{
_logger.LogInformation("{0}: {1}", e.Message, e.StackTrace);
return false;
}
}
public async Task<bool> UpdateContactAsync(ContactDetailsModel contactToUpdate)
{
try
{
rpcUpdateContactDetailsReq rpcCont = _mapper.Map<rpcUpdateContactDetailsReq>(contactToUpdate);
var call = _grpcClient.UpdateCustomerContactAsync(rpcCont);
var response = await call.ResponseAsync;
var status = call.GetStatus();
if (status.StatusCode == Grpc.Core.StatusCode.OK)
{
_logger.LogInformation("Contact with ID: {0} Updated", contactToUpdate.Id);
return true;
}
else
{
_logger.LogInformation("{0}: {1}", status.StatusCode, status.Detail);
return false;
}
}
catch (Exception e)
{
//TODO: Handle Ex.
_logger.LogError(e, e.Message);
return false;
}
}
#endregion
#region Customer Notes
public async Task<IEnumerable<NoteModel>> GetCustomerNotesAsync()
{
try
{
var call = _grpcClient.GetAllNotesAsync(new EmptyReq());
var rs = await call;
List<NoteModel> list = new List<NoteModel>();
foreach (var item in rs.NoteList)
{
list.Add(_mapper.Map<NoteModel>(item));
}
return list;
}
catch (Exception e)
{
//TODO: Handle Ex.
_logger.LogError(e, e.Message);
return new List<NoteModel>();
}
}
public async Task<IEnumerable<NoteModel>> GetCustomerNotesByCustomerAsync(CustomerModel model)
{
if(model is null)
{
return new List<NoteModel>();
}
return await GetCustomerNotesByCustomerAsync(model.NIF);
}
public async Task<IEnumerable<NoteModel>> GetCustomerNotesByCustomerAsync(string customerId)
{
try
{
var call = _grpcClient.GetNoteByCustomerAsync(new CustomerIdReq() { CustomerId = customerId});
var rs = await call;
List<NoteModel> list = new List<NoteModel>();
foreach (var item in rs.NoteList)
{
list.Add(_mapper.Map<NoteModel>(item));
}
return list;
}
catch (Exception e)
{
//TODO: Handle Ex.
_logger.LogError(e, e.Message);
return new List<NoteModel>();
}
}
public async Task<bool> AddCustomerNoteAsync(NoteModel noteToAdd)
{
try
{
rpcAddNoteReq rpcNt = _mapper.Map<rpcAddNoteReq>(noteToAdd);
var call = _grpcClient.AddNoteAsync(rpcNt);
var response = await call.ResponseAsync;
var status = call.GetStatus();
if (status.StatusCode == Grpc.Core.StatusCode.OK)
{
_logger.LogInformation("Note added for customer with ID: {0}", noteToAdd.CustomerNIF);
return true;
}
else
{
_logger.LogInformation("{0}: {1}", status.StatusCode, status.Detail);
return false;
}
}
catch (Exception e)
{
//TODO: Handle Ex.
_logger.LogError(e, e.Message);
return false;
}
}
public async Task<bool> RemoveCustomerNoteAsync(NoteModel noteToRemove)
{
if (noteToRemove is null)
{
return false;
}
return await RemoveContactAsync(noteToRemove.Id);
}
public async Task<bool> RemoveCustomerNoteAsync(int noteId)
{
try
{
var call = _grpcClient.RemoveNoteAsync(new NoteIdReq { NoteId = noteId });
var response = await call.ResponseAsync;
var status = call.GetStatus();
if (status.StatusCode == Grpc.Core.StatusCode.OK)
{
_logger.LogInformation("Note with ID: {0} removed", noteId);
return true;
}
else
{
_logger.LogInformation("{0}: {1}", status.StatusCode, status.Detail);
return false;
}
}
catch (Exception e)
{
_logger.LogInformation("{0}: {1}", e.Message, e.StackTrace);
return false;
}
}
public async Task<bool> UpdateCustomerNoteAsync(NoteModel noteToUpdate)
{
try
{
rpcUpdateNoteReq rpcNt = _mapper.Map<rpcUpdateNoteReq>(noteToUpdate);
var call = _grpcClient.UpdateNoteAsync(rpcNt);
var response = await call.ResponseAsync;
var status = call.GetStatus();
if (status.StatusCode == Grpc.Core.StatusCode.OK)
{
_logger.LogInformation("Note with ID: {0} Updated", noteToUpdate.Id);
return true;
}
else
{
_logger.LogInformation("{0}: {1}", status.StatusCode, status.Detail);
return false;
}
}
catch (Exception e)
{
//TODO: Handle Ex.
_logger.LogError(e, e.Message);
return false;
}
}
#endregion
}
}
@@ -0,0 +1,63 @@
using AutoMapper;
using Google.Protobuf.WellKnownTypes;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestApp.Business.Mapper
{
//String -> DateTime
public class StringToDateTimeConverter : ITypeConverter<string, DateTime>
{
public DateTime Convert(string source, DateTime destination, ResolutionContext context)
{
var esES = new CultureInfo("es-ES");
DateTime dateTime;
if (DateTime.TryParseExact(source, "dd/MM/yyyy", esES, DateTimeStyles.AllowLeadingWhite, out dateTime))
{
return dateTime;
}
return DateTime.UnixEpoch;
}
}
//DateTime -> String (Format dd/MM/yyyy).
public class DateTimeToStringConverter : ITypeConverter<DateTime, string>
{
public string Convert(DateTime source, string destination, ResolutionContext context)
{
return source.ToString("dd/MM/yyyy");
}
}
//DateTime -> grpc.Timestamp.
public class DateTimeToTimeStamp : ITypeConverter<DateTime, Google.Protobuf.WellKnownTypes.Timestamp>
{
public Timestamp Convert(DateTime source, Timestamp destination, ResolutionContext context)
{
//Timestamp.FromDateTime() requiere el time en UTC.
DateTime utcTime = source.Kind == DateTimeKind.Utc ? source : source.ToUniversalTime();
return Timestamp.FromDateTime(utcTime);
}
}
//grpc.Timestamp -> DateTime
public class TimeStampToDateTime : ITypeConverter<Google.Protobuf.WellKnownTypes.Timestamp, DateTime>
{
public DateTime Convert(Timestamp source, DateTime destination, ResolutionContext context)
{
if (source is null)
{
return DateTime.UnixEpoch;
}
return source.ToDateTime();
}
}
}
@@ -0,0 +1,60 @@
using AutoMapper;
using DGM.HoC.CRM.API.RPC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TestApp.Business.Model;
namespace TestApp.Business.Mapper
{
public class apiCRM_MappingProfile : Profile
{
public apiCRM_MappingProfile()
{
//DateTime <--> String Mapping.
CreateMap<string, DateTime>().ConvertUsing<StringToDateTimeConverter>();
CreateMap<DateTime, string>().ConvertUsing<DateTimeToStringConverter>();
//DateTime <--> grpc.Timestamp Mapping.
CreateMap<Google.Protobuf.WellKnownTypes.Timestamp, DateTime>().ConvertUsing<TimeStampToDateTime>();
CreateMap<DateTime, Google.Protobuf.WellKnownTypes.Timestamp>().ConvertUsing<DateTimeToTimeStamp>();
CreateMap<rpcAddress, AddressModel>(MemberList.Source);
CreateMap<AddressModel, rpcAddress>().ForAllMembers(map => map.NullSubstitute(""));
CreateMap<ContactDetailsModel, rpcContact>(MemberList.Destination).ForMember(dest => dest.Value, opt => opt.MapFrom(src => src.ContactValue));
CreateMap<rpcContact, ContactDetailsModel>(MemberList.Source).ForMember(dest => dest.ContactValue, opt => opt.MapFrom(src => src.Value));
CreateMap<CustomerModel, rpcCustomer>(MemberList.Destination);
CreateMap<rpcCustomer, CustomerModel>(MemberList.Source);
CreateMap<NoteModel, rpcNote>(MemberList.Destination);
CreateMap<rpcNote, NoteModel>(MemberList.Source);
CreateMap<CustomerModel, rpcAddCustomerReq>(MemberList.Destination);
CreateMap<CustomerModel, rpcUpdateCustomerReq>(MemberList.Destination);
CreateMap<rpcAddCustomerReq, CustomerModel>(MemberList.Source);
//CreateMap<rpcUpdateCustomerReq, CustomerModel>(MemberList.None);
CreateMap<NoteModel, rpcAddNoteReq>(MemberList.Destination);
CreateMap<NoteModel, rpcUpdateNoteReq>(MemberList.Destination);
CreateMap<rpcAddNoteReq, NoteModel>(MemberList.Source);
//CreateMap<rpcUpdateNoteReq, CustomerNoteModel>(MemberList.None);
CreateMap<ContactDetailsModel, rpcAddContactDetailsReq>(MemberList.Destination).ForMember(dest => dest.Value, opt => opt.MapFrom(src => src.ContactValue));
CreateMap<ContactDetailsModel, rpcUpdateContactDetailsReq>(MemberList.Destination).ForMember(dest => dest.Value, opt => opt.MapFrom(src => src.ContactValue));
CreateMap<rpcAddContactDetailsReq, ContactDetailsModel>(MemberList.Source).ForMember(dest => dest.ContactValue, opt => opt.MapFrom(src => src.Value));
//CreateMap<rpcUpdateContactDetailsReq, ContactDetailsModel>(MemberList.None);
CreateMap<CustomerFilterModel, rpcCustomerFilter>(MemberList.Destination);
CreateMap<rpcCustomerFilter, CustomerFilterModel>(MemberList.Source);
}
}
}
@@ -0,0 +1,69 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestApp.Business.Model
{
public class AddressModel : ObservableObject
{
private string? tipoVia;
private string? nombreVia;
private string? numero;
private string? provincia;
private string? poblacion;
private string? codigoPostal;
private string? pais;
public string? TipoVia
{
get => tipoVia;
set => SetProperty(ref tipoVia, value);
}
public string? NombreVia
{
get => nombreVia;
set => SetProperty(ref nombreVia, value);
}
public string? Numero
{
get => numero;
set => SetProperty(ref numero, value);
}
public string? Provincia
{
get => provincia;
set => SetProperty(ref provincia, value);
}
public string? Poblacion
{
get => poblacion;
set => SetProperty(ref poblacion, value);
}
public string? CodigoPostal
{
get => codigoPostal;
set => SetProperty(ref codigoPostal, value);
}
public string? Pais
{
get => pais;
set => SetProperty(ref pais, value);
}
public void updateData(AddressModel model)
{
this.TipoVia = model.tipoVia;
this.NombreVia = model.nombreVia;
this.Numero = model.numero;
this.Provincia = model.provincia;
this.Poblacion = model.poblacion;
this.CodigoPostal = model.codigoPostal;
this.Pais = model.pais;
}
}
}
@@ -0,0 +1,55 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestApp.Business.Model
{
public class ContactDetailsModel : ObservableObject
{
private int id;
private string type;
private string contactValue;
private string comment;
private string customerNIF;
public int Id
{
get => id;
set => SetProperty(ref id, value);
}
public string Type
{
get => type;
set => SetProperty(ref type, value);
}
public string ContactValue
{
get => contactValue;
set => SetProperty(ref contactValue, value);
}
public string Comment
{
get => comment;
set => SetProperty(ref comment, value);
}
public string CustomerNIF
{
get => customerNIF;
set => SetProperty(ref customerNIF, value);
}
public void updateData(ContactDetailsModel model)
{
this.Type = model.type;
this.ContactValue = model.contactValue;
this.Comment = model.comment;
}
}
}
@@ -0,0 +1,48 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Uno.Extensions.Configuration;
namespace TestApp.Business.Model
{
public partial class CustomerFilterModel : ObservableObject
{
[ObservableProperty]
private string nif;
[ObservableProperty]
private string name;
[ObservableProperty]
private string contactData;
[ObservableProperty]
private bool strict = false;
//If null -> Results are not paginated.
[ObservableProperty]
private int? pageSize;
[ObservableProperty]
private int? pageIndex;
public CustomerFilterModel(string nif, string name, string contactData, bool strict, int pageSize, int pageIndex)
{
Nif = nif;
Name = name;
ContactData = contactData;
Strict = strict;
PageSize = pageSize;
PageIndex = pageIndex;
}
public CustomerFilterModel()
{
Nif = string.Empty;
Name = string.Empty;
ContactData = string.Empty;
Strict = false;
PageSize = null;
PageIndex = null;
}
}
}
@@ -0,0 +1,62 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestApp.Business.Model
{
public class CustomerModel : ObservableObject
{
private string nif;
private string name;
private AddressModel customerAddress = new AddressModel();
private DateTime createTime = DateTime.UnixEpoch;
private DateTime lastUsedTime = DateTime.UnixEpoch;
public string NIF
{
get => nif;
set => SetProperty(ref nif, value);
}
public string Name
{
get => name;
set => SetProperty(ref name, value);
}
public AddressModel CustomerAddress
{
get => customerAddress;
set => SetProperty(ref customerAddress, value);
}
public DateTime CreateTime
{
get => createTime;
set => SetProperty(ref createTime, value);
}
public DateTime LastUsedTime
{
get => lastUsedTime;
set => SetProperty(ref lastUsedTime, value);
}
public void updateData(CustomerModel model)
{
this.NIF = model.nif;
this.Name = model.name;
this.CreateTime = model.createTime;
this.LastUsedTime = model.lastUsedTime;
this.CustomerAddress = model.customerAddress;
//this.Address.updateData(model.address);
}
}
}
@@ -0,0 +1,66 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestApp.Business.Model
{
public class NoteModel : ObservableObject
{
private int id;
private string status;
private string data;
private string customerNIF;
private DateTime createTime;
private CustomerModel customer;
public int Id
{
get => id;
set => SetProperty(ref id, value);
}
public string Status
{
get => status;
set => SetProperty(ref status, value);
}
public string Data
{
get => data;
set => SetProperty(ref data, value);
}
public string CustomerNIF
{
get => customerNIF;
set => SetProperty(ref customerNIF, value);
}
public DateTime CreateTime
{
get => createTime;
set => SetProperty(ref createTime, value);
}
public CustomerModel Customer
{
get => customer;
set => SetProperty(ref customer, value);
}
public void UpdateData(NoteModel note)
{
this.Id = note.id;
this.Status = note.status;
this.Data = note.data;
this.CustomerNIF = note.customerNIF;
this.CreateTime = note.createTime;
if(note.customer is not null)
{
this.Customer = customer;
}
}
}
}
@@ -0,0 +1,33 @@
<ContentDialog
x:Class="TestApp.Controls.ContactDetailsDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestApp.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="TITLE"
Style="{ThemeResource DefaultContentDialogStyle}"
PrimaryButtonText="Guardar"
PrimaryButtonClick="ContentDialog_PrimaryButtonClick"
CloseButtonText="Cancelar">
<StackPanel x:Name="MainPanel"
Orientation="Vertical"
HorizontalAlignment="Stretch" Spacing="8">
<TextBox x:Name="txtContactId"
Header="Contact.Id" Text="{x:Bind viewModel.Id, Mode=TwoWay}"
IsReadOnly="True"
Margin="5"/>
<TextBox x:Name="txtContactType"
Header="Contact.Id" Text="{x:Bind viewModel.Type, Mode=TwoWay}"
Margin="5"/>
<ComboBox x:Name="CmbContactType"
ItemsSource="{x:Bind contactTypes}"
SelectedValue="{x:Bind viewModel.Type, Mode=TwoWay}"
Visibility="Collapsed"/>
<TextBox x:Name="txtContactValue"
Header="Contact.Value" Text="{x:Bind viewModel.ContactValue, Mode=TwoWay}"
Margin="5"/>
<TextBox x:Name="txtContactComment"
Header="Contact.Comment" Text="{x:Bind viewModel.Comment, Mode=TwoWay}"
Margin="5"/>
</StackPanel>
</ContentDialog>
@@ -0,0 +1,61 @@
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 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 TestApp.Business.Model;
using CommunityToolkit.Mvvm.ComponentModel;
using System.ComponentModel;
namespace TestApp.Controls
{
public sealed partial class ContactDetailsDialog : ContentDialog
{
public ContactDetailsModel? viewModel;
public bool isNewContact = false;
public List<string> contactTypes;
public ContactDetailsDialog()
{
this.InitializeComponent();
contactTypes = new List<string>
{
"Phone",
"Email",
"Other"
};
if(viewModel is null)
{
viewModel = new ContactDetailsModel();
}
}
public void CreateNewContact(string customerId)
{
viewModel = new ContactDetailsModel();
viewModel.CustomerNIF = customerId;
PrimaryButtonText = "Crear";
}
private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
{
}
}
}
@@ -0,0 +1,31 @@
<ContentDialog
x:Class="TestApp.Controls.Notes.NoteDetailsDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestApp.Controls.Notes"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Style="{ThemeResource DefaultContentDialogStyle}"
PrimaryButtonText="Save"
CloseButtonText="Cancel">
<Grid x:Name="MainPanel"
MinWidth="350" MinHeight="200">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<TextBox x:Name="txtNoteData"
Grid.Column="0" Grid.Row="0"
Text="{x:Bind viewModel.Data, Mode=TwoWay}"
TextWrapping="Wrap"
IsReadOnly="{x:Bind IsReadOnly}"/>
<TextBox x:Name="txtNoteStatus"
Grid.Column="0" Grid.Row="1"
Margin="0 10 0 0"
Header="Status"
Text="{x:Bind viewModel.Status, Mode=TwoWay}" TextWrapping="Wrap"
IsReadOnly="{x:Bind IsReadOnly}"/>
</Grid>
</ContentDialog>
@@ -0,0 +1,58 @@
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 TestApp.Business.Model;
using Windows.Foundation;
using Windows.Foundation.Collections;
namespace TestApp.Controls.Notes
{
public sealed partial class NoteDetailsDialog : ContentDialog
{
public NoteModel? viewModel { get; set; }
public bool IsReadOnly { get; set; }
public NoteDetailsDialog()
{
this.InitializeComponent();
if(viewModel is null)
{
viewModel = new NoteModel();
}
IsReadOnly = true;
}
public void CreateNewNote()
{
viewModel = new NoteModel();
IsReadOnly = false;
PrimaryButtonText = "Add";
}
public void EditNote()
{
IsReadOnly = false;
PrimaryButtonText = "Save";
}
private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
{
}
private void ContentDialog_SecondaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
{
}
}
}
@@ -0,0 +1,53 @@
<UserControl
x:Class="TestApp.Controls.NoteViewer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestApp.Controls"
xmlns:models="using:TestApp.Business.Model"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<UserControl.Resources>
<DataTemplate x:Key="NoteTemplate" x:DataType="models:NoteModel">
<RelativePanel MinWidth="325" Width="300"
Padding="15">
<TextBlock x:Name="txtNoteTitle"
RelativePanel.AlignVerticalCenterWith="btDeleteNote"
Text="Note"/>
<Button x:Name="btDeleteNote"
RelativePanel.AlignRightWithPanel="True" RelativePanel.AlignTopWithPanel="True"
Content="delete"/>
<TextBlock x:Name="txtNoteText"
RelativePanel.Below="txtNoteTitle" Text="{x:Bind Data}"
TextWrapping="Wrap"/>
<TextBlock x:Name="txtNoteStatus"
RelativePanel.Below="txtNoteText"
Text="{x:Bind Status}"/>
</RelativePanel>
</DataTemplate>
</UserControl.Resources>
<GridView x:Name="NoteViewerGridView"
ItemTemplate="{StaticResource NoteTemplate}"
IsItemClickEnabled="True" SelectionMode="Single"
ItemClick="NoteViewerGridView_ItemClick"
ItemsSource="{x:Bind NoteList}"
SelectedItem="{x:Bind SelectedNote, Mode=TwoWay}"
Padding="15"
Background="{StaticResource CardBackgroundFillColorDefault}"
CornerRadius="5"
CanReorderItems="True" AllowDrop="True">
<GridView.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="Margin" Value="15"/>
<Setter Property="BorderBrush" Value="MediumAquamarine"/>
<Setter Property="BorderThickness" Value="1"/>
</Style>
</GridView.ItemContainerStyle>
</GridView>
</UserControl>
@@ -0,0 +1,69 @@
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 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.Collections.ObjectModel;
using TestApp.Business.Model;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.ComponentModel;
using System.ComponentModel;
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
namespace TestApp.Controls
{
public sealed partial class NoteViewer : UserControl
{
public ObservableCollection<NoteModel> NoteList
{
get => (ObservableCollection<NoteModel>)GetValue(NoteListProp);
set => SetValue(NoteListProp, value);
}
public NoteModel SelectedNote
{
get => (NoteModel)GetValue(SelectedNoteProperty);
set => SetValue(SelectedNoteProperty, value);
}
public static readonly DependencyProperty NoteListProp = DependencyProperty.Register(
nameof(NoteList),
typeof(ObservableCollection<NoteModel>),
typeof(NoteViewer),
new PropertyMetadata(new ObservableCollection<NoteModel>()));
public static readonly DependencyProperty SelectedNoteProperty = DependencyProperty.Register(
nameof(SelectedNote),
typeof(NoteModel),
typeof(NoteViewer),
null);
public NoteViewer()
{
this.InitializeComponent();
if(NoteList is null)
{
NoteList = new ObservableCollection<NoteModel>();
}
SelectedNote = null;
}
private void NoteViewerGridView_ItemClick(object sender, ItemClickEventArgs e)
{
}
}
}
+18
View File
@@ -0,0 +1,18 @@
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Hosting;
global using Microsoft.Extensions.Logging;
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 System;
global using System.Collections.Generic;
global using System.Collections.Immutable;
global using System.Linq;
global using System.Net.Http;
global using System.Threading;
global using System.Threading.Tasks;
global using Uno.Extensions.Hosting;
global using Windows.ApplicationModel;
global using Application = Microsoft.UI.Xaml.Application;
global using ApplicationExecutionState = Windows.ApplicationModel.Activation.ApplicationExecutionState;
+21
View File
@@ -0,0 +1,21 @@
<Page x:Class="TestApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<NavigationView x:Name="NavView"
ItemInvoked="NavView_ItemInvoked"
AlwaysShowHeader="False">
<NavigationView.MenuItems>
<NavigationViewItem Icon="Home" Content="Home" Tag="TestApp.Pages.HomePage" />
<NavigationViewItem Icon="Contact2" Content="Clientes" Tag="TestApp.Pages.CustomerListPage" />
<NavigationViewItem Icon="Account" Content="Detalles Cliente" Tag="TestApp.Pages.CustomerDetailsPage" />
<NavigationViewItem x:Name="navItem_DevTests" Icon="ContactInfo" Content="Test" Tag="TestApp.Pages.TestPage" />
</NavigationView.MenuItems>
<Frame x:Name="ContentFrame" Navigated="ContentFrame_Navigated" Padding="0,0,0,0"/>
</NavigationView>
</Page>
+80
View File
@@ -0,0 +1,80 @@
using Microsoft.Extensions.Configuration;
using Microsoft.UI.Xaml.Media.Animation;
namespace TestApp
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
NavView.SelectedItem = NavView.MenuItems.OfType<NavigationViewItem>().First();
ContentFrame.Navigate(
typeof(Pages.HomePage),
null,
new Microsoft.UI.Xaml.Media.Animation.EntranceNavigationTransitionInfo());
}
private void NavView_ItemInvoked(NavigationView sender,
NavigationViewItemInvokedEventArgs args)
{
if (args.IsSettingsInvoked == true)
{
HandleNavigation("settings", args.RecommendedNavigationTransitionInfo);
}
else if (args != null && args.InvokedItemContainer != null && args.InvokedItemContainer.Tag != null)
{
HandleNavigation(args.InvokedItemContainer.Tag.ToString(), args.RecommendedNavigationTransitionInfo);
}
}
private void ContentFrame_Navigated(object sender, NavigationEventArgs e)
{
NavView.IsBackEnabled = ContentFrame.CanGoBack;
if (ContentFrame.SourcePageType == typeof(Pages.SettingsPage))
{
// SettingsItem is not part of NavView.MenuItems, and doesn't have a Tag.
NavView.SelectedItem = (NavigationViewItem)NavView.SettingsItem;
}
else if (ContentFrame.SourcePageType != null)
{
NavView.SelectedItem = NavView.MenuItems
.OfType<NavigationViewItem>()
.First(n => n.Tag.Equals(ContentFrame.SourcePageType.FullName?.ToString()));
}
NavView.Header = ((NavigationViewItem)NavView.SelectedItem)?.Content?.ToString();
}
private void HandleNavigation(string navItemTag, NavigationTransitionInfo transitionInfo)
{
Type? _page = null;
if (navItemTag is null) { return; }
if (navItemTag == "settings")
{
_page = typeof(Pages.SettingsPage);
}
else
{
_page = Type.GetType(navItemTag);
}
var preNavPageType = ContentFrame.CurrentSourcePageType;
if (!(_page is null) && !Type.Equals(preNavPageType, _page))
{
ContentFrame.Navigate(_page, null, transitionInfo);
}
}
private void DisableDevelopmentPages()
{
navItem_DevTests.Visibility = Visibility.Collapsed;
}
}
}
@@ -0,0 +1,287 @@
<Page
x:Class="TestApp.Pages.CustomerDetailsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestApp.Pages"
xmlns:model="using:TestApp.Business.Model"
xmlns:controls="using:TestApp.Controls"
xmlns:converters="using:CommunityToolkit.WinUI.UI.Converters"
xmlns:myconverters="using:TestApp.Utils.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<DataTemplate x:Key="ContactListViewTemplate" x:DataType="model:ContactDetailsModel">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Ellipse x:Name="Ellipse"
Grid.RowSpan="2"
Width ="32"
Height="32"
Margin="6"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Fill="{ThemeResource SystemControlBackgroundBaseMediumBrush}"/>
<TextBlock Grid.Column="1"
Text="{x:Bind ContactValue}"
x:Phase="1"
Style="{ThemeResource BaseTextBlockStyle}"
Margin="12,6,0,0"/>
<TextBlock Grid.Column="1"
Grid.Row="1"
Text="{x:Bind Comment}"
x:Phase="2"
Style="{ThemeResource BodyTextBlockStyle}"
Margin="12,0,0,6"/>
</Grid>
</DataTemplate>
<converters:BoolToVisibilityConverter x:Key="boolToVisConv"/>
<converters:BoolNegationConverter x:Key="boolNegConv"/>
<myconverters:InvBoolToVisibilityConverter x:Key="invBoolToVisConv"/>
</Page.Resources>
<Pivot Margin="15" Background="{StaticResource AcrylicBackgroundFillColorDefaultBrush}">
<PivotItem Header="Datos">
<Grid x:Name="MainGrid"
RowSpacing="8"
Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Title and command bar -->
<RelativePanel x:Name="TopBarPanel" Margin="10"
Grid.Row="0">
<TextBlock x:Name="PageTitle"
Text="Detalles cliente"
Style="{StaticResource TitleTextBlockStyle}"/>
<CommandBar x:Name="MainCommandBar"
HorizontalAlignment="Stretch"
Background="Transparent"
DefaultLabelPosition="Right"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.RightOf="PageTitle">
<AppBarButton x:Name="btCreateCustomer" Label="Add Customer" Icon="Add" Click="btCreateCustomer_Click"/>
<AppBarButton x:Name="btDeleteCustomer" Label="Delete Customer" Icon="Delete" Click="btDeleteCustomer_Click"/>
<AppBarSeparator/>
<AppBarToggleButton x:Name="btToggleEditMode"
Label="Edit" Icon="Edit"
IsChecked="{x:Bind viewModel.IsEditMode, Mode=TwoWay}"
IsEnabled="{x:Bind viewModel.IsEditMode, Converter={StaticResource boolNegConv}, Mode=OneWay}"/>
<AppBarButton x:Name="btSaveDetails"
Label="Save" Icon="Save"
Click="btSaveDetails_Click"
Visibility="{x:Bind viewModel.IsEditMode, Converter={StaticResource boolToVisConv}, Mode=OneWay}"/>
<AppBarButton x:Name="btCancelEdit"
Label="Cancel" Icon="Cancel"
Click="btCancelEdit_Click"
IsEnabled="{x:Bind viewModel.IsNewCustomer, Converter={StaticResource boolNegConv}, Mode=OneWay}"
Visibility="{x:Bind viewModel.IsEditMode, Converter={StaticResource boolToVisConv}, Mode=OneWay}"/>
<AppBarSeparator/>
<AppBarButton x:Name="btClientSync" Click="btClientSync_Click" Label="Sync" Icon="Sync"/>
<AppBarSeparator/>
<AppBarButton x:Name="btCloseDetails" Click="btCloseDetails_Click" Label="Close" Icon="ClosePane"/>
</CommandBar>
</RelativePanel>
<!-- Info bar -->
<InfoBar x:Name="infoBar"
Grid.Row="1"
Margin="0 0 20 0"
IsOpen="False"/>
<!-- Page Content -->
<ScrollViewer Grid.Row="2">
<Grid x:Name="ContentPanel"
RowSpacing="10"
Margin="0 0 20 25"
ScrollViewer.VerticalScrollMode="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<!-- General Tab -->
<Expander x:Name="xpCustomerGeneral"
Header="General" IsExpanded="True"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
Grid.Row="0">
<Expander.Content>
<StackPanel x:Name="panelCustomerGeneral"
VerticalAlignment="Center" Margin="10 0 25 0">
<TextBox x:Name="txtCustomerID"
Header="Customer ID" Text="{x:Bind viewModel.customer.NIF, Mode=TwoWay}"
Margin="5"/>
<TextBox x:Name="txtCustomerName"
Header="Customer Name" Text="{x:Bind viewModel.customer.Name, Mode=TwoWay}"
IsReadOnly="{x:Bind viewModel.IsEditMode, Converter={StaticResource boolNegConv}, Mode=OneWay}"
Margin="5"/>
</StackPanel>
</Expander.Content>
</Expander>
<!-- Address Tab -->
<Expander x:Name="xpCustomerAddress"
Header="Address"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
Grid.Row="1">
<Expander.Content>
<StackPanel x:Name="panelCustomerAddress"
VerticalAlignment="Center" Margin="10 0 25 0">
<TextBox x:Name="txtAddressTipoVia"
Header="Address.TipoVia" Text="{x:Bind viewModel.customer.CustomerAddress.TipoVia, Mode=TwoWay}"
IsReadOnly="{x:Bind viewModel.IsEditMode, Converter={StaticResource boolNegConv}, Mode=OneWay}"
Margin="5"/>
<TextBox x:Name="txtAddressNombreVia"
Header="Address.NombreVia" Text="{x:Bind viewModel.customer.CustomerAddress.NombreVia, Mode=TwoWay}"
IsReadOnly="{x:Bind viewModel.IsEditMode, Converter={StaticResource boolNegConv}, Mode=OneWay}"
Margin="5"/>
<TextBox x:Name="txtAddressNumero"
Header="Address.Numero" Text="{x:Bind viewModel.customer.CustomerAddress.Numero, Mode=TwoWay}"
IsReadOnly="{x:Bind viewModel.IsEditMode, Converter={StaticResource boolNegConv}, Mode=OneWay}"
Margin="5"/>
<TextBox x:Name="txtAddressProvincia"
Header="Address.Provincia" Text="{x:Bind viewModel.customer.CustomerAddress.Provincia, Mode=TwoWay}"
IsReadOnly="{x:Bind viewModel.IsEditMode, Converter={StaticResource boolNegConv}, Mode=OneWay}"
Margin="5"/>
<TextBox x:Name="txtAddressPoblacion"
Header="Address.Poblacion" Text="{x:Bind viewModel.customer.CustomerAddress.Poblacion, Mode=TwoWay}"
IsReadOnly="{x:Bind viewModel.IsEditMode, Converter={StaticResource boolNegConv}, Mode=OneWay}"
Margin="5"/>
<TextBox x:Name="txtAddressCodigoPostal"
Header="Address.CodigoPostal" Text="{x:Bind viewModel.customer.CustomerAddress.CodigoPostal, Mode=TwoWay}"
IsReadOnly="{x:Bind viewModel.IsEditMode, Converter={StaticResource boolNegConv}, Mode=OneWay}"
Margin="5"/>
<TextBox x:Name="txtAddressPais"
Header="Address.Pais" Text="{x:Bind viewModel.customer.CustomerAddress.Pais, Mode=TwoWay}"
IsReadOnly="{x:Bind viewModel.IsEditMode, Converter={StaticResource boolNegConv}, Mode=OneWay}"
Margin="5"/>
</StackPanel>
</Expander.Content>
</Expander>
<!-- Customer Contact Details-->
<Expander x:Name="xpCustomerContacts"
Header="Contact Data"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
Grid.Row="2">
<Expander.Content>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ListView x:Name="ContactListPanel"
Grid.Column="0"
ItemTemplate="{StaticResource ContactListViewTemplate}"
SelectionMode="Single"
ItemsSource="{x:Bind viewModel.customerContacts, Mode=OneWay}"
SelectedItem="{x:Bind viewModel.selectedContact, Mode=TwoWay}"
Visibility="{x:Bind viewModel.HasContacts, Converter={StaticResource boolToVisConv}, Mode=OneWay}">
</ListView>
<TextBlock Text="Empty"
Grid.Column="0"
VerticalAlignment="Center" HorizontalAlignment="Center"
Visibility="{x:Bind viewModel.HasContacts, Converter={StaticResource invBoolToVisConv}, Mode=OneWay}"/>
<StackPanel x:Name="ContactControlsPanel"
Grid.Column="1">
<Button x:Name="btAddContact"
Click="btAddContact_Click"
IsEnabled="{x:Bind viewModel.IsNewCustomer, Converter={StaticResource boolNegConv}, Mode=OneWay}"
Margin="8">
<StackPanel Orientation="Horizontal" Spacing="10">
<SymbolIcon Symbol="Add"/>
<TextBlock Text="Add Contact"/>
</StackPanel>
</Button>
<Button x:Name="btUpdateContact"
Click="btUpdateContact_Click"
IsEnabled="{x:Bind viewModel.IsNewCustomer, Converter={StaticResource boolNegConv}, Mode=OneWay}"
Margin="8">
<StackPanel Orientation="Horizontal" Spacing="10">
<SymbolIcon Symbol="Edit"/>
<TextBlock Text="Update Contact"/>
</StackPanel>
</Button>
<Button x:Name="btDeleteContact"
Click="btDeleteContact_Click"
IsEnabled="{x:Bind viewModel.IsNewCustomer, Converter={StaticResource boolNegConv}, Mode=OneWay}"
Margin="8">
<StackPanel Orientation="Horizontal" Spacing="10">
<SymbolIcon Symbol="Delete"/>
<TextBlock Text="Delete Contact"/>
</StackPanel>
</Button>
</StackPanel>
</Grid>
</Expander.Content>
</Expander>
<!-- Time data -->
<RelativePanel x:Name="TimePanel" VerticalAlignment="Center"
HorizontalAlignment="Stretch"
Grid.Row="4">
<TextBox x:Name="txtCustomerLastUsedDate"
Header="Last Used Time" Text="{x:Bind viewModel.customer.LastUsedTime.ToLongDateString(), Mode=OneWay}"
Margin="5" Width="auto" Padding="15 5"
IsReadOnly="True"/>
<TextBox x:Name="txtCustomerCreateDate"
RelativePanel.AlignRightWithPanel="True"
Header="Creation Time" Text="{x:Bind viewModel.customer.CreateTime.ToLongDateString(), Mode=OneWay}"
Margin="5" Width="auto" Padding="15 5"
IsReadOnly="True" />
</RelativePanel>
</Grid>
</ScrollViewer>
</Grid>
</PivotItem>
<PivotItem Header="Notas Cliente">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Note Controls-->
<CommandBar x:Name="cmdBarNoteControls"
Grid.Row="0"
DefaultLabelPosition="Bottom" HorizontalContentAlignment="Center" HorizontalAlignment="Center">
<AppBarButton x:Name="btAddNote" Icon="Add" Label="Add" Click="btAddNote_Click"/>
<AppBarButton x:Name="btEditNote" Icon="Edit" Label="Edit" Click="btEditNote_Click"/>
<AppBarButton x:Name="btDeleteNote" Icon="Delete" Label="Delete" Click="btDeleteNote_Click"/>
</CommandBar>
<controls:NoteViewer x:Name="NoteViewer"
Grid.Row="1"
NoteList="{x:Bind viewModel.customerNotes, Mode=OneWay}" SelectedNote="{x:Bind viewModel.selectedNote, Mode=TwoWay}"/>
</Grid>
</PivotItem>
</Pivot>
</Page>
@@ -0,0 +1,418 @@
using Grpc.Core;
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 TestApp.Business.Model;
using TestApp.Controls;
using TestApp.Controls.Notes;
using TestApp.ViewModels;
using Windows.Foundation;
using Windows.Foundation.Collections;
namespace TestApp.Pages
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class CustomerDetailsPage : Page
{
public CustomerDetailsViewModel viewModel;
public CustomerDetailsPage()
{
if(viewModel is null)
{
this.viewModel = (CustomerDetailsViewModel)ActivatorUtilities.GetServiceOrCreateInstance(App.Host.Services, typeof(CustomerDetailsViewModel));
}
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if(e.Parameter is not null && e.Parameter is string && !string.IsNullOrWhiteSpace((string)e.Parameter))
{
string customerId = e.Parameter.ToString();
ShowCustomerData(customerId);
}
else
{
ShowCreateNew();
}
//base.OnNavigatedTo(e);
}
private async void ShowCustomerData(string customerID)
{
bool customerStatus = await this.viewModel.LoadCustomerData(customerID);
if (!customerStatus)
{
ShowError("Error", "No se han podido recuperar los datos del cliente");
}
bool contactsStatus = await this.viewModel.LoadCustomerContacts();
if (!contactsStatus)
{
ShowError("Error", "No se han podido recuperar los contactos del cliente");
}
bool noteStatus = await this.viewModel.LoadCustomerNotes();
if(!noteStatus)
{
ShowError("Error", "No se han podido recuperar las notas del cliente");
}
txtCustomerID.IsReadOnly = true;
txtCustomerCreateDate.Visibility = Visibility.Visible;
txtCustomerLastUsedDate.Visibility = Visibility.Visible;
}
private void ShowCreateNew()
{
this.viewModel.CreateNewCustomer();
txtCustomerID.IsReadOnly = false;
txtCustomerCreateDate.Visibility = Visibility.Collapsed;
txtCustomerLastUsedDate.Visibility = Visibility.Collapsed;
}
#region Event Handlers
private void btCreateCustomer_Click(object sender, RoutedEventArgs e)
{
ShowCreateNew();
}
private async void btDeleteCustomer_Click(object sender, RoutedEventArgs e)
{
if(viewModel.customer == null)
{
return;
}
ContentDialog d = new ContentDialog()
{
XamlRoot = this.XamlRoot,
Title = "Confirmar eliminación",
Content = $"¿Eliminar Cliente: {viewModel.customer.NIF} - {viewModel.customer.Name}?",
PrimaryButtonText = "Eliminar",
CloseButtonText = "Cancelar"
};
var rs = await d.ShowAsync();
bool deleted = false;
if(rs == ContentDialogResult.Primary)
{
deleted = await viewModel.DeleteCustomerData();
}
if(deleted)
{
ShowInfo("Eliminado", "Se ha eliminado el contacto");
}
}
private async void btClientSync_Click(object sender, RoutedEventArgs e)
{
ShowCustomerData(txtCustomerID.Text);
}
private async void btSaveDetails_Click(object sender, RoutedEventArgs e)
{
bool status = await this.viewModel.SaveCustomerData();
if(!status)
{
ShowError("Error", "No se han podido guardar los datos del cliente");
return;
}
if(viewModel.customer is null)
{
Frame.Navigate(typeof(CustomerListPage));
return;
}
ShowInfo("Guardado", "Se han guardado los datos del cliente");
//Reload Page on save or create.
ShowCustomerData(this.viewModel.customer.NIF);
}
private void btCancelEdit_Click(object sender, RoutedEventArgs e)
{
}
private void btCloseDetails_Click(object sender, RoutedEventArgs e)
{
Frame.Navigate(typeof(CustomerListPage));
}
#region Contact Controls
private async void btAddContact_Click(object sender, RoutedEventArgs e)
{
if(viewModel.customer is null)
{
return;
}
ContactDetailsDialog contactDialog = new ContactDetailsDialog()
{
XamlRoot = this.XamlRoot
};
contactDialog.CreateNewContact(viewModel.customer.NIF);
var rs = await contactDialog.ShowAsync(ContentDialogPlacement.InPlace);
bool created = false;
if(rs == ContentDialogResult.None)
{
return;
}
if(rs == ContentDialogResult.Primary)
{
if(contactDialog.viewModel is null)
{
ShowError("Error al añadir un contacto", "El viewModel es null...");
return;
}
created = await viewModel.AddContact(contactDialog.viewModel);
}
if(created)
{
ShowInfo("Contacto creado", "Se ha creado el nuevo contacto");
return;
}
ShowWarn("Error", "Ha ocurrido un error al crear el contacto");
}
private async void btUpdateContact_Click(object sender, RoutedEventArgs e)
{
if (viewModel.selectedContact is null)
{
ShowWarn("Nothing selected", "No se ha seleccionado ningún contacto");
return;
}
ContactDetailsDialog contactDialog = new ContactDetailsDialog()
{
XamlRoot = this.XamlRoot,
viewModel = viewModel.selectedContact
};
var rs = await contactDialog.ShowAsync(ContentDialogPlacement.InPlace);
bool updated = false;
if (rs == ContentDialogResult.None)
{
return;
}
if (rs == ContentDialogResult.Primary)
{
updated = await viewModel.UpdateSelectedContact();
}
if(updated)
{
ShowInfo("Contacto actualizado", "Se han actualizado los datos de contacto");
return;
}
ShowWarn("Error", "Ha ocurrido un error al actualizar los datos del contacto.");
}
private async void btDeleteContact_Click(object sender, RoutedEventArgs e)
{
if(viewModel.selectedContact is null)
{
ShowWarn("Nothing selected", "No se ha seleccionado ningún contacto");
return;
}
ContentDialog d = new ContentDialog()
{
XamlRoot = this.XamlRoot,
Title = "Confirmar eliminación",
Content = $"¿Eliminar contacto: {viewModel.selectedContact.Comment} - {viewModel.selectedContact.ContactValue}?",
PrimaryButtonText = "Confirmar",
CloseButtonText = "Cancelar"
};
var rs = await d.ShowAsync();
if (rs == ContentDialogResult.Primary)
{
if (await viewModel.RemoveSelectedContact())
{
ShowInfo("Eliminado", "Contacto eliminado");
}
}
}
#endregion
#region Note Controls
private async void btAddNote_Click(object sender, RoutedEventArgs e)
{
if (viewModel.customer is null)
{
return;
}
NoteDetailsDialog noteDialog = new NoteDetailsDialog()
{
XamlRoot = this.XamlRoot
};
noteDialog.CreateNewNote();
var rs = await noteDialog.ShowAsync();
bool created = false;
if (rs == ContentDialogResult.None)
{
return;
}
if (rs == ContentDialogResult.Primary)
{
if (noteDialog.viewModel is null)
{
ShowError("Error al añadir una nota", "No se han podido extraer los datos del diálogo");
return;
}
created = await viewModel.AddNote(noteDialog.viewModel);
}
if (created)
{
ShowInfo("Nota creada", "Se ha creado la nueva nota");
return;
}
ShowWarn("Error", "Ha ocurrido un error al crear la nota");
}
private async void btEditNote_Click(object sender, RoutedEventArgs e)
{
if (viewModel.selectedNote is null)
{
ShowWarn("Nothing selected", "No se ha seleccionado ninguna nota");
return;
}
NoteDetailsDialog noteDialog = new NoteDetailsDialog()
{
XamlRoot = this.XamlRoot,
viewModel = viewModel.selectedNote
};
noteDialog.EditNote();
var rs = await noteDialog.ShowAsync();
bool updated = false;
if (rs == ContentDialogResult.None)
{
return;
}
if (rs == ContentDialogResult.Primary)
{
updated = await viewModel.UpdateSelectedNote();
}
if (updated)
{
ShowInfo("Nota actualizada", "Se han actualizado los datos de la nota");
return;
}
ShowWarn("Error", "Ha ocurrido un error al actualizar los datos de la nota.");
}
private async void btDeleteNote_Click(object sender, RoutedEventArgs e)
{
if (viewModel.selectedNote is null)
{
ShowWarn("Nothing selected", "No se ha seleccionado ningún contacto");
return;
}
ContentDialog d = new ContentDialog()
{
XamlRoot = this.XamlRoot,
Title = "Confirmar eliminación",
Content = $"¿Eliminar Nota: {viewModel.selectedNote.Status}?",
PrimaryButtonText = "Confirmar",
CloseButtonText = "Cancelar"
};
var rs = await d.ShowAsync();
if (rs == ContentDialogResult.Primary)
{
if (await viewModel.RemoveSelectedNote())
{
ShowInfo("Eliminada", "Nota eliminada");
}
}
}
#endregion
#endregion
#region Utils
private void ShowInfo(string title, string msg)
{
infoBar.IsOpen = true;
infoBar.Severity = InfoBarSeverity.Informational;
infoBar.Title = title;
infoBar.Message = msg;
}
private void ShowWarn(string title, string msg)
{
infoBar.IsOpen = true;
infoBar.Severity = InfoBarSeverity.Warning;
infoBar.Title = title;
infoBar.Message = msg;
}
private void ShowError(string title, string msg)
{
infoBar.IsOpen = true;
infoBar.Severity = InfoBarSeverity.Error;
infoBar.Title = title;
infoBar.Message = msg;
}
#endregion
}
}
+119
View File
@@ -0,0 +1,119 @@
<Page
x:Class="TestApp.Pages.CustomerListPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestApp.Pages"
xmlns:model="using:TestApp.Business.Model"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<DataTemplate x:Key="CustomerListItem" x:DataType="model:CustomerModel">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="300"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{x:Bind NIF}" FontSize="14"
Grid.Column="0" VerticalAlignment="Center"/>
<TextBlock Text="{x:Bind Name}" FontSize="14"
Grid.Column="1" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</Page.Resources>
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<RelativePanel x:Name="topMenuPanel"
Grid.Row="0">
<TextBlock x:Name="PageTitle"
Text="Buscar clientes"
Style="{StaticResource TitleTextBlockStyle}"/>
<CommandBar x:Name="MainCommandBar"
HorizontalAlignment="Stretch"
Background="Transparent"
DefaultLabelPosition="Right"
RelativePanel.AlignRightWithPanel="True">
<AppBarButton x:Name="btClientDetails" Click="btClientDetails_Click" Label="Details" Icon="View"/>
<AppBarButton x:Name="btClientRemove" Click="btClientRemove_Click" Label="Remove" Icon="Delete"/>
<AppBarSeparator/>
<AppBarButton x:Name="btClientAdd" Click="btClientAdd_Click" Label="Create Client" Icon="Contact"/>
<AppBarSeparator/>
<AppBarButton x:Name="btClientSync" Click="btClientSync_Click" Label="Sync" Icon="Sync"/>
</CommandBar>
</RelativePanel>
<InfoBar x:Name="infoBar"
Grid.Row="1"
Margin="0 10"
IsOpen="False"/>
<Expander x:Name="customerFilter"
Grid.Row="2"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch">
<Expander.Header>
<RelativePanel>
<TextBlock Text="Customer Filter"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignVerticalCenterWithPanel="True"/>
<Button x:Name="btSearch"
Content="Search"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.AlignVerticalCenterWithPanel="True"
Click="btSearch_Click"/>
</RelativePanel>
</Expander.Header>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
RowSpacing="10" ColumnSpacing="50">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBox x:Name="txtFilerNif"
Header="NIF" Text="{x:Bind viewModel.filter.Nif, Mode=TwoWay}"
Grid.Row="0" Grid.Column="0"/>
<TextBox x:Name="txtFilerName"
Header="Name" Text="{x:Bind viewModel.filter.Name, Mode=TwoWay}"
Grid.Row="0" Grid.Column="1"/>
<TextBox x:Name="txtFilerContact"
Header="ContactData" Text="{x:Bind viewModel.filter.ContactData, Mode=TwoWay}"
Grid.Row="1" Grid.Column="0"/>
</Grid>
</Expander>
<ListView x:Name="CustomerListView"
Grid.Row="3"
Margin="0 10"
ItemTemplate="{StaticResource CustomerListItem}"
ItemsSource="{x:Bind viewModel.CustomerList, Mode=OneWay}"
SelectedItem="{x:Bind viewModel.SelectedCustomer, Mode=TwoWay}">
<ListView.HeaderTemplate>
<DataTemplate>
<Grid Padding="12" Background="{ThemeResource SystemAccentColor}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="300"/>
</Grid.ColumnDefinitions>
<TextBlock Text="NIF" Grid.Column="0"/>
<TextBlock Text="Name" Grid.Column="1"/>
</Grid>
</DataTemplate>
</ListView.HeaderTemplate>
</ListView>
</Grid>
</Page>
@@ -0,0 +1,143 @@
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 TestApp.ViewModels;
using Windows.Foundation;
using Windows.Foundation.Collections;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
namespace TestApp.Pages
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class CustomerListPage : Page
{
public CustomerListViewModel viewModel;
public CustomerListPage()
{
this.viewModel = (CustomerListViewModel)ActivatorUtilities.GetServiceOrCreateInstance(App.Host.Services, typeof(CustomerListViewModel));
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
_ = viewModel.LoadCustomers();
base.OnNavigatedTo(e);
}
#region Event Handlers
private void btClientDetails_Click(object sender, RoutedEventArgs e)
{
if(viewModel.SelectedCustomer is null)
{
ShowWarn("Nothing selected", "No se ha seleccionado ningún elemento");
return;
}
Frame.Navigate(typeof(CustomerDetailsPage), viewModel.SelectedCustomer.NIF);
}
private async void btClientRemove_Click(object sender, RoutedEventArgs e)
{
if (viewModel.SelectedCustomer is null)
{
ShowWarn("Nothing selected", "No se ha seleccionado ningún elemento");
return;
}
ContentDialog dialog = new ContentDialog()
{
XamlRoot = this.XamlRoot,
Title = "Confirmar eliminación",
Content = $"¿Eliminar cliente con ID: {viewModel.SelectedCustomer.NIF}?",
PrimaryButtonText = "Confirmar",
CloseButtonText = "Cancelar"
};
var rs = await dialog.ShowAsync();
if(rs == ContentDialogResult.Primary)
{
if(await viewModel.RemoveSelectedCustomer())
{
ShowInfo("Eliminado", "Cliente eliminado");
}
}
}
private async void btClientSync_Click(object sender, RoutedEventArgs e)
{
var rs = await viewModel.LoadCustomers();
if(rs)
{
ShowInfo("Actualizado", "Se han actualizado los datos de los clientes");
}
else
{
ShowError("Error", "No se han podido actualizar los clientes");
}
}
private void btClientAdd_Click(object sender, RoutedEventArgs e)
{
Frame.Navigate(typeof(CustomerDetailsPage));
}
private async void btSearch_Click(object sender, RoutedEventArgs e)
{
var rs = await viewModel.SearchCustomers();
if (!rs)
{
ShowError("Error", "No se han podido actualizar los clientes");
}
}
#endregion
#region Utils
private void ShowInfo(string title, string msg)
{
infoBar.IsOpen = true;
infoBar.Severity = InfoBarSeverity.Informational;
infoBar.Title = title;
infoBar.Message = msg;
}
private void ShowWarn(string title, string msg)
{
infoBar.IsOpen = true;
infoBar.Severity = InfoBarSeverity.Warning;
infoBar.Title = title;
infoBar.Message = msg;
}
private void ShowError(string title, string msg)
{
infoBar.IsOpen = true;
infoBar.Severity = InfoBarSeverity.Error;
infoBar.Title = title;
infoBar.Message = msg;
}
#endregion
}
}
+23
View File
@@ -0,0 +1,23 @@
<Page
x:Class="TestApp.Pages.HomePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestApp.Pages"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<RelativePanel>
<TextBlock
x:Name="lbTitle"
RelativePanel.AlignHorizontalCenterWithPanel="True"
Margin="20"
Text="Hotel on Containers!" FontSize="60"/>
<StackPanel
RelativePanel.AlignHorizontalCenterWithPanel="True"
RelativePanel.Below="lbTitle">
<Button x:Name="btClient" Content="Lista de Clientes" Click="btClient_Click" FontSize="20"/>
</StackPanel>
</RelativePanel>
</Page>
+35
View File
@@ -0,0 +1,35 @@
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;
namespace TestApp.Pages
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class HomePage : Page
{
public HomePage()
{
this.InitializeComponent();
}
private void btClient_Click(object sender, RoutedEventArgs e)
{
this.Frame.Navigate(typeof(CustomerListPage));
}
}
}
+26
View File
@@ -0,0 +1,26 @@
<Page
x:Class="TestApp.Pages.SettingsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestApp.Pages"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkit="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel Orientation="Vertical" Spacing="4" Padding="20">
<!-- Info bar -->
<InfoBar x:Name="infoBar"
Margin="0 0 20 0"
IsOpen="False"/>
<TextBox x:Name="txtCRM_API"
Header="CRM API" Text="{x:Bind viewModel.TxtCRMApi, Mode=TwoWay}"/>
<TextBox x:Name="txtBookings_API"
Header="Bookings API" Text="{x:Bind viewModel.TxtBookingsApi, Mode=TwoWay}"/>
<Button x:Name="btSave" x:Uid="generalBtSave"
Content="SSS"
Click="btSave_Click"/>
</StackPanel>
</Page>
@@ -0,0 +1,89 @@
using Microsoft.Extensions.Configuration;
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 TestApp.ViewModels;
using Windows.Foundation;
using Windows.Foundation.Collections;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
namespace TestApp.Pages
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class SettingsPage : Page
{
AppSettingsViewModel viewModel;
public SettingsPage()
{
if(viewModel is null)
{
this.viewModel = ActivatorUtilities.GetServiceOrCreateInstance<AppSettingsViewModel>(App.Host.Services);
}
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if(viewModel is null)
{
return;
}
viewModel.LoadDataFromConfig();
//base.OnNavigatedTo(e);
}
#region Event Handlers
private async void btSave_Click(object sender, RoutedEventArgs e)
{
bool rs = await viewModel.SaveDataToConfig();
ShowInfo("Saved", "Guadados");
}
#endregion
#region Utils
private void ShowInfo(string title, string msg)
{
infoBar.IsOpen = true;
infoBar.Severity = InfoBarSeverity.Informational;
infoBar.Title = title;
infoBar.Message = msg;
}
private void ShowWarn(string title, string msg)
{
infoBar.IsOpen = true;
infoBar.Severity = InfoBarSeverity.Warning;
infoBar.Title = title;
infoBar.Message = msg;
}
private void ShowError(string title, string msg)
{
infoBar.IsOpen = true;
infoBar.Severity = InfoBarSeverity.Error;
infoBar.Title = title;
infoBar.Message = msg;
}
#endregion
}
}
+39
View File
@@ -0,0 +1,39 @@
<Page
x:Class="TestApp.Pages.TestPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestApp.Pages"
xmlns:models="using:TestApp.Business.Model"
xmlns:controls="using:TestApp.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<DataTemplate x:Key="CustomerTemplate" x:DataType="models:CustomerModel">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Customer: "/>
<TextBlock Text="{x:Bind NIF}"/>
<TextBlock Text="{x:Bind Name}"/>
</StackPanel>
</DataTemplate>
</Page.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<controls:NoteViewer Grid.Row="0"
NoteList="{x:Bind NoteList, Mode=OneWay}" SelectedNote="{x:Bind SelectedNote, Mode=TwoWay}"/>
<StackPanel Grid.Row="1"
Margin="25" Spacing="15">
<Button x:Name="btTestDialog" Content="Open Note dialog" Click="btTestDialog_Click"/>
<Button x:Name="btAddNote" Content="Add Note" Click="btAddNote_Click"/>
</StackPanel>
</Grid>
</Page>
+105
View File
@@ -0,0 +1,105 @@
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 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 TestApp.Controls.Notes;
using System.Collections.ObjectModel;
using TestApp.Business.Model;
using Uno.Extensions;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
namespace TestApp.Pages
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class TestPage : Page
{
public ObservableCollection<NoteModel> NoteList;
public NoteModel? SelectedNote { get; set; }
public ObservableCollection<CustomerModel> CustomerList;
public CustomerFilterModel? Filter { get; set; }
public TestPage()
{
this.InitializeComponent();
// TEST DATA.
NoteList = new ObservableCollection<NoteModel>()
{
new NoteModel()
{
Id = 1,
CustomerNIF = "12345U",
Data = "Test Note 1",
Status = "Open"
},
new NoteModel()
{
Id = 2,
CustomerNIF = "12345U",
Data = "Test Note 2",
Status = "Close"
}
};
SelectedNote = null;
CustomerList = new ObservableCollection<CustomerModel>();
Filter = new CustomerFilterModel();
}
private async void btTestDialog_Click(object sender, RoutedEventArgs e)
{
NoteDetailsDialog dialog = new NoteDetailsDialog()
{
XamlRoot = this.XamlRoot,
viewModel = SelectedNote
};
dialog.EditNote();
var rs = await dialog.ShowAsync();
if(rs == ContentDialogResult.Primary)
{
var updatedNote = dialog.viewModel;
_ = NoteList.Replace(note => note?.Id == updatedNote?.Id, updatedNote);
}
}
private async void btAddNote_Click(object sender, RoutedEventArgs e)
{
NoteDetailsDialog dialog = new NoteDetailsDialog()
{
XamlRoot = this.XamlRoot
};
dialog.CreateNewNote();
var rs = await dialog.ShowAsync();
if(rs == ContentDialogResult.Primary)
{
var createdNote = dialog.viewModel;
if(createdNote is null) { return; }
NoteList.Add(createdNote);
}
}
}
}
+127
View File
@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ApplicationName" xml:space="preserve">
<value>TestApp-en</value>
<comment>App Name</comment>
</data>
<data name="generalBtSave.Content" xml:space="preserve">
<value>Save</value>
</data>
</root>
+121
View File
@@ -0,0 +1,121 @@
<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-android</TargetFrameworks>
<!-- Ensures the .xr.xml files are generated in a proper layout folder -->
<GenerateLibraryLayout>true</GenerateLibraryLayout>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net7.0-windows10.0.19041|AnyCPU'">
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net7.0-windows10.0.19041|AnyCPU'">
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net7.0|AnyCPU'">
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net7.0|AnyCPU'">
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net7.0-android|AnyCPU'">
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net7.0-android|AnyCPU'">
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="12.0.1" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="Grpc.Net.Client" Version="2.53.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Uno.Extensions.Configuration" Version="2.3.10" />
<PackageReference Include="Uno.WinUI" Version="4.9.45" />
<PackageReference Include="Uno.Resizetizer" Version="1.0.4" />
<PackageReference Include="Uno.Toolkit.WinUI" Version="3.0.5" />
<PackageReference Include="Uno.Extensions.Hosting.WinUI" Version="2.3.10" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="7.0.0" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0-windows10.0.19041'">
<PackageReference Include="CommunityToolkit.WinUI" Version="7.1.2" />
<PackageReference Include="CommunityToolkit.WinUI.UI" Version="7.1.2" />
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls" Version="7.1.2" />
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" Version="7.1.2" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' != 'net7.0-windows10.0.19041'">
<PackageReference Include="Uno.CommunityToolkit.WinUI" Version="7.1.100" />
<PackageReference Include="Uno.CommunityToolkit.WinUI.UI" Version="7.1.100" />
<PackageReference Include="Uno.CommunityToolkit.WinUI.UI.Controls" Version="7.1.100" />
<PackageReference Include="Uno.CommunityToolkit.WinUI.UI.Controls.DataGrid" Version="7.1.100" />
</ItemGroup>
<Choose>
<When Condition="$(IsWinAppSdk)">
<ItemGroup>
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.2.230313.1" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.755" />
</ItemGroup>
<ItemGroup>
<!--
If you encounter this error message:
error NETSDK1148: A referenced assembly was compiled using a newer version of Microsoft.Windows.SDK.NET.dll.
Please update to a newer .NET SDK in order to reference this assembly.
This means that the two packages below must be aligned with the "build" version number of
the "Microsoft.Windows.SDK.BuildTools" package above, and the "revision" version number
must be the highest found in https://www.nuget.org/packages/Microsoft.Windows.SDK.NET.Ref.
-->
<!-- <FrameworkReference Update="Microsoft.Windows.SDK.NET.Ref" RuntimeFrameworkVersion="10.0.22621.28" />
<FrameworkReference Update="Microsoft.Windows.SDK.NET.Ref" TargetingPackVersion="10.0.22621.28" /> -->
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<Content Include="Assets\**" />
<Page Include="**\*.xaml" Exclude="bin\**\*.xaml;obj\**\*.xaml" />
<Compile Update="**\*.xaml.cs">
<DependentUpon>%(Filename)</DependentUpon>
</Compile>
<PRIResource Include="**\*.resw" />
</ItemGroup>
</Otherwise>
</Choose>
<ItemGroup>
<UnoImage Include="Assets\**\*.svg" />
<UpToDateCheckInput Include="**\*.xaml" Exclude="bin\**\*.xaml;obj\**\*.xaml" />
</ItemGroup>
<ItemGroup>
<None Remove="Controls\ContactDetailsDialog.xaml" />
<None Remove="Controls\Notes\NoteDetailsDialog.xaml" />
<None Remove="Controls\Notes\NoteViewer.xaml" />
<None Remove="Pages\CustomerDetailsPage.xaml" />
<None Remove="Pages\CustomerListPage.xaml" />
<None Remove="Pages\HomePage.xaml" />
<None Remove="Pages\SettingsPage.xaml" />
<None Remove="Pages\TestPage.xaml" />
</ItemGroup>
<ItemGroup>
<UpToDateCheckInput Remove="Controls\ContactDetailsDialog.xaml" />
<UpToDateCheckInput Remove="Controls\Notes\NoteDetailsDialog.xaml" />
<UpToDateCheckInput Remove="Controls\Notes\NoteViewer.xaml" />
<UpToDateCheckInput Remove="Pages\CustomerDetailsPage.xaml" />
<UpToDateCheckInput Remove="Pages\CustomerListPage.xaml" />
<UpToDateCheckInput Remove="Pages\HomePage.xaml" />
<UpToDateCheckInput Remove="Pages\SettingsPage.xaml" />
<UpToDateCheckInput Remove="Pages\TestPage.xaml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\TestApp.Data\TestApp.Data.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,18 @@
using CommunityToolkit.WinUI.UI.Converters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestApp.Utils.Converters
{
class InvBoolToVisibilityConverter : BoolToObjectConverter
{
public InvBoolToVisibilityConverter()
{
TrueValue = Visibility.Collapsed;
FalseValue = Visibility.Visible;
}
}
}
@@ -0,0 +1,45 @@
using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TestApp.Business.Config;
using Uno.Extensions.Configuration;
namespace TestApp.ViewModels
{
public partial class AppSettingsViewModel : ObservableObject
{
IWritableOptions<NetworkSettings> _netSettings;
[ObservableProperty]
private string txtCRMApi = string.Empty;
[ObservableProperty]
private string txtBookingsApi = string.Empty;
public AppSettingsViewModel(IWritableOptions<NetworkSettings> networkSettings)
{
_netSettings = networkSettings;
}
public void LoadDataFromConfig()
{
TxtCRMApi = _netSettings.Value.Url_CRMApi ?? "";
TxtBookingsApi = _netSettings.Value.Url_BookingApi ?? "";
}
public async Task<bool> SaveDataToConfig()
{
await _netSettings.UpdateAsync(settings => settings with
{
Url_CRMApi = TxtCRMApi ?? "",
Url_BookingApi = TxtBookingsApi ?? ""
});
return true;
}
}
}
@@ -0,0 +1,296 @@
using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.UI.Xaml.Controls.Primitives;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TestApp.Business.DAO;
using TestApp.Business.Model;
using Uno.Extensions;
namespace TestApp.ViewModels
{
public partial class CustomerDetailsViewModel : ObservableObject
{
public apiCRM_Service _customerService;
public CustomerModel? customer { get; set; }
public ObservableCollection<ContactDetailsModel> customerContacts { get; }
public ContactDetailsModel? selectedContact { get; set; }
[ObservableProperty]
private bool isEditMode = false;
[ObservableProperty]
private bool isNewCustomer = false;
[ObservableProperty]
private bool hasContacts = false;
[ObservableProperty]
private bool hasNotes = false;
public ObservableCollection<NoteModel> customerNotes { get; }
public NoteModel? selectedNote { get; set; }
public CustomerDetailsViewModel(apiCRM_Service customerService)
{
this._customerService = customerService;
if(customer is null)
{
customer = new CustomerModel();
}
if(customerContacts is null)
{
customerContacts = new ObservableCollection<ContactDetailsModel>();
}
selectedContact = null;
if(customerNotes is null)
{
customerNotes = new ObservableCollection<NoteModel>();
}
selectedNote = null;
hasContacts = false;
isNewCustomer = false;
isEditMode = false;
}
public async void CreateNewCustomer()
{
IsNewCustomer = true;
IsEditMode = true;
customer = new CustomerModel();
selectedContact = null;
customerContacts.Clear();
selectedNote = null;
customerNotes.Clear();
}
public async void CancelEdit()
{
if(customer is null)
{
return;
}
IsEditMode = false;
await LoadCustomerData(customer.NIF);
}
public async Task<bool> LoadCustomerData(string customerID)
{
var data = await _customerService.GetCustomerByIdAsync(customerID);
if(data is null)
{
return false;
}
customer?.updateData(data);
return true;
}
public async Task<bool> SaveCustomerData()
{
if(customer is null)
{
return false;
}
if(IsNewCustomer)
{
bool added = await _customerService.AddCustomerAsync(customer);
IsNewCustomer = false;
IsEditMode = false;
return added;
}
bool updated = await _customerService.UpdateCustomerAsync(customer);
IsEditMode = false;
return updated;
}
public async Task<bool> DeleteCustomerData()
{
if(customer is null)
{
return false;
}
bool deleted = await _customerService.RemoveCustomerAsync(customer);
if(deleted)
{
//Limpiamos todos los datos.
CreateNewCustomer();
}
return deleted;
}
#region Customer Contacts
public async Task<bool> LoadCustomerContacts()
{
if(customer is null)
{
return false;
}
var data = await _customerService.GetContactsByCustomerAsync(customer.NIF);
customerContacts.Clear();
customerContacts.AddRange(data);
HasContacts = !customerContacts.Empty();
return true;
}
public async Task<bool> AddContact(ContactDetailsModel contactToAdd)
{
bool status = await _customerService.AddContactAsync(contactToAdd);
if(status)
{
customerContacts.Add(contactToAdd);
HasContacts = true;
//Update Data from DB -> We need to get at least the ID of new note.
await LoadCustomerContacts();
}
return status;
}
public async Task<bool> UpdateSelectedContact()
{
if(selectedContact is null)
{
return false;
}
bool status = await _customerService.UpdateContactAsync(selectedContact);
if(status)
{
customerContacts.Replace(cust => cust.Id == selectedContact.Id, selectedContact);
}
return status;
}
public async Task<bool> RemoveSelectedContact()
{
if(selectedContact is null)
{
return false;
}
bool status = await _customerService.RemoveContactAsync(selectedContact.Id);
if (status == true)
{
customerContacts.Remove(selectedContact);
HasContacts = !customerContacts.Empty();
}
return status;
}
#endregion
#region Customer Notes
public async Task<bool> LoadCustomerNotes()
{
if (customer is null)
{
return false;
}
var data = await _customerService.GetCustomerNotesByCustomerAsync(customer.NIF);
customerNotes.Clear();
customerNotes.AddRange(data);
return true;
}
public async Task<bool> AddNote(NoteModel noteToAdd)
{
if(customer is null)
{
return false;
}
noteToAdd.CustomerNIF = customer.NIF;
bool status = await _customerService.AddCustomerNoteAsync(noteToAdd);
if (status)
{
customerNotes.Add(noteToAdd);
HasNotes = true;
//Refresh data from DB.
await LoadCustomerNotes();
}
return status;
}
public async Task<bool> UpdateSelectedNote()
{
if (selectedNote is null)
{
return false;
}
bool status = await _customerService.UpdateCustomerNoteAsync(selectedNote);
if (status)
{
customerNotes.Replace(cust => cust.Id == selectedNote.Id, selectedNote);
}
return status;
}
public async Task<bool> RemoveSelectedNote()
{
if (selectedNote is null)
{
return false;
}
bool status = await _customerService.RemoveCustomerNoteAsync(selectedNote.Id);
if (status == true)
{
customerNotes.Remove(selectedNote);
HasNotes = !customerNotes.Empty();
}
return status;
}
#endregion
}
}
@@ -0,0 +1,96 @@
using CommunityToolkit.Mvvm.ComponentModel;
using DGM.HoC.CRM.API.RPC;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TestApp.Business.DAO;
using TestApp.Business.Model;
using Uno.Extensions;
namespace TestApp.ViewModels
{
public class CustomerListViewModel : ObservableObject
{
apiCRM_Service _customerService;
public ObservableCollection<CustomerModel> CustomerList { get; }
public CustomerFilterModel? filter { get; set; }
public CustomerModel? SelectedCustomer { get; set; }
public CustomerListViewModel(apiCRM_Service customerService)
{
this._customerService = customerService;
if (CustomerList is null)
{
CustomerList = new ObservableCollection<CustomerModel>();
}
SelectedCustomer = null;
//If config "Paginated" == True -> Set paginated data on filter.
filter = new CustomerFilterModel();
}
public async Task<bool> LoadCustomers()
{
var list = await _customerService.GetCustomersAsync();
if (list is null)
{
//Error.
return false;
}
CustomerList.Clear();
CustomerList.AddRange(list);
return true;
}
public async Task<bool> SearchCustomers()
{
if(filter is null)
{
return await LoadCustomers();
}
var list = await _customerService.GetCustomersByFilter(filter);
if(list is null)
{
return false;
}
CustomerList.Clear();
CustomerList.AddRange(list);
return true;
}
public async Task<bool> RemoveSelectedCustomer()
{
if(SelectedCustomer is null)
{
return false;
}
bool status = await _customerService.RemoveCustomerAsync(SelectedCustomer);
if(status == true)
{
CustomerList.Remove(SelectedCustomer);
}
return status;
}
}
}
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TestApp.Business.DAO;
using TestApp.Business.Model;
using Uno.Extensions;
namespace TestApp.ViewModels
{
internal class CustomerNoteListViewModel
{
apiCRM_Service _customerService;
public ObservableCollection<NoteModel> Notes { get; }
public NoteModel? SelectedItem { get; set; }
public CustomerModel? customer;
public CustomerNoteListViewModel(apiCRM_Service customerService)
{
this._customerService = customerService;
if (Notes is null)
{
Notes = new ObservableCollection<NoteModel>();
}
SelectedItem = null;
}
public async void LoadAllNotes()
{
var list = await _customerService.GetCustomerNotesAsync();
if (list is null)
{
//Error.
return;
}
Notes.Clear();
Notes.AddRange(list);
}
}
}
+9
View File
@@ -0,0 +1,9 @@
{
"AppConfig": {
"Title": "ContainersApp2"
},
"NetworkSettings": {
"Url_CRMApi": "https://localhost:5106",
"Url_BookingApi": "https://localhost:5108"
}
}