[
  {
    "path": ".gitignore",
    "content": "#project.json files\nproject.json.old\n\ndist\n.vs\n\n#remove generated files\n**/wwwroot/app/**/*.js\n**/wwwroot/app/**/*.map\n\n#remove node_modules copied into wwwroot\n**/wwwroot/lib\n**/wwwroot/libs/*\n\n## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/.docker/wait-for-postgres.sh",
    "content": "#!/bin/bash\n\nset -e\n\nhost=\"$1\"\nshift\ncmd=\"$@\"\n\nuntil psql -h \"$host\" -U \"postgres\" -c '\\l'; do\n  >&2 echo \"Postgres is unavailable - sleeping\"\n  sleep 1\ndone\n\n>&2 echo \"Postgres is up - executing command\"\nexec $cmd\n\n#Can call from docker-compose.yml by adding the following to dependent service    entrypoint: ./.docker/wait-for-postgres.sh postgres:5432"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/.dockerignore",
    "content": "node_modules\n*/node_modules"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/APIs/CustomersServiceController.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Mvc;\nusing AspNetCorePostgreSQLDockerApp.Models;\nusing AspNetCorePostgreSQLDockerApp.Repository;\nusing Microsoft.AspNetCore.Http;\n\nnamespace AspNetCorePostgreSQLDockerApp.Apis\n{\n    [Route(\"api/[controller]/customers\")]\n    public class CustomersServiceController : Controller\n    {\n        ICustomersRepository _repo;\n\n        public CustomersServiceController(ICustomersRepository repo) {\n          _repo = repo;\n        }\n\n        // GET api/dataservice/customers\n        [HttpGet()]\n        [ProducesResponseType(typeof(List<Customer>), 200)]\n        [ProducesResponseType(typeof(List<Customer>), 404)]\n        public async Task<ActionResult> Customers()\n        {\n            var customers = await _repo.GetCustomersAsync();\n            if (customers == null) {\n              return NotFound();\n            }\n            return Ok(customers);\n        }\n\n        // GET api/dataservice/customers/5\n        [HttpGet(\"{id}\", Name = \"GetCustomersRoute\")]\n        [ProducesResponseType(typeof(Customer), 200)]\n        [ProducesResponseType(typeof(Customer), 404)]\n        public async Task<ActionResult> Customers(int id)\n        {\n            var customer = await _repo.GetCustomerAsync(id);\n            if (customer == null) {\n              return NotFound();\n            }\n            return Ok(customer);\n        }\n\n        // POST api/customers\n        [HttpPost()]\n        [ProducesResponseType(typeof(Customer), 201)]\n        [ProducesResponseType(typeof(string), 400)]\n        public async Task<ActionResult> PostCustomer([FromBody]Customer customer)\n        {\n          if (!ModelState.IsValid) {\n            return BadRequest(this.ModelState);\n          }\n\n          var newCustomer = await _repo.InsertCustomerAsync(customer);\n          if (newCustomer == null) {\n            return BadRequest(\"Unable to insert customer\");\n          }\n          return CreatedAtRoute(\"GetCustomersRoute\", new { id = newCustomer.Id}, newCustomer);\n        }\n\n        // PUT api/dataservice/customers/5\n        [HttpPut(\"{id}\")]\n        [ProducesResponseType(typeof(bool), 200)]\n        [ProducesResponseType(typeof(bool), 400)]\n        public async Task<ActionResult> PutCustomer(int id, [FromBody]Customer customer)\n        {\n          if (!ModelState.IsValid) {\n            return BadRequest(this.ModelState);\n          }\n\n          var status = await _repo.UpdateCustomerAsync(customer);\n          if (!status) {\n            return BadRequest(\"Unable to update customer\");\n          }\n          return Ok(status);\n        }\n\n        // DELETE api/dataservice/customers/5\n        [HttpDelete(\"{id}\")]\n        [ProducesResponseType(typeof(bool), 200)]\n        [ProducesResponseType(typeof(bool), 404)]\n        public async Task<ActionResult> DeleteCustomer(int id)\n        {\n          var status = await _repo.DeleteCustomerAsync(id);\n          if (!status) {\n            return NotFound();\n          }\n          return Ok(status);\n        }\n\n        [HttpGet(\"states\")]\n        [ProducesResponseType(typeof(List<State>), 200)]\n        [ProducesResponseType(typeof(List<State>), 404)]\n        public async Task<ActionResult> States() {\n          var states = await _repo.GetStatesAsync();\n          if (states == null) {\n            return NotFound();\n          }\n          return Ok(states);\n        }\n\n    }\n\n    public static class HttpRequestExtensions\n    {\n        public static Uri ToUri(this HttpRequest request)\n        {\n            var hostComponents = request.Host.ToUriComponent().Split(':');\n\n            var builder = new UriBuilder\n            {\n                Scheme = request.Scheme,\n                Host = hostComponents[0],\n                Path = request.Path,\n                Query = request.QueryString.ToUriComponent()\n            };\n\n            if (hostComponents.Length == 2)\n            {\n                builder.Port = Convert.ToInt32(hostComponents[1]);\n            }\n\n            return builder.Uri;\n        }\n    }\n}\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/AspNetCorePostgreSQLDockerApp.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk.Web\">\r\n\r\n  <PropertyGroup>\r\n    <TargetFramework>netcoreapp3.1</TargetFramework>\r\n  </PropertyGroup>\r\n\r\n  <ItemGroup>\r\n    <PackageReference Include=\"Npgsql.EntityFrameworkCore.PostgreSQL\" Version=\"3.1.2\" />\r\n    <PackageReference Include=\"Microsoft.AspNetCore.SpaServices.Extensions\" Version=\"3.1.2\" />\r\n    <PackageReference Include=\"Swashbuckle.AspNetCore\" Version=\"5.1.0\" />\r\n  </ItemGroup>\r\n\r\n</Project>\r\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/.editorconfig",
    "content": "# Editor configuration, see http://editorconfig.org\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.md]\nmax_line_length = off\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/.gitignore",
    "content": "# See http://help.github.com/ignore-files/ for more about ignoring files.\n\n# compiled output\n/dist\n/tmp\n/out-tsc\n\n# dependencies\n/node_modules\n\n# IDEs and editors\n/.idea\n.project\n.classpath\n.c9/\n*.launch\n.settings/\n*.sublime-workspace\n\n# IDE - VSCode\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n\n# misc\n/.sass-cache\n/connect.lock\n/coverage\n/libpeerconnection.log\nnpm-debug.log\nyarn-error.log\ntestem.log\n/typings\n\n# System Files\n.DS_Store\nThumbs.db\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/README.md",
    "content": "# CustomersApp\n\nThis project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 7.0.4.\n\n## Development server\n\nRun `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.\n\n## Code scaffolding\n\nRun `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.\n\n## Build\n\nRun `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.\n\n## Running unit tests\n\nRun `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).\n\n## Running end-to-end tests\n\nRun `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).\n\n## Further help\n\nTo get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/angular.json",
    "content": "{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"version\": 1,\n  \"newProjectRoot\": \"projects\",\n  \"projects\": {\n    \"customers-app\": {\n      \"root\": \"\",\n      \"sourceRoot\": \"src\",\n      \"projectType\": \"application\",\n      \"prefix\": \"app\",\n      \"schematics\": {},\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular-devkit/build-angular:browser\",\n          \"options\": {\n            \"aot\": true,\n            \"outputPath\": \"../wwwroot/dist\",\n            \"deleteOutputPath\": false,\n            \"index\": \"src/index.html\",\n            \"main\": \"src/main.ts\",\n            \"polyfills\": \"src/polyfills.ts\",\n            \"tsConfig\": \"src/tsconfig.app.json\",\n            \"assets\": [\n              \"src/favicon.ico\",\n              \"src/assets\"\n            ],\n            \"styles\": [\n              \"src/styles.css\"\n            ],\n            \"scripts\": []\n          },\n          \"configurations\": {\n            \"production\": {\n              \"fileReplacements\": [\n                {\n                  \"replace\": \"src/environments/environment.ts\",\n                  \"with\": \"src/environments/environment.prod.ts\"\n                }\n              ],\n              \"optimization\": true,\n              \"outputHashing\": \"all\",\n              \"sourceMap\": false,\n              \"extractCss\": true,\n              \"namedChunks\": false,\n              \"aot\": true,\n              \"extractLicenses\": true,\n              \"vendorChunk\": false,\n              \"buildOptimizer\": true,\n              \"budgets\": [\n                {\n                  \"type\": \"initial\",\n                  \"maximumWarning\": \"2mb\",\n                  \"maximumError\": \"5mb\"\n                },\n                {\n                  \"type\": \"anyComponentStyle\",\n                  \"maximumWarning\": \"6kb\"\n                }\n              ]\n            }\n          }\n        },\n        \"serve\": {\n          \"builder\": \"@angular-devkit/build-angular:dev-server\",\n          \"options\": {\n            \"browserTarget\": \"customers-app:build\"\n          },\n          \"configurations\": {\n            \"production\": {\n              \"browserTarget\": \"customers-app:build:production\"\n            }\n          }\n        },\n        \"extract-i18n\": {\n          \"builder\": \"@angular-devkit/build-angular:extract-i18n\",\n          \"options\": {\n            \"browserTarget\": \"customers-app:build\"\n          }\n        },\n        \"test\": {\n          \"builder\": \"@angular-devkit/build-angular:karma\",\n          \"options\": {\n            \"main\": \"src/test.ts\",\n            \"polyfills\": \"src/polyfills.ts\",\n            \"tsConfig\": \"src/tsconfig.spec.json\",\n            \"karmaConfig\": \"src/karma.conf.js\",\n            \"styles\": [\n              \"src/styles.css\"\n            ],\n            \"scripts\": [],\n            \"assets\": [\n              \"src/favicon.ico\",\n              \"src/assets\"\n            ]\n          }\n        },\n        \"lint\": {\n          \"builder\": \"@angular-devkit/build-angular:tslint\",\n          \"options\": {\n            \"tsConfig\": [\n              \"src/tsconfig.app.json\",\n              \"src/tsconfig.spec.json\"\n            ],\n            \"exclude\": [\n              \"**/node_modules/**\"\n            ]\n          }\n        }\n      }\n    },\n    \"customers-app-e2e\": {\n      \"root\": \"e2e/\",\n      \"projectType\": \"application\",\n      \"prefix\": \"\",\n      \"architect\": {\n        \"e2e\": {\n          \"builder\": \"@angular-devkit/build-angular:protractor\",\n          \"options\": {\n            \"protractorConfig\": \"e2e/protractor.conf.js\",\n            \"devServerTarget\": \"customers-app:serve\"\n          },\n          \"configurations\": {\n            \"production\": {\n              \"devServerTarget\": \"customers-app:serve:production\"\n            }\n          }\n        },\n        \"lint\": {\n          \"builder\": \"@angular-devkit/build-angular:tslint\",\n          \"options\": {\n            \"tsConfig\": \"e2e/tsconfig.e2e.json\",\n            \"exclude\": [\n              \"**/node_modules/**\"\n            ]\n          }\n        }\n      }\n    }\n  },\n  \"defaultProject\": \"customers-app\"\n}"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/browserslist",
    "content": "# This file is currently used by autoprefixer to adjust CSS to support the below specified browsers\n# For additional information regarding the format and rule options, please see:\n# https://github.com/browserslist/browserslist#queries\n#\n# For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed\n\n> 0.5%\nlast 2 versions\nFirefox ESR\nnot dead\nnot IE 9-11"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/e2e/protractor.conf.js",
    "content": "// Protractor configuration file, see link for more information\n// https://github.com/angular/protractor/blob/master/lib/config.ts\n\nconst { SpecReporter } = require('jasmine-spec-reporter');\n\nexports.config = {\n  allScriptsTimeout: 11000,\n  specs: [\n    './src/**/*.e2e-spec.ts'\n  ],\n  capabilities: {\n    'browserName': 'chrome'\n  },\n  directConnect: true,\n  baseUrl: 'http://localhost:4200/',\n  framework: 'jasmine',\n  jasmineNodeOpts: {\n    showColors: true,\n    defaultTimeoutInterval: 30000,\n    print: function() {}\n  },\n  onPrepare() {\n    require('ts-node').register({\n      project: require('path').join(__dirname, './tsconfig.e2e.json')\n    });\n    jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));\n  }\n};"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/e2e/src/app.e2e-spec.ts",
    "content": "import { AppPage } from './app.po';\n\ndescribe('workspace-project App', () => {\n  let page: AppPage;\n\n  beforeEach(() => {\n    page = new AppPage();\n  });\n\n  it('should display welcome message', () => {\n    page.navigateTo();\n    expect(page.getParagraphText()).toEqual('Welcome to customers-app!');\n  });\n});\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/e2e/src/app.po.ts",
    "content": "import { browser, by, element } from 'protractor';\n\nexport class AppPage {\n  navigateTo() {\n    return browser.get('/');\n  }\n\n  getParagraphText() {\n    return element(by.css('app-root h1')).getText();\n  }\n}\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/e2e/tsconfig.e2e.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../out-tsc/app\",\n    \"module\": \"commonjs\",\n    \"target\": \"es5\",\n    \"types\": [\n      \"jasmine\",\n      \"jasminewd2\",\n      \"node\"\n    ]\n  }\n}"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/package.json",
    "content": "{\n  \"name\": \"customers-app\",\n  \"version\": \"1.0.0\",\n  \"scripts\": {\n    \"ng\": \"ng\",\n    \"start\": \"ng serve\",\n    \"build\": \"ng build\",\n    \"test\": \"ng test\",\n    \"lint\": \"ng lint\",\n    \"e2e\": \"ng e2e\"\n  },\n  \"private\": true,\n  \"dependencies\": {\n    \"@angular/animations\": \"~9.0.6\",\n    \"@angular/common\": \"~9.0.6\",\n    \"@angular/compiler\": \"~9.0.6\",\n    \"@angular/core\": \"~11.0.5\",\n    \"@angular/forms\": \"~9.0.6\",\n    \"@angular/platform-browser\": \"~9.0.6\",\n    \"@angular/platform-browser-dynamic\": \"~9.0.6\",\n    \"@angular/router\": \"~9.0.6\",\n    \"core-js\": \"^2.5.4\",\n    \"rxjs\": \"~6.5.4\",\n    \"tslib\": \"^1.10.0\",\n    \"zone.js\": \"~0.10.2\"\n  },\n  \"devDependencies\": {\n    \"@angular-devkit/build-angular\": \"~0.900.6\",\n    \"@angular/cli\": \"~9.0.6\",\n    \"@angular/compiler-cli\": \"~9.0.6\",\n    \"@angular/language-service\": \"~9.0.6\",\n    \"@types/node\": \"^12.11.1\",\n    \"@types/jasmine\": \"~3.3.8\",\n    \"@types/jasminewd2\": \"~2.0.3\",\n    \"codelyzer\": \"^5.1.2\",\n    \"jasmine-core\": \"~3.4.0\",\n    \"jasmine-spec-reporter\": \"~4.2.1\",\n    \"karma\": \"~6.3.16\",\n    \"karma-chrome-launcher\": \"~2.2.0\",\n    \"karma-coverage-istanbul-reporter\": \"~2.0.1\",\n    \"karma-jasmine\": \"~2.0.1\",\n    \"karma-jasmine-html-reporter\": \"^1.4.0\",\n    \"protractor\": \"~5.4.4\",\n    \"ts-node\": \"~7.0.0\",\n    \"tslint\": \"~5.15.0\",\n    \"typescript\": \"~3.7.5\"\n  }\n}\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/app/app-routing.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { Routes, RouterModule } from '@angular/router';\n\nimport { CustomersComponent }     from './customers/customers.component';\n\nconst routes: Routes = [\n  { path: '',  pathMatch:'full', redirectTo: '/customers' },\n  { path: 'customers', component: CustomersComponent }\n];\n\n@NgModule({\n  imports: [RouterModule.forRoot(routes)],\n  exports: [RouterModule]\n})\nexport class AppRoutingModule { }\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/app/app.component.css",
    "content": ""
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/app/app.component.html",
    "content": "<router-outlet></router-outlet>\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/app/app.component.spec.ts",
    "content": "import { TestBed, async } from '@angular/core/testing';\nimport { RouterTestingModule } from '@angular/router/testing';\nimport { AppComponent } from './app.component';\n\ndescribe('AppComponent', () => {\n  beforeEach(async(() => {\n    TestBed.configureTestingModule({\n      imports: [\n        RouterTestingModule\n      ],\n      declarations: [\n        AppComponent\n      ],\n    }).compileComponents();\n  }));\n\n  it('should create the app', () => {\n    const fixture = TestBed.createComponent(AppComponent);\n    const app = fixture.debugElement.componentInstance;\n    expect(app).toBeTruthy();\n  });\n\n  it(`should have as title 'customers-app'`, () => {\n    const fixture = TestBed.createComponent(AppComponent);\n    const app = fixture.debugElement.componentInstance;\n    expect(app.title).toEqual('customers-app');\n  });\n\n  it('should render title in a h1 tag', () => {\n    const fixture = TestBed.createComponent(AppComponent);\n    fixture.detectChanges();\n    const compiled = fixture.debugElement.nativeElement;\n    expect(compiled.querySelector('h1').textContent).toContain('Welcome to customers-app!');\n  });\n});\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/app/app.component.ts",
    "content": "import { Component } from '@angular/core';\n\n@Component({\n  selector: 'app-root',\n  templateUrl: './app.component.html',\n  styleUrls: ['./app.component.css']\n})\nexport class AppComponent {\n  title = 'customers-app';\n}\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/app/app.module.ts",
    "content": "import { BrowserModule } from '@angular/platform-browser';\nimport { NgModule } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ReactiveFormsModule } from '@angular/forms';\nimport { HttpClientModule } from '@angular/common/http';\n\nimport { AppRoutingModule } from './app-routing.module';\nimport { AppComponent } from './app.component';\nimport { CustomersComponent } from './customers/customers.component';\n\n@NgModule({\n  declarations: [\n    AppComponent, CustomersComponent\n  ],\n  imports: [\n    BrowserModule,\n    AppRoutingModule,\n    FormsModule, ReactiveFormsModule, HttpClientModule\n  ],\n  providers: [],\n  bootstrap: [AppComponent]\n})\nexport class AppModule { }\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/app/core/data.service.ts",
    "content": "import { Injectable } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\n\nimport { Observable } from 'rxjs';\nimport { map, catchError } from 'rxjs/operators';\n\nimport { ICustomer } from '../shared/interfaces';\n\n@Injectable({\n    providedIn: 'root'\n})\nexport class DataService {\n    \n    private url: string = 'api/customersservice/customers/';\n    \n    constructor(private http: HttpClient) { }\n    \n    getCustomersSummary() : Observable<ICustomer[]> {\n        return this.http.get<ICustomer[]>(this.url)\n            .pipe(\n                catchError(this.handleError)\n            );\n    }\n    \n    updateCustomer(customer: ICustomer) {       \n      return this.http.put(this.url + customer.id, customer)\n                .pipe(\n                    catchError(this.handleError)\n                );\n    }\n    \n    handleError(error: any) {\n        console.error(error);\n        return Observable.throw(error.json().error || 'Server error');\n    }\n    \n}\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/app/customers/customers.component.html",
    "content": "<h1>Customers</h1>\n<br />\n\n<!-- Added navbar to switch between list view shown in video and new edit view -->\n<div class=\"navbar\">\n    <ul class=\"nav navbar-nav\">\n        <li class=\"toolbar-item\">\n            <a (click)=\"editViewEnabled=false\" [class.active]=\"!editViewEnabled\">\n                <span class=\"glyphicon glyphicon-align-justify\"></span> List View\n            </a>\n        </li>\n        <li class=\"toolbar-item\">\n            <a (click)=\"editViewEnabled=true\" [class.active]=\"editViewEnabled\">\n                <span class=\"glyphicon glyphicon-pencil\"></span> Edit View\n            </a>\n        </li>\n    </ul>\n</div>\n\n<div *ngIf=\"!editViewEnabled\">\n    <div class=\"row header-row\">\n        <div class=\"col-md-2\">\n            Name\n        </div>\n        <div class=\"col-md-4\">\n            Email\n        </div>\n        <div class=\"col-md-4\">\n            Address\n        </div>\n        <div class=\"col-md-2\">\n            City\n        </div>\n    </div>\n    <div class=\"row\" *ngFor=\"let customer of customers\">\n        <div class=\"col-md-2\">\n            {{ customer.firstName  }} {{ customer.lastName }} \n        </div>\n        <div class=\"col-md-4\">\n            {{ customer.email }}\n        </div>\n        <div class=\"col-md-4\">\n            {{ customer.address }}\n        </div>\n        <div class=\"col-md-2\">\n            {{ customer.city }}\n        </div>\n        <br />\n    </div>\n</div>\n\n<!-- Added editable list to demonstrate doing an HTTP PUT -->\n<div *ngIf=\"editViewEnabled\">\n    <div class=\"container\" *ngFor=\"let customer of customers\">\n        <div class=\"row\" *ngIf=\"editId !== customer.id\">\n            <div class=\"col-md-4\">\n            {{ customer.firstName  }} {{ customer.lastName }} \n            </div>\n            <div class=\"col-md-8\">\n                <span class=\"btn btn-success pull-left\" \n                    (click)=\"editId=customer.id\">Edit</span>\n            </div>\n        </div>\n        <div *ngIf=\"editId == customer.id\">\n            <h4>{{ customer.firstName  }} {{ customer.lastName }}</h4>\n            <br />\n            <form (ngSubmit)=\"save(customer)\" #customerForm=\"ngForm\">\n                <div class=\"form-group\">\n                    <label for=\"name\">First Name</label>\n                    <input type=\"text\" class=\"form-control\" name=\"firstName\" #firstName=\"ngModel\" [(ngModel)]=\"customer.firstName\" required>\n                    <div class=\"alert alert-danger\" [hidden]=\"firstName.valid\">First Name is required</div>\n                </div>\n                <div class=\"form-group\">\n                    <label for=\"name\">Last Name</label>\n                    <input type=\"text\" class=\"form-control\" name=\"lastName\" #lastName=\"ngModel\" [(ngModel)]=\"customer.lastName\" required>\n                    <div class=\"alert alert-danger\" [hidden]=\"lastName.valid\">Last Name is required</div>\n                </div>\n                <div class=\"form-group\">\n                    <label for=\"name\">Email</label>\n                    <input type=\"text\" class=\"form-control\" name=\"email\" #email=\"ngModel\" [(ngModel)]=\"customer.email\" required>\n                    <div class=\"alert alert-danger\" [hidden]=\"email.valid\">Email is required</div>\n                </div>\n                <div class=\"form-group\">\n                    <label for=\"name\">City</label>\n                    <input type=\"text\" class=\"form-control\" name=\"city\" #city=\"ngModel\" [(ngModel)]=\"customer.city\" required>\n                    <div class=\"alert alert-danger\" [hidden]=\"city.valid\">City is required</div>\n                </div>\n                <div class=\"form-group\">\n                    <label for=\"name\">Address</label>\n                    <input type=\"text\" class=\"form-control\" name=\"address\" #address=\"ngModel\" [(ngModel)]=\"customer.address\" required>\n                    <div class=\"alert alert-danger\" [hidden]=\"address.valid\">Address is required</div>\n                </div>\n                <button type=\"submit\" class=\"btn btn-success\" [disabled]=\"!customerForm.valid\">Submit</button>&nbsp;\n                <span type=\"button\" class=\"btn btn-default\" (click)=\"editId=0\">Cancel</span>\n            </form>\n        </div>\n        <br />\n    </div>\n\n    <span class=\"alert alert-danger\" [hidden]=\"!errorMessage\">{{ errorMessage }}</span>\n</div>"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/app/customers/customers.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\nimport { DataService } from '../core/data.service';\nimport { ICustomer } from '../shared/interfaces';\n\n@Component({\n    selector: 'app-customers',\n    templateUrl: 'customers.component.html'\n})\nexport class CustomersComponent implements OnInit {\n    \n    customers: ICustomer[] = [];\n    editId: number = 0;\n    errorMessage: string;\n    editViewEnabled = false;\n\n    constructor(private dataService: DataService) {  }\n\n    ngOnInit() { \n        this.dataService.getCustomersSummary()\n            .subscribe((data: ICustomer[]) => this.customers = data);\n    }\n    \n    save(customer: ICustomer) {\n        this.dataService.updateCustomer(customer)\n            .subscribe((status: boolean) => {\n                if (status) {\n                    this.editId = 0;\n                } else {\n                    this.errorMessage = 'Unable to save customer';\n                }\n            })\n    }\n\n}"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/app/shared/interfaces.ts",
    "content": "export interface ICustomer {\n    id: number;\n    firstName: string;\n    lastName: string;\n    email: string;\n    address: string;\n    city: string;\n    state: IState;\n    zip: number;\n    gender: string;\n    latitude: number;\n    longitude: number;\n    orderCount?: number;\n    orders?: IOrder[];\n    ordersTotal?: number;\n}\n\nexport interface IState {\n    abbreviation: string;\n    name: string;\n}\n\nexport interface IOrder {\n    product: string;\n    price: number;\n    quantity: number;\n    orderTotal?: number;\n}"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/assets/.gitkeep",
    "content": ""
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/environments/environment.prod.ts",
    "content": "export const environment = {\n  production: true\n};\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/environments/environment.ts",
    "content": "// This file can be replaced during build by using the `fileReplacements` array.\n// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.\n// The list of file replacements can be found in `angular.json`.\n\nexport const environment = {\n  production: false\n};\n\n/*\n * For easier debugging in development mode, you can import the following file\n * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.\n *\n * This import should be commented out in production mode because it will have a negative impact\n * on performance if an error is thrown.\n */\n// import 'zone.js/dist/zone-error';  // Included with Angular CLI.\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <title>CustomersApp</title>\n  <base href=\"/\">\n\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n  <link rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\">\n</head>\n<body>\n  <app-root></app-root>\n</body>\n</html>\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/karma.conf.js",
    "content": "// Karma configuration file, see link for more information\n// https://karma-runner.github.io/1.0/config/configuration-file.html\n\nmodule.exports = function (config) {\n  config.set({\n    basePath: '',\n    frameworks: ['jasmine', '@angular-devkit/build-angular'],\n    plugins: [\n      require('karma-jasmine'),\n      require('karma-chrome-launcher'),\n      require('karma-jasmine-html-reporter'),\n      require('karma-coverage-istanbul-reporter'),\n      require('@angular-devkit/build-angular/plugins/karma')\n    ],\n    client: {\n      clearContext: false // leave Jasmine Spec Runner output visible in browser\n    },\n    coverageIstanbulReporter: {\n      dir: require('path').join(__dirname, '../coverage'),\n      reports: ['html', 'lcovonly'],\n      fixWebpackSourcePaths: true\n    },\n    reporters: ['progress', 'kjhtml'],\n    port: 9876,\n    colors: true,\n    logLevel: config.LOG_INFO,\n    autoWatch: true,\n    browsers: ['Chrome'],\n    singleRun: false\n  });\n};"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/main.ts",
    "content": "import { enableProdMode } from '@angular/core';\nimport { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\n\nimport { AppModule } from './app/app.module';\nimport { environment } from './environments/environment';\n\nif (environment.production) {\n  enableProdMode();\n}\n\nplatformBrowserDynamic().bootstrapModule(AppModule)\n  .catch(err => console.error(err));\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/polyfills.ts",
    "content": "/**\n * This file includes polyfills needed by Angular and is loaded before the app.\n * You can add your own extra polyfills to this file.\n *\n * This file is divided into 2 sections:\n *   1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.\n *   2. Application imports. Files imported after ZoneJS that should be loaded before your main\n *      file.\n *\n * The current setup is for so-called \"evergreen\" browsers; the last versions of browsers that\n * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),\n * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.\n *\n * Learn more in https://angular.io/guide/browser-support\n */\n\n/***************************************************************************************************\n * BROWSER POLYFILLS\n */\n\n/** IE10 and IE11 requires the following for NgClass support on SVG elements */\n// import 'classlist.js';  // Run `npm install --save classlist.js`.\n\n/**\n * Web Animations `@angular/platform-browser/animations`\n * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.\n * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).\n */\n// import 'web-animations-js';  // Run `npm install --save web-animations-js`.\n\n/**\n * By default, zone.js will patch all possible macroTask and DomEvents\n * user can disable parts of macroTask/DomEvents patch by setting following flags\n * because those flags need to be set before `zone.js` being loaded, and webpack\n * will put import in the top of bundle, so user need to create a separate file\n * in this directory (for example: zone-flags.ts), and put the following flags\n * into that file, and then add the following code before importing zone.js.\n * import './zone-flags.ts';\n *\n * The flags allowed in zone-flags.ts are listed here.\n *\n * The following flags will work for all browsers.\n *\n * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame\n * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick\n * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames\n *\n *  in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js\n *  with the following flag, it will bypass `zone.js` patch for IE/Edge\n *\n *  (window as any).__Zone_enable_cross_context_check = true;\n *\n */\n\n/***************************************************************************************************\n * Zone JS is required by default for Angular itself.\n */\nimport 'zone.js/dist/zone';  // Included with Angular CLI.\n\n\n/***************************************************************************************************\n * APPLICATION IMPORTS\n */\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/styles.css",
    "content": "/* You can add global styles to this file, and also import other style files */\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/test.ts",
    "content": "// This file is required by karma.conf.js and loads recursively all the .spec and framework files\n\nimport 'zone.js/dist/zone-testing';\nimport { getTestBed } from '@angular/core/testing';\nimport {\n  BrowserDynamicTestingModule,\n  platformBrowserDynamicTesting\n} from '@angular/platform-browser-dynamic/testing';\n\ndeclare const require: any;\n\n// First, initialize the Angular testing environment.\ngetTestBed().initTestEnvironment(\n  BrowserDynamicTestingModule,\n  platformBrowserDynamicTesting()\n);\n// Then we find all the tests.\nconst context = require.context('./', true, /\\.spec\\.ts$/);\n// And load the modules.\ncontext.keys().map(context);\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/tsconfig.app.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../out-tsc/app\",\n    \"types\": []\n  },\n  \"files\": [\n    \"main.ts\",\n    \"polyfills.ts\"\n  ],\n  \"include\": [\n    \"src/**/*.d.ts\"\n  ]\n}\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/tsconfig.spec.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../out-tsc/spec\",\n    \"types\": [\n      \"jasmine\",\n      \"node\"\n    ]\n  },\n  \"files\": [\n    \"test.ts\",\n    \"polyfills.ts\"\n  ],\n  \"include\": [\n    \"**/*.spec.ts\",\n    \"**/*.d.ts\"\n  ]\n}\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/src/tslint.json",
    "content": "{\n    \"extends\": \"../tslint.json\",\n    \"rules\": {\n        \"directive-selector\": [\n            true,\n            \"attribute\",\n            \"app\",\n            \"camelCase\"\n        ],\n        \"component-selector\": [\n            true,\n            \"element\",\n            \"app\",\n            \"kebab-case\"\n        ]\n    }\n}\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/tsconfig.json",
    "content": "{\n  \"compileOnSave\": false,\n  \"compilerOptions\": {\n    \"baseUrl\": \"./\",\n    \"downlevelIteration\": true,\n    \"importHelpers\": true,\n    \"outDir\": \"./dist/out-tsc\",\n    \"sourceMap\": true,\n    \"declaration\": false,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"emitDecoratorMetadata\": true,\n    \"experimentalDecorators\": true,\n    \"target\": \"es2015\",\n    \"typeRoots\": [\n      \"node_modules/@types\"\n    ],\n    \"lib\": [\n      \"es2018\",\n      \"dom\"\n    ]\n  }\n}\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Client/tslint.json",
    "content": "{\n  \"rulesDirectory\": [\n    \"node_modules/codelyzer\"\n  ],\n  \"rules\": {\n    \"arrow-return-shorthand\": true,\n    \"callable-types\": true,\n    \"class-name\": true,\n    \"comment-format\": [\n      true,\n      \"check-space\"\n    ],\n    \"curly\": true,\n    \"deprecation\": {\n      \"severity\": \"warn\"\n    },\n    \"eofline\": true,\n    \"forin\": true,\n    \"import-blacklist\": [\n      true,\n      \"rxjs/Rx\"\n    ],\n    \"import-spacing\": true,\n    \"indent\": [\n      true,\n      \"spaces\"\n    ],\n    \"interface-over-type-literal\": true,\n    \"label-position\": true,\n    \"max-line-length\": [\n      true,\n      140\n    ],\n    \"member-access\": false,\n    \"member-ordering\": [\n      true,\n      {\n        \"order\": [\n          \"static-field\",\n          \"instance-field\",\n          \"static-method\",\n          \"instance-method\"\n        ]\n      }\n    ],\n    \"no-arg\": true,\n    \"no-bitwise\": true,\n    \"no-console\": [\n      true,\n      \"debug\",\n      \"info\",\n      \"time\",\n      \"timeEnd\",\n      \"trace\"\n    ],\n    \"no-construct\": true,\n    \"no-debugger\": true,\n    \"no-duplicate-super\": true,\n    \"no-empty\": false,\n    \"no-empty-interface\": true,\n    \"no-eval\": true,\n    \"no-inferrable-types\": [\n      true,\n      \"ignore-params\"\n    ],\n    \"no-misused-new\": true,\n    \"no-non-null-assertion\": true,\n    \"no-redundant-jsdoc\": true,\n    \"no-shadowed-variable\": true,\n    \"no-string-literal\": false,\n    \"no-string-throw\": true,\n    \"no-switch-case-fall-through\": true,\n    \"no-trailing-whitespace\": true,\n    \"no-unnecessary-initializer\": true,\n    \"no-unused-expression\": true,\n    \"no-use-before-declare\": true,\n    \"no-var-keyword\": true,\n    \"object-literal-sort-keys\": false,\n    \"one-line\": [\n      true,\n      \"check-open-brace\",\n      \"check-catch\",\n      \"check-else\",\n      \"check-whitespace\"\n    ],\n    \"prefer-const\": true,\n    \"quotemark\": [\n      true,\n      \"single\"\n    ],\n    \"radix\": true,\n    \"semicolon\": [\n      true,\n      \"always\"\n    ],\n    \"triple-equals\": [\n      true,\n      \"allow-null-check\"\n    ],\n    \"typedef-whitespace\": [\n      true,\n      {\n        \"call-signature\": \"nospace\",\n        \"index-signature\": \"nospace\",\n        \"parameter\": \"nospace\",\n        \"property-declaration\": \"nospace\",\n        \"variable-declaration\": \"nospace\"\n      }\n    ],\n    \"unified-signatures\": true,\n    \"variable-name\": false,\n    \"whitespace\": [\n      true,\n      \"check-branch\",\n      \"check-decl\",\n      \"check-operator\",\n      \"check-separator\",\n      \"check-type\"\n    ],\n    \"no-output-on-prefix\": true,\n    \"no-inputs-metadata-property\": true,\n    \"no-outputs-metadata-property\": true,\n    \"no-host-metadata-property\": true,\n    \"no-input-rename\": true,\n    \"no-output-rename\": true,\n    \"use-lifecycle-interface\": true,\n    \"use-pipe-transform-interface\": true,\n    \"component-class-suffix\": true,\n    \"directive-class-suffix\": true\n  }\n}\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Controllers/CustomersController.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace AspNetCorePostgreSQLDockerApp.Controllers\n{\n    public class CustomersController : Controller\n    {\n\n        public ActionResult Index()\n        {\n            return View();\n        }\n    }\n}\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Controllers/HomeController.cs",
    "content": "using System;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System.Threading.Tasks;\r\nusing Microsoft.AspNetCore.Mvc;\r\n\r\nusing AspNetCorePostgreSQLDockerApp.Repository;\r\n\r\nnamespace AspNetCorePostgreSQLDockerApp.Controllers\r\n{\r\n    public class HomeController : Controller\r\n    {\r\n\r\n        IDockerCommandsRepository _repo;\r\n\r\n        public HomeController(IDockerCommandsRepository repo) {\r\n          _repo = repo;\r\n        }\r\n\r\n        public async Task<IActionResult> Index()\r\n        {\r\n            //Call into PostgreSQL\r\n            var commands = await _repo.GetDockerCommandsAsync();\r\n            return View(commands);\r\n        }\r\n\r\n        public IActionResult About()\r\n        {\r\n            ViewData[\"Message\"] = \"Your application description page.\";\r\n\r\n            return View();\r\n        }\r\n\r\n        public IActionResult Contact()\r\n        {\r\n            ViewData[\"Message\"] = \"Your contact page.\";\r\n\r\n            return View();\r\n        }\r\n\r\n        // public IActionResult Error()\r\n        // {\r\n        //     return View();\r\n        // }\r\n    }\r\n}\r\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Models/Customer.cs",
    "content": "using System.Collections.Generic;\n\nnamespace AspNetCorePostgreSQLDockerApp.Models {\n  public class Customer\n  {\n    public int Id { get; set; }\n    public string FirstName { get; set; }\n    public string LastName { get; set; }\n    public string Email { get; set; }\n    public string Address { get; set; }\n    public string City { get; set; }\n    public State State { get; set; }\n    public int Zip { get; set; }\n    public string Gender { get; set; }\n    public int OrderCount { get; set; }\n    public List<Order> Orders { get; set; }\n  }\n}"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Models/DockerCommand.cs",
    "content": "using System;\nusing System.Collections.Generic;\n\nnamespace AspNetCorePostgreSQLDockerApp.Models {\n  \n  public class DockerCommand {\n    public int Id { get; set; }\n    public string Command { get; set; }\n    public string Description { get; set; }\n    public List<DockerCommandExample> Examples { get; set; }    \n  }\n  \n}"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Models/DockerCommandExample.cs",
    "content": "using System;\n\nnamespace AspNetCorePostgreSQLDockerApp.Models {\n  \n  public class DockerCommandExample {\n    public int Id { get; set; }\n    public string Example { get; set; }\n    public string Description { get; set; }\n  }\n  \n}"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Models/Order.cs",
    "content": "namespace AspNetCorePostgreSQLDockerApp.Models {\n  public class Order {\n    public int Id { get; set; }\n    public string Product { get; set; }\n    public int Quantity { get; set; }\n    public decimal Price { get; set; }\n  }\n}"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Models/State.cs",
    "content": "namespace AspNetCorePostgreSQLDockerApp.Models {\n  public class State {\n    public int Id { get; set; }\n    public string Abbreviation { get; set; }\n    public string Name { get; set; }\n  }\n}"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Program.cs",
    "content": "using Microsoft.AspNetCore;\r\nusing Microsoft.AspNetCore.Hosting;\r\nusing Microsoft.Extensions.Hosting;\r\n\r\nnamespace AspNetCorePostgreSQLDockerApp\r\n{\r\n    public class Program\r\n    {\r\n        public static void Main(string[] args)\r\n        {\r\n            CreateHostBuilder(args).Build().Run();\r\n        }\r\n\r\n        public static IHostBuilder CreateHostBuilder(string[] args) =>\r\n            Host.CreateDefaultBuilder(args)\r\n                .ConfigureWebHostDefaults(webBuilder =>\r\n                {\r\n                    webBuilder.UseStartup<Startup>();\r\n                });\r\n    }\r\n}"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Properties/launchSettings.json",
    "content": "{\r\n  \"iisSettings\": {\r\n    \"windowsAuthentication\": false,\r\n    \"anonymousAuthentication\": true,\r\n    \"iisExpress\": {\r\n      \"applicationUrl\": \"http://localhost:50389/\",\r\n      \"sslPort\": 0\r\n    }\r\n  },\r\n  \"profiles\": {\r\n    \"IIS Express\": {\r\n      \"commandName\": \"IISExpress\",\r\n      \"launchBrowser\": true,\r\n      \"environmentVariables\": {\r\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\r\n      }\r\n    },\r\n    \"AspNetCorePostgreSQLDockerApp\": {\r\n      \"commandName\": \"Project\",\r\n      \"launchBrowser\": true,\r\n      \"launchUrl\": \"http://0.0.0.0:5000\",\r\n      \"environmentVariables\": {\r\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\r\n      }\r\n    }\r\n  }\r\n}"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Repository/CustomersDbContext.cs",
    "content": "using Microsoft.EntityFrameworkCore;\nusing AspNetCorePostgreSQLDockerApp.Models;\n\nnamespace AspNetCorePostgreSQLDockerApp.Repository\n{\n    public class CustomersDbContext : DbContext\n    {\n        public DbSet<Customer> Customers { get; set; }\n        public DbSet<Order> Orders { get; set; }\n        public DbSet<State> States { get; set; }\n\n        public CustomersDbContext (DbContextOptions<CustomersDbContext> options) : base(options) { }\n    }\n}"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Repository/CustomersDbSeeder.cs",
    "content": "using Microsoft.EntityFrameworkCore;\nusing System;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\nusing System.Linq;\nusing Microsoft.Extensions.Logging;\nusing Microsoft.Extensions.DependencyInjection;\nusing AspNetCorePostgreSQLDockerApp.Models;\n\nnamespace AspNetCorePostgreSQLDockerApp.Repository\n{\n    public class CustomersDbSeeder\n    {\n        readonly ILogger _logger;\n\n        public CustomersDbSeeder(ILoggerFactory loggerFactory)\n        {\n            _logger = loggerFactory.CreateLogger(\"CustomersDbSeederLogger\");\n        }\n\n        public async Task SeedAsync(IServiceProvider serviceProvider)\n        {\n            //Based on EF team's example at https://github.com/aspnet/MusicStore/blob/dev/samples/MusicStore/Models/SampleData.cs\n            using (var serviceScope = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())\n            {\n                var customersDb = serviceScope.ServiceProvider.GetService<CustomersDbContext>();\n                if (await customersDb.Database.EnsureCreatedAsync())\n                {\n                    if (!await customersDb.Customers.AnyAsync()) {\n                      await InsertCustomersSampleData(customersDb);\n                    }\n                }\n            }\n        }\n\n        public async Task InsertCustomersSampleData(CustomersDbContext db)\n        {\n            var states = GetStates();\n            db.States.AddRange(states);\n            try\n            {\n                await db.SaveChangesAsync();\n            }\n            catch (Exception exp)\n            {                \n                _logger.LogError($\"Error in {nameof(CustomersDbSeeder)}: \" + exp.Message);\n                throw; \n            }\n\n            var customers = GetCustomers(states);\n            db.Customers.AddRange(customers);\n\n            try\n            {\n              await db.SaveChangesAsync();\n            }\n            catch (Exception exp)\n            {\n              _logger.LogError($\"Error in {nameof(CustomersDbSeeder)}: \" + exp.Message);\n              throw;\n            }\n\n        }\n\n        private List<Customer> GetCustomers(List<State> states) {\n            //Customers\n            var customerNames = new string[]\n            {\n                \"Marcus,HighTower,Male,acmecorp.com\",\n                \"Jesse,Smith,Female,gmail.com\",\n                \"Albert,Einstein,Male,outlook.com\",\n                \"Dan,Wahlin,Male,yahoo.com\",\n                \"Ward,Bell,Male,gmail.com\",\n                \"Brad,Green,Male,gmail.com\",\n                \"Igor,Minar,Male,gmail.com\",\n                \"Miško,Hevery,Male,gmail.com\",\n                \"Michelle,Avery,Female,acmecorp.com\",\n                \"Heedy,Wahlin,Female,hotmail.com\",\n                \"Thomas,Martin,Male,outlook.com\",\n                \"Jean,Martin,Female,outlook.com\",\n                \"Robin,Cleark,Female,acmecorp.com\",\n                \"Juan,Paulo,Male,yahoo.com\",\n                \"Gene,Thomas,Male,gmail.com\",\n                \"Pinal,Dave,Male,gmail.com\",\n                \"Fred,Roberts,Male,outlook.com\",\n                \"Tina,Roberts,Female,outlook.com\",\n                \"Cindy,Jamison,Female,gmail.com\",\n                \"Robyn,Flores,Female,yahoo.com\",\n                \"Jeff,Wahlin,Male,gmail.com\",\n                \"Danny,Wahlin,Male,gmail.com\",\n                \"Elaine,Jones,Female,yahoo.com\",\n                \"John,Papa,Male,gmail.com\"\n            };\n            var addresses = new string[]\n            {\n                \"1234 Anywhere St.\",\n                \"435 Main St.\",\n                \"1 Atomic St.\",\n                \"85 Cedar Dr.\",\n                \"12 Ocean View St.\",\n                \"1600 Amphitheatre Parkway\",\n                \"1604 Amphitheatre Parkway\",\n                \"1607 Amphitheatre Parkway\",\n                \"346 Cedar Ave.\",\n                \"4576 Main St.\",\n                \"964 Point St.\",\n                \"98756 Center St.\",\n                \"35632 Richmond Circle Apt B\",\n                \"2352 Angular Way\",\n                \"23566 Directive Pl.\",\n                \"235235 Yaz Blvd.\",\n                \"7656 Crescent St.\",\n                \"76543 Moon Ave.\",\n                \"84533 Hardrock St.\",\n                \"5687534 Jefferson Way\",\n                \"346346 Blue Pl.\",\n                \"23423 Adams St.\",\n                \"633 Main St.\",\n                \"899 Mickey Way\"\n            };\n\n            var citiesStates = new string[]\n            {\n                \"Phoenix,AZ,Arizona\",\n                \"Encinitas,CA,California\",\n                \"Seattle,WA,Washington\",\n                \"Chandler,AZ,Arizona\",\n                \"Dallas,TX,Texas\",\n                \"Orlando,FL,Florida\",\n                \"Carey,NC,North Carolina\",\n                \"Anaheim,CA,California\",\n                \"Dallas,TX,Texas\",\n                \"New York,NY,New York\",\n                \"White Plains,NY,New York\",\n                \"Las Vegas,NV,Nevada\",\n                \"Los Angeles,CA,California\",\n                \"Portland,OR,Oregon\",\n                \"Seattle,WA,Washington\",\n                \"Houston,TX,Texas\",\n                \"Chicago,IL,Illinois\",\n                \"Atlanta,GA,Georgia\",\n                \"Chandler,AZ,Arizona\",\n                \"Buffalo,NY,New York\",\n                \"Albuquerque,AZ,Arizona\",\n                \"Boise,ID,Idaho\",\n                \"Salt Lake City,UT,Utah\",\n                \"Orlando,FL,Florida\"\n            };\n\n            var citiesIds = new int[] {5, 9, 44, 5, 36, 17, 16, 9, 36, 14, 14, 6, 9, 24, 44, 36, 25, 19, 5, 14, 5, 23, 38, 17};\n            var zip = 85229;\n\n            var orders = new List<Order> \n            {\n                new Order { Product = \"Basket\", Price = 29.99M, Quantity = 1 },\n                new Order { Product = \"Yarn\", Price = 9.99M, Quantity = 1 },\n                new Order { Product = \"Needes\", Price = 5.99M, Quantity = 1 },\n                new Order { Product = \"Speakers\", Price = 499.99M, Quantity = 1 },\n                new Order { Product = \"iPod\", Price = 399.99M, Quantity = 1 },\n                new Order { Product = \"Table\", Price = 329.99M, Quantity = 1 },\n                new Order { Product = \"Chair\", Price = 129.99M, Quantity = 4 },\n                new Order { Product = \"Lamp\", Price = 89.99M, Quantity = 5 },\n                new Order { Product = \"Call of Duty\", Price = 59.99M, Quantity = 1 },\n                new Order { Product = \"Controller\", Price = 49.99M, Quantity = 1 },\n                new Order { Product = \"Gears of War\", Price = 49.99M, Quantity = 1 },\n                new Order { Product = \"Lego City\", Price = 49.99M, Quantity = 1 },\n                new Order { Product = \"Baseball\", Price = 9.99M, Quantity = 5 },\n                new Order { Product = \"Bat\", Price = 19.99M, Quantity = 1 }\n            };\n\n            int firstOrder, lastOrder, tempOrder = 0;\n            var ordersLength = orders.Count;\n            var customers = new List<Customer>();\n            var random = new Random();\n\n            for (var i = 0; i < customerNames.Length; i++) {\n                var nameGenderHost = customerNames[i].Split(',');\n                var cityState = citiesStates[i].Split(',');\n                var state = states.Where(s => s.Abbreviation == cityState[1]).SingleOrDefault();\n\n                var customer = new Customer {\n                    FirstName = nameGenderHost[0],\n                    LastName = nameGenderHost[1],\n                    Email = nameGenderHost[0] + '.' + nameGenderHost[1] + '@' + nameGenderHost[3],\n                    Address = addresses[i],\n                    City = cityState[0],\n                    State = state,\n                    Zip = zip + i,\n                    Gender = nameGenderHost[2],\n                    OrderCount = 0\n                };\n\n                firstOrder = (int)Math.Floor(random.NextDouble() * orders.Count);\n                lastOrder = (int)Math.Floor(random.NextDouble() * orders.Count);\n\n                if (firstOrder > lastOrder) {\n                    tempOrder = firstOrder;\n                    firstOrder = lastOrder;\n                    lastOrder = tempOrder;\n                }\n\n                customer.Orders = new List<Order>();\n\n                for (var j = firstOrder; j <= lastOrder && j < ordersLength; j++) {\n                    var order = new Order {\n                        Product = orders[j].Product,\n                        Price = orders[j].Price,\n                        Quantity = orders[j].Quantity\n                    };\n                    customer.Orders.Add(order);\n                }\n                customer.OrderCount = customer.Orders.Count;\n                customers.Add(customer);\n            }\n\n            return customers;\n        }\n\n        private List<State> GetStates() {\n            var states = new List<State> \n            {\n                new State { Name = \"Alabama\", Abbreviation = \"AL\" },\n                new State { Name = \"Montana\", Abbreviation = \"MT\" },\n                new State { Name = \"Alaska\", Abbreviation = \"AK\" },\n                new State { Name = \"Nebraska\", Abbreviation = \"NE\" },\n                new State { Name = \"Arizona\", Abbreviation = \"AZ\" },\n                new State { Name = \"Nevada\", Abbreviation = \"NV\" },\n                new State { Name = \"Arkansas\", Abbreviation = \"AR\" },\n                new State { Name = \"New Hampshire\", Abbreviation = \"NH\" },\n                new State { Name = \"California\", Abbreviation = \"CA\" },\n                new State { Name = \"New Jersey\", Abbreviation = \"NJ\" },\n                new State { Name = \"Colorado\", Abbreviation = \"CO\" },\n                new State { Name = \"New Mexico\", Abbreviation = \"NM\" },\n                new State { Name = \"Connecticut\", Abbreviation = \"CT\" },\n                new State { Name = \"New York\", Abbreviation = \"NY\" },\n                new State { Name = \"Delaware\", Abbreviation = \"DE\" },\n                new State { Name = \"North Carolina\", Abbreviation = \"NC\" },\n                new State { Name = \"Florida\", Abbreviation = \"FL\" },\n                new State { Name = \"North Dakota\", Abbreviation = \"ND\" },\n                new State { Name = \"Georgia\", Abbreviation = \"GA\" },\n                new State { Name = \"Ohio\", Abbreviation = \"OH\" },\n                new State { Name = \"Hawaii\", Abbreviation = \"HI\" },\n                new State { Name = \"Oklahoma\", Abbreviation = \"OK\" },\n                new State { Name = \"Idaho\", Abbreviation = \"ID\" },\n                new State { Name = \"Oregon\", Abbreviation = \"OR\" },\n                new State { Name = \"Illinois\", Abbreviation = \"IL\" },\n                new State { Name = \"Pennsylvania\", Abbreviation = \"PA\" },\n                new State { Name = \"Indiana\", Abbreviation = \"IN\" },\n                new State { Name = \"Rhode Island\", Abbreviation = \"RI\" },\n                new State { Name = \"Iowa\", Abbreviation = \"IA\" },\n                new State { Name = \"South Carolina\", Abbreviation = \"SC\" },\n                new State { Name = \"Kansas\", Abbreviation = \"KS\" },\n                new State { Name = \"South Dakota\", Abbreviation = \"SD\" },\n                new State { Name = \"Kentucky\", Abbreviation = \"KY\" },\n                new State { Name = \"Tennessee\", Abbreviation = \"TN\" },\n                new State { Name = \"Louisiana\", Abbreviation = \"LA\" },\n                new State { Name = \"Texas\", Abbreviation = \"TX\" },\n                new State { Name = \"Maine\", Abbreviation = \"ME\" },\n                new State { Name = \"Utah\", Abbreviation = \"UT\" },\n                new State { Name = \"Maryland\", Abbreviation = \"MD\" },\n                new State { Name = \"Vermont\", Abbreviation = \"VT\" },\n                new State { Name = \"Massachusetts\", Abbreviation = \"MA\" },\n                new State { Name = \"Virginia\", Abbreviation = \"VA\" },\n                new State { Name = \"Michigan\", Abbreviation = \"MI\" },\n                new State { Name = \"Washington\", Abbreviation = \"WA\" },\n                new State { Name = \"Minnesota\", Abbreviation = \"MN\" },\n                new State { Name = \"West Virginia\", Abbreviation = \"WV\" },\n                new State { Name = \"Mississippi\", Abbreviation = \"MS\" },\n                new State { Name = \"Wisconsin\", Abbreviation = \"WI\" },\n                new State { Name = \"Missouri\", Abbreviation = \"MO\" },\n                new State { Name = \"Wyoming\", Abbreviation = \"WY\" }\n            };\n\n            return states;\n        }\n    }\n}"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Repository/CustomersRepository.cs",
    "content": "using System;\nusing Microsoft.EntityFrameworkCore;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\n\nusing Microsoft.Extensions.Logging;\nusing AspNetCorePostgreSQLDockerApp.Models;\n\nnamespace AspNetCorePostgreSQLDockerApp.Repository\n{\n    public class CustomersRepository : ICustomersRepository\n    {\n\n        private readonly CustomersDbContext _context;\n        private readonly ILogger _logger;\n\n        public CustomersRepository(CustomersDbContext context, ILoggerFactory loggerFactory) {\n          _context = context;\n          _logger = loggerFactory.CreateLogger(\"CustomersRepository\");\n        }\n\n        public async Task<List<Customer>> GetCustomersAsync()\n        {\n            return await _context.Customers.OrderBy(c => c.LastName).ToListAsync();\n        }\n\n        public async Task<Customer> GetCustomerAsync(int id)\n        {\n            return await _context.Customers.SingleOrDefaultAsync(c => c.Id == id);\n        }\n\n        public async Task<List<State>> GetStatesAsync()\n        {\n            return await _context.States.OrderBy(s => s.Abbreviation).ToListAsync();\n        }\n\n        public async Task<Customer> InsertCustomerAsync(Customer customer)\n        {\n            _context.Add(customer);\n            try\n            {\n              await _context.SaveChangesAsync();\n            }\n            catch (System.Exception exp)\n            {\n               _logger.LogError($\"Error in {nameof(InsertCustomerAsync)}: \" + exp.Message);\n            }\n\n            return customer;\n        }\n\n        public async Task<bool> UpdateCustomerAsync(Customer customer)\n        {\n            //Will update all properties of the Customer\n            _context.Customers.Attach(customer);\n            _context.Entry(customer).State = EntityState.Modified;\n            try\n            {\n              return (await _context.SaveChangesAsync() > 0 ? true : false);\n            }\n            catch (Exception exp)\n            {\n               _logger.LogError($\"Error in {nameof(UpdateCustomerAsync)}: \" + exp.Message);\n            }\n            return false;\n        }\n\n        public async Task<bool> DeleteCustomerAsync(int id)\n        {\n            //Extra hop to the database but keeps it nice and simple for this demo\n            var customer = await _context.Customers.SingleOrDefaultAsync(c => c.Id == id);\n            _context.Remove(customer);\n            try\n            {\n              return (await _context.SaveChangesAsync() > 0 ? true : false);\n            }\n            catch (System.Exception exp)\n            {\n               _logger.LogError($\"Error in {nameof(DeleteCustomerAsync)}: \" + exp.Message);\n            }\n            return false;\n        }\n\n    }\n}"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Repository/DockerCommandsDbContext.cs",
    "content": "using Microsoft.EntityFrameworkCore;\nusing AspNetCorePostgreSQLDockerApp.Models;\n\nnamespace AspNetCorePostgreSQLDockerApp.Repository\n{\n    public class DockerCommandsDbContext : DbContext\n    {\n        public DbSet<DockerCommand> DockerCommands { get; set; }\n\n        public DockerCommandsDbContext(DbContextOptions<DockerCommandsDbContext> options) : base(options) { }\n    }\n}"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Repository/DockerCommandsDbSeeder.cs",
    "content": "using Microsoft.EntityFrameworkCore;\nusing System;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\nusing System.Linq;\nusing Microsoft.Extensions.Logging;\nusing Microsoft.Extensions.DependencyInjection;\nusing AspNetCorePostgreSQLDockerApp.Models;\n\nnamespace AspNetCorePostgreSQLDockerApp.Repository\n{\n    public class DockerCommandsDbSeeder\n    {\n        readonly ILogger _logger;\n\n        public DockerCommandsDbSeeder(ILoggerFactory loggerFactory)\n        {\n            _logger = loggerFactory.CreateLogger(\"DockerCommandsDbSeederLogger\");\n        }\n\n        public async Task SeedAsync(IServiceProvider serviceProvider)\n        {\n            //Based on EF team's example at https://github.com/aspnet/MusicStore/blob/dev/samples/MusicStore/Models/SampleData.cs\n            using (var serviceScope = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())\n            {\n                var dockerDb = serviceScope.ServiceProvider.GetService<DockerCommandsDbContext>();\n                var customersDb = serviceScope.ServiceProvider.GetService<CustomersDbContext>();\n\n                if (await dockerDb.Database.EnsureCreatedAsync())\n                {\n                    if (!await dockerDb.DockerCommands.AnyAsync()) {\n                      await InsertDockerSampleData(dockerDb);\n                    }\n                }\n            }\n        }\n\n        public async Task InsertDockerSampleData(DockerCommandsDbContext db)\n        {\n            var commands = GetDockerCommands();\n            db.DockerCommands.AddRange(commands);\n\n            try\n            {\n              await db.SaveChangesAsync();\n            }\n            catch (Exception exp)\n            {\n              _logger.LogError($\"Error in {nameof(DockerCommandsDbSeeder)}: \" + exp.Message);\n            }\n\n        }\n\n        private List<DockerCommand> GetDockerCommands()\n        {\n            var cmd1 = new DockerCommand {\n                Command = \"run\",\n                Description = \"Runs a Docker container\",\n                Examples  = new List<DockerCommandExample> {\n                    new DockerCommandExample {\n                        Example = \"docker run imageName\",\n                        Description = \"Creates a running container from the image. Pulls it from Docker Hub if the image is not local\"\n                    },\n                    new DockerCommandExample {\n                        Example = \"docker run -d -p 8080:3000 imageName\",\n                        Description = \"Runs a container in 'daemon' mode with an external port of 8080 and a container port of 3000.\"\n                    }\n                }\n            };\n\n            var cmd2 = new DockerCommand {\n                Command = \"ps\",\n                Description = \"Lists containers\",\n                Examples  = new List<DockerCommandExample> {\n                    new DockerCommandExample {\n                        Example = \"docker ps\",\n                        Description = \"Lists all running containers\"\n                    },\n                    new DockerCommandExample {\n                        Example = \"docker ps -a\",\n                        Description = \"Lists all containers (even if they are not running)\"\n                    }\n                }\n            };\n\n            return new List<DockerCommand> { cmd1, cmd2 };\n        }\n\n    }\n}"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Repository/DockerCommandsRepository.cs",
    "content": "using System;\nusing Microsoft.EntityFrameworkCore;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\n\nusing Microsoft.Extensions.Logging;\nusing AspNetCorePostgreSQLDockerApp.Models;\n\nnamespace AspNetCorePostgreSQLDockerApp.Repository\n{\n    public class DockerCommandsRepository : IDockerCommandsRepository\n    {\n        private readonly DockerCommandsDbContext _context;\n        private readonly ILogger _logger;\n\n        public DockerCommandsRepository(DockerCommandsDbContext context, ILoggerFactory loggerFactory) {\n          _context = context;\n          _logger = loggerFactory.CreateLogger(\"DockerCommandsRepository\");\n        }\n\n        public async Task<List<DockerCommand>> GetDockerCommandsAsync() {\n          return await _context.DockerCommands.Include(dc => dc.Examples).ToListAsync();\n        }\n\n        public async Task InsertDockerCommandAsync(DockerCommand command) {\n          _context.DockerCommands.Add(command);\n          try {\n            await _context.SaveChangesAsync();\n          }\n          catch (Exception exp) {\n            _logger.LogError($\"Error in {nameof(InsertDockerCommandAsync)}: \" + exp.Message);\n          }\n        }\n    }\n}"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Repository/ICustomersRepository.cs",
    "content": "using System.Collections.Generic;\nusing System.Threading.Tasks;\n\nusing AspNetCorePostgreSQLDockerApp.Models;\n\nnamespace AspNetCorePostgreSQLDockerApp.Repository\n{\n    public interface ICustomersRepository\n    {     \n        Task<List<Customer>> GetCustomersAsync();\n\n        Task<Customer> GetCustomerAsync(int id);\n        \n        Task<Customer> InsertCustomerAsync(Customer customer);\n        Task<bool> UpdateCustomerAsync(Customer customer);\n        Task<bool> DeleteCustomerAsync(int id);\n        Task<List<State>> GetStatesAsync();\n    }\n}"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Repository/IDockerCommandsRepository.cs",
    "content": "using System.Collections.Generic;\nusing System.Threading.Tasks;\n\nusing AspNetCorePostgreSQLDockerApp.Models;\n\nnamespace AspNetCorePostgreSQLDockerApp.Repository\n{\n    public interface IDockerCommandsRepository\n    {     \n        Task<List<DockerCommand>> GetDockerCommandsAsync();\n        \n        Task InsertDockerCommandAsync(DockerCommand command);\n    }\n}"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Startup.cs",
    "content": "using System;\r\nusing System.IO;\r\nusing Microsoft.AspNetCore.Builder;\r\nusing Microsoft.AspNetCore.Hosting;\r\nusing Microsoft.AspNetCore.Http;\r\nusing Microsoft.EntityFrameworkCore;\r\nusing Microsoft.Extensions.Configuration;\r\nusing Microsoft.Extensions.DependencyInjection;\r\nusing Microsoft.Extensions.Hosting;\r\nusing Microsoft.Extensions.Logging;\r\nusing Microsoft.Extensions.FileProviders;\r\nusing Microsoft.AspNetCore.SpaServices.AngularCli;\r\nusing Microsoft.OpenApi.Models;\r\nusing AspNetCorePostgreSQLDockerApp.Repository;\r\n\r\nnamespace AspNetCorePostgreSQLDockerApp\r\n{\r\n    public class Startup\r\n    {\r\n        public Startup(IConfiguration configuration)\r\n        {\r\n            Configuration = configuration;\r\n        }\r\n\r\n        public IConfiguration Configuration { get; set; }\r\n\r\n        // This method gets called by the runtime. Use this method to add services to the container.\r\n        public void ConfigureServices(IServiceCollection services)\r\n        {\r\n\r\n            //Add PostgreSQL support\r\n            services.AddEntityFrameworkNpgsql()\r\n                .AddDbContext<DockerCommandsDbContext>(options =>\r\n                    options.UseNpgsql(Configuration[\"Data:DbContext:DockerCommandsConnectionString\"]))\r\n                .AddDbContext<CustomersDbContext>(options =>\r\n                    options.UseNpgsql(Configuration[\"Data:DbContext:CustomersConnectionString\"]));\r\n\r\n\r\n            services.AddControllersWithViews();\r\n\r\n            // Add our PostgreSQL Repositories (scoped to each request)\r\n            services.AddScoped<IDockerCommandsRepository, DockerCommandsRepository>();\r\n            services.AddScoped<ICustomersRepository, CustomersRepository>();\r\n            \r\n            //Transient: Created each time they're needed\r\n            services.AddTransient<DockerCommandsDbSeeder>();\r\n            services.AddTransient<CustomersDbSeeder>();\r\n\r\n            services.AddSwaggerGen(options =>\r\n            {\r\n                options.SwaggerDoc(\"v1\", new OpenApiInfo\r\n                {\r\n                    Version = \"v1\",\r\n                    Title = \"Application API\",\r\n                    Description = \"Application Documentation\",\r\n                    Contact = new OpenApiContact { Name = \"Author\" },\r\n                    License = new OpenApiLicense { Name = \"MIT\", Url = new Uri(\"https://en.wikipedia.org/wiki/MIT_License\") }\r\n                });\r\n\r\n                // Add XML comment document by uncommenting the following\r\n                // var filePath = Path.Combine(PlatformServices.Default.Application.ApplicationBasePath, \"MyApi.xml\");\r\n                // options.IncludeXmlComments(filePath);\r\n\r\n            });\r\n\r\n            services.AddCors(o => o.AddPolicy(\"AllowAllPolicy\", options =>\r\n            {\r\n                options.AllowAnyOrigin()\r\n                       .AllowAnyMethod()\r\n                       .AllowAnyHeader();\r\n            }));\r\n\r\n            services.AddSpaStaticFiles(configuration =>\r\n            {\r\n                configuration.RootPath = \"dist\";\r\n            });\r\n\r\n            // services.AddRouting(options => options.LowercaseUrls = true);\r\n\r\n        }\r\n\r\n        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.\r\n        public void Configure(IApplicationBuilder app, IWebHostEnvironment env,\r\n                              DockerCommandsDbSeeder dockerCommandsDbSeeder, CustomersDbSeeder customersDbSeeder)\r\n        {\r\n            if (env.IsDevelopment())\r\n            {\r\n                app.UseDeveloperExceptionPage();\r\n            }\r\n            else\r\n            {\r\n                app.UseExceptionHandler(\"/Home/Error\");\r\n            }\r\n\r\n            app.UseCors(\"AllowAllPolicy\");\r\n\r\n            app.UseStaticFiles();\r\n            app.UseSpaStaticFiles();\r\n\r\n            // Enable middleware to serve generated Swagger as a JSON endpoint\r\n            app.UseSwagger();\r\n\r\n            // Enable middleware to serve swagger-ui assets (HTML, JS, CSS etc.)\r\n            // Visit http://localhost:5000/swagger\r\n            app.UseSwaggerUI(c =>\r\n            {\r\n                c.SwaggerEndpoint(\"/swagger/v1/swagger.json\", \"My API V1\");\r\n            });\r\n\r\n            app.UseRouting();\r\n\r\n            app.UseEndpoints(endpoints =>\r\n            {\r\n                endpoints.MapControllers();\r\n\r\n                endpoints.MapControllerRoute(\r\n                    name: \"default\",\r\n                    pattern: \"{controller}/{action}/{id?}\");\r\n\r\n                // Handle redirecting client-side routes to Customers/Index route\r\n                endpoints.MapFallbackToController(\"Index\", \"Customers\");\r\n            });\r\n\r\n            customersDbSeeder.SeedAsync(app.ApplicationServices).Wait();\r\n            dockerCommandsDbSeeder.SeedAsync(app.ApplicationServices).Wait();\r\n\r\n        }\r\n\r\n    }\r\n}\r\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Views/Customers/Index.cshtml",
    "content": "<main class=\"container\">\n    <app-root>\n        Loading...\n    </app-root>\n    <br /><br />\n</main>\n\n<!-- Angular scripts -->\n<script src=\"dist/runtime-es2015.js\" type=\"module\"></script>  \n<script src=\"dist/runtime-es5.js\" nomodule defer></script>\n<script src=\"dist/polyfills-es5.js\" nomodule defer></script>\n<script src=\"dist/polyfills-es2015.js\" type=\"module\"></script>\n<script src=\"dist/styles-es2015.js\" type=\"module\"></script>\n<script src=\"dist/styles-es5.js\" nomodule defer></script>\n<script src=\"dist/vendor-es2015.js\" type=\"module\"></script>\n<script src=\"dist/vendor-es5.js\" nomodule defer></script>\n<script src=\"dist/main-es2015.js\" type=\"module\"></script>\n<script src=\"dist/main-es5.js\" nomodule defer></script>"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Views/Home/Index.cshtml",
    "content": "@model List<AspNetCorePostgreSQLDockerApp.Models.DockerCommand>\r\n@{\r\n    ViewData[\"Title\"] = \"Home Page\";\r\n}\r\n\r\n<h1>Docker Commands</h1>\r\nFrom the <a href=\"https://www.pluralsight.com/courses/docker-web-development\">Docker for Web Developers</a> course on Pluralsight.\r\n<br />\r\n<br />\r\n@foreach (var dockerCommand in Model) {\r\n\r\n   <h2>@dockerCommand.Command Command</h2>\r\n   @dockerCommand.Description\r\n   <br />\r\n   \r\n   @foreach (var commandExample in dockerCommand.Examples) {\r\n        <h3>@commandExample.Example</h3>\r\n        @commandExample.Description\r\n        <br />\r\n   }\r\n   \r\n   <br />\r\n}\r\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Views/Shared/Error.cshtml",
    "content": "@{\r\n    ViewData[\"Title\"] = \"Error\";\r\n}\r\n\r\n<h1 class=\"text-danger\">Error.</h1>\r\n<h2 class=\"text-danger\">An error occurred while processing your request.</h2>\r\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Views/Shared/_Layout.cshtml",
    "content": "<!doctype html>\r\n<html lang=\"\">\r\n    <head>\r\n        <base href=\"/\" />\r\n        <meta charset=\"utf-8\" />\r\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\r\n        <title>@ViewData[\"Title\"] - Asp.Net Core PostgreSQL Docker/Angular App</title>\r\n\r\n        <environment names=\"Development,Staging,Production\">\r\n            <link rel=\"stylesheet\" href=\"//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css\" />\r\n            <link rel=\"stylesheet\" href=\"~/css/site.css\" asp-append-version=\"true\" />\r\n        </environment>\r\n    </head>\r\n    <body>\r\n        <div class=\"navbar navbar-inverse navbar-fixed-top\">\r\n            <div class=\"container\">\r\n                <div class=\"navbar-header\">\r\n                    <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-collapse\">\r\n                        <span class=\"sr-only\">Toggle navigation</span>\r\n                        <span class=\"icon-bar\"></span>\r\n                        <span class=\"icon-bar\"></span>\r\n                        <span class=\"icon-bar\"></span>\r\n                    </button>\r\n                    <a asp-controller=\"Home\" asp-action=\"Index\" class=\"navbar-brand\">ASP.NET Core, PostgreSQL, Docker and Angular/TypeScript App</a>\r\n                </div>\r\n                <div class=\"navbar-collapse collapse\">\r\n                    <ul class=\"nav navbar-nav\">\r\n                        <li><a asp-controller=\"Home\" asp-action=\"Index\">Docker Commands</a></li>\r\n                        <li><a href=\"/customers\">Customers</a></li>\r\n                    </ul>\r\n                </div>\r\n            </div>\r\n        </div>\r\n        <div class=\"container body-content\">\r\n            @RenderBody()\r\n            <hr />\r\n            <footer>\r\n                <p>&copy; 2020 - Wahlin Consulting</p>\r\n            </footer>\r\n        </div>\r\n\r\n        <environment names=\"Development,Staging,Production\">\r\n\r\n        </environment>\r\n\r\n        @RenderSection(\"scripts\", required: false)\r\n    </body>\r\n</html>\r\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Views/Shared/_ValidationScriptsPartial.cshtml",
    "content": "<environment names=\"Development\">\r\n    <script src=\"~/lib/jquery-validation/dist/jquery.validate.js\"></script>\r\n    <script src=\"~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js\"></script>\r\n</environment>\r\n<environment names=\"Staging,Production\">\r\n    <script src=\"https://ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/jquery.validate.min.js\"\r\n            asp-fallback-src=\"~/lib/jquery-validation/dist/jquery.validate.min.js\"\r\n            asp-fallback-test=\"window.jQuery && window.jQuery.validator\">\r\n    </script>\r\n    <script src=\"https://ajax.aspnetcdn.com/ajax/mvc/5.2.3/jquery.validate.unobtrusive.min.js\"\r\n            asp-fallback-src=\"~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js\"\r\n            asp-fallback-test=\"window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive\">\r\n    </script>\r\n</environment>\r\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Views/_ViewImports.cshtml",
    "content": "@using AspNetCorePostgreSQLDockerApp\r\n@using AspNetCorePostgreSQLDockerApp.Models\r\n@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers\r\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/Views/_ViewStart.cshtml",
    "content": "@{\r\n    Layout = \"_Layout\";\r\n}\r\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/appsettings.json",
    "content": "{\n  \"Logging\": {\n    \"IncludeScopes\": false,\n    \"LogLevel\": {\n      \"Default\": \"Debug\",\n      \"System\": \"Information\",\n      \"Microsoft\": \"Information\"\n    }\n  },\n  \"Data\": {\n    \"DbContext\": {\n      \"LocalConnectionString\":  \"User ID=<YourUserName>;Password=;Server=127.0.0.1;Port=5432;Database=<YourUserName>;Pooling=true;\",\n      \"ConnectionString\":  \"User ID=postgres;Password=password;Server=postgres;Port=5432;Database=POSTGRES_USER;Integrated Security=true;Pooling=true;\",\n      \"DockerCommandsConnectionString\":  \"User ID=postgres;Password=password;Server=postgres;Port=5432;Database=DockerCommands;Integrated Security=true;Pooling=true;\",\n      \"CustomersConnectionString\":  \"User ID=postgres;Password=password;Server=postgres;Port=5432;Database=Customers;Integrated Security=true;Pooling=true;\"\n    }\n  }\n}\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/aspnetcore.dockerfile",
    "content": "FROM mcr.microsoft.com/dotnet/core/sdk\n\nLABEL author=\"Dan Wahlin\"\n\nENV ASPNETCORE_URLS=http://+:5000\n\nWORKDIR /var/www/aspnetcoreapp\n\nCOPY . .\n\nEXPOSE 5000\n\nENTRYPOINT [\"/bin/bash\", \"-c\", \"dotnet restore && dotnet run\"]\n\n# Note that this is only for demo and is intended to keep things simple. \n# A multi-stage dockerfile would normally be used here to build the .dll and use\n# the mcr.microsoft.com/dotnet/core/aspnet image for the final image\n\n# Legacy linking commands. While these work, they aren't the preferred way now.\n# Instead, use networks (see the docker-compose.yml file for an example).\n\n# docker build -f aspnetcore.dockerfile -t danwahlin/aspnetcore .\n# docker run -d --name my-postgres -e POSTGRES_PASSWORD=password postgres\n# docker run -d -p 5000:5000 --link my-postgres:postgres danwahlin/aspnetcore"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/aspnetcore.prod.dockerfile",
    "content": "FROM mcr.microsoft.com/dotnet/core/sdk AS build\nWORKDIR /var/www/aspnetcoreapp\n\n# copy csproj and restore as distinct layers\nCOPY ./*.csproj ./\nRUN dotnet restore\n\n# copy everything else and build app\nCOPY ./ ./\nRUN dotnet publish -c Release -o out\n\nFROM mcr.microsoft.com/dotnet/core/aspnet\nENV ASPNETCORE_URLS=http://+:5000\nWORKDIR /var/www/aspnetcoreapp\nCOPY --from=build /var/www/aspnetcoreapp/out ./\nENTRYPOINT [\"dotnet\", \"AspNetCorePostgreSQLDockerApp.dll\"]\n\n\n\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/docker-compose.azure.yml",
    "content": "version: '3.7'\n\nservices:\n\n  web:\n    container_name: 'aspnetcoreapp'\n    # would need to tag aspnetcoreapp image as shown below to run\n    # used to setup a Web App for Containers example\n    # https://docs.microsoft.com/en-us/azure/app-service/containers/quickstart-multi-container\n    image: 'danwahlin/aspnetcoreapp'\n    ports:\n     - \"80:5000\"\n    depends_on:\n     - \"postgres\"\n    networks:\n      - aspnetcoreapp-network\n\n  postgres:\n    container_name: 'postgres'\n    image: postgres\n    environment:\n      # change this for a \"real\" app!\n      POSTGRES_PASSWORD: password\n    networks:\n      - aspnetcoreapp-network\n\nnetworks:\n  aspnetcoreapp-network:\n    driver: bridge\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/docker-compose.prod.yml",
    "content": "version: '3.7'\n\nservices:\n\n  web:\n    container_name: 'aspnetcoreapp'\n    image: 'aspnetcoreapp'\n    build:\n      context: .\n      dockerfile: aspnetcore.prod.dockerfile\n    ports:\n     - \"5000:5000\"\n    depends_on:\n     - \"postgres\"\n    networks:\n      - aspnetcoreapp-network\n\n  postgres:\n    container_name: 'postgres'\n    image: postgres\n    environment:\n      # change this for a \"real\" app!\n      POSTGRES_PASSWORD: password\n    networks:\n      - aspnetcoreapp-network\n\nnetworks:\n  aspnetcoreapp-network:\n    driver: bridge\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/docker-compose.yml",
    "content": "version: '3.7'\n\nservices:\n\n  web:\n    container_name: 'aspnetcoreapp'\n    image: 'aspnetcoreapp'\n    build:\n      context: .\n      dockerfile: aspnetcore.dockerfile\n    ports:\n     - \"5000:5000\"\n    depends_on:\n     - \"postgres\"\n    networks:\n      - aspnetcoreapp-network\n\n  postgres:\n    container_name: 'postgres'\n    image: postgres\n    environment:\n      # change this for a \"real\" app!\n      POSTGRES_PASSWORD: password\n    networks:\n      - aspnetcoreapp-network\n\nnetworks:\n  aspnetcoreapp-network:\n    driver: bridge\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/wwwroot/css/site.css",
    "content": "body {\n    padding-top: 50px;\n    padding-bottom: 20px;\n}\n\n/* Wrapping element */\n/* Set some basic padding to keep content from hitting the edges */\n.body-content {\n    padding-left: 15px;\n    padding-right: 15px;\n}\n\n.header-row {\n  background-color: #efefef;\n}\n\n.header-row div {\n  font-weight: bold;\n  margin: 10px 00px 10px 0px;\n}\n\n/* Set widths on the form inputs since otherwise they're 100% wide */\ninput,\nselect,\ntextarea,\n.alert-danger {\n    max-width: 300px;\n}\n\n.toolbar-item a {\n  cursor: pointer;\n}\n\ninput.ng-invalid, select.ng-invalid {\n  border-left: 5px solid #a94442;\n}\n\ninput.ng-valid, select.ng-valid {\n  border-left: 5px solid #42A948;\n}\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/wwwroot/index2.html",
    "content": "<html>\n  <head>\n    <title>Angular and ASP.NET Core</title>\n    <base href=\"/\" />\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css\" />\n    <link rel=\"stylesheet\" href=\"css/site.css\">\n  </head>\n\n  <body>\n\n    <main class=\"container\">\n        <app-root>\n            Loading...\n        </app-root>\n        <br /><br />\n    </main>\n\n    <script type=\"text/javascript\" src=\"runtime.js\"></script>\n    <script type=\"text/javascript\" src=\"polyfills.js\"></script>\n    <script type=\"text/javascript\" src=\"styles.js\"></script>\n    <script type=\"text/javascript\" src=\"vendor.js\"></script>\n    <script type=\"text/javascript\" src=\"main.js\"></script>\n  </body>\n</html>\n\n\n\n\n\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp/wwwroot/web.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<configuration>\r\n  <system.webServer>\r\n    <handlers>\r\n      <add name=\"httpPlatformHandler\" path=\"*\" verb=\"*\" modules=\"httpPlatformHandler\" resourceType=\"Unspecified\"/>\r\n    </handlers>\r\n    <httpPlatform processPath=\"%DNX_PATH%\" arguments=\"%DNX_ARGS%\" stdoutLogEnabled=\"false\"/>\r\n  </system.webServer>\r\n</configuration>\r\n"
  },
  {
    "path": "AspNetCorePostgreSQLDockerApp.sln",
    "content": "﻿\r\nMicrosoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio 15\r\nVisualStudioVersion = 15.0.26228.9\r\nMinimumVisualStudioVersion = 10.0.40219.1\r\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"AspNetCorePostgreSQLDockerApp\", \"AspNetCorePostgreSQLDockerApp/AspNetCorePostgreSQLDockerApp.csproj\", \"{94FF9455-201B-452A-8262-AFB25D1CF615}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"AspNetCorePostgreSQLDockerApp\", \"AspNetCorePostgreSQLDockerApp\\AspNetCorePostgreSQLDockerApp.csproj\", \"{E32E1866-48E9-47FA-9DEF-3F91BC29C5C8}\"\r\nEndProject\r\nGlobal\r\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n\t\tDebug|Any CPU = Debug|Any CPU\r\n\t\tRelease|Any CPU = Release|Any CPU\r\n\tEndGlobalSection\r\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n\t\t{E32E1866-48E9-47FA-9DEF-3F91BC29C5C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{E32E1866-48E9-47FA-9DEF-3F91BC29C5C8}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{E32E1866-48E9-47FA-9DEF-3F91BC29C5C8}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{E32E1866-48E9-47FA-9DEF-3F91BC29C5C8}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\tEndGlobalSection\r\n\tGlobalSection(SolutionProperties) = preSolution\r\n\t\tHideSolutionNode = FALSE\r\n\tEndGlobalSection\r\n\tGlobalSection(NestedProjects) = preSolution\r\n\t\t{E32E1866-48E9-47FA-9DEF-3F91BC29C5C8} = {94FF9455-201B-452A-8262-AFB25D1CF615}\r\n\tEndGlobalSection\r\nEndGlobal\r\n"
  },
  {
    "path": "README.md",
    "content": "# ASP.NET Core with PostgreSQL and Docker Demo\r\n\r\nApplication demo designed to show how ASP.NET Core and PostgreSQL can be run in Docker containers. The app uses Entity Framework to create a simple database that stores Docker commands and examples. It also shows how Angular can be integrated with Web API to display customer information.\r\n\r\n### Running the App with Docker Compose\r\n\r\n1. Install `Docker Desktop for Mac` or `Docker Desktop for Windows`.\r\n\r\n1. Navigate to the `AspNetCorePostgreSQLDockerApp` subfolder in a console window.\r\n\r\n1. Open the `Client` folder in a terminal window and run the following commands at the root of the folder (requires Node.js):\r\n\r\n    - `npm install`\r\n    - `npm install -g @angular/cli`\r\n    - `ng build`\r\n\r\n1. Move back up a level to the `AspNetCorePostgreSQLDockerApp` in the terminal window:\r\n\r\n    - Run `docker-compose build`\r\n\r\n    - Run `docker-compose up`\r\n\r\n1. Navigate to http://localhost:5000 in your browser to view the site.\r\n\r\n## Using the Web App for Container Services on Azure\r\n\r\n1. Run `docker-compose -f docker-compose.prod.yml build`.\r\n1. Tag the `aspnetcoreapp` image as `[yourDockerHubUserAccount]/aspnetcoreapp`. Make sure you substitute your Docker Hub user account for `[yourDockerHubUserAccount]`.\r\n1. Push the image to Docker Hub using `docker push [yourDockerHubUserAccount]/aspnetcoreapp`.\r\n1. Open `docker-compose azure.yml` file and change the image for the `web` service to `[yourDockerHubUserAccount]/aspnetcoreapp`.\r\n1. Create a new `Web App for Containers` service in Azure. You'll need to add it to a new or existing Resource Group.\r\n1. On the `Docker` tab, switch `Options` to `Docker Compose`, `Image Source` to `Docker Hub` and upload the `docker-compose azure.yml` file using the `Configuration File` section of the screen.\r\n1. Wait for the service to start (it may take a few minutes to pull the image and fire up the Web App Service) and then click the web link it provides in the `Overview` section to hit the app.\r\n"
  }
]