diff --git a/.env b/.env index e677e97df..f77f64682 100644 --- a/.env +++ b/.env @@ -8,8 +8,8 @@ ESHOP_EXTERNAL_DNS_NAME_OR_IP=localhost ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP=10.121.122.92 #ESHOP_AZURE_REDIS_BASKET_DB= -#ESHOP_AZURE_STORAGE_CATALOG= -#ESHOP_AZURE_STORAGE_MARKETING= +#ESHOP_AZURE_STORAGE_CATALOG_URL= +#ESHOP_AZURE_STORAGE_MARKETING_URL= #ESHOP_AZURE_SERVICE_BUS= #ESHOP_AZURE_COSMOSDB= #ESHOP_AZURE_CATALOG_DB= diff --git a/.gitattributes b/.gitattributes index 1ff0c4230..ef8281262 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,6 +2,7 @@ # Set default behavior to automatically normalize line endings. ############################################################################### * text=auto +*.sh text eol=lf ############################################################################### # Set default behavior for command prompt diff. diff --git a/README.md b/README.md index ae28f7951..9271da0b7 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,9 @@ Sample .NET Core reference application, powered by Microsoft, based on a simplified microservices architecture and Docker containers.

**Note for Pull Requests**: We accept pull request from the community. When doing it, please do it onto the DEV branch which is the consolidated work-in-progress branch. Do not request it onto Master, if possible. +## Moving to .NET Core 2.0 "wave" +NOTE: During August/September 2017 we'll be moving the solution to .NET Core "wave". Not just compilation but also new recommended code in EF Core 2.0, ASP.NET Core 2.0, and other new related versions. + >**PLEASE** Read our [branch guide](./branch-guide.md) to know about our branching policy > ### DISCLAIMER diff --git a/cli-linux/build-bits-linux.sh b/cli-linux/build-bits-linux.sh index 75ace0938..bcb3b9f06 100755 --- a/cli-linux/build-bits-linux.sh +++ b/cli-linux/build-bits-linux.sh @@ -16,7 +16,6 @@ declare -a projectList=( "$path/Services/Location/Locations.API" "$path/Services/Marketing/Marketing.API" "$path/Services/Payment/Payment.API" - "$path/Services/GracePeriod/GracePeriodManager" "$path/Web/WebMVC" "$path/Web/WebStatus" ) @@ -32,9 +31,9 @@ do pushd $path/$project rm -rf obj/Docker/publish echo -e "\e[33m\tRestoring project $project" - dotnet restore + dotnet restore --verbosity minimal echo -e "\e[33m\tBuilding and publishing $project" - dotnet publish -o obj/Docker/publish + dotnet publish -c Release -o obj/Docker/publish --verbosity minimal popd done diff --git a/cli-mac/build-bits.sh b/cli-mac/build-bits.sh index 681c3605d..fdf61e359 100755 --- a/cli-mac/build-bits.sh +++ b/cli-mac/build-bits.sh @@ -25,7 +25,7 @@ do echo -e "\e[33m\tRestoring project" dotnet restore echo -e "\e[33m\tBuilding and publishing projects" - dotnet publish -o obj/Docker/publish + dotnet publish -o obj/Docker/publish -c Release popd done diff --git a/cli-windows/build-bits.ps1 b/cli-windows/build-bits.ps1 index 272227b3d..38cdfddcd 100644 --- a/cli-windows/build-bits.ps1 +++ b/cli-windows/build-bits.ps1 @@ -8,6 +8,9 @@ if ([string]::IsNullOrEmpty($rootPath)) { } Write-Host "Root path used is $rootPath" -ForegroundColor Yellow +workflow BuildAndPublish { + param ([string] $rootPath + ) $projectPaths = @{Path="$rootPath\src\Web\WebMVC";Prj="WebMVC.csproj"}, @{Path="$rootPath\src\Web\WebSPA";Prj="WebSPA.csproj"}, @@ -15,25 +18,25 @@ $projectPaths = @{Path="$rootPath\src\Services\Catalog\Catalog.API";Prj="Catalog.API.csproj"}, @{Path="$rootPath\src\Services\Ordering\Ordering.API";Prj="Ordering.API.csproj"}, @{Path="$rootPath\src\Services\Basket\Basket.API";Prj="Basket.API.csproj"}, - @{Path="$rootPath\src\Services\GracePeriod\GracePeriodManager";Prj="GracePeriodManager.csproj"}, @{Path="$rootPath\src\Services\Location\Locations.API";Prj="Locations.API.csproj"}, @{Path="$rootPath\src\Services\Marketing\Marketing.API";Prj="Marketing.API.csproj"}, @{Path="$rootPath\src\Services\Payment\Payment.API";Prj="Payment.API.csproj"}, @{Path="$rootPath\src\Web\WebStatus";Prj="WebStatus.csproj"} -$projectPaths | foreach { - $projectPath = $_.Path - $projectFile = $_.Prj - $outPath = $_.Path + "\obj\Docker\publish" - $projectPathAndFile = "$projectPath\$projectFile" - Write-Host "Deleting old publish files in $outPath" -ForegroundColor Yellow - remove-item -path $outPath -Force -Recurse -ErrorAction SilentlyContinue - Write-Host "Publishing $projectPathAndFile to $outPath" -ForegroundColor Yellow - dotnet restore $projectPathAndFile - dotnet build $projectPathAndFile - dotnet publish $projectPathAndFile -o $outPath + foreach -parallel ($item in $projectPaths) { + $projectPath = $item.Path + $projectFile = $item.Prj + $outPath = $item.Path + "\obj\Docker\publish" + $projectPathAndFile = "$projectPath\$projectFile" + #Write-Host "Deleting old publish files in $outPath" -ForegroundColor Yellow + remove-item -path $outPath -Force -Recurse -ErrorAction SilentlyContinue + #Write-Host "Publishing $projectPathAndFile to $outPath" -ForegroundColor Yellow + dotnet build $projectPathAndFile + dotnet publish $projectPathAndFile -o $outPath -c Release + } } +BuildAndPublish $rootPath ######################################################################################## # Delete old eShop Docker images diff --git a/cli-windows/delete-vs-and-eshop-images.ps1 b/cli-windows/delete-vs-and-eshop-images.ps1 new file mode 100644 index 000000000..f37dc6ea4 --- /dev/null +++ b/cli-windows/delete-vs-and-eshop-images.ps1 @@ -0,0 +1,46 @@ + # Delete all containers + Write-Host "Deleting all running containers in the local Docker Host" + docker rm $(docker ps -a -q) -f + +$eShopImagesToDelete = docker images --filter=reference="eshop/*" -q +If (-Not $eShopImagesToDelete) {Write-Host "Not deleting eShop images as there are no eShop images in the current local Docker repo."} +Else +{ + # Delete all eshop images + Write-Host "Deleting eShop images in local Docker repo" + Write-Host $eShopImagesToDelete + docker rmi $(docker images --filter=reference="eshop/*" -q) -f +} + +$VSImagesToDelete = docker images --filter=reference="catalog.api:dev" -q +If (-Not $VSImagesToDelete) {Write-Host "Not deleting VS images as there are no VS images in the current local Docker repo."} +Else +{ + # Delete all eshop images + Write-Host "Deleting images created by VS in local Docker repo" + Write-Host $VSImagesToDelete + docker rmi $(docker images --filter=reference="*:dev" -q) -f + + #docker rmi $(docker images --filter=reference="eshop/payment.api:dev" -q) -f + #docker rmi $(docker images --filter=reference="eshop/webspa:dev" -q) -f + #docker rmi $(docker images --filter=reference="eshop/webmvc:dev" -q) -f + #docker rmi $(docker images --filter=reference="eshop/catalog.api:dev" -q) -f + #docker rmi $(docker images --filter=reference="eshop/marketing.api:dev" -q) -f + #docker rmi $(docker images --filter=reference="eshop/ordering.api:dev" -q) -f + #docker rmi $(docker images --filter=reference="eshop/basket.api:dev" -q) -f + #docker rmi $(docker images --filter=reference="eshop/identity.api:dev" -q) -f + #docker rmi $(docker images --filter=reference="eshop/locations.api:dev" -q) -f + #docker rmi $(docker images --filter=reference="eshop/webstatus:dev" -q) -f +} + +# DELETE ALL IMAGES AND CONTAINERS + +# Delete all containers +# docker rm $(docker ps -a -q) -f + +# Delete all images +# docker rmi $(docker images -q) + +#Filter by image name (Has to be complete, cannot be a wildcard) +#docker ps -q --filter=ancestor=eshop/identity.api:dev + diff --git a/cli-windows/start-windows-containers.ps1 b/cli-windows/start-windows-containers.ps1 index 300c63568..56b7a34e9 100644 --- a/cli-windows/start-windows-containers.ps1 +++ b/cli-windows/start-windows-containers.ps1 @@ -1,9 +1,16 @@ -Param([string] $rootPath) +Param( + [parameter(Mandatory=$false)][string] $rootPath, + [parameter(Mandatory=$false)][bool]$buildBits=$true +) + $scriptPath = Split-Path $script:MyInvocation.MyCommand.Path if ([string]::IsNullOrEmpty($rootPath)) { $rootPath = "$scriptPath\.." } Write-Host "Root path used is $rootPath" -ForegroundColor Yellow -& .\build-bits.ps1 -rootPath $rootPath -docker-compose -f "$rootPath\docker-compose-windows.yml" -f "$rootPath\docker-compose-windows.override.yml" up + +if ($buildBits) { + & $scriptPath\build-bits.ps1 -rootPath $rootPath +} +docker-compose -f "$rootPath\docker-compose-windows.yml" -f "$rootPath\docker-compose.override.yml" up diff --git a/deploy/az/azurefunctions/azurefunctionsdeploy.parameters.json b/deploy/az/azurefunctions/azurefunctionsdeploy.parameters.json index 8472e9998..9ef07000d 100644 --- a/deploy/az/azurefunctions/azurefunctionsdeploy.parameters.json +++ b/deploy/az/azurefunctions/azurefunctionsdeploy.parameters.json @@ -1,5 +1,9 @@ { "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": {} + "contentVersion": "1.0.0.0", + "parameters": { + "SitesEshopfunctionsName": { + "value": "eshopfunctionsapp" + } + } } \ No newline at end of file diff --git a/deploy/az/azurefunctions/readme.md b/deploy/az/azurefunctions/readme.md index 5716bf615..6ce3630b2 100644 --- a/deploy/az/azurefunctions/readme.md +++ b/deploy/az/azurefunctions/readme.md @@ -4,20 +4,22 @@ The ARM template `azurefunctionsdeploy.json` and its parameter file (`azurefunct ## Editing azurefunctionsdeploy.parameters.json file -You can edit the `azurefunctionsdeploy.parameters.parameters.json` file to set your values, but is not needed. +You can edit the `azurefunctionsdeploy.parameters.parameters.json` file to set your values, but is not needed. The only parameter that can be set is: + +1. `SitesEshopfunctionsName` is a string that is used to create the Azure function app name. ## Deploy the template Once parameter file is edited you can deploy it using [create-resources script](../readme.md). -i. e. if you are in windows, to deploy sql databases in a new resourcegroup located in westus, go to `deploy\az` folder and type: +i. e. if you are in Windows, to deploy the Azure Functions environment in a new resourcegroup located in westus, go to `deploy\az` folder and type: ``` create-resources.cmd azurefunctions\azurefunctionsdeploy newResourceGroup -c westus ``` ## Deploy Marketing azure function with Visual Studio. -Alternatively, instead of using ARM templates, you can deploy Marketing azure function directly by publishing the project Marketing-functions in eShopOnContainers-AzureFunctions.sln with Visual Studio publish tool. +You need to deploy the Marketing azure function from Visual Studio 2017 15.3 from the the Marketing-functions project in the solution eShopOnContainers-AzureFunctions.sln (Visual Studio publish tool). ## Setting Azure function configurations diff --git a/deploy/az/cosmos/readme.md b/deploy/az/cosmos/readme.md new file mode 100644 index 000000000..ae040ae95 --- /dev/null +++ b/deploy/az/cosmos/readme.md @@ -0,0 +1,31 @@ +# Deploying Azure Cosmosdb + +The ARM template `deploycosmos.json` and its parameter file (`deploycosmos.parameters.json`) are used to deploy following resources: + +1. One Cosmosdb database + +## Editing deploycosmos.parameters.json file + +You can edit the `deploycosmos.parameters.json` file to set your values, but is not needed. The only parameter that can +be set is: + +1. `name` is a string that is used to create the database name. ARM script creates unique values by appending a unique string to this parameter value, so you can leave the default value. + +## Deploy the template + +Once parameter file is edited you can deploy it using [create-resources script](../readme.md). + +i. e. if you are in windows, to deploy a Cosmosdb database in a new resourcegroup located in westus, go to `deploy\az` folder and type: + +``` +create-resources.cmd cosmos\deploycosmos newResourceGroup -c westus +``` + + + + + + + + + diff --git a/deploy/az/redis/readme.md b/deploy/az/redis/readme.md index 093a9af14..61be1f6f9 100644 --- a/deploy/az/redis/readme.md +++ b/deploy/az/redis/readme.md @@ -15,7 +15,7 @@ be set is: Once parameter file is edited you can deploy it using [create-resources script](../readme.md). -i. e. if you are in windows, to deploy sql databases in a new resourcegroup located in westus, go to `deploy\az` folder and type: +i. e. if you are in windows, to deploy a Redis cache in a new Azure Resource Group located in westus, go to `deploy\az` folder and type: ``` create-resources.cmd redis\redisdeploy newResourceGroup -c westus diff --git a/deploy/az/storage/catalog/deploystorage.json b/deploy/az/storage/catalog/deploystorage.json index e3fced6b2..2e2ed1b4b 100644 --- a/deploy/az/storage/catalog/deploystorage.json +++ b/deploy/az/storage/catalog/deploystorage.json @@ -7,11 +7,14 @@ }, "profileName" : { "type": "string" + }, + "endpointName" : { + "type": "string" } }, "variables": { "catalogstorage": "[concat(parameters('catalogstorage'), uniqueString(resourceGroup().id))]", - "endpointName": "[concat('endpoint-', uniqueString(resourceGroup().id))]", + "endpointName": "[concat(parameters('endpointName'), uniqueString(resourceGroup().id))]", "profileName": "[parameters('profileName')]" }, "resources": [ diff --git a/deploy/az/storage/catalog/deploystorage.parameters.json b/deploy/az/storage/catalog/deploystorage.parameters.json index 2c5256a09..b54e546fe 100644 --- a/deploy/az/storage/catalog/deploystorage.parameters.json +++ b/deploy/az/storage/catalog/deploystorage.parameters.json @@ -7,6 +7,9 @@ }, "profileName":{ "value": "eshopcatalog" + }, + "endpointName":{ + "value": "catalog-endpoint" } } } \ No newline at end of file diff --git a/deploy/az/storage/catalog/readme.md b/deploy/az/storage/catalog/readme.md new file mode 100644 index 000000000..f3ece6fed --- /dev/null +++ b/deploy/az/storage/catalog/readme.md @@ -0,0 +1,37 @@ +# Deploying Catalog Storage + +The ARM template `deploystorage.json` and its parameter file (`deploystorage.parameters.json`) are used to deploy following resources: + +1. One Storage Account +2. One CDN profile +3. One Endpoint + +## Editing deploystorage.parameters.json file + +You can edit the `deploystorage.parameters.json` file to set your values, but is not needed. The only parameters that can +be set are: + +1. `catalogstorage` is a string that is used to create the storage account name. ARM script creates unique values by appending a unique string to this parameter value, so you can leave the default value. + +2. `profileName` is a string that is used to create the CDN profile name. + +3. `endpointName` is a string that is used to create the storage endpoint name. ARM script creates unique values by appending a unique string to this parameter value, so you can leave the default value. + +## Deploy the template + +Once parameter file is edited you can deploy it using [create-resources script](../../readme.md). + +i. e. if you are in windows, to deploy a Storage Account in a new resourcegroup located in westus, go to `deploy\az` folder and type: + +``` +create-resources.cmd catalog\deploystorage newResourceGroup -c westus +``` + + + + + + + + + diff --git a/deploy/az/storage/marketing/deploystorage.json b/deploy/az/storage/marketing/deploystorage.json index cceb524d0..632e0d09a 100644 --- a/deploy/az/storage/marketing/deploystorage.json +++ b/deploy/az/storage/marketing/deploystorage.json @@ -7,11 +7,14 @@ }, "profileName" : { "type": "string" + }, + "endpointName" : { + "type": "string" } }, "variables": { "marketingstorage": "[concat(parameters('marketingstorage'), uniqueString(resourceGroup().id))]", - "endpointName": "[concat('endpoint-', uniqueString(resourceGroup().id))]", + "endpointName": "[concat(parameters('endpointName'), uniqueString(resourceGroup().id))]", "profileName": "[parameters('profileName')]" }, "resources": [ diff --git a/deploy/az/storage/marketing/deploystorage.parameters.json b/deploy/az/storage/marketing/deploystorage.parameters.json index 1608fd34a..40f7b3a1b 100644 --- a/deploy/az/storage/marketing/deploystorage.parameters.json +++ b/deploy/az/storage/marketing/deploystorage.parameters.json @@ -7,6 +7,9 @@ }, "profileName":{ "value": "eshopmarketing" + }, + "endpointName":{ + "value": "marketing-endpoint" } } } \ No newline at end of file diff --git a/deploy/az/storage/marketing/readme.md b/deploy/az/storage/marketing/readme.md new file mode 100644 index 000000000..2b457b608 --- /dev/null +++ b/deploy/az/storage/marketing/readme.md @@ -0,0 +1,37 @@ +# Deploying Marketing Storage + +The ARM template `deploystorage.json` and its parameter file (`deploystorage.parameters.json`) are used to deploy following resources: + +1. One Storage Account +2. One CDN profile +3. One Endpoint + +## Editing deploystorage.parameters.json file + +You can edit the `deploystorage.parameters.json` file to set your values, but is not needed. The only parameters that can +be set are: + +1. `marketingstorage` is a string that is used to create the storage account name. ARM script creates unique values by appending a unique string to this parameter value, so you can leave the default value. + +2. `profileName` is a string that is used to create the CDN profile name. + +3. `endpointName` is a string that is used to create the storage endpoint name. ARM script creates unique values by appending a unique string to this parameter value, so you can leave the default value. + +## Deploy the template + +Once parameter file is edited you can deploy it using [create-resources script](../../readme.md). + +i. e. if you are in windows, to deploy a Storage account in a new resourcegroup located in westus, go to `deploy\az` folder and type: + +``` +create-resources.cmd marketing\deploystorage newResourceGroup -c westus +``` + + + + + + + + + diff --git a/deploy/readme.md b/deploy/readme.md index 7d760c6bd..27b168713 100644 --- a/deploy/readme.md +++ b/deploy/readme.md @@ -20,6 +20,10 @@ Using `docker-machine` is the recommended way to create a VM with docker install 1. [Deploying SQL Server and databases](az/sql/readme.md) 2. [Deploying Azure Service Bus](az/servicebus/readme.md) 3. [Deploying Redis Cache](az/redis/readme.md) +4. [Deploying Cosmosdb](az/cosmos/readme.md) +5. [Deploying Catalog Storage](az/storage/catalog/readme.md) +6. [Deploying Marketing Storage](az/storage/marketing/readme.md) +7. [Deploying Marketing Azure functions](az/azurefunctions/readme.md) diff --git a/docker-compose-windows.override.yml b/docker-compose-windows.override.yml deleted file mode 100644 index 84dc5487d..000000000 --- a/docker-compose-windows.override.yml +++ /dev/null @@ -1,169 +0,0 @@ -version: '2.1' - -# The default docker-compose.override file can use the "localhost" as the external name for testing web apps within the same dev machine. -# The ESHOP_EXTERNAL_DNS_NAME_OR_IP environment variable is taken, by default, from the ".env" file defined like: -# ESHOP_EXTERNAL_DNS_NAME_OR_IP=localhost -# but values present in the environment vars at runtime will always override those defined inside the .env file -# An external IP or DNS name has to be used (instead localhost and the 10.0.75.1 IP) when testing the Web apps and the Xamarin apps from remote machines/devices using the same WiFi, for instance. - -services: - - basket.api: - environment: - - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=${ESHOP_AZURE_REDIS_BASKET_DB:-basket.data} - - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - - IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105 - - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - - AzureServiceBusEnabled=False - ports: - - "5103:80" - - catalog.api: - environment: - - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=${ESHOP_AZURE_CATALOG_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word} - - PicBaseUrl=${ESHOP_AZURE_STORAGE_CATALOG:-http://localhost:5101/api/v1/catalog/items/[0]/pic/} #Local: You need to open your local dev-machine firewall at range 5100-5110. - - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - - AzureStorageAccountName=${ESHOP_AZURE_STORAGE_CATALOG_NAME} - - AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_CATALOG_KEY} - - UseCustomizationData=True - - AzureServiceBusEnabled=False - ports: - - "5101:80" - - identity.api: - environment: - - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 - - SpaClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5104 - - XamarinCallback=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105/xamarincallback #localhost do not work for UWP login, so we have to use "external" IP always - - ConnectionStrings__DefaultConnection=${ESHOP_AZURE_IDENTITY_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Service.IdentityDb;User Id=sa;Password=Pass@word} - - MvcClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5100 #Local: You need to open your local dev-machine firewall at range 5100-5110. - - LocationApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5109 - - MarketingApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5110 - - BasketApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5103 - - OrderingApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5102 - - UseCustomizationData=True - ports: - - "5105:80" - - ordering.api: - environment: - - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=${ESHOP_AZURE_ORDERING_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word} - - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - - IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105 - - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - - UseCustomizationData=True - - AzureServiceBusEnabled=False - ports: - - "5102:80" - - webspa: - environment: - - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 - - CatalogUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5101 - - OrderingUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5102 - - IdentityUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. - - BasketUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5103 - - MarketingUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5110 - - CatalogUrlHC=http://catalog.api/hc - - OrderingUrlHC=http://ordering.api/hc - - IdentityUrlHC=http://identity.api/hc #Local: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}, if using external IP or DNS name from browser. - - BasketUrlHC=http://basket.api/hc - - MarketingUrlHC=http://marketing.api/hc - - UseCustomizationData=True - ports: - - "5104:80" - - webmvc: - environment: - - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 - - CatalogUrl=http://catalog.api - - OrderingUrl=http://ordering.api - - BasketUrl=http://basket.api - - IdentityUrl=http://10.0.75.1:5105 - - MarketingUrl=http://marketing.api #Local: Use 10.0.75.1 in a "Docker for Windows" environment, if using "localhost" from browser. - - UseCustomizationData=True #Remote: Use ${ESHOP_EXTERNAL_DNS_NAME_OR_IP} if using external IP or DNS name from browser. - ports: - - "5100:80" - - sql.data: - environment: - - SA_PASSWORD=Pass@word - - ACCEPT_EULA=Y - ports: - - "5433:1433" - - nosql.data: - ports: - - "27017:27017" - - locations.api: - environment: - - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=${ESHOP_AZURE_COSMOSDB:-mongodb://nosql.data} - - Database=LocationsDb - - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - - IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105 - - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - - AzureServiceBusEnabled=False - ports: - - "5109:80" - - marketing.api: - environment: - - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=${ESHOP_AZURE_MARKETING_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word} - - MongoConnectionString=${ESHOP_AZURE_COSMOSDB:-mongodb://nosql.data} - - MongoDatabase=MarketingDb - - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - - IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105 - - CampaignDetailFunctionUri=${ESHOP_AZUREFUNC_CAMPAIGN_DETAILS_URI} - - PicBaseUrl=${ESHOP_AZURE_STORAGE_MARKETING:-http://localhost:5110/api/v1/campaigns/[0]/pic/} - - AzureStorageAccountName=${ESHOP_AZURE_STORAGE_MARKETING_NAME} - - AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_MARKETING_KEY} - - AzureServiceBusEnabled=False - ports: - - "5110:80" - - graceperiodmanager: - environment: - - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word - - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - - AzureServiceBusEnabled=False - - webstatus: - environment: - - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 - - CatalogUrl=http://catalog.api/hc - - OrderingUrl=http://ordering.api/hc - - BasketUrl=http://basket.api/hc - - IdentityUrl=http://identity.api/hc - - LocationsUrl=http://locations.api/hc - - MarketingUrl=http://marketing.api/hc - - mvc=http://webmvc/hc - - spa=http://webspa/hc - ports: - - "5107:80" - - payment.api: - environment: - - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 - - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - - AzureServiceBusEnabled=False - ports: - - "5108:80" \ No newline at end of file diff --git a/docker-compose-windows.prod.yml b/docker-compose-windows.prod.yml index 57873ccfa..d5ea2d1bc 100644 --- a/docker-compose-windows.prod.yml +++ b/docker-compose-windows.prod.yml @@ -21,6 +21,7 @@ services: - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - IdentityUrlExternal=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} + - AzureServiceBusEnabled=False ports: - "5103:5103" @@ -29,11 +30,13 @@ services: - ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_URLS=http://0.0.0.0:80 - ConnectionString=${ESHOP_AZURE_CATALOG_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word} - - PicBaseUrl=${ESHOP_AZURE_STORAGE_CATALOG} #Local: You need to open your local dev-machine firewall at range 5100-5110. + - PicBaseUrl=${ESHOP_AZURE_STORAGE_CATALOG:-http://localhost:5101/api/v1/catalog/items/[0]/pic/} #Local: You need to open your local dev-machine firewall at range 5100-5110. - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - AzureStorageAccountName=${ESHOP_AZURE_STORAGE_CATALOG_NAME} - AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_CATALOG_KEY} - UseCustomizationData=True + - AzureServiceBusEnabled=False + - AzureStorageEnabled=False ports: - "5101:80" @@ -62,6 +65,7 @@ services: - IdentityUrlExternal=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - UseCustomizationData=True + - AzureServiceBusEnabled=False ports: - "5102:80" @@ -92,6 +96,7 @@ services: - IdentityUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}, if using external IP or DNS name from browser. - BasketUrl=http://basket.api - MarketingUrl=http://marketing.api + - UseCustomizationData=True #Remote: Use ${ESHOP_EXTERNAL_DNS_NAME_OR_IP} if using external IP or DNS name from browser. ports: - "5100:80" @@ -106,18 +111,13 @@ services: - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - IdentityUrlExternal=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 - CampaignDetailFunctionUri=${ESHOP_AZUREFUNC_CAMPAIGN_DETAILS_URI} - - PicBaseUrl=${ESHOP_AZURE_STORAGE_MARKETING} + - PicBaseUrl=${ESHOP_AZURE_STORAGE_MARKETING:-http://localhost:5110/api/v1/campaigns/[0]/pic/} - AzureStorageAccountName=${ESHOP_AZURE_STORAGE_MARKETING_NAME} - AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_MARKETING_KEY} + - AzureServiceBusEnabled=False + - AzureStorageEnabled=False ports: - "5110:80" - - graceperiodmanager: - environment: - - ASPNETCORE_ENVIRONMENT=Production - - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word - - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} sql.data: environment: @@ -151,6 +151,7 @@ services: - ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_URLS=http://0.0.0.0:5108 - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} + - AzureServiceBusEnabled=False ports: - "5108:80" @@ -163,5 +164,6 @@ services: - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - IdentityUrlExternal=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} + - AzureServiceBusEnabled=False ports: - "5109:80" \ No newline at end of file diff --git a/docker-compose-windows.yml b/docker-compose-windows.yml index 6296f5ca7..1a71968ba 100644 --- a/docker-compose-windows.yml +++ b/docker-compose-windows.yml @@ -5,7 +5,7 @@ services: image: eshop/basket.api-win:${TAG:-latest} build: context: ./src/Services/Basket/Basket.API - dockerfile: Dockerfile.nanowin + dockerfile: Dockerfile depends_on: - basket.data - identity.api @@ -15,7 +15,7 @@ services: image: eshop/catalog.api-win:${TAG:-latest} build: context: ./src/Services/Catalog/Catalog.API - dockerfile: Dockerfile.nanowin + dockerfile: Dockerfile depends_on: - sql.data - rabbitmq @@ -24,7 +24,7 @@ services: image: eshop/identity.api-win:${TAG:-latest} build: context: ./src/Services/Identity/Identity.API - dockerfile: Dockerfile.nanowin + dockerfile: Dockerfile depends_on: - sql.data @@ -32,25 +32,39 @@ services: image: eshop/ordering.api-win:${TAG:-latest} build: context: ./src/Services/Ordering/Ordering.API - dockerfile: Dockerfile.nanowin + dockerfile: Dockerfile depends_on: - sql.data - rabbitmq + marketing.api: + image: eshop/marketing.api:${TAG:-latest} + build: + context: ./src/Services/Marketing/Marketing.API + dockerfile: Dockerfile + depends_on: + - sql.data + - nosql.data + - identity.api + - rabbitmq + webspa: image: eshop/webspa-win:${TAG:-latest} build: context: ./src/Web/WebSPA - dockerfile: Dockerfile.nanowin + dockerfile: Dockerfile depends_on: + - catalog.api + - ordering.api - identity.api - basket.api + - marketing.api webmvc: image: eshop/webmvc-win:${TAG:-latest} build: context: ./src/Web/WebMVC - dockerfile: Dockerfile.nanowin + dockerfile: Dockerfile depends_on: - catalog.api - ordering.api @@ -62,28 +76,25 @@ services: image: eshop/webstatus:${TAG:-latest} build: context: ./src/Web/WebStatus - dockerfile: Dockerfile.nanowin + dockerfile: Dockerfile + + payment.api: + image: eshop/payment.api:${TAG:-latest} + build: + context: ./src/Services/Payment/Payment.API + dockerfile: Dockerfile + depends_on: + - rabbitmq locations.api: image: eshop/locations.api:${TAG:-latest} build: context: ./src/Services/Location/Locations.API - dockerfile: Dockerfile.nanowin + dockerfile: Dockerfile depends_on: - nosql.data - rabbitmq - marketing.api: - image: eshop/marketing.api:${TAG:-latest} - build: - context: ./src/Services/Marketing/Marketing.API - dockerfile: Dockerfile.nanowin - depends_on: - - sql.data - - nosql.data - - identity.api - - rabbitmq - sql.data: image: microsoft/mssql-server-windows @@ -94,7 +105,7 @@ services: image: redis:nanoserver # build: # context: ./_docker/redis -# dockerfile: Dockerfile.nanowin +# dockerfile: Dockerfile ports: - "6379:6379" @@ -102,26 +113,10 @@ services: image: spring2/rabbitmq # build: # context: ./_docker/rabbitmq -# dockerfile: Dockerfile.nanowin +# dockerfile: Dockerfile ports: - - "5672:5672" - - graceperiodmanager: - image: eshop/graceperiodmanager:${TAG:-latest} - build: - context: ./src/Services/GracePeriod/GracePeriodManager - dockerfile: Dockerfile.nanowin - depends_on: - - sql.data - - rabbitmq - - payment.api: - image: eshop/payment.api:${TAG:-latest} - build: - context: ./src/Services/Payment/Payment.API - dockerfile: Dockerfile.nanowin - depends_on: - - rabbitmq + - "15672:15672" + - "5672:5672" networks: default: diff --git a/docker-compose.ci.build.yml b/docker-compose.ci.build.yml index edf84b572..02fe39637 100644 --- a/docker-compose.ci.build.yml +++ b/docker-compose.ci.build.yml @@ -2,7 +2,7 @@ version: '2.1' services: ci-build: - image: microsoft/aspnetcore-build:1.1.2 + image: microsoft/aspnetcore-build:2.0 volumes: - .:/src - ./cli-linux:/cli-linux @@ -11,8 +11,8 @@ services: # Next line is using the .sln file to compile all the projects. # Sometime there is an issue in msbuild exits the process before finishing building the bits: (https://github.com/Microsoft/msbuild/issues/2153) # Random error: error MSB4017: The build stopped unexpectedly be cause of an unexpected logger failure. - command: /bin/bash -c "pushd ./src/Web/WebSPA && npm rebuild node-sass && popd && dotnet restore ./eShopOnContainers-ServicesAndWebApps.sln && dotnet publish ./eShopOnContainers-ServicesAndWebApps.sln -c Release -o ./obj/Docker/publish" + #command: /bin/bash -c "pushd ./src/Web/WebSPA && npm rebuild node-sass && popd && dotnet restore ./eShopOnContainers-ServicesAndWebApps.sln --verbosity minimal && dotnet publish ./eShopOnContainers-ServicesAndWebApps.sln -c Release -o ./obj/Docker/publish --verbosity minimal" # NOTE: Using build-bits-linux.sh from Linux build container exits before ending. -# command: /bin/bash -c "pushd ./src/Web/WebSPA && npm rebuild node-sass && popd && pushd /cli-linux && ./build-bits-linux.sh /src" + command: /bin/bash -c "pushd ./src/Web/WebSPA && npm rebuild node-sass && popd && pushd /cli-linux && ./build-bits-linux.sh /src" \ No newline at end of file diff --git a/docker-compose.dcproj b/docker-compose.dcproj index 92590035d..23547b577 100644 --- a/docker-compose.dcproj +++ b/docker-compose.dcproj @@ -15,12 +15,6 @@ docker-compose.yml - - - docker-compose.yml - - - docker-compose.yml diff --git a/docker-compose.override.yml b/docker-compose.override.yml index f3576eb87..6870b617f 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -25,12 +25,13 @@ services: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://0.0.0.0:80 - ConnectionString=${ESHOP_AZURE_CATALOG_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word} - - PicBaseUrl=${ESHOP_AZURE_STORAGE_CATALOG:-http://localhost:5101/api/v1/catalog/items/[0]/pic/} #Local: You need to open your local dev-machine firewall at range 5100-5110. + - PicBaseUrl=${ESHOP_AZURE_STORAGE_CATALOG_URL:-http://localhost:5101/api/v1/catalog/items/[0]/pic/} #Local: You need to open your local dev-machine firewall at range 5100-5110. - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - AzureStorageAccountName=${ESHOP_AZURE_STORAGE_CATALOG_NAME} - AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_CATALOG_KEY} - UseCustomizationData=True - AzureServiceBusEnabled=False + - AzureStorageEnabled=False ports: - "5101:80" @@ -60,6 +61,8 @@ services: - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - UseCustomizationData=True - AzureServiceBusEnabled=False + - GracePeriodTime=1 + - CheckUpdateTime=30000 ports: - "5102:80" @@ -74,20 +77,13 @@ services: - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105 - CampaignDetailFunctionUri=${ESHOP_AZUREFUNC_CAMPAIGN_DETAILS_URI} - - PicBaseUrl=${ESHOP_AZURE_STORAGE_MARKETING:-http://localhost:5110/api/v1/campaigns/[0]/pic/} + - PicBaseUrl=${ESHOP_AZURE_STORAGE_MARKETING_URL:-http://localhost:5110/api/v1/campaigns/[0]/pic/} - AzureStorageAccountName=${ESHOP_AZURE_STORAGE_MARKETING_NAME} - AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_MARKETING_KEY} - AzureServiceBusEnabled=False + - AzureStorageEnabled=False ports: - "5110:80" - - graceperiodmanager: - environment: - - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word - - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - - AzureServiceBusEnabled=False webspa: environment: @@ -121,17 +117,6 @@ services: ports: - "5100:80" - sql.data: - environment: - - SA_PASSWORD=Pass@word - - ACCEPT_EULA=Y - ports: - - "5433:1433" - - nosql.data: - ports: - - "27017:27017" - webstatus: environment: - ASPNETCORE_ENVIRONMENT=Development @@ -168,3 +153,14 @@ services: - AzureServiceBusEnabled=False ports: - "5109:80" + + sql.data: + environment: + - SA_PASSWORD=Pass@word + - ACCEPT_EULA=Y + ports: + - "5433:1433" + + nosql.data: + ports: + - "27017:27017" diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 3b5ff6779..f768b5872 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -21,6 +21,7 @@ services: - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - IdentityUrlExternal=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} + - AzureServiceBusEnabled=False ports: - "5103:80" @@ -29,11 +30,13 @@ services: - ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_URLS=http://0.0.0.0:80 - ConnectionString=${ESHOP_AZURE_CATALOG_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word} - - PicBaseUrl=${ESHOP_AZURE_STORAGE_CATALOG} #Local: You need to open your local dev-machine firewall at range 5100-5110. + - PicBaseUrl=${ESHOP_AZURE_STORAGE_CATALOG_URL:-http://localhost:5101/api/v1/catalog/items/[0]/pic/} #Local: You need to open your local dev-machine firewall at range 5100-5110. - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - AzureStorageAccountName=${ESHOP_AZURE_STORAGE_CATALOG_NAME} - AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_CATALOG_KEY} - UseCustomizationData=True + - AzureServiceBusEnabled=False + - AzureStorageEnabled=False ports: - "5101:80" @@ -62,6 +65,7 @@ services: - IdentityUrlExternal=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - UseCustomizationData=True + - AzureServiceBusEnabled=False ports: - "5102:80" @@ -73,22 +77,17 @@ services: - MongoConnectionString=${ESHOP_AZURE_COSMOSDB:-mongodb://nosql.data} - MongoDatabase=MarketingDb - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. + - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - IdentityUrlExternal=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 - CampaignDetailFunctionUri=${ESHOP_AZUREFUNC_CAMPAIGN_DETAILS_URI} - - PicBaseUrl=${ESHOP_AZURE_STORAGE_MARKETING} + - PicBaseUrl=${ESHOP_AZURE_STORAGE_MARKETING_URL:-http://localhost:5110/api/v1/campaigns/[0]/pic/} - AzureStorageAccountName=${ESHOP_AZURE_STORAGE_MARKETING_NAME} - AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_MARKETING_KEY} + - AzureServiceBusEnabled=False + - AzureStorageEnabled=False ports: - "5110:80" - graceperiodmanager: - environment: - - ASPNETCORE_ENVIRONMENT=Production - - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word - - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - webspa: environment: - ASPNETCORE_ENVIRONMENT=Production @@ -113,9 +112,11 @@ services: - ASPNETCORE_URLS=http://0.0.0.0:80 - CatalogUrl=http://catalog.api - OrderingUrl=http://ordering.api - - IdentityUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}, if using external IP or DNS name from browser. - BasketUrl=http://basket.api - - MarketingUrl=http://marketing.api + - IdentityUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}, if using external IP or DNS name from browser. + - MarketingUrl=http://marketing.api #Local: Use 10.0.75.1 in a "Docker for Windows" environment, if using "localhost" from browser. + #Remote: Use ${ESHOP_EXTERNAL_DNS_NAME_OR_IP} if using external IP or DNS name from browser. + - UseCustomizationData=True ports: - "5100:80" @@ -151,6 +152,7 @@ services: - ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_URLS=http://0.0.0.0:5108 - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} + - AzureServiceBusEnabled=False ports: - "5108:80" @@ -163,5 +165,6 @@ services: - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - IdentityUrlExternal=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} + - AzureServiceBusEnabled=False ports: - "5109:80" \ No newline at end of file diff --git a/docker-compose.vs.debug.yml b/docker-compose.vs.debug.yml deleted file mode 100644 index 9c4879f61..000000000 --- a/docker-compose.vs.debug.yml +++ /dev/null @@ -1,166 +0,0 @@ -version: '2.1' - -services: - basket.api: - image: eshop/basket.api:dev - build: - args: - source: ${DOCKER_BUILD_SOURCE} - environment: - - DOTNET_USE_POLLING_FILE_WATCHER=1 - volumes: - - ./src/Services/Basket/Basket.API:/app - - ~/.nuget/packages:/root/.nuget/packages:ro - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" - - catalog.api: - image: eshop/catalog.api:dev - build: - args: - source: ${DOCKER_BUILD_SOURCE} - environment: - - DOTNET_USE_POLLING_FILE_WATCHER=1 - volumes: - - ./src/Services/Catalog/Catalog.API:/app - - ~/.nuget/packages:/root/.nuget/packages:ro - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" - - identity.api: - image: eshop/identity.api:dev - build: - args: - source: ${DOCKER_BUILD_SOURCE} - environment: - - DOTNET_USE_POLLING_FILE_WATCHER=1 - volumes: - - ./src/Services/Identity/Identity.API:/app - - ~/.nuget/packages:/root/.nuget/packages:ro - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" - - ordering.api: - image: eshop/ordering.api:dev - build: - args: - source: ${DOCKER_BUILD_SOURCE} - environment: - - DOTNET_USE_POLLING_FILE_WATCHER=1 - volumes: - - ./src/Services/Ordering/Ordering.API:/app - - ~/.nuget/packages:/root/.nuget/packages:ro - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" - - marketing.api: - image: eshop/marketing.api:dev - build: - args: - source: ${DOCKER_BUILD_SOURCE} - environment: - - DOTNET_USE_POLLING_FILE_WATCHER=1 - volumes: - - ./src/Services/Marketing/Marketing.API:/app - - ~/.nuget/packages:/root/.nuget/packages:ro - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" - - - webspa: - image: eshop/webspa:dev - build: - args: - source: ${DOCKER_BUILD_SOURCE} - environment: - - DOTNET_USE_POLLING_FILE_WATCHER=1 - volumes: - - ./src/Web/WebSPA:/app - - ~/.nuget/packages:/root/.nuget/packages:ro - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" - - webmvc: - image: eshop/webmvc:dev - build: - args: - source: ${DOCKER_BUILD_SOURCE} - environment: - - DOTNET_USE_POLLING_FILE_WATCHER=1 - volumes: - - ./src/Web/WebMVC:/app - - ~/.nuget/packages:/root/.nuget/packages:ro - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" - - webstatus: - image: eshop/webstatus:dev - build: - args: - source: ${DOCKER_BUILD_SOURCE} - environment: - - DOTNET_USE_POLLING_FILE_WATCHER=1 - volumes: - - ./src/Web/WebStatus:/app - - ~/.nuget/packages:/root/.nuget/packages:ro - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" - - payment.api: - image: eshop/payment.api:dev - build: - args: - source: ${DOCKER_BUILD_SOURCE} - environment: - - DOTNET_USE_POLLING_FILE_WATCHER=1 - volumes: - - ./src/Services/Payment/Payment.API:/app - - ~/.nuget/packages:/root/.nuget/packages:ro - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" - - graceperiodmanager: - image: eshop/graceperiodmanager:dev - build: - args: - source: ${DOCKER_BUILD_SOURCE} - volumes: - - ./src/Services/GracePeriod/GracePeriodManager:/app - - ~/.nuget/packages:/root/.nuget/packages:ro - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" - - locations.api: - image: eshop/locations.api:dev - build: - args: - source: ${DOCKER_BUILD_SOURCE} - environment: - - DOTNET_USE_POLLING_FILE_WATCHER=1 - volumes: - - ./src/Services/Location/Locations.API:/app - - ~/.nuget/packages:/root/.nuget/packages:ro - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" diff --git a/docker-compose.vs.release.yml b/docker-compose.vs.release.yml deleted file mode 100644 index 92be2557b..000000000 --- a/docker-compose.vs.release.yml +++ /dev/null @@ -1,112 +0,0 @@ -version: '2.1' - -services: - basket.api: - build: - args: - source: ${DOCKER_BUILD_SOURCE} - volumes: - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" - - catalog.api: - build: - args: - source: ${DOCKER_BUILD_SOURCE} - volumes: - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" - - identity.api: - build: - args: - source: ${DOCKER_BUILD_SOURCE} - volumes: - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" - - ordering.api: - build: - args: - source: ${DOCKER_BUILD_SOURCE} - volumes: - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" - - marketing.api: - build: - args: - source: ${DOCKER_BUILD_SOURCE} - volumes: - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" - - webspa: - build: - args: - source: ${DOCKER_BUILD_SOURCE} - volumes: - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" - - webmvc: - build: - args: - source: ${DOCKER_BUILD_SOURCE} - volumes: - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" - - webstatus: - build: - args: - source: ${DOCKER_BUILD_SOURCE} - volumes: - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" - - payment.api: - build: - args: - source: ${DOCKER_BUILD_SOURCE} - volumes: - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" - - graceperiodmanager: - build: - args: - source: ${DOCKER_BUILD_SOURCE} - volumes: - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" - - locations.api: - build: - args: - source: ${DOCKER_BUILD_SOURCE} - volumes: - - ~/clrdbg:/clrdbg:ro - entrypoint: tail -f /dev/null - labels: - - "com.microsoft.visualstudio.targetoperatingsystem=linux" diff --git a/docker-compose.yml b/docker-compose.yml index 3d60489b5..cf26bcf5f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -49,23 +49,17 @@ services: - identity.api - rabbitmq - graceperiodmanager: - image: eshop/graceperiodmanager:${TAG:-latest} - build: - context: ./src/Services/GracePeriod/GracePeriodManager - dockerfile: Dockerfile - depends_on: - - sql.data - - rabbitmq - webspa: image: eshop/webspa:${TAG:-latest} build: context: ./src/Web/WebSPA dockerfile: Dockerfile depends_on: + - catalog.api + - ordering.api - identity.api - basket.api + - marketing.api webmvc: image: eshop/webmvc:${TAG:-latest} @@ -79,22 +73,6 @@ services: - basket.api - marketing.api - sql.data: - image: microsoft/mssql-server-linux - - nosql.data: - image: mongo - - basket.data: - image: redis - ports: - - "6379:6379" - - rabbitmq: - image: rabbitmq - ports: - - "5672:5672" - webstatus: image: eshop/webstatus:${TAG:-latest} build: @@ -117,3 +95,20 @@ services: depends_on: - nosql.data - rabbitmq + + sql.data: + image: microsoft/mssql-server-linux + + nosql.data: + image: mongo + + basket.data: + image: redis + ports: + - "6379:6379" + + rabbitmq: + image: rabbitmq:3-management + ports: + - "15672:15672" + - "5672:5672" \ No newline at end of file diff --git a/docs/Enterprise-Application-Patterns-using-XamarinForms.pdf b/docs/Enterprise-Application-Patterns-using-XamarinForms.pdf index 7184e3042..cdce68944 100644 Binary files a/docs/Enterprise-Application-Patterns-using-XamarinForms.pdf and b/docs/Enterprise-Application-Patterns-using-XamarinForms.pdf differ diff --git a/eShopOnContainers-Android.sln b/eShopOnContainers-Android.sln index f1f10b26f..b3324f540 100644 --- a/eShopOnContainers-Android.sln +++ b/eShopOnContainers-Android.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26430.6 +VisualStudioVersion = 15.0.26730.8 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{932D8224-11F6-4D07-B109-DA28AD288A63}" EndProject diff --git a/eShopOnContainers-AzureFunctions.sln b/eShopOnContainers-AzureFunctions.sln index 7e14fc19d..d129fc0fe 100644 --- a/eShopOnContainers-AzureFunctions.sln +++ b/eShopOnContainers-AzureFunctions.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26608.5 +VisualStudioVersion = 15.0.26730.8 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Infrastructure", "Infrastructure", "{5B1011EC-CEE5-47AA-B336-99381D573679}" EndProject diff --git a/eShopOnContainers-MobileApps.sln b/eShopOnContainers-MobileApps.sln index f70efddf1..ecc3fdb6b 100755 --- a/eShopOnContainers-MobileApps.sln +++ b/eShopOnContainers-MobileApps.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26228.9 +VisualStudioVersion = 15.0.26730.8 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{932D8224-11F6-4D07-B109-DA28AD288A63}" EndProject @@ -473,6 +473,8 @@ Global {A7337243-33B8-463A-87AD-944B75EFD820}.AppStore|x86.Build.0 = Release|x86 {A7337243-33B8-463A-87AD-944B75EFD820}.AppStore|x86.Deploy.0 = Release|x86 {A7337243-33B8-463A-87AD-944B75EFD820}.Debug|Any CPU.ActiveCfg = Debug|x86 + {A7337243-33B8-463A-87AD-944B75EFD820}.Debug|Any CPU.Build.0 = Debug|x86 + {A7337243-33B8-463A-87AD-944B75EFD820}.Debug|Any CPU.Deploy.0 = Debug|x86 {A7337243-33B8-463A-87AD-944B75EFD820}.Debug|ARM.ActiveCfg = Debug|ARM {A7337243-33B8-463A-87AD-944B75EFD820}.Debug|ARM.Build.0 = Debug|ARM {A7337243-33B8-463A-87AD-944B75EFD820}.Debug|ARM.Deploy.0 = Debug|ARM diff --git a/eShopOnContainers-ServicesAndWebApps.sln b/eShopOnContainers-ServicesAndWebApps.sln index 01ea95a22..a8a6e7ace 100644 --- a/eShopOnContainers-ServicesAndWebApps.sln +++ b/eShopOnContainers-ServicesAndWebApps.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26430.14 +VisualStudioVersion = 15.0.26730.8 MinimumVisualStudioVersion = 10.0.40219.1 Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{FEA0C318-FFED-4D39-8781-265718CA43DD}" EndProject @@ -81,8 +81,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Health EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventBus.Tests", "src\BuildingBlocks\EventBus\EventBus.Tests\EventBus.Tests.csproj", "{4A980AC4-7205-46BF-8CCB-09E44D700FD4}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GracePeriodManager", "src\Services\GracePeriod\GracePeriodManager\GracePeriodManager.csproj", "{F6E0F0DD-1400-43C3-B5E0-7CC325728C47}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Location", "Location", "{41139F64-4046-4F16-96B7-D941D96FA9C6}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Locations.API", "src\Services\Location\Locations.API\Locations.API.csproj", "{E7581357-FC34-474C-B8F5-307EE3CE05EF}" @@ -1079,54 +1077,6 @@ Global {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Release|x64.Build.0 = Release|Any CPU {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Release|x86.ActiveCfg = Release|Any CPU {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Release|x86.Build.0 = Release|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Ad-Hoc|x64.Build.0 = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Ad-Hoc|x86.Build.0 = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.AppStore|Any CPU.Build.0 = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.AppStore|ARM.ActiveCfg = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.AppStore|ARM.Build.0 = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.AppStore|iPhone.ActiveCfg = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.AppStore|iPhone.Build.0 = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.AppStore|x64.ActiveCfg = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.AppStore|x64.Build.0 = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.AppStore|x86.ActiveCfg = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.AppStore|x86.Build.0 = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Debug|ARM.ActiveCfg = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Debug|ARM.Build.0 = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Debug|iPhone.Build.0 = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Debug|x64.ActiveCfg = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Debug|x64.Build.0 = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Debug|x86.ActiveCfg = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Debug|x86.Build.0 = Debug|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Release|Any CPU.Build.0 = Release|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Release|ARM.ActiveCfg = Release|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Release|ARM.Build.0 = Release|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Release|iPhone.ActiveCfg = Release|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Release|iPhone.Build.0 = Release|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Release|x64.ActiveCfg = Release|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Release|x64.Build.0 = Release|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Release|x86.ActiveCfg = Release|Any CPU - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47}.Release|x86.Build.0 = Release|Any CPU {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU @@ -1505,7 +1455,6 @@ Global {22A0F9C1-2D4A-4107-95B7-8459E6688BC5} = {A81ECBC2-6B00-4DCD-8388-469174033379} {4BD76717-3102-4969-8C2C-BAAA3F0263B6} = {A81ECBC2-6B00-4DCD-8388-469174033379} {4A980AC4-7205-46BF-8CCB-09E44D700FD4} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F} - {F6E0F0DD-1400-43C3-B5E0-7CC325728C47} = {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B} {41139F64-4046-4F16-96B7-D941D96FA9C6} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8} {E7581357-FC34-474C-B8F5-307EE3CE05EF} = {41139F64-4046-4F16-96B7-D941D96FA9C6} {88B22DBB-AA8F-4290-A454-2C109352C345} = {DB0EFB20-B024-4E5E-A75C-52143C131D25} @@ -1517,4 +1466,7 @@ Global {969E793C-C413-490E-9C9D-B2B46DA5AF32} = {EF0337F2-ED00-4643-89FD-EE10863F1870} {983EAB84-65C5-4793-A300-08F97C791A15} = {0D1E7D4E-12DD-4B67-9595-7C0BD347F8C8} EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {25728519-5F0F-4973-8A64-0A81EB4EA8D9} + EndGlobalSection EndGlobal diff --git a/eShopOnContainers-iOS.sln b/eShopOnContainers-iOS.sln index a6e889786..e220e7c4e 100644 --- a/eShopOnContainers-iOS.sln +++ b/eShopOnContainers-iOS.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26430.6 +VisualStudioVersion = 15.0.26730.8 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{932D8224-11F6-4D07-B109-DA28AD288A63}" EndProject diff --git a/eShopOnContainers.sln b/eShopOnContainers.sln index 414ff7993..ae44be741 100644 --- a/eShopOnContainers.sln +++ b/eShopOnContainers.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26430.6 +VisualStudioVersion = 15.0.26730.8 MinimumVisualStudioVersion = 10.0.40219.1 Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{FEA0C318-FFED-4D39-8781-265718CA43DD}" ProjectSection(ProjectDependencies) = postProject diff --git a/global.json b/global.json index 38fed7db6..dfad1f9f9 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version":"1.0.4" + "version":"2.0.2" } } \ No newline at end of file diff --git a/k8s/README.k8s.md b/k8s/README.k8s.md index 507bc2c54..2192959d5 100644 --- a/k8s/README.k8s.md +++ b/k8s/README.k8s.md @@ -58,6 +58,12 @@ The script accepts following parameters: + `deployInfrastructure`: If `true` infrastructure containers (rabbitmq, mongo, redis, sql) will be deployed in k8s. If `false` those containers (and its related deployments and services in k8s) won't be deployed. + `dockerOrg`: Name of the organization in the registry where the images are (or will be pushed). Default value is `eshop` (which has images provided by Microsoft) +**Important:** If you **don't pass the `-buildBits $true` the script won't build and publish the projects** to their `obj/Docker/publish` folder. If any project is not published, you'll be receiving errors like: + +``` +ERROR: Service 'xxxxxxx' failed to build: COPY failed: stat /var/lib/docker/tmp/docker-builder123456789/obj/Docker/publish: no such file or directory +``` + ### Typical usages of the script: Build all projects, and deploy all them in k8s including infrastructure containers in a organization called `foo` in Docker Hub. Images will be tagged with my current git branch and containers will use the configuration set in `conf_local.yml` file: @@ -76,4 +82,4 @@ Deploy k8s using public images that Microsoft provides: ``` ./deploy.ps1 -buildImages $false -configFile conf_local.yml -imageTag master -``` \ No newline at end of file +``` diff --git a/k8s/img/blob_creation.png b/k8s/img/blob_creation.png index a9e386ead..1b391e72c 100644 Binary files a/k8s/img/blob_creation.png and b/k8s/img/blob_creation.png differ diff --git a/k8s/img/deploy_script_task.png b/k8s/img/deploy_script_task.png index 96e50d3c5..2e5e1e4ac 100644 Binary files a/k8s/img/deploy_script_task.png and b/k8s/img/deploy_script_task.png differ diff --git a/k8s/img/get_kubectlbin_task.png b/k8s/img/get_kubectlbin_task.png index 423aceca8..7d999579d 100644 Binary files a/k8s/img/get_kubectlbin_task.png and b/k8s/img/get_kubectlbin_task.png differ diff --git a/k8s/img/get_kubectlconfig_task.png b/k8s/img/get_kubectlconfig_task.png index 594e68ba7..e9585ae81 100644 Binary files a/k8s/img/get_kubectlconfig_task.png and b/k8s/img/get_kubectlconfig_task.png differ diff --git a/k8s/readme.md b/k8s/readme.md index 680652e35..43534d32e 100644 --- a/k8s/readme.md +++ b/k8s/readme.md @@ -9,4 +9,4 @@ Refer to file [README.k8s.md](./README.k8s.md) for detailed information Refer to file [README.CICD.k8s.md](./README.CICD.k8s.md) for information about how to set a VSTS build for deploying on k8s -Refer to file [conf-files.md](./conf-files.md) for a brief descriptio of every YAML file in this folder \ No newline at end of file +Refer to file [conf-files.md](./conf-files.md) for a brief description of every YAML file in this folder \ No newline at end of file diff --git a/README.ENV.md b/readme/README.ENV.md similarity index 100% rename from README.ENV.md rename to readme/README.ENV.md diff --git a/readme/readme-docker-compose.md b/readme/readme-docker-compose.md new file mode 100644 index 000000000..69735a9f4 --- /dev/null +++ b/readme/readme-docker-compose.md @@ -0,0 +1,79 @@ +# Docker-compose yaml files + +In the root folder of the repo are all docker-compose files (`docker-compose*.yml`). Here is a list of all of them and what is their purpose: + +## Container build + +* `docker-compose.ci.build.yml`: This file is for starting the build container to build the project using a container that has all needed prerequisites. Refer to [corresponding wiki section](https://github.com/dotnet-architecture/eShopOnContainers/wiki/03.-Setting-the-eShopOnContainers-solution-up-in-a-Windows-CLI-environment-(dotnet-CLI,-Docker-CLI-and-VS-Code)#build-the-bits-through-the-build-container-image) for more information. + +## Files needed to run eShopOnContainers locally + +* `docker-compose.yml`: This file contains **the definition of all images needed for running eShopOnContainers**. +* `docker-compose.override.yml`: This file contains the base configuration for all images of the previous file + +Usually these two files are using together. The standard way to start eShopOnContainers from CLI is: + +``` +docker-compose -f docker-compose.yml -f docker-compose.override.yml +``` + +This will start eShopOnContainers with all containers running locally, and it is the default development environment. + +## Files needed to run eShopOnContainers on a remote docker host + +* `docker-compose.prod.yml`: This file is a replacement of the `docker-compose.override.yml` but contains some configurations more suitable for a "production" environment or when you need to run the services using an external docker host. + +``` +docker-compose -f docker-compose.yml -f docker-compose.prod.yml +``` + +When using this file the following environments variables must be set: + +* `ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP` with the IP or DNS name of the docker host that runs the services (can use `localhost` if needed). +* `ESHOP_AZURE_STORAGE_CATALOG` with the URL of the Azure Storage that will host the catalog images +* `ESHOP_AZURE_STORAGE_MARKETING` with the URL of the Azure Storage that will host the marketing campaign images + +You might wonder why an external image resource (storage) is needed when using `docker-compose.prod.yml` instead of `docker-compose.override.yml`. Answer to this is related to a limitation of Docker Compose file format. This is how we set the environment configuration of Catalog microservice in `docker-compose.override.yml`: + +``` +PicBaseUrl=${ESHOP_AZURE_STORAGE_CATALOG:-http://localhost:5101/api/v1/catalog/items/[0]/pic/} +``` + +The `PicBaseUrl` variable is set to the value of `ESHOP_AZURE_STORAGE_CATALOG` if this variable is set to any value other than blank string. If not, the value is set to `http://localhost:5101/api/v1/catalog/items/[0]/pic/`. That works perfectly in a local environment where you run all your services in `localhost` and setting `ESHOP_AZURE_STORAGE_CATALOG` you can use or not Azure Storage for the images (if you don't use Azure Storage images are served locally by catalog servide). But when you run the services in a external docker host, specified in `ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP`, the configuration should be as follows: + +``` +PicBaseUrl=${ESHOP_AZURE_STORAGE_CATALOG:-http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5101/api/v1/catalog/items/[0]/pic/} +``` + +So, use `ESHOP_AZURE_STORAGE_CATALOG` if set, and if not use `http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5101/api/v1/catalog/items/[0]/pic/}`. Unfortunately seems that docker-compose do not substitute variables inside variables, so the value that `PicBaseUrl` gets if `ESHOP_AZURE_STORAGE_CATALOG` is not set is literally `http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5101/api/v1/catalog/items/[0]/pic/}` without any substitution. + +**For more information** about docker-compose variable substitution read the [compose docs](https://docs.docker.com/compose/compose-file/#variable-substitution). + +## Other files + +* `docker-compose.nobuild.yml`: This file contains the definition of all images needed to run the eShopOnContainers. Contains **the same images that `docker-compose.yml`** but without any `build` instruction. If you use this file instead of `docker-compose.yml` when launching the project and you don't have the images built locally, **the images will be pulled from dockerhub**. This file is not intended for development usage, but for some CI/CD scenarios. +* `docker-compose.vs.debug.yml`: This file is used by Docker Tools of VS2017, and should not be used directly. +* `docker-compose.vs.release.yml`: This file is used by Docker Tools of VS2017, and should not be used directly. + +**Note**: The reason why we need the `docker-compose.nobuild.yml` is that [docker-compose issue #3391](https://github.com/docker/compose/issues/3391). Once solved, parameter `--no-build` of docker-compose could be used safely in a CI/CD environments and the need for this file will disappear. + + +## Windows container files + +All `docker-compose-windows*.yml` files have a 1:1 relationship with the same file without the `-windows` in its name. Those files are used to run Windows Containers instead of Linux Containers. + +* `docker-compose-windows.yml`: Contains the definitions of all containers that are needed to run eShopOnContainers using windows containers (equivalent to `docker-compose.yml`). +* `docker-compose-windows.override.yml`: Contains the base configuration for all windows containers + +**Note** We plan **to remove** the `docker-compose-windows.override.yml` file, because it is **exactly the same** as the `docker-compose.override.yml`. The reason of its existence is historical, but is no longer needed. You can use `docker-compose.override.yml` instead. + +* `docker-compose-windows.prod.yml` is the equivalent of `docker-compose.prod.yml` for containers windows. As happens with `docker-compose-windows.override.yml` this file will be deleted in a near future, so you should use `docker-compose.prod.yml` instead. + +## "External container" files + +These files were intended to provide a fast way to start only "infrastructure" containers (SQL Server, Redis, etc). *This files are deprecated and will be deleted in a near future**: + +* `docker-compose-external.override.yml` +* `docker-compose-external.yml` + +If you want to start only certain containers use `docker-compose -f ... -f ... up container1 contaner2 containerN` as specified in [compose doc](https://docs.docker.com/compose/reference/up/) \ No newline at end of file diff --git a/readme/readme.md b/readme/readme.md new file mode 100644 index 000000000..b6280f56d --- /dev/null +++ b/readme/readme.md @@ -0,0 +1,19 @@ +# Documentation index + +This file contains links to the documentation of the project. + +* **Wiki**: The wiki contains detailed step-by-step information about how to set up the project. Read it at: [https://github.com/dotnet-architecture/eShopOnContainers/wiki](https://github.com/dotnet-architecture/eShopOnContainers/wiki) + +## Documentation included in files + +* [Branch Guide](../branch-guide.md): List of branches used and their purpose. +* [vsts-docs folder](../vsts-docs/readme.md): Information about how to setup a CI/CD procedure using VSTS +* [Kubernetes](../k8s/readme.md): Information about how to deploy eShopOnContainers in a kubernetes cluster, and how to setup a CI/CD for k8s using VSTS +* [deploy](../deploy/readme.md): Information about how deploy Azure resources using the Azure CLI 2.0. +* [.env file](./README.ENV.md): What is the `.env` file and how to use it to configure eShopOnContainers to use external resources (like Azure) +* [docker-compose files](./readme-docker-compose.md): What are all these `docker-compose-*.yml` files + +## Docs folder + +The `/docs` folder contains the pdfs versions of the books + diff --git a/src/BuildingBlocks/DataProtection/DataProtection/DataProtection.csproj b/src/BuildingBlocks/DataProtection/DataProtection/DataProtection.csproj index bfe61a85a..c5266d0a9 100644 --- a/src/BuildingBlocks/DataProtection/DataProtection/DataProtection.csproj +++ b/src/BuildingBlocks/DataProtection/DataProtection/DataProtection.csproj @@ -1,7 +1,7 @@  - netcoreapp1.1 + netstandard1.5 Microsoft.eShopOnContainers.BuildingBlocks diff --git a/src/BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj b/src/BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj index 1387a74dd..48f96ab59 100644 --- a/src/BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj +++ b/src/BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj @@ -1,11 +1,11 @@  - netcoreapp1.1 + netstandard2.0 - + diff --git a/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj b/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj index fe7e35d98..22a2d3091 100644 --- a/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj +++ b/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj @@ -1,7 +1,7 @@  - netcoreapp1.1 + netstandard2.0 Microsoft.eShopOnContainers.BuildingBlocks.EventBus @@ -10,8 +10,7 @@ - - + \ No newline at end of file diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs index 07a130f22..f438623a6 100644 --- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs +++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs @@ -11,10 +11,7 @@ using RabbitMQ.Client; using RabbitMQ.Client.Events; using RabbitMQ.Client.Exceptions; using System; -using System.Collections.Generic; -using System.Linq; using System.Net.Sockets; -using System.Reflection; using System.Text; using System.Threading.Tasks; @@ -184,7 +181,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ }; channel.BasicConsume(queue: _queueName, - noAck: true, + autoAck: false, consumer: consumer); channel.CallbackException += (sender, ea) => diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj index d7e3a58d8..6966a57f1 100644 --- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj +++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj @@ -1,17 +1,17 @@  - netcoreapp1.1 + netstandard2.0 Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ - - - - - - + + + + + + diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/DefaultServiceBusPersisterConnection.cs b/src/BuildingBlocks/EventBus/EventBusServiceBus/DefaultServiceBusPersisterConnection.cs index db1b6b390..a3f563c2f 100644 --- a/src/BuildingBlocks/EventBus/EventBusServiceBus/DefaultServiceBusPersisterConnection.cs +++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/DefaultServiceBusPersisterConnection.cs @@ -1,7 +1,6 @@ using Microsoft.Azure.ServiceBus; using Microsoft.Extensions.Logging; using System; -using System.IO; namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus { diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs index 50f588ac3..03a3d1139 100644 --- a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs +++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs @@ -1,18 +1,16 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus { - using System; + using Autofac; + using Microsoft.Azure.ServiceBus; + using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; using Microsoft.Extensions.Logging; - using Microsoft.Azure.ServiceBus; using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + using System; using System.Text; using System.Threading.Tasks; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; - using System.Reflection; - using Microsoft.Azure.ServiceBus.Filters; - using Autofac; - using Newtonsoft.Json.Linq; public class EventBusServiceBus : IEventBus { @@ -129,11 +127,25 @@ _subscriptionClient.RegisterMessageHandler( async (message, token) => { - var eventName = message.Label; + var eventName = $"{message.Label}{INTEGRATION_EVENT_SUFIX}"; var messageData = Encoding.UTF8.GetString(message.Body); await ProcessEvent(eventName, messageData); + + // Complete the message so that it is not received again. + await _subscriptionClient.CompleteAsync(message.SystemProperties.LockToken); }, - new MessageHandlerOptions() { MaxConcurrentCalls = 10, AutoComplete = true }); + new MessageHandlerOptions(ExceptionReceivedHandler) { MaxConcurrentCalls = 10, AutoComplete = false }); + } + + private Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs) + { + Console.WriteLine($"Message handler encountered an exception {exceptionReceivedEventArgs.Exception}."); + var context = exceptionReceivedEventArgs.ExceptionReceivedContext; + Console.WriteLine("Exception context for troubleshooting:"); + Console.WriteLine($"- Endpoint: {context.Endpoint}"); + Console.WriteLine($"- Entity Path: {context.EntityPath}"); + Console.WriteLine($"- Executing Action: {context.Action}"); + return Task.CompletedTask; } private async Task ProcessEvent(string eventName, string message) @@ -169,13 +181,13 @@ try { _subscriptionClient - .RemoveRuleAsync(SubscriptionClient.DefaultRule) + .RemoveRuleAsync(RuleDescription.DefaultRuleName) .GetAwaiter() .GetResult(); } catch (MessagingEntityNotFoundException) { - _logger.LogInformation($"The messaging entity {SubscriptionClient.DefaultRule} Could not be found."); + _logger.LogInformation($"The messaging entity { RuleDescription.DefaultRuleName } Could not be found."); } } } diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj index 5be30800e..07c7a7607 100644 --- a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj +++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj @@ -1,13 +1,14 @@  - netcoreapp1.1 + netstandard2.0 Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus - - + + + diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/IServiceBusPersisterConnection.cs b/src/BuildingBlocks/EventBus/EventBusServiceBus/IServiceBusPersisterConnection.cs index 283031247..52737cef7 100644 --- a/src/BuildingBlocks/EventBus/EventBusServiceBus/IServiceBusPersisterConnection.cs +++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/IServiceBusPersisterConnection.cs @@ -1,7 +1,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus { - using System; using Microsoft.Azure.ServiceBus; + using System; public interface IServiceBusPersisterConnection : IDisposable { diff --git a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj index cc3d51f6a..8d5c8f0ad 100644 --- a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj +++ b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj @@ -1,22 +1,21 @@  - netcoreapp1.1 + netstandard2.0 Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF - - - - - - - + + + + + + - + diff --git a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IntegrationEventLogService.cs b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IntegrationEventLogService.cs index bef74b452..5ac8bb862 100644 --- a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IntegrationEventLogService.cs +++ b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IntegrationEventLogService.cs @@ -6,6 +6,7 @@ using System.Data.Common; using System.Linq; using System.Threading.Tasks; using System; +using Microsoft.EntityFrameworkCore.Diagnostics; namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services { diff --git a/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.AzureStorage/Microsoft.Extensions.HealthChecks.AzureStorage.csproj b/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.AzureStorage/Microsoft.Extensions.HealthChecks.AzureStorage.csproj index 24d5ce92b..0007d0be6 100644 --- a/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.AzureStorage/Microsoft.Extensions.HealthChecks.AzureStorage.csproj +++ b/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.AzureStorage/Microsoft.Extensions.HealthChecks.AzureStorage.csproj @@ -1,8 +1,7 @@  - netstandard1.3 - $(PackageTargetFallback);net46 + netstandard2.0 false false false @@ -17,11 +16,11 @@ - + - - + + diff --git a/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/Microsoft.Extensions.HealthChecks.csproj b/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/Microsoft.Extensions.HealthChecks.csproj index c0a9c571a..8ef22e156 100644 --- a/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/Microsoft.Extensions.HealthChecks.csproj +++ b/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/Microsoft.Extensions.HealthChecks.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/BuildingBlocks/Resilience/Resilience.Http/Resilience.Http.csproj b/src/BuildingBlocks/Resilience/Resilience.Http/Resilience.Http.csproj index e472bb7a5..e1c32cff2 100644 --- a/src/BuildingBlocks/Resilience/Resilience.Http/Resilience.Http.csproj +++ b/src/BuildingBlocks/Resilience/Resilience.Http/Resilience.Http.csproj @@ -1,14 +1,14 @@  - netstandard1.4 + netstandard2.0 Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http - - - + + + \ No newline at end of file diff --git a/src/BuildingBlocks/Resilience/Resilience.Http/StandardHttpClient.cs b/src/BuildingBlocks/Resilience/Resilience.Http/StandardHttpClient.cs index 423fc42bb..6cd378c88 100644 --- a/src/BuildingBlocks/Resilience/Resilience.Http/StandardHttpClient.cs +++ b/src/BuildingBlocks/Resilience/Resilience.Http/StandardHttpClient.cs @@ -40,7 +40,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http throw new ArgumentException("Value must be either post or put.", nameof(method)); } - // a new StringContent must be created for each retry + // a new StringContent must be created for each retry // as it is disposed after each call var requestMessage = new HttpRequestMessage(method, uri); @@ -59,7 +59,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http var response = await _client.SendAsync(requestMessage); - // raise exception if HttpResponseCode 500 + // raise exception if HttpResponseCode 500 // needed for circuit breaker to track fails if (response.StatusCode == HttpStatusCode.InternalServerError) @@ -73,12 +73,12 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http public async Task PostAsync(string uri, T item, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer") { - return await DoPostPutAsync(HttpMethod.Post, uri, item, authorizationToken, requestId, authorizationToken); + return await DoPostPutAsync(HttpMethod.Post, uri, item, authorizationToken, requestId, authorizationMethod); } public async Task PutAsync(string uri, T item, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer") { - return await DoPostPutAsync(HttpMethod.Put, uri, item, authorizationToken, requestId, authorizationToken); + return await DoPostPutAsync(HttpMethod.Put, uri, item, authorizationToken, requestId, authorizationMethod); } public async Task DeleteAsync(string uri, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer") { diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/App.xaml b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/App.xaml index 9aabf918c..79b0ff307 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/App.xaml +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/App.xaml @@ -1,12 +1,11 @@ - + - + #ffffff @@ -18,6 +17,69 @@ #00857D #e2e2e2 #ff5252 + #757575 + #FFFFFF + #979797 + #007aff + #CCCCCC + #C9C9C9 + Transparent + Transparent + #007aff + #FFFFFF + #007aff + Transparent + #FFFFFF + #1FAECE + Transparent + Transparent + + + + + + + + + + + + + + + + + - + + + + + + - - - - - - + + + + + + + + + + + + + + + + + banner3b \ No newline at end of file diff --git a/src/Web/WebStatus/wwwroot/images/banner4.svg b/src/Web/WebStatus/wwwroot/images/banner4.svg deleted file mode 100644 index 38b3d7cd1..000000000 --- a/src/Web/WebStatus/wwwroot/images/banner4.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/Web/WebStatus/wwwroot/js/site.js b/src/Web/WebStatus/wwwroot/js/site.js deleted file mode 100644 index 82ecce7b4..000000000 --- a/src/Web/WebStatus/wwwroot/js/site.js +++ /dev/null @@ -1 +0,0 @@ -// Write your Javascript code. diff --git a/src/Web/WebStatus/wwwroot/js/site.min.js b/src/Web/WebStatus/wwwroot/js/site.min.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/Web/WebStatus/wwwroot/lib/jquery-validation-unobtrusive/.bower.json b/src/Web/WebStatus/wwwroot/lib/jquery-validation-unobtrusive/.bower.json deleted file mode 100644 index ccf48121d..000000000 --- a/src/Web/WebStatus/wwwroot/lib/jquery-validation-unobtrusive/.bower.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "jquery-validation-unobtrusive", - "version": "3.2.6", - "homepage": "https://github.com/aspnet/jquery-validation-unobtrusive", - "description": "Add-on to jQuery Validation to enable unobtrusive validation options in data-* attributes.", - "main": [ - "jquery.validate.unobtrusive.js" - ], - "ignore": [ - "**/.*", - "*.json", - "*.md", - "*.txt", - "gulpfile.js" - ], - "keywords": [ - "jquery", - "asp.net", - "mvc", - "validation", - "unobtrusive" - ], - "authors": [ - "Microsoft" - ], - "license": "http://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm", - "repository": { - "type": "git", - "url": "git://github.com/aspnet/jquery-validation-unobtrusive.git" - }, - "dependencies": { - "jquery-validation": ">=1.8", - "jquery": ">=1.8" - }, - "_release": "3.2.6", - "_resolution": { - "type": "version", - "tag": "v3.2.6", - "commit": "13386cd1b5947d8a5d23a12b531ce3960be1eba7" - }, - "_source": "git://github.com/aspnet/jquery-validation-unobtrusive.git", - "_target": "3.2.6", - "_originalSource": "jquery-validation-unobtrusive" -} \ No newline at end of file diff --git a/src/Web/WebStatus/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js b/src/Web/WebStatus/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js deleted file mode 100644 index 1b0de1249..000000000 --- a/src/Web/WebStatus/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js +++ /dev/null @@ -1,416 +0,0 @@ -/*! -** Unobtrusive validation support library for jQuery and jQuery Validate -** Copyright (C) Microsoft Corporation. All rights reserved. -*/ - -/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */ -/*global document: false, jQuery: false */ - -(function ($) { - var $jQval = $.validator, - adapters, - data_validation = "unobtrusiveValidation"; - - function setValidationValues(options, ruleName, value) { - options.rules[ruleName] = value; - if (options.message) { - options.messages[ruleName] = options.message; - } - } - - function splitAndTrim(value) { - return value.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g); - } - - function escapeAttributeValue(value) { - // As mentioned on http://api.jquery.com/category/selectors/ - return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1"); - } - - function getModelPrefix(fieldName) { - return fieldName.substr(0, fieldName.lastIndexOf(".") + 1); - } - - function appendModelPrefix(value, prefix) { - if (value.indexOf("*.") === 0) { - value = value.replace("*.", prefix); - } - return value; - } - - function onError(error, inputElement) { // 'this' is the form element - var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"), - replaceAttrValue = container.attr("data-valmsg-replace"), - replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null; - - container.removeClass("field-validation-valid").addClass("field-validation-error"); - error.data("unobtrusiveContainer", container); - - if (replace) { - container.empty(); - error.removeClass("input-validation-error").appendTo(container); - } - else { - error.hide(); - } - } - - function onErrors(event, validator) { // 'this' is the form element - var container = $(this).find("[data-valmsg-summary=true]"), - list = container.find("ul"); - - if (list && list.length && validator.errorList.length) { - list.empty(); - container.addClass("validation-summary-errors").removeClass("validation-summary-valid"); - - $.each(validator.errorList, function () { - $("

  • ").html(this.message).appendTo(list); - }); - } - } - - function onSuccess(error) { // 'this' is the form element - var container = error.data("unobtrusiveContainer"); - - if (container) { - var replaceAttrValue = container.attr("data-valmsg-replace"), - replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) : null; - - container.addClass("field-validation-valid").removeClass("field-validation-error"); - error.removeData("unobtrusiveContainer"); - - if (replace) { - container.empty(); - } - } - } - - function onReset(event) { // 'this' is the form element - var $form = $(this), - key = '__jquery_unobtrusive_validation_form_reset'; - if ($form.data(key)) { - return; - } - // Set a flag that indicates we're currently resetting the form. - $form.data(key, true); - try { - $form.data("validator").resetForm(); - } finally { - $form.removeData(key); - } - - $form.find(".validation-summary-errors") - .addClass("validation-summary-valid") - .removeClass("validation-summary-errors"); - $form.find(".field-validation-error") - .addClass("field-validation-valid") - .removeClass("field-validation-error") - .removeData("unobtrusiveContainer") - .find(">*") // If we were using valmsg-replace, get the underlying error - .removeData("unobtrusiveContainer"); - } - - function validationInfo(form) { - var $form = $(form), - result = $form.data(data_validation), - onResetProxy = $.proxy(onReset, form), - defaultOptions = $jQval.unobtrusive.options || {}, - execInContext = function (name, args) { - var func = defaultOptions[name]; - func && $.isFunction(func) && func.apply(form, args); - } - - if (!result) { - result = { - options: { // options structure passed to jQuery Validate's validate() method - errorClass: defaultOptions.errorClass || "input-validation-error", - errorElement: defaultOptions.errorElement || "span", - errorPlacement: function () { - onError.apply(form, arguments); - execInContext("errorPlacement", arguments); - }, - invalidHandler: function () { - onErrors.apply(form, arguments); - execInContext("invalidHandler", arguments); - }, - messages: {}, - rules: {}, - success: function () { - onSuccess.apply(form, arguments); - execInContext("success", arguments); - } - }, - attachValidation: function () { - $form - .off("reset." + data_validation, onResetProxy) - .on("reset." + data_validation, onResetProxy) - .validate(this.options); - }, - validate: function () { // a validation function that is called by unobtrusive Ajax - $form.validate(); - return $form.valid(); - } - }; - $form.data(data_validation, result); - } - - return result; - } - - $jQval.unobtrusive = { - adapters: [], - - parseElement: function (element, skipAttach) { - /// - /// Parses a single HTML element for unobtrusive validation attributes. - /// - /// The HTML element to be parsed. - /// [Optional] true to skip attaching the - /// validation to the form. If parsing just this single element, you should specify true. - /// If parsing several elements, you should specify false, and manually attach the validation - /// to the form when you are finished. The default is false. - var $element = $(element), - form = $element.parents("form")[0], - valInfo, rules, messages; - - if (!form) { // Cannot do client-side validation without a form - return; - } - - valInfo = validationInfo(form); - valInfo.options.rules[element.name] = rules = {}; - valInfo.options.messages[element.name] = messages = {}; - - $.each(this.adapters, function () { - var prefix = "data-val-" + this.name, - message = $element.attr(prefix), - paramValues = {}; - - if (message !== undefined) { // Compare against undefined, because an empty message is legal (and falsy) - prefix += "-"; - - $.each(this.params, function () { - paramValues[this] = $element.attr(prefix + this); - }); - - this.adapt({ - element: element, - form: form, - message: message, - params: paramValues, - rules: rules, - messages: messages - }); - } - }); - - $.extend(rules, { "__dummy__": true }); - - if (!skipAttach) { - valInfo.attachValidation(); - } - }, - - parse: function (selector) { - /// - /// Parses all the HTML elements in the specified selector. It looks for input elements decorated - /// with the [data-val=true] attribute value and enables validation according to the data-val-* - /// attribute values. - /// - /// Any valid jQuery selector. - - // $forms includes all forms in selector's DOM hierarchy (parent, children and self) that have at least one - // element with data-val=true - var $selector = $(selector), - $forms = $selector.parents() - .addBack() - .filter("form") - .add($selector.find("form")) - .has("[data-val=true]"); - - $selector.find("[data-val=true]").each(function () { - $jQval.unobtrusive.parseElement(this, true); - }); - - $forms.each(function () { - var info = validationInfo(this); - if (info) { - info.attachValidation(); - } - }); - } - }; - - adapters = $jQval.unobtrusive.adapters; - - adapters.add = function (adapterName, params, fn) { - /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation. - /// The name of the adapter to be added. This matches the name used - /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). - /// [Optional] An array of parameter names (strings) that will - /// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and - /// mmmm is the parameter name). - /// The function to call, which adapts the values from the HTML - /// attributes into jQuery Validate rules and/or messages. - /// - if (!fn) { // Called with no params, just a function - fn = params; - params = []; - } - this.push({ name: adapterName, params: params, adapt: fn }); - return this; - }; - - adapters.addBool = function (adapterName, ruleName) { - /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where - /// the jQuery Validate validation rule has no parameter values. - /// The name of the adapter to be added. This matches the name used - /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). - /// [Optional] The name of the jQuery Validate rule. If not provided, the value - /// of adapterName will be used instead. - /// - return this.add(adapterName, function (options) { - setValidationValues(options, ruleName || adapterName, true); - }); - }; - - adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) { - /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where - /// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and - /// one for min-and-max). The HTML parameters are expected to be named -min and -max. - /// The name of the adapter to be added. This matches the name used - /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). - /// The name of the jQuery Validate rule to be used when you only - /// have a minimum value. - /// The name of the jQuery Validate rule to be used when you only - /// have a maximum value. - /// The name of the jQuery Validate rule to be used when you - /// have both a minimum and maximum value. - /// [Optional] The name of the HTML attribute that - /// contains the minimum value. The default is "min". - /// [Optional] The name of the HTML attribute that - /// contains the maximum value. The default is "max". - /// - return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) { - var min = options.params.min, - max = options.params.max; - - if (min && max) { - setValidationValues(options, minMaxRuleName, [min, max]); - } - else if (min) { - setValidationValues(options, minRuleName, min); - } - else if (max) { - setValidationValues(options, maxRuleName, max); - } - }); - }; - - adapters.addSingleVal = function (adapterName, attribute, ruleName) { - /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where - /// the jQuery Validate validation rule has a single value. - /// The name of the adapter to be added. This matches the name used - /// in the data-val-nnnn HTML attribute(where nnnn is the adapter name). - /// [Optional] The name of the HTML attribute that contains the value. - /// The default is "val". - /// [Optional] The name of the jQuery Validate rule. If not provided, the value - /// of adapterName will be used instead. - /// - return this.add(adapterName, [attribute || "val"], function (options) { - setValidationValues(options, ruleName || adapterName, options.params[attribute]); - }); - }; - - $jQval.addMethod("__dummy__", function (value, element, params) { - return true; - }); - - $jQval.addMethod("regex", function (value, element, params) { - var match; - if (this.optional(element)) { - return true; - } - - match = new RegExp(params).exec(value); - return (match && (match.index === 0) && (match[0].length === value.length)); - }); - - $jQval.addMethod("nonalphamin", function (value, element, nonalphamin) { - var match; - if (nonalphamin) { - match = value.match(/\W/g); - match = match && match.length >= nonalphamin; - } - return match; - }); - - if ($jQval.methods.extension) { - adapters.addSingleVal("accept", "mimtype"); - adapters.addSingleVal("extension", "extension"); - } else { - // for backward compatibility, when the 'extension' validation method does not exist, such as with versions - // of JQuery Validation plugin prior to 1.10, we should use the 'accept' method for - // validating the extension, and ignore mime-type validations as they are not supported. - adapters.addSingleVal("extension", "extension", "accept"); - } - - adapters.addSingleVal("regex", "pattern"); - adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"); - adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range"); - adapters.addMinMax("minlength", "minlength").addMinMax("maxlength", "minlength", "maxlength"); - adapters.add("equalto", ["other"], function (options) { - var prefix = getModelPrefix(options.element.name), - other = options.params.other, - fullOtherName = appendModelPrefix(other, prefix), - element = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(fullOtherName) + "']")[0]; - - setValidationValues(options, "equalTo", element); - }); - adapters.add("required", function (options) { - // jQuery Validate equates "required" with "mandatory" for checkbox elements - if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") { - setValidationValues(options, "required", true); - } - }); - adapters.add("remote", ["url", "type", "additionalfields"], function (options) { - var value = { - url: options.params.url, - type: options.params.type || "GET", - data: {} - }, - prefix = getModelPrefix(options.element.name); - - $.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) { - var paramName = appendModelPrefix(fieldName, prefix); - value.data[paramName] = function () { - var field = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(paramName) + "']"); - // For checkboxes and radio buttons, only pick up values from checked fields. - if (field.is(":checkbox")) { - return field.filter(":checked").val() || field.filter(":hidden").val() || ''; - } - else if (field.is(":radio")) { - return field.filter(":checked").val() || ''; - } - return field.val(); - }; - }); - - setValidationValues(options, "remote", value); - }); - adapters.add("password", ["min", "nonalphamin", "regex"], function (options) { - if (options.params.min) { - setValidationValues(options, "minlength", options.params.min); - } - if (options.params.nonalphamin) { - setValidationValues(options, "nonalphamin", options.params.nonalphamin); - } - if (options.params.regex) { - setValidationValues(options, "regex", options.params.regex); - } - }); - - $(function () { - $jQval.unobtrusive.parse(document); - }); -}(jQuery)); \ No newline at end of file diff --git a/src/Web/WebStatus/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js b/src/Web/WebStatus/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js deleted file mode 100644 index be9a38a4c..000000000 --- a/src/Web/WebStatus/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js +++ /dev/null @@ -1,5 +0,0 @@ -/* -** Unobtrusive validation support library for jQuery and jQuery Validate -** Copyright (C) Microsoft Corporation. All rights reserved. -*/ -!function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a("
  • ").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function m(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=p.unobtrusive.options||{},m=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),m("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),m("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),m("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var u,p=a.validator,v="unobtrusiveValidation";p.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=m(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){p.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=m(this);a&&a.attachValidation()})}},u=p.unobtrusive.adapters,u.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},u.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},u.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},u.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},p.addMethod("__dummy__",function(a,e,n){return!0}),p.addMethod("regex",function(a,e,n){var t;return this.optional(e)?!0:(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),p.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),p.methods.extension?(u.addSingleVal("accept","mimtype"),u.addSingleVal("extension","extension")):u.addSingleVal("extension","extension","accept"),u.addSingleVal("regex","pattern"),u.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),u.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),u.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),u.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),u.add("required",function(a){("INPUT"!==a.element.tagName.toUpperCase()||"CHECKBOX"!==a.element.type.toUpperCase())&&e(a,"required",!0)}),u.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),u.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),a(function(){p.unobtrusive.parse(document)})}(jQuery); \ No newline at end of file diff --git a/src/Web/WebStatus/wwwroot/lib/jquery-validation/.bower.json b/src/Web/WebStatus/wwwroot/lib/jquery-validation/.bower.json deleted file mode 100644 index cab34a4a6..000000000 --- a/src/Web/WebStatus/wwwroot/lib/jquery-validation/.bower.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "jquery-validation", - "homepage": "http://jqueryvalidation.org/", - "repository": { - "type": "git", - "url": "git://github.com/jzaefferer/jquery-validation.git" - }, - "authors": [ - "Jörn Zaefferer " - ], - "description": "Form validation made easy", - "main": "dist/jquery.validate.js", - "keywords": [ - "forms", - "validation", - "validate" - ], - "license": "MIT", - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "test", - "demo", - "lib" - ], - "dependencies": { - "jquery": ">= 1.7.2" - }, - "version": "1.14.0", - "_release": "1.14.0", - "_resolution": { - "type": "version", - "tag": "1.14.0", - "commit": "c1343fb9823392aa9acbe1c3ffd337b8c92fed48" - }, - "_source": "git://github.com/jzaefferer/jquery-validation.git", - "_target": ">=1.8", - "_originalSource": "jquery-validation" -} \ No newline at end of file diff --git a/src/Web/WebStatus/wwwroot/lib/jquery-validation/LICENSE.md b/src/Web/WebStatus/wwwroot/lib/jquery-validation/LICENSE.md deleted file mode 100644 index dc377cc03..000000000 --- a/src/Web/WebStatus/wwwroot/lib/jquery-validation/LICENSE.md +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) -===================== - -Copyright Jörn Zaefferer - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/src/Web/WebStatus/wwwroot/lib/jquery-validation/dist/additional-methods.js b/src/Web/WebStatus/wwwroot/lib/jquery-validation/dist/additional-methods.js deleted file mode 100644 index df41fbd40..000000000 --- a/src/Web/WebStatus/wwwroot/lib/jquery-validation/dist/additional-methods.js +++ /dev/null @@ -1,998 +0,0 @@ -/*! - * jQuery Validation Plugin v1.14.0 - * - * http://jqueryvalidation.org/ - * - * Copyright (c) 2015 Jörn Zaefferer - * Released under the MIT license - */ -(function( factory ) { - if ( typeof define === "function" && define.amd ) { - define( ["jquery", "./jquery.validate"], factory ); - } else { - factory( jQuery ); - } -}(function( $ ) { - -(function() { - - function stripHtml(value) { - // remove html tags and space chars - return value.replace(/<.[^<>]*?>/g, " ").replace(/ | /gi, " ") - // remove punctuation - .replace(/[.(),;:!?%#$'\"_+=\/\-“”’]*/g, ""); - } - - $.validator.addMethod("maxWords", function(value, element, params) { - return this.optional(element) || stripHtml(value).match(/\b\w+\b/g).length <= params; - }, $.validator.format("Please enter {0} words or less.")); - - $.validator.addMethod("minWords", function(value, element, params) { - return this.optional(element) || stripHtml(value).match(/\b\w+\b/g).length >= params; - }, $.validator.format("Please enter at least {0} words.")); - - $.validator.addMethod("rangeWords", function(value, element, params) { - var valueStripped = stripHtml(value), - regex = /\b\w+\b/g; - return this.optional(element) || valueStripped.match(regex).length >= params[0] && valueStripped.match(regex).length <= params[1]; - }, $.validator.format("Please enter between {0} and {1} words.")); - -}()); - -// Accept a value from a file input based on a required mimetype -$.validator.addMethod("accept", function(value, element, param) { - // Split mime on commas in case we have multiple types we can accept - var typeParam = typeof param === "string" ? param.replace(/\s/g, "").replace(/,/g, "|") : "image/*", - optionalValue = this.optional(element), - i, file; - - // Element is optional - if (optionalValue) { - return optionalValue; - } - - if ($(element).attr("type") === "file") { - // If we are using a wildcard, make it regex friendly - typeParam = typeParam.replace(/\*/g, ".*"); - - // Check if the element has a FileList before checking each file - if (element.files && element.files.length) { - for (i = 0; i < element.files.length; i++) { - file = element.files[i]; - - // Grab the mimetype from the loaded file, verify it matches - if (!file.type.match(new RegExp( "\\.?(" + typeParam + ")$", "i"))) { - return false; - } - } - } - } - - // Either return true because we've validated each file, or because the - // browser does not support element.files and the FileList feature - return true; -}, $.validator.format("Please enter a value with a valid mimetype.")); - -$.validator.addMethod("alphanumeric", function(value, element) { - return this.optional(element) || /^\w+$/i.test(value); -}, "Letters, numbers, and underscores only please"); - -/* - * Dutch bank account numbers (not 'giro' numbers) have 9 digits - * and pass the '11 check'. - * We accept the notation with spaces, as that is common. - * acceptable: 123456789 or 12 34 56 789 - */ -$.validator.addMethod("bankaccountNL", function(value, element) { - if (this.optional(element)) { - return true; - } - if (!(/^[0-9]{9}|([0-9]{2} ){3}[0-9]{3}$/.test(value))) { - return false; - } - // now '11 check' - var account = value.replace(/ /g, ""), // remove spaces - sum = 0, - len = account.length, - pos, factor, digit; - for ( pos = 0; pos < len; pos++ ) { - factor = len - pos; - digit = account.substring(pos, pos + 1); - sum = sum + factor * digit; - } - return sum % 11 === 0; -}, "Please specify a valid bank account number"); - -$.validator.addMethod("bankorgiroaccountNL", function(value, element) { - return this.optional(element) || - ($.validator.methods.bankaccountNL.call(this, value, element)) || - ($.validator.methods.giroaccountNL.call(this, value, element)); -}, "Please specify a valid bank or giro account number"); - -/** - * BIC is the business identifier code (ISO 9362). This BIC check is not a guarantee for authenticity. - * - * BIC pattern: BBBBCCLLbbb (8 or 11 characters long; bbb is optional) - * - * BIC definition in detail: - * - First 4 characters - bank code (only letters) - * - Next 2 characters - ISO 3166-1 alpha-2 country code (only letters) - * - Next 2 characters - location code (letters and digits) - * a. shall not start with '0' or '1' - * b. second character must be a letter ('O' is not allowed) or one of the following digits ('0' for test (therefore not allowed), '1' for passive participant and '2' for active participant) - * - Last 3 characters - branch code, optional (shall not start with 'X' except in case of 'XXX' for primary office) (letters and digits) - */ -$.validator.addMethod("bic", function(value, element) { - return this.optional( element ) || /^([A-Z]{6}[A-Z2-9][A-NP-Z1-2])(X{3}|[A-WY-Z0-9][A-Z0-9]{2})?$/.test( value ); -}, "Please specify a valid BIC code"); - -/* - * Código de identificación fiscal ( CIF ) is the tax identification code for Spanish legal entities - * Further rules can be found in Spanish on http://es.wikipedia.org/wiki/C%C3%B3digo_de_identificaci%C3%B3n_fiscal - */ -$.validator.addMethod( "cifES", function( value ) { - "use strict"; - - var num = [], - controlDigit, sum, i, count, tmp, secondDigit; - - value = value.toUpperCase(); - - // Quick format test - if ( !value.match( "((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)" ) ) { - return false; - } - - for ( i = 0; i < 9; i++ ) { - num[ i ] = parseInt( value.charAt( i ), 10 ); - } - - // Algorithm for checking CIF codes - sum = num[ 2 ] + num[ 4 ] + num[ 6 ]; - for ( count = 1; count < 8; count += 2 ) { - tmp = ( 2 * num[ count ] ).toString(); - secondDigit = tmp.charAt( 1 ); - - sum += parseInt( tmp.charAt( 0 ), 10 ) + ( secondDigit === "" ? 0 : parseInt( secondDigit, 10 ) ); - } - - /* The first (position 1) is a letter following the following criteria: - * A. Corporations - * B. LLCs - * C. General partnerships - * D. Companies limited partnerships - * E. Communities of goods - * F. Cooperative Societies - * G. Associations - * H. Communities of homeowners in horizontal property regime - * J. Civil Societies - * K. Old format - * L. Old format - * M. Old format - * N. Nonresident entities - * P. Local authorities - * Q. Autonomous bodies, state or not, and the like, and congregations and religious institutions - * R. Congregations and religious institutions (since 2008 ORDER EHA/451/2008) - * S. Organs of State Administration and regions - * V. Agrarian Transformation - * W. Permanent establishments of non-resident in Spain - */ - if ( /^[ABCDEFGHJNPQRSUVW]{1}/.test( value ) ) { - sum += ""; - controlDigit = 10 - parseInt( sum.charAt( sum.length - 1 ), 10 ); - value += controlDigit; - return ( num[ 8 ].toString() === String.fromCharCode( 64 + controlDigit ) || num[ 8 ].toString() === value.charAt( value.length - 1 ) ); - } - - return false; - -}, "Please specify a valid CIF number." ); - -/* - * Brazillian CPF number (Cadastrado de Pessoas Físicas) is the equivalent of a Brazilian tax registration number. - * CPF numbers have 11 digits in total: 9 numbers followed by 2 check numbers that are being used for validation. - */ -$.validator.addMethod("cpfBR", function(value) { - // Removing special characters from value - value = value.replace(/([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g, ""); - - // Checking value to have 11 digits only - if (value.length !== 11) { - return false; - } - - var sum = 0, - firstCN, secondCN, checkResult, i; - - firstCN = parseInt(value.substring(9, 10), 10); - secondCN = parseInt(value.substring(10, 11), 10); - - checkResult = function(sum, cn) { - var result = (sum * 10) % 11; - if ((result === 10) || (result === 11)) {result = 0;} - return (result === cn); - }; - - // Checking for dump data - if (value === "" || - value === "00000000000" || - value === "11111111111" || - value === "22222222222" || - value === "33333333333" || - value === "44444444444" || - value === "55555555555" || - value === "66666666666" || - value === "77777777777" || - value === "88888888888" || - value === "99999999999" - ) { - return false; - } - - // Step 1 - using first Check Number: - for ( i = 1; i <= 9; i++ ) { - sum = sum + parseInt(value.substring(i - 1, i), 10) * (11 - i); - } - - // If first Check Number (CN) is valid, move to Step 2 - using second Check Number: - if ( checkResult(sum, firstCN) ) { - sum = 0; - for ( i = 1; i <= 10; i++ ) { - sum = sum + parseInt(value.substring(i - 1, i), 10) * (12 - i); - } - return checkResult(sum, secondCN); - } - return false; - -}, "Please specify a valid CPF number"); - -/* NOTICE: Modified version of Castle.Components.Validator.CreditCardValidator - * Redistributed under the the Apache License 2.0 at http://www.apache.org/licenses/LICENSE-2.0 - * Valid Types: mastercard, visa, amex, dinersclub, enroute, discover, jcb, unknown, all (overrides all other settings) - */ -$.validator.addMethod("creditcardtypes", function(value, element, param) { - if (/[^0-9\-]+/.test(value)) { - return false; - } - - value = value.replace(/\D/g, ""); - - var validTypes = 0x0000; - - if (param.mastercard) { - validTypes |= 0x0001; - } - if (param.visa) { - validTypes |= 0x0002; - } - if (param.amex) { - validTypes |= 0x0004; - } - if (param.dinersclub) { - validTypes |= 0x0008; - } - if (param.enroute) { - validTypes |= 0x0010; - } - if (param.discover) { - validTypes |= 0x0020; - } - if (param.jcb) { - validTypes |= 0x0040; - } - if (param.unknown) { - validTypes |= 0x0080; - } - if (param.all) { - validTypes = 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080; - } - if (validTypes & 0x0001 && /^(5[12345])/.test(value)) { //mastercard - return value.length === 16; - } - if (validTypes & 0x0002 && /^(4)/.test(value)) { //visa - return value.length === 16; - } - if (validTypes & 0x0004 && /^(3[47])/.test(value)) { //amex - return value.length === 15; - } - if (validTypes & 0x0008 && /^(3(0[012345]|[68]))/.test(value)) { //dinersclub - return value.length === 14; - } - if (validTypes & 0x0010 && /^(2(014|149))/.test(value)) { //enroute - return value.length === 15; - } - if (validTypes & 0x0020 && /^(6011)/.test(value)) { //discover - return value.length === 16; - } - if (validTypes & 0x0040 && /^(3)/.test(value)) { //jcb - return value.length === 16; - } - if (validTypes & 0x0040 && /^(2131|1800)/.test(value)) { //jcb - return value.length === 15; - } - if (validTypes & 0x0080) { //unknown - return true; - } - return false; -}, "Please enter a valid credit card number."); - -/** - * Validates currencies with any given symbols by @jameslouiz - * Symbols can be optional or required. Symbols required by default - * - * Usage examples: - * currency: ["£", false] - Use false for soft currency validation - * currency: ["$", false] - * currency: ["RM", false] - also works with text based symbols such as "RM" - Malaysia Ringgit etc - * - * - * - * Soft symbol checking - * currencyInput: { - * currency: ["$", false] - * } - * - * Strict symbol checking (default) - * currencyInput: { - * currency: "$" - * //OR - * currency: ["$", true] - * } - * - * Multiple Symbols - * currencyInput: { - * currency: "$,£,¢" - * } - */ -$.validator.addMethod("currency", function(value, element, param) { - var isParamString = typeof param === "string", - symbol = isParamString ? param : param[0], - soft = isParamString ? true : param[1], - regex; - - symbol = symbol.replace(/,/g, ""); - symbol = soft ? symbol + "]" : symbol + "]?"; - regex = "^[" + symbol + "([1-9]{1}[0-9]{0,2}(\\,[0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)$"; - regex = new RegExp(regex); - return this.optional(element) || regex.test(value); - -}, "Please specify a valid currency"); - -$.validator.addMethod("dateFA", function(value, element) { - return this.optional(element) || /^[1-4]\d{3}\/((0?[1-6]\/((3[0-1])|([1-2][0-9])|(0?[1-9])))|((1[0-2]|(0?[7-9]))\/(30|([1-2][0-9])|(0?[1-9]))))$/.test(value); -}, $.validator.messages.date); - -/** - * Return true, if the value is a valid date, also making this formal check dd/mm/yyyy. - * - * @example $.validator.methods.date("01/01/1900") - * @result true - * - * @example $.validator.methods.date("01/13/1990") - * @result false - * - * @example $.validator.methods.date("01.01.1900") - * @result false - * - * @example - * @desc Declares an optional input element whose value must be a valid date. - * - * @name $.validator.methods.dateITA - * @type Boolean - * @cat Plugins/Validate/Methods - */ -$.validator.addMethod("dateITA", function(value, element) { - var check = false, - re = /^\d{1,2}\/\d{1,2}\/\d{4}$/, - adata, gg, mm, aaaa, xdata; - if ( re.test(value)) { - adata = value.split("/"); - gg = parseInt(adata[0], 10); - mm = parseInt(adata[1], 10); - aaaa = parseInt(adata[2], 10); - xdata = new Date(Date.UTC(aaaa, mm - 1, gg, 12, 0, 0, 0)); - if ( ( xdata.getUTCFullYear() === aaaa ) && ( xdata.getUTCMonth () === mm - 1 ) && ( xdata.getUTCDate() === gg ) ) { - check = true; - } else { - check = false; - } - } else { - check = false; - } - return this.optional(element) || check; -}, $.validator.messages.date); - -$.validator.addMethod("dateNL", function(value, element) { - return this.optional(element) || /^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test(value); -}, $.validator.messages.date); - -// Older "accept" file extension method. Old docs: http://docs.jquery.com/Plugins/Validation/Methods/accept -$.validator.addMethod("extension", function(value, element, param) { - param = typeof param === "string" ? param.replace(/,/g, "|") : "png|jpe?g|gif"; - return this.optional(element) || value.match(new RegExp("\\.(" + param + ")$", "i")); -}, $.validator.format("Please enter a value with a valid extension.")); - -/** - * Dutch giro account numbers (not bank numbers) have max 7 digits - */ -$.validator.addMethod("giroaccountNL", function(value, element) { - return this.optional(element) || /^[0-9]{1,7}$/.test(value); -}, "Please specify a valid giro account number"); - -/** - * IBAN is the international bank account number. - * It has a country - specific format, that is checked here too - */ -$.validator.addMethod("iban", function(value, element) { - // some quick simple tests to prevent needless work - if (this.optional(element)) { - return true; - } - - // remove spaces and to upper case - var iban = value.replace(/ /g, "").toUpperCase(), - ibancheckdigits = "", - leadingZeroes = true, - cRest = "", - cOperator = "", - countrycode, ibancheck, charAt, cChar, bbanpattern, bbancountrypatterns, ibanregexp, i, p; - - // check the country code and find the country specific format - countrycode = iban.substring(0, 2); - bbancountrypatterns = { - "AL": "\\d{8}[\\dA-Z]{16}", - "AD": "\\d{8}[\\dA-Z]{12}", - "AT": "\\d{16}", - "AZ": "[\\dA-Z]{4}\\d{20}", - "BE": "\\d{12}", - "BH": "[A-Z]{4}[\\dA-Z]{14}", - "BA": "\\d{16}", - "BR": "\\d{23}[A-Z][\\dA-Z]", - "BG": "[A-Z]{4}\\d{6}[\\dA-Z]{8}", - "CR": "\\d{17}", - "HR": "\\d{17}", - "CY": "\\d{8}[\\dA-Z]{16}", - "CZ": "\\d{20}", - "DK": "\\d{14}", - "DO": "[A-Z]{4}\\d{20}", - "EE": "\\d{16}", - "FO": "\\d{14}", - "FI": "\\d{14}", - "FR": "\\d{10}[\\dA-Z]{11}\\d{2}", - "GE": "[\\dA-Z]{2}\\d{16}", - "DE": "\\d{18}", - "GI": "[A-Z]{4}[\\dA-Z]{15}", - "GR": "\\d{7}[\\dA-Z]{16}", - "GL": "\\d{14}", - "GT": "[\\dA-Z]{4}[\\dA-Z]{20}", - "HU": "\\d{24}", - "IS": "\\d{22}", - "IE": "[\\dA-Z]{4}\\d{14}", - "IL": "\\d{19}", - "IT": "[A-Z]\\d{10}[\\dA-Z]{12}", - "KZ": "\\d{3}[\\dA-Z]{13}", - "KW": "[A-Z]{4}[\\dA-Z]{22}", - "LV": "[A-Z]{4}[\\dA-Z]{13}", - "LB": "\\d{4}[\\dA-Z]{20}", - "LI": "\\d{5}[\\dA-Z]{12}", - "LT": "\\d{16}", - "LU": "\\d{3}[\\dA-Z]{13}", - "MK": "\\d{3}[\\dA-Z]{10}\\d{2}", - "MT": "[A-Z]{4}\\d{5}[\\dA-Z]{18}", - "MR": "\\d{23}", - "MU": "[A-Z]{4}\\d{19}[A-Z]{3}", - "MC": "\\d{10}[\\dA-Z]{11}\\d{2}", - "MD": "[\\dA-Z]{2}\\d{18}", - "ME": "\\d{18}", - "NL": "[A-Z]{4}\\d{10}", - "NO": "\\d{11}", - "PK": "[\\dA-Z]{4}\\d{16}", - "PS": "[\\dA-Z]{4}\\d{21}", - "PL": "\\d{24}", - "PT": "\\d{21}", - "RO": "[A-Z]{4}[\\dA-Z]{16}", - "SM": "[A-Z]\\d{10}[\\dA-Z]{12}", - "SA": "\\d{2}[\\dA-Z]{18}", - "RS": "\\d{18}", - "SK": "\\d{20}", - "SI": "\\d{15}", - "ES": "\\d{20}", - "SE": "\\d{20}", - "CH": "\\d{5}[\\dA-Z]{12}", - "TN": "\\d{20}", - "TR": "\\d{5}[\\dA-Z]{17}", - "AE": "\\d{3}\\d{16}", - "GB": "[A-Z]{4}\\d{14}", - "VG": "[\\dA-Z]{4}\\d{16}" - }; - - bbanpattern = bbancountrypatterns[countrycode]; - // As new countries will start using IBAN in the - // future, we only check if the countrycode is known. - // This prevents false negatives, while almost all - // false positives introduced by this, will be caught - // by the checksum validation below anyway. - // Strict checking should return FALSE for unknown - // countries. - if (typeof bbanpattern !== "undefined") { - ibanregexp = new RegExp("^[A-Z]{2}\\d{2}" + bbanpattern + "$", ""); - if (!(ibanregexp.test(iban))) { - return false; // invalid country specific format - } - } - - // now check the checksum, first convert to digits - ibancheck = iban.substring(4, iban.length) + iban.substring(0, 4); - for (i = 0; i < ibancheck.length; i++) { - charAt = ibancheck.charAt(i); - if (charAt !== "0") { - leadingZeroes = false; - } - if (!leadingZeroes) { - ibancheckdigits += "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(charAt); - } - } - - // calculate the result of: ibancheckdigits % 97 - for (p = 0; p < ibancheckdigits.length; p++) { - cChar = ibancheckdigits.charAt(p); - cOperator = "" + cRest + "" + cChar; - cRest = cOperator % 97; - } - return cRest === 1; -}, "Please specify a valid IBAN"); - -$.validator.addMethod("integer", function(value, element) { - return this.optional(element) || /^-?\d+$/.test(value); -}, "A positive or negative non-decimal number please"); - -$.validator.addMethod("ipv4", function(value, element) { - return this.optional(element) || /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i.test(value); -}, "Please enter a valid IP v4 address."); - -$.validator.addMethod("ipv6", function(value, element) { - return this.optional(element) || /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i.test(value); -}, "Please enter a valid IP v6 address."); - -$.validator.addMethod("lettersonly", function(value, element) { - return this.optional(element) || /^[a-z]+$/i.test(value); -}, "Letters only please"); - -$.validator.addMethod("letterswithbasicpunc", function(value, element) { - return this.optional(element) || /^[a-z\-.,()'"\s]+$/i.test(value); -}, "Letters or punctuation only please"); - -$.validator.addMethod("mobileNL", function(value, element) { - return this.optional(element) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)6((\s|\s?\-\s?)?[0-9]){8}$/.test(value); -}, "Please specify a valid mobile number"); - -/* For UK phone functions, do the following server side processing: - * Compare original input with this RegEx pattern: - * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$ - * Extract $1 and set $prefix to '+44' if $1 is '44', otherwise set $prefix to '0' - * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2. - * A number of very detailed GB telephone number RegEx patterns can also be found at: - * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers - */ -$.validator.addMethod("mobileUK", function(phone_number, element) { - phone_number = phone_number.replace(/\(|\)|\s+|-/g, ""); - return this.optional(element) || phone_number.length > 9 && - phone_number.match(/^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/); -}, "Please specify a valid mobile number"); - -/* - * The número de identidad de extranjero ( NIE )is a code used to identify the non-nationals in Spain - */ -$.validator.addMethod( "nieES", function( value ) { - "use strict"; - - value = value.toUpperCase(); - - // Basic format test - if ( !value.match( "((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)" ) ) { - return false; - } - - // Test NIE - //T - if ( /^[T]{1}/.test( value ) ) { - return ( value[ 8 ] === /^[T]{1}[A-Z0-9]{8}$/.test( value ) ); - } - - //XYZ - if ( /^[XYZ]{1}/.test( value ) ) { - return ( - value[ 8 ] === "TRWAGMYFPDXBNJZSQVHLCKE".charAt( - value.replace( "X", "0" ) - .replace( "Y", "1" ) - .replace( "Z", "2" ) - .substring( 0, 8 ) % 23 - ) - ); - } - - return false; - -}, "Please specify a valid NIE number." ); - -/* - * The Número de Identificación Fiscal ( NIF ) is the way tax identification used in Spain for individuals - */ -$.validator.addMethod( "nifES", function( value ) { - "use strict"; - - value = value.toUpperCase(); - - // Basic format test - if ( !value.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)") ) { - return false; - } - - // Test NIF - if ( /^[0-9]{8}[A-Z]{1}$/.test( value ) ) { - return ( "TRWAGMYFPDXBNJZSQVHLCKE".charAt( value.substring( 8, 0 ) % 23 ) === value.charAt( 8 ) ); - } - // Test specials NIF (starts with K, L or M) - if ( /^[KLM]{1}/.test( value ) ) { - return ( value[ 8 ] === String.fromCharCode( 64 ) ); - } - - return false; - -}, "Please specify a valid NIF number." ); - -jQuery.validator.addMethod( "notEqualTo", function( value, element, param ) { - return this.optional(element) || !$.validator.methods.equalTo.call( this, value, element, param ); -}, "Please enter a different value, values must not be the same." ); - -$.validator.addMethod("nowhitespace", function(value, element) { - return this.optional(element) || /^\S+$/i.test(value); -}, "No white space please"); - -/** -* Return true if the field value matches the given format RegExp -* -* @example $.validator.methods.pattern("AR1004",element,/^AR\d{4}$/) -* @result true -* -* @example $.validator.methods.pattern("BR1004",element,/^AR\d{4}$/) -* @result false -* -* @name $.validator.methods.pattern -* @type Boolean -* @cat Plugins/Validate/Methods -*/ -$.validator.addMethod("pattern", function(value, element, param) { - if (this.optional(element)) { - return true; - } - if (typeof param === "string") { - param = new RegExp("^(?:" + param + ")$"); - } - return param.test(value); -}, "Invalid format."); - -/** - * Dutch phone numbers have 10 digits (or 11 and start with +31). - */ -$.validator.addMethod("phoneNL", function(value, element) { - return this.optional(element) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test(value); -}, "Please specify a valid phone number."); - -/* For UK phone functions, do the following server side processing: - * Compare original input with this RegEx pattern: - * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$ - * Extract $1 and set $prefix to '+44' if $1 is '44', otherwise set $prefix to '0' - * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2. - * A number of very detailed GB telephone number RegEx patterns can also be found at: - * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers - */ -$.validator.addMethod("phoneUK", function(phone_number, element) { - phone_number = phone_number.replace(/\(|\)|\s+|-/g, ""); - return this.optional(element) || phone_number.length > 9 && - phone_number.match(/^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/); -}, "Please specify a valid phone number"); - -/** - * matches US phone number format - * - * where the area code may not start with 1 and the prefix may not start with 1 - * allows '-' or ' ' as a separator and allows parens around area code - * some people may want to put a '1' in front of their number - * - * 1(212)-999-2345 or - * 212 999 2344 or - * 212-999-0983 - * - * but not - * 111-123-5434 - * and not - * 212 123 4567 - */ -$.validator.addMethod("phoneUS", function(phone_number, element) { - phone_number = phone_number.replace(/\s+/g, ""); - return this.optional(element) || phone_number.length > 9 && - phone_number.match(/^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]([02-9]\d|1[02-9])-?\d{4}$/); -}, "Please specify a valid phone number"); - -/* For UK phone functions, do the following server side processing: - * Compare original input with this RegEx pattern: - * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$ - * Extract $1 and set $prefix to '+44' if $1 is '44', otherwise set $prefix to '0' - * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2. - * A number of very detailed GB telephone number RegEx patterns can also be found at: - * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers - */ -//Matches UK landline + mobile, accepting only 01-3 for landline or 07 for mobile to exclude many premium numbers -$.validator.addMethod("phonesUK", function(phone_number, element) { - phone_number = phone_number.replace(/\(|\)|\s+|-/g, ""); - return this.optional(element) || phone_number.length > 9 && - phone_number.match(/^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/); -}, "Please specify a valid uk phone number"); - -/** - * Matches a valid Canadian Postal Code - * - * @example jQuery.validator.methods.postalCodeCA( "H0H 0H0", element ) - * @result true - * - * @example jQuery.validator.methods.postalCodeCA( "H0H0H0", element ) - * @result false - * - * @name jQuery.validator.methods.postalCodeCA - * @type Boolean - * @cat Plugins/Validate/Methods - */ -$.validator.addMethod( "postalCodeCA", function( value, element ) { - return this.optional( element ) || /^[ABCEGHJKLMNPRSTVXY]\d[A-Z] \d[A-Z]\d$/.test( value ); -}, "Please specify a valid postal code" ); - -/* -* Valida CEPs do brasileiros: -* -* Formatos aceitos: -* 99999-999 -* 99.999-999 -* 99999999 -*/ -$.validator.addMethod("postalcodeBR", function(cep_value, element) { - return this.optional(element) || /^\d{2}.\d{3}-\d{3}?$|^\d{5}-?\d{3}?$/.test( cep_value ); -}, "Informe um CEP válido."); - -/* Matches Italian postcode (CAP) */ -$.validator.addMethod("postalcodeIT", function(value, element) { - return this.optional(element) || /^\d{5}$/.test(value); -}, "Please specify a valid postal code"); - -$.validator.addMethod("postalcodeNL", function(value, element) { - return this.optional(element) || /^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test(value); -}, "Please specify a valid postal code"); - -// Matches UK postcode. Does not match to UK Channel Islands that have their own postcodes (non standard UK) -$.validator.addMethod("postcodeUK", function(value, element) { - return this.optional(element) || /^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test(value); -}, "Please specify a valid UK postcode"); - -/* - * Lets you say "at least X inputs that match selector Y must be filled." - * - * The end result is that neither of these inputs: - * - * - * - * - * ...will validate unless at least one of them is filled. - * - * partnumber: {require_from_group: [1,".productinfo"]}, - * description: {require_from_group: [1,".productinfo"]} - * - * options[0]: number of fields that must be filled in the group - * options[1]: CSS selector that defines the group of conditionally required fields - */ -$.validator.addMethod("require_from_group", function(value, element, options) { - var $fields = $(options[1], element.form), - $fieldsFirst = $fields.eq(0), - validator = $fieldsFirst.data("valid_req_grp") ? $fieldsFirst.data("valid_req_grp") : $.extend({}, this), - isValid = $fields.filter(function() { - return validator.elementValue(this); - }).length >= options[0]; - - // Store the cloned validator for future validation - $fieldsFirst.data("valid_req_grp", validator); - - // If element isn't being validated, run each require_from_group field's validation rules - if (!$(element).data("being_validated")) { - $fields.data("being_validated", true); - $fields.each(function() { - validator.element(this); - }); - $fields.data("being_validated", false); - } - return isValid; -}, $.validator.format("Please fill at least {0} of these fields.")); - -/* - * Lets you say "either at least X inputs that match selector Y must be filled, - * OR they must all be skipped (left blank)." - * - * The end result, is that none of these inputs: - * - * - * - * - * - * ...will validate unless either at least two of them are filled, - * OR none of them are. - * - * partnumber: {skip_or_fill_minimum: [2,".productinfo"]}, - * description: {skip_or_fill_minimum: [2,".productinfo"]}, - * color: {skip_or_fill_minimum: [2,".productinfo"]} - * - * options[0]: number of fields that must be filled in the group - * options[1]: CSS selector that defines the group of conditionally required fields - * - */ -$.validator.addMethod("skip_or_fill_minimum", function(value, element, options) { - var $fields = $(options[1], element.form), - $fieldsFirst = $fields.eq(0), - validator = $fieldsFirst.data("valid_skip") ? $fieldsFirst.data("valid_skip") : $.extend({}, this), - numberFilled = $fields.filter(function() { - return validator.elementValue(this); - }).length, - isValid = numberFilled === 0 || numberFilled >= options[0]; - - // Store the cloned validator for future validation - $fieldsFirst.data("valid_skip", validator); - - // If element isn't being validated, run each skip_or_fill_minimum field's validation rules - if (!$(element).data("being_validated")) { - $fields.data("being_validated", true); - $fields.each(function() { - validator.element(this); - }); - $fields.data("being_validated", false); - } - return isValid; -}, $.validator.format("Please either skip these fields or fill at least {0} of them.")); - -/* Validates US States and/or Territories by @jdforsythe - * Can be case insensitive or require capitalization - default is case insensitive - * Can include US Territories or not - default does not - * Can include US Military postal abbreviations (AA, AE, AP) - default does not - * - * Note: "States" always includes DC (District of Colombia) - * - * Usage examples: - * - * This is the default - case insensitive, no territories, no military zones - * stateInput: { - * caseSensitive: false, - * includeTerritories: false, - * includeMilitary: false - * } - * - * Only allow capital letters, no territories, no military zones - * stateInput: { - * caseSensitive: false - * } - * - * Case insensitive, include territories but not military zones - * stateInput: { - * includeTerritories: true - * } - * - * Only allow capital letters, include territories and military zones - * stateInput: { - * caseSensitive: true, - * includeTerritories: true, - * includeMilitary: true - * } - * - * - * - */ - -$.validator.addMethod("stateUS", function(value, element, options) { - var isDefault = typeof options === "undefined", - caseSensitive = ( isDefault || typeof options.caseSensitive === "undefined" ) ? false : options.caseSensitive, - includeTerritories = ( isDefault || typeof options.includeTerritories === "undefined" ) ? false : options.includeTerritories, - includeMilitary = ( isDefault || typeof options.includeMilitary === "undefined" ) ? false : options.includeMilitary, - regex; - - if (!includeTerritories && !includeMilitary) { - regex = "^(A[KLRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$"; - } else if (includeTerritories && includeMilitary) { - regex = "^(A[AEKLPRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$"; - } else if (includeTerritories) { - regex = "^(A[KLRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$"; - } else { - regex = "^(A[AEKLPRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$"; - } - - regex = caseSensitive ? new RegExp(regex) : new RegExp(regex, "i"); - return this.optional(element) || regex.test(value); -}, -"Please specify a valid state"); - -// TODO check if value starts with <, otherwise don't try stripping anything -$.validator.addMethod("strippedminlength", function(value, element, param) { - return $(value).text().length >= param; -}, $.validator.format("Please enter at least {0} characters")); - -$.validator.addMethod("time", function(value, element) { - return this.optional(element) || /^([01]\d|2[0-3]|[0-9])(:[0-5]\d){1,2}$/.test(value); -}, "Please enter a valid time, between 00:00 and 23:59"); - -$.validator.addMethod("time12h", function(value, element) { - return this.optional(element) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test(value); -}, "Please enter a valid time in 12-hour am/pm format"); - -// same as url, but TLD is optional -$.validator.addMethod("url2", function(value, element) { - return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value); -}, $.validator.messages.url); - -/** - * Return true, if the value is a valid vehicle identification number (VIN). - * - * Works with all kind of text inputs. - * - * @example - * @desc Declares a required input element whose value must be a valid vehicle identification number. - * - * @name $.validator.methods.vinUS - * @type Boolean - * @cat Plugins/Validate/Methods - */ -$.validator.addMethod("vinUS", function(v) { - if (v.length !== 17) { - return false; - } - - var LL = [ "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" ], - VL = [ 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 7, 9, 2, 3, 4, 5, 6, 7, 8, 9 ], - FL = [ 8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2 ], - rs = 0, - i, n, d, f, cd, cdv; - - for (i = 0; i < 17; i++) { - f = FL[i]; - d = v.slice(i, i + 1); - if (i === 8) { - cdv = d; - } - if (!isNaN(d)) { - d *= f; - } else { - for (n = 0; n < LL.length; n++) { - if (d.toUpperCase() === LL[n]) { - d = VL[n]; - d *= f; - if (isNaN(cdv) && n === 8) { - cdv = LL[n]; - } - break; - } - } - } - rs += d; - } - cd = rs % 11; - if (cd === 10) { - cd = "X"; - } - if (cd === cdv) { - return true; - } - return false; -}, "The specified vehicle identification number (VIN) is invalid."); - -$.validator.addMethod("zipcodeUS", function(value, element) { - return this.optional(element) || /^\d{5}(-\d{4})?$/.test(value); -}, "The specified US ZIP Code is invalid"); - -$.validator.addMethod("ziprange", function(value, element) { - return this.optional(element) || /^90[2-5]\d\{2\}-\d{4}$/.test(value); -}, "Your ZIP-code must be in the range 902xx-xxxx to 905xx-xxxx"); - -})); \ No newline at end of file diff --git a/src/Web/WebStatus/wwwroot/lib/jquery-validation/dist/additional-methods.min.js b/src/Web/WebStatus/wwwroot/lib/jquery-validation/dist/additional-methods.min.js deleted file mode 100644 index b63c3ca12..000000000 --- a/src/Web/WebStatus/wwwroot/lib/jquery-validation/dist/additional-methods.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery Validation Plugin - v1.14.0 - 6/30/2015 - * http://jqueryvalidation.org/ - * Copyright (c) 2015 Jörn Zaefferer; Licensed MIT */ -!function(a){"function"==typeof define&&define.amd?define(["jquery","./jquery.validate.min"],a):a(jQuery)}(function(a){!function(){function b(a){return a.replace(/<.[^<>]*?>/g," ").replace(/ | /gi," ").replace(/[.(),;:!?%#$'\"_+=\/\-“”’]*/g,"")}a.validator.addMethod("maxWords",function(a,c,d){return this.optional(c)||b(a).match(/\b\w+\b/g).length<=d},a.validator.format("Please enter {0} words or less.")),a.validator.addMethod("minWords",function(a,c,d){return this.optional(c)||b(a).match(/\b\w+\b/g).length>=d},a.validator.format("Please enter at least {0} words.")),a.validator.addMethod("rangeWords",function(a,c,d){var e=b(a),f=/\b\w+\b/g;return this.optional(c)||e.match(f).length>=d[0]&&e.match(f).length<=d[1]},a.validator.format("Please enter between {0} and {1} words."))}(),a.validator.addMethod("accept",function(b,c,d){var e,f,g="string"==typeof d?d.replace(/\s/g,"").replace(/,/g,"|"):"image/*",h=this.optional(c);if(h)return h;if("file"===a(c).attr("type")&&(g=g.replace(/\*/g,".*"),c.files&&c.files.length))for(e=0;ec;c++)d=h-c,e=f.substring(c,c+1),g+=d*e;return g%11===0},"Please specify a valid bank account number"),a.validator.addMethod("bankorgiroaccountNL",function(b,c){return this.optional(c)||a.validator.methods.bankaccountNL.call(this,b,c)||a.validator.methods.giroaccountNL.call(this,b,c)},"Please specify a valid bank or giro account number"),a.validator.addMethod("bic",function(a,b){return this.optional(b)||/^([A-Z]{6}[A-Z2-9][A-NP-Z1-2])(X{3}|[A-WY-Z0-9][A-Z0-9]{2})?$/.test(a)},"Please specify a valid BIC code"),a.validator.addMethod("cifES",function(a){"use strict";var b,c,d,e,f,g,h=[];if(a=a.toUpperCase(),!a.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)"))return!1;for(d=0;9>d;d++)h[d]=parseInt(a.charAt(d),10);for(c=h[2]+h[4]+h[6],e=1;8>e;e+=2)f=(2*h[e]).toString(),g=f.charAt(1),c+=parseInt(f.charAt(0),10)+(""===g?0:parseInt(g,10));return/^[ABCDEFGHJNPQRSUVW]{1}/.test(a)?(c+="",b=10-parseInt(c.charAt(c.length-1),10),a+=b,h[8].toString()===String.fromCharCode(64+b)||h[8].toString()===a.charAt(a.length-1)):!1},"Please specify a valid CIF number."),a.validator.addMethod("cpfBR",function(a){if(a=a.replace(/([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g,""),11!==a.length)return!1;var b,c,d,e,f=0;if(b=parseInt(a.substring(9,10),10),c=parseInt(a.substring(10,11),10),d=function(a,b){var c=10*a%11;return(10===c||11===c)&&(c=0),c===b},""===a||"00000000000"===a||"11111111111"===a||"22222222222"===a||"33333333333"===a||"44444444444"===a||"55555555555"===a||"66666666666"===a||"77777777777"===a||"88888888888"===a||"99999999999"===a)return!1;for(e=1;9>=e;e++)f+=parseInt(a.substring(e-1,e),10)*(11-e);if(d(f,b)){for(f=0,e=1;10>=e;e++)f+=parseInt(a.substring(e-1,e),10)*(12-e);return d(f,c)}return!1},"Please specify a valid CPF number"),a.validator.addMethod("creditcardtypes",function(a,b,c){if(/[^0-9\-]+/.test(a))return!1;a=a.replace(/\D/g,"");var d=0;return c.mastercard&&(d|=1),c.visa&&(d|=2),c.amex&&(d|=4),c.dinersclub&&(d|=8),c.enroute&&(d|=16),c.discover&&(d|=32),c.jcb&&(d|=64),c.unknown&&(d|=128),c.all&&(d=255),1&d&&/^(5[12345])/.test(a)?16===a.length:2&d&&/^(4)/.test(a)?16===a.length:4&d&&/^(3[47])/.test(a)?15===a.length:8&d&&/^(3(0[012345]|[68]))/.test(a)?14===a.length:16&d&&/^(2(014|149))/.test(a)?15===a.length:32&d&&/^(6011)/.test(a)?16===a.length:64&d&&/^(3)/.test(a)?16===a.length:64&d&&/^(2131|1800)/.test(a)?15===a.length:128&d?!0:!1},"Please enter a valid credit card number."),a.validator.addMethod("currency",function(a,b,c){var d,e="string"==typeof c,f=e?c:c[0],g=e?!0:c[1];return f=f.replace(/,/g,""),f=g?f+"]":f+"]?",d="^["+f+"([1-9]{1}[0-9]{0,2}(\\,[0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)$",d=new RegExp(d),this.optional(b)||d.test(a)},"Please specify a valid currency"),a.validator.addMethod("dateFA",function(a,b){return this.optional(b)||/^[1-4]\d{3}\/((0?[1-6]\/((3[0-1])|([1-2][0-9])|(0?[1-9])))|((1[0-2]|(0?[7-9]))\/(30|([1-2][0-9])|(0?[1-9]))))$/.test(a)},a.validator.messages.date),a.validator.addMethod("dateITA",function(a,b){var c,d,e,f,g,h=!1,i=/^\d{1,2}\/\d{1,2}\/\d{4}$/;return i.test(a)?(c=a.split("/"),d=parseInt(c[0],10),e=parseInt(c[1],10),f=parseInt(c[2],10),g=new Date(Date.UTC(f,e-1,d,12,0,0,0)),h=g.getUTCFullYear()===f&&g.getUTCMonth()===e-1&&g.getUTCDate()===d?!0:!1):h=!1,this.optional(b)||h},a.validator.messages.date),a.validator.addMethod("dateNL",function(a,b){return this.optional(b)||/^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test(a)},a.validator.messages.date),a.validator.addMethod("extension",function(a,b,c){return c="string"==typeof c?c.replace(/,/g,"|"):"png|jpe?g|gif",this.optional(b)||a.match(new RegExp("\\.("+c+")$","i"))},a.validator.format("Please enter a value with a valid extension.")),a.validator.addMethod("giroaccountNL",function(a,b){return this.optional(b)||/^[0-9]{1,7}$/.test(a)},"Please specify a valid giro account number"),a.validator.addMethod("iban",function(a,b){if(this.optional(b))return!0;var c,d,e,f,g,h,i,j,k,l=a.replace(/ /g,"").toUpperCase(),m="",n=!0,o="",p="";if(c=l.substring(0,2),h={AL:"\\d{8}[\\dA-Z]{16}",AD:"\\d{8}[\\dA-Z]{12}",AT:"\\d{16}",AZ:"[\\dA-Z]{4}\\d{20}",BE:"\\d{12}",BH:"[A-Z]{4}[\\dA-Z]{14}",BA:"\\d{16}",BR:"\\d{23}[A-Z][\\dA-Z]",BG:"[A-Z]{4}\\d{6}[\\dA-Z]{8}",CR:"\\d{17}",HR:"\\d{17}",CY:"\\d{8}[\\dA-Z]{16}",CZ:"\\d{20}",DK:"\\d{14}",DO:"[A-Z]{4}\\d{20}",EE:"\\d{16}",FO:"\\d{14}",FI:"\\d{14}",FR:"\\d{10}[\\dA-Z]{11}\\d{2}",GE:"[\\dA-Z]{2}\\d{16}",DE:"\\d{18}",GI:"[A-Z]{4}[\\dA-Z]{15}",GR:"\\d{7}[\\dA-Z]{16}",GL:"\\d{14}",GT:"[\\dA-Z]{4}[\\dA-Z]{20}",HU:"\\d{24}",IS:"\\d{22}",IE:"[\\dA-Z]{4}\\d{14}",IL:"\\d{19}",IT:"[A-Z]\\d{10}[\\dA-Z]{12}",KZ:"\\d{3}[\\dA-Z]{13}",KW:"[A-Z]{4}[\\dA-Z]{22}",LV:"[A-Z]{4}[\\dA-Z]{13}",LB:"\\d{4}[\\dA-Z]{20}",LI:"\\d{5}[\\dA-Z]{12}",LT:"\\d{16}",LU:"\\d{3}[\\dA-Z]{13}",MK:"\\d{3}[\\dA-Z]{10}\\d{2}",MT:"[A-Z]{4}\\d{5}[\\dA-Z]{18}",MR:"\\d{23}",MU:"[A-Z]{4}\\d{19}[A-Z]{3}",MC:"\\d{10}[\\dA-Z]{11}\\d{2}",MD:"[\\dA-Z]{2}\\d{18}",ME:"\\d{18}",NL:"[A-Z]{4}\\d{10}",NO:"\\d{11}",PK:"[\\dA-Z]{4}\\d{16}",PS:"[\\dA-Z]{4}\\d{21}",PL:"\\d{24}",PT:"\\d{21}",RO:"[A-Z]{4}[\\dA-Z]{16}",SM:"[A-Z]\\d{10}[\\dA-Z]{12}",SA:"\\d{2}[\\dA-Z]{18}",RS:"\\d{18}",SK:"\\d{20}",SI:"\\d{15}",ES:"\\d{20}",SE:"\\d{20}",CH:"\\d{5}[\\dA-Z]{12}",TN:"\\d{20}",TR:"\\d{5}[\\dA-Z]{17}",AE:"\\d{3}\\d{16}",GB:"[A-Z]{4}\\d{14}",VG:"[\\dA-Z]{4}\\d{16}"},g=h[c],"undefined"!=typeof g&&(i=new RegExp("^[A-Z]{2}\\d{2}"+g+"$",""),!i.test(l)))return!1;for(d=l.substring(4,l.length)+l.substring(0,4),j=0;j9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/)},"Please specify a valid mobile number"),a.validator.addMethod("nieES",function(a){"use strict";return a=a.toUpperCase(),a.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)")?/^[T]{1}/.test(a)?a[8]===/^[T]{1}[A-Z0-9]{8}$/.test(a):/^[XYZ]{1}/.test(a)?a[8]==="TRWAGMYFPDXBNJZSQVHLCKE".charAt(a.replace("X","0").replace("Y","1").replace("Z","2").substring(0,8)%23):!1:!1},"Please specify a valid NIE number."),a.validator.addMethod("nifES",function(a){"use strict";return a=a.toUpperCase(),a.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)")?/^[0-9]{8}[A-Z]{1}$/.test(a)?"TRWAGMYFPDXBNJZSQVHLCKE".charAt(a.substring(8,0)%23)===a.charAt(8):/^[KLM]{1}/.test(a)?a[8]===String.fromCharCode(64):!1:!1},"Please specify a valid NIF number."),jQuery.validator.addMethod("notEqualTo",function(b,c,d){return this.optional(c)||!a.validator.methods.equalTo.call(this,b,c,d)},"Please enter a different value, values must not be the same."),a.validator.addMethod("nowhitespace",function(a,b){return this.optional(b)||/^\S+$/i.test(a)},"No white space please"),a.validator.addMethod("pattern",function(a,b,c){return this.optional(b)?!0:("string"==typeof c&&(c=new RegExp("^(?:"+c+")$")),c.test(a))},"Invalid format."),a.validator.addMethod("phoneNL",function(a,b){return this.optional(b)||/^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test(a)},"Please specify a valid phone number."),a.validator.addMethod("phoneUK",function(a,b){return a=a.replace(/\(|\)|\s+|-/g,""),this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/)},"Please specify a valid phone number"),a.validator.addMethod("phoneUS",function(a,b){return a=a.replace(/\s+/g,""),this.optional(b)||a.length>9&&a.match(/^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]([02-9]\d|1[02-9])-?\d{4}$/)},"Please specify a valid phone number"),a.validator.addMethod("phonesUK",function(a,b){return a=a.replace(/\(|\)|\s+|-/g,""),this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/)},"Please specify a valid uk phone number"),a.validator.addMethod("postalCodeCA",function(a,b){return this.optional(b)||/^[ABCEGHJKLMNPRSTVXY]\d[A-Z] \d[A-Z]\d$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postalcodeBR",function(a,b){return this.optional(b)||/^\d{2}.\d{3}-\d{3}?$|^\d{5}-?\d{3}?$/.test(a)},"Informe um CEP válido."),a.validator.addMethod("postalcodeIT",function(a,b){return this.optional(b)||/^\d{5}$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postalcodeNL",function(a,b){return this.optional(b)||/^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postcodeUK",function(a,b){return this.optional(b)||/^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test(a)},"Please specify a valid UK postcode"),a.validator.addMethod("require_from_group",function(b,c,d){var e=a(d[1],c.form),f=e.eq(0),g=f.data("valid_req_grp")?f.data("valid_req_grp"):a.extend({},this),h=e.filter(function(){return g.elementValue(this)}).length>=d[0];return f.data("valid_req_grp",g),a(c).data("being_validated")||(e.data("being_validated",!0),e.each(function(){g.element(this)}),e.data("being_validated",!1)),h},a.validator.format("Please fill at least {0} of these fields.")),a.validator.addMethod("skip_or_fill_minimum",function(b,c,d){var e=a(d[1],c.form),f=e.eq(0),g=f.data("valid_skip")?f.data("valid_skip"):a.extend({},this),h=e.filter(function(){return g.elementValue(this)}).length,i=0===h||h>=d[0];return f.data("valid_skip",g),a(c).data("being_validated")||(e.data("being_validated",!0),e.each(function(){g.element(this)}),e.data("being_validated",!1)),i},a.validator.format("Please either skip these fields or fill at least {0} of them.")),a.validator.addMethod("stateUS",function(a,b,c){var d,e="undefined"==typeof c,f=e||"undefined"==typeof c.caseSensitive?!1:c.caseSensitive,g=e||"undefined"==typeof c.includeTerritories?!1:c.includeTerritories,h=e||"undefined"==typeof c.includeMilitary?!1:c.includeMilitary;return d=g||h?g&&h?"^(A[AEKLPRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$":g?"^(A[KLRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$":"^(A[AEKLPRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$":"^(A[KLRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$",d=f?new RegExp(d):new RegExp(d,"i"),this.optional(b)||d.test(a)},"Please specify a valid state"),a.validator.addMethod("strippedminlength",function(b,c,d){return a(b).text().length>=d},a.validator.format("Please enter at least {0} characters")),a.validator.addMethod("time",function(a,b){return this.optional(b)||/^([01]\d|2[0-3]|[0-9])(:[0-5]\d){1,2}$/.test(a)},"Please enter a valid time, between 00:00 and 23:59"),a.validator.addMethod("time12h",function(a,b){return this.optional(b)||/^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test(a)},"Please enter a valid time in 12-hour am/pm format"),a.validator.addMethod("url2",function(a,b){return this.optional(b)||/^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(a)},a.validator.messages.url),a.validator.addMethod("vinUS",function(a){if(17!==a.length)return!1;var b,c,d,e,f,g,h=["A","B","C","D","E","F","G","H","J","K","L","M","N","P","R","S","T","U","V","W","X","Y","Z"],i=[1,2,3,4,5,6,7,8,1,2,3,4,5,7,9,2,3,4,5,6,7,8,9],j=[8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2],k=0;for(b=0;17>b;b++){if(e=j[b],d=a.slice(b,b+1),8===b&&(g=d),isNaN(d)){for(c=0;c