Merge branch 'master' into dev
# Conflicts: # src/Mobile/eShopOnContainers/eShopOnContainers.Core/eShopOnContainers.Core.csproj # src/Services/Catalog/Catalog.API/Startup.cs # src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs # src/Web/WebMVC/Startup.cs
This commit is contained in:
commit
756cb3dafa
21
README.md
21
README.md
@ -14,11 +14,15 @@ Sample .NET Core reference application, powered by Microsoft, based on a simplif
|
|||||||
**Architecture overview**: This reference application is cross-platform either at the server and client side, thanks to .NET Core services capable of running on Linux or Windows containers depending on your Docker host, and to Xamarin for mobile apps running on Android, iOS or Windows/UWP plus any browser for the client web apps.
|
**Architecture overview**: This reference application is cross-platform either at the server and client side, thanks to .NET Core services capable of running on Linux or Windows containers depending on your Docker host, and to Xamarin for mobile apps running on Android, iOS or Windows/UWP plus any browser for the client web apps.
|
||||||
The architecture proposes a simplified microservice oriented architecture implementation with multiple autonomous microservices (each one owning its own data/db) and implementing different approaches within each microservice (simple CRUD vs. DDD/CQRS patterns) using Http as the current communication protocol.
|
The architecture proposes a simplified microservice oriented architecture implementation with multiple autonomous microservices (each one owning its own data/db) and implementing different approaches within each microservice (simple CRUD vs. DDD/CQRS patterns) using Http as the current communication protocol.
|
||||||
<p>
|
<p>
|
||||||
The plan is to add asynchronous communication for data updates propagation across multiple services based on integration events and an event bus plus other features defined at the <a href='https://github.com/dotnet/eShopOnContainers/wiki/01.-Roadmap-and-Milestones-for-future-releases'>roadmap</a>.
|
It also supports asynchronous communication for data updates propagation across multiple services based on Integration Events and an Event Bus plus other features defined at the <a href='https://github.com/dotnet/eShopOnContainers/wiki/01.-Roadmap-and-Milestones-for-future-releases'>roadmap</a>.
|
||||||
<p>
|
<p>
|
||||||
<img src="img/eshop_logo.png">
|
<img src="img/eshop_logo.png">
|
||||||
<img src="img/eShopOnContainers_Architecture_Diagram.png">
|
<img src="img/eShopOnContainers_Architecture_Diagram.png">
|
||||||
<p>
|
<p>
|
||||||
|
The microservices are different in type, meaning different internal architecture patterns approaches depending on it purpose, as shown in the image below.
|
||||||
|
<p>
|
||||||
|
<img src="img/eShopOnContainers_Types_Of_Microservices.png">
|
||||||
|
<p>
|
||||||
<p>
|
<p>
|
||||||
Additional miroservice styles with other frameworks and No-SQL databases will be added, eventually. This is a great opportunity for pull requests from the community, like a new microservice using Nancy, or even other languages like Node, Go, Python or data containers with MongoDB with Azure DocDB compatibility, PostgreSQL, RavenDB, Event Store, MySql, etc. You name it! :)
|
Additional miroservice styles with other frameworks and No-SQL databases will be added, eventually. This is a great opportunity for pull requests from the community, like a new microservice using Nancy, or even other languages like Node, Go, Python or data containers with MongoDB with Azure DocDB compatibility, PostgreSQL, RavenDB, Event Store, MySql, etc. You name it! :)
|
||||||
|
|
||||||
@ -30,15 +34,14 @@ Additional miroservice styles with other frameworks and No-SQL databases will be
|
|||||||
## Related documentation and guidance
|
## Related documentation and guidance
|
||||||
While developing this reference application, we are creating a reference Guide/eBook named <b>"Architecting and Developing Containerized and Microservice based .NET Applications"</b> which explains in detail how to develop this kind of architectural style (microservices, Docker containers, Domain-Driven Design for certain microservices) plus other simpler architectural styles, like monolithic apps that can also live as Docker containers.
|
While developing this reference application, we are creating a reference Guide/eBook named <b>"Architecting and Developing Containerized and Microservice based .NET Applications"</b> which explains in detail how to develop this kind of architectural style (microservices, Docker containers, Domain-Driven Design for certain microservices) plus other simpler architectural styles, like monolithic apps that can also live as Docker containers.
|
||||||
<p>
|
<p>
|
||||||
There's also an additional eBook focusing on Containers/Docker lifecycle (DevOps, CI/CD, etc.) with Microsoft Tools, already published.
|
There are also additional eBooks focusing on Containers/Docker lifecycle (DevOps, CI/CD, etc.) with Microsoft Tools, already published plus an additional eBook focusing on Enterprise Apps Patterns with Xamarin.Forms.
|
||||||
You can start reviewing these Guides/eBooks here:
|
You can download them and start reviewing these Guides/eBooks here:
|
||||||
<p>
|
<p>
|
||||||
You can download both eBooks from here:
|
|
||||||
|
|
||||||
| Architecting & Developing | Containers Lifecycle & CI/CD |
|
| Architecting & Developing | Containers Lifecycle & CI/CD | App patterns with Xamarin.Forms |
|
||||||
| ------------ | ------------|
|
| ------------ | ------------| ------------|
|
||||||
| <a href='docs/architecting-and-developing-containerized-and-microservice-based-net-applications-ebook-early-draft.pdf'><img src="img/ebook_arch_dev_microservices_containers_cover.png"> </a> | <a href='https://aka.ms/dockerlifecycleebook'> <img src="img/ebook_containers_lifecycle.png"> </a> |
|
| <a href='https://aka.ms/microservicesebook'><img src="img/ebook_arch_dev_microservices_containers_cover.png"> </a> | <a href='https://aka.ms/dockerlifecycleebook'> <img src="img/ebook_containers_lifecycle.png"> </a> | <a href='https://aka.ms/xamarinpatternsebook'> <img src="img/xamarin-enterprise-patterns-ebook-cover-small.png"> </a> |
|
||||||
| <a href='docs/architecting-and-developing-containerized-and-microservice-based-net-applications-ebook-early-draft.pdf'>**Download** (Early DRAFT, still work in progress)</a> | <a href='https://aka.ms/dockerlifecycleebook'>**Download** - First Edition from late 2016</a> |
|
| <sup> <a href='https://aka.ms/microservicesebook'>**Download** (Early DRAFT, still work in progress)</a> </sup> | <sup> <a href='https://aka.ms/dockerlifecycleebook'>**Download** (First Edition from late 2016) </a> </sup> | <sup> <a href='https://aka.ms/xamarinpatternsebook'>**Download** (Early DRAFT, still work in progress) </a> </sup> |
|
||||||
|
|
||||||
Send feedback to [cesardl@microsoft.com](cesardl@microsoft.com)
|
Send feedback to [cesardl@microsoft.com](cesardl@microsoft.com)
|
||||||
<p>
|
<p>
|
||||||
@ -89,7 +92,7 @@ The app was also partially tested on "Docker for Mac" using a development MacOS
|
|||||||
|
|
||||||
## Sending feedback and pull requests
|
## Sending feedback and pull requests
|
||||||
As mentioned, we'd appreciate to your feedback, improvements and ideas.
|
As mentioned, we'd appreciate to your feedback, improvements and ideas.
|
||||||
You can create new issues at the issues section, do pull requests and/or send emails to eshop_feedback@service.microsoft.com
|
You can create new issues at the issues section, do pull requests and/or send emails to **eshop_feedback@service.microsoft.com**
|
||||||
|
|
||||||
## Questions
|
## Questions
|
||||||
[QUESTION] Answer +1 if the solution is working for you (Through VS2017 or CLI environment):
|
[QUESTION] Answer +1 if the solution is working for you (Through VS2017 or CLI environment):
|
||||||
|
@ -45,6 +45,7 @@ services:
|
|||||||
- ASPNETCORE_URLS=http://0.0.0.0:5102
|
- ASPNETCORE_URLS=http://0.0.0.0:5102
|
||||||
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word
|
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word
|
||||||
- identityUrl=http://identity.api:5105 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
|
- identityUrl=http://identity.api:5105 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
|
||||||
|
- BasketUrl=http://basket.api:5103
|
||||||
- EventBusConnection=rabbitmq
|
- EventBusConnection=rabbitmq
|
||||||
ports:
|
ports:
|
||||||
- "5102:5102"
|
- "5102:5102"
|
||||||
|
@ -19,6 +19,7 @@ services:
|
|||||||
- ASPNETCORE_URLS=http://0.0.0.0:5103
|
- ASPNETCORE_URLS=http://0.0.0.0:5103
|
||||||
- ConnectionString=basket.data
|
- ConnectionString=basket.data
|
||||||
- identityUrl=http://identity.api:5105 #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105.
|
- identityUrl=http://identity.api:5105 #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105.
|
||||||
|
- EventBusConnection=rabbitmq
|
||||||
ports:
|
ports:
|
||||||
- "5103:5103"
|
- "5103:5103"
|
||||||
|
|
||||||
@ -28,6 +29,7 @@ services:
|
|||||||
- ASPNETCORE_URLS=http://0.0.0.0:5101
|
- ASPNETCORE_URLS=http://0.0.0.0:5101
|
||||||
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word
|
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word
|
||||||
- ExternalCatalogBaseUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5101 #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105.
|
- ExternalCatalogBaseUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5101 #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105.
|
||||||
|
- EventBusConnection=rabbitmq
|
||||||
ports:
|
ports:
|
||||||
- "5101:5101"
|
- "5101:5101"
|
||||||
|
|
||||||
@ -48,6 +50,8 @@ services:
|
|||||||
- ASPNETCORE_URLS=http://0.0.0.0:5102
|
- ASPNETCORE_URLS=http://0.0.0.0:5102
|
||||||
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word
|
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word
|
||||||
- identityUrl=http://identity.api:5105 #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105.
|
- identityUrl=http://identity.api:5105 #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105.
|
||||||
|
- BasketUrl=http://basket.api:5103
|
||||||
|
- EventBusConnection=rabbitmq
|
||||||
ports:
|
ports:
|
||||||
- "5102:5102"
|
- "5102:5102"
|
||||||
|
|
||||||
@ -82,10 +86,13 @@ services:
|
|||||||
|
|
||||||
webstatus:
|
webstatus:
|
||||||
environment:
|
environment:
|
||||||
- ASPNETCORE_ENVIRONMENT=Development
|
- ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
- ASPNETCORE_URLS=http://0.0.0.0:5107
|
||||||
- CatalogUrl=http://catalog.api:5101/hc
|
- CatalogUrl=http://catalog.api:5101/hc
|
||||||
- OrderingUrl=http://ordering.api:5102/hc
|
- OrderingUrl=http://ordering.api:5102/hc
|
||||||
- BasketUrl=http://basket.api:5103/hc
|
- BasketUrl=http://basket.api:5103/hc
|
||||||
- IdentityUrl=http://10.0.75.1:5105/hc
|
- mvc=http://webmvc:5100/hc
|
||||||
|
- spa=http://webspa:5104/hc
|
||||||
|
- IdentityUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}, if using external IP or DNS name from browser.
|
||||||
ports:
|
ports:
|
||||||
- "5107:5107"
|
- "5107:5107"
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 427 KiB After Width: | Height: | Size: 405 KiB |
BIN
img/eShopOnContainers_Architecture_Diagram_old.png
Normal file
BIN
img/eShopOnContainers_Architecture_Diagram_old.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 427 KiB |
BIN
img/eShopOnContainers_Types_Of_Microservices.png
Normal file
BIN
img/eShopOnContainers_Types_Of_Microservices.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 156 KiB |
Binary file not shown.
Before Width: | Height: | Size: 30 KiB |
BIN
img/xamarin-enterprise-patterns-ebook-cover-small.png
Normal file
BIN
img/xamarin-enterprise-patterns-ebook-cover-small.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
@ -3,7 +3,7 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
xmlns:light="clr-namespace:Xamarin.Forms.Themes;assembly=Xamarin.Forms.Theme.Light"
|
xmlns:light="clr-namespace:Xamarin.Forms.Themes;assembly=Xamarin.Forms.Theme.Light"
|
||||||
xmlns:converters="clr-namespace:eShopOnContainers.Core.Converters;assembly=eShopOnContainers.Core"
|
xmlns:converters="clr-namespace:eShopOnContainers.Core.Converters;assembly=eShopOnContainers.Core"
|
||||||
xmlns:effects="clr-namespace:eShopOnContainers.Core.Effects;assembly=eShopOnContainers.Core"
|
xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core"
|
||||||
x:Class="eShopOnContainers.App">
|
x:Class="eShopOnContainers.App">
|
||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
<ResourceDictionary MergedWith="light:LightThemeResources">
|
<ResourceDictionary MergedWith="light:LightThemeResources">
|
||||||
@ -17,6 +17,7 @@
|
|||||||
<Color x:Key="GreenColor">#00A69C</Color>
|
<Color x:Key="GreenColor">#00A69C</Color>
|
||||||
<Color x:Key="DarkGreenColor">#00857D</Color>
|
<Color x:Key="DarkGreenColor">#00857D</Color>
|
||||||
<Color x:Key="GrayColor">#e2e2e2</Color>
|
<Color x:Key="GrayColor">#e2e2e2</Color>
|
||||||
|
<Color x:Key="ErrorColor">#ff5252</Color>
|
||||||
|
|
||||||
<!-- FONTS -->
|
<!-- FONTS -->
|
||||||
<OnPlatform
|
<OnPlatform
|
||||||
@ -100,6 +101,7 @@
|
|||||||
<!-- CONVERTERS -->
|
<!-- CONVERTERS -->
|
||||||
<converters:CountToBoolConverter x:Key="CountToBoolConverter" />
|
<converters:CountToBoolConverter x:Key="CountToBoolConverter" />
|
||||||
<converters:DatetimeConverter x:Key="DatetimeConverter" />
|
<converters:DatetimeConverter x:Key="DatetimeConverter" />
|
||||||
|
<converters:FirstValidationErrorConverter x:Key="FirstValidationErrorConverter" />
|
||||||
<converters:ImageConverter x:Key="ImageConverter" />
|
<converters:ImageConverter x:Key="ImageConverter" />
|
||||||
<converters:ItemTappedEventArgsConverter x:Key="ItemTappedEventArgsConverter" />
|
<converters:ItemTappedEventArgsConverter x:Key="ItemTappedEventArgsConverter" />
|
||||||
<converters:InverseCountToBoolConverter x:Key="InverseCountToBoolConverter" />
|
<converters:InverseCountToBoolConverter x:Key="InverseCountToBoolConverter" />
|
||||||
@ -110,6 +112,14 @@
|
|||||||
<converters:WebNavigatedEventArgsConverter x:Key="WebNavigatedEventArgsConverter" />
|
<converters:WebNavigatedEventArgsConverter x:Key="WebNavigatedEventArgsConverter" />
|
||||||
|
|
||||||
<!-- STYLES -->
|
<!-- STYLES -->
|
||||||
|
<Style x:Key="ValidationErrorLabelStyle"
|
||||||
|
TargetType="{x:Type Label}">
|
||||||
|
<Setter Property="TextColor"
|
||||||
|
Value="{StaticResource ErrorColor}" />
|
||||||
|
<Setter Property="FontSize"
|
||||||
|
Value="{StaticResource LittleSize}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
<Style x:Key="EntryStyle"
|
<Style x:Key="EntryStyle"
|
||||||
TargetType="{x:Type Entry}">
|
TargetType="{x:Type Entry}">
|
||||||
<Setter Property="FontFamily"
|
<Setter Property="FontFamily"
|
||||||
@ -126,9 +136,9 @@
|
|||||||
Value="Bold" />
|
Value="Bold" />
|
||||||
<Setter Property="Opacity"
|
<Setter Property="Opacity"
|
||||||
Value="0.6" />
|
Value="0.6" />
|
||||||
<Setter Property="effects:LineColorEffect.ApplyLineColor"
|
<Setter Property="behaviors:LineColorBehavior.ApplyLineColor"
|
||||||
Value="True" />
|
Value="True" />
|
||||||
<Setter Property="effects:LineColorEffect.LineColor"
|
<Setter Property="behaviors:LineColorBehavior.LineColor"
|
||||||
Value="{StaticResource BlackColor}" />
|
Value="{StaticResource BlackColor}" />
|
||||||
<Style.Triggers>
|
<Style.Triggers>
|
||||||
<Trigger TargetType="Entry"
|
<Trigger TargetType="Entry"
|
||||||
@ -157,16 +167,16 @@
|
|||||||
Value="Transparent" />
|
Value="Transparent" />
|
||||||
<Setter Property="Opacity"
|
<Setter Property="Opacity"
|
||||||
Value="0.6" />
|
Value="0.6" />
|
||||||
<Setter Property="effects:LineColorEffect.ApplyLineColor"
|
<Setter Property="behaviors:LineColorBehavior.ApplyLineColor"
|
||||||
Value="True" />
|
Value="True" />
|
||||||
<Setter Property="effects:LineColorEffect.LineColor"
|
<Setter Property="behaviors:LineColorBehavior.LineColor"
|
||||||
Value="Gray" />
|
Value="Gray" />
|
||||||
<Style.Triggers>
|
<Style.Triggers>
|
||||||
<Trigger TargetType="Entry"
|
<Trigger TargetType="Entry"
|
||||||
Property="IsFocused"
|
Property="IsFocused"
|
||||||
Value="True">
|
Value="True">
|
||||||
<Setter Property="Opacity" Value="1" />
|
<Setter Property="Opacity" Value="1" />
|
||||||
<Setter Property="effects:LineColorEffect.LineColor"
|
<Setter Property="behaviors:LineColorBehavior.LineColor"
|
||||||
Value="{StaticResource GreenColor}" />
|
Value="{StaticResource GreenColor}" />
|
||||||
</Trigger>
|
</Trigger>
|
||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
using eShopOnContainers.Core.Helpers;
|
using eShopOnContainers.Core.Helpers;
|
||||||
using eShopOnContainers.Services;
|
using eShopOnContainers.Services;
|
||||||
using eShopOnContainers.ViewModels.Base;
|
using eShopOnContainers.Core.ViewModels.Base;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
using Xamarin.Forms.Xaml;
|
using Xamarin.Forms.Xaml;
|
||||||
@ -27,13 +27,13 @@ namespace eShopOnContainers
|
|||||||
private void InitApp()
|
private void InitApp()
|
||||||
{
|
{
|
||||||
UseMockServices = Settings.UseMocks;
|
UseMockServices = Settings.UseMocks;
|
||||||
|
ViewModelLocator.Initialize();
|
||||||
ViewModelLocator.Instance.UpdateDependencies(UseMockServices);
|
ViewModelLocator.UpdateDependencies(UseMockServices);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task InitNavigation()
|
private Task InitNavigation()
|
||||||
{
|
{
|
||||||
var navigationService = ViewModelLocator.Instance.Resolve<INavigationService>();
|
var navigationService = ViewModelLocator.Resolve<INavigationService>();
|
||||||
return navigationService.InitializeAsync();
|
return navigationService.InitializeAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
using eShopOnContainers.Core.Effects;
|
||||||
|
|
||||||
namespace eShopOnContainers.Core.Effects
|
namespace eShopOnContainers.Core.Behaviors
|
||||||
{
|
{
|
||||||
public static class LineColorEffect
|
public static class LineColorBehavior
|
||||||
{
|
{
|
||||||
public static readonly BindableProperty ApplyLineColorProperty =
|
public static readonly BindableProperty ApplyLineColorProperty =
|
||||||
BindableProperty.CreateAttached("ApplyLineColor", typeof(bool), typeof(LineColorEffect), false,
|
BindableProperty.CreateAttached("ApplyLineColor", typeof(bool), typeof(LineColorBehavior), false,
|
||||||
propertyChanged: OnApplyLineColorChanged);
|
propertyChanged: OnApplyLineColorChanged);
|
||||||
|
|
||||||
|
public static readonly BindableProperty LineColorProperty =
|
||||||
|
BindableProperty.CreateAttached("LineColor", typeof(Color), typeof(LineColorBehavior), Color.Default);
|
||||||
|
|
||||||
public static bool GetApplyLineColor(BindableObject view)
|
public static bool GetApplyLineColor(BindableObject view)
|
||||||
{
|
{
|
||||||
return (bool)view.GetValue(ApplyLineColorProperty);
|
return (bool)view.GetValue(ApplyLineColorProperty);
|
||||||
@ -19,6 +23,16 @@ namespace eShopOnContainers.Core.Effects
|
|||||||
view.SetValue(ApplyLineColorProperty, value);
|
view.SetValue(ApplyLineColorProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Color GetLineColor(BindableObject view)
|
||||||
|
{
|
||||||
|
return (Color)view.GetValue(LineColorProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetLineColor(BindableObject view, Color value)
|
||||||
|
{
|
||||||
|
view.SetValue(LineColorProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
private static void OnApplyLineColorChanged(BindableObject bindable, object oldValue, object newValue)
|
private static void OnApplyLineColorChanged(BindableObject bindable, object oldValue, object newValue)
|
||||||
{
|
{
|
||||||
var view = bindable as View;
|
var view = bindable as View;
|
||||||
@ -28,9 +42,9 @@ namespace eShopOnContainers.Core.Effects
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasShadow = (bool)newValue;
|
bool hasLine = (bool)newValue;
|
||||||
|
|
||||||
if (hasShadow)
|
if (hasLine)
|
||||||
{
|
{
|
||||||
view.Effects.Add(new EntryLineColorEffect());
|
view.Effects.Add(new EntryLineColorEffect());
|
||||||
}
|
}
|
||||||
@ -43,25 +57,5 @@ namespace eShopOnContainers.Core.Effects
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly BindableProperty LineColorProperty =
|
|
||||||
BindableProperty.CreateAttached("LineColor", typeof(Color), typeof(LineColorEffect), Color.Default);
|
|
||||||
|
|
||||||
public static Color GetLineColor(BindableObject view)
|
|
||||||
{
|
|
||||||
return (Color)view.GetValue(LineColorProperty);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetLineColor(BindableObject view, Color value)
|
|
||||||
{
|
|
||||||
view.SetValue(LineColorProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
class EntryLineColorEffect : RoutingEffect
|
|
||||||
{
|
|
||||||
public EntryLineColorEffect() : base("eShopOnContainers.EntryLineColorEffect")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace eShopOnContainers.Core.Converters
|
||||||
|
{
|
||||||
|
public class FirstValidationErrorConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
ICollection<string> errors = value as ICollection<string>;
|
||||||
|
return errors != null && errors.Count > 0 ? errors.ElementAt(0) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace eShopOnContainers.Core.Effects
|
||||||
|
{
|
||||||
|
public class EntryLineColorEffect : RoutingEffect
|
||||||
|
{
|
||||||
|
public EntryLineColorEffect() : base("eShopOnContainers.EntryLineColorEffect")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +0,0 @@
|
|||||||
using eShopOnContainers.Core.Animations.Base;
|
|
||||||
using System;
|
|
||||||
using Xamarin.Forms;
|
|
||||||
|
|
||||||
namespace eShopOnContainers.Core.Extensions
|
|
||||||
{
|
|
||||||
public static class AnimationExtension
|
|
||||||
{
|
|
||||||
public static async void Animate(this VisualElement visualElement, AnimationBase animation, Action onFinishedCallback = null)
|
|
||||||
{
|
|
||||||
animation.Target = visualElement;
|
|
||||||
|
|
||||||
await animation.Begin();
|
|
||||||
|
|
||||||
onFinishedCallback?.Invoke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
using eShopOnContainers.Core.Models.Basket;
|
using eShopOnContainers.Core.Models.Basket;
|
||||||
using eShopOnContainers.Core.Models.Catalog;
|
using eShopOnContainers.Core.Models.Catalog;
|
||||||
using eShopOnContainers.ViewModels.Base;
|
using eShopOnContainers.Core.ViewModels.Base;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@ -21,7 +21,7 @@ namespace eShopOnContainers.Core.Helpers
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!ViewModelLocator.Instance.UseMockService
|
if (!ViewModelLocator.UseMockService
|
||||||
&& Settings.UrlBase != GlobalSetting.DefaultEndpoint)
|
&& Settings.UrlBase != GlobalSetting.DefaultEndpoint)
|
||||||
{
|
{
|
||||||
foreach (var catalogItem in catalogItems)
|
foreach (var catalogItem in catalogItems)
|
||||||
@ -54,7 +54,7 @@ namespace eShopOnContainers.Core.Helpers
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!ViewModelLocator.Instance.UseMockService
|
if (!ViewModelLocator.UseMockService
|
||||||
&& Settings.UrlBase != GlobalSetting.DefaultEndpoint)
|
&& Settings.UrlBase != GlobalSetting.DefaultEndpoint)
|
||||||
{
|
{
|
||||||
foreach (var basketItem in basketItems)
|
foreach (var basketItem in basketItems)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using eShopOnContainers.ViewModels.Base;
|
using eShopOnContainers.Core.ViewModels.Base;
|
||||||
using Plugin.Settings;
|
using Plugin.Settings;
|
||||||
using Plugin.Settings.Abstractions;
|
using Plugin.Settings.Abstractions;
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ namespace eShopOnContainers.Core.Helpers
|
|||||||
private const string IdUrlBase = "url_base";
|
private const string IdUrlBase = "url_base";
|
||||||
private static readonly string AccessTokenDefault = string.Empty;
|
private static readonly string AccessTokenDefault = string.Empty;
|
||||||
private static readonly string IdTokenDefault = string.Empty;
|
private static readonly string IdTokenDefault = string.Empty;
|
||||||
private static readonly bool UseMocksDefault = ViewModelLocator.Instance.UseMockService;
|
private static readonly bool UseMocksDefault = true;
|
||||||
private static readonly string UrlBaseDefault = GlobalSetting.Instance.BaseEndpoint;
|
private static readonly string UrlBaseDefault = GlobalSetting.Instance.BaseEndpoint;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using eShopOnContainers.ViewModels.Base;
|
using eShopOnContainers.Core.ViewModels.Base;
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace eShopOnContainers.Services
|
namespace eShopOnContainers.Services
|
||||||
@ -12,12 +11,6 @@ namespace eShopOnContainers.Services
|
|||||||
|
|
||||||
Task NavigateToAsync<TViewModel>(object parameter) where TViewModel : ViewModelBase;
|
Task NavigateToAsync<TViewModel>(object parameter) where TViewModel : ViewModelBase;
|
||||||
|
|
||||||
Task NavigateToAsync(Type viewModelType);
|
|
||||||
|
|
||||||
Task NavigateToAsync(Type viewModelType, object parameter);
|
|
||||||
|
|
||||||
Task NavigateBackAsync();
|
|
||||||
|
|
||||||
Task RemoveLastFromBackStackAsync();
|
Task RemoveLastFromBackStackAsync();
|
||||||
|
|
||||||
Task RemoveBackStackAsync();
|
Task RemoveBackStackAsync();
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
using eShopOnContainers.Core.Helpers;
|
using eShopOnContainers.Core.Helpers;
|
||||||
using eShopOnContainers.Core.ViewModels;
|
using eShopOnContainers.Core.ViewModels;
|
||||||
using eShopOnContainers.Core.Views;
|
using eShopOnContainers.Core.Views;
|
||||||
using eShopOnContainers.ViewModels.Base;
|
using eShopOnContainers.Core.ViewModels.Base;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Globalization;
|
||||||
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
@ -11,23 +12,6 @@ namespace eShopOnContainers.Services
|
|||||||
{
|
{
|
||||||
public class NavigationService : INavigationService
|
public class NavigationService : INavigationService
|
||||||
{
|
{
|
||||||
protected readonly Dictionary<Type, Type> _mappings;
|
|
||||||
|
|
||||||
protected Application CurrentApplication
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return Application.Current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public NavigationService()
|
|
||||||
{
|
|
||||||
_mappings = new Dictionary<Type, Type>();
|
|
||||||
|
|
||||||
CreatePageViewModelMappings();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task InitializeAsync()
|
public Task InitializeAsync()
|
||||||
{
|
{
|
||||||
if(string.IsNullOrEmpty(Settings.AuthAccessToken))
|
if(string.IsNullOrEmpty(Settings.AuthAccessToken))
|
||||||
@ -46,32 +30,9 @@ namespace eShopOnContainers.Services
|
|||||||
return InternalNavigateToAsync(typeof(TViewModel), parameter);
|
return InternalNavigateToAsync(typeof(TViewModel), parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task NavigateToAsync(Type viewModelType)
|
public Task RemoveLastFromBackStackAsync()
|
||||||
{
|
{
|
||||||
return InternalNavigateToAsync(viewModelType, null);
|
var mainPage = Application.Current.MainPage as CustomNavigationView;
|
||||||
}
|
|
||||||
|
|
||||||
public Task NavigateToAsync(Type viewModelType, object parameter)
|
|
||||||
{
|
|
||||||
return InternalNavigateToAsync(viewModelType, parameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task NavigateBackAsync()
|
|
||||||
{
|
|
||||||
if (CurrentApplication.MainPage is CatalogView)
|
|
||||||
{
|
|
||||||
var mainPage = CurrentApplication.MainPage as CatalogView;
|
|
||||||
await mainPage.Navigation.PopAsync();
|
|
||||||
}
|
|
||||||
else if (CurrentApplication.MainPage != null)
|
|
||||||
{
|
|
||||||
await CurrentApplication.MainPage.Navigation.PopAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual Task RemoveLastFromBackStackAsync()
|
|
||||||
{
|
|
||||||
var mainPage = CurrentApplication.MainPage as CustomNavigationView;
|
|
||||||
|
|
||||||
if (mainPage != null)
|
if (mainPage != null)
|
||||||
{
|
{
|
||||||
@ -82,9 +43,9 @@ namespace eShopOnContainers.Services
|
|||||||
return Task.FromResult(true);
|
return Task.FromResult(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual Task RemoveBackStackAsync()
|
public Task RemoveBackStackAsync()
|
||||||
{
|
{
|
||||||
var mainPage = CurrentApplication.MainPage as CustomNavigationView;
|
var mainPage = Application.Current.MainPage as CustomNavigationView;
|
||||||
|
|
||||||
if (mainPage != null)
|
if (mainPage != null)
|
||||||
{
|
{
|
||||||
@ -98,67 +59,49 @@ namespace eShopOnContainers.Services
|
|||||||
return Task.FromResult(true);
|
return Task.FromResult(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual async Task InternalNavigateToAsync(Type viewModelType, object parameter)
|
private async Task InternalNavigateToAsync(Type viewModelType, object parameter)
|
||||||
{
|
{
|
||||||
Page page = CreateAndBindPage(viewModelType, parameter);
|
Page page = CreatePage(viewModelType, parameter);
|
||||||
|
|
||||||
if (page is LoginView)
|
if (page is LoginView)
|
||||||
{
|
{
|
||||||
CurrentApplication.MainPage = new CustomNavigationView(page);
|
Application.Current.MainPage = new CustomNavigationView(page);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var navigationPage = CurrentApplication.MainPage as CustomNavigationView;
|
var navigationPage = Application.Current.MainPage as CustomNavigationView;
|
||||||
|
|
||||||
if (navigationPage != null)
|
if (navigationPage != null)
|
||||||
{
|
{
|
||||||
await navigationPage.PushAsync(page);
|
await navigationPage.PushAsync(page);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CurrentApplication.MainPage = new CustomNavigationView(page);
|
Application.Current.MainPage = new CustomNavigationView(page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await (page.BindingContext as ViewModelBase).InitializeAsync(parameter);
|
await (page.BindingContext as ViewModelBase).InitializeAsync(parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Type GetPageTypeForViewModel(Type viewModelType)
|
private Type GetPageTypeForViewModel(Type viewModelType)
|
||||||
{
|
{
|
||||||
if (!_mappings.ContainsKey(viewModelType))
|
var viewName = viewModelType.FullName.Replace("Model", string.Empty);
|
||||||
{
|
var viewModelAssemblyName = viewModelType.GetTypeInfo().Assembly.FullName;
|
||||||
throw new KeyNotFoundException($"No map for ${viewModelType} was found on navigation mappings");
|
var viewAssemblyName = string.Format(CultureInfo.InvariantCulture, "{0}, {1}", viewName, viewModelAssemblyName);
|
||||||
}
|
var viewType = Type.GetType(viewAssemblyName);
|
||||||
|
return viewType;
|
||||||
|
}
|
||||||
|
|
||||||
return _mappings[viewModelType];
|
private Page CreatePage(Type viewModelType, object parameter)
|
||||||
}
|
{
|
||||||
|
Type pageType = GetPageTypeForViewModel(viewModelType);
|
||||||
|
if (pageType == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"Cannot locate page type for {viewModelType}");
|
||||||
|
}
|
||||||
|
|
||||||
protected Page CreateAndBindPage(Type viewModelType, object parameter)
|
Page page = Activator.CreateInstance(pageType) as Page;
|
||||||
{
|
return page;
|
||||||
Type pageType = GetPageTypeForViewModel(viewModelType);
|
}
|
||||||
|
|
||||||
if (pageType == null)
|
|
||||||
{
|
|
||||||
throw new Exception($"Mapping type for {viewModelType} is not a page");
|
|
||||||
}
|
|
||||||
|
|
||||||
Page page = Activator.CreateInstance(pageType) as Page;
|
|
||||||
ViewModelBase viewModel = ViewModelLocator.Instance.Resolve(viewModelType) as ViewModelBase;
|
|
||||||
page.BindingContext = viewModel;
|
|
||||||
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreatePageViewModelMappings()
|
|
||||||
{
|
|
||||||
_mappings.Add(typeof(BasketViewModel), typeof(BasketView));
|
|
||||||
_mappings.Add(typeof(CatalogViewModel), typeof(CatalogView));
|
|
||||||
_mappings.Add(typeof(CheckoutViewModel), typeof(CheckoutView));
|
|
||||||
_mappings.Add(typeof(LoginViewModel), typeof(LoginView));
|
|
||||||
_mappings.Add(typeof(MainViewModel), typeof(MainView));
|
|
||||||
_mappings.Add(typeof(OrderDetailViewModel), typeof(OrderDetailView));
|
|
||||||
_mappings.Add(typeof(ProfileViewModel), typeof(ProfileView));
|
|
||||||
_mappings.Add(typeof(SettingsViewModel), typeof(SettingsView));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,5 @@
|
|||||||
using eShopOnContainers.ViewModels.Base;
|
using eShopOnContainers.Core.ViewModels.Base;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace eShopOnContainers.Core.Validations
|
namespace eShopOnContainers.Core.Validations
|
||||||
@ -8,13 +7,24 @@ namespace eShopOnContainers.Core.Validations
|
|||||||
public class ValidatableObject<T> : ExtendedBindableObject, IValidity
|
public class ValidatableObject<T> : ExtendedBindableObject, IValidity
|
||||||
{
|
{
|
||||||
private readonly List<IValidationRule<T>> _validations;
|
private readonly List<IValidationRule<T>> _validations;
|
||||||
private readonly ObservableCollection<string> _errors;
|
private List<string> _errors;
|
||||||
private T _value;
|
private T _value;
|
||||||
private bool _isValid;
|
private bool _isValid;
|
||||||
|
|
||||||
public List<IValidationRule<T>> Validations => _validations;
|
public List<IValidationRule<T>> Validations => _validations;
|
||||||
|
|
||||||
public ObservableCollection<string> Errors => _errors;
|
public List<string> Errors
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _errors;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_errors = value;
|
||||||
|
RaisePropertyChanged(() => Errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public T Value
|
public T Value
|
||||||
{
|
{
|
||||||
@ -22,7 +32,6 @@ namespace eShopOnContainers.Core.Validations
|
|||||||
{
|
{
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_value = value;
|
_value = value;
|
||||||
@ -36,11 +45,9 @@ namespace eShopOnContainers.Core.Validations
|
|||||||
{
|
{
|
||||||
return _isValid;
|
return _isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_isValid = value;
|
_isValid = value;
|
||||||
_errors.Clear();
|
|
||||||
RaisePropertyChanged(() => IsValid);
|
RaisePropertyChanged(() => IsValid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,7 +55,7 @@ namespace eShopOnContainers.Core.Validations
|
|||||||
public ValidatableObject()
|
public ValidatableObject()
|
||||||
{
|
{
|
||||||
_isValid = true;
|
_isValid = true;
|
||||||
_errors = new ObservableCollection<string>();
|
_errors = new List<string>();
|
||||||
_validations = new List<IValidationRule<T>>();
|
_validations = new List<IValidationRule<T>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,11 +66,7 @@ namespace eShopOnContainers.Core.Validations
|
|||||||
IEnumerable<string> errors = _validations.Where(v => !v.Check(Value))
|
IEnumerable<string> errors = _validations.Where(v => !v.Check(Value))
|
||||||
.Select(v => v.ValidationMessage);
|
.Select(v => v.ValidationMessage);
|
||||||
|
|
||||||
foreach (var error in errors)
|
Errors = errors.ToList();
|
||||||
{
|
|
||||||
Errors.Add(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
IsValid = !Errors.Any();
|
IsValid = !Errors.Any();
|
||||||
|
|
||||||
return this.IsValid;
|
return this.IsValid;
|
||||||
|
@ -3,7 +3,7 @@ using System.Linq.Expressions;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
namespace eShopOnContainers.ViewModels.Base
|
namespace eShopOnContainers.Core.ViewModels.Base
|
||||||
{
|
{
|
||||||
public abstract class ExtendedBindableObject : BindableObject
|
public abstract class ExtendedBindableObject : BindableObject
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
namespace eShopOnContainers.Core.ViewModels.Base
|
namespace eShopOnContainers.Core.ViewModels.Base
|
||||||
{
|
{
|
||||||
public class MessengerKeys
|
public class MessageKeys
|
||||||
{
|
{
|
||||||
// Add product to basket
|
// Add product to basket
|
||||||
public const string AddProduct = "AddProduct";
|
public const string AddProduct = "AddProduct";
|
@ -1,9 +1,8 @@
|
|||||||
using eShopOnContainers.Core;
|
using eShopOnContainers.Core.Helpers;
|
||||||
using eShopOnContainers.Core.Helpers;
|
|
||||||
using eShopOnContainers.Services;
|
using eShopOnContainers.Services;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace eShopOnContainers.ViewModels.Base
|
namespace eShopOnContainers.Core.ViewModels.Base
|
||||||
{
|
{
|
||||||
public abstract class ViewModelBase : ExtendedBindableObject
|
public abstract class ViewModelBase : ExtendedBindableObject
|
||||||
{
|
{
|
||||||
@ -28,8 +27,8 @@ namespace eShopOnContainers.ViewModels.Base
|
|||||||
|
|
||||||
public ViewModelBase()
|
public ViewModelBase()
|
||||||
{
|
{
|
||||||
DialogService = ViewModelLocator.Instance.Resolve<IDialogService>();
|
DialogService = ViewModelLocator.Resolve<IDialogService>();
|
||||||
NavigationService = ViewModelLocator.Instance.Resolve<INavigationService>();
|
NavigationService = ViewModelLocator.Resolve<INavigationService>();
|
||||||
GlobalSetting.Instance.BaseEndpoint = Settings.UrlBase;
|
GlobalSetting.Instance.BaseEndpoint = Settings.UrlBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
using Microsoft.Practices.Unity;
|
using Microsoft.Practices.Unity;
|
||||||
using eShopOnContainers.Core.ViewModels;
|
|
||||||
using eShopOnContainers.Services;
|
using eShopOnContainers.Services;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Reflection;
|
||||||
using eShopOnContainers.Core.Services.Catalog;
|
using eShopOnContainers.Core.Services.Catalog;
|
||||||
using eShopOnContainers.Core.Services.OpenUrl;
|
using eShopOnContainers.Core.Services.OpenUrl;
|
||||||
using eShopOnContainers.Core.Services.RequestProvider;
|
using eShopOnContainers.Core.Services.RequestProvider;
|
||||||
@ -9,100 +10,101 @@ using eShopOnContainers.Core.Services.Basket;
|
|||||||
using eShopOnContainers.Core.Services.Identity;
|
using eShopOnContainers.Core.Services.Identity;
|
||||||
using eShopOnContainers.Core.Services.Order;
|
using eShopOnContainers.Core.Services.Order;
|
||||||
using eShopOnContainers.Core.Services.User;
|
using eShopOnContainers.Core.Services.User;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
namespace eShopOnContainers.ViewModels.Base
|
namespace eShopOnContainers.Core.ViewModels.Base
|
||||||
{
|
{
|
||||||
public class ViewModelLocator
|
public static class ViewModelLocator
|
||||||
{
|
{
|
||||||
private bool _useMockService;
|
private static readonly IUnityContainer _unityContainer = new UnityContainer();
|
||||||
private readonly IUnityContainer _unityContainer;
|
|
||||||
|
|
||||||
private static readonly ViewModelLocator _instance = new ViewModelLocator();
|
public static readonly BindableProperty AutoWireViewModelProperty =
|
||||||
|
BindableProperty.CreateAttached("AutoWireViewModel", typeof(bool), typeof(ViewModelLocator), default(bool), propertyChanged: OnAutoWireViewModelChanged);
|
||||||
|
|
||||||
public static ViewModelLocator Instance
|
public static bool GetAutoWireViewModel(BindableObject bindable)
|
||||||
{
|
{
|
||||||
get { return _instance; }
|
return (bool)bindable.GetValue(ViewModelLocator.AutoWireViewModelProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool UseMockService
|
public static void SetAutoWireViewModel(BindableObject bindable, bool value)
|
||||||
{
|
{
|
||||||
get { return _useMockService; }
|
bindable.SetValue(ViewModelLocator.AutoWireViewModelProperty, value);
|
||||||
set { _useMockService = value; ; }
|
}
|
||||||
}
|
|
||||||
|
|
||||||
protected ViewModelLocator()
|
public static bool UseMockService { get; set; }
|
||||||
{
|
|
||||||
_unityContainer = new UnityContainer();
|
|
||||||
|
|
||||||
// Services
|
public static void Initialize()
|
||||||
_unityContainer.RegisterType<IDialogService, DialogService>();
|
{
|
||||||
RegisterSingleton<INavigationService, NavigationService>();
|
// Services
|
||||||
_unityContainer.RegisterType<IOpenUrlService, OpenUrlService>();
|
_unityContainer.RegisterType<IDialogService, DialogService>();
|
||||||
_unityContainer.RegisterType<IRequestProvider, RequestProvider>();
|
_unityContainer.RegisterType<INavigationService, NavigationService>(new ContainerControlledLifetimeManager());
|
||||||
_unityContainer.RegisterType<IIdentityService, IdentityService>();
|
_unityContainer.RegisterType<IOpenUrlService, OpenUrlService>();
|
||||||
|
_unityContainer.RegisterType<IRequestProvider, RequestProvider>();
|
||||||
|
_unityContainer.RegisterType<IIdentityService, IdentityService>();
|
||||||
|
_unityContainer.RegisterType<ICatalogService, CatalogMockService>();
|
||||||
|
_unityContainer.RegisterType<IBasketService, BasketMockService>();
|
||||||
|
_unityContainer.RegisterType<IUserService, UserMockService>();
|
||||||
|
|
||||||
_unityContainer.RegisterType<ICatalogService, CatalogMockService>();
|
// View models
|
||||||
_unityContainer.RegisterType<IBasketService, BasketMockService>();
|
_unityContainer.RegisterType<BasketViewModel>();
|
||||||
_unityContainer.RegisterType<IUserService, UserMockService>();
|
_unityContainer.RegisterType<CatalogViewModel>();
|
||||||
|
_unityContainer.RegisterType<CheckoutViewModel>();
|
||||||
|
_unityContainer.RegisterType<LoginViewModel>();
|
||||||
|
_unityContainer.RegisterType<MainViewModel>();
|
||||||
|
_unityContainer.RegisterType<OrderDetailViewModel>();
|
||||||
|
_unityContainer.RegisterType<ProfileViewModel>();
|
||||||
|
_unityContainer.RegisterType<SettingsViewModel>();
|
||||||
|
}
|
||||||
|
|
||||||
// View models
|
public static void UpdateDependencies(bool useMockServices)
|
||||||
_unityContainer.RegisterType<BasketViewModel>();
|
{
|
||||||
_unityContainer.RegisterType<CatalogViewModel>();
|
// Change injected dependencies
|
||||||
_unityContainer.RegisterType<CheckoutViewModel>();
|
if (useMockServices)
|
||||||
_unityContainer.RegisterType<LoginViewModel>();
|
{
|
||||||
_unityContainer.RegisterType<MainViewModel>();
|
_unityContainer.RegisterInstance<ICatalogService>(new CatalogMockService());
|
||||||
_unityContainer.RegisterType<OrderDetailViewModel>();
|
_unityContainer.RegisterInstance<IBasketService>(new BasketMockService());
|
||||||
_unityContainer.RegisterType<ProfileViewModel>();
|
_unityContainer.RegisterInstance<IOrderService>(new OrderMockService());
|
||||||
_unityContainer.RegisterType<SettingsViewModel>();
|
_unityContainer.RegisterInstance<IUserService>(new UserMockService());
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateDependencies(bool useMockServices)
|
UseMockService = true;
|
||||||
{
|
}
|
||||||
// Change injected dependencies
|
else
|
||||||
if (useMockServices)
|
{
|
||||||
{
|
var requestProvider = Resolve<IRequestProvider>();
|
||||||
_unityContainer.RegisterInstance<ICatalogService>(new CatalogMockService());
|
_unityContainer.RegisterInstance<ICatalogService>(new CatalogService(requestProvider));
|
||||||
_unityContainer.RegisterInstance<IBasketService>(new BasketMockService());
|
_unityContainer.RegisterInstance<IBasketService>(new BasketService(requestProvider));
|
||||||
_unityContainer.RegisterInstance<IOrderService>(new OrderMockService());
|
_unityContainer.RegisterInstance<IOrderService>(new OrderService(requestProvider));
|
||||||
_unityContainer.RegisterInstance<IUserService>(new UserMockService());
|
_unityContainer.RegisterInstance<IUserService>(new UserService(requestProvider));
|
||||||
|
|
||||||
UseMockService = true;
|
UseMockService = false;
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
var requestProvider = Resolve<IRequestProvider>();
|
|
||||||
_unityContainer.RegisterInstance<ICatalogService>(new CatalogService(requestProvider));
|
|
||||||
_unityContainer.RegisterInstance<IBasketService>(new BasketService(requestProvider));
|
|
||||||
_unityContainer.RegisterInstance<IOrderService>(new OrderService(requestProvider));
|
|
||||||
_unityContainer.RegisterInstance<IUserService>(new UserService(requestProvider));
|
|
||||||
|
|
||||||
UseMockService = false;
|
public static T Resolve<T>()
|
||||||
}
|
{
|
||||||
}
|
return _unityContainer.Resolve<T>();
|
||||||
|
}
|
||||||
|
|
||||||
public T Resolve<T>()
|
private static void OnAutoWireViewModelChanged(BindableObject bindable, object oldValue, object newValue)
|
||||||
{
|
{
|
||||||
return _unityContainer.Resolve<T>();
|
var view = bindable as Element;
|
||||||
}
|
if (view == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
public object Resolve(Type type)
|
var viewType = view.GetType();
|
||||||
{
|
var viewName = viewType.FullName.Replace(".Views.", ".ViewModels.");
|
||||||
return _unityContainer.Resolve(type);
|
var viewAssemblyName = viewType.GetTypeInfo().Assembly.FullName;
|
||||||
}
|
var viewModelName = string.Format(CultureInfo.InvariantCulture, "{0}Model, {1}", viewName, viewAssemblyName);
|
||||||
|
|
||||||
public void Register<T>(T instance)
|
var viewModelType = Type.GetType(viewModelName);
|
||||||
{
|
if (viewModelType == null)
|
||||||
_unityContainer.RegisterInstance<T>(instance);
|
{
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
public void Register<TInterface, T>() where T : TInterface
|
var viewModel = _unityContainer.Resolve(viewModelType);
|
||||||
{
|
view.BindingContext = viewModel;
|
||||||
_unityContainer.RegisterType<TInterface, T>();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegisterSingleton<TInterface, T>() where T : TInterface
|
|
||||||
{
|
|
||||||
_unityContainer.RegisterType<TInterface, T>(new ContainerControlledLifetimeManager());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -4,8 +4,6 @@ using eShopOnContainers.Core.Models.Catalog;
|
|||||||
using eShopOnContainers.Core.Services.Basket;
|
using eShopOnContainers.Core.Services.Basket;
|
||||||
using eShopOnContainers.Core.Services.User;
|
using eShopOnContainers.Core.Services.User;
|
||||||
using eShopOnContainers.Core.ViewModels.Base;
|
using eShopOnContainers.Core.ViewModels.Base;
|
||||||
using eShopOnContainers.ViewModels.Base;
|
|
||||||
using System;
|
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -61,7 +59,7 @@ namespace eShopOnContainers.Core.ViewModels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICommand AddCommand => new Command<BasketItem>(AddItem);
|
public ICommand AddCommand => new Command<BasketItem>(async (item) => await AddItemAsync(item));
|
||||||
|
|
||||||
public ICommand CheckoutCommand => new Command(async () => await CheckoutAsync());
|
public ICommand CheckoutCommand => new Command(async () => await CheckoutAsync());
|
||||||
|
|
||||||
@ -84,22 +82,22 @@ namespace eShopOnContainers.Core.ViewModels
|
|||||||
foreach (var basketItem in basket.Items)
|
foreach (var basketItem in basket.Items)
|
||||||
{
|
{
|
||||||
BadgeCount += basketItem.Quantity;
|
BadgeCount += basketItem.Quantity;
|
||||||
AddBasketItem(basketItem);
|
await AddBasketItemAsync(basketItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MessagingCenter.Unsubscribe<CatalogViewModel, CatalogItem>(this, MessengerKeys.AddProduct);
|
MessagingCenter.Unsubscribe<CatalogViewModel, CatalogItem>(this, MessageKeys.AddProduct);
|
||||||
MessagingCenter.Subscribe<CatalogViewModel, CatalogItem>(this, MessengerKeys.AddProduct, (sender, arg) =>
|
MessagingCenter.Subscribe<CatalogViewModel, CatalogItem>(this, MessageKeys.AddProduct, async (sender, arg) =>
|
||||||
{
|
{
|
||||||
BadgeCount++;
|
BadgeCount++;
|
||||||
|
|
||||||
AddCatalogItem(arg);
|
await AddCatalogItemAsync(arg);
|
||||||
});
|
});
|
||||||
|
|
||||||
await base.InitializeAsync(navigationData);
|
await base.InitializeAsync(navigationData);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddCatalogItem(CatalogItem item)
|
private async Task AddCatalogItemAsync(CatalogItem item)
|
||||||
{
|
{
|
||||||
BasketItems.Add(new BasketItem
|
BasketItems.Add(new BasketItem
|
||||||
{
|
{
|
||||||
@ -110,26 +108,26 @@ namespace eShopOnContainers.Core.ViewModels
|
|||||||
Quantity = 1
|
Quantity = 1
|
||||||
});
|
});
|
||||||
|
|
||||||
ReCalculateTotal();
|
await ReCalculateTotalAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddItem(BasketItem item)
|
private async Task AddItemAsync(BasketItem item)
|
||||||
{
|
{
|
||||||
BadgeCount++;
|
BadgeCount++;
|
||||||
|
|
||||||
AddBasketItem(item);
|
await AddBasketItemAsync(item);
|
||||||
|
|
||||||
RaisePropertyChanged(() => BasketItems);
|
RaisePropertyChanged(() => BasketItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddBasketItem(BasketItem item)
|
private async Task AddBasketItemAsync(BasketItem item)
|
||||||
{
|
{
|
||||||
BasketItems.Add(item);
|
BasketItems.Add(item);
|
||||||
|
|
||||||
ReCalculateTotal();
|
await ReCalculateTotalAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void ReCalculateTotal()
|
private async Task ReCalculateTotalAsync()
|
||||||
{
|
{
|
||||||
Total = 0;
|
Total = 0;
|
||||||
|
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using eShopOnContainers.ViewModels.Base;
|
using eShopOnContainers.Core.ViewModels.Base;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
using eShopOnContainers.Core.ViewModels.Base;
|
|
||||||
using eShopOnContainers.Core.Models.Catalog;
|
using eShopOnContainers.Core.Models.Catalog;
|
||||||
using eShopOnContainers.Core.Services.Catalog;
|
using eShopOnContainers.Core.Services.Catalog;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Linq;
|
|
||||||
using eShopOnContainers.Core.Services.Basket;
|
using eShopOnContainers.Core.Services.Basket;
|
||||||
using eShopOnContainers.Core.Helpers;
|
|
||||||
using eShopOnContainers.Core.Services.User;
|
using eShopOnContainers.Core.Services.User;
|
||||||
|
|
||||||
namespace eShopOnContainers.Core.ViewModels
|
namespace eShopOnContainers.Core.ViewModels
|
||||||
@ -20,19 +17,11 @@ namespace eShopOnContainers.Core.ViewModels
|
|||||||
private CatalogBrand _brand;
|
private CatalogBrand _brand;
|
||||||
private ObservableCollection<CatalogType> _types;
|
private ObservableCollection<CatalogType> _types;
|
||||||
private CatalogType _type;
|
private CatalogType _type;
|
||||||
|
|
||||||
private IBasketService _basketService;
|
|
||||||
private ICatalogService _productsService;
|
private ICatalogService _productsService;
|
||||||
private IUserService _userService;
|
|
||||||
|
|
||||||
public CatalogViewModel(
|
public CatalogViewModel(ICatalogService productsService)
|
||||||
IBasketService basketService,
|
|
||||||
ICatalogService productsService,
|
|
||||||
IUserService userService)
|
|
||||||
{
|
{
|
||||||
_basketService = basketService;
|
|
||||||
_productsService = productsService;
|
_productsService = productsService;
|
||||||
_userService = userService;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObservableCollection<CatalogItem> Products
|
public ObservableCollection<CatalogItem> Products
|
||||||
@ -91,9 +80,9 @@ namespace eShopOnContainers.Core.ViewModels
|
|||||||
|
|
||||||
public ICommand AddCatalogItemCommand => new Command<CatalogItem>(AddCatalogItem);
|
public ICommand AddCatalogItemCommand => new Command<CatalogItem>(AddCatalogItem);
|
||||||
|
|
||||||
public ICommand FilterCommand => new Command(Filter);
|
public ICommand FilterCommand => new Command(async () => await FilterAsync());
|
||||||
|
|
||||||
public ICommand ClearFilterCommand => new Command(ClearFilter);
|
public ICommand ClearFilterCommand => new Command(async () => await ClearFilterAsync());
|
||||||
|
|
||||||
public override async Task InitializeAsync(object navigationData)
|
public override async Task InitializeAsync(object navigationData)
|
||||||
{
|
{
|
||||||
@ -110,10 +99,10 @@ namespace eShopOnContainers.Core.ViewModels
|
|||||||
private void AddCatalogItem(CatalogItem catalogItem)
|
private void AddCatalogItem(CatalogItem catalogItem)
|
||||||
{
|
{
|
||||||
// Add new item to Basket
|
// Add new item to Basket
|
||||||
MessagingCenter.Send(this, MessengerKeys.AddProduct, catalogItem);
|
MessagingCenter.Send(this, MessageKeys.AddProduct, catalogItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void Filter()
|
private async Task FilterAsync()
|
||||||
{
|
{
|
||||||
if (Brand == null && Type == null)
|
if (Brand == null && Type == null)
|
||||||
{
|
{
|
||||||
@ -123,13 +112,13 @@ namespace eShopOnContainers.Core.ViewModels
|
|||||||
IsBusy = true;
|
IsBusy = true;
|
||||||
|
|
||||||
// Filter catalog products
|
// Filter catalog products
|
||||||
MessagingCenter.Send(this, MessengerKeys.Filter);
|
MessagingCenter.Send(this, MessageKeys.Filter);
|
||||||
Products = await _productsService.FilterAsync(Brand.Id, Type.Id);
|
Products = await _productsService.FilterAsync(Brand.Id, Type.Id);
|
||||||
|
|
||||||
IsBusy = false;
|
IsBusy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void ClearFilter()
|
private async Task ClearFilterAsync()
|
||||||
{
|
{
|
||||||
IsBusy = true;
|
IsBusy = true;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
using eShopOnContainers.Core.Models.Navigation;
|
using eShopOnContainers.Core.Models.Navigation;
|
||||||
using eShopOnContainers.ViewModels.Base;
|
using eShopOnContainers.Core.ViewModels.Base;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -139,7 +139,7 @@ namespace eShopOnContainers.Core.ViewModels
|
|||||||
await _basketService.ClearBasketAsync(_shippingAddress.Id.ToString(), authToken);
|
await _basketService.ClearBasketAsync(_shippingAddress.Id.ToString(), authToken);
|
||||||
|
|
||||||
// Reset Basket badge
|
// Reset Basket badge
|
||||||
var basketViewModel = ViewModelLocator.Instance.Resolve<BasketViewModel>();
|
var basketViewModel = ViewModelLocator.Resolve<BasketViewModel>();
|
||||||
basketViewModel.BadgeCount = 0;
|
basketViewModel.BadgeCount = 0;
|
||||||
|
|
||||||
// Navigate to Orders
|
// Navigate to Orders
|
||||||
|
@ -2,9 +2,8 @@
|
|||||||
using eShopOnContainers.Core.Models.User;
|
using eShopOnContainers.Core.Models.User;
|
||||||
using eShopOnContainers.Core.Services.Identity;
|
using eShopOnContainers.Core.Services.Identity;
|
||||||
using eShopOnContainers.Core.Services.OpenUrl;
|
using eShopOnContainers.Core.Services.OpenUrl;
|
||||||
using eShopOnContainers.Core.Services.User;
|
|
||||||
using eShopOnContainers.Core.Validations;
|
using eShopOnContainers.Core.Validations;
|
||||||
using eShopOnContainers.ViewModels.Base;
|
using eShopOnContainers.Core.ViewModels.Base;
|
||||||
using IdentityModel.Client;
|
using IdentityModel.Client;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@ -25,16 +24,13 @@ namespace eShopOnContainers.Core.ViewModels
|
|||||||
|
|
||||||
private IOpenUrlService _openUrlService;
|
private IOpenUrlService _openUrlService;
|
||||||
private IIdentityService _identityService;
|
private IIdentityService _identityService;
|
||||||
private IUserService _userService;
|
|
||||||
|
|
||||||
public LoginViewModel(
|
public LoginViewModel(
|
||||||
IOpenUrlService openUrlService,
|
IOpenUrlService openUrlService,
|
||||||
IIdentityService identityService,
|
IIdentityService identityService)
|
||||||
IUserService userService)
|
|
||||||
{
|
{
|
||||||
_openUrlService = openUrlService;
|
_openUrlService = openUrlService;
|
||||||
_identityService = identityService;
|
_identityService = identityService;
|
||||||
_userService = userService;
|
|
||||||
|
|
||||||
_userName = new ValidatableObject<string>();
|
_userName = new ValidatableObject<string>();
|
||||||
_password = new ValidatableObject<string>();
|
_password = new ValidatableObject<string>();
|
||||||
@ -131,6 +127,10 @@ namespace eShopOnContainers.Core.ViewModels
|
|||||||
|
|
||||||
public ICommand SettingsCommand => new Command(async () => await SettingsAsync());
|
public ICommand SettingsCommand => new Command(async () => await SettingsAsync());
|
||||||
|
|
||||||
|
public ICommand ValidateUserNameCommand => new Command(() => ValidateUserName());
|
||||||
|
|
||||||
|
public ICommand ValidatePasswordCommand => new Command(() => ValidatePassword());
|
||||||
|
|
||||||
public override Task InitializeAsync(object navigationData)
|
public override Task InitializeAsync(object navigationData)
|
||||||
{
|
{
|
||||||
if(navigationData is LogoutParameter)
|
if(navigationData is LogoutParameter)
|
||||||
@ -255,16 +255,26 @@ namespace eShopOnContainers.Core.ViewModels
|
|||||||
|
|
||||||
private bool Validate()
|
private bool Validate()
|
||||||
{
|
{
|
||||||
bool isValidUser = _userName.Validate();
|
bool isValidUser = ValidateUserName();
|
||||||
bool isValidPassword = _password.Validate();
|
bool isValidPassword = ValidatePassword();
|
||||||
|
|
||||||
return isValidUser && isValidPassword;
|
return isValidUser && isValidPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool ValidateUserName()
|
||||||
|
{
|
||||||
|
return _userName.Validate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ValidatePassword()
|
||||||
|
{
|
||||||
|
return _password.Validate();
|
||||||
|
}
|
||||||
|
|
||||||
private void AddValidations()
|
private void AddValidations()
|
||||||
{
|
{
|
||||||
_userName.Validations.Add(new IsNotNullOrEmptyRule<string> { ValidationMessage = "Username should not be empty" });
|
_userName.Validations.Add(new IsNotNullOrEmptyRule<string> { ValidationMessage = "A username is required." });
|
||||||
_password.Validations.Add(new IsNotNullOrEmptyRule<string> { ValidationMessage = "Password should not be empty" });
|
_password.Validations.Add(new IsNotNullOrEmptyRule<string> { ValidationMessage = "A password is required." });
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InvalidateMock()
|
public void InvalidateMock()
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using eShopOnContainers.ViewModels.Base;
|
using eShopOnContainers.Core.ViewModels.Base;
|
||||||
using eShopOnContainers.Core.Models.Navigation;
|
using eShopOnContainers.Core.Models.Navigation;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
using eShopOnContainers.Core.ViewModels.Base;
|
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
|
||||||
namespace eShopOnContainers.Core.ViewModels
|
namespace eShopOnContainers.Core.ViewModels
|
||||||
@ -19,7 +18,7 @@ namespace eShopOnContainers.Core.ViewModels
|
|||||||
{
|
{
|
||||||
// Change selected application tab
|
// Change selected application tab
|
||||||
var tabIndex = ((TabParameter)navigationData).TabIndex;
|
var tabIndex = ((TabParameter)navigationData).TabIndex;
|
||||||
MessagingCenter.Send(this, MessengerKeys.ChangeTab, tabIndex);
|
MessagingCenter.Send(this, MessageKeys.ChangeTab, tabIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.InitializeAsync(navigationData);
|
return base.InitializeAsync(navigationData);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using eShopOnContainers.Core.Models.Orders;
|
using eShopOnContainers.Core.Models.Orders;
|
||||||
using eShopOnContainers.ViewModels.Base;
|
using eShopOnContainers.Core.ViewModels.Base;
|
||||||
using eShopOnContainers.Core.Services.Catalog;
|
using eShopOnContainers.Core.Services.Catalog;
|
||||||
using eShopOnContainers.Core.Services.Basket;
|
using eShopOnContainers.Core.Services.Basket;
|
||||||
using eShopOnContainers.Core.Services.Order;
|
using eShopOnContainers.Core.Services.Order;
|
||||||
@ -13,17 +13,10 @@ namespace eShopOnContainers.Core.ViewModels
|
|||||||
{
|
{
|
||||||
private Order _order;
|
private Order _order;
|
||||||
|
|
||||||
private IBasketService _orderService;
|
|
||||||
private ICatalogService _catalogService;
|
|
||||||
private IOrderService _ordersService;
|
private IOrderService _ordersService;
|
||||||
|
|
||||||
public OrderDetailViewModel(
|
public OrderDetailViewModel(IOrderService ordersService)
|
||||||
IBasketService orderService,
|
|
||||||
ICatalogService catalogService,
|
|
||||||
IOrderService ordersService)
|
|
||||||
{
|
{
|
||||||
_orderService = orderService;
|
|
||||||
_catalogService = catalogService;
|
|
||||||
_ordersService = ordersService;
|
_ordersService = ordersService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ using eShopOnContainers.Core.Helpers;
|
|||||||
using eShopOnContainers.Core.Models.Orders;
|
using eShopOnContainers.Core.Models.Orders;
|
||||||
using eShopOnContainers.Core.Models.User;
|
using eShopOnContainers.Core.Models.User;
|
||||||
using eShopOnContainers.Core.Services.Order;
|
using eShopOnContainers.Core.Services.Order;
|
||||||
using eShopOnContainers.ViewModels.Base;
|
using eShopOnContainers.Core.ViewModels.Base;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using eShopOnContainers.ViewModels.Base;
|
using eShopOnContainers.Core.ViewModels.Base;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -71,7 +71,7 @@ namespace eShopOnContainers.Core.ViewModels
|
|||||||
|
|
||||||
private void MockServices()
|
private void MockServices()
|
||||||
{
|
{
|
||||||
ViewModelLocator.Instance.UpdateDependencies(!UseAzureServices);
|
ViewModelLocator.UpdateDependencies(!UseAzureServices);
|
||||||
UpdateInfo();
|
UpdateInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,9 +2,11 @@
|
|||||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
x:Class="eShopOnContainers.Core.Views.BasketView"
|
x:Class="eShopOnContainers.Core.Views.BasketView"
|
||||||
|
xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core"
|
||||||
xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core"
|
xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core"
|
||||||
xmlns:templates="clr-namespace:eShopOnContainers.Core.Views.Templates;assembly=eShopOnContainers.Core"
|
xmlns:templates="clr-namespace:eShopOnContainers.Core.Views.Templates;assembly=eShopOnContainers.Core"
|
||||||
Title="Cart">
|
viewModelBase:ViewModelLocator.AutoWireViewModel="true"
|
||||||
|
Title="Cart">
|
||||||
<ContentPage.Resources>
|
<ContentPage.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
|
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
x:Class="eShopOnContainers.Core.Views.CatalogView"
|
x:Class="eShopOnContainers.Core.Views.CatalogView"
|
||||||
xmlns:templates="clr-namespace:eShopOnContainers.Core.Views.Templates;assembly=eShopOnContainers.Core"
|
xmlns:templates="clr-namespace:eShopOnContainers.Core.Views.Templates;assembly=eShopOnContainers.Core"
|
||||||
xmlns:views="clr-namespace:eShopOnContainers.Core.Views;assembly=eShopOnContainers.Core"
|
xmlns:views="clr-namespace:eShopOnContainers.Core.Views;assembly=eShopOnContainers.Core"
|
||||||
|
xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core"
|
||||||
xmlns:animations="clr-namespace:eShopOnContainers.Core.Animations;assembly=eShopOnContainers.Core"
|
xmlns:animations="clr-namespace:eShopOnContainers.Core.Animations;assembly=eShopOnContainers.Core"
|
||||||
xmlns:triggers="clr-namespace:eShopOnContainers.Core.Triggers;assembly=eShopOnContainers.Core"
|
xmlns:triggers="clr-namespace:eShopOnContainers.Core.Triggers;assembly=eShopOnContainers.Core"
|
||||||
xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core"
|
xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core"
|
||||||
|
viewModelBase:ViewModelLocator.AutoWireViewModel="true"
|
||||||
Title="Catalog">
|
Title="Catalog">
|
||||||
<ContentPage.Resources>
|
<ContentPage.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
|
@ -8,17 +8,15 @@ namespace eShopOnContainers.Core.Views
|
|||||||
{
|
{
|
||||||
public partial class CatalogView : ContentPage, IMenuContainerPage
|
public partial class CatalogView : ContentPage, IMenuContainerPage
|
||||||
{
|
{
|
||||||
private FiltersView _filterView;
|
private FiltersView _filterView = new FiltersView();
|
||||||
|
|
||||||
public CatalogView()
|
public CatalogView()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
_filterView = new FiltersView();
|
|
||||||
|
|
||||||
SlideMenu = _filterView;
|
SlideMenu = _filterView;
|
||||||
|
|
||||||
MessagingCenter.Subscribe<CatalogViewModel>(this, MessengerKeys.Filter, (sender) =>
|
MessagingCenter.Subscribe<CatalogViewModel>(this, MessageKeys.Filter, (sender) =>
|
||||||
{
|
{
|
||||||
Filter();
|
Filter();
|
||||||
});
|
});
|
||||||
@ -42,7 +40,6 @@ namespace eShopOnContainers.Core.Views
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override void OnBindingContextChanged()
|
protected override void OnBindingContextChanged()
|
||||||
{
|
{
|
||||||
base.OnBindingContextChanged();
|
base.OnBindingContextChanged();
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
x:Class="eShopOnContainers.Core.Views.CheckoutView"
|
x:Class="eShopOnContainers.Core.Views.CheckoutView"
|
||||||
|
xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core"
|
||||||
xmlns:templates="clr-namespace:eShopOnContainers.Core.Views.Templates;assembly=eShopOnContainers.Core"
|
xmlns:templates="clr-namespace:eShopOnContainers.Core.Views.Templates;assembly=eShopOnContainers.Core"
|
||||||
|
viewModelBase:ViewModelLocator.AutoWireViewModel="true"
|
||||||
Title="Checkout">
|
Title="Checkout">
|
||||||
<ContentPage.Resources>
|
<ContentPage.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
@ -82,8 +84,7 @@
|
|||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<!-- ORDER INFO -->
|
<!-- ORDER INFO -->
|
||||||
<Grid
|
<Grid>
|
||||||
x:Name="OrderInfo">
|
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition />
|
<ColumnDefinition />
|
||||||
<ColumnDefinition />
|
<ColumnDefinition />
|
||||||
@ -139,8 +140,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
<!-- SHIPPING ADDRESS -->
|
<!-- SHIPPING ADDRESS -->
|
||||||
<Grid
|
<Grid
|
||||||
x:Name="ShippingAddress"
|
Grid.Row="1"
|
||||||
Grid.Row="1"
|
|
||||||
Margin="12">
|
Margin="12">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
@ -167,9 +167,7 @@
|
|||||||
</StackLayout>
|
</StackLayout>
|
||||||
</Grid>
|
</Grid>
|
||||||
<!-- ORDER ITEMS -->
|
<!-- ORDER ITEMS -->
|
||||||
<Grid
|
<Grid Grid.Row="2">
|
||||||
x:Name="OrderItems"
|
|
||||||
Grid.Row="2">
|
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
|
@ -2,9 +2,11 @@
|
|||||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
x:Class="eShopOnContainers.Core.Views.LoginView"
|
x:Class="eShopOnContainers.Core.Views.LoginView"
|
||||||
|
xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core"
|
||||||
xmlns:animations="clr-namespace:eShopOnContainers.Core.Animations;assembly=eShopOnContainers.Core"
|
xmlns:animations="clr-namespace:eShopOnContainers.Core.Animations;assembly=eShopOnContainers.Core"
|
||||||
xmlns:triggers="clr-namespace:eShopOnContainers.Core.Triggers;assembly=eShopOnContainers.Core"
|
xmlns:triggers="clr-namespace:eShopOnContainers.Core.Triggers;assembly=eShopOnContainers.Core"
|
||||||
xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core">
|
xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core"
|
||||||
|
viewModelBase:ViewModelLocator.AutoWireViewModel="true">
|
||||||
<ContentPage.Title>
|
<ContentPage.Title>
|
||||||
<OnPlatform
|
<OnPlatform
|
||||||
x:TypeArguments="x:String"
|
x:TypeArguments="x:String"
|
||||||
@ -175,30 +177,60 @@
|
|||||||
Margin="24">
|
Margin="24">
|
||||||
<Label
|
<Label
|
||||||
Text="User name or email"
|
Text="User name or email"
|
||||||
Style="{StaticResource HeaderLabelStyle}"/>
|
Style="{StaticResource HeaderLabelStyle}" />
|
||||||
<Entry
|
<Entry Text="{Binding UserName.Value, Mode=TwoWay}">
|
||||||
Text="{Binding UserName.Value, Mode=TwoWay}">
|
<Entry.Style>
|
||||||
<Entry.Style>
|
|
||||||
<OnPlatform x:TypeArguments="Style"
|
<OnPlatform x:TypeArguments="Style"
|
||||||
iOS="{StaticResource EntryStyle}"
|
iOS="{StaticResource EntryStyle}"
|
||||||
Android="{StaticResource EntryStyle}"
|
Android="{StaticResource EntryStyle}"
|
||||||
WinPhone="{StaticResource UwpEntryStyle}"/>
|
WinPhone="{StaticResource UwpEntryStyle}"/>
|
||||||
</Entry.Style>
|
</Entry.Style>
|
||||||
|
<Entry.Behaviors>
|
||||||
|
<behaviors:EventToCommandBehavior
|
||||||
|
EventName="TextChanged"
|
||||||
|
Command="{Binding ValidateUserNameCommand}" />
|
||||||
|
</Entry.Behaviors>
|
||||||
|
<Entry.Triggers>
|
||||||
|
<DataTrigger
|
||||||
|
TargetType="Entry"
|
||||||
|
Binding="{Binding UserName.IsValid}"
|
||||||
|
Value="False">
|
||||||
|
<Setter Property="behaviors:LineColorBehavior.LineColor" Value="{StaticResource ErrorColor}" />
|
||||||
|
</DataTrigger>
|
||||||
|
</Entry.Triggers>
|
||||||
</Entry>
|
</Entry>
|
||||||
|
<Label
|
||||||
|
Text="{Binding UserName.Errors, Converter={StaticResource FirstValidationErrorConverter}"
|
||||||
|
Style="{StaticResource ValidationErrorLabelStyle}" />
|
||||||
<Label
|
<Label
|
||||||
Text="Password"
|
Text="Password"
|
||||||
Style="{StaticResource HeaderLabelStyle}"/>
|
Style="{StaticResource HeaderLabelStyle}"/>
|
||||||
<Entry
|
<Entry
|
||||||
IsPassword="True"
|
IsPassword="True"
|
||||||
Text="{Binding Password.Value, Mode=TwoWay}"
|
Text="{Binding Password.Value, Mode=TwoWay}">
|
||||||
Style="{StaticResource EntryStyle}">
|
|
||||||
<Entry.Style>
|
<Entry.Style>
|
||||||
<OnPlatform x:TypeArguments="Style"
|
<OnPlatform x:TypeArguments="Style"
|
||||||
iOS="{StaticResource EntryStyle}"
|
iOS="{StaticResource EntryStyle}"
|
||||||
Android="{StaticResource EntryStyle}"
|
Android="{StaticResource EntryStyle}"
|
||||||
WinPhone="{StaticResource UwpEntryStyle}"/>
|
WinPhone="{StaticResource UwpEntryStyle}"/>
|
||||||
</Entry.Style>
|
</Entry.Style>
|
||||||
|
<Entry.Behaviors>
|
||||||
|
<behaviors:EventToCommandBehavior
|
||||||
|
EventName="TextChanged"
|
||||||
|
Command="{Binding ValidatePasswordCommand}" />
|
||||||
|
</Entry.Behaviors>
|
||||||
|
<Entry.Triggers>
|
||||||
|
<DataTrigger
|
||||||
|
TargetType="Entry"
|
||||||
|
Binding="{Binding Password.IsValid}"
|
||||||
|
Value="False">
|
||||||
|
<Setter Property="behaviors:LineColorBehavior.LineColor" Value="{StaticResource ErrorColor}" />
|
||||||
|
</DataTrigger>
|
||||||
|
</Entry.Triggers>
|
||||||
</Entry>
|
</Entry>
|
||||||
|
<Label
|
||||||
|
Text="{Binding Password.Errors, Converter={StaticResource FirstValidationErrorConverter}"
|
||||||
|
Style="{StaticResource ValidationErrorLabelStyle}" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<!-- LOGIN BUTTON -->
|
<!-- LOGIN BUTTON -->
|
||||||
<Grid
|
<Grid
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using eShopOnContainers.Core.Helpers;
|
using eShopOnContainers.Core.ViewModels;
|
||||||
using eShopOnContainers.Core.ViewModels;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -22,14 +21,16 @@ namespace eShopOnContainers.Core.Views
|
|||||||
this.Content = null;
|
this.Content = null;
|
||||||
this.Content = content;
|
this.Content = content;
|
||||||
|
|
||||||
_animate = true;
|
var vm = BindingContext as LoginViewModel;
|
||||||
await AnimateIn();
|
if (vm != null)
|
||||||
|
|
||||||
var vm = BindingContext as LoginViewModel;
|
|
||||||
|
|
||||||
if(vm != null)
|
|
||||||
{
|
{
|
||||||
vm.InvalidateMock();
|
vm.InvalidateMock();
|
||||||
|
|
||||||
|
if (!vm.IsMock)
|
||||||
|
{
|
||||||
|
_animate = true;
|
||||||
|
await AnimateIn();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,14 +55,13 @@ namespace eShopOnContainers.Core.Views
|
|||||||
{
|
{
|
||||||
while (_animate)
|
while (_animate)
|
||||||
{
|
{
|
||||||
await uiElement.ScaleTo(1.05, duration, Easing.SinInOut);
|
await uiElement.ScaleTo(1.05, duration, Easing.SinInOut);
|
||||||
|
await Task.WhenAll(
|
||||||
await Task.WhenAll(
|
uiElement.FadeTo(1, duration, Easing.SinInOut),
|
||||||
uiElement.FadeTo(1, duration, Easing.SinInOut),
|
uiElement.LayoutTo(new Rectangle(new Point(0, 0), new Size(uiElement.Width, uiElement.Height))),
|
||||||
uiElement.LayoutTo(new Rectangle(new Point(0, 0), new Size(uiElement.Width, uiElement.Height))),
|
uiElement.FadeTo(.9, duration, Easing.SinInOut),
|
||||||
uiElement.FadeTo(.9, duration, Easing.SinInOut),
|
uiElement.ScaleTo(1.15, duration, Easing.SinInOut)
|
||||||
uiElement.ScaleTo(1.15, duration, Easing.SinInOut)
|
);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
|
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
x:Class="eShopOnContainers.Core.Views.MainView"
|
x:Class="eShopOnContainers.Core.Views.MainView"
|
||||||
xmlns:views="clr-namespace:eShopOnContainers.Core.Views;assembly=eShopOnContainers.Core"
|
xmlns:views="clr-namespace:eShopOnContainers.Core.Views;assembly=eShopOnContainers.Core"
|
||||||
|
xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core"
|
||||||
xmlns:controls="clr-namespace:eShopOnContainers.Core.Controls;assembly=eShopOnContainers.Core"
|
xmlns:controls="clr-namespace:eShopOnContainers.Core.Controls;assembly=eShopOnContainers.Core"
|
||||||
BarBackgroundColor="{StaticResource DarkGreenColor}"
|
BarBackgroundColor="{StaticResource DarkGreenColor}"
|
||||||
BackgroundColor="{StaticResource BackgroundColor}"
|
BackgroundColor="{StaticResource BackgroundColor}"
|
||||||
BarTextColor="{StaticResource WhiteColor}">
|
BarTextColor="{StaticResource WhiteColor}"
|
||||||
|
viewModelBase:ViewModelLocator.AutoWireViewModel="true">
|
||||||
<TabbedPage.Title>
|
<TabbedPage.Title>
|
||||||
<OnPlatform
|
<OnPlatform
|
||||||
x:TypeArguments="x:String"
|
x:TypeArguments="x:String"
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
using eShopOnContainers.Core.ViewModels;
|
using eShopOnContainers.Core.ViewModels;
|
||||||
using eShopOnContainers.Core.ViewModels.Base;
|
using eShopOnContainers.Core.ViewModels.Base;
|
||||||
using eShopOnContainers.ViewModels.Base;
|
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
namespace eShopOnContainers.Core.Views
|
namespace eShopOnContainers.Core.Views
|
||||||
@ -16,7 +15,7 @@ namespace eShopOnContainers.Core.Views
|
|||||||
{
|
{
|
||||||
base.OnAppearing();
|
base.OnAppearing();
|
||||||
|
|
||||||
MessagingCenter.Subscribe<MainViewModel, int>(this, MessengerKeys.ChangeTab, (sender, arg) =>
|
MessagingCenter.Subscribe<MainViewModel, int>(this, MessageKeys.ChangeTab, (sender, arg) =>
|
||||||
{
|
{
|
||||||
switch(arg)
|
switch(arg)
|
||||||
{
|
{
|
||||||
@ -32,17 +31,9 @@ namespace eShopOnContainers.Core.Views
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var homeViewModel = ViewModelLocator.Instance.Resolve<CatalogViewModel>();
|
await ((CatalogViewModel)HomeView.BindingContext).InitializeAsync(null);
|
||||||
await homeViewModel.InitializeAsync(null);
|
await ((BasketViewModel)BasketView.BindingContext).InitializeAsync(null);
|
||||||
HomeView.BindingContext = homeViewModel;
|
await ((ProfileViewModel)ProfileView.BindingContext).InitializeAsync(null);
|
||||||
|
|
||||||
var basketViewModel = ViewModelLocator.Instance.Resolve<BasketViewModel>();
|
|
||||||
await basketViewModel.InitializeAsync(null);
|
|
||||||
BasketView.BindingContext = basketViewModel;
|
|
||||||
|
|
||||||
var profileViewModel = ViewModelLocator.Instance.Resolve<ProfileViewModel>();
|
|
||||||
await profileViewModel.InitializeAsync(null);
|
|
||||||
ProfileView.BindingContext = profileViewModel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async void OnCurrentPageChanged()
|
protected override async void OnCurrentPageChanged()
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
x:Class="eShopOnContainers.Core.Views.OrderDetailView"
|
x:Class="eShopOnContainers.Core.Views.OrderDetailView"
|
||||||
|
xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core"
|
||||||
xmlns:templates="clr-namespace:eShopOnContainers.Core.Views.Templates;assembly=eShopOnContainers.Core"
|
xmlns:templates="clr-namespace:eShopOnContainers.Core.Views.Templates;assembly=eShopOnContainers.Core"
|
||||||
xmlns:animations="clr-namespace:eShopOnContainers.Core.Animations;assembly=eShopOnContainers.Core"
|
xmlns:animations="clr-namespace:eShopOnContainers.Core.Animations;assembly=eShopOnContainers.Core"
|
||||||
xmlns:triggers="clr-namespace:eShopOnContainers.Core.Triggers;assembly=eShopOnContainers.Core"
|
xmlns:triggers="clr-namespace:eShopOnContainers.Core.Triggers;assembly=eShopOnContainers.Core"
|
||||||
|
viewModelBase:ViewModelLocator.AutoWireViewModel="true"
|
||||||
Title="{Binding Order.OrderNumber}">
|
Title="{Binding Order.OrderNumber}">
|
||||||
<ContentPage.Resources>
|
<ContentPage.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
x:Class="eShopOnContainers.Core.Views.ProfileView"
|
x:Class="eShopOnContainers.Core.Views.ProfileView"
|
||||||
xmlns:views="clr-namespace:eShopOnContainers.Core.Views;assembly=eShopOnContainers.Core"
|
xmlns:views="clr-namespace:eShopOnContainers.Core.Views;assembly=eShopOnContainers.Core"
|
||||||
|
xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core"
|
||||||
xmlns:templates="clr-namespace:eShopOnContainers.Core.Views.Templates;assembly=eShopOnContainers.Core"
|
xmlns:templates="clr-namespace:eShopOnContainers.Core.Views.Templates;assembly=eShopOnContainers.Core"
|
||||||
xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core"
|
xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core"
|
||||||
|
viewModelBase:ViewModelLocator.AutoWireViewModel="true"
|
||||||
Title="My profile">
|
Title="My profile">
|
||||||
<ContentPage.Resources>
|
<ContentPage.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
x:Class="eShopOnContainers.Core.Views.SettingsView"
|
x:Class="eShopOnContainers.Core.Views.SettingsView"
|
||||||
|
xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core"
|
||||||
xmlns:controls="clr-namespace:eShopOnContainers.Core.Controls;assembly=eShopOnContainers.Core"
|
xmlns:controls="clr-namespace:eShopOnContainers.Core.Controls;assembly=eShopOnContainers.Core"
|
||||||
xmlns:animations="clr-namespace:eShopOnContainers.Core.Animations;assembly=eShopOnContainers.Core"
|
xmlns:animations="clr-namespace:eShopOnContainers.Core.Animations;assembly=eShopOnContainers.Core"
|
||||||
xmlns:triggers="clr-namespace:eShopOnContainers.Core.Triggers;assembly=eShopOnContainers.Core"
|
xmlns:triggers="clr-namespace:eShopOnContainers.Core.Triggers;assembly=eShopOnContainers.Core"
|
||||||
xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core"
|
xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core"
|
||||||
|
viewModelBase:ViewModelLocator.AutoWireViewModel="true"
|
||||||
Title="Settings">
|
Title="Settings">
|
||||||
<ContentPage.Resources>
|
<ContentPage.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
|
@ -112,7 +112,7 @@
|
|||||||
<Compile Include="Validations\IValidity.cs" />
|
<Compile Include="Validations\IValidity.cs" />
|
||||||
<Compile Include="Validations\ValidatableObject.cs" />
|
<Compile Include="Validations\ValidatableObject.cs" />
|
||||||
<Compile Include="ViewModels\Base\ExtendedBindableObject.cs" />
|
<Compile Include="ViewModels\Base\ExtendedBindableObject.cs" />
|
||||||
<Compile Include="ViewModels\Base\MessengerKeys.cs" />
|
<Compile Include="ViewModels\Base\MessageKeys.cs" />
|
||||||
<Compile Include="ViewModels\Base\ViewModelBase.cs" />
|
<Compile Include="ViewModels\Base\ViewModelBase.cs" />
|
||||||
<Compile Include="ViewModels\Base\ViewModelLocator.cs" />
|
<Compile Include="ViewModels\Base\ViewModelLocator.cs" />
|
||||||
<Compile Include="ViewModels\BasketViewModel.cs" />
|
<Compile Include="ViewModels\BasketViewModel.cs" />
|
||||||
@ -166,6 +166,9 @@
|
|||||||
<DependentUpon>ProductTemplate.xaml</DependentUpon>
|
<DependentUpon>ProductTemplate.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Converters\WebNavigatingEventArgsConverter.cs" />
|
<Compile Include="Converters\WebNavigatingEventArgsConverter.cs" />
|
||||||
|
<Compile Include="Converters\FirstValidationErrorConverter.cs" />
|
||||||
|
<Compile Include="Effects\EntryLineColorEffect.cs" />
|
||||||
|
<Compile Include="Behaviors\LineColorBehavior.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="app.config" />
|
<None Include="app.config" />
|
||||||
|
@ -3,7 +3,7 @@ using eShopOnContainers.Droid.Effects;
|
|||||||
using Xamarin.Forms.Platform.Android;
|
using Xamarin.Forms.Platform.Android;
|
||||||
using System;
|
using System;
|
||||||
using Android.Widget;
|
using Android.Widget;
|
||||||
using eShopOnContainers.Core.Effects;
|
using eShopOnContainers.Core.Behaviors;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ namespace eShopOnContainers.Droid.Effects
|
|||||||
|
|
||||||
protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)
|
protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)
|
||||||
{
|
{
|
||||||
if (args.PropertyName == LineColorEffect.LineColorProperty.PropertyName)
|
if (args.PropertyName == LineColorBehavior.LineColorProperty.PropertyName)
|
||||||
{
|
{
|
||||||
UpdateLineColor();
|
UpdateLineColor();
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ namespace eShopOnContainers.Droid.Effects
|
|||||||
{
|
{
|
||||||
if (control != null)
|
if (control != null)
|
||||||
{
|
{
|
||||||
control.Background.SetColorFilter(LineColorEffect.GetLineColor(Element).ToAndroid(), Android.Graphics.PorterDuff.Mode.SrcAtop);
|
control.Background.SetColorFilter(LineColorBehavior.GetLineColor(Element).ToAndroid(), Android.Graphics.PorterDuff.Mode.SrcAtop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -8,7 +8,7 @@ using Xamarin.Forms;
|
|||||||
using Xamarin.Forms.Platform.UWP;
|
using Xamarin.Forms.Platform.UWP;
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
using eShopOnContainers.Windows.Effects;
|
using eShopOnContainers.Windows.Effects;
|
||||||
using eShopOnContainers.Core.Effects;
|
using eShopOnContainers.Core.Behaviors;
|
||||||
|
|
||||||
[assembly: ResolutionGroupName("eShopOnContainers")]
|
[assembly: ResolutionGroupName("eShopOnContainers")]
|
||||||
[assembly: ExportEffect(typeof(EntryLineColorEffect), "EntryLineColorEffect")]
|
[assembly: ExportEffect(typeof(EntryLineColorEffect), "EntryLineColorEffect")]
|
||||||
@ -38,7 +38,7 @@ namespace eShopOnContainers.Windows.Effects
|
|||||||
|
|
||||||
protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)
|
protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)
|
||||||
{
|
{
|
||||||
if (args.PropertyName == LineColorEffect.LineColorProperty.PropertyName)
|
if (args.PropertyName == LineColorBehavior.LineColorProperty.PropertyName)
|
||||||
{
|
{
|
||||||
UpdateLineColor();
|
UpdateLineColor();
|
||||||
}
|
}
|
||||||
@ -49,7 +49,7 @@ namespace eShopOnContainers.Windows.Effects
|
|||||||
if (control != null)
|
if (control != null)
|
||||||
{
|
{
|
||||||
control.BorderThickness = new Xaml.Thickness(0, 0, 0, 1);
|
control.BorderThickness = new Xaml.Thickness(0, 0, 0, 1);
|
||||||
var lineColor = XamarinFormColorToWindowsColor(LineColorEffect.GetLineColor(Element));
|
var lineColor = XamarinFormColorToWindowsColor(LineColorBehavior.GetLineColor(Element));
|
||||||
control.BorderBrush = new Media.SolidColorBrush(lineColor);
|
control.BorderBrush = new Media.SolidColorBrush(lineColor);
|
||||||
|
|
||||||
var style = Xaml.Application.Current.Resources["FormTextBoxStyle"] as Xaml.Style;
|
var style = Xaml.Application.Current.Resources["FormTextBoxStyle"] as Xaml.Style;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
using CoreAnimation;
|
using CoreAnimation;
|
||||||
using CoreGraphics;
|
using CoreGraphics;
|
||||||
using eShopOnContainers.Core.Effects;
|
using eShopOnContainers.Core.Behaviors;
|
||||||
using eShopOnContainers.iOS.Effects;
|
using eShopOnContainers.iOS.Effects;
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
@ -39,7 +39,7 @@ namespace eShopOnContainers.iOS.Effects
|
|||||||
{
|
{
|
||||||
base.OnElementPropertyChanged(args);
|
base.OnElementPropertyChanged(args);
|
||||||
|
|
||||||
if (args.PropertyName == LineColorEffect.LineColorProperty.PropertyName ||
|
if (args.PropertyName == LineColorBehavior.LineColorProperty.PropertyName ||
|
||||||
args.PropertyName == "Height")
|
args.PropertyName == "Height")
|
||||||
{
|
{
|
||||||
Initialize();
|
Initialize();
|
||||||
@ -71,7 +71,7 @@ namespace eShopOnContainers.iOS.Effects
|
|||||||
}
|
}
|
||||||
|
|
||||||
lineLayer.Frame = new CGRect(0f, Control.Frame.Height - 1f, Control.Bounds.Width, 1f);
|
lineLayer.Frame = new CGRect(0f, Control.Frame.Height - 1f, Control.Bounds.Width, 1f);
|
||||||
lineLayer.BorderColor = LineColorEffect.GetLineColor(Element).ToCGColor();
|
lineLayer.BorderColor = LineColorBehavior.GetLineColor(Element).ToCGColor();
|
||||||
control.TintColor = control.TextColor;
|
control.TintColor = control.TextColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using global::Catalog.API.IntegrationEvents;
|
using global::Catalog.API.IntegrationEvents;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
public class Startup
|
public class Startup
|
||||||
{
|
{
|
||||||
|
@ -1,31 +1,30 @@
|
|||||||
using IdentityServer4.Models;
|
using IdentityServer4.Models;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using IdentityServer4;
|
||||||
|
|
||||||
namespace Identity.API.Configuration
|
namespace Identity.API.Configuration
|
||||||
{
|
{
|
||||||
public class Config
|
public class Config
|
||||||
{
|
{
|
||||||
// scopes define the resources in your system
|
// ApiResources define the apis in your system
|
||||||
public static IEnumerable<Scope> GetScopes()
|
public static IEnumerable<ApiResource> GetApis()
|
||||||
{
|
{
|
||||||
return new List<Scope>
|
return new List<ApiResource>
|
||||||
{
|
{
|
||||||
//Authentication OpenId uses this scopes;
|
new ApiResource("orders", "Orders Service"),
|
||||||
StandardScopes.OpenId,
|
new ApiResource("basket", "Basket Service")
|
||||||
StandardScopes.Profile,
|
};
|
||||||
|
}
|
||||||
|
|
||||||
//Each api we want to securice;
|
// Identity resources are data like user ID, name, or email address of a user
|
||||||
new Scope
|
// see: http://docs.identityserver.io/en/release/configuration/resources.html
|
||||||
{
|
public static IEnumerable<IdentityResource> GetResources()
|
||||||
Name = "orders",
|
{
|
||||||
Description = "Orders Service"
|
return new List<IdentityResource>
|
||||||
},
|
{
|
||||||
new Scope
|
new IdentityResources.OpenId(),
|
||||||
{
|
new IdentityResources.Profile()
|
||||||
Name = "basket",
|
|
||||||
Description = "Basket Service"
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,8 +46,8 @@ namespace Identity.API.Configuration
|
|||||||
AllowedCorsOrigins = { $"{clientsUrl["Spa"]}" },
|
AllowedCorsOrigins = { $"{clientsUrl["Spa"]}" },
|
||||||
AllowedScopes =
|
AllowedScopes =
|
||||||
{
|
{
|
||||||
StandardScopes.OpenId.Name,
|
IdentityServerConstants.StandardScopes.OpenId,
|
||||||
StandardScopes.Profile.Name,
|
IdentityServerConstants.StandardScopes.Profile,
|
||||||
"orders",
|
"orders",
|
||||||
"basket"
|
"basket"
|
||||||
}
|
}
|
||||||
@ -65,8 +64,8 @@ namespace Identity.API.Configuration
|
|||||||
AllowedCorsOrigins = { "http://eshopxamarin" },
|
AllowedCorsOrigins = { "http://eshopxamarin" },
|
||||||
AllowedScopes =
|
AllowedScopes =
|
||||||
{
|
{
|
||||||
StandardScopes.OpenId.Name,
|
IdentityServerConstants.StandardScopes.OpenId,
|
||||||
StandardScopes.Profile.Name,
|
IdentityServerConstants.StandardScopes.Profile,
|
||||||
"orders",
|
"orders",
|
||||||
"basket"
|
"basket"
|
||||||
}
|
}
|
||||||
@ -82,6 +81,7 @@ namespace Identity.API.Configuration
|
|||||||
ClientUri = $"{clientsUrl["Mvc"]}", // public uri of the client
|
ClientUri = $"{clientsUrl["Mvc"]}", // public uri of the client
|
||||||
AllowedGrantTypes = GrantTypes.Hybrid,
|
AllowedGrantTypes = GrantTypes.Hybrid,
|
||||||
RequireConsent = false,
|
RequireConsent = false,
|
||||||
|
AllowOfflineAccess = true,
|
||||||
RedirectUris = new List<string>
|
RedirectUris = new List<string>
|
||||||
{
|
{
|
||||||
$"{clientsUrl["Mvc"]}/signin-oidc",
|
$"{clientsUrl["Mvc"]}/signin-oidc",
|
||||||
@ -96,9 +96,9 @@ namespace Identity.API.Configuration
|
|||||||
},
|
},
|
||||||
AllowedScopes = new List<string>
|
AllowedScopes = new List<string>
|
||||||
{
|
{
|
||||||
StandardScopes.OpenId.Name,
|
IdentityServerConstants.StandardScopes.OpenId,
|
||||||
StandardScopes.Profile.Name,
|
IdentityServerConstants.StandardScopes.Profile,
|
||||||
StandardScopes.OfflineAccess.Name,
|
IdentityServerConstants.StandardScopes.OfflineAccess,
|
||||||
"orders",
|
"orders",
|
||||||
"basket",
|
"basket",
|
||||||
},
|
},
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
using IdentityModel;
|
using IdentityModel;
|
||||||
using IdentityServer4.Quickstart.UI.Models;
|
using IdentityServer4.Quickstart.UI.Models;
|
||||||
using IdentityServer4.Services;
|
using IdentityServer4.Services;
|
||||||
using IdentityServer4.Services.InMemory;
|
|
||||||
using Microsoft.AspNetCore.Http.Authentication;
|
using Microsoft.AspNetCore.Http.Authentication;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System;
|
using System;
|
||||||
|
@ -22,7 +22,7 @@ namespace IdentityServer4.Quickstart.UI.Controllers
|
|||||||
{
|
{
|
||||||
private readonly ILogger<ConsentController> _logger;
|
private readonly ILogger<ConsentController> _logger;
|
||||||
private readonly IClientStore _clientStore;
|
private readonly IClientStore _clientStore;
|
||||||
private readonly IScopeStore _scopeStore;
|
private readonly IResourceStore _resourceStore;
|
||||||
private readonly IIdentityServerInteractionService _interaction;
|
private readonly IIdentityServerInteractionService _interaction;
|
||||||
|
|
||||||
|
|
||||||
@ -30,12 +30,12 @@ namespace IdentityServer4.Quickstart.UI.Controllers
|
|||||||
ILogger<ConsentController> logger,
|
ILogger<ConsentController> logger,
|
||||||
IIdentityServerInteractionService interaction,
|
IIdentityServerInteractionService interaction,
|
||||||
IClientStore clientStore,
|
IClientStore clientStore,
|
||||||
IScopeStore scopeStore)
|
IResourceStore resourceStore)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_interaction = interaction;
|
_interaction = interaction;
|
||||||
_clientStore = clientStore;
|
_clientStore = clientStore;
|
||||||
_scopeStore = scopeStore;
|
_resourceStore = resourceStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -120,10 +120,10 @@ namespace IdentityServer4.Quickstart.UI.Controllers
|
|||||||
var client = await _clientStore.FindEnabledClientByIdAsync(request.ClientId);
|
var client = await _clientStore.FindEnabledClientByIdAsync(request.ClientId);
|
||||||
if (client != null)
|
if (client != null)
|
||||||
{
|
{
|
||||||
var scopes = await _scopeStore.FindEnabledScopesAsync(request.ScopesRequested);
|
var resources = await _resourceStore.FindEnabledResourcesByScopeAsync(request.ScopesRequested);
|
||||||
if (scopes != null && scopes.Any())
|
if (resources != null && (resources.IdentityResources.Any() || resources.ApiResources.Any()))
|
||||||
{
|
{
|
||||||
return new ConsentViewModel(model, returnUrl, request, client, scopes);
|
return new ConsentViewModel(model, returnUrl, request, client, resources);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -41,8 +41,8 @@
|
|||||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="1.1.0-msbuild3-final">
|
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="1.1.0-msbuild3-final">
|
||||||
<PrivateAssets>All</PrivateAssets>
|
<PrivateAssets>All</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="1.0.0-rc3" />
|
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="1.0.0" />
|
||||||
<PackageReference Include="IdentityServer4.EntityFramework" Version="1.0.0-rc3" />
|
<PackageReference Include="IdentityServer4.EntityFramework" Version="1.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish">
|
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish">
|
||||||
|
@ -10,7 +10,7 @@ namespace Identity.API.Models.AccountViewModels
|
|||||||
{
|
{
|
||||||
public class ConsentViewModel : ConsentInputModel
|
public class ConsentViewModel : ConsentInputModel
|
||||||
{
|
{
|
||||||
public ConsentViewModel(ConsentInputModel model, string returnUrl, AuthorizationRequest request, Client client, IEnumerable<Scope> scopes)
|
public ConsentViewModel(ConsentInputModel model, string returnUrl, AuthorizationRequest request, Client client, Resources resources)
|
||||||
{
|
{
|
||||||
RememberConsent = model?.RememberConsent ?? true;
|
RememberConsent = model?.RememberConsent ?? true;
|
||||||
ScopesConsented = model?.ScopesConsented ?? Enumerable.Empty<string>();
|
ScopesConsented = model?.ScopesConsented ?? Enumerable.Empty<string>();
|
||||||
@ -22,8 +22,8 @@ namespace Identity.API.Models.AccountViewModels
|
|||||||
ClientLogoUrl = client.LogoUri;
|
ClientLogoUrl = client.LogoUri;
|
||||||
AllowRememberConsent = client.AllowRememberConsent;
|
AllowRememberConsent = client.AllowRememberConsent;
|
||||||
|
|
||||||
IdentityScopes = scopes.Where(x => x.Type == ScopeType.Identity).Select(x => new ScopeViewModel(x, ScopesConsented.Contains(x.Name) || model == null)).ToArray();
|
IdentityScopes = resources.IdentityResources.Select(x => new ScopeViewModel(x, ScopesConsented.Contains(x.Name) || model == null)).ToArray();
|
||||||
ResourceScopes = scopes.Where(x => x.Type == ScopeType.Resource).Select(x => new ScopeViewModel(x, ScopesConsented.Contains(x.Name) || model == null)).ToArray();
|
ResourceScopes = resources.ApiResources.SelectMany(x => x.Scopes).Select(x => new ScopeViewModel(x, ScopesConsented.Contains(x.Name) || model == null)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ClientName { get; set; }
|
public string ClientName { get; set; }
|
||||||
@ -47,6 +47,16 @@ namespace Identity.API.Models.AccountViewModels
|
|||||||
Checked = check || scope.Required;
|
Checked = check || scope.Required;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ScopeViewModel(IdentityResource identity, bool check)
|
||||||
|
{
|
||||||
|
Name = identity.Name;
|
||||||
|
DisplayName = identity.DisplayName;
|
||||||
|
Description = identity.Description;
|
||||||
|
Emphasize = identity.Emphasize;
|
||||||
|
Required = identity.Required;
|
||||||
|
Checked = check || identity.Required;
|
||||||
|
}
|
||||||
|
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string DisplayName { get; set; }
|
public string DisplayName { get; set; }
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
|
@ -78,7 +78,8 @@ namespace eShopOnContainers.Identity
|
|||||||
// Adds IdentityServer
|
// Adds IdentityServer
|
||||||
services.AddIdentityServer(x => x.IssuerUri = "null")
|
services.AddIdentityServer(x => x.IssuerUri = "null")
|
||||||
.AddSigningCredential(Certificate.Get())
|
.AddSigningCredential(Certificate.Get())
|
||||||
.AddInMemoryScopes(Config.GetScopes())
|
.AddInMemoryApiResources(Config.GetApis())
|
||||||
|
.AddInMemoryIdentityResources(Config.GetResources())
|
||||||
.AddInMemoryClients(Config.GetClients(clientUrls))
|
.AddInMemoryClients(Config.GetClients(clientUrls))
|
||||||
.AddAspNetIdentity<ApplicationUser>()
|
.AddAspNetIdentity<ApplicationUser>()
|
||||||
.Services.AddTransient<IProfileService, ProfileService>();
|
.Services.AddTransient<IProfileService, ProfileService>();
|
||||||
|
@ -34,6 +34,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Autof
|
|||||||
.Select(i => new KeyedService("IAsyncNotificationHandler", i)))
|
.Select(i => new KeyedService("IAsyncNotificationHandler", i)))
|
||||||
.AsImplementedInterfaces();
|
.AsImplementedInterfaces();
|
||||||
|
|
||||||
|
|
||||||
builder
|
builder
|
||||||
.RegisterAssemblyTypes(typeof(CreateOrderCommandValidator).GetTypeInfo().Assembly)
|
.RegisterAssemblyTypes(typeof(CreateOrderCommandValidator).GetTypeInfo().Assembly)
|
||||||
.Where(t => t.IsClosedTypeOf(typeof(IValidator<>)))
|
.Where(t => t.IsClosedTypeOf(typeof(IValidator<>)))
|
||||||
|
@ -14,6 +14,7 @@ using Microsoft.IdentityModel.Tokens;
|
|||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using WebMVC.Services.Utilities;
|
||||||
using Microsoft.Extensions.HealthChecks;
|
using Microsoft.Extensions.HealthChecks;
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.HttpResilience;
|
using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.HttpResilience;
|
||||||
|
|
||||||
@ -48,7 +49,10 @@ namespace Microsoft.eShopOnContainers.WebMVC
|
|||||||
|
|
||||||
services.AddHealthChecks(checks =>
|
services.AddHealthChecks(checks =>
|
||||||
{
|
{
|
||||||
checks.AddValueTaskCheck("HTTP Endpoint", () => new ValueTask<IHealthCheckResult>(HealthCheckResult.Healthy("Ok")));
|
checks.AddUrlCheck(Configuration["CatalogUrl"]);
|
||||||
|
checks.AddUrlCheck(Configuration["OrderingUrl"]);
|
||||||
|
checks.AddUrlCheck(Configuration["BasketUrl"]);
|
||||||
|
checks.AddUrlCheck(Configuration["IdentityUrl"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add application services.
|
// Add application services.
|
||||||
@ -116,14 +120,9 @@ namespace Microsoft.eShopOnContainers.WebMVC
|
|||||||
SaveTokens = true,
|
SaveTokens = true,
|
||||||
GetClaimsFromUserInfoEndpoint = true,
|
GetClaimsFromUserInfoEndpoint = true,
|
||||||
RequireHttpsMetadata = false,
|
RequireHttpsMetadata = false,
|
||||||
|
Scope = { "openid", "profile", "orders", "basket" }
|
||||||
};
|
};
|
||||||
|
|
||||||
oidcOptions.Scope.Clear();
|
|
||||||
oidcOptions.Scope.Add("openid");
|
|
||||||
oidcOptions.Scope.Add("profile");
|
|
||||||
oidcOptions.Scope.Add("orders");
|
|
||||||
oidcOptions.Scope.Add("basket");
|
|
||||||
|
|
||||||
//Wait untill identity service is ready on compose.
|
//Wait untill identity service is ready on compose.
|
||||||
app.UseOpenIdConnectAuthentication(oidcOptions);
|
app.UseOpenIdConnectAuthentication(oidcOptions);
|
||||||
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
|
|
||||||
Let's create here the simplest monolithic MVC Web app with just the Home Page and ASP.NET Core MVC.
|
|
||||||
Please, don't say anything about "Containers" here.
|
|
||||||
|
|
||||||
From a "branding point of view" it should be named as "eShopWeb"
|
|
||||||
|
|
||||||
Cesar.
|
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user