Merge branch 'Dev' of https://github.com/dotnet/eShopOnContainers.git
This commit is contained in:
commit
158fd0ba4b
@ -18,6 +18,18 @@ dotnet restore $webPathToJson
|
|||||||
dotnet build $webPathToJson
|
dotnet build $webPathToJson
|
||||||
dotnet publish $webPathToJson -o $webPathToPub
|
dotnet publish $webPathToJson -o $webPathToPub
|
||||||
|
|
||||||
|
# *** WebSPA image ***
|
||||||
|
$webSPAPathToJson = $scriptPath + "\src\Web\WebSPA\eShopOnContainers.WebSPA\project.json"
|
||||||
|
Write-Host "webSPAPathToJson is $webSPAPathToJson" -ForegroundColor Yellow
|
||||||
|
$webSPAPathToPub = $scriptPath + "\pub\webSPA"
|
||||||
|
Write-Host "webSPAPathToPub is $webSPAPathToPub" -ForegroundColor Yellow
|
||||||
|
|
||||||
|
Write-Host "Restore Dependencies just in case as it is needed to run dotnet publish" -ForegroundColor Blue
|
||||||
|
dotnet restore $webSPAPathToJson
|
||||||
|
dotnet build $webSPAPathToJson
|
||||||
|
dotnet publish $webSPAPathToJson -o $webSPAPathToPub
|
||||||
|
|
||||||
|
|
||||||
#*** Catalog service image ***
|
#*** Catalog service image ***
|
||||||
$catalogPathToJson = $scriptPath + "\src\Services\Catalog\Catalog.API\project.json"
|
$catalogPathToJson = $scriptPath + "\src\Services\Catalog\Catalog.API\project.json"
|
||||||
Write-Host "catalogPathToJson is $catalogPathToJson" -ForegroundColor Yellow
|
Write-Host "catalogPathToJson is $catalogPathToJson" -ForegroundColor Yellow
|
||||||
@ -55,4 +67,4 @@ docker build -t eshop/web $webPathToPub
|
|||||||
docker build -t eshop/catalog.api $catalogPathToPub
|
docker build -t eshop/catalog.api $catalogPathToPub
|
||||||
docker build -t eshop/ordering.api $orderingPathToPub
|
docker build -t eshop/ordering.api $orderingPathToPub
|
||||||
docker build -t eshop/basket.api $basketPathToPub
|
docker build -t eshop/basket.api $basketPathToPub
|
||||||
|
docker build -t eshop/webspa $webSPAPathToPub
|
||||||
|
@ -16,6 +16,21 @@ services:
|
|||||||
- identity.data
|
- identity.data
|
||||||
- basket.api
|
- basket.api
|
||||||
|
|
||||||
|
webspa:
|
||||||
|
image: eshop/webspa
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
environment:
|
||||||
|
- CatalogUrl=http://catalog.api
|
||||||
|
- OrderingUrl=http://ordering.api
|
||||||
|
ports:
|
||||||
|
- "5104:80"
|
||||||
|
depends_on:
|
||||||
|
- catalog.api
|
||||||
|
- identity.data
|
||||||
|
- basket.api
|
||||||
|
|
||||||
catalog.api:
|
catalog.api:
|
||||||
image: eshop/catalog.api
|
image: eshop/catalog.api
|
||||||
environment:
|
environment:
|
||||||
@ -28,7 +43,7 @@ services:
|
|||||||
- catalog.data
|
- catalog.data
|
||||||
|
|
||||||
catalog.data:
|
catalog.data:
|
||||||
image: eshop/mssql-server-private-preview
|
image: microsoft/mssql-server-linux
|
||||||
environment:
|
environment:
|
||||||
- SA_PASSWORD=Pass@word
|
- SA_PASSWORD=Pass@word
|
||||||
- ACCEPT_EULA=Y
|
- ACCEPT_EULA=Y
|
||||||
@ -56,7 +71,7 @@ services:
|
|||||||
- "5432:1433"
|
- "5432:1433"
|
||||||
|
|
||||||
identity.data:
|
identity.data:
|
||||||
image: eshop/mssql-server-private-preview
|
image: microsoft/mssql-server-linux
|
||||||
environment:
|
environment:
|
||||||
- SA_PASSWORD=Pass@word
|
- SA_PASSWORD=Pass@word
|
||||||
- ACCEPT_EULA=Y
|
- ACCEPT_EULA=Y
|
||||||
|
@ -58,6 +58,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared Code", "Shared Code"
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Targets", "Targets", "{9CC7814B-72A6-465B-A61C-57B512DEE303}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Targets", "Targets", "{9CC7814B-72A6-465B-A61C-57B512DEE303}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "eShopOnContainers.WebSPA", "src\Web\WebSPA\eShopOnContainers.WebSPA\eShopOnContainers.WebSPA.xproj", "{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
|
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
|
||||||
@ -506,6 +508,54 @@ Global
|
|||||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Release|x86.ActiveCfg = Release|x86
|
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Release|x86.ActiveCfg = Release|x86
|
||||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Release|x86.Build.0 = Release|x86
|
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Release|x86.Build.0 = Release|x86
|
||||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Release|x86.Deploy.0 = Release|x86
|
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Release|x86.Deploy.0 = Release|x86
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.AppStore|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.AppStore|x64.Build.0 = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.AppStore|x86.Build.0 = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Release|iPhone.Build.0 = Release|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -533,5 +583,6 @@ Global
|
|||||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B} = {9CC7814B-72A6-465B-A61C-57B512DEE303}
|
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B} = {9CC7814B-72A6-465B-A61C-57B512DEE303}
|
||||||
{778289CA-31F7-4464-8C2A-612EE846F8A7} = {F61357CE-1CC2-410E-8776-B16EEBC98EB8}
|
{778289CA-31F7-4464-8C2A-612EE846F8A7} = {F61357CE-1CC2-410E-8776-B16EEBC98EB8}
|
||||||
{9CC7814B-72A6-465B-A61C-57B512DEE303} = {F61357CE-1CC2-410E-8776-B16EEBC98EB8}
|
{9CC7814B-72A6-465B-A61C-57B512DEE303} = {F61357CE-1CC2-410E-8776-B16EEBC98EB8}
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2} = {E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||||
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
|
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
|
||||||
<AndroidUseLatestPlatformSdk>true</AndroidUseLatestPlatformSdk>
|
<AndroidUseLatestPlatformSdk>true</AndroidUseLatestPlatformSdk>
|
||||||
<TargetFrameworkVersion>v7.0</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v6.0</TargetFrameworkVersion>
|
||||||
<AndroidSupportedAbis>armeabi,armeabi-v7a,x86</AndroidSupportedAbis>
|
<AndroidSupportedAbis>armeabi,armeabi-v7a,x86</AndroidSupportedAbis>
|
||||||
<AndroidStoreUncompressedFileExtensions />
|
<AndroidStoreUncompressedFileExtensions />
|
||||||
<MandroidI18n />
|
<MandroidI18n />
|
||||||
|
@ -307,6 +307,27 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AndroidResource Include="Resources\drawable-xxxhdpi\menu_cart.png" />
|
<AndroidResource Include="Resources\drawable-xxxhdpi\menu_cart.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\drawable-xxxhdpi\icon.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\drawable-hdpi\background.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\drawable-xhdpi\background.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\drawable-xxhdpi\background.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\drawable-xxxhdpi\background.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\drawable\fake_product_04.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\drawable\fake_product_05.png" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||||
<Import Project="..\..\packages\Xamarin.Android.Support.Vector.Drawable.23.3.0\build\Xamarin.Android.Support.Vector.Drawable.targets" Condition="Exists('..\..\packages\Xamarin.Android.Support.Vector.Drawable.23.3.0\build\Xamarin.Android.Support.Vector.Drawable.targets')" />
|
<Import Project="..\..\packages\Xamarin.Android.Support.Vector.Drawable.23.3.0\build\Xamarin.Android.Support.Vector.Drawable.targets" Condition="Exists('..\..\packages\Xamarin.Android.Support.Vector.Drawable.23.3.0\build\Xamarin.Android.Support.Vector.Drawable.targets')" />
|
||||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
223
src/Web/WebSPA/eShopOnContainers.WebSPA/.gitignore
vendored
Normal file
223
src/Web/WebSPA/eShopOnContainers.WebSPA/.gitignore
vendored
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
|
||||||
|
coverage/**/**
|
||||||
|
client/**/*.js
|
||||||
|
/doc
|
||||||
|
client/**/*.js.map
|
||||||
|
npm-debug.log*
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
|
||||||
|
# Visual Studio 2015 cache/options directory
|
||||||
|
.vs/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUNIT
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# DNX
|
||||||
|
project.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_i.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# JustCode is a .NET coding add-in
|
||||||
|
.JustCode
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
## TODO: Comment the next line if you want to checkin your
|
||||||
|
## web deploy settings but do note that will include unencrypted
|
||||||
|
## passwords
|
||||||
|
#*.pubxml
|
||||||
|
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/packages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/packages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/packages/repositories.config
|
||||||
|
|
||||||
|
# Windows Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Windows Store app package directory
|
||||||
|
AppPackages/
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
[Ss]tyle[Cc]op.*
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
node_modules/
|
||||||
|
bower_components/
|
||||||
|
**/wwwroot/tmp/
|
||||||
|
**/wwwroot/*.bundle.map
|
||||||
|
**/wwwroot/*.js
|
||||||
|
/wwwroot/dist/
|
||||||
|
|
||||||
|
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# LightSwitch generated files
|
||||||
|
GeneratedArtifacts/
|
||||||
|
_Pvt_Extensions/
|
||||||
|
ModelManifest.xml
|
237
src/Web/WebSPA/eShopOnContainers.WebSPA/.npmignore
Normal file
237
src/Web/WebSPA/eShopOnContainers.WebSPA/.npmignore
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
/Properties/launchSettings.json
|
||||||
|
|
||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
build/
|
||||||
|
bld/
|
||||||
|
bin/
|
||||||
|
Bin/
|
||||||
|
obj/
|
||||||
|
Obj/
|
||||||
|
|
||||||
|
# Visual Studio 2015 cache/options directory
|
||||||
|
.vs/
|
||||||
|
/wwwroot/dist/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUNIT
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# DNX
|
||||||
|
project.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_i.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# JustCode is a .NET coding add-in
|
||||||
|
.JustCode
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/packages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/packages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/packages/repositories.config
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Microsoft Azure ApplicationInsights config file
|
||||||
|
ApplicationInsights.config
|
||||||
|
|
||||||
|
# Windows Store app package directory
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
node_modules/
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
2
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/custom-typings.d.ts
vendored
Normal file
2
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/custom-typings.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Extra variables that live on Global that will be replaced by webpack DefinePlugin
|
||||||
|
// declare var process: any;
|
BIN
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/images/brand.png
Normal file
BIN
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/images/brand.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 713 KiB |
Binary file not shown.
After Width: | Height: | Size: 8.6 KiB |
23
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/main.ts
Normal file
23
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/main.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import './polyfills';
|
||||||
|
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
import { enableProdMode } from '@angular/core';
|
||||||
|
|
||||||
|
import { AppModule } from './modules/app.module';
|
||||||
|
|
||||||
|
if (process.env.ENV === 'Development') {
|
||||||
|
// Development
|
||||||
|
} else {
|
||||||
|
// Production
|
||||||
|
enableProdMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
platformBrowserDynamic().bootstrapModule(AppModule);
|
||||||
|
|
||||||
|
// Basic hot reloading support. Automatically reloads and restarts the Angular 2 app each time
|
||||||
|
// you modify source files. This will not preserve any application state other than the URL.
|
||||||
|
declare var module: any;
|
||||||
|
|
||||||
|
if (module.hot) {
|
||||||
|
module.hot.accept();
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
$primary-colour: #00A69C;
|
||||||
|
$primary-accent: #83D01B;
|
||||||
|
|
||||||
|
$white-colour: #FFFFFF;
|
||||||
|
$grey-colour: #E2E2E2;
|
||||||
|
$text-colour: #757575;
|
||||||
|
|
||||||
|
$grey-box-shadow: 10px 10px 20px #F2F2F2;
|
||||||
|
$grey-box-border: 1px solid #DDDDDD;
|
@ -0,0 +1,14 @@
|
|||||||
|
<!-- header component -->
|
||||||
|
<appc-header></appc-header>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<!-- component routing placeholder -->
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<!-- footer component -->
|
||||||
|
<appc-footer></appc-footer>
|
||||||
|
|
||||||
|
</div>
|
@ -0,0 +1,2 @@
|
|||||||
|
@import './_variables.scss';
|
||||||
|
|
@ -0,0 +1,37 @@
|
|||||||
|
import { Title } from '@angular/platform-browser';
|
||||||
|
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { TranslateService } from 'ng2-translate/ng2-translate';
|
||||||
|
|
||||||
|
import { DataService } from './shared/services/data.service';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* App Component
|
||||||
|
* Top Level Component
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'appc-app',
|
||||||
|
styleUrls: ['./app.component.scss'],
|
||||||
|
templateUrl: './app.component.html'
|
||||||
|
})
|
||||||
|
export class AppComponent implements OnInit {
|
||||||
|
|
||||||
|
|
||||||
|
constructor(private translate: TranslateService, private titleService: Title) {
|
||||||
|
// this language will be used as a fallback when a translation isn't found in the current language
|
||||||
|
translate.setDefaultLang('en');
|
||||||
|
|
||||||
|
// the lang to use, if the lang isn't available, it will use the current loader to get them
|
||||||
|
translate.use('en');
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.translate.get('title')
|
||||||
|
.subscribe(title => this.setTitle(title));
|
||||||
|
}
|
||||||
|
|
||||||
|
public setTitle(newTitle: string) {
|
||||||
|
this.titleService.setTitle(newTitle);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
import { NgModule, NgModuleFactoryLoader } from '@angular/core';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
// import { FormsModule } from '@angular/forms';
|
||||||
|
import { HttpModule } from '@angular/http';
|
||||||
|
import { RouterModule } from '@angular/Router';
|
||||||
|
|
||||||
|
import { routing } from './app.routes';
|
||||||
|
import { AppService } from './app.service';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
import { SharedModule } from './shared/shared.module';
|
||||||
|
import { CatalogModule } from './catalog/catalog.module';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [AppComponent],
|
||||||
|
imports: [
|
||||||
|
BrowserModule,
|
||||||
|
routing,
|
||||||
|
// FormsModule,
|
||||||
|
HttpModule,
|
||||||
|
// Only module that app module loads
|
||||||
|
SharedModule.forRoot(),
|
||||||
|
CatalogModule
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
AppService
|
||||||
|
],
|
||||||
|
bootstrap: [AppComponent]
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
@ -0,0 +1,15 @@
|
|||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
|
||||||
|
export const routes: Routes = [
|
||||||
|
{ path: '', redirectTo: 'catalog', pathMatch: 'full' }
|
||||||
|
// Lazy async modules
|
||||||
|
// {
|
||||||
|
// path: 'login', loadChildren: () => new Promise(resolve => {
|
||||||
|
// (require as any).ensure([], (require: any) => {
|
||||||
|
// resolve(require('./+login/login.module').LoginModule);
|
||||||
|
// });
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
];
|
||||||
|
|
||||||
|
export const routing = RouterModule.forRoot(routes);
|
@ -0,0 +1,6 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AppService {
|
||||||
|
constructor() { }
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
<div class="catalog-banner">
|
||||||
|
<img class="catalog-banner-image" src="../../images/main_banner.png" />
|
||||||
|
<div class="container">
|
||||||
|
<img src="../../images/main_banner_text.png" class="catalog-banner-text" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="catalog-filter">
|
||||||
|
<div class="catalog-filter-container">
|
||||||
|
<div class="container">
|
||||||
|
<select>
|
||||||
|
<option>Opción 1</option>
|
||||||
|
<option>Opción 2</option>
|
||||||
|
</select>
|
||||||
|
<select>
|
||||||
|
<option>Opción 1</option>
|
||||||
|
<option>Opción 2</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="catalog-content row">
|
||||||
|
<div class="col-md-4 catalog-content-item">
|
||||||
|
<img src="https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt"/>
|
||||||
|
<button class="catalog-content-item-button">[ ADD TO CART ]</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 catalog-content-item">
|
||||||
|
<img src="https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" />
|
||||||
|
<button class="catalog-content-item-button">[ ADD TO CART ]</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 catalog-content-item">
|
||||||
|
<img src="https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" />
|
||||||
|
<button class="catalog-content-item-button">[ ADD TO CART ]</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 catalog-content-item">
|
||||||
|
<img src="https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" />
|
||||||
|
<button class="catalog-content-item-button">[ ADD TO CART ]</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 catalog-content-item">
|
||||||
|
<img src="https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" />
|
||||||
|
<button class="catalog-content-item-button">[ ADD TO CART ]</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,55 @@
|
|||||||
|
@import '../_variables.scss';
|
||||||
|
|
||||||
|
.catalog{
|
||||||
|
&-banner {
|
||||||
|
height: 258px;
|
||||||
|
vertical-align:middle;
|
||||||
|
|
||||||
|
&-image {
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
height: 258px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-text {
|
||||||
|
position:relative;
|
||||||
|
top: 75px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-filter {
|
||||||
|
height: 65px;
|
||||||
|
|
||||||
|
&-container {
|
||||||
|
position:absolute;
|
||||||
|
width:100%;
|
||||||
|
background-color: $primary-colour;
|
||||||
|
left:0;
|
||||||
|
height: 65px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-content{
|
||||||
|
margin-top: 10px;
|
||||||
|
|
||||||
|
&-item {
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&-image{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
&-button {
|
||||||
|
width: 255px;
|
||||||
|
height: 45px;
|
||||||
|
padding: 10px 20px 10px 20px;
|
||||||
|
background-color: $primary-accent;
|
||||||
|
color: white;
|
||||||
|
font-size: 16px;
|
||||||
|
margin: 10px 0;
|
||||||
|
border:none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'appc-catalog',
|
||||||
|
styleUrls: ['./catalog.component.scss'],
|
||||||
|
templateUrl: './catalog.component.html'
|
||||||
|
})
|
||||||
|
export class CatalogComponent implements OnInit {
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
console.log('catalog component loaded');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
|
||||||
|
import { CatalogComponent } from './catalog.component';
|
||||||
|
import { routing } from './catalog.routes';
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [routing],
|
||||||
|
declarations: [CatalogComponent]
|
||||||
|
})
|
||||||
|
export class CatalogModule { }
|
@ -0,0 +1,9 @@
|
|||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
|
||||||
|
import { CatalogComponent } from './catalog.component';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{ path: 'catalog', component: CatalogComponent }
|
||||||
|
];
|
||||||
|
|
||||||
|
export const routing = RouterModule.forChild(routes);
|
@ -0,0 +1,3 @@
|
|||||||
|
<h1>404!</h1>
|
||||||
|
|
||||||
|
<p>Page you are looking for does not exists.</p>
|
@ -0,0 +1,11 @@
|
|||||||
|
/* tslint:disable:no-unused-variable */
|
||||||
|
|
||||||
|
import { TestBed, async } from '@angular/core/testing';
|
||||||
|
import { PageNotFoundComponent } from './page-not-found.component';
|
||||||
|
|
||||||
|
describe('Component: PageNotFound', () => {
|
||||||
|
it('should create an instance', () => {
|
||||||
|
let component = new PageNotFoundComponent();
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,15 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'appc-page-not-found',
|
||||||
|
templateUrl: './page-not-found.component.html',
|
||||||
|
styleUrls: ['./page-not-found.component.scss']
|
||||||
|
})
|
||||||
|
export class PageNotFoundComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'appc-page-heading',
|
||||||
|
template: `<h4>{{text}}</h4>`
|
||||||
|
})
|
||||||
|
export class PageHeadingComponent {
|
||||||
|
@Input() text: string;
|
||||||
|
constructor() { }
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
import {
|
||||||
|
fakeAsync,
|
||||||
|
tick,
|
||||||
|
TestBed
|
||||||
|
} from '@angular/core/testing';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { By } from '@angular/platform-browser/src/dom/debug/by';
|
||||||
|
|
||||||
|
// Load the implementations that should be tested
|
||||||
|
import { XLargeDirective } from './x-large.directive';
|
||||||
|
|
||||||
|
describe('x-large directive', () => {
|
||||||
|
// Create a test component to test directives
|
||||||
|
@Component({
|
||||||
|
template: '<div x-large>Content</div>'
|
||||||
|
})
|
||||||
|
class TestComponent { }
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [
|
||||||
|
XLargeDirective,
|
||||||
|
TestComponent
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should sent font-size to x-large', fakeAsync(() => {
|
||||||
|
TestBed.compileComponents().then(() => {
|
||||||
|
|
||||||
|
const fixture = TestBed.createComponent(TestComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
tick();
|
||||||
|
const element = fixture.debugElement.query(By.css('div'));
|
||||||
|
|
||||||
|
// expect(element.nativeElement.style.fontSize).toBe('x-large');
|
||||||
|
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,18 @@
|
|||||||
|
import { Directive, ElementRef, Renderer } from '@angular/core';
|
||||||
|
/*
|
||||||
|
* Directive
|
||||||
|
* XLarge is a simple directive to show how one is made
|
||||||
|
*/
|
||||||
|
@Directive({
|
||||||
|
selector: '[appdXlarge]' // using [ ] means selecting attributes
|
||||||
|
})
|
||||||
|
export class XLargeDirective {
|
||||||
|
constructor(element: ElementRef, renderer: Renderer) {
|
||||||
|
// simple DOM manipulation to set font size to x-large
|
||||||
|
// `nativeElement` is the direct reference to the DOM element
|
||||||
|
// element.nativeElement.style.fontSize = 'x-large';
|
||||||
|
|
||||||
|
// for server/webworker support use the renderer
|
||||||
|
renderer.setElementStyle(element.nativeElement, 'fontSize', 'x-large');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
export class ControlBase<T>{
|
||||||
|
value: T;
|
||||||
|
key: string;
|
||||||
|
label: string;
|
||||||
|
placeholder: string;
|
||||||
|
required: boolean;
|
||||||
|
minlength: number;
|
||||||
|
maxlength: number;
|
||||||
|
order: number;
|
||||||
|
type: string;
|
||||||
|
class: string;
|
||||||
|
|
||||||
|
constructor(options: {
|
||||||
|
value?: T,
|
||||||
|
key?: string,
|
||||||
|
label?: string,
|
||||||
|
placeholder?: string,
|
||||||
|
required?: boolean,
|
||||||
|
minlength?: number,
|
||||||
|
maxlength?: number,
|
||||||
|
order?: number,
|
||||||
|
type?: string,
|
||||||
|
class?: string;
|
||||||
|
} = {}) {
|
||||||
|
this.value = options.value;
|
||||||
|
this.key = options.key || '';
|
||||||
|
this.label = options.label || '';
|
||||||
|
this.placeholder = options.placeholder || '';
|
||||||
|
this.required = !!options.required;
|
||||||
|
this.minlength = options.minlength;
|
||||||
|
this.maxlength = options.maxlength;
|
||||||
|
this.order = options.order === undefined ? 1 : options.order;
|
||||||
|
this.type = options.type || '';
|
||||||
|
this.class = options.class || '';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
import { ControlBase } from './control-base';
|
||||||
|
|
||||||
|
export class ControlCheckbox extends ControlBase<string> {
|
||||||
|
type: string;
|
||||||
|
|
||||||
|
constructor(options: any = {}) {
|
||||||
|
super(options);
|
||||||
|
this.type = 'checkbox';
|
||||||
|
this.value = options.value || false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
import { ControlBase } from './control-base';
|
||||||
|
|
||||||
|
export class ControlDropdown extends ControlBase<string> {
|
||||||
|
options: { key: string, value: string }[] = [];
|
||||||
|
|
||||||
|
constructor(options: any = {}) {
|
||||||
|
super(options);
|
||||||
|
this.type = 'dropdown';
|
||||||
|
this.options = options.options || [];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
import { ControlBase } from './control-base';
|
||||||
|
|
||||||
|
export class ControlTextbox extends ControlBase<boolean> {
|
||||||
|
constructor(options: any = {}) {
|
||||||
|
super(options);
|
||||||
|
this.type = options.type || 'textbox';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
<!--{{f.controls[control.key] | json}}-->
|
||||||
|
<div #f="ngForm" [formGroup]="form" [ngSwitch]="control.type" class="form-group {{control.class}}" [class.has-danger]="invalid"
|
||||||
|
[class.has-success]="valid" [class.form-check]="control.type === 'checkbox'">
|
||||||
|
|
||||||
|
<label *ngSwitchCase="'dropdown'" [attr.for]="control.key" class="col-form-label">{{control.label}}</label>
|
||||||
|
<select *ngSwitchCase="'dropdown'" [id]="control.key" [formControlName]="control.key" [class.form-control-success]="valid"
|
||||||
|
[class.form-control-danger]="invalid" class="form-control">
|
||||||
|
<option *ngFor="let opt of control.options" [value]="opt.key">{{opt.value}}</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<label *ngSwitchCase="'checkbox'" [attr.for]="control.key" class="form-check-label">
|
||||||
|
<input #ck *ngSwitchCase="'checkbox'" (change)="control.value = ck.checked" [id]="control.key" [formControlName]="control.key"
|
||||||
|
[type]="control.type" class="form-check-input">
|
||||||
|
{{control.label}}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<!--This is not the switch case because of multiple control types-->
|
||||||
|
<label *ngIf="control.type === 'textbox' || control.type === 'email' || control.type === 'password'" [attr.for]="control.key" class="col-form-label">{{control.label}}</label>
|
||||||
|
<input *ngIf="control.type === 'textbox' || control.type === 'email' || control.type === 'password'" [id]="control.key" [formControlName]="control.key" [type]="control.type"
|
||||||
|
[placeholder]="control.placeholder" [class.form-control-success]="valid" [class.form-control-danger]="invalid" class="form-control">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<appc-control-error-message [form]="f" [control]="control"></appc-control-error-message>
|
||||||
|
|
||||||
|
</div>
|
@ -0,0 +1,26 @@
|
|||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
import { FormGroup } from '@angular/forms';
|
||||||
|
import { ControlBase } from './control-base';
|
||||||
|
import { ErrorMessageComponent } from './error-message.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'appc-dynamic-control',
|
||||||
|
templateUrl: './dynamic-form-control.component.html'
|
||||||
|
})
|
||||||
|
export class DynamicFormControlComponent {
|
||||||
|
@Input() control;
|
||||||
|
@Input() form;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.control = undefined;
|
||||||
|
this.form = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
get valid() {
|
||||||
|
return this.form.controls[this.control.key].valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
get invalid() {
|
||||||
|
return !this.form.controls[this.control.key].valid && this.form.controls[this.control.key].touched;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
<form class="{{formClass}}" (ngSubmit)="onSubmit()" [formGroup]="form" novalidate role="form">
|
||||||
|
<appc-dynamic-control *ngFor="let ctrl of controls" [control]="ctrl" [form]="form"></appc-dynamic-control>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary pull-right" [disabled]="!form.valid">{{btnText}}</button>
|
||||||
|
</form>
|
@ -0,0 +1,30 @@
|
|||||||
|
import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';
|
||||||
|
import { FormGroup } from '@angular/forms';
|
||||||
|
|
||||||
|
import { ControlBase } from './control-base';
|
||||||
|
import { FormControlService } from './form-control.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'appc-dynamic-form',
|
||||||
|
templateUrl: './dynamic-form.component.html'
|
||||||
|
})
|
||||||
|
export class DynamicFormComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input() controls: ControlBase<any>[] = [];
|
||||||
|
@Input() btnText: string = 'Submit'; // Default value at least
|
||||||
|
@Input() formClass: string = 'form-horizontal';
|
||||||
|
// Note: don't keep name of output events as same as native events such as submit etc.
|
||||||
|
@Output() formsubmit: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
form: FormGroup;
|
||||||
|
|
||||||
|
constructor(private _controlService: FormControlService) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
let sortedControls = this.controls.sort((a, b) => a.order - b.order);
|
||||||
|
this.form = this._controlService.toControlGroup(sortedControls);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
|
this.formsubmit.emit(this.form.value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import { Component, Host, Input } from '@angular/core';
|
||||||
|
import { FormGroupDirective } from '@angular/forms';
|
||||||
|
|
||||||
|
import { ControlBase } from './control-base';
|
||||||
|
import { ValidationService } from './validation.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'appc-control-error-message',
|
||||||
|
template: `<div *ngIf="errorMessage" class="form-control-feedback"> {{errorMessage}} </div>`
|
||||||
|
})
|
||||||
|
export class ErrorMessageComponent {
|
||||||
|
@Input() control: ControlBase<any>;
|
||||||
|
@Input() form: FormGroupDirective;
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
get errorMessage() {
|
||||||
|
let c = this.form.form.get(this.control.key);
|
||||||
|
for (let propertyName in c.errors) {
|
||||||
|
if (c.errors.hasOwnProperty(propertyName) && c.touched) {
|
||||||
|
return ValidationService.getValidatorErrorMessage(propertyName, this.control.minlength || this.control.maxlength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
<div class="alert alert-danger" *ngIf="errors?.length > 0">
|
||||||
|
<ul>
|
||||||
|
<li *ngFor="let error of errors">
|
||||||
|
{{error}}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
@ -0,0 +1,11 @@
|
|||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'appc-error-summary',
|
||||||
|
templateUrl: './error-summary.component.html'
|
||||||
|
})
|
||||||
|
export class ErrorSummaryComponent {
|
||||||
|
@Input() errors: string | string[];
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||||
|
|
||||||
|
import { ControlBase } from './control-base';
|
||||||
|
import { ValidationService } from './validation.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class FormControlService {
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
toControlGroup(controls: ControlBase<any>[]) {
|
||||||
|
let group: any = {};
|
||||||
|
|
||||||
|
controls.forEach(control => {
|
||||||
|
let validators = [];
|
||||||
|
// Required
|
||||||
|
if (control.required) {
|
||||||
|
validators.push(Validators.required);
|
||||||
|
}
|
||||||
|
// Minlength
|
||||||
|
if (control.minlength) {
|
||||||
|
validators.push(Validators.minLength(control.minlength));
|
||||||
|
}
|
||||||
|
// Maxlength
|
||||||
|
if (control.maxlength) {
|
||||||
|
validators.push(Validators.minLength(control.maxlength));
|
||||||
|
}
|
||||||
|
// Email
|
||||||
|
if (control.type === 'email') {
|
||||||
|
validators.push(ValidationService.emailValidator);
|
||||||
|
}
|
||||||
|
// Password
|
||||||
|
if (control.type === 'password') {
|
||||||
|
validators.push(ValidationService.passwordValidator);
|
||||||
|
}
|
||||||
|
group[control.key] = new FormControl(control.value || '', validators);
|
||||||
|
});
|
||||||
|
|
||||||
|
return new FormGroup(group);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
export class ValidationService {
|
||||||
|
|
||||||
|
static getValidatorErrorMessage(code: string, fieldLength: number) {
|
||||||
|
let config: any = {
|
||||||
|
'required': 'This is a required field',
|
||||||
|
'minlength': 'Minimum length is ' + fieldLength,
|
||||||
|
'maxlength': 'Maximum length is ' + fieldLength,
|
||||||
|
'invalidCreditCard': 'Invalid credit card number',
|
||||||
|
'invalidEmailAddress': 'Invalid email address',
|
||||||
|
'invalidPassword': 'Password must be at least 6 characters long, and contain a number and special character.'
|
||||||
|
};
|
||||||
|
return config[code];
|
||||||
|
}
|
||||||
|
|
||||||
|
static creditCardValidator(control: any) {
|
||||||
|
// Visa, MasterCard, American Express, Diners Club, Discover, JCB
|
||||||
|
if (control.value.match(/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/)) {
|
||||||
|
return undefined;
|
||||||
|
} else {
|
||||||
|
return { 'invalidCreditCard': true };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static emailValidator(control: any) {
|
||||||
|
// RFC 2822 compliant regex
|
||||||
|
if (control.value.match(/[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/)) {
|
||||||
|
return undefined;
|
||||||
|
} else {
|
||||||
|
return { 'invalidEmailAddress': true };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static passwordValidator(control: any) {
|
||||||
|
// {6,100} - Assert password is between 6 and 100 characters
|
||||||
|
// (?=.*[0-9]) - Assert a string has at least one number
|
||||||
|
if (control.value.match(/^(?=.*[0-9])[a-zA-Z0-9!"@#$%^&*]{6,100}$/)) {
|
||||||
|
return undefined;
|
||||||
|
} else {
|
||||||
|
return { 'invalidPassword': true };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
<footer class="text-muted">
|
||||||
|
<div class="container">
|
||||||
|
<hr>
|
||||||
|
<p class="text-muted">
|
||||||
|
© 2015-2016 {{'title' | translate}} Company
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
@ -0,0 +1,8 @@
|
|||||||
|
@import '../../_variables.scss';
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
padding-top: 40px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
margin-top: 40px;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'appc-footer',
|
||||||
|
styleUrls: ['./footer.component.scss'],
|
||||||
|
templateUrl: './footer.component.html'
|
||||||
|
})
|
||||||
|
export class FooterComponent {
|
||||||
|
constructor() { }
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
<header class="navbar navbar-light navbar-static-top">
|
||||||
|
<div class="container">
|
||||||
|
<nav>
|
||||||
|
<div class="clearfix">
|
||||||
|
<!--<button class="navbar-toggler float-xs-right hidden-sm-up collapsed" type="button" data-toggle="collapse" data-target="#bd-main-nav"
|
||||||
|
aria-controls="bd-main-nav" aria-expanded="false" aria-label="Toggle navigation" (click)="toggleNav()">
|
||||||
|
☰
|
||||||
|
</button>
|
||||||
|
<a class="navbar-brand hidden-sm-up header-brand" routerLink="home">
|
||||||
|
Ng2fbBootstrap
|
||||||
|
<img src="../../../images/brand.png" />
|
||||||
|
</a>-->
|
||||||
|
</div>
|
||||||
|
<div class="" id="bd-main-nav" aria-expanded="false" style="height: 0px;">
|
||||||
|
<a class="navbar-brand" routerLink="home">
|
||||||
|
<img src="../../../images/brand.png" />
|
||||||
|
</a>
|
||||||
|
<!--<ul class="nav navbar-nav">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-item nav-link" routerLinkActive="active" routerLink="home">Home</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-item nav-link" routerLinkActive="active" routerLink="examples">Examples</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<ul class="nav float-xs-left float-md-right">
|
||||||
|
|
||||||
|
<li class="nav-item" *ngIf="authService.isLoggedIn() && authService.user()">
|
||||||
|
<a class="nav-item nav-link" routerLinkActive="active" routerLink="profile">
|
||||||
|
<i class="fa fa-user"></i> {{authService.user().displayName}}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-item" *ngIf="!authService.isLoggedIn()">
|
||||||
|
<a class="nav-item nav-link" routerLinkActive="active" routerLink="register">
|
||||||
|
<i class="fa fa-user"></i> Register
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-item" *ngIf="!authService.isLoggedIn()">
|
||||||
|
<a class="nav-item nav-link" routerLinkActive="active" routerLink="login">
|
||||||
|
<i class="fa fa-sign-in"></i>Login
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" *ngIf="authService.isLoggedIn() && authService.user()?.roles?.indexOf('Admin') > -1">
|
||||||
|
<a class="nav-item nav-link" routerLinkActive="active" routerLink="admin">
|
||||||
|
<i class="fa fa-gear"></i> Admin
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" *ngIf="authService.isLoggedIn()">
|
||||||
|
<a class="nav-item nav-link" (click)="authService.logout()" routerLinkActive="active" href="javascript:void(null);">
|
||||||
|
<i class="fa fa-sign-out"></i> Logout
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>-->
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</header>
|
@ -0,0 +1,5 @@
|
|||||||
|
@import '../../_variables.scss';
|
||||||
|
|
||||||
|
.header-brand {
|
||||||
|
background-image:url('../../../images/brand.png')
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
import { Component, Inject } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
import { AuthService } from '../services/auth.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'appc-header',
|
||||||
|
styleUrls: ['./header.component.scss'],
|
||||||
|
templateUrl: './header.component.html'
|
||||||
|
})
|
||||||
|
export class HeaderComponent {
|
||||||
|
isCollapsed: boolean = true;
|
||||||
|
constructor(private router: Router, private authService: AuthService) { }
|
||||||
|
|
||||||
|
toggleNav() {
|
||||||
|
this.isCollapsed = !this.isCollapsed;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
export class OperationResult {
|
||||||
|
constructor(public succeeded: boolean, public message: string) { }
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
import { User } from './user.model';
|
||||||
|
// todo: I dont think user follows angular style guides
|
||||||
|
|
||||||
|
describe('User Model', () => {
|
||||||
|
it('has displayName', () => {
|
||||||
|
let userModel: User = {displayName: 'test', roles: ['1']};
|
||||||
|
expect(userModel.displayName).toEqual('test');
|
||||||
|
});
|
||||||
|
it('has displayName', () => {
|
||||||
|
let userModel: User = {displayName: 'test', roles: ['admin']};
|
||||||
|
expect(userModel.roles[0]).toEqual('admin');
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,4 @@
|
|||||||
|
export class User {
|
||||||
|
constructor(public displayName: string, public roles: string[]) {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
import { UppercasePipe } from './uppercase.pipe';
|
||||||
|
|
||||||
|
describe('Pipe appfUppercase', () => {
|
||||||
|
let pipe: UppercasePipe;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
pipe = new UppercasePipe();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('transforms "abc" to "ABC"', () => {
|
||||||
|
expect(pipe.transform('abc')).toEqual('ABC');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('transforms "abc def" to "ABC DEF"', () => {
|
||||||
|
expect(pipe.transform('abc def')).toEqual('ABC DEF');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('leaves "ABC DEF" unchanged', () => {
|
||||||
|
expect(pipe.transform('ABC DEF')).toEqual('ABC DEF');
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,10 @@
|
|||||||
|
import { Pipe, PipeTransform } from '@angular/core';
|
||||||
|
|
||||||
|
@Pipe({
|
||||||
|
name: 'appfUppercase'
|
||||||
|
})
|
||||||
|
export class UppercasePipe implements PipeTransform {
|
||||||
|
transform(value: string) {
|
||||||
|
return value.toUpperCase();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,207 @@
|
|||||||
|
// CREDIT:
|
||||||
|
// The vast majority of this code came right from Ben Nadel's post:
|
||||||
|
// http://www.bennadel.com/blog/3047-creating-specialized-http-clients-in-angular-2-beta-8.htm
|
||||||
|
//
|
||||||
|
// My updates are mostly adapting it for Typescript:
|
||||||
|
// 1. Importing required modules
|
||||||
|
// 2. Adding type notations
|
||||||
|
// 3. Using the 'fat-arrow' syntax to properly scope in-line functions
|
||||||
|
//
|
||||||
|
import 'rxjs/add/operator/map';
|
||||||
|
import 'rxjs/add/operator/catch';
|
||||||
|
import 'rxjs/add/operator/finally';
|
||||||
|
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Http, Response, RequestOptions, RequestMethod, URLSearchParams } from '@angular/http';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { Subject } from 'rxjs/Subject';
|
||||||
|
|
||||||
|
import { HttpErrorHandlerService } from './http-error-handler.service';
|
||||||
|
|
||||||
|
// Import the rxjs operators we need (in a production app you'll
|
||||||
|
// probably want to import only the operators you actually use)
|
||||||
|
//
|
||||||
|
export class ApiGatewayOptions {
|
||||||
|
method: RequestMethod;
|
||||||
|
url: string;
|
||||||
|
headers: any = {};
|
||||||
|
params = {};
|
||||||
|
data = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ApiGatewayService {
|
||||||
|
|
||||||
|
// Define the internal Subject we'll use to push the command count
|
||||||
|
private pendingCommandsSubject = new Subject<number>();
|
||||||
|
private pendingCommandCount = 0;
|
||||||
|
|
||||||
|
// Provide the *public* Observable that clients can subscribe to
|
||||||
|
private pendingCommands$: Observable<number>;
|
||||||
|
|
||||||
|
constructor(private http: Http, private httpErrorHandler: HttpErrorHandlerService) {
|
||||||
|
this.pendingCommands$ = this.pendingCommandsSubject.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
// I perform a GET request to the API, appending the given params
|
||||||
|
// as URL search parameters. Returns a stream.
|
||||||
|
get(url: string, params: any): Observable<Response> {
|
||||||
|
let options = new ApiGatewayOptions();
|
||||||
|
options.method = RequestMethod.Get;
|
||||||
|
options.url = url;
|
||||||
|
options.params = params;
|
||||||
|
return this.request(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
// I perform a POST request to the API. If both the params and data
|
||||||
|
// are present, the params will be appended as URL search parameters
|
||||||
|
// and the data will be serialized as a JSON payload. If only the
|
||||||
|
// data is present, it will be serialized as a JSON payload. Returns
|
||||||
|
// a stream.
|
||||||
|
post(url: string, data: any, params: any): Observable<Response> {
|
||||||
|
if (!data) {
|
||||||
|
data = params;
|
||||||
|
params = {};
|
||||||
|
}
|
||||||
|
let options = new ApiGatewayOptions();
|
||||||
|
options.method = RequestMethod.Post;
|
||||||
|
options.url = url;
|
||||||
|
options.params = params;
|
||||||
|
options.data = data;
|
||||||
|
return this.request(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private request(options: ApiGatewayOptions): Observable<any> {
|
||||||
|
options.method = (options.method || RequestMethod.Get);
|
||||||
|
options.url = (options.url || '');
|
||||||
|
options.headers = (options.headers || {});
|
||||||
|
options.params = (options.params || {});
|
||||||
|
options.data = (options.data || {});
|
||||||
|
|
||||||
|
this.interpolateUrl(options);
|
||||||
|
this.addXsrfToken(options);
|
||||||
|
this.addContentType(options);
|
||||||
|
// TODO add auth token when available
|
||||||
|
// this.addAuthToken(options);
|
||||||
|
|
||||||
|
let requestOptions = new RequestOptions();
|
||||||
|
requestOptions.method = options.method;
|
||||||
|
requestOptions.url = options.url;
|
||||||
|
requestOptions.headers = options.headers;
|
||||||
|
requestOptions.search = this.buildUrlSearchParams(options.params);
|
||||||
|
requestOptions.body = JSON.stringify(options.data);
|
||||||
|
|
||||||
|
let isCommand = (options.method !== RequestMethod.Get);
|
||||||
|
|
||||||
|
if (isCommand) {
|
||||||
|
this.pendingCommandsSubject.next(++this.pendingCommandCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
let stream = this.http.request(options.url, requestOptions)
|
||||||
|
.catch((error: any) => {
|
||||||
|
this.httpErrorHandler.handle(error);
|
||||||
|
return Observable.throw(error);
|
||||||
|
})
|
||||||
|
.map(this.unwrapHttpValue)
|
||||||
|
.catch((error: any) => {
|
||||||
|
return Observable.throw(this.unwrapHttpError(error));
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
if (isCommand) {
|
||||||
|
this.pendingCommandsSubject.next(--this.pendingCommandCount);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private addContentType(options: ApiGatewayOptions): ApiGatewayOptions {
|
||||||
|
if (options.method !== RequestMethod.Get) {
|
||||||
|
options.headers['Content-Type'] = 'application/json; charset=UTF-8';
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
private addAuthToken(options: ApiGatewayOptions): ApiGatewayOptions {
|
||||||
|
options.headers.Authorization = 'Bearer ' + JSON.parse(sessionStorage.getItem('accessToken'));
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
private extractValue(collection: any, key: string): any {
|
||||||
|
let value = collection[key];
|
||||||
|
delete (collection[key]);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private addXsrfToken(options: ApiGatewayOptions): ApiGatewayOptions {
|
||||||
|
let xsrfToken = this.getXsrfCookie();
|
||||||
|
if (xsrfToken) {
|
||||||
|
options.headers['X-XSRF-TOKEN'] = xsrfToken;
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getXsrfCookie(): string {
|
||||||
|
let matches = document.cookie.match(/\bXSRF-TOKEN=([^\s;]+)/);
|
||||||
|
try {
|
||||||
|
return (matches && decodeURIComponent(matches[1]));
|
||||||
|
} catch (decodeError) {
|
||||||
|
return ('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private addCors(options: ApiGatewayOptions): ApiGatewayOptions {
|
||||||
|
options.headers['Access-Control-Allow-Origin'] = '*';
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildUrlSearchParams(params: any): URLSearchParams {
|
||||||
|
let searchParams = new URLSearchParams();
|
||||||
|
for (let key in params) {
|
||||||
|
if (params.hasOwnProperty(key)) {
|
||||||
|
searchParams.append(key, params[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return searchParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
private interpolateUrl(options: ApiGatewayOptions): ApiGatewayOptions {
|
||||||
|
options.url = options.url.replace(/:([a-zA-Z]+[\w-]*)/g, ($0, token) => {
|
||||||
|
// Try to move matching token from the params collection.
|
||||||
|
if (options.params.hasOwnProperty(token)) {
|
||||||
|
return (this.extractValue(options.params, token));
|
||||||
|
}
|
||||||
|
// Try to move matching token from the data collection.
|
||||||
|
if (options.data.hasOwnProperty(token)) {
|
||||||
|
return (this.extractValue(options.data, token));
|
||||||
|
}
|
||||||
|
// If a matching value couldn't be found, just replace
|
||||||
|
// the token with the empty string.
|
||||||
|
return ('');
|
||||||
|
});
|
||||||
|
// Clean up any repeating slashes.
|
||||||
|
options.url = options.url.replace(/\/{2,}/g, '/');
|
||||||
|
// Clean up any trailing slashes.
|
||||||
|
options.url = options.url.replace(/\/+$/g, '');
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
private unwrapHttpError(error: any): any {
|
||||||
|
try {
|
||||||
|
return (error.json());
|
||||||
|
} catch (jsonError) {
|
||||||
|
return ({
|
||||||
|
code: -1,
|
||||||
|
message: 'An unexpected error occurred.'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private unwrapHttpValue(value: Response): any {
|
||||||
|
return (value.json());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs/Rx';
|
||||||
|
import { TranslateLoader } from 'ng2-translate/ng2-translate';
|
||||||
|
import { MissingTranslationHandler, MissingTranslationHandlerParams } from 'ng2-translate/ng2-translate';
|
||||||
|
|
||||||
|
import { ContentService } from './content.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ApiTranslationLoader implements TranslateLoader {
|
||||||
|
|
||||||
|
constructor(private cs: ContentService) { }
|
||||||
|
|
||||||
|
getTranslation(lang: string): Observable<any> {
|
||||||
|
return this.cs.get(lang);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CustomMissingTranslationHandler implements MissingTranslationHandler {
|
||||||
|
handle(params: MissingTranslationHandlerParams) {
|
||||||
|
return params.key;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
import { DataService } from './data.service';
|
||||||
|
import { User } from '../models/user.model';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AuthService {
|
||||||
|
|
||||||
|
constructor(private router: Router) { }
|
||||||
|
|
||||||
|
logout() {
|
||||||
|
sessionStorage.clear();
|
||||||
|
this.router.navigate(['/login']);
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoggedIn(): boolean {
|
||||||
|
return this.user(undefined) !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
user(user: User): User {
|
||||||
|
if (user) {
|
||||||
|
sessionStorage.setItem('user', JSON.stringify(user));
|
||||||
|
}
|
||||||
|
let userData = JSON.parse(sessionStorage.getItem('user'));
|
||||||
|
if (userData) {
|
||||||
|
user = new User(userData.displayName, userData.roles);
|
||||||
|
}
|
||||||
|
return user ? user : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
setAuth(res: any): void {
|
||||||
|
if (res && res.user) {
|
||||||
|
sessionStorage.setItem('user', JSON.stringify(res.user));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { DataService } from './data.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ContentService {
|
||||||
|
|
||||||
|
constructor(public dataService: DataService) { }
|
||||||
|
|
||||||
|
get(lang?: string): any {
|
||||||
|
return this.dataService.get('api/content?lang=' + (lang ? lang : 'en'));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { ApiGatewayService } from './api-gateway.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class DataService {
|
||||||
|
|
||||||
|
constructor(public http: ApiGatewayService) { }
|
||||||
|
|
||||||
|
get(url: string, params?: any) {
|
||||||
|
return this.http.get(url, undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
post(url: string, data: any, params?: any) {
|
||||||
|
return this.http.post(url, data, params);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
// CREDIT:
|
||||||
|
// The vast majority of this code came right from Ben Nadel's post:
|
||||||
|
// http://www.bennadel.com/blog/3047-creating-specialized-http-clients-in-angular-2-beta-8.htm
|
||||||
|
//
|
||||||
|
// My updates are mostly adapting it for Typescript:
|
||||||
|
// 1. Importing required modules
|
||||||
|
// 2. Adding type notations
|
||||||
|
// 3. Using the 'fat-arrow' syntax to properly scope in-line functions
|
||||||
|
//
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class HttpErrorHandlerService {
|
||||||
|
|
||||||
|
constructor(private _router: Router) { }
|
||||||
|
|
||||||
|
handle(error: any) {
|
||||||
|
if (error.status === 401) {
|
||||||
|
sessionStorage.clear();
|
||||||
|
// window.location.href = 'login';
|
||||||
|
this._router.navigate(['Login']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class NotificationService {
|
||||||
|
|
||||||
|
printSuccessMessage(message: string) {
|
||||||
|
console.log(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
printErrorMessage(message: string) {
|
||||||
|
console.error(message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UtilityService {
|
||||||
|
|
||||||
|
private _router: Router;
|
||||||
|
|
||||||
|
constructor(router: Router) {
|
||||||
|
this._router = router;
|
||||||
|
}
|
||||||
|
|
||||||
|
convertDateTime(date: Date) {
|
||||||
|
let _formattedDate = new Date(date.toString());
|
||||||
|
return _formattedDate.toDateString();
|
||||||
|
}
|
||||||
|
|
||||||
|
navigate(path: string) {
|
||||||
|
this._router.navigate([path]);
|
||||||
|
}
|
||||||
|
|
||||||
|
navigateToSignIn() {
|
||||||
|
this.navigate('/login');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
import { NgModule, ModuleWithProviders } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { FormsModule, ReactiveFormsModule, FormBuilder } from '@angular/forms';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { HttpModule, JsonpModule } from '@angular/http';
|
||||||
|
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
|
import { TranslateModule, TranslateLoader } from 'ng2-translate/ng2-translate';
|
||||||
|
|
||||||
|
import { PageHeadingComponent } from './directives/page-heading.directive';
|
||||||
|
import { DynamicFormComponent } from './forms/dynamic-form.component';
|
||||||
|
import { DynamicFormControlComponent } from './forms/dynamic-form-control.component';
|
||||||
|
import { ErrorMessageComponent } from './forms/error-message.component';
|
||||||
|
import { ErrorSummaryComponent } from './forms/error-summary.component';
|
||||||
|
import { FormControlService } from './forms/form-control.service';
|
||||||
|
|
||||||
|
import { HeaderComponent } from './layout/header.component';
|
||||||
|
import { FooterComponent } from './layout/footer.component';
|
||||||
|
// Services
|
||||||
|
import { DataService } from './services/data.service';
|
||||||
|
import { ApiGatewayService } from './services/api-gateway.service';
|
||||||
|
import { AuthService } from './services/auth.service';
|
||||||
|
import { HttpErrorHandlerService } from './services/http-error-handler.service';
|
||||||
|
import { ApiTranslationLoader } from './services/api-translation-loader.service';
|
||||||
|
import { ContentService } from './services/content.service';
|
||||||
|
import { UtilityService } from './services/utility.service';
|
||||||
|
import { UppercasePipe } from './pipes/uppercase.pipe';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
FormsModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
RouterModule,
|
||||||
|
NgbModule.forRoot(),
|
||||||
|
// No need to export as these modules don't expose any components/directive etc'
|
||||||
|
HttpModule,
|
||||||
|
JsonpModule,
|
||||||
|
TranslateModule.forRoot({ provide: TranslateLoader, useClass: ApiTranslationLoader })
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
DynamicFormComponent,
|
||||||
|
DynamicFormControlComponent,
|
||||||
|
ErrorMessageComponent,
|
||||||
|
ErrorSummaryComponent,
|
||||||
|
FooterComponent,
|
||||||
|
HeaderComponent,
|
||||||
|
PageHeadingComponent,
|
||||||
|
UppercasePipe
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
// Modules
|
||||||
|
CommonModule,
|
||||||
|
FormsModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
RouterModule,
|
||||||
|
NgbModule,
|
||||||
|
TranslateModule,
|
||||||
|
// Providers, Components, directive, pipes
|
||||||
|
DynamicFormComponent,
|
||||||
|
DynamicFormControlComponent,
|
||||||
|
ErrorSummaryComponent,
|
||||||
|
ErrorMessageComponent,
|
||||||
|
FooterComponent,
|
||||||
|
HeaderComponent,
|
||||||
|
PageHeadingComponent,
|
||||||
|
UppercasePipe
|
||||||
|
]
|
||||||
|
|
||||||
|
})
|
||||||
|
export class SharedModule {
|
||||||
|
static forRoot(): ModuleWithProviders {
|
||||||
|
return {
|
||||||
|
ngModule: SharedModule,
|
||||||
|
providers: [
|
||||||
|
// Providers
|
||||||
|
HttpErrorHandlerService,
|
||||||
|
ApiGatewayService,
|
||||||
|
AuthService,
|
||||||
|
DataService,
|
||||||
|
ContentService,
|
||||||
|
FormControlService,
|
||||||
|
UtilityService
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
23
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/polyfills.ts
Normal file
23
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/polyfills.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Added parts of es6 which are necessary for your project or your browser support requirements.
|
||||||
|
import 'core-js/es6/symbol';
|
||||||
|
import 'core-js/es6/object';
|
||||||
|
import 'core-js/es6/function';
|
||||||
|
import 'core-js/es6/parse-int';
|
||||||
|
import 'core-js/es6/parse-float';
|
||||||
|
import 'core-js/es6/number';
|
||||||
|
import 'core-js/es6/math';
|
||||||
|
import 'core-js/es6/string';
|
||||||
|
import 'core-js/es6/date';
|
||||||
|
import 'core-js/es6/array';
|
||||||
|
import 'core-js/es6/regexp';
|
||||||
|
import 'core-js/es6/map';
|
||||||
|
import 'core-js/es6/set';
|
||||||
|
import 'core-js/es6/weak-map';
|
||||||
|
import 'core-js/es6/weak-set';
|
||||||
|
import 'core-js/es6/typed';
|
||||||
|
import 'core-js/es6/reflect';
|
||||||
|
// see issue https://github.com/AngularClass/angular2-webpack-starter/issues/709
|
||||||
|
// import 'core-js/es6/promise';
|
||||||
|
|
||||||
|
import 'core-js/es7/reflect';
|
||||||
|
import 'zone.js/dist/zone';
|
20
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/vendor.ts
Normal file
20
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/vendor.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// For vendors for example jQuery, Lodash, angular2-jwt just import them here unless you plan on
|
||||||
|
// chunking vendors files for async loading. You would need to import the async loaded vendors
|
||||||
|
// at the entry point of the async loaded file. Also see custom-typings.d.ts as you also need to
|
||||||
|
// run `typings install x` where `x` is your module
|
||||||
|
|
||||||
|
// Angular 2
|
||||||
|
import '@angular/platform-browser';
|
||||||
|
import '@angular/platform-browser-dynamic';
|
||||||
|
import '@angular/core';
|
||||||
|
import '@angular/common';
|
||||||
|
import '@angular/forms';
|
||||||
|
import '@angular/http';
|
||||||
|
import '@angular/router';
|
||||||
|
|
||||||
|
// RxJS
|
||||||
|
import 'rxjs/add/operator/map';
|
||||||
|
import 'rxjs/add/operator/mergeMap';
|
||||||
|
import 'rxjs/add/operator/catch';
|
||||||
|
import 'rxjs/add/operator/finally';
|
||||||
|
import 'rxjs/add/observable/throw';
|
7
src/Web/WebSPA/eShopOnContainers.WebSPA/Dockerfile
Normal file
7
src/Web/WebSPA/eShopOnContainers.WebSPA/Dockerfile
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
FROM microsoft/aspnetcore:1.0.1
|
||||||
|
ENTRYPOINT ["dotnet", "eShopOnContainers.WebSPA.dll"]
|
||||||
|
ARG source=.
|
||||||
|
WORKDIR /app
|
||||||
|
ENV ASPNETCORE_URLS http://*:80
|
||||||
|
EXPOSE 80
|
||||||
|
COPY $source .
|
27
src/Web/WebSPA/eShopOnContainers.WebSPA/Program.cs
Normal file
27
src/Web/WebSPA/eShopOnContainers.WebSPA/Program.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using System.IO;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
|
namespace eShopConContainers.WebSPA
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
var config = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(Directory.GetCurrentDirectory())
|
||||||
|
.AddJsonFile("hosting.json", optional: true)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var host = new WebHostBuilder()
|
||||||
|
.UseKestrel()
|
||||||
|
.UseConfiguration(config)
|
||||||
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
|
.UseIISIntegration()
|
||||||
|
.UseStartup<Startup>()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
host.Run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:1250/",
|
||||||
|
"sslPort": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"profiles": {
|
||||||
|
"IIS Express": {
|
||||||
|
"commandName": "IISExpress",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
// For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace eShopConContainers.WebSPA.Server.Controllers
|
||||||
|
{
|
||||||
|
public class HomeController : Controller
|
||||||
|
{
|
||||||
|
private readonly IHostingEnvironment _env;
|
||||||
|
|
||||||
|
public HomeController(IHostingEnvironment env)
|
||||||
|
{
|
||||||
|
_env = env;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IActionResult Index()
|
||||||
|
{
|
||||||
|
ViewBag.HashedMain = GetHashedMainDotJs();
|
||||||
|
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetHashedMainDotJs()
|
||||||
|
{
|
||||||
|
var basePath = _env.WebRootPath + "//dist//";
|
||||||
|
var info = new System.IO.DirectoryInfo(basePath);
|
||||||
|
var file = info.GetFiles().Where(f => f.Name.StartsWith("main.") && !f.Name.EndsWith("bundle.map")).FirstOrDefault();
|
||||||
|
|
||||||
|
return file.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
93
src/Web/WebSPA/eShopOnContainers.WebSPA/Startup.cs
Normal file
93
src/Web/WebSPA/eShopOnContainers.WebSPA/Startup.cs
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Antiforgery;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.SpaServices.Webpack;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
|
||||||
|
namespace eShopConContainers.WebSPA
|
||||||
|
{
|
||||||
|
public class Startup
|
||||||
|
{
|
||||||
|
private IHostingEnvironment _hostingEnv;
|
||||||
|
public Startup(IHostingEnvironment env)
|
||||||
|
{
|
||||||
|
_hostingEnv = env;
|
||||||
|
|
||||||
|
var builder = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(env.ContentRootPath)
|
||||||
|
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
|
||||||
|
.AddEnvironmentVariables();
|
||||||
|
|
||||||
|
if (env.IsDevelopment())
|
||||||
|
{
|
||||||
|
// For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709
|
||||||
|
builder.AddUserSecrets();
|
||||||
|
}
|
||||||
|
|
||||||
|
Configuration = builder.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IConfigurationRoot Configuration { get; set; }
|
||||||
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
|
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
|
||||||
|
public void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
|
||||||
|
|
||||||
|
services.AddMvc()
|
||||||
|
.AddJsonOptions(options =>
|
||||||
|
{
|
||||||
|
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IAntiforgery antiforgery)
|
||||||
|
{
|
||||||
|
if (env.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseDeveloperExceptionPage();
|
||||||
|
|
||||||
|
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
|
||||||
|
{
|
||||||
|
HotModuleReplacement = true,
|
||||||
|
ConfigFile = "config/webpack.config.js"
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure XSRF middleware, This pattern is for SPA style applications where XSRF token is added on Index page
|
||||||
|
// load and passed back token on every subsequent async request
|
||||||
|
app.Use(async (context, next) =>
|
||||||
|
{
|
||||||
|
if (string.Equals(context.Request.Path.Value, "/", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
var tokens = antiforgery.GetAndStoreTokens(context);
|
||||||
|
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions() { HttpOnly = false });
|
||||||
|
}
|
||||||
|
await next.Invoke();
|
||||||
|
});
|
||||||
|
|
||||||
|
app.UseStaticFiles();
|
||||||
|
|
||||||
|
|
||||||
|
app.UseMvc(routes =>
|
||||||
|
{
|
||||||
|
routes.MapRoute(
|
||||||
|
name: "default",
|
||||||
|
template: "{controller=Home}/{action=Index}/{id?}");
|
||||||
|
|
||||||
|
routes.MapSpaFallbackRoute(
|
||||||
|
name: "spa-fallback",
|
||||||
|
defaults: new { controller = "Home", action = "Index" });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
<style>
|
||||||
|
div.app-spinner {
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<appc-app asp-prerender-webpack-config="config/webpack.config.js">
|
||||||
|
<div class="app-spinner">
|
||||||
|
<i class="fa fa-spinner fa-spin fa-5x" aria-hidden="true"></i>
|
||||||
|
</div>
|
||||||
|
</appc-app>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
window.user = '@ViewBag.user';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script src="~/dist/vendor.js" asp-append-version="true"></script>
|
||||||
|
<script src="~/dist/@ViewBag.HashedMain" asp-append-version="true"></script>
|
@ -0,0 +1,16 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>eShopConContainers.WebSPA</title>
|
||||||
|
<base href="/" />
|
||||||
|
<link rel="stylesheet" href="~/dist/vendor.css" asp-append-version="true" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
@RenderBody()
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
@addTagHelper "*, Microsoft.AspNetCore.Mvc.TagHelpers"
|
||||||
|
@addTagHelper "*, Microsoft.AspNetCore.SpaServices"
|
@ -0,0 +1,3 @@
|
|||||||
|
@{
|
||||||
|
Layout = "_Layout";
|
||||||
|
}
|
47
src/Web/WebSPA/eShopOnContainers.WebSPA/appsettings.json
Normal file
47
src/Web/WebSPA/eShopOnContainers.WebSPA/appsettings.json
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"DefaultConnection": "Data Source=AspNetCore.db"
|
||||||
|
},
|
||||||
|
"Logging": {
|
||||||
|
"IncludeScopes": false,
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Debug",
|
||||||
|
"System": "Information",
|
||||||
|
"Microsoft": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Email": {
|
||||||
|
"From": "",
|
||||||
|
"Subject": "",
|
||||||
|
"SendGrid": {
|
||||||
|
"Username": "",
|
||||||
|
"Password": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Authentication": {
|
||||||
|
"Google": {
|
||||||
|
"ClientId": "",
|
||||||
|
"ClientSecret": ""
|
||||||
|
},
|
||||||
|
"Facebook": {
|
||||||
|
"AppId": "",
|
||||||
|
"AppSecret": ""
|
||||||
|
},
|
||||||
|
"Microsoft": {
|
||||||
|
"ClientId": "",
|
||||||
|
"ClientSecret": ""
|
||||||
|
},
|
||||||
|
"Twitter": {
|
||||||
|
"ConsumerKey": "",
|
||||||
|
"ConsumerSecret": ""
|
||||||
|
},
|
||||||
|
"Github": {
|
||||||
|
"ClientId": "",
|
||||||
|
"ClientSecret": ""
|
||||||
|
},
|
||||||
|
"LinkedIn": {
|
||||||
|
"ClientId": "",
|
||||||
|
"ClientSecret": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
src/Web/WebSPA/eShopOnContainers.WebSPA/config/helpers.js
Normal file
23
src/Web/WebSPA/eShopOnContainers.WebSPA/config/helpers.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* @author: @AngularClass
|
||||||
|
*/
|
||||||
|
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
// Helper functions
|
||||||
|
var ROOT = path.resolve(__dirname, '..');
|
||||||
|
|
||||||
|
console.log('root directory:', root() + '\n');
|
||||||
|
|
||||||
|
function hasProcessFlag(flag) {
|
||||||
|
return process.argv.join('').indexOf(flag) > -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function root(args) {
|
||||||
|
args = Array.prototype.slice.call(arguments, 0);
|
||||||
|
return path.join.apply(path, [ROOT].concat(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
exports.hasProcessFlag = hasProcessFlag;
|
||||||
|
exports.root = root;
|
@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
devtool: 'cheap-module-source-map'
|
||||||
|
};
|
@ -0,0 +1,74 @@
|
|||||||
|
var path = require('path');
|
||||||
|
var webpack = require('webpack');
|
||||||
|
var merge = require('extendify')({ isDeep: true, arrays: 'concat' });
|
||||||
|
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||||
|
var extractCSS = new ExtractTextPlugin('styles.css');
|
||||||
|
var ForkCheckerPlugin = require('awesome-typescript-loader').ForkCheckerPlugin;
|
||||||
|
var devConfig = require('./webpack.config.dev');
|
||||||
|
var prodConfig = require('./webpack.config.prod');
|
||||||
|
var isDevelopment = process.env.ASPNETCORE_ENVIRONMENT === 'Production';
|
||||||
|
|
||||||
|
console.log("==========Dev Mode = " + isDevelopment + " ============" )
|
||||||
|
|
||||||
|
module.exports = merge({
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.js', '.ts']
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{ test: /\.ts$/, exclude: [/\.(spec|e2e)\.ts$/], loaders: ['awesome-typescript-loader?forkChecker=true ', 'angular2-template-loader'] },
|
||||||
|
{ test: /\.html$/, loader: "html" },
|
||||||
|
{ test: /\.css/, loader: extractCSS.extract(['css']) },
|
||||||
|
{ test: /\.scss$/, loaders: ['raw-loader', 'sass-loader?sourceMap'] },
|
||||||
|
{ test: /\.json$/, loader: 'json-loader' },
|
||||||
|
{
|
||||||
|
test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
|
||||||
|
loader: "url?limit=10000&mimetype=application/font-woff"
|
||||||
|
}, {
|
||||||
|
test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
|
||||||
|
loader: "url?limit=10000&mimetype=application/font-woff"
|
||||||
|
}, {
|
||||||
|
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
|
||||||
|
loader: "url?limit=10000&mimetype=application/octet-stream"
|
||||||
|
}, {
|
||||||
|
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
|
||||||
|
loader: "file"
|
||||||
|
}, {
|
||||||
|
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
|
||||||
|
loader: "url?limit=10000&mimetype=image/svg+xml"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(png|jpg|gif)$/,
|
||||||
|
loader: "file"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
entry: {
|
||||||
|
'main': './Client/main.ts'
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
path: path.join(__dirname, '../wwwroot', 'dist'),
|
||||||
|
filename: '[name].js',
|
||||||
|
publicPath: '/dist/'
|
||||||
|
},
|
||||||
|
profile: true,
|
||||||
|
plugins: [
|
||||||
|
extractCSS,
|
||||||
|
new webpack.DllReferencePlugin({
|
||||||
|
context: __dirname,
|
||||||
|
manifest: require('../wwwroot/dist/vendor-manifest.json')
|
||||||
|
}),
|
||||||
|
// To eliminate warning
|
||||||
|
// https://github.com/AngularClass/angular2-webpack-starter/issues/993
|
||||||
|
new webpack.ContextReplacementPlugin(
|
||||||
|
/angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
|
||||||
|
__dirname
|
||||||
|
),
|
||||||
|
new ForkCheckerPlugin(),
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
'process.env': {
|
||||||
|
'ENV': JSON.stringify(process.env.ASPNETCORE_ENVIRONMENT)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}, isDevelopment ? devConfig : prodConfig);
|
@ -0,0 +1,23 @@
|
|||||||
|
var webpack = require('webpack');
|
||||||
|
const WebpackMd5Hash = require('webpack-md5-hash');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
devtool: 'source-map',
|
||||||
|
output: {
|
||||||
|
filename: '[name].[chunkhash].bundle.js',
|
||||||
|
sourceMapFilename: '[name].[chunkhash].bundle.map',
|
||||||
|
chunkFilename: '[id].[chunkhash].chunk.js'
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
// new webpack.LoaderOptionsPlugin({
|
||||||
|
// minimize: true,
|
||||||
|
// debug: false
|
||||||
|
// }),
|
||||||
|
new WebpackMd5Hash(),
|
||||||
|
new webpack.optimize.UglifyJsPlugin({
|
||||||
|
beautify: false,
|
||||||
|
comments: false,
|
||||||
|
sourceMap: true
|
||||||
|
})
|
||||||
|
]
|
||||||
|
};
|
@ -0,0 +1,73 @@
|
|||||||
|
var path = require('path');
|
||||||
|
var webpack = require('webpack');
|
||||||
|
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||||
|
var extractCSS = new ExtractTextPlugin('vendor.css');
|
||||||
|
var isDevelopment = process.env.ASPNETCORE_ENVIRONMENT === 'Development';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.js']
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{ test: /\.(png|woff|woff2|eot|ttf|svg)$/, loader: 'url-loader?limit=100000' },
|
||||||
|
{ test: /\.scss$/i, loader: extractCSS.extract(['css?minimize', 'sass']) },
|
||||||
|
{ test: /\.json$/, loader: 'json-loader' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
entry: {
|
||||||
|
// polyfills: [
|
||||||
|
// 'core-js/es6/symbol',
|
||||||
|
// 'core-js/es6/object',
|
||||||
|
// 'core-js/es6/function',
|
||||||
|
// 'core-js/es6/parse-int',
|
||||||
|
// 'core-js/es6/parse-float',
|
||||||
|
// 'core-js/es6/number',
|
||||||
|
// 'core-js/es6/math',
|
||||||
|
// 'core-js/es6/string',
|
||||||
|
// 'core-js/es6/date',
|
||||||
|
// 'core-js/es6/array',
|
||||||
|
// 'core-js/es6/regexp',
|
||||||
|
// 'core-js/es6/map',
|
||||||
|
// 'core-js/es6/set',
|
||||||
|
// 'core-js/es6/reflect',
|
||||||
|
// 'core-js/es7/reflect',
|
||||||
|
// 'zone.js/dist/zone'
|
||||||
|
// ],
|
||||||
|
vendor: [
|
||||||
|
'font-awesome/scss/font-awesome.scss',
|
||||||
|
'bootstrap/scss/bootstrap.scss',
|
||||||
|
'@angular/common',
|
||||||
|
'@angular/compiler',
|
||||||
|
'@angular/core',
|
||||||
|
'@angular/http',
|
||||||
|
'@angular/forms',
|
||||||
|
'@angular/platform-browser',
|
||||||
|
'@angular/platform-browser-dynamic',
|
||||||
|
'@angular/router'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
path: path.join(__dirname, '../wwwroot', 'dist'),
|
||||||
|
filename: '[name].js',
|
||||||
|
library: '[name]_[hash]',
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
extractCSS,
|
||||||
|
// To eliminate warning
|
||||||
|
// https://github.com/AngularClass/angular2-webpack-starter/issues/993
|
||||||
|
new webpack.ContextReplacementPlugin(
|
||||||
|
/angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
|
||||||
|
__dirname
|
||||||
|
),
|
||||||
|
new webpack.DllPlugin({
|
||||||
|
path: path.join(__dirname, '../wwwroot', 'dist', '[name]-manifest.json'),
|
||||||
|
name: '[name]_[hash]'
|
||||||
|
})
|
||||||
|
].concat(isDevelopment ? [] : [
|
||||||
|
new webpack.optimize.UglifyJsPlugin({
|
||||||
|
beautify: false,
|
||||||
|
comments: false
|
||||||
|
})
|
||||||
|
])
|
||||||
|
};
|
78
src/Web/WebSPA/eShopOnContainers.WebSPA/docker-compose.yml
Normal file
78
src/Web/WebSPA/eShopOnContainers.WebSPA/docker-compose.yml
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
version: '2'
|
||||||
|
|
||||||
|
services:
|
||||||
|
webspa:
|
||||||
|
image: eshop/webspa
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
environment:
|
||||||
|
- CatalogUrl=http://catalog.api
|
||||||
|
- OrderingUrl=http://ordering.api
|
||||||
|
ports:
|
||||||
|
- "5104:80"
|
||||||
|
depends_on:
|
||||||
|
- catalog.api
|
||||||
|
- identity.data
|
||||||
|
|
||||||
|
catalog.api:
|
||||||
|
image: eshop/catalog.api
|
||||||
|
environment:
|
||||||
|
- ConnectionString=Server=catalog.data;Initial Catalog=CatalogData;User Id=sa;Password=Pass@word
|
||||||
|
expose:
|
||||||
|
- "80"
|
||||||
|
ports:
|
||||||
|
- "5101:80"
|
||||||
|
depends_on:
|
||||||
|
- catalog.data
|
||||||
|
|
||||||
|
catalog.data:
|
||||||
|
image: eshop/mssql-server-private-preview
|
||||||
|
environment:
|
||||||
|
- SA_PASSWORD=Pass@word
|
||||||
|
- ACCEPT_EULA=Y
|
||||||
|
ports:
|
||||||
|
- "5434:1433"
|
||||||
|
|
||||||
|
ordering.api:
|
||||||
|
image: eshop/ordering.api
|
||||||
|
environment:
|
||||||
|
- ConnectionString=Server=ordering.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word
|
||||||
|
ports:
|
||||||
|
- "5102:80"
|
||||||
|
# (Go to Production): For secured/final deployment, remove Ports mapping and
|
||||||
|
# leave just the internal expose section
|
||||||
|
# expose:
|
||||||
|
# - "80"
|
||||||
|
extra_hosts:
|
||||||
|
- "CESARDLBOOKVHD:10.0.75.1"
|
||||||
|
depends_on:
|
||||||
|
- ordering.data
|
||||||
|
|
||||||
|
ordering.data:
|
||||||
|
image: eshop/ordering.data.sqlserver.linux
|
||||||
|
ports:
|
||||||
|
- "5432:1433"
|
||||||
|
|
||||||
|
identity.data:
|
||||||
|
image: eshop/mssql-server-private-preview
|
||||||
|
environment:
|
||||||
|
- SA_PASSWORD=Pass@word
|
||||||
|
- ACCEPT_EULA=Y
|
||||||
|
ports:
|
||||||
|
- "5433:1433"
|
||||||
|
|
||||||
|
basket.api:
|
||||||
|
image: eshop/basket.api
|
||||||
|
environment:
|
||||||
|
- ConnectionString=basket.data
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
ports:
|
||||||
|
- "5103:80"
|
||||||
|
depends_on:
|
||||||
|
- basket.data
|
||||||
|
|
||||||
|
basket.data:
|
||||||
|
image: redis
|
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||||
|
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||||
|
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>9842db3a-1391-48c7-a49c-2fabd0a18ac2</ProjectGuid>
|
||||||
|
<RootNamespace>eShopOnContainers.WebSPA</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VSToolsPath)\DotNet.Web\Microsoft.DotNet.Web.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||||
|
</Project>
|
3
src/Web/WebSPA/eShopOnContainers.WebSPA/hosting.json
Normal file
3
src/Web/WebSPA/eShopOnContainers.WebSPA/hosting.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"server.urls": "http://localhost:5000;http://localhost:5001"
|
||||||
|
}
|
109
src/Web/WebSPA/eShopOnContainers.WebSPA/package.json
Normal file
109
src/Web/WebSPA/eShopOnContainers.WebSPA/package.json
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
{
|
||||||
|
"name": "eshopaspnetnetcoredockerspa",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"private": true,
|
||||||
|
"keywords": [
|
||||||
|
"aspnetcore",
|
||||||
|
"entityframework core",
|
||||||
|
"angular2",
|
||||||
|
"webpack2",
|
||||||
|
"typescript2",
|
||||||
|
"bootstrap4",
|
||||||
|
"docker"
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"name": "Microsoft",
|
||||||
|
"email": "cesardl@microsoft.com"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"rimraf": "rimraf",
|
||||||
|
"tslint": "tslint",
|
||||||
|
"typedoc": "typedoc",
|
||||||
|
"typings": "typings",
|
||||||
|
"webpack": "webpack",
|
||||||
|
"clean": "npm cache clean && npm run rimraf -- node_modules doc typings coverage wwwroot/dist",
|
||||||
|
"clean:dist": "npm run rimraf -- wwwroot/dist",
|
||||||
|
"preclean:install": "npm run clean",
|
||||||
|
"clean:install": "npm set progress=false && npm install",
|
||||||
|
"preclean:start": "npm run clean",
|
||||||
|
"clean:start": "npm start",
|
||||||
|
"build:vendor": "node node_modules/webpack/bin/webpack.js --config config/webpack.config.vendor.js",
|
||||||
|
"build:main": "node node_modules/webpack/bin/webpack.js --config config/webpack.config.js",
|
||||||
|
"setdev": "set ASPNETCORE_ENVIRONMENT=Development",
|
||||||
|
"setprod": "set ASPNETCORE_ENVIRONMENT=Production",
|
||||||
|
"build:dev": "npm run setdev && npm run clean:dist && npm run build:vendor && npm run build:main",
|
||||||
|
"build:prod": "npm run setprod && npm run clean:dist && npm run build:vendor && npm run build:main",
|
||||||
|
"lint": "npm run tslint \"Client/**/*.ts\"",
|
||||||
|
"docs": "npm run typedoc -- --options typedoc.json --exclude '**/*.spec.ts' ./Client/",
|
||||||
|
"version": "npm run build",
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@angular/common": "2.1.2",
|
||||||
|
"@angular/compiler": "2.1.2",
|
||||||
|
"@angular/compiler-cli": "2.1.2",
|
||||||
|
"@angular/core": "2.1.2",
|
||||||
|
"@angular/forms": "2.1.2",
|
||||||
|
"@angular/http": "2.1.2",
|
||||||
|
"@angular/platform-browser": "2.1.2",
|
||||||
|
"@angular/platform-browser-dynamic": "2.1.2",
|
||||||
|
"@angular/platform-server": "2.1.2",
|
||||||
|
"@angular/router": "3.1.2",
|
||||||
|
"@ng-bootstrap/ng-bootstrap": "1.0.0-alpha.11",
|
||||||
|
"aspnet-prerendering": "1.0.7",
|
||||||
|
"aspnet-webpack": "1.0.24",
|
||||||
|
"bootstrap": "4.0.0-alpha.5",
|
||||||
|
"core-js": "2.4.1",
|
||||||
|
"font-awesome": "4.6.3",
|
||||||
|
"isomorphic-fetch": "2.2.1",
|
||||||
|
"ng2-translate": "4.0.0",
|
||||||
|
"normalize.css": "5.0.0",
|
||||||
|
"preboot": "4.5.2",
|
||||||
|
"rxjs": "5.0.0-beta.12",
|
||||||
|
"zone.js": "0.6.26"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/core-js": "0.9.34",
|
||||||
|
"@types/hammerjs": "2.0.33",
|
||||||
|
"@types/jasmine": "2.5.35",
|
||||||
|
"@types/node": "6.0.45",
|
||||||
|
"@types/protractor": "1.5.20",
|
||||||
|
"@types/selenium-webdriver": "2.44.26",
|
||||||
|
"@types/sinon": "1.16.31",
|
||||||
|
"@types/source-map": "0.1.28",
|
||||||
|
"@types/uglify-js": "2.6.28",
|
||||||
|
"@types/webpack": "1.12.35",
|
||||||
|
"angular2-template-loader": "0.6.0",
|
||||||
|
"awesome-typescript-loader": "2.2.4",
|
||||||
|
"codelyzer": "1.0.0-beta.3",
|
||||||
|
"copy-webpack-plugin": "^4.0.0",
|
||||||
|
"css": "2.2.1",
|
||||||
|
"css-loader": "0.25.0",
|
||||||
|
"es6-promise": "3.2.1",
|
||||||
|
"es6-promise-loader": "1.0.2",
|
||||||
|
"expose-loader": "0.7.1",
|
||||||
|
"extendify": "1.0.0",
|
||||||
|
"extract-text-webpack-plugin": "2.0.0-beta.4",
|
||||||
|
"file-loader": "0.9.0",
|
||||||
|
"html-loader": "0.4.4",
|
||||||
|
"html-webpack-plugin": "^2.24.1",
|
||||||
|
"json-loader": "0.5.4",
|
||||||
|
"node-sass": "3.9.3",
|
||||||
|
"parse5": "2.1.5",
|
||||||
|
"raw-loader": "0.5.1",
|
||||||
|
"rimraf": "2.5.4",
|
||||||
|
"sass-loader": "4.0.2",
|
||||||
|
"source-map-loader": "0.1.5",
|
||||||
|
"style-loader": "0.13.1",
|
||||||
|
"ts-helpers": "1.1.1",
|
||||||
|
"ts-node": "1.4.3",
|
||||||
|
"tslint": "3.15.1",
|
||||||
|
"tslint-loader": "2.1.5",
|
||||||
|
"typedoc": "0.5.0",
|
||||||
|
"typescript": "2.0.6",
|
||||||
|
"url-loader": "0.5.7",
|
||||||
|
"webpack": "2.1.0-beta.25",
|
||||||
|
"webpack-externals-plugin": "1.0.0",
|
||||||
|
"webpack-hot-middleware": "2.13.0",
|
||||||
|
"webpack-md5-hash": "0.0.5"
|
||||||
|
}
|
||||||
|
}
|
116
src/Web/WebSPA/eShopOnContainers.WebSPA/project.json
Normal file
116
src/Web/WebSPA/eShopOnContainers.WebSPA/project.json
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
{
|
||||||
|
"userSecretsId": "aspnetcorespa-c23d27a4-eb88-4b18-9b77-2a93f3b15119",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.NETCore.App": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"type": "platform"
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Configuration.UserSecrets": "1.0.0",
|
||||||
|
"Microsoft.AspNetCore.Authentication.Cookies": "1.0.0",
|
||||||
|
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||||
|
"Microsoft.AspNetCore.Mvc": "1.0.1",
|
||||||
|
"Microsoft.AspNetCore.Cors": "1.0.0",
|
||||||
|
"Microsoft.AspNetCore.Antiforgery": "1.0.1",
|
||||||
|
"Microsoft.AspNetCore.Authorization": "1.0.0",
|
||||||
|
"Newtonsoft.Json": "9.0.1",
|
||||||
|
"Webpack": "3.0.0",
|
||||||
|
"Microsoft.AspNetCore.AngularServices": "1.0.0-beta-000014",
|
||||||
|
"Microsoft.AspNetCore.Razor.Tools": {
|
||||||
|
"version": "1.0.0-preview2-final",
|
||||||
|
"type": "build"
|
||||||
|
},
|
||||||
|
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
|
||||||
|
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
|
||||||
|
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
|
||||||
|
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
|
||||||
|
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||||
|
"Microsoft.Extensions.Logging": "1.0.0",
|
||||||
|
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||||
|
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
||||||
|
"Microsoft.VisualStudio.Web.CodeGeneration.Tools": {
|
||||||
|
"version": "1.0.0-preview2-final",
|
||||||
|
"type": "build"
|
||||||
|
},
|
||||||
|
"Microsoft.VisualStudio.Web.CodeGenerators.Mvc": {
|
||||||
|
"version": "1.0.0-preview2-final",
|
||||||
|
"type": "build"
|
||||||
|
},
|
||||||
|
"Microsoft.AspNetCore.Http.Abstractions": "1.0.0"
|
||||||
|
},
|
||||||
|
"tools": {
|
||||||
|
"Microsoft.DotNet.Watcher.Tools": {
|
||||||
|
"version": "1.0.0-*",
|
||||||
|
"imports": "portable-net451+win8"
|
||||||
|
},
|
||||||
|
"Microsoft.AspNetCore.Razor.Tools": {
|
||||||
|
"version": "1.0.0-preview2-final",
|
||||||
|
"imports": "portable-net45+win8+dnxcore50"
|
||||||
|
},
|
||||||
|
"Microsoft.AspNetCore.Server.IISIntegration.Tools": {
|
||||||
|
"version": "1.0.0-preview2-final",
|
||||||
|
"imports": "portable-net45+win8+dnxcore50"
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.SecretManager.Tools": {
|
||||||
|
"version": "1.0.0-preview2-final",
|
||||||
|
"imports": "portable-net45+win8+dnxcore50"
|
||||||
|
},
|
||||||
|
"Microsoft.VisualStudio.Web.CodeGeneration.Tools": {
|
||||||
|
"version": "1.0.0-preview2-final",
|
||||||
|
"imports": [
|
||||||
|
"portable-net45+win8+dnxcore50",
|
||||||
|
"portable-net45+win8"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"frameworks": {
|
||||||
|
"netcoreapp1.0": {
|
||||||
|
"imports": [
|
||||||
|
"dotnet5.6",
|
||||||
|
"portable-net45+win8"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"buildOptions": {
|
||||||
|
"emitEntryPoint": true,
|
||||||
|
"preserveCompilationContext": true,
|
||||||
|
"compile": {
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"Client"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"debugType": "portable"
|
||||||
|
},
|
||||||
|
"runtimeOptions": {
|
||||||
|
"configProperties": {
|
||||||
|
"System.GC.Server": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"publishOptions": {
|
||||||
|
"include": [
|
||||||
|
"appsettings.json",
|
||||||
|
"Client",
|
||||||
|
"typings",
|
||||||
|
"Views",
|
||||||
|
"tsconfig.json",
|
||||||
|
"tsd.json",
|
||||||
|
"web.config",
|
||||||
|
"config",
|
||||||
|
"wwwroot",
|
||||||
|
"dockerfile"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
// "prepublish": [
|
||||||
|
// "npm install",
|
||||||
|
// "node node_modules/webpack/bin/webpack.js --config config/webpack.config.vendor.js",
|
||||||
|
// "node node_modules/webpack/bin/webpack.js --config config/webpack.config.js"
|
||||||
|
// ],
|
||||||
|
"postpublish": [
|
||||||
|
"dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"tooling": {
|
||||||
|
"defaultNamespace": "eShopOnContainers.SPA"
|
||||||
|
}
|
||||||
|
}
|
42
src/Web/WebSPA/eShopOnContainers.WebSPA/tsconfig.json
Normal file
42
src/Web/WebSPA/eShopOnContainers.WebSPA/tsconfig.json
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"module": "commonjs",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"declaration": false,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"strictNullChecks": false,
|
||||||
|
"baseUrl": "./src",
|
||||||
|
"paths": {},
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"es6"
|
||||||
|
],
|
||||||
|
"types": [
|
||||||
|
"hammerjs",
|
||||||
|
"jasmine",
|
||||||
|
"node",
|
||||||
|
"protractor",
|
||||||
|
"selenium-webdriver",
|
||||||
|
"source-map",
|
||||||
|
"uglify-js",
|
||||||
|
"webpack"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"wwwroot"
|
||||||
|
],
|
||||||
|
"awesomeTypescriptLoaderOptions": {
|
||||||
|
"forkChecker": true,
|
||||||
|
"useWebpackText": true
|
||||||
|
},
|
||||||
|
"compileOnSave": false,
|
||||||
|
"buildOnSave": false,
|
||||||
|
"atom": {
|
||||||
|
"rewriteTsconfig": false
|
||||||
|
}
|
||||||
|
}
|
178
src/Web/WebSPA/eShopOnContainers.WebSPA/tslint.json
Normal file
178
src/Web/WebSPA/eShopOnContainers.WebSPA/tslint.json
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
{
|
||||||
|
"rulesDirectory": [
|
||||||
|
"node_modules/codelyzer"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"directive-selector-name": [
|
||||||
|
true,
|
||||||
|
"camelCase"
|
||||||
|
],
|
||||||
|
"component-selector-name": [
|
||||||
|
true,
|
||||||
|
"kebab-case"
|
||||||
|
],
|
||||||
|
"directive-selector-type": [
|
||||||
|
true,
|
||||||
|
"attribute"
|
||||||
|
],
|
||||||
|
"component-selector-type": [
|
||||||
|
true,
|
||||||
|
"element"
|
||||||
|
],
|
||||||
|
"directive-selector-prefix": [
|
||||||
|
true,
|
||||||
|
"appd"
|
||||||
|
],
|
||||||
|
"component-selector-prefix": [
|
||||||
|
true,
|
||||||
|
"appc"
|
||||||
|
],
|
||||||
|
"use-input-property-decorator": true,
|
||||||
|
"use-output-property-decorator": true,
|
||||||
|
"use-host-property-decorator": true,
|
||||||
|
"no-attribute-parameter-decorator": true,
|
||||||
|
"no-input-rename": true,
|
||||||
|
"no-output-rename": true,
|
||||||
|
"no-forward-ref": true,
|
||||||
|
"use-life-cycle-interface": true,
|
||||||
|
"use-pipe-transform-interface": true,
|
||||||
|
"pipe-naming": [
|
||||||
|
true,
|
||||||
|
"camelCase",
|
||||||
|
"appf"
|
||||||
|
],
|
||||||
|
"component-class-suffix": true,
|
||||||
|
"directive-class-suffix": true,
|
||||||
|
"import-destructuring-spacing": true,
|
||||||
|
"member-access": false,
|
||||||
|
"member-ordering": [
|
||||||
|
true,
|
||||||
|
"public-before-private",
|
||||||
|
"static-before-instance",
|
||||||
|
"variables-before-functions"
|
||||||
|
],
|
||||||
|
"no-any": false,
|
||||||
|
"no-inferrable-types": false,
|
||||||
|
"no-internal-module": true,
|
||||||
|
"no-var-requires": false,
|
||||||
|
"typedef": false,
|
||||||
|
"typedef-whitespace": [
|
||||||
|
true,
|
||||||
|
{
|
||||||
|
"call-signature": "nospace",
|
||||||
|
"index-signature": "nospace",
|
||||||
|
"parameter": "nospace",
|
||||||
|
"property-declaration": "nospace",
|
||||||
|
"variable-declaration": "nospace"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"call-signature": "space",
|
||||||
|
"index-signature": "space",
|
||||||
|
"parameter": "space",
|
||||||
|
"property-declaration": "space",
|
||||||
|
"variable-declaration": "space"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ban": false,
|
||||||
|
"curly": false,
|
||||||
|
"forin": true,
|
||||||
|
"label-position": true,
|
||||||
|
"label-undefined": true,
|
||||||
|
"no-arg": true,
|
||||||
|
"no-bitwise": true,
|
||||||
|
"no-conditional-assignment": true,
|
||||||
|
"no-console": [
|
||||||
|
true,
|
||||||
|
"debug",
|
||||||
|
"info",
|
||||||
|
"time",
|
||||||
|
"timeEnd",
|
||||||
|
"trace"
|
||||||
|
],
|
||||||
|
"no-construct": true,
|
||||||
|
"no-debugger": true,
|
||||||
|
"no-duplicate-key": true,
|
||||||
|
"no-duplicate-variable": true,
|
||||||
|
"no-empty": false,
|
||||||
|
"no-eval": true,
|
||||||
|
"no-null-keyword": true,
|
||||||
|
"no-shadowed-variable": true,
|
||||||
|
"no-string-literal": true,
|
||||||
|
"no-switch-case-fall-through": true,
|
||||||
|
"no-unreachable": true,
|
||||||
|
"no-unused-expression": true,
|
||||||
|
"no-unused-variable": false,
|
||||||
|
"no-use-before-declare": true,
|
||||||
|
"no-var-keyword": true,
|
||||||
|
"radix": true,
|
||||||
|
"switch-default": true,
|
||||||
|
"triple-equals": [
|
||||||
|
true,
|
||||||
|
"allow-null-check"
|
||||||
|
],
|
||||||
|
"use-strict": [
|
||||||
|
true,
|
||||||
|
"check-module"
|
||||||
|
],
|
||||||
|
"eofline": true,
|
||||||
|
"indent": [
|
||||||
|
true,
|
||||||
|
"spaces"
|
||||||
|
],
|
||||||
|
"max-line-length": [
|
||||||
|
true,
|
||||||
|
200
|
||||||
|
],
|
||||||
|
"no-require-imports": false,
|
||||||
|
"no-trailing-whitespace": true,
|
||||||
|
"object-literal-sort-keys": false,
|
||||||
|
"trailing-comma": [
|
||||||
|
true,
|
||||||
|
{
|
||||||
|
"multiline": "never",
|
||||||
|
"singleline": "never"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"align": false,
|
||||||
|
"class-name": true,
|
||||||
|
"comment-format": [
|
||||||
|
true,
|
||||||
|
"check-space"
|
||||||
|
],
|
||||||
|
"interface-name": false,
|
||||||
|
"jsdoc-format": true,
|
||||||
|
"no-consecutive-blank-lines": false,
|
||||||
|
"no-constructor-vars": false,
|
||||||
|
"one-line": [
|
||||||
|
true,
|
||||||
|
"check-open-brace",
|
||||||
|
"check-catch",
|
||||||
|
"check-else",
|
||||||
|
"check-finally",
|
||||||
|
"check-whitespace"
|
||||||
|
],
|
||||||
|
"quotemark": [
|
||||||
|
true,
|
||||||
|
"single",
|
||||||
|
"avoid-escape"
|
||||||
|
],
|
||||||
|
"semicolon": [
|
||||||
|
true,
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"variable-name": [
|
||||||
|
true,
|
||||||
|
"check-format",
|
||||||
|
"allow-leading-underscore",
|
||||||
|
"ban-keywords"
|
||||||
|
],
|
||||||
|
"whitespace": [
|
||||||
|
true,
|
||||||
|
"check-branch",
|
||||||
|
"check-decl",
|
||||||
|
"check-operator",
|
||||||
|
"check-separator",
|
||||||
|
"check-type"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
15
src/Web/WebSPA/eShopOnContainers.WebSPA/typedoc.json
Normal file
15
src/Web/WebSPA/eShopOnContainers.WebSPA/typedoc.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"mode": "modules",
|
||||||
|
"out": "doc",
|
||||||
|
"theme": "default",
|
||||||
|
"ignoreCompilerErrors": "true",
|
||||||
|
"experimentalDecorators": "true",
|
||||||
|
"emitDecoratorMetadata": "true",
|
||||||
|
"target": "ES5",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"preserveConstEnums": "true",
|
||||||
|
"stripInternal": "true",
|
||||||
|
"suppressExcessPropertyErrors": "true",
|
||||||
|
"suppressImplicitAnyIndexErrors": "true",
|
||||||
|
"module": "commonjs"
|
||||||
|
}
|
14
src/Web/WebSPA/eShopOnContainers.WebSPA/web.config
Normal file
14
src/Web/WebSPA/eShopOnContainers.WebSPA/web.config
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Configure your application settings in appsettings.json. Learn more at https://go.microsoft.com/fwlink/?LinkId=786380
|
||||||
|
-->
|
||||||
|
|
||||||
|
<system.webServer>
|
||||||
|
<handlers>
|
||||||
|
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified"/>
|
||||||
|
</handlers>
|
||||||
|
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false"/>
|
||||||
|
</system.webServer>
|
||||||
|
</configuration>
|
BIN
src/Web/WebSPA/eShopOnContainers.WebSPA/wwwroot/favicon.ico
Normal file
BIN
src/Web/WebSPA/eShopOnContainers.WebSPA/wwwroot/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<system.webServer>
|
||||||
|
<handlers>
|
||||||
|
<add name="httpPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified"/>
|
||||||
|
</handlers>
|
||||||
|
<httpPlatform processPath="%DNX_PATH%" arguments="%DNX_ARGS%" stdoutLogEnabled="false"/>
|
||||||
|
</system.webServer>
|
||||||
|
</configuration>
|
Loading…
x
Reference in New Issue
Block a user